diff options
-rw-r--r-- | src/arch/i386/boot/acpigen.c | 109 | ||||
-rw-r--r-- | src/arch/i386/include/arch/acpigen.h | 1 | ||||
-rw-r--r-- | src/cpu/amd/model_fxx/powernow_acpi.c | 2 | ||||
-rw-r--r-- | src/northbridge/amd/amdk8/amdk8_acpi.c | 2 |
4 files changed, 102 insertions, 12 deletions
diff --git a/src/arch/i386/boot/acpigen.c b/src/arch/i386/boot/acpigen.c index 3dec671494..2ad2a92cde 100644 --- a/src/arch/i386/boot/acpigen.c +++ b/src/arch/i386/boot/acpigen.c @@ -147,22 +147,111 @@ int acpigen_emit_stream(char *data, int size) 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 @@ int acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len) 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 @@ int acpigen_write_PPC(u8 nr) /* 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 */ diff --git a/src/arch/i386/include/arch/acpigen.h b/src/arch/i386/include/arch/acpigen.h index 0abeae5050..63c369d6a8 100644 --- a/src/arch/i386/include/arch/acpigen.h +++ b/src/arch/i386/include/arch/acpigen.h @@ -29,6 +29,7 @@ int acpigen_write_package(int nr_el); 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); diff --git a/src/cpu/amd/model_fxx/powernow_acpi.c b/src/cpu/amd/model_fxx/powernow_acpi.c index 1e789e3729..6ad1686dad 100644 --- a/src/cpu/amd/model_fxx/powernow_acpi.c +++ b/src/cpu/amd/model_fxx/powernow_acpi.c @@ -376,7 +376,7 @@ write_pstates: 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); diff --git a/src/northbridge/amd/amdk8/amdk8_acpi.c b/src/northbridge/amd/amdk8/amdk8_acpi.c index b6d4ed46f9..46b17db161 100644 --- a/src/northbridge/amd/amdk8/amdk8_acpi.c +++ b/src/northbridge/amd/amdk8/amdk8_acpi.c @@ -270,7 +270,7 @@ int k8acpi_write_vars(void) { 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); |