arch/x86/acpigen: Add generator for _ROM

Generate ACPI AML code for _ROM method.
This function takes as input ROM data and ROM length.

 Arguments passed into _DSM method:
 Arg0 = Offset in Bytes
 Arg1 = Bytes to return

Example:
 acpigen_write_rom(0xdeadbeef, 0x10000)

 AML code generated would look like:
        Method (_ROM, 2, NotSerialized)  // _ROM: Read-Only Memory
        {
            OperationRegion (ROMS, SystemMemory, 0xdeadbeef, 0x00010000)
            Field (ROMS, AnyAcc, NoLock, Preserve)
            {
                Offset (0x00),
                RBF0,   524288
            }

            Local0 = Arg0
            Local1 = Arg1
            If (Local1 > 0x1000)
            {
                Local1 = 0x1000
            }

            If (Local0 > 0x00010000)
            {
                Return (Buffer (Local1)
                {
                     0x00
                })
            }

            If (Local0 > 0x0f000)
            {
                Local2 = 0x10000 - Local0
                If (Local1 > Local2)
                {
                     Local1 = Local2
                }
            }

            Name (ROM1, Buffer (Local1)
            {
                 0x00
            })
            Local1 *= 0x08
            Local0 *= 0x08
            CreateField (RBF0, Local0, Local1, TMPB)
            ROM1 = TMPB /* \_SB_.PCI0.GFX0._ROM.TMPB */
            Return (ROM1) /* \_SB_.PCI0.GFX0._ROM.ROM1 */
        }

Change-Id: Ie118b15257295b7133c8e585c0fd5218249dec8d
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/20547
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
This commit is contained in:
Patrick Rudolph 2017-04-28 16:34:26 +02:00
parent a8733e381d
commit 6be6df0014
2 changed files with 200 additions and 0 deletions

View File

@ -1311,6 +1311,198 @@ void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count)
acpigen_pop_len(); /* Method _DSM */
}
/*
* Generate ACPI AML code for _ROM method.
* This function takes as input ROM data and ROM length.
*
* Arguments passed into _DSM method:
* Arg0 = Offset in Bytes
* Arg1 = Bytes to return
*
* Example:
* acpigen_write_rom(0xdeadbeef, 0x10000)
*
* AML code generated would look like:
* Method (_ROM, 2, NotSerialized) {
*
* OperationRegion("ROMS", SYSTEMMEMORY, 0xdeadbeef, 0x10000)
* Field (ROMS, AnyAcc, NoLock, Preserve)
* {
* Offset (0),
* RBF0, 0x80000
* }
*
* Store (Arg0, Local0)
* Store (Arg1, Local1)
*
* If (LGreater (Local1, 0x1000))
* {
* Store (0x1000, Local1)
* }
*
* If (LGreater (Local0, 0x10000))
* {
* Return(Buffer(Local1){0})
* }
*
* If (LGreater (Local0, 0x0f000))
* {
* Subtract (0x10000, Local0, Local2)
* If (LGreater (Local1, Local2))
* {
* Store (Local2, Local1)
* }
* }
*
* Name (ROM1, Buffer (Local1) {0})
*
* Multiply (Local0, 0x08, Local0)
* Multiply (Local1, 0x08, Local1)
*
* CreateField (RBF0, Local0, Local1, TMPB)
* Store (TMPB, ROM1)
* Return (ROM1)
* }
*/
void acpigen_write_rom(void *bios, const size_t length)
{
ASSERT(bios)
ASSERT(length)
/* Method (_ROM, 2, NotSerialized) */
acpigen_write_method("_ROM", 2);
/* OperationRegion("ROMS", SYSTEMMEMORY, current, length) */
struct opregion opreg = OPREGION("ROMS", SYSTEMMEMORY,
(uintptr_t)bios, length);
acpigen_write_opregion(&opreg);
struct fieldlist l[] = {
FIELDLIST_OFFSET(0),
FIELDLIST_NAMESTR("RBF0", 8 * length),
};
/* Field (ROMS, AnyAcc, NoLock, Preserve)
* {
* Offset (0),
* RBF0, 0x80000
* } */
acpigen_write_field(opreg.name, l, 2, FIELD_ANYACC |
FIELD_NOLOCK | FIELD_PRESERVE);
/* Store (Arg0, Local0) */
acpigen_write_store();
acpigen_emit_byte(ARG0_OP);
acpigen_emit_byte(LOCAL0_OP);
/* Store (Arg1, Local1) */
acpigen_write_store();
acpigen_emit_byte(ARG1_OP);
acpigen_emit_byte(LOCAL1_OP);
/* ACPI SPEC requires to return at maximum 4KiB */
/* If (LGreater (Local1, 0x1000)) */
acpigen_write_if();
acpigen_emit_byte(LGREATER_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_write_integer(0x1000);
/* Store (0x1000, Local1) */
acpigen_write_store();
acpigen_write_integer(0x1000);
acpigen_emit_byte(LOCAL1_OP);
/* Pop if */
acpigen_pop_len();
/* If (LGreater (Local0, length)) */
acpigen_write_if();
acpigen_emit_byte(LGREATER_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_integer(length);
/* Return(Buffer(Local1){0}) */
acpigen_emit_byte(RETURN_OP);
acpigen_emit_byte(BUFFER_OP);
acpigen_write_len_f();
acpigen_emit_byte(LOCAL1_OP);
acpigen_emit_byte(0);
acpigen_pop_len();
/* Pop if */
acpigen_pop_len();
/* If (LGreater (Local0, length - 4096)) */
acpigen_write_if();
acpigen_emit_byte(LGREATER_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_integer(length - 4096);
/* Subtract (length, Local0, Local2) */
acpigen_emit_byte(SUBTRACT_OP);
acpigen_write_integer(length);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(LOCAL2_OP);
/* If (LGreater (Local1, Local2)) */
acpigen_write_if();
acpigen_emit_byte(LGREATER_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_emit_byte(LOCAL2_OP);
/* Store (Local2, Local1) */
acpigen_write_store();
acpigen_emit_byte(LOCAL2_OP);
acpigen_emit_byte(LOCAL1_OP);
/* Pop if */
acpigen_pop_len();
/* Pop if */
acpigen_pop_len();
/* Name (ROM1, Buffer (Local1) {0}) */
acpigen_write_name("ROM1");
acpigen_emit_byte(BUFFER_OP);
acpigen_write_len_f();
acpigen_emit_byte(LOCAL1_OP);
acpigen_emit_byte(0);
acpigen_pop_len();
/* Multiply (Local1, 0x08, Local1) */
acpigen_emit_byte(MULTIPLY_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_write_integer(0x08);
acpigen_emit_byte(LOCAL1_OP);
/* Multiply (Local0, 0x08, Local0) */
acpigen_emit_byte(MULTIPLY_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_integer(0x08);
acpigen_emit_byte(LOCAL0_OP);
/* CreateField (RBF0, Local0, Local1, TMPB) */
acpigen_emit_ext_op(CREATEFIELD_OP);
acpigen_emit_namestring("RBF0");
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_emit_namestring("TMPB");
/* Store (TMPB, ROM1) */
acpigen_write_store();
acpigen_emit_namestring("TMPB");
acpigen_emit_namestring("ROM1");
/* Return (ROM1) */
acpigen_emit_byte(RETURN_OP);
acpigen_emit_namestring("ROM1");
/* Pop method */
acpigen_pop_len();
}
/* Soc-implemented functions -- weak definitions. */
int __attribute__((weak)) acpigen_soc_read_rx_gpio(unsigned int gpio_num)
{

View File

@ -264,6 +264,14 @@ void acpigen_write_return_byte(uint8_t arg);
void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *),
size_t count, void *arg);
void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count);
/*
* Generate ACPI AML code for _ROM method.
* This function takes as input ROM data and ROM length.
* The ROM length has to be multiple of 4096 and has to be less
* than the current implementation limit of 0x40000.
*/
void acpigen_write_rom(void *bios, const size_t length);
/*
* Generate ACPI AML code for OperationRegion
* This function takes input region name, region space, region offset & region