Author: ruik Date: 2009-06-21 22:26:13 +0200 (Sun, 21 Jun 2009) New Revision: 4368
Modified: trunk/coreboot-v2/src/arch/i386/boot/acpigen.c trunk/coreboot-v2/src/arch/i386/include/arch/acpigen.h trunk/coreboot-v2/src/cpu/amd/model_fxx/powernow_acpi.c trunk/coreboot-v2/src/northbridge/amd/amdk8/amdk8_acpi.c Log:
This patch adds a proper namestring generation to our ACPIgen generator. Its used for Name and Scope and Processor now. As bonus, it allows to create a multi name paths too. Like Scope(\ALL.YOUR.BASE).
Signed-off-by: Rudolf Marek r.marek@assembler.cz Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: trunk/coreboot-v2/src/arch/i386/boot/acpigen.c =================================================================== --- trunk/coreboot-v2/src/arch/i386/boot/acpigen.c 2009-06-19 21:18:14 UTC (rev 4367) +++ trunk/coreboot-v2/src/arch/i386/boot/acpigen.c 2009-06-21 20:26:13 UTC (rev 4368) @@ -147,22 +147,111 @@ return size; }
+/* The NameString are bit tricky, each element can be 4 chars, if + less its padded with underscore. Check 18.2.2 and 18.4 + and 5.3 of ACPI specs 3.0 for details +*/ + +static int acpigen_emit_simple_namestring(char *name) { + int i, len = 0; + char ud[] = "____"; + for (i = 0; i < 4; i++) { + if ((name[i] == '\0') || (name[i] == '.')) { + len += acpigen_emit_stream(ud, 4 - i); + break; + } else { + len += acpigen_emit_byte(name[i]); + } + } + return len; +} + +static int acpigen_emit_double_namestring(char *name, int dotpos) { + int len = 0; + /* mark dual name prefix */ + len += acpigen_emit_byte(0x2e); + len += acpigen_emit_simple_namestring(name); + len += acpigen_emit_simple_namestring(&name[dotpos + 1]); + return len; +} + +static int acpigen_emit_multi_namestring(char *name) { + int len = 0, count = 0; + unsigned char *pathlen; + /* mark multi name prefix */ + len += acpigen_emit_byte(0x2f); + len += acpigen_emit_byte(0x0); + pathlen = ((unsigned char *) acpigen_get_current()) - 1; + + while (name[0] != '\0') { + len += acpigen_emit_simple_namestring(name); + /* find end or next entity */ + while ((name[0] != '.') && (name[0] != '\0')) + name++; + /* forward to next */ + if (name[0] == '.') + name++; + count++; + } + + pathlen[0] = count; + return len; +} + + +int acpigen_emit_namestring(char *namepath) { + int dotcount = 0, i; + int dotpos; + int len = 0; + + /* we can start with a \ */ + if (namepath[0] == '\') { + len += acpigen_emit_byte('\'); + namepath++; + } + + /* and there can be any number of ^ */ + while (namepath[0] == '^') { + len += acpigen_emit_byte('^'); + namepath++; + } + + ASSERT(namepath[0] != '\0'); + + i = 0; + while (namepath[i] != '\0') { + if (namepath[i] == '.') { + dotcount++; + dotpos = i; + } + i++; + } + + if (dotcount == 0) { + len += acpigen_emit_simple_namestring(namepath); + } else if (dotcount == 1) { + len += acpigen_emit_double_namestring(namepath, dotpos); + } else { + len += acpigen_emit_multi_namestring(namepath); + } + return len; +} + int acpigen_write_name(char *name) { - int len = strlen(name); + int len; /* name op */ - acpigen_emit_byte(0x8); - acpigen_emit_stream(name, len); - return len + 1; + len = acpigen_emit_byte(0x8); + return len + acpigen_emit_namestring(name); }
int acpigen_write_scope(char *name) { int len; /* scope op */ - acpigen_emit_byte(0x10); - len = acpigen_write_len_f(); - return len + acpigen_emit_stream(name, strlen(name)) + 1; + len = acpigen_emit_byte(0x10); + len += acpigen_write_len_f(); + return len + acpigen_emit_namestring(name); }
int acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len) @@ -178,8 +267,8 @@ acpigen_emit_byte(0x83); len = acpigen_write_len_f();
- sprintf(pscope, "\._PR_CPU%x", (unsigned int) cpuindex); - len += acpigen_emit_stream(pscope, strlen(pscope)); + sprintf(pscope, "\_PR.CPU%x", (unsigned int) cpuindex); + len += acpigen_emit_namestring(pscope); acpigen_emit_byte(cpuindex); acpigen_emit_byte(pblock_addr & 0xff); acpigen_emit_byte((pblock_addr >> 8) & 0xff); @@ -238,7 +327,7 @@ /* method op */ acpigen_emit_byte(0x14); len = acpigen_write_len_f(); - len += acpigen_emit_stream("_PPC", 4); + len += acpigen_emit_namestring("_PPC"); /* no fnarg */ acpigen_emit_byte(0x00); /* return */
Modified: trunk/coreboot-v2/src/arch/i386/include/arch/acpigen.h =================================================================== --- trunk/coreboot-v2/src/arch/i386/include/arch/acpigen.h 2009-06-19 21:18:14 UTC (rev 4367) +++ trunk/coreboot-v2/src/arch/i386/include/arch/acpigen.h 2009-06-21 20:26:13 UTC (rev 4368) @@ -29,6 +29,7 @@ int acpigen_write_byte(unsigned int data); int acpigen_emit_byte(unsigned char data); int acpigen_emit_stream(char *data, int size); +int acpigen_emit_namestring(char *namepath); int acpigen_write_dword(unsigned int data); int acpigen_write_qword(uint64_t data); int acpigen_write_name(char *name);
Modified: trunk/coreboot-v2/src/cpu/amd/model_fxx/powernow_acpi.c =================================================================== --- trunk/coreboot-v2/src/cpu/amd/model_fxx/powernow_acpi.c 2009-06-19 21:18:14 UTC (rev 4367) +++ trunk/coreboot-v2/src/cpu/amd/model_fxx/powernow_acpi.c 2009-06-21 20:26:13 UTC (rev 4368) @@ -376,7 +376,7 @@
int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP) { int lens; - char pscope[] = "\_PR_"; + char pscope[] = "\_PR";
lens = acpigen_write_scope(pscope); lens += pstates_algorithm(pcontrol_blk, plen, onlyBSP);
Modified: trunk/coreboot-v2/src/northbridge/amd/amdk8/amdk8_acpi.c =================================================================== --- trunk/coreboot-v2/src/northbridge/amd/amdk8/amdk8_acpi.c 2009-06-19 21:18:14 UTC (rev 4367) +++ trunk/coreboot-v2/src/northbridge/amd/amdk8/amdk8_acpi.c 2009-06-21 20:26:13 UTC (rev 4368) @@ -270,7 +270,7 @@ { int lens; msr_t msr; - char pscope[] = "\._SB_PCI0"; + char pscope[] = "\_SB.PCI0";
lens = acpigen_write_scope(pscope); lens += k8acpi_write_pci_data(4, "BUSN", 0xe0);