Hello,
The namestring handling in ACPIgen was a big trickery. We were pasing the
strings as it was a bytestream already. This was a reason for instead of
_PR one had to write _PR_
Or \_SB.PCI0 was in fact \_SB_PCI0.
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 <[email protected]>
I have no board now, so I cannot test it on real HW. I did some tests which a
ACPIgen testbench which I'm attaching for future reference.
I dont know what happen to fam10 code, but I think it will need similar change.
Rudolf
Index: src/cpu/amd/model_fxx/powernow_acpi.c
===================================================================
--- src/cpu/amd/model_fxx/powernow_acpi.c (revision 4367)
+++ src/cpu/amd/model_fxx/powernow_acpi.c (working copy)
@@ -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);
Index: src/northbridge/amd/amdk8/amdk8_acpi.c
===================================================================
--- src/northbridge/amd/amdk8/amdk8_acpi.c (revision 4367)
+++ src/northbridge/amd/amdk8/amdk8_acpi.c (working copy)
@@ -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);
Index: src/arch/i386/boot/acpigen.c
===================================================================
--- src/arch/i386/boot/acpigen.c (revision 4367)
+++ src/arch/i386/boot/acpigen.c (working copy)
@@ -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 */
Index: src/arch/i386/include/arch/acpigen.h
===================================================================
--- src/arch/i386/include/arch/acpigen.h (revision 4367)
+++ src/arch/i386/include/arch/acpigen.h (working copy)
@@ -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);
#include "acpigen.h"
static int k8acpi_write_TOM1(void)
{
int len;
len = acpigen_write_name("TOM1");
len += acpigen_write_dword(0x12345678);
return len;
}
static int k8acpi_write_SBLK(void)
{
int len;
len = acpigen_write_name("SBLK");
len += acpigen_write_byte(42);
return len;
}
static int k8acpi_write_BUSN(void)
{
int len, lenp;
len = acpigen_write_name("BUSN");
lenp = acpigen_write_package(4);
lenp += acpigen_write_dword(0x11111111);
lenp += acpigen_write_dword(0x22222222);
lenp += acpigen_write_dword(0x33333333);
lenp += acpigen_write_dword(0x44444444);
// minus the opcode
acpigen_patch_len(lenp - 1);
return len + lenp;
}
int k8acpi_write_data(void)
{
int lens;
int ltot = 0;
// char pscope[] = "\\._SB_PCI0";
char pscope[] = "\\_SB.PCI0";
char pscope1[] = "\\_SB";
lens = acpigen_write_scope(pscope);
lens += k8acpi_write_BUSN();
// lens += acpigen_write_MMIO();
// lens += acpigen_write_PCIO();
lens += k8acpi_write_SBLK();
// lens += acpigen_write_SBDN();
// lens += acpigen_write_HCLK();
// lens += acpigen_write_HCDN();
// lens += acpigen_write_CBST();
//minus opcode
acpigen_patch_len(lens - 1);
lens = acpigen_write_scope(pscope1);
lens += k8acpi_write_TOM1();
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("TEST");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("TES");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("TE");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("T");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("\\Q");
acpigen_patch_len(lens - 1);
ltot += lens;
/*
lens = acpigen_write_scope("^A");
acpigen_patch_len(lens - 1);
ltot += lens;
*/
lens = acpigen_write_scope("\\QRTY");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("T.ASDF");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("T.ASD");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("T.AS");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("T.A");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("TEST.QWER.TYUI");
acpigen_patch_len(lens - 1);
ltot += lens;
lens = acpigen_write_scope("ALL.YOUR.BASE.ARE.BELO.NG.TO.US");
acpigen_patch_len(lens - 1);
ltot += lens;
return ltot;
}
#include "assert.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//int pnow_gen_for_core(int core);
int k8acpi_write_data(void);
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct acpi_table_header { /* ACPI common table header */
char signature[4]; /* ACPI signature (4 ASCII characters) */
u32 length; /* Length of table, in bytes, including header */
u8 revision; /* ACPI Specification minor version # */
u8 checksum; /* To make sum of entire table == 0 */
char oem_id[6]; /* OEM identification */
char oem_table_id[8]; /* OEM table identification */
u32 oem_revision; /* OEM revision number */
char asl_compiler_id[4]; /* ASL compiler vendor ID */
u32 asl_compiler_revision; /* ASL compiler revision number */
} __attribute__ ((packed)) acpi_header_t;
//("SSDT.aml", "SSDT", 1, "AMD-K8", "AMD-ACPI", 100925440)
acpi_header_t *ssdt;
// = (acpi_header_t *) buffer;
char buffer[10000];
int main(void)
{
int fd = open("test", O_RDWR|O_CREAT);
ssdt = (acpi_header_t *) buffer;
memcpy(&ssdt->signature, "SSDT", 4);
ssdt->revision = 1;
memcpy(&ssdt->oem_id, "COREBO", 6);
memcpy(&ssdt->oem_table_id, "K8-ACPI ", 8);
ssdt->oem_revision = 42;
memcpy(&ssdt->asl_compiler_id, "GENAML", 4);
ssdt->asl_compiler_revision = 42;
acpigen_set_current(buffer+36);
//pnow_gen();
k8acpi_write_data();
ssdt->length = (int) ((char *)acpigen_get_current() - &buffer[0]);
write(fd, buffer, ssdt->length);
close(fd);
return 0;
}
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot