<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/20547">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">arch/x86/acpigen: Add generator for _ROM<br><br>Add a common generator for method _ROM.<br>To be used with graphic devices.<br>The data has to be placed in system memory and has to be<br>a multiple of 4096.<br><br>Change-Id: Ie118b15257295b7133c8e585c0fd5218249dec8d<br>Signed-off-by: Patrick Rudolph <siro@das-labor.org><br>---<br>M src/arch/x86/acpigen.c<br>M src/arch/x86/include/arch/acpigen.h<br>2 files changed, 217 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/47/20547/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c<br>index f9690b3..d00c4bd 100644<br>--- a/src/arch/x86/acpigen.c<br>+++ b/src/arch/x86/acpigen.c<br>@@ -1295,6 +1295,215 @@<br>      acpigen_pop_len();      /* Method _DSM */<br> }<br> <br>+/*<br>+ * Generate ACPI AML code for _ROM method.<br>+ * This function takes as input ROM data and ROM length.<br>+ * The ROM length has to be multiple of 4096 and has to be less<br>+ * than the current implementation limit of 0x40000.<br>+ *<br>+ * Arguments passed into _DSM method:<br>+ * Arg0 = Offset in Bytes<br>+ * Arg1 = Bytes to return<br>+ *<br>+ * AML code generated would look like:<br>+ * Method (_ROM, 2, Serialized) {<br>+ *      ToBuffer (Arg0, Local0)<br>+ *    ToBuffer (Arg1, Local1)<br>+ *<br>+ *       OperationRegion("ROMS", SYSTEMMEMORY, current, entries * 0x10000)<br>+ *        Field (ROMS, AnyAcc, NoLock, Preserve)<br>+ *     {<br>+ *          Offset (0),<br>+ *                RBF0,   0x80000<br>+ *            RBF1,   0x80000<br>+ *            RBF2,   0x80000<br>+ *            RBF3,   0x80000<br>+ *    }<br>+ *<br>+ *     If (LGreater (LOCAL1_OP, 0x1000))<br>+ *  {<br>+ *          Store (0x1000, Local1)<br>+ *     }<br>+ *<br>+ *     If (LGreater (LOCAL0_OP, 0x10000))<br>+ * {<br>+ *          Return(Buffer(Local1){0})<br>+ *  }<br>+ *<br>+ *     Multiply (Local1, 0x08, Local3)<br>+ *    Name (ROM1, Buffer (0x80000) {0})<br>+ *  Name (ROM2, Buffer (Local1) {0})<br>+ *<br>+ *      If (LLess (LOCAL0_OP, 0x10000))<br>+ *    {<br>+ *          Store (RBFx, ROM1)<br>+ *         Subtract (Local0, 0, Local0)<br>+ *       }<br>+ *<br>+ *     Multiply (Local0, 0x08, Local2)<br>+ *    CreateField (ROM1, Local2, Local3, TMPB)<br>+ *   Store (TMPB, ROM2)<br>+ * Return (ROM2)<br>+ * }<br>+ */<br>+<br>+void acpigen_write_rom(void *bios, size_t length)<br>+{<br>+        struct fieldlist l[] = {<br>+             FIELDLIST_OFFSET(0),<br>+         FIELDLIST_NAMESTR("RBF0", 0x80000),<br>+                FIELDLIST_NAMESTR("RBF1", 0x80000),<br>+                FIELDLIST_NAMESTR("RBF2", 0x80000),<br>+                FIELDLIST_NAMESTR("RBF3", 0x80000),<br>+        };<br>+   ASSERT(bios)<br>+ ASSERT(length)<br>+       ASSERT(!(length & 0xfff))<br>+<br>+     /* Split ROM into smaller chunks */<br>+  size_t entries = DIV_ROUND_UP(length, 0x10000);<br>+      ASSERT(entries <= (ARRAY_SIZE(l) - 1))<br>+<br>+ /* Method (_ROM, 2) */<br>+       acpigen_write_method("_ROM", 2);<br>+<br>+        /* OperationRegion("ROMS", SYSTEMMEMORY, current, entries * 0x10000) */<br>+    struct opregion opreg = OPREGION("ROMS", SYSTEMMEMORY,<br>+                     (u32)(uintptr_t)bios, entries * 0x10000);<br>+    acpigen_write_opregion(&opreg);<br>+<br>+       /* Field (ROMS, AnyAcc, NoLock, Preserve)<br>+     * {<br>+  *  Offset (0),<br>+       *  RBF0,   0x80000<br>+   *  RBF1,   0x80000<br>+   *  RBF2,   0x80000<br>+   *  RBF3,   0x80000<br>+   * } */<br>+      acpigen_write_field(opreg.name, l, ARRAY_SIZE(l), FIELD_ANYACC |<br>+                         FIELD_NOLOCK | FIELD_PRESERVE);<br>+<br>+       /* ToBuffer (Arg0, Local0) */<br>+        acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);<br>+<br>+      /* ToBuffer (Arg1, Local1) */<br>+        acpigen_write_to_buffer(ARG1_OP, LOCAL1_OP);<br>+<br>+      /* ACPI SPEC requires to return at maximum 4KiB */<br>+   /* If (LGreater (LOCAL1_OP, 0x1000)) */<br>+      acpigen_write_if();<br>+  acpigen_emit_byte(LGREATER_OP);<br>+      acpigen_emit_byte(LOCAL1_OP);<br>+        acpigen_write_integer(0x1000);<br>+<br>+    /* Store (0x1000, Local1) */<br>+ acpigen_write_store();<br>+       acpigen_write_integer(0x1000);<br>+       acpigen_emit_byte(LOCAL1_OP);<br>+<br>+     /* Pop if */<br>+ acpigen_pop_len();<br>+<br>+        /* If (LGreater (LOCAL0_OP, length)) */<br>+      acpigen_write_if();<br>+  acpigen_emit_byte(LGREATER_OP);<br>+      acpigen_emit_byte(LOCAL0_OP);<br>+        acpigen_write_integer(length);<br>+<br>+    /* Return(Buffer(Local1){0}) */<br>+      acpigen_emit_byte(RETURN_OP);<br>+        acpigen_emit_byte(BUFFER_OP);<br>+        acpigen_write_len_f();<br>+       acpigen_emit_byte(LOCAL1_OP);<br>+        acpigen_emit_byte(0);<br>+        acpigen_pop_len();<br>+<br>+        /* Pop if */<br>+ acpigen_pop_len();<br>+<br>+        /* Multiply (Local1, 0x08, Local3) */<br>+        acpigen_emit_byte(MULTIPLY_OP);<br>+      acpigen_emit_byte(LOCAL1_OP);<br>+        acpigen_write_integer(0x08);<br>+ acpigen_emit_byte(LOCAL3_OP);<br>+<br>+     /* Name (ROM1, Buffer (0x80000) {0}) */<br>+      acpigen_write_name("ROM1");<br>+        acpigen_emit_byte(BUFFER_OP);<br>+        acpigen_write_len_f();<br>+       acpigen_write_integer(0x80000);<br>+      acpigen_emit_byte(0);<br>+        acpigen_pop_len();<br>+<br>+        /* Name (ROM2, Buffer (Local1) {0}) */<br>+       acpigen_write_name("ROM2");<br>+        acpigen_emit_byte(BUFFER_OP);<br>+        acpigen_write_len_f();<br>+       acpigen_emit_byte(LOCAL1_OP);<br>+        acpigen_emit_byte(0);<br>+        acpigen_pop_len();<br>+<br>+        for (size_t i = 0; i < entries; i++) {<br>+            const char name[5] = {'R', 'B', 'F', '0' + i, 0};<br>+<br>+         /* If (LLess (LOCAL0_OP, 0x10000 * (i + 1))) */<br>+              acpigen_write_if();<br>+          acpigen_emit_byte(LLESS_OP);<br>+         acpigen_emit_byte(LOCAL0_OP);<br>+                acpigen_write_integer(0x10000 * (i + 1));<br>+<br>+         /* Store (RBFx, ROM1) */<br>+             acpigen_write_store();<br>+               acpigen_emit_namestring(name);<br>+               acpigen_emit_namestring("ROM1");<br>+<br>+                /* Subtract (Local0, 0x10000 * i, Local0) */<br>+         acpigen_emit_byte(SUBTRACT_OP);<br>+              acpigen_emit_byte(LOCAL0_OP);<br>+                acpigen_write_integer(0x10000 * i);<br>+          acpigen_emit_byte(LOCAL0_OP);<br>+<br>+             /* Pop if */<br>+         acpigen_pop_len();<br>+<br>+                if ((i + 1) < entries) {<br>+                  /* else */<br>+                   acpigen_write_else();<br>+                }<br>+    }<br>+<br>+ for (size_t i = 0; i < entries - 1; i++) {<br>+                /* Pop else */<br>+               acpigen_pop_len();<br>+   }<br>+<br>+ /* Multiply (Local0, 0x08, Local2) */<br>+        acpigen_emit_byte(MULTIPLY_OP);<br>+      acpigen_emit_byte(LOCAL0_OP);<br>+        acpigen_write_integer(0x08);<br>+ acpigen_emit_byte(LOCAL2_OP);<br>+<br>+     /* CreateField (ROM1, Local2, Local3, TMPB) */<br>+       acpigen_emit_ext_op(CREATEFIELD_OP);<br>+ acpigen_emit_namestring("ROM1");<br>+   acpigen_emit_byte(LOCAL2_OP);<br>+        acpigen_emit_byte(LOCAL3_OP);<br>+        acpigen_emit_namestring("TMPB");<br>+<br>+        /* Store (TMPB, ROM2) */<br>+     acpigen_write_store();<br>+       acpigen_emit_namestring("TMPB");<br>+   acpigen_emit_namestring("ROM2");<br>+<br>+        /* Return (ROM2) */<br>+  acpigen_emit_byte(RETURN_OP);<br>+        acpigen_emit_namestring("ROM2");<br>+<br>+        /* Pop method */<br>+     acpigen_pop_len();<br>+}<br>+<br>+<br> /* Soc-implemented functions -- weak definitions. */<br> int __attribute__((weak)) acpigen_soc_read_rx_gpio(unsigned int gpio_num)<br> {<br>diff --git a/src/arch/x86/include/arch/acpigen.h b/src/arch/x86/include/arch/acpigen.h<br>index 37d0d55..a7c3e56 100644<br>--- a/src/arch/x86/include/arch/acpigen.h<br>+++ b/src/arch/x86/include/arch/acpigen.h<br>@@ -260,6 +260,14 @@<br> void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *),<br>                        size_t count, void *arg);<br> void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count);<br>+<br>+/*<br>+ * Generate ACPI AML code for _ROM method.<br>+ * This function takes as input ROM data and ROM length.<br>+ * The ROM length has to be multiple of 4096 and has to be less<br>+ * than the current implementation limit of 0x40000.<br>+ */<br>+void acpigen_write_rom(void *bios, size_t length);<br> /*<br>  * Generate ACPI AML code for OperationRegion<br>  * This function takes input region name, region space, region offset & region<br></pre><p>To view, visit <a href="https://review.coreboot.org/20547">change 20547</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/20547"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ie118b15257295b7133c8e585c0fd5218249dec8d </div>
<div style="display:none"> Gerrit-Change-Number: 20547 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <siro@das-labor.org> </div>