diff options
author | Rudolf Marek <r.marek@assembler.cz> | 2009-06-21 20:26:13 +0000 |
---|---|---|
committer | Rudolf Marek <r.marek@assembler.cz> | 2009-06-21 20:26:13 +0000 |
commit | 3310d75e6cddf3832d514b2ec26aa81ea8cfa0c6 (patch) | |
tree | 138255f1e1c3f0ab27f740563436bb49f65ddb3c /src/arch/i386 | |
parent | f17f647a62427e7241c6cbee0a81be5a46072cd9 (diff) |
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>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4368 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/i386')
-rw-r--r-- | src/arch/i386/boot/acpigen.c | 109 | ||||
-rw-r--r-- | src/arch/i386/include/arch/acpigen.h | 1 |
2 files changed, 100 insertions, 10 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); |