[coreboot-gerrit] Change in coreboot[master]: arch/x86/acpigen: Add generator for _ROM

Patrick Rudolph (Code Review) gerrit at coreboot.org
Wed Jul 12 19:45:48 CEST 2017


Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/20547


Change subject: arch/x86/acpigen: Add generator for _ROM
......................................................................

arch/x86/acpigen: Add generator for _ROM

Add a common generator for method _ROM.
To be used with graphic devices.
The data has to be placed in system memory and has to be
a multiple of 4096.

Change-Id: Ie118b15257295b7133c8e585c0fd5218249dec8d
Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
M src/arch/x86/acpigen.c
M src/arch/x86/include/arch/acpigen.h
2 files changed, 217 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/47/20547/1

diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c
index f9690b3..d00c4bd 100644
--- a/src/arch/x86/acpigen.c
+++ b/src/arch/x86/acpigen.c
@@ -1295,6 +1295,215 @@
 	acpigen_pop_len();	/* Method _DSM */
 }
 
+/*
+ * 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.
+ *
+ * Arguments passed into _DSM method:
+ * Arg0 = Offset in Bytes
+ * Arg1 = Bytes to return
+ *
+ * AML code generated would look like:
+ * Method (_ROM, 2, Serialized) {
+ *	ToBuffer (Arg0, Local0)
+ *	ToBuffer (Arg1, Local1)
+ *
+ *	OperationRegion("ROMS", SYSTEMMEMORY, current, entries * 0x10000)
+ *	Field (ROMS, AnyAcc, NoLock, Preserve)
+ *	{
+ *		Offset (0),
+ *		RBF0,   0x80000
+ *		RBF1,   0x80000
+ *		RBF2,   0x80000
+ *		RBF3,   0x80000
+ *	}
+ *
+ *	If (LGreater (LOCAL1_OP, 0x1000))
+ *	{
+ *		Store (0x1000, Local1)
+ *	}
+ *
+ *	If (LGreater (LOCAL0_OP, 0x10000))
+ *	{
+ *		Return(Buffer(Local1){0})
+ *	}
+ *
+ *	Multiply (Local1, 0x08, Local3)
+ *	Name (ROM1, Buffer (0x80000) {0})
+ *	Name (ROM2, Buffer (Local1) {0})
+ *
+ *	If (LLess (LOCAL0_OP, 0x10000))
+ *	{
+ *		Store (RBFx, ROM1)
+ *		Subtract (Local0, 0, Local0)
+ *	}
+ *
+ *	Multiply (Local0, 0x08, Local2)
+ *	CreateField (ROM1, Local2, Local3, TMPB)
+ *	Store (TMPB, ROM2)
+ *	Return (ROM2)
+ * }
+ */
+
+void acpigen_write_rom(void *bios, size_t length)
+{
+	struct fieldlist l[] = {
+		FIELDLIST_OFFSET(0),
+		FIELDLIST_NAMESTR("RBF0", 0x80000),
+		FIELDLIST_NAMESTR("RBF1", 0x80000),
+		FIELDLIST_NAMESTR("RBF2", 0x80000),
+		FIELDLIST_NAMESTR("RBF3", 0x80000),
+	};
+	ASSERT(bios)
+	ASSERT(length)
+	ASSERT(!(length & 0xfff))
+
+	/* Split ROM into smaller chunks */
+	size_t entries = DIV_ROUND_UP(length, 0x10000);
+	ASSERT(entries <= (ARRAY_SIZE(l) - 1))
+
+	/* Method (_ROM, 2) */
+	acpigen_write_method("_ROM", 2);
+
+	/* OperationRegion("ROMS", SYSTEMMEMORY, current, entries * 0x10000) */
+	struct opregion opreg = OPREGION("ROMS", SYSTEMMEMORY,
+			(u32)(uintptr_t)bios, entries * 0x10000);
+	acpigen_write_opregion(&opreg);
+
+	/* Field (ROMS, AnyAcc, NoLock, Preserve)
+	 * {
+	 *  Offset (0),
+	 *  RBF0,   0x80000
+	 *  RBF1,   0x80000
+	 *  RBF2,   0x80000
+	 *  RBF3,   0x80000
+	 * } */
+	acpigen_write_field(opreg.name, l, ARRAY_SIZE(l), FIELD_ANYACC |
+			    FIELD_NOLOCK | FIELD_PRESERVE);
+
+	/* ToBuffer (Arg0, Local0) */
+	acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);
+
+	/* ToBuffer (Arg1, Local1) */
+	acpigen_write_to_buffer(ARG1_OP, LOCAL1_OP);
+
+	/* ACPI SPEC requires to return at maximum 4KiB */
+	/* If (LGreater (LOCAL1_OP, 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_OP, 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();
+
+	/* Multiply (Local1, 0x08, Local3) */
+	acpigen_emit_byte(MULTIPLY_OP);
+	acpigen_emit_byte(LOCAL1_OP);
+	acpigen_write_integer(0x08);
+	acpigen_emit_byte(LOCAL3_OP);
+
+	/* Name (ROM1, Buffer (0x80000) {0}) */
+	acpigen_write_name("ROM1");
+	acpigen_emit_byte(BUFFER_OP);
+	acpigen_write_len_f();
+	acpigen_write_integer(0x80000);
+	acpigen_emit_byte(0);
+	acpigen_pop_len();
+
+	/* Name (ROM2, Buffer (Local1) {0}) */
+	acpigen_write_name("ROM2");
+	acpigen_emit_byte(BUFFER_OP);
+	acpigen_write_len_f();
+	acpigen_emit_byte(LOCAL1_OP);
+	acpigen_emit_byte(0);
+	acpigen_pop_len();
+
+	for (size_t i = 0; i < entries; i++) {
+		const char name[5] = {'R', 'B', 'F', '0' + i, 0};
+
+		/* If (LLess (LOCAL0_OP, 0x10000 * (i + 1))) */
+		acpigen_write_if();
+		acpigen_emit_byte(LLESS_OP);
+		acpigen_emit_byte(LOCAL0_OP);
+		acpigen_write_integer(0x10000 * (i + 1));
+
+		/* Store (RBFx, ROM1) */
+		acpigen_write_store();
+		acpigen_emit_namestring(name);
+		acpigen_emit_namestring("ROM1");
+
+		/* Subtract (Local0, 0x10000 * i, Local0) */
+		acpigen_emit_byte(SUBTRACT_OP);
+		acpigen_emit_byte(LOCAL0_OP);
+		acpigen_write_integer(0x10000 * i);
+		acpigen_emit_byte(LOCAL0_OP);
+
+		/* Pop if */
+		acpigen_pop_len();
+
+		if ((i + 1) < entries) {
+			/* else */
+			acpigen_write_else();
+		}
+	}
+
+	for (size_t i = 0; i < entries - 1; i++) {
+		/* Pop else */
+		acpigen_pop_len();
+	}
+
+	/* Multiply (Local0, 0x08, Local2) */
+	acpigen_emit_byte(MULTIPLY_OP);
+	acpigen_emit_byte(LOCAL0_OP);
+	acpigen_write_integer(0x08);
+	acpigen_emit_byte(LOCAL2_OP);
+
+	/* CreateField (ROM1, Local2, Local3, TMPB) */
+	acpigen_emit_ext_op(CREATEFIELD_OP);
+	acpigen_emit_namestring("ROM1");
+	acpigen_emit_byte(LOCAL2_OP);
+	acpigen_emit_byte(LOCAL3_OP);
+	acpigen_emit_namestring("TMPB");
+
+	/* Store (TMPB, ROM2) */
+	acpigen_write_store();
+	acpigen_emit_namestring("TMPB");
+	acpigen_emit_namestring("ROM2");
+
+	/* Return (ROM2) */
+	acpigen_emit_byte(RETURN_OP);
+	acpigen_emit_namestring("ROM2");
+
+	/* Pop method */
+	acpigen_pop_len();
+}
+
+
 /* Soc-implemented functions -- weak definitions. */
 int __attribute__((weak)) acpigen_soc_read_rx_gpio(unsigned int gpio_num)
 {
diff --git a/src/arch/x86/include/arch/acpigen.h b/src/arch/x86/include/arch/acpigen.h
index 37d0d55..a7c3e56 100644
--- a/src/arch/x86/include/arch/acpigen.h
+++ b/src/arch/x86/include/arch/acpigen.h
@@ -260,6 +260,14 @@
 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, size_t length);
 /*
  * Generate ACPI AML code for OperationRegion
  * This function takes input region name, region space, region offset & region

-- 
To view, visit https://review.coreboot.org/20547
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie118b15257295b7133c8e585c0fd5218249dec8d
Gerrit-Change-Number: 20547
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <siro at das-labor.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20170712/40ce83b8/attachment-0001.html>


More information about the coreboot-gerrit mailing list