Patch set implement as follows: 1. Minor changes around existing tools - reorganize building process, - move common code to separate direction, - no functionality changes. 2. Add BFAPEI (Blob For APEI) tool which can create blobs for APEI testing. - see commit log for more details
Changes for v2: - compilation regardless of whether APEI is used or not, - correct file name in comment headers, - move ACPI structures, defines, etc. to acpi.h headers, - suppress compiler warnings.
Tomasz Nowicki (4): map, cab: Reorganize building process and tree hierarchy. bfapei: Add tool that can create blobs for APEI table testing. bfapei: Move generic ACPI structures to separated file, remove duplicated defines. Suppress compiler warnings, file comment headers cleanup.
Makefile | 28 +- platforms/Makefile | 9 +- tools/bfapei/Makefile | 11 + tools/bfapei/bfapei.c | 271 +++++++++++++++++++ tools/bfapei/bfapei.h | 49 ++++ tools/cab/Makefile | 12 +- tools/cab/cab.c | 535 +------------------------------------- tools/cab/cab.h | 149 ----------- tools/common/Makefile | 4 + tools/common/build_aml.c | 455 ++++++++++++++++++++++++++++++++ tools/common/check_aml.c | 512 ++++++++++++++++++++++++++++++++++++ tools/common/include/acpi.h | 204 +++++++++++++++ tools/common/include/build_aml.h | 74 ++++++ tools/common/include/check_aml.h | 92 +++++++ tools/mab/Makefile | 13 +- tools/mab/mab.c | 437 +------------------------------ tools/mab/mab.h | 77 ------ 17 files changed, 1734 insertions(+), 1198 deletions(-) create mode 100644 tools/bfapei/Makefile create mode 100644 tools/bfapei/bfapei.c create mode 100644 tools/bfapei/bfapei.h create mode 100644 tools/common/Makefile create mode 100644 tools/common/build_aml.c create mode 100644 tools/common/check_aml.c create mode 100644 tools/common/include/acpi.h create mode 100644 tools/common/include/build_aml.h create mode 100644 tools/common/include/check_aml.h
o move common code to separate direction so others application can reuse it o appropriate changes around Makefile files o minor changes regarding compilator worrnings
Signed-off-by: Tomasz Nowicki tomasz.nowicki@linaro.org --- Makefile | 16 +- platforms/Makefile | 6 +- tools/cab/Makefile | 12 +- tools/cab/cab.c | 527 +------------------------------------- tools/cab/cab.h | 149 ----------- tools/common/Makefile | 4 + tools/common/build_aml.c | 455 ++++++++++++++++++++++++++++++++ tools/common/check_aml.c | 512 ++++++++++++++++++++++++++++++++++++ tools/common/include/build_aml.h | 74 ++++++ tools/common/include/check_aml.h | 99 +++++++ tools/mab/Makefile | 13 +- tools/mab/mab.c | 430 +------------------------------ tools/mab/mab.h | 77 ------ 13 files changed, 1183 insertions(+), 1191 deletions(-) create mode 100644 tools/common/Makefile create mode 100644 tools/common/build_aml.c create mode 100644 tools/common/check_aml.c create mode 100644 tools/common/include/build_aml.h create mode 100644 tools/common/include/check_aml.h
diff --git a/Makefile b/Makefile index ef63965..e897c69 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,21 @@ MABDIR := tools/mab/ CABDIR := tools/cab/ +COMMON_DIR := tools/common/ PLATDIR := platforms/
-%.acpi : $(MABDIR)/mab $(CABDIR)/cab +%.acpi : mab cab make MAB=$(CURDIR)/$(MABDIR)/mab PADDR=$(PADDR) -C $(PLATDIR) $@
-$(MABDIR)/mab : FORCE - make -C $(MABDIR) +mab : FORCE + make -C $(MABDIR) PROG=mab
-$(CABDIR)/cab : FORCE - make -C $(CABDIR) +cab : FORCE + make -C $(CABDIR) PROG=cab
clean : - make -C $(MABDIR) clean - make -C $(CABDIR) clean + make -C $(MABDIR) clean PROG=mab + make -C $(CABDIR) clean PROG=cab + make -C $(COMMON_DIR) clean make -C $(PLATDIR) clean
FORCE : diff --git a/platforms/Makefile b/platforms/Makefile index 95e8453..caff1c8 100644 --- a/platforms/Makefile +++ b/platforms/Makefile @@ -6,9 +6,9 @@ endif $(MAB) -d $@ $(PADDR_ARG) -i $(basename $@).manifest -o $@
clean : - -rm *.acpi/*.aml - -rm *.acpi/*.lst - -rm *.acpi/*.acpi + -rm -f *.acpi/*.aml + -rm -f *.acpi/*.lst + -rm -f *.acpi/*.acpi
FORCE :
diff --git a/tools/cab/Makefile b/tools/cab/Makefile index b363232..2dcec39 100644 --- a/tools/cab/Makefile +++ b/tools/cab/Makefile @@ -1,7 +1,11 @@ -CFLAGS := -g +CFLAGS := -g -Wall -I../common/include
-cab : cab.h cab.c - $(CC) $(CFLAGS) -o cab cab.c +HEADERS = $(wildcard *.h) $(wildcard ../common/include/*.h) + +SOURCES = $(wildcard *.c) $(wildcard ../common/*.c) + +$(PROG) : $(patsubst %.c,%.o, $(SOURCES)) $(HEADERS) + $(CC) $(CFLAGS) $(patsubst %.c,%.o, $(SOURCES)) -o $@
clean : - -rm -f cab cab.o + -rm -f $(patsubst %.c,%.o, $(wildcard *.c)) $(PROG) diff --git a/tools/cab/cab.c b/tools/cab/cab.c index 155e055..481c021 100644 --- a/tools/cab/cab.c +++ b/tools/cab/cab.c @@ -11,28 +11,12 @@ * */
-#include "cab.h" - -#include <sys/queue.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> - -#include <ctype.h> -#include <endian.h> -#include <errno.h> -#include <fcntl.h> -#include <libgen.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> +#include <build_aml.h> +#include <check_aml.h>
-int passed; -int failed; +#include "cab.h"
-void usage(void) +static void usage(void) { printf("%s %s\n", PROGNAME, VERSION); printf("usage: %s -b <blob> -p <paddr> [-q]\n", PROGNAME); @@ -42,517 +26,24 @@ void usage(void) printf(" -q => if given, supress output\n"); }
-int get_file_size(char *fname) -{ - struct stat buf; - int err; - - err = stat(fname, &buf); - if (err) - printf("? cannot stat %s (%d)\n", fname, err); - return (err == 0 ? buf.st_size : 0); -} - -int valid_sig(char *sig) -{ - char **p; - - p = known_sigs; - while (*p != NULL) { - if (strncmp(*p, sig, strlen(*p)) == 0) - return 1; - p++; - } - return 0; -} - -struct table *build_table_entry(unsigned char *buf) -{ - struct table *tmp; - const int RSDP_NUDGE = 3; - int len; - - tmp = (struct table *)malloc(sizeof(struct table)); - if (tmp != NULL) { - memset(tmp, 0, sizeof(struct table)); - - /* fill in the struct */ - len = SIG_LENGTH + 1; - if (strncmp(buf, SIG_RSDP, SIG_LENGTH + RSDP_NUDGE) == 0) - len += RSDP_NUDGE; - tmp->signature = (char *)malloc(len); - memset(tmp->signature, 0, len); - memcpy(tmp->signature, buf, len - 1); - - LIST_INSERT_HEAD(&thead, tmp, tables); - } - - return tmp; -} - -struct table *find_table(char *sig) -{ - struct table *np; - - LIST_FOREACH(np, &thead, tables) { - if (strncmp(np->signature, sig, strlen(np->signature)) == 0) - return np; - } - return NULL; -} - -struct known_table_info *find_known_table_info(char *sig) -{ - struct known_table_info *np; - - for (np = known_info; np->signature != NULL; np++) { - if (strncmp(np->signature, sig, strlen(np->signature)) == 0) - return np; - } - return NULL; -} - -int verify_checksum(unsigned char *start, int offset, int len) -{ - uint8_t newsum, oldsum; - uint8_t *p; - uint8_t old_cksum, cksum; - - old_cksum = start[offset]; - cksum = old_cksum; - newsum = 0; - for (p = (uint8_t *)start; p < (uint8_t *)(start + len); p++) - newsum += *p; - - oldsum = cksum; - newsum = (uint8_t)(newsum - oldsum); - - cksum = (uint8_t)(0 - newsum); - - return (old_cksum == cksum ? PASS : FAIL); -} - -int verify_revision(unsigned char *r, int min) -{ - return (*(uint8_t *)r >= min ? PASS : FAIL); -} - -void presult(int res, char *topic) -{ - if (res != 0) - passed++; - else - failed++; - if (res >= 0) - printf("[%4s] %s\n", (res != 0) ? "PASS" : "FAIL", topic); - else - printf("[%4s] %s\n", "INFO", topic); -} - -void check_blob_header(unsigned char *blob) -{ - int res; - - printf("\nchecking blob header...\n"); - res = strncmp(blob, BLOB_MAGIC, BLOB_MAGIC_SIZE); - res = (res == 0 ? PASS : FAIL); - presult(res, "blob magic number is correct"); -} - -void check_table_header(char *name, unsigned char *loc) -{ - const int CHECKSUM_OFFSET = 9; - const int CREATOR_ID_OFFSET = 28; - const int CREATOR_ID_LEN = 4; - const int CREATOR_REV_OFFSET = 32; - const int CREATOR_REV_LEN = 4; - const int OEMID_OFFSET = 10; - const int OEMID_LEN = 6; - const int REVISION_OFFSET = 8; - - struct known_table_info *kp; - char buf[MAX_LINE]; - int res; - int offset; - uint32_t len; - int min; - - /* valid signature? */ - kp = find_known_table_info(name); - res = (kp ? PASS : FAIL); - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: signature is correct", name); - presult(res, buf); - - if (!kp) { - printf("? %s is an unknown table\n", name); - return; - } - - /* possibly usable length? */ - len = *(uint32_t *)(loc + TABLE_LEN_OFFSET); - res = PASS; - if ((len <= 0) || (len < MIN_TABLE_LENGTH)) - res = FAIL; - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: table length is reasonable (%d)", name, len); - presult(res, buf); - - /* valid checksum? */ - res = verify_checksum(loc, CHECKSUM_OFFSET, len); - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: checksum is correct", name); - presult(res, buf); - - /* valid revision number? */ - res = verify_revision(loc + REVISION_OFFSET, kp->min_revision); - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: minimum revision is correct", name); - presult(res, buf); - - /* non-empty OEMID field? */ - res = (loc[OEMID_OFFSET] != 0 ? PASS : FAIL); - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: there is an OEMID (", name); - strncat(buf, (unsigned char *)(loc + OEMID_OFFSET), OEMID_LEN); - strncat(buf, ")", 1); - presult(res, buf); - - /* non-empty CreatorID field? */ - res = (loc[CREATOR_ID_OFFSET] != 0 ? PASS : FAIL); - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: there is a CreatorID", name); - presult(res, buf); - - /* non-empty CreatorRevision field? */ - res = (loc[CREATOR_REV_OFFSET] != 0 ? PASS : FAIL); - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s: there is a CreatorRevision", name); - presult(res, buf); -} - -void check_first_table_is_rsdp(unsigned char *blob) -{ - int res; - - res = strncmp(blob + BLOB_HEADER_SIZE, SIG_RSDP, strlen(SIG_RSDP)); - res = (res == 0 ? PASS : FAIL); - presult(res, "first table has RSDP signature"); -} - -void check_rsdp(unsigned char *blob) -{ - const int RSDP_FIRST_CKSUM_OFFSET = 8; - const int RSDP_FIRST_CKSUM_LEN = 20; - const int RSDP_SECOND_CKSUM_OFFSET = 32; - const int RSDP_SECOND_CKSUM_LEN = 36; - const int RSDP_RSDT_ADDR_OFFSET = 16; - - unsigned char *ptr; - int res; - uint32_t rsdt_addr; - - ptr = blob + BLOB_HEADER_SIZE; - printf("\nchecking RSDP...\n"); - check_first_table_is_rsdp(blob); - - res = verify_checksum(ptr, RSDP_FIRST_CKSUM_OFFSET, - RSDP_FIRST_CKSUM_LEN); - presult(res, "first RSDP checksum verified"); - - res = verify_checksum(ptr, RSDP_SECOND_CKSUM_OFFSET, - RSDP_SECOND_CKSUM_LEN); - presult(res, "second RSDP checksum verified"); - - rsdt_addr = *(uint32_t *)(ptr + RSDP_RSDT_ADDR_OFFSET); - res = (rsdt_addr == 0) ? PASS : FAIL; - presult(res, "RSDT address is null"); -} - -void find_all_tables(unsigned char *blob, int size, int base_addr) -{ - struct table *tp; - unsigned char *p; - int offset; - int delta; - - /* this assumes that all signatures and lengths are correct */ - printf("\nscanning for tables...\n"); - - p = blob + BLOB_HEADER_SIZE; - offset = (int)(p - blob); - - while (offset + SIG_LENGTH < size) { - if (valid_sig(p)) { - tp = build_table_entry(p); - if (tp) { - delta = TABLE_LEN_OFFSET; - if (strcmp(tp->signature, SIG_RSDP) == 0) - delta = RSDP_LEN_OFFSET; - tp->len = *(uint32_t *)(p + delta); - tp->offset = offset; - tp->paddr = base_addr + offset; - - offset += *(uint32_t *)(p + delta); - p += tp->len; - } else { - printf("? no room for building a table\n"); - exit(1); - } - } else { - /* skip forward until we find something; a table - * could have been moved to the next page boundary */ - while (offset + SIG_LENGTH < size) { - p++; - offset++; - if (isalpha(*p) && valid_sig(p)) - break; - } - } - } -} - -void check_rsdp_relocs(unsigned char *blob, int size, uint64_t paddr) -{ - const int RSDT_ADDR_OFFSET = 16; - const int XSDT_ADDR_OFFSET = 24; - - struct table *np, *xp; - int res; - uint32_t rsdt_addr; - uint64_t xsdt_addr; - - printf("\nchecking RSDP relocations...\n"); - - res = FAIL; - np = find_table(SIG_RSDP); - if (np) { - np->ref_cnt++; - - rsdt_addr = *(uint32_t *)(blob + np->offset + RSDT_ADDR_OFFSET); - res = (rsdt_addr == 0) ? PASS : FAIL; - presult(res, "RSDP has null RSDT pointer"); - - xsdt_addr = *(uint32_t *)(blob + np->offset + XSDT_ADDR_OFFSET); - xp = find_table(SIG_XSDT); - if (xp) { - xp->ref_cnt++; - if ((xsdt_addr == xp->paddr) && - (strncmp(blob + xp->offset, SIG_XSDT, - strlen(xp->signature)) == 0)) - res = PASS; - } - presult(res, "RSDP has correct XSDT pointer"); - } else { - res = FAIL; - presult(res, "RSDP has null RSDT pointer"); - presult(res, "RSDP has correct XSDT pointer"); - } -} - -void check_xsdt_relocs(unsigned char *blob, int size, uint64_t paddr) -{ - const int XSDT_ENTRY_START = 36; - const int XSDT_ENTRY_SIZE = 8; - - struct table *np, *xp; - int res; - int cnt; - int ii; - int offset; - uint32_t len; - uint64_t *tpaddr; - char buf[MAX_LINE]; - - printf("\nchecking XSDT relocations...\n"); - - res = FAIL; - np = find_table(SIG_XSDT); - if (np) { - len = *(uint32_t *)(blob + np->offset + TABLE_LEN_OFFSET); - cnt = (len - XSDT_ENTRY_START) / XSDT_ENTRY_SIZE; - tpaddr = (uint64_t *)(blob + np->offset + XSDT_ENTRY_START); - if (len < 1) { - printf("? XSDT can not have an empty list\n"); - exit(1); - } - - /* first entry needs to be the FACP (aka FADT) */ - offset = (*tpaddr - paddr); - if (strncmp(blob + offset, SIG_FACP, strlen(SIG_FACP)) == 0) - res = PASS; - presult(res, "first XSDT entry points to the FADT (aka FACP)"); - - /* verify all the relocations, best we can */ - for (ii = 0; ii < cnt; ii++, tpaddr++) { - offset = (*tpaddr - paddr); - res = FAIL; - if (valid_sig(blob + offset)) { - xp = find_table(blob + offset); - if (xp) { - xp->ref_cnt++; - if ((*tpaddr == xp->paddr) && - (strncmp(blob + xp->offset, - blob + offset, - strlen(xp->signature)) == 0)) - res = PASS; - memset(buf, 0, MAX_LINE); - sprintf(buf, - "XSDT has correct %s pointer", - xp->signature); - presult(res, buf); - } else { - memset(buf, 0, MAX_LINE); - sprintf(buf, - "XSDT entry %d does not point to a valid table", - ii); - presult(res, buf); - } - } - } - } else { - printf("? XSDT can not be found in table list\n"); - exit(1); - } -} - -void check_fadt_relocs(unsigned char *blob, int size, uint64_t paddr) -{ - const int FWCTL_OFFSET = 36; - const int DSDT_OFFSET = 40; - const int XFWCTL_OFFSET = 132; - const int XDSDT_OFFSET = 140; - - struct table *np, *xp; - uint32_t fwctl, dsdt; - uint64_t xfwctl, xdsdt; - uint64_t tpaddr; - int res; - int offset; - - printf("\nchecking FADT relocations...\n"); - np = find_table(SIG_FACP); - if (np) { - fwctl = *(uint32_t *)(blob + np->offset + FWCTL_OFFSET); - xfwctl = *(uint64_t *)(blob + np->offset + XFWCTL_OFFSET); - res = FAIL; - if ((fwctl == 0 && xfwctl == 0) || /* no FACS is okay */ - (fwctl == 0 && xfwctl != 0) || - (fwctl != 0 && xfwctl == 0)) - res = PASS; - presult(res, "FADT has a proper 32-bit FACS pointer"); - presult(res, "FADT has a proper 64-bit FACS pointer"); - if (fwctl != 0 && xfwctl != 0) - presult(INFO, - "both fields have been set, not just one"); - - if (fwctl != 0 || xfwctl != 0) { - tpaddr = (fwctl == 0) ? xfwctl : fwctl; - offset = tpaddr - paddr; - - xp = find_table(SIG_FACS); - if (xp) { - xp->ref_cnt++; - res = FAIL; - if ((tpaddr == xp->paddr) && - (strncmp(blob + xp->offset, - blob + offset, - strlen(xp->signature)) == 0)) - res = PASS; - presult(res, "FADT has correct FACS pointer"); - - } else { - printf("? FADT refers to an FACS but "); - printf("there is no such table\n"); - exit(1); - } - } - - dsdt = *(uint32_t *)(blob + np->offset + DSDT_OFFSET); - xdsdt = *(uint64_t *)(blob + np->offset + XDSDT_OFFSET); - res = FAIL; - if ((dsdt == 0 && xdsdt != 0) || /* must have a DSDT */ - (dsdt != 0 && xdsdt == 0)) - res = PASS; - presult(res, "FADT has a proper 32-bit DSDT pointer"); - presult(res, "FADT has a proper 64-bit DSDT pointer"); - if (dsdt != 0 && xdsdt != 0) - presult(INFO, - "both fields have been set, not just one"); - - if (dsdt != 0 || xdsdt != 0) { - tpaddr = (dsdt == 0) ? xdsdt : dsdt; - offset = tpaddr - paddr; - - xp = find_table(SIG_DSDT); - if (xp) { - xp->ref_cnt++; - res = FAIL; - if ((tpaddr == xp->paddr) && - (strncmp(blob + xp->offset, - blob + offset, - strlen(xp->signature)) == 0)) - res = PASS; - presult(res, "FADT has correct DSDT pointer"); - - } else { - printf("? FADT refers to a DSDT but "); - printf("there is no such table\n"); - exit(1); - } - } - - } else { - printf("? FADT (aka FACP) can not be found in table list\n"); - exit(1); - } -} - -void check_ref_cnts(void) -{ - struct table *np; - int res; - char buf[MAX_LINE]; - - printf("\nchecking references to tables...\n"); - LIST_FOREACH(np, &thead, tables) { - memset(buf, 0, MAX_LINE); - sprintf(buf, "%s referenced only once", np->signature); - res = (np->ref_cnt == 1) ? PASS : FAIL; - presult(res, buf); - } - -} - -void check_relocations(unsigned char *blob, int size, uint64_t paddr) -{ - check_rsdp_relocs(blob, size, paddr); - check_xsdt_relocs(blob, size, paddr); - check_fadt_relocs(blob, size, paddr); - check_ref_cnts(); -} - int main(int argc, char *argv[]) { - int ii, jj; - int offset; - int delta; + int ii; int size; int fd; unsigned char *blob; char *acpi_blob_name; char *paddr_cmd; uint64_t paddr = 0; - char sig[SIG_LENGTH]; struct table *np; int opt; int quiet; + int failed;
/* parameter handling */ acpi_blob_name = NULL; paddr_cmd = NULL; quiet = 0; - passed = 0; failed = 0;
while ((opt = getopt(argc, argv, "b:p:q")) != EOF) { @@ -640,11 +131,7 @@ int main(int argc, char *argv[])
check_relocations(blob, size, paddr);
- printf("\nTotal tests: %d\n", passed + failed); - printf("Passed: %d\n", passed); - printf("Failed: %d\n", failed); - printf("Success rate: %0.1f%\n", - (100.0 * (float)passed) / (float)(passed + failed)); + failed = check_print_summary();
munmap(blob, size);
diff --git a/tools/cab/cab.h b/tools/cab/cab.h index 4512757..464ac45 100644 --- a/tools/cab/cab.h +++ b/tools/cab/cab.h @@ -13,157 +13,8 @@ * */
-#include <stdint.h> -#include <string.h> - -#include <sys/queue.h> - /* VERSION a.b.c = <ACPI standard>.<functionality changes>.<bug fixes> */ const char VERSION[] = { "5.0~3.1" }; const char PROGNAME[] = { "cab" };
-#define PASS 1 -#define FAIL 0 -#define INFO (-1) - -#define BLOB_HEADER_SIZE 8 -#define BLOB_MAGIC "ACPI" -#define BLOB_MAGIC_SIZE 4 -#define MAX_LINE 1024 -#define MIN_TABLE_LENGTH 36 -#define NOT_REQUIRED 0 -#define REQUIRED 1 -#define RSDP_LEN_OFFSET 20 -#define SIG_LENGTH 4 -#define TABLE_LEN_OFFSET 4 - -#define SIG_APIC "APIC" -#define SIG_BERT "BERT" -#define SIG_CPEP "CPEP" -#define SIG_DSDT "DSDT" -#define SIG_ECDT "ECDT" -#define SIG_EINJ "EINJ" -#define SIG_ERST "ERST" -#define SIG_FACP "FACP" -#define SIG_FACS "FACS" -#define SIG_FPDT "FPDT" -#define SIG_GTDT "GTDT" -#define SIG_HEST "HEST" -#define SIG_MCFG "MCFG" -#define SIG_MCHI "MCHI" -#define SIG_MPST "MPST" -#define SIG_MSCT "MSCT" -#define SIG_OEM "OEM" -#define SIG_PCCT "PCCT" -#define SIG_PMTT "PMTT" -#define SIG_RASF "RASF" -#define SIG_RSDP "RSD PTR" -#define SIG_RSDT "RSDT" -#define SIG_SLIT "SLIT" -#define SIG_SPMI "SPMI" -#define SIG_SRAT "SRAT" -#define SIG_SSDT "SSDT" -#define SIG_UEFI "UEFI" -#define SIG_XSDT "XSDT" - -struct known_table_info { - char *signature; /* table signature */ - int min_revision; /* minimum allowed revision */ -}; - -struct known_table_info known_info[] = { - { SIG_APIC, 3 }, - { SIG_BERT, 1 }, - { SIG_CPEP, 1 }, - { SIG_DSDT, 2 }, - { SIG_ECDT, 1 }, - { SIG_EINJ, 1 }, - { SIG_ERST, 1 }, - { SIG_FACP, 5 }, - { SIG_FACS, 5 }, - { SIG_FPDT, 1 }, - { SIG_GTDT, 1 }, - { SIG_HEST, 1 }, - { SIG_MCFG, 1 }, - { SIG_MCHI, 1 }, - { SIG_MPST, 1 }, - { SIG_MSCT, 1 }, - { SIG_OEM, 1 }, - { SIG_PMTT, 1 }, - { SIG_RASF, 1 }, - { SIG_RSDP, 2 }, - { SIG_RSDT, 1 }, - { SIG_SLIT, 1 }, - { SIG_SPMI, 1 }, - { SIG_SRAT, 3 }, - { SIG_SSDT, 2 }, - { SIG_UEFI, 1 }, - { SIG_XSDT, 1 }, - { NULL, 0 } -}; - -char *known_sigs[] = { - "APIC", - "BERT", - "CPEP", - "DSDT", - "ECDT", - "EINJ", - "ERST", - "FACP", - "FACS", - "FPDT", - "GTDT", - "HEST", - "MCFG", - "MCHI", - "MPST", - "MSCT", - "OEM", - "PCCT", - "PMTT", - "RASF", - "RSD PTR", - "SLIT", - "SPMI", - "SRAT", - "SSDT", - "UEFI", - "XSDT", - NULL -}; - -LIST_HEAD(table_head, table) thead; -struct table_head *theadp; - -struct table { - char *signature; /* an ACPI table name/signature */ - int len; /* reported table length */ - int offset; /* location in the blob */ - uint64_t paddr; /* where it should live in RAM */ - int ref_cnt; /* reference count */ - LIST_ENTRY(table) tables; -}; - - -struct table *build_table_entry(unsigned char *buf); -void check_blob_header(unsigned char *blob); -void check_fadt_relocs(unsigned char *blob, int size, uint64_t paddr); -void check_first_table_is_rsdp(unsigned char *blob); -void check_rsdp(unsigned char *blob); -void check_ref_cnts(void); -void check_relocations(unsigned char *blob, int size, uint64_t paddr); -void check_rsdp_relocs(unsigned char *blob, int size, uint64_t paddr); -void check_table_header(char *name, unsigned char *loc); -void check_xsdt_relocs(unsigned char *blob, int size, uint64_t paddr); -void find_all_tables(unsigned char *blob, int size, int base_addr); -struct known_table_info *find_known_table_info(char *sig); -struct table *find_table(char *sig); -int get_file_size(char *fname); -void usage(void); -int valid_sig(char *sig); -int verify_checksum(unsigned char *start, int offset, int len); -int verify_revision(unsigned char *r, int min); -void presult(int res, char *topic); - #endif diff --git a/tools/common/Makefile b/tools/common/Makefile new file mode 100644 index 0000000..03d9388 --- /dev/null +++ b/tools/common/Makefile @@ -0,0 +1,4 @@ +SOURCES = $(wildcard *.c) + +clean : + -rm -f $(patsubst %.c,%.o, $(SOURCES)) diff --git a/tools/common/build_aml.c b/tools/common/build_aml.c new file mode 100644 index 0000000..ebfcdc4 --- /dev/null +++ b/tools/common/build_aml.c @@ -0,0 +1,455 @@ +/* + * build_aml.c: helper functions for the tool to Make A Blob of ACPI tables + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Al Stone al.stone@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#include <build_aml.h> + +char *known_sigs[] = { + "apic", + "bert", + "cpep", + "dsdt", + "ecdt", + "einj", + "erst", + "facp", + "facs", + "fpdt", + "gtdt", + "hest", + "mcfg", + "mchi", + "mpst", + "msct", + "oem", + "pcct", + "pmtt", + "rasf", + "rsdp", + "slit", + "spmi", + "srat", + "ssdt", + "uefi", + "xsdt", + NULL +}; + +int get_file_size(char *fname) +{ + struct stat buf; + int err; + + err = stat(fname, &buf); + if (err) + printf("? cannot stat %s (%d)\n", fname, err); + return (err == 0 ? buf.st_size : 0); +} + +int valid_sig(char *sig) +{ + char **p; + + p = known_sigs; + while (*p != NULL) { + if (strcmp(*p, sig) == 0) + return 1; + p++; + } + return 0; +} + +struct table *build_table_entry(char *dir, char *buf) +{ + struct table *tmp; + char sig[MAX_LINE]; + char fname[MAX_LINE]; + int ii, n; + char *p; + + tmp = (struct table *)malloc(sizeof(struct table)); + if (tmp != NULL) { + memset(tmp, 0, sizeof(struct table)); + memset(sig, 0, MAX_LINE); + memset(fname, 0, MAX_LINE); + + /* parse the line */ + n = 0; + for (ii = 0; ii < strlen(buf); ii++) { + if (buf[ii] == ':' || isspace(buf[ii])) + break; + sig[n++] = buf[ii]; + } + if (!valid_sig((unsigned char*)sig)) { + free(tmp); + return NULL; + } + while (buf[ii] == ':' || isspace(buf[ii])) + ii++; + n = 0; + for (; ii < strlen(buf); ii++) { + if (buf[ii] == '\n' || !isascii(buf[ii])) + break; + fname[n++] = buf[ii]; + } + + /* fill in the struct */ + tmp->signature = (char *)malloc(strlen(sig) + 1); + memset(tmp->signature, 0, strlen(sig) + 1); + memcpy(tmp->signature, sig, strlen(sig)); + + n = strlen(fname) + strlen(dir) + 2; + tmp->asl_name = (char *)malloc(n); + memset(tmp->asl_name, 0, n); + strcpy(tmp->asl_name, dir); + strcat(tmp->asl_name, "/"); + strcat(tmp->asl_name, fname); + + tmp->aml_name = (char *)malloc(n); + memset(tmp->aml_name, 0, n); + strcpy(tmp->aml_name, tmp->asl_name); + p = strrchr(tmp->aml_name, '.'); + if (p) + strcpy(p, ".aml"); + + tmp->file_size = -1; /* need to build .aml file first */ + tmp->offset = -1; + } + + return tmp; +} + +int read_manifest(char *dir, char *fname) +{ + FILE *fp; + struct table *p; + char line[MAX_LINE]; + char *tmp; + char buf[MAX_LINE]; + + memset(buf, 0, MAX_LINE); + strcpy(buf, dir); + strcat(buf, "/"); + strcat(buf, fname); + fp = fopen(buf, "r"); + if (!fp) + return -ENOENT; + + LIST_INIT(&thead); + memset(line, 0, MAX_LINE); + tmp = fgets(line, MAX_LINE, fp); + while (tmp != NULL) { + if (strlen(line) > 0 && line[0] != '#' && line[0] != '\n') { + p = build_table_entry(dir, line); + if (p) + LIST_INSERT_HEAD(&thead, p, tables); + } + memset(line, 0, MAX_LINE); + tmp = fgets(line, MAX_LINE, fp); + } + fclose(fp); + + return 0; +} + +void set_blob_header(unsigned char *blob, int blob_size) +{ + uint32_t *psize; + + /* the resulting blob contents are always little-endian */ + memcpy(blob, BLOB_MAGIC, BLOB_MAGIC_SIZE); + + psize = (uint32_t *)(blob + BLOB_MAGIC_SIZE); + *psize = (uint32_t)(htobe32(blob_size)); + +} + +struct table *find_table(char *sig) +{ + struct table *np; + + LIST_FOREACH(np, &thead, tables) { + if (strcmp(np->signature, sig) == 0) + return np; + } + return NULL; +} + +void write_table(unsigned char *blob, struct table *tp, int offset) +{ + unsigned char *start; + FILE *fp; + + tp->offset = offset; + start = blob + offset; + fp = fopen(tp->aml_name, "r"); + if (fp) { + fread(start, 1, tp->file_size, fp); + fclose(fp); + } +} + +void write_blob(char *dir, char *fname, unsigned char *blob, int size) +{ + FILE *fp; + char newname[MAX_LINE]; + + memset(newname, 0, MAX_LINE); + strcpy(newname, dir); + strcat(newname, "/"); + strcat(newname, fname); + + fp = fopen(newname, "w+"); + if (fp) { + fwrite(blob, 1, size, fp); + fclose(fp); + } else { + printf("? could not open the blob file: %s\n", newname); + } +} + +void set_checksum(unsigned char *start, int len, uint8_t *cksum) +{ + uint8_t newsum, oldsum; + uint8_t *p; + + newsum = 0; + for (p = (uint8_t *)start; p < (uint8_t *)(start + len); p++) + newsum += *p; + + oldsum = *cksum; + newsum = (uint8_t)(newsum - oldsum); + + *cksum = (uint8_t)(0 - newsum); +} + +int add_table(unsigned char **blob, char *table_name, int offset, int reqd) +{ + struct table *p; + int new_offset; + int adjustment = 0; + + p = find_table(table_name); + new_offset = offset + p->file_size; + + /* + * Handle crossing of page boundaries to prevent problems + * on armv7 with small page sizes + */ + if ((new_offset / PAGE_SIZE) != (offset / PAGE_SIZE)) { + adjustment = PAGE_SIZE - (offset % PAGE_SIZE); + /* + * If this is the first page crossing remove the + * blob header from calculations + */ + if (!(offset / PAGE_SIZE)) + adjustment -= BLOB_HEADER_SIZE; + } + + if (p) { + *blob = realloc(*blob, offset + adjustment + p->file_size); + write_table(*blob, p, offset + adjustment); + p->offset = offset + adjustment; + } else { + if (reqd) { + printf("? %s table is required\n", table_name); + return 0; + } + } + + /* NB: ACPI table size cannot be zero -- there must be a header */ + return p->file_size + adjustment; +} + +void fixup_rsdp(unsigned char *blob, uint64_t paddr) +{ + /* We could use the 32-bit RSDT address but that has + * essentially been deprecated. Instead, use the 64-bit + * XSDT address though be sure to use little-endian values. + */ + const int RSDP_FIRST_CHECKSUM_BYTES = 20; + const int RSDP_FIRST_CHECKSUM_OFFSET = 8; + const int RSDP_SECOND_CHECKSUM_BYTES = 36; + const int RSDP_SECOND_CHECKSUM_OFFSET = 32; + const int RSDT_ADDR_OFFSET = 16; + const int XSDT_ADDR_OFFSET = 24; + + uint8_t *pcksum; + uint32_t *stmp; + uint64_t *ltmp; + struct table *rsdpp; + struct table *p; + + /* NB: there are no safety checks on the find_table() + * return value because if we've gotten this far and + * the RSDP doesn't exist, something else has gone + * seriously wrong far earlier. + */ + rsdpp = find_table("rsdp"); + stmp = (uint32_t *)(blob + rsdpp->offset + RSDT_ADDR_OFFSET); + ltmp = (uint64_t *)(blob + rsdpp->offset + XSDT_ADDR_OFFSET); + + p = find_table("xsdt"); + if (p) + *ltmp = p->offset + paddr; + else + *ltmp = (uint64_t)0; + + p = find_table("rsdt"); + if (p) + *stmp = p->offset + paddr; + else + *stmp = (uint64_t)0; + + /* always reset the checksum, even if it is seldom used */ + pcksum = (uint8_t *)(blob + rsdpp->offset + RSDP_FIRST_CHECKSUM_OFFSET); + set_checksum((unsigned char *)(blob + rsdpp->offset), + RSDP_FIRST_CHECKSUM_BYTES, pcksum); + + pcksum = (uint8_t *) + (blob + rsdpp->offset + RSDP_SECOND_CHECKSUM_OFFSET); + set_checksum((unsigned char *)(blob + rsdpp->offset), + RSDP_SECOND_CHECKSUM_BYTES, pcksum); +} + +void fixup_facp(unsigned char *blob, int *offset, uint64_t paddr, int facs64) +{ + const int DSDT_ADDR_OFFSET = 40; + const int FACP_CHECKSUM_OFFSET = 9; + const int FIRMWARE_CTRL_OFFSET = 36; + const int X_DSDT_ADDR_OFFSET = 140; + const int X_FIRMWARE_CTRL_OFFSET = 132; + + struct table *facpp; + struct table *p; + uint32_t *stmp; + uint64_t *ltmp; + uint8_t *pcksum; + + facpp = find_table("facp"); + + /* add in the DSDT and X_DSDT addresses */ + stmp = (uint32_t *)(blob + facpp->offset + DSDT_ADDR_OFFSET); + ltmp = (uint64_t *)(blob + facpp->offset + X_DSDT_ADDR_OFFSET); + p = find_table("dsdt"); + if (p) { + if (facs64) { + *stmp = (uint32_t)0; + *ltmp = (uint64_t)p->offset + paddr; + } else { + *stmp = (uint32_t)p->offset + paddr; + *ltmp = (uint64_t)0; + } + } else { + *stmp = (uint32_t)0; + *ltmp = (uint64_t)0; + return; + } + + /* add in the FIRMWARE_CTRL and X_FIRMWARE_CTRL addresses */ + stmp = (uint32_t *)(blob + facpp->offset + FIRMWARE_CTRL_OFFSET); + ltmp = (uint64_t *)(blob + facpp->offset + X_FIRMWARE_CTRL_OFFSET); + p = find_table("facs"); + if (p) { + if (facs64) { + *stmp = (uint32_t)0; + *ltmp = (uint64_t)p->offset + paddr; + } else { + *stmp = (uint32_t)p->offset + paddr; + *ltmp = (uint64_t)0; + } + } else { + *stmp = (uint32_t)0; + *ltmp = (uint64_t)0; + return; + } + + /* always reset the checksum, even if it is seldom used */ + pcksum = (uint8_t *)(blob + facpp->offset + FACP_CHECKSUM_OFFSET); + set_checksum((unsigned char *)(blob + facpp->offset), + facpp->file_size, pcksum); +} + +void fixup_xsdt(unsigned char **blob, int *offset, uint64_t paddr) +{ + const int FACP_ADDR_OFFSET = 36; + const int XSDT_CHECKSUM_OFFSET = 9; + const int XSDT_HEADER_SIZE = 36; + + struct table *xsdtp; + struct table *p; + uint64_t *tmp; + uint8_t *pcksum; + int delta; + int allowed; + + xsdtp = find_table("xsdt"); + tmp = (uint64_t *)(*blob + xsdtp->offset + FACP_ADDR_OFFSET); + allowed = (xsdtp->file_size - XSDT_HEADER_SIZE) / sizeof(uint64_t); + + /* first table must be FACP (aka FADT) */ + p = find_table("facp"); + if (p) + *tmp = p->offset + paddr; + else { + *tmp = (uint64_t)0; + return; + } + + /* any tables not already in use go here */ + allowed--; + tmp++; + LIST_FOREACH(p, &thead, tables) { + if (p->offset < 0) { + if ((unsigned long long)tmp < + (unsigned long long) + (xsdtp + xsdtp->file_size)) { + delta = add_table(blob, p->signature, + *offset, NOT_REQUIRED); + *offset += delta; + *tmp++ = p->offset + paddr; + allowed--; + if (allowed < 1) + break; + } + } + } + + /* always reset the checksum, even if it is seldom used */ + pcksum = (uint8_t *)(*blob + xsdtp->offset + XSDT_CHECKSUM_OFFSET); + set_checksum((unsigned char *)(*blob + xsdtp->offset), + xsdtp->file_size, pcksum); +} + +void build_aml(int q, char *dir, char *iasl_cmd, struct table *tp) +{ + char cmd[MAX_LINE]; + struct stat mbuf; + struct stat sbuf; + + if (!tp) + return; + + if ((stat(tp->aml_name, &mbuf) == 0) && + (stat(tp->asl_name, &sbuf) == 0)) { + if (mbuf.st_mtime > sbuf.st_mtime) + return; /* AML file is newer than ASL file */ + } + + strcpy(cmd, iasl_cmd); + strcat(cmd, " "); + strcat(cmd, tp->asl_name); + if (q) + strcat(cmd, " >/dev/null 2&1"); + + system(cmd); +} diff --git a/tools/common/check_aml.c b/tools/common/check_aml.c new file mode 100644 index 0000000..ac47aa6 --- /dev/null +++ b/tools/common/check_aml.c @@ -0,0 +1,512 @@ +/* + * cab.c: helper functions for the tool to Check A Blob of ACPI tables + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Al Stone al.stone@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#include <build_aml.h> +#include <check_aml.h> + +int passed; +int failed; + +struct known_table_info known_info[] = { + { SIG_APIC, 3 }, + { SIG_BERT, 1 }, + { SIG_CPEP, 1 }, + { SIG_DSDT, 2 }, + { SIG_ECDT, 1 }, + { SIG_EINJ, 1 }, + { SIG_ERST, 1 }, + { SIG_FACP, 5 }, + { SIG_FACS, 5 }, + { SIG_FPDT, 1 }, + { SIG_GTDT, 1 }, + { SIG_HEST, 1 }, + { SIG_MCFG, 1 }, + { SIG_MCHI, 1 }, + { SIG_MPST, 1 }, + { SIG_MSCT, 1 }, + { SIG_OEM, 1 }, + { SIG_PMTT, 1 }, + { SIG_RASF, 1 }, + { SIG_RSDP, 2 }, + { SIG_RSDT, 1 }, + { SIG_SLIT, 1 }, + { SIG_SPMI, 1 }, + { SIG_SRAT, 3 }, + { SIG_SSDT, 2 }, + { SIG_UEFI, 1 }, + { SIG_XSDT, 1 }, + { NULL, 0 } +}; + +struct table *check_table_entry(unsigned char *buf) +{ + struct table *tmp; + const int RSDP_NUDGE = 3; + int len; + + tmp = (struct table *)malloc(sizeof(struct table)); + if (tmp != NULL) { + memset(tmp, 0, sizeof(struct table)); + + /* fill in the struct */ + len = SIG_LENGTH + 1; + if (strncmp((char *)buf, SIG_RSDP, SIG_LENGTH + RSDP_NUDGE) == 0) + len += RSDP_NUDGE; + tmp->signature = (char *)malloc(len); + memset(tmp->signature, 0, len); + memcpy(tmp->signature, buf, len - 1); + + LIST_INSERT_HEAD(&thead, tmp, tables); + } + + return tmp; +} + +struct known_table_info *find_known_table_info(char *sig) +{ + struct known_table_info *np; + + for (np = known_info; np->signature != NULL; np++) { + if (strncmp(np->signature, sig, strlen(np->signature)) == 0) + return np; + } + return NULL; +} + +int verify_checksum(unsigned char *start, int offset, int len) +{ + uint8_t newsum, oldsum; + uint8_t *p; + uint8_t old_cksum, cksum; + + old_cksum = start[offset]; + cksum = old_cksum; + newsum = 0; + for (p = (uint8_t *)start; p < (uint8_t *)(start + len); p++) + newsum += *p; + + oldsum = cksum; + newsum = (uint8_t)(newsum - oldsum); + + cksum = (uint8_t)(0 - newsum); + + return (old_cksum == cksum ? PASS : FAIL); +} + +int verify_revision(unsigned char *r, int min) +{ + return (*(uint8_t *)r >= min ? PASS : FAIL); +} + +void check_blob_header(unsigned char *blob) +{ + int res; + + printf("\nchecking blob header...\n"); + res = strncmp((char *)blob, BLOB_MAGIC, BLOB_MAGIC_SIZE); + res = (res == 0 ? PASS : FAIL); + presult(res, "blob magic number is correct"); +} + +void check_table_header(char *name, unsigned char *loc) +{ + const int CHECKSUM_OFFSET = 9; + const int CREATOR_ID_OFFSET = 28; + const int CREATOR_REV_OFFSET = 32; + const int OEMID_OFFSET = 10; + const int OEMID_LEN = 6; + const int REVISION_OFFSET = 8; + + struct known_table_info *kp; + char buf[MAX_LINE]; + int res; + uint32_t len; + + /* valid signature? */ + kp = find_known_table_info(name); + res = (kp ? PASS : FAIL); + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: signature is correct", name); + presult(res, buf); + + if (!kp) { + printf("? %s is an unknown table\n", name); + return; + } + + /* possibly usable length? */ + len = *(uint32_t *)(loc + TABLE_LEN_OFFSET); + res = PASS; + if ((len <= 0) || (len < MIN_TABLE_LENGTH)) + res = FAIL; + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: table length is reasonable (%d)", name, len); + presult(res, buf); + + /* valid checksum? */ + res = verify_checksum(loc, CHECKSUM_OFFSET, len); + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: checksum is correct", name); + presult(res, buf); + + /* valid revision number? */ + res = verify_revision(loc + REVISION_OFFSET, kp->min_revision); + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: minimum revision is correct", name); + presult(res, buf); + + /* non-empty OEMID field? */ + res = (loc[OEMID_OFFSET] != 0 ? PASS : FAIL); + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: there is an OEMID (", name); + strncat(buf, (char *)(loc + OEMID_OFFSET), OEMID_LEN); + strncat(buf, ")", 1); + presult(res, buf); + + /* non-empty CreatorID field? */ + res = (loc[CREATOR_ID_OFFSET] != 0 ? PASS : FAIL); + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: there is a CreatorID", name); + presult(res, buf); + + /* non-empty CreatorRevision field? */ + res = (loc[CREATOR_REV_OFFSET] != 0 ? PASS : FAIL); + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s: there is a CreatorRevision", name); + presult(res, buf); +} + +void check_first_table_is_rsdp(unsigned char *blob) +{ + int res; + + res = strncmp((char *)blob + BLOB_HEADER_SIZE, SIG_RSDP, strlen(SIG_RSDP)); + res = (res == 0 ? PASS : FAIL); + presult(res, "first table has RSDP signature"); +} + +void check_rsdp(unsigned char *blob) +{ + const int RSDP_FIRST_CKSUM_OFFSET = 8; + const int RSDP_FIRST_CKSUM_LEN = 20; + const int RSDP_SECOND_CKSUM_OFFSET = 32; + const int RSDP_SECOND_CKSUM_LEN = 36; + const int RSDP_RSDT_ADDR_OFFSET = 16; + + unsigned char *ptr; + int res; + uint32_t rsdt_addr; + + ptr = blob + BLOB_HEADER_SIZE; + printf("\nchecking RSDP...\n"); + check_first_table_is_rsdp(blob); + + res = verify_checksum(ptr, RSDP_FIRST_CKSUM_OFFSET, + RSDP_FIRST_CKSUM_LEN); + presult(res, "first RSDP checksum verified"); + + res = verify_checksum(ptr, RSDP_SECOND_CKSUM_OFFSET, + RSDP_SECOND_CKSUM_LEN); + presult(res, "second RSDP checksum verified"); + + rsdt_addr = *(uint32_t *)(ptr + RSDP_RSDT_ADDR_OFFSET); + res = (rsdt_addr == 0) ? PASS : FAIL; + presult(res, "RSDT address is null"); +} + +void find_all_tables(unsigned char *blob, int size, int base_addr) +{ + struct table *tp; + unsigned char *p; + int offset; + int delta; + + /* this assumes that all signatures and lengths are correct */ + printf("\nscanning for tables...\n"); + + p = blob + BLOB_HEADER_SIZE; + offset = (int)(p - blob); + + while (offset + SIG_LENGTH < size) { + if (valid_sig(p)) { + tp = check_table_entry(p); + if (tp) { + delta = TABLE_LEN_OFFSET; + if (strcmp(tp->signature, SIG_RSDP) == 0) + delta = RSDP_LEN_OFFSET; + tp->len = *(uint32_t *)(p + delta); + tp->offset = offset; + tp->paddr = base_addr + offset; + + offset += *(uint32_t *)(p + delta); + p += tp->len; + } else { + printf("? no room for building a table\n"); + exit(1); + } + } else { + /* skip forward until we find something; a table + * could have been moved to the next page boundary */ + while (offset + SIG_LENGTH < size) { + p++; + offset++; + if (isalpha(*p) && valid_sig(p)) + break; + } + } + } +} + +void check_rsdp_relocs(unsigned char *blob, int size, uint64_t paddr) +{ + const int RSDT_ADDR_OFFSET = 16; + const int XSDT_ADDR_OFFSET = 24; + + struct table *np, *xp; + int res; + uint32_t rsdt_addr; + uint64_t xsdt_addr; + + printf("\nchecking RSDP relocations...\n"); + + res = FAIL; + np = find_table(SIG_RSDP); + if (np) { + np->ref_cnt++; + + rsdt_addr = *(uint32_t *)(blob + np->offset + RSDT_ADDR_OFFSET); + res = (rsdt_addr == 0) ? PASS : FAIL; + presult(res, "RSDP has null RSDT pointer"); + + xsdt_addr = *(uint32_t *)(blob + np->offset + XSDT_ADDR_OFFSET); + xp = find_table(SIG_XSDT); + if (xp) { + xp->ref_cnt++; + if ((xsdt_addr == xp->paddr) && + (strncmp((char *)blob + xp->offset, SIG_XSDT, + strlen(xp->signature)) == 0)) + res = PASS; + } + presult(res, "RSDP has correct XSDT pointer"); + } else { + res = FAIL; + presult(res, "RSDP has null RSDT pointer"); + presult(res, "RSDP has correct XSDT pointer"); + } +} + +void check_xsdt_relocs(unsigned char *blob, int size, uint64_t paddr) +{ + const int XSDT_ENTRY_START = 36; + const int XSDT_ENTRY_SIZE = 8; + + struct table *np, *xp; + int res; + int cnt; + int ii; + int offset; + uint32_t len; + uint64_t *tpaddr; + char buf[MAX_LINE]; + + printf("\nchecking XSDT relocations...\n"); + + res = FAIL; + np = find_table(SIG_XSDT); + if (np) { + len = *(uint32_t *)(blob + np->offset + TABLE_LEN_OFFSET); + cnt = (len - XSDT_ENTRY_START) / XSDT_ENTRY_SIZE; + tpaddr = (uint64_t *)(blob + np->offset + XSDT_ENTRY_START); + if (len < 1) { + printf("? XSDT can not have an empty list\n"); + exit(1); + } + + /* first entry needs to be the FACP (aka FADT) */ + offset = (*tpaddr - paddr); + if (strncmp((char *)blob + offset, SIG_FACP, strlen(SIG_FACP)) == 0) + res = PASS; + presult(res, "first XSDT entry points to the FADT (aka FACP)"); + + /* verify all the relocations, best we can */ + for (ii = 0; ii < cnt; ii++, tpaddr++) { + offset = (*tpaddr - paddr); + res = FAIL; + if (valid_sig((unsigned char *)blob + offset)) { + xp = find_table((char *)blob + offset); + if (xp) { + xp->ref_cnt++; + if ((*tpaddr == xp->paddr) && + (strncmp((char *)blob + xp->offset, + (char *)blob + offset, + strlen(xp->signature)) == 0)) + res = PASS; + memset(buf, 0, MAX_LINE); + sprintf(buf, + "XSDT has correct %s pointer", + xp->signature); + presult(res, buf); + } else { + memset(buf, 0, MAX_LINE); + sprintf(buf, + "XSDT entry %d does not point to a valid table", + ii); + presult(res, buf); + } + } + } + } else { + printf("? XSDT can not be found in table list\n"); + exit(1); + } +} + +void check_fadt_relocs(unsigned char *blob, int size, uint64_t paddr) +{ + const int FWCTL_OFFSET = 36; + const int DSDT_OFFSET = 40; + const int XFWCTL_OFFSET = 132; + const int XDSDT_OFFSET = 140; + + struct table *np, *xp; + uint32_t fwctl, dsdt; + uint64_t xfwctl, xdsdt; + uint64_t tpaddr; + int res; + int offset; + + printf("\nchecking FADT relocations...\n"); + np = find_table(SIG_FACP); + if (np) { + fwctl = *(uint32_t *)(blob + np->offset + FWCTL_OFFSET); + xfwctl = *(uint64_t *)(blob + np->offset + XFWCTL_OFFSET); + res = FAIL; + if ((fwctl == 0 && xfwctl == 0) || /* no FACS is okay */ + (fwctl == 0 && xfwctl != 0) || + (fwctl != 0 && xfwctl == 0)) + res = PASS; + presult(res, "FADT has a proper 32-bit FACS pointer"); + presult(res, "FADT has a proper 64-bit FACS pointer"); + if (fwctl != 0 && xfwctl != 0) + presult(INFO, + "both fields have been set, not just one"); + + if (fwctl != 0 || xfwctl != 0) { + tpaddr = (fwctl == 0) ? xfwctl : fwctl; + offset = tpaddr - paddr; + + xp = find_table(SIG_FACS); + if (xp) { + xp->ref_cnt++; + res = FAIL; + if ((tpaddr == xp->paddr) && + (strncmp((char *)blob + xp->offset, + (char *)blob + offset, + strlen(xp->signature)) == 0)) + res = PASS; + presult(res, "FADT has correct FACS pointer"); + + } else { + printf("? FADT refers to an FACS but "); + printf("there is no such table\n"); + exit(1); + } + } + + dsdt = *(uint32_t *)(blob + np->offset + DSDT_OFFSET); + xdsdt = *(uint64_t *)(blob + np->offset + XDSDT_OFFSET); + res = FAIL; + if ((dsdt == 0 && xdsdt != 0) || /* must have a DSDT */ + (dsdt != 0 && xdsdt == 0)) + res = PASS; + presult(res, "FADT has a proper 32-bit DSDT pointer"); + presult(res, "FADT has a proper 64-bit DSDT pointer"); + if (dsdt != 0 && xdsdt != 0) + presult(INFO, + "both fields have been set, not just one"); + + if (dsdt != 0 || xdsdt != 0) { + tpaddr = (dsdt == 0) ? xdsdt : dsdt; + offset = tpaddr - paddr; + + xp = find_table(SIG_DSDT); + if (xp) { + xp->ref_cnt++; + res = FAIL; + if ((tpaddr == xp->paddr) && + (strncmp((char *)blob + xp->offset, + (char *)blob + offset, + strlen(xp->signature)) == 0)) + res = PASS; + presult(res, "FADT has correct DSDT pointer"); + + } else { + printf("? FADT refers to a DSDT but "); + printf("there is no such table\n"); + exit(1); + } + } + + } else { + printf("? FADT (aka FACP) can not be found in table list\n"); + exit(1); + } +} + +void check_ref_cnts(void) +{ + struct table *np; + int res; + char buf[MAX_LINE]; + + printf("\nchecking references to tables...\n"); + LIST_FOREACH(np, &thead, tables) { + memset(buf, 0, MAX_LINE); + sprintf(buf, "%s referenced only once", np->signature); + res = (np->ref_cnt == 1) ? PASS : FAIL; + presult(res, buf); + } + +} + +void check_relocations(unsigned char *blob, int size, uint64_t paddr) +{ + check_rsdp_relocs(blob, size, paddr); + check_xsdt_relocs(blob, size, paddr); + check_fadt_relocs(blob, size, paddr); + check_ref_cnts(); +} + +void presult(int res, char *topic) +{ + if (res != 0) + passed++; + else + failed++; + if (res >= 0) + printf("[%4s] %s\n", (res != 0) ? "PASS" : "FAIL", topic); + else + printf("[%4s] %s\n", "INFO", topic); +} + +int check_print_summary(void) +{ + check_print_summary(); + printf("\nTotal tests: %d\n", passed + failed); + printf("Passed: %d\n", passed); + printf("Failed: %d\n", failed); + printf("Success rate: %0.1f%\n", + (100.0 * (float)passed) / (float)(passed + failed)); + + return failed; +} diff --git a/tools/common/include/build_aml.h b/tools/common/include/build_aml.h new file mode 100644 index 0000000..91334d7 --- /dev/null +++ b/tools/common/include/build_aml.h @@ -0,0 +1,74 @@ +/* + * mab.h: tool to Make A Blob of ACPI tables + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Al Stone al.stone@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#ifndef COMMON_H_ +#define COMMON_H_ + +#include <ctype.h> +#include <endian.h> +#include <errno.h> +#include <libgen.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/queue.h> +#include <sys/types.h> +#include <sys/stat.h> + +#define BLOB_HEADER_SIZE 8 +#define BLOB_MAGIC "ACPI" +#define BLOB_MAGIC_SIZE 4 +#define MAX_LINE 1024 +#define NOT_REQUIRED 0 +#define REQUIRED 1 +#define SIG_LENGTH 4 + +LIST_HEAD(table_head, table) thead; +struct table_head *theadp; + +struct table { + char *signature; /* an ACPI table name/signature */ + char *asl_name; /* ASL file name */ + char *aml_name; /* corresponding AML name */ + int file_size; /* aka table size */ + int offset; /* location in the blob */ + int len; /* reported table length */ + uint64_t paddr; /* where it should live in RAM */ + int ref_cnt; /* reference count */ + LIST_ENTRY(table) tables; +}; + +int add_table(unsigned char **blob, char *table_name, int offset, int reqd); +void build_aml(int q, char *dir, char *iasl_cmd, struct table *tp); +struct table *build_table_entry(char *dir, char *buf); +struct table *find_table(char *sig); +int get_file_size(char *fname); +int read_manifest(char *dir, char *fname); +void set_blob_header(unsigned char *blob, int blob_size); +void set_checksum(unsigned char *start, int len, uint8_t *cksum); +void write_blob(char *dir, char *fname, unsigned char *blob, int size); +void write_table(unsigned char *blob, struct table *tp, int offset); +int valid_sig(char *sig); + +void fixup_facp(unsigned char *blob, int *offset, unsigned long paddr, + int facs64); +void fixup_rsdp(unsigned char *blob, unsigned long paddr); +void fixup_xsdt(unsigned char **blob, int *offset, unsigned long paddr); + +/* Currently a hack to avoid issues on 4k pages on armv7 */ +#define PAGE_SIZE 0x1000 + +#endif /* COMMON_H_ */ diff --git a/tools/common/include/check_aml.h b/tools/common/include/check_aml.h new file mode 100644 index 0000000..69e4ae8 --- /dev/null +++ b/tools/common/include/check_aml.h @@ -0,0 +1,99 @@ +/* + * cab.h: tool to Check A Blob of ACPI tables + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Al Stone al.stone@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#ifndef CHECK_AML_H_ +#define CHECK_AML_H_ + +#include <sys/queue.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include <ctype.h> +#include <endian.h> +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define PASS 1 +#define FAIL 0 +#define INFO (-1) + +#define BLOB_HEADER_SIZE 8 +#define BLOB_MAGIC "ACPI" +#define BLOB_MAGIC_SIZE 4 +#define MAX_LINE 1024 +#define MIN_TABLE_LENGTH 36 +#define NOT_REQUIRED 0 +#define REQUIRED 1 +#define RSDP_LEN_OFFSET 20 +#define SIG_LENGTH 4 +#define TABLE_LEN_OFFSET 4 + +#define SIG_APIC "APIC" +#define SIG_BERT "BERT" +#define SIG_CPEP "CPEP" +#define SIG_DSDT "DSDT" +#define SIG_ECDT "ECDT" +#define SIG_EINJ "EINJ" +#define SIG_ERST "ERST" +#define SIG_FACP "FACP" +#define SIG_FACS "FACS" +#define SIG_FPDT "FPDT" +#define SIG_GTDT "GTDT" +#define SIG_HEST "HEST" +#define SIG_MCFG "MCFG" +#define SIG_MCHI "MCHI" +#define SIG_MPST "MPST" +#define SIG_MSCT "MSCT" +#define SIG_OEM "OEM" +#define SIG_PCCT "PCCT" +#define SIG_PMTT "PMTT" +#define SIG_RASF "RASF" +#define SIG_RSDP "RSD PTR" +#define SIG_RSDT "RSDT" +#define SIG_SLIT "SLIT" +#define SIG_SPMI "SPMI" +#define SIG_SRAT "SRAT" +#define SIG_SSDT "SSDT" +#define SIG_UEFI "UEFI" +#define SIG_XSDT "XSDT" + +struct known_table_info { + char *signature; /* table signature */ + int min_revision; /* minimum allowed revision */ +}; + +struct table *check_table_entry(unsigned char *buf); +void check_blob_header(unsigned char *blob); +void check_fadt_relocs(unsigned char *blob, int size, uint64_t paddr); +void check_first_table_is_rsdp(unsigned char *blob); +void check_rsdp(unsigned char *blob); +void check_ref_cnts(void); +void check_relocations(unsigned char *blob, int size, uint64_t paddr); +void check_rsdp_relocs(unsigned char *blob, int size, uint64_t paddr); +void check_table_header(char *name, unsigned char *loc); +void check_xsdt_relocs(unsigned char *blob, int size, uint64_t paddr); +int check_print_summary(void); +void presult(int res, char *topic); +void find_all_tables(unsigned char *blob, int size, int base_addr); +struct known_table_info *find_known_table_info(char *sig); +int verify_checksum(unsigned char *start, int offset, int len); +int verify_revision(unsigned char *r, int min); + +#endif /* CHECK_AML_H_ */ diff --git a/tools/mab/Makefile b/tools/mab/Makefile index 0627202..ec0f0bb 100644 --- a/tools/mab/Makefile +++ b/tools/mab/Makefile @@ -1,8 +1,13 @@ -CFLAGS := -g +CFLAGS := -g -Wall -I../common/include
-mab : mab.h mab.c - $(CC) $(CFLAGS) -o mab mab.c +HEADERS = $(wildcard *.h) $(wildcard ../common/include/*.h) + +SOURCES = $(wildcard *.c) $(wildcard ../common/*.c) + + +$(PROG) : $(patsubst %.c,%.o, $(SOURCES)) $(HEADERS) + $(CC) $(CFLAGS) $(patsubst %.c,%.o, $(SOURCES)) -o $@
clean : - -rm mab + -rm -f $(patsubst %.c,%.o, $(wildcard *.c)) $(PROG)
diff --git a/tools/mab/mab.c b/tools/mab/mab.c index 2ca11fc..060ba72 100644 --- a/tools/mab/mab.c +++ b/tools/mab/mab.c @@ -11,24 +11,11 @@ * */
-#include "mab.h" - -#include <ctype.h> -#include <endian.h> -#include <errno.h> -#include <libgen.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <sys/queue.h> -#include <sys/types.h> -#include <sys/stat.h> +#include <build_aml.h>
+#include "mab.h"
-void usage(void) +static void usage(void) { printf("%s %s\n", PROGNAME, VERSION); printf("usage: %s -d <dir> -o <blob> -i <manifest> ", PROGNAME); @@ -45,417 +32,6 @@ void usage(void) printf(" -H => if given, do NOT add a blob header\n"); }
-int get_file_size(char *fname) -{ - struct stat buf; - int err; - - err = stat(fname, &buf); - if (err) - printf("? cannot stat %s (%d)\n", fname, err); - return (err == 0 ? buf.st_size : 0); -} - -int valid_sig(char *sig) -{ - char **p; - - p = known_sigs; - while (*p != NULL) { - if (strcmp(*p, sig) == 0) - return 1; - p++; - } - return 0; -} - -struct table *build_table_entry(char *dir, char *buf) -{ - struct table *tmp; - char sig[MAX_LINE]; - char fname[MAX_LINE]; - int ii, n; - char *p; - - tmp = (struct table *)malloc(sizeof(struct table)); - if (tmp != NULL) { - memset(tmp, 0, sizeof(struct table)); - memset(sig, 0, MAX_LINE); - memset(fname, 0, MAX_LINE); - - /* parse the line */ - n = 0; - for (ii = 0; ii < strlen(buf); ii++) { - if (buf[ii] == ':' || isspace(buf[ii])) - break; - sig[n++] = buf[ii]; - } - if (!valid_sig(sig)) { - free(tmp); - return NULL; - } - while (buf[ii] == ':' || isspace(buf[ii])) - ii++; - n = 0; - for (; ii < strlen(buf); ii++) { - if (buf[ii] == '\n' || !isascii(buf[ii])) - break; - fname[n++] = buf[ii]; - } - - /* fill in the struct */ - tmp->signature = (char *)malloc(strlen(sig) + 1); - memset(tmp->signature, 0, strlen(sig) + 1); - memcpy(tmp->signature, sig, strlen(sig)); - - n = strlen(fname) + strlen(dir) + 2; - tmp->asl_name = (char *)malloc(n); - memset(tmp->asl_name, 0, n); - strcpy(tmp->asl_name, dir); - strcat(tmp->asl_name, "/"); - strcat(tmp->asl_name, fname); - - tmp->aml_name = (char *)malloc(n); - memset(tmp->aml_name, 0, n); - strcpy(tmp->aml_name, tmp->asl_name); - p = strrchr(tmp->aml_name, '.'); - if (p) - strcpy(p, ".aml"); - - tmp->file_size = -1; /* need to build .aml file first */ - tmp->offset = -1; - } - - return tmp; -} - -int read_manifest(char *dir, char *fname) -{ - FILE *fp; - struct table *p; - char line[MAX_LINE]; - char *tmp; - char buf[MAX_LINE]; - - memset(buf, 0, MAX_LINE); - strcpy(buf, dir); - strcat(buf, "/"); - strcat(buf, fname); - fp = fopen(buf, "r"); - if (!fp) - return -ENOENT; - - LIST_INIT(&thead); - memset(line, 0, MAX_LINE); - tmp = fgets(line, MAX_LINE, fp); - while (tmp != NULL) { - if (strlen(line) > 0 && line[0] != '#' && line[0] != '\n') { - p = build_table_entry(dir, line); - if (p) - LIST_INSERT_HEAD(&thead, p, tables); - } - memset(line, 0, MAX_LINE); - tmp = fgets(line, MAX_LINE, fp); - } - fclose(fp); - - return 0; -} - -void set_blob_header(unsigned char *blob, int blob_size) -{ - uint32_t *psize; - - /* the resulting blob contents are always little-endian */ - memcpy(blob, BLOB_MAGIC, BLOB_MAGIC_SIZE); - - psize = (uint32_t *)(blob + BLOB_MAGIC_SIZE); - *psize = (uint32_t)(htobe32(blob_size)); - -} - -struct table *find_table(char *sig) -{ - struct table *np; - - LIST_FOREACH(np, &thead, tables) { - if (strcmp(np->signature, sig) == 0) - return np; - } - return NULL; -} - -void write_table(unsigned char *blob, struct table *tp, int offset) -{ - unsigned char *buf; - unsigned char *start; - FILE *fp; - - tp->offset = offset; - start = (unsigned char *)(blob + offset); - fp = fopen(tp->aml_name, "r"); - if (fp) { - fread(start, 1, tp->file_size, fp); - fclose(fp); - } -} - -void write_blob(char *dir, char *fname, unsigned char *blob, int size) -{ - FILE *fp; - char newname[MAX_LINE]; - - memset(newname, 0, MAX_LINE); - strcpy(newname, dir); - strcat(newname, "/"); - strcat(newname, fname); - - fp = fopen(newname, "w+"); - if (fp) { - fwrite(blob, 1, size, fp); - fclose(fp); - } else { - printf("? could not open the blob file: %s\n", newname); - } -} - -void set_checksum(unsigned char *start, int len, uint8_t *cksum) -{ - uint8_t newsum, oldsum; - uint8_t *p; - - newsum = 0; - for (p = (uint8_t *)start; p < (uint8_t *)(start + len); p++) - newsum += *p; - - oldsum = *cksum; - newsum = (uint8_t)(newsum - oldsum); - - *cksum = (uint8_t)(0 - newsum); -} - -int add_table(unsigned char **blob, char *table_name, int offset, int reqd) -{ - struct table *p; - int new_offset; - int adjustment = 0; - - p = find_table(table_name); - new_offset = offset + p->file_size; - - /* - * Handle crossing of page boundaries to prevent problems - * on armv7 with small page sizes - */ - if ((new_offset / PAGE_SIZE) != (offset / PAGE_SIZE)) { - adjustment = PAGE_SIZE - (offset % PAGE_SIZE); - /* - * If this is the first page crossing remove the - * blob header from calculations - */ - if (!(offset / PAGE_SIZE)) - adjustment -= BLOB_HEADER_SIZE; - } - - if (p) { - *blob = realloc(*blob, offset + adjustment + p->file_size); - write_table(*blob, p, offset + adjustment); - p->offset = offset + adjustment; - } else { - if (reqd) { - printf("? %s table is required\n", table_name); - return 0; - } - } - - /* NB: ACPI table size cannot be zero -- there must be a header */ - return p->file_size + adjustment; -} - -void fixup_rsdp(unsigned char *blob, uint64_t paddr) -{ - /* We could use the 32-bit RSDT address but that has - * essentially been deprecated. Instead, use the 64-bit - * XSDT address though be sure to use little-endian values. - */ - const int RSDP_FIRST_CHECKSUM_BYTES = 20; - const int RSDP_FIRST_CHECKSUM_OFFSET = 8; - const int RSDP_SECOND_CHECKSUM_BYTES = 36; - const int RSDP_SECOND_CHECKSUM_OFFSET = 32; - const int RSDT_ADDR_OFFSET = 16; - const int XSDT_ADDR_OFFSET = 24; - - uint8_t *pcksum; - uint32_t *stmp; - uint64_t *ltmp; - struct table *rsdpp; - struct table *p; - - /* NB: there are no safety checks on the find_table() - * return value because if we've gotten this far and - * the RSDP doesn't exist, something else has gone - * seriously wrong far earlier. - */ - rsdpp = find_table("rsdp"); - stmp = (uint32_t *)(blob + rsdpp->offset + RSDT_ADDR_OFFSET); - ltmp = (uint64_t *)(blob + rsdpp->offset + XSDT_ADDR_OFFSET); - - p = find_table("xsdt"); - if (p) - *ltmp = p->offset + paddr; - else - *ltmp = (uint64_t)0; - - p = find_table("rsdt"); - if (p) - *stmp = p->offset + paddr; - else - *stmp = (uint64_t)0; - - /* always reset the checksum, even if it is seldom used */ - pcksum = (uint8_t *)(blob + rsdpp->offset + RSDP_FIRST_CHECKSUM_OFFSET); - set_checksum((unsigned char *)(blob + rsdpp->offset), - RSDP_FIRST_CHECKSUM_BYTES, pcksum); - - pcksum = (uint8_t *) - (blob + rsdpp->offset + RSDP_SECOND_CHECKSUM_OFFSET); - set_checksum((unsigned char *)(blob + rsdpp->offset), - RSDP_SECOND_CHECKSUM_BYTES, pcksum); -} - -void fixup_facp(unsigned char *blob, int *offset, uint64_t paddr, int facs64) -{ - const int DSDT_ADDR_OFFSET = 40; - const int FACP_CHECKSUM_OFFSET = 9; - const int FIRMWARE_CTRL_OFFSET = 36; - const int X_DSDT_ADDR_OFFSET = 140; - const int X_FIRMWARE_CTRL_OFFSET = 132; - - struct table *facpp; - struct table *p; - uint32_t *stmp; - uint64_t *ltmp; - uint8_t *pcksum; - - facpp = find_table("facp"); - - /* add in the DSDT and X_DSDT addresses */ - stmp = (uint32_t *)(blob + facpp->offset + DSDT_ADDR_OFFSET); - ltmp = (uint64_t *)(blob + facpp->offset + X_DSDT_ADDR_OFFSET); - p = find_table("dsdt"); - if (p) { - if (facs64) { - *stmp = (uint32_t)0; - *ltmp = (uint64_t)p->offset + paddr; - } else { - *stmp = (uint32_t)p->offset + paddr; - *ltmp = (uint64_t)0; - } - } else { - *stmp = (uint32_t)0; - *ltmp = (uint64_t)0; - return; - } - - /* add in the FIRMWARE_CTRL and X_FIRMWARE_CTRL addresses */ - stmp = (uint32_t *)(blob + facpp->offset + FIRMWARE_CTRL_OFFSET); - ltmp = (uint64_t *)(blob + facpp->offset + X_FIRMWARE_CTRL_OFFSET); - p = find_table("facs"); - if (p) { - if (facs64) { - *stmp = (uint32_t)0; - *ltmp = (uint64_t)p->offset + paddr; - } else { - *stmp = (uint32_t)p->offset + paddr; - *ltmp = (uint64_t)0; - } - } else { - *stmp = (uint32_t)0; - *ltmp = (uint64_t)0; - return; - } - - /* always reset the checksum, even if it is seldom used */ - pcksum = (uint8_t *)(blob + facpp->offset + FACP_CHECKSUM_OFFSET); - set_checksum((unsigned char *)(blob + facpp->offset), - facpp->file_size, pcksum); -} - -void fixup_xsdt(unsigned char **blob, int *offset, uint64_t paddr) -{ - const int FACP_ADDR_OFFSET = 36; - const int XSDT_CHECKSUM_OFFSET = 9; - const int XSDT_HEADER_SIZE = 36; - - struct table *xsdtp; - struct table *p; - uint64_t *tmp; - uint8_t *pcksum; - int delta; - int allowed; - - xsdtp = find_table("xsdt"); - tmp = (uint64_t *)(*blob + xsdtp->offset + FACP_ADDR_OFFSET); - allowed = (xsdtp->file_size - XSDT_HEADER_SIZE) / sizeof(uint64_t); - - /* first table must be FACP (aka FADT) */ - p = find_table("facp"); - if (p) - *tmp = p->offset + paddr; - else { - *tmp = (uint64_t)0; - return; - } - - /* any tables not already in use go here */ - allowed--; - tmp++; - LIST_FOREACH(p, &thead, tables) { - if (p->offset < 0) { - if ((unsigned long long)tmp < - (unsigned long long) - (xsdtp + xsdtp->file_size)) { - delta = add_table(blob, p->signature, - *offset, NOT_REQUIRED); - *offset += delta; - *tmp++ = p->offset + paddr; - allowed--; - if (allowed < 1) - break; - } - } - } - - /* always reset the checksum, even if it is seldom used */ - pcksum = (uint8_t *)(*blob + xsdtp->offset + XSDT_CHECKSUM_OFFSET); - set_checksum((unsigned char *)(*blob + xsdtp->offset), - xsdtp->file_size, pcksum); -} - -void build_aml(int q, char *dir, char *iasl_cmd, struct table *tp) -{ - char cmd[MAX_LINE]; - struct stat mbuf; - struct stat sbuf; - - if (!tp) - return; - - if ((stat(tp->aml_name, &mbuf) == 0) && - (stat(tp->asl_name, &sbuf) == 0)) { - if (mbuf.st_mtime > sbuf.st_mtime) - return; /* AML file is newer than ASL file */ - } - - strcpy(cmd, iasl_cmd); - strcat(cmd, " "); - strcat(cmd, tp->asl_name); - if (q) - strcat(cmd, " >/dev/null 2&1"); - - system(cmd); -} - int main(int argc, char *argv[]) { int err = 0; diff --git a/tools/mab/mab.h b/tools/mab/mab.h index 15fb441..64bfbee 100644 --- a/tools/mab/mab.h +++ b/tools/mab/mab.h @@ -13,85 +13,8 @@ * */
-#include <stdint.h> -#include <string.h> - -#include <sys/queue.h> - -#define BLOB_HEADER_SIZE 8 -#define BLOB_MAGIC "ACPI" -#define BLOB_MAGIC_SIZE 4 -#define MAX_LINE 1024 -#define NOT_REQUIRED 0 -#define REQUIRED 1 -#define SIG_LENGTH 4 - /* VERSION a.b.c = <public release>.<functionality changes>.<bug fixes> */ const char VERSION[] = { "0.28.1" }; const char PROGNAME[] = { "mab" };
-char *known_sigs[] = { - "apic", - "bert", - "cpep", - "dsdt", - "ecdt", - "einj", - "erst", - "facp", - "facs", - "fpdt", - "gtdt", - "hest", - "mcfg", - "mchi", - "mpst", - "msct", - "oem", - "pcct", - "pmtt", - "rasf", - "rsdp", - "slit", - "spmi", - "srat", - "ssdt", - "uefi", - "xsdt", - NULL -}; - -LIST_HEAD(table_head, table) thead; -struct table_head *theadp; - -struct table { - char *signature; /* an ACPI table name/signature */ - char *asl_name; /* ASL file name */ - char *aml_name; /* corresponding AML name */ - int file_size; /* aka table size */ - int offset; /* location in the blob */ - LIST_ENTRY(table) tables; -}; - -int add_table(unsigned char **blob, char *table_name, int offset, int reqd); -void build_aml(int q, char *dir, char *iasl_cmd, struct table *tp); -struct table *build_table_entry(char *dir, char *buf); -struct table *find_table(char *sig); -int get_file_size(char *fname); -int read_manifest(char *dir, char *fname); -void set_blob_header(unsigned char *blob, int blob_size); -void set_checksum(unsigned char *start, int len, uint8_t *cksum); -void write_blob(char *dir, char *fname, unsigned char *blob, int size); -void write_table(unsigned char *blob, struct table *tp, int offset); -void usage(void); -int valid_sig(char *sig); - -void fixup_facp(unsigned char *blob, int *offset, unsigned long paddr, - int facs64); -void fixup_rsdp(unsigned char *blob, unsigned long paddr); -void fixup_xsdt(unsigned char **blob, int *offset, unsigned long paddr); - -/* Currently a hack to avoid issues on 4k pages on armv7 */ -#define PAGE_SIZE 0x1000 - #endif
Similar to mab and cab, bfapei "Blob For APEI" create blob which can be passed to the kernel by special u-boot commands for debugging purposes. It enable testing of APEI without any h/w interaction. The idea is to set physical region aside so kernel could reference to it. Once blob is filling with appropriate value we can pretend registers, storage etc.
Currently bfapei is able to create blob to test tables like: o HEST - kernel need to trigger error, related error info is ready to read
root@localhost:~# echo 1 > /sys/kernel/debug/apei/einj/error_inject {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2 {1}[Hardware Error]: APEI generic hardware error status {1}[Hardware Error]: severity: 1, fatal {1}[Hardware Error]: section: 0, severity: 0, recoverable {1}[Hardware Error]: flags: 0x00 {1}[Hardware Error]: section_type: memory error
o BERT - kernel check list of errors (boot process) pointed from BERT, any errors with status flag set is printed out
[...] [Hardware Error]: Error record from previous boot: {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2 {1}[Hardware Error]: APEI generic hardware error status {1}[Hardware Error]: severity: 1, fatal {1}[Hardware Error]: section: 0, severity: 0, recoverable {1}[Hardware Error]: flags: 0x00 {1}[Hardware Error]: section_type: memory error [...]
O ERST - appropriate registers are set so when there is kernel panic ERST driver dump log to region reserved within the blob, once kernel back to life it can mount pstore file system and read logs (files) for more details
panic! [...] root@localhost:~# mount -t pstore - /sys/fs/pstore root@localhost:~# ll /sys/fs/pstore/ total 0 drwxr-xr-x 2 root root 0 Sep 5 15:19 ./ drwxr-xr-x 4 root root 0 Jan 1 1970 ../ -r--r--r-- 1 root root 29374 Sep 5 14:01 dmesg-erst-0
HOWTO: Add appropriate flag to make command: make PADDR=0x42010000 APEI=<einj|bert|erst> exynos5250-arndale.acpi
Signed-off-by: Tomasz Nowicki tomasz.nowicki@linaro.org --- Makefile | 14 ++- platforms/Makefile | 3 + tools/bfapei/Makefile | 11 ++ tools/bfapei/bfapei.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/bfapei/bfapei.h | 235 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 tools/bfapei/Makefile create mode 100644 tools/bfapei/bfapei.c create mode 100644 tools/bfapei/bfapei.h
diff --git a/Makefile b/Makefile index e897c69..076cce0 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,16 @@ MABDIR := tools/mab/ CABDIR := tools/cab/ +BFAPEI_DIR := tools/bfapei/ COMMON_DIR := tools/common/ PLATDIR := platforms/
-%.acpi : mab cab - make MAB=$(CURDIR)/$(MABDIR)/mab PADDR=$(PADDR) -C $(PLATDIR) $@ +ARGS := MAB=$(CURDIR)/$(MABDIR)/mab PADDR=$(PADDR) +ifdef APEI + ARGS += BFAPEI=$(CURDIR)/$(BFAPEI_DIR)/bfapei APEI=$(APEI) +endif + +%.acpi : mab cab bfapei + make $(ARGS) -C $(PLATDIR) $@
mab : FORCE make -C $(MABDIR) PROG=mab @@ -12,9 +18,13 @@ mab : FORCE cab : FORCE make -C $(CABDIR) PROG=cab
+bfapei : FORCE + make -C $(BFAPEI_DIR) PROG=bfapei + clean : make -C $(MABDIR) clean PROG=mab make -C $(CABDIR) clean PROG=cab + make -C $(BFAPEI_DIR) clean PROG=bfapei make -C $(COMMON_DIR) clean make -C $(PLATDIR) clean
diff --git a/platforms/Makefile b/platforms/Makefile index caff1c8..a94fbdb 100644 --- a/platforms/Makefile +++ b/platforms/Makefile @@ -4,6 +4,9 @@ endif
%.acpi : FORCE $(MAB) -d $@ $(PADDR_ARG) -i $(basename $@).manifest -o $@ +ifdef APEI + $(BFAPEI) -d $@ -i $(basename $@).manifest -t $(APEI) -o apei.acpi +endif
clean : -rm -f *.acpi/*.aml diff --git a/tools/bfapei/Makefile b/tools/bfapei/Makefile new file mode 100644 index 0000000..f12aace --- /dev/null +++ b/tools/bfapei/Makefile @@ -0,0 +1,11 @@ +CFLAGS := -g -Wall -I../common/include + +HEADERS = $(wildcard *.h) $(wildcard ../common/include/*.h) + +SOURCES = $(wildcard *.c) $(wildcard ../common/*.c) + +$(PROG) : $(patsubst %.c,%.o, $(SOURCES)) $(HEADERS) + $(CC) $(CFLAGS) $(patsubst %.c,%.o, $(SOURCES)) -o $@ + +clean : + -rm -f $(patsubst %.c,%.o, $(wildcard *.c)) $(PROG) *.acpi diff --git a/tools/bfapei/bfapei.c b/tools/bfapei/bfapei.c new file mode 100644 index 0000000..a410076 --- /dev/null +++ b/tools/bfapei/bfapei.c @@ -0,0 +1,271 @@ +/* + * bfapei.c: main program for the tool to make a Blob of APEI tables + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Tomasz Nowicki tomasz.nowicki@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#include <ctype.h> +#include <endian.h> +#include <errno.h> +#include <libgen.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/queue.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <build_aml.h> +#include <check_aml.h> + +#include "bfapei.h" + +/* + * Overview of blob for APEI testing + * + * +--------------------+ 0x0 base address, need to be obtained from HEST. + * | | + * | place for status | HEST and BERT reference to this region + * | block error info | during error servicing. + * | | + * +--------------------+ +0x100 + * | | + * | place for ERST | ERST driver reference to this region during + * | registers | persistent error handling. + * | | + * +--------------------+ +0x200 + * | | + * + * ~~~~~~~~~~~~~~~~~~~~~~~~ + * + * | | + * +--------------------+ +0x2000 + * | | + * | buffer for dmesg | kernel log is dumping here during panic + * | log | when there is a kernel oops or panic + * | | + * +--------------------+ +0x12000 + */ + +static void usage(void) { + printf("%s %s\n", PROGNAME, VERSION); + printf("usage: %s -d <dir> -o <blob> -i <manifest>\n", PROGNAME); + printf("-t [hest|bert|erst]\n"); + printf(" -d <dir> => directory of ASL files\n"); + printf(" -o <blob> => file name for resulting APEI blob\n"); + printf(" -i <manifest> => list of AML files needed\n"); + printf(" -t => blob type for APEI\n"); + printf(" -q => if given, supress output\n"); +} + +static uint64_t obtain_esb(char *homedir, char *manifest_name) +{ + int err, table_size, i, error_source_count; + struct acpi_hest_generic *generic; + struct acpi_table_hest *hest_hdr; + struct table *p; + char *blob; + FILE *fp; + + /* What tables can we handle with */ + err = read_manifest(homedir, manifest_name); + if (err) { + printf("? could not read manifest: %s\n", manifest_name); + return 0; + } + + /* HEST table would be candidate */ + p = find_table("hest"); + if (!p) { + printf("Not found hest table!\n"); + return 0; + } + + if (!p->aml_name) { + printf("No aml file created for %s table!\n", p->asl_name); + return 0; + } + + table_size = get_file_size(p->aml_name); + blob = (char *)malloc(table_size); + if (!blob) { + printf("Memory allocation error!\n"); + return 0; + } + + fp = fopen(p->aml_name, "r"); + if (!fp) { + printf("File %s can not be opened!\n", p->aml_name); + return 0; + } + table_size = fread(blob, 1, table_size, fp); + fclose(fp); + + /* How many error sources we should traverse looking for GHES ? */ + hest_hdr = (struct acpi_table_hest *)blob; + error_source_count = hest_hdr->error_source_count; + + blob = (char *)(hest_hdr + 1); + generic = (struct acpi_hest_generic *)blob; + for (i = 0; i < error_source_count; i++) { + if (generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR) + return generic->error_status_address.address; + } + + return 0; +} + +static int bfapei_hest(char **buf, int *size, uint64_t paddr, int status) +{ + struct acpi_hest_generic_status *block_ptr; + struct acpi_hest_generic_data *gdata; + struct cper_sec_mem_err *mem_err; + uint64_t *add_ptr; + int reqr_size = sizeof(uint64_t) + + sizeof(struct acpi_hest_generic_status) + + sizeof(struct acpi_hest_generic_data) + + sizeof (struct cper_sec_mem_err); + + if (*size < reqr_size) { + *buf = realloc(*buf, *size + reqr_size); + if (!(*buf)) { + printf("Error during memory allocation!\n"); + return BFAPEI_FAIL; + } + memset(*buf + *size, 0, reqr_size - *size); + *size += reqr_size; + } + + /* + * Fill in blob which will be parsed by GHES driver. + */ + + /* First point to generic error status block */ + add_ptr = (uint64_t *) *buf; + *add_ptr = paddr + sizeof(uint64_t); + + /* Fill in generic error status block */ + block_ptr = (struct acpi_hest_generic_status *) (++add_ptr); + block_ptr->block_status = status; + block_ptr->data_length = sizeof(struct acpi_hest_generic_data); + block_ptr->error_severity = GHES_SEV_CORRECTED; + + /* Fill in generic error data entry */ + gdata = (struct acpi_hest_generic_data *) (block_ptr + 1); + memcpy(gdata->section_type, (void *) &CPER_SEC_PLATFORM_MEM, + sizeof(uuid_le)); + gdata->error_data_length = sizeof(struct cper_sec_mem_err); + block_ptr->data_length += gdata->error_data_length; + + mem_err = (struct cper_sec_mem_err *) (gdata + 1); + /* Place for more specific err info */ + + return BFAPEI_OK; +} + +static int bfapei_erst(char **buf, int *size, uint64_t paddr) +{ + int reqr_size = 0x400; + + if (*size < reqr_size) { + *buf = realloc(*buf, *size + reqr_size); + if (!(*buf)) { + printf("Error during memory allocation!\n"); + return BFAPEI_FAIL; + } + memset(*buf + *size, 0, reqr_size - *size); + *size += reqr_size; + } + + /* + * Fill in ERST registers. + */ + WRITE_ERST_REG(*buf, ACPI_ERST_GET_COMMAND_STATUS, ERST_STATUS_SUCCESS); + WRITE_ERST_REG(*buf, ACPI_ERST_CHECK_BUSY_STATUS, 1); + + WRITE_ERST_REG(*buf, ACPI_ERST_GET_ERROR_RANGE, paddr + 0x2000); + WRITE_ERST_REG(*buf, ACPI_ERST_GET_ERROR_LENGTH, 0x10000); + WRITE_ERST_REG(*buf, ACPI_ERST_GET_ERROR_ATTRIBUTES, ERST_RANGE_SLOW); + + return BFAPEI_OK; +} + +int main(int argc, char *argv[]) { + char *homedir, *apei_blob_name, *manifest_name, *blob_type; + int opt, size = 0, quiet = 0; + uint64_t paddr; + char *buf = NULL;; + + while ((opt = getopt(argc, argv, "d:o:i:t:q")) != EOF) { + switch (opt) { + case 'd': + homedir = optarg; + break; + case 'o': + apei_blob_name = optarg; + break; + case 'i': + manifest_name = optarg; + break; + case 't': + blob_type = optarg; + break; + case 'q': + quiet = 1; + break; + default: + usage(); + return BFAPEI_FAIL; + } + } + + if ((argc > (optind + 1)) || (apei_blob_name == NULL) || + (homedir == NULL) || (manifest_name == NULL) || + (blob_type == NULL)) { + printf("Missing a parameter value\n"); + usage(); + return BFAPEI_FAIL; + } + + paddr = obtain_esb(homedir, manifest_name); + if (!paddr) { + printf("No Error Status Block address obtained !\n"); + return BFAPEI_FAIL; + } + + if (strncmp(blob_type, "hest", 4) == 0) { + if (bfapei_hest(&buf, &size, paddr, 0)) + return BFAPEI_FAIL; + } + + /* Set status flag so error will be visible for BERT driver */ + if (strncmp(blob_type, "bert", 4) == 0) { + if (bfapei_hest(&buf, &size, paddr, 1)) + return BFAPEI_FAIL; + } + + if (strncmp(blob_type, "erst", 4) == 0) { + if (bfapei_erst(&buf, &size, paddr)) + return BFAPEI_FAIL; + } + + /* Save buffer to specified file. */ + write_blob(homedir, apei_blob_name, buf, size); + + if (!quiet) { + printf("%s blob for %s APEI table testing created\n", apei_blob_name, blob_type); + printf("Physical address: 0x%llx\n", paddr); + } + + return BFAPEI_OK; +} diff --git a/tools/bfapei/bfapei.h b/tools/bfapei/bfapei.h new file mode 100644 index 0000000..63b08c5 --- /dev/null +++ b/tools/bfapei/bfapei.h @@ -0,0 +1,235 @@ +/* + * bfapei.h: tool to make a Blob For APEI testing + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Tomasz Nowicki tomasz.nowicki@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#ifndef _APEI_H +#define _APEI_H + +/* VERSION a.b.c = <public release>.<functionality changes>.<bug fixes> */ +const char VERSION[] = { "0.1.0" }; +const char PROGNAME[] = { "bfapei" }; + +#define ACPI_NAME_SIZE 4 +#define ACPI_OEM_ID_SIZE 6 +#define ACPI_OEM_TABLE_ID_SIZE 8 + +/* Generic ACPI table header */ + +struct acpi_table_header { + char signature[ACPI_NAME_SIZE]; /* ASCII table signature */ + uint32_t length; /* Length of table in bytes, including this header */ + uint8_t revision; /* ACPI Specification minor version number */ + uint8_t checksum; /* To make sum of entire table == 0 */ + char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ + uint32_t oem_revision; /* OEM revision number */ + char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */ + uint32_t asl_compiler_revision; /* ASL compiler version */ +}; + +/* HEST - Hardware Error Source Table */ + +struct acpi_table_hest { + struct acpi_table_header header; /* Common ACPI table header */ + uint32_t error_source_count; +}; + +/* HEST subtable header */ + +struct acpi_hest_header { + uint16_t type; + uint16_t source_id; +}; + +/* Values for Type field above for subtables */ + +enum acpi_hest_types { + ACPI_HEST_TYPE_IA32_CHECK = 0, + ACPI_HEST_TYPE_IA32_CORRECTED_CHECK = 1, + ACPI_HEST_TYPE_IA32_NMI = 2, + ACPI_HEST_TYPE_NOT_USED3 = 3, + ACPI_HEST_TYPE_NOT_USED4 = 4, + ACPI_HEST_TYPE_NOT_USED5 = 5, + ACPI_HEST_TYPE_AER_ROOT_PORT = 6, + ACPI_HEST_TYPE_AER_ENDPOINT = 7, + ACPI_HEST_TYPE_AER_BRIDGE = 8, + ACPI_HEST_TYPE_GENERIC_ERROR = 9, + ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ +}; + +/* GAS - Generic Address Structure */ +struct acpi_generic_address { + uint8_t space_id; /* Address space where struct or register exists */ + uint8_t bit_width; /* Size in bits of given register */ + uint8_t bit_offset; /* Bit offset within the register */ + uint8_t access_width; /* Minimum Access size (ACPI 3.0) */ + uint64_t address; /* 64-bit address of struct or register */ +} __attribute__ ((packed)); + +/* Hardware Error Notification */ + +struct acpi_hest_notify { + uint8_t type; + uint8_t length; + uint16_t config_write_enable; + uint32_t poll_interval; + uint32_t vector; + uint32_t polling_threshold_value; + uint32_t polling_threshold_window; + uint32_t error_threshold_value; + uint32_t error_threshold_window; +}; + +/* 9: Generic Hardware Error Source */ + +struct acpi_hest_generic { + struct acpi_hest_header header; + uint16_t related_source_id; + uint8_t reserved; + uint8_t enabled; + uint32_t records_to_preallocate; + uint32_t max_sections_per_record; + uint32_t max_raw_data_length; + struct acpi_generic_address error_status_address; + struct acpi_hest_notify notify; + uint32_t error_block_length; +}; + +enum { + GHES_SEV_NO = 0x0, + GHES_SEV_CORRECTED = 0x1, + GHES_SEV_RECOVERABLE = 0x2, + GHES_SEV_PANIC = 0x3, +}; + +/* Generic Error Status block */ + +struct acpi_hest_generic_status { + uint32_t block_status; + uint32_t raw_data_offset; + uint32_t raw_data_length; + uint32_t data_length; + uint32_t error_severity; +}; + +/* Generic Error Data entry */ + +struct acpi_hest_generic_data { + uint8_t section_type[16]; + uint32_t error_severity; + uint16_t revision; + uint8_t validation_bits; + uint8_t flags; + uint32_t error_data_length; + uint8_t fru_id[16]; + uint8_t fru_text[20]; +}; + +typedef struct { + uint8_t b[16]; +} uuid_le; + +#define UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ +((uuid_le) \ +{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + +/* Platform Memory */ +#define CPER_SEC_PLATFORM_MEM \ + UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \ + 0xED, 0x7C, 0x83, 0xB1) + +/* Memory Error Section */ +struct cper_sec_mem_err { + uint64_t validation_bits; + uint64_t error_status; + uint64_t physical_addr; + uint64_t physical_addr_mask; + uint16_t node; + uint16_t card; + uint16_t module; + uint16_t bank; + uint16_t device; + uint16_t row; + uint16_t column; + uint16_t bit_pos; + uint64_t requestor_id; + uint64_t responder_id; + uint64_t target_id; + uint8_t error_type; +} __attribute__ ((packed)); + +/* ERST Error Log Address Range atrributes */ +#define ERST_RANGE_RESERVED 0x0001 +#define ERST_RANGE_NVRAM 0x0002 +#define ERST_RANGE_SLOW 0x0004 + +/* ERST command status */ +#define ERST_STATUS_SUCCESS 0x0 +#define ERST_STATUS_NOT_ENOUGH_SPACE 0x1 +#define ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x2 +#define ERST_STATUS_FAILED 0x3 +#define ERST_STATUS_RECORD_STORE_EMPTY 0x4 +#define ERST_STATUS_RECORD_NOT_FOUND 0x5 + +#define MAX_LINE 1024 +#define BFAPEI_OK 0 +#define BFAPEI_FAIL 1 + +#define SIZE sizeof(uint64_t) + sizeof(struct acpi_hest_generic_status) + \ + sizeof(struct acpi_hest_generic_data) + \ + sizeof (struct cper_sec_mem_err) + +/* Values for Action field above */ + +enum acpi_erst_actions { + ACPI_ERST_BEGIN_WRITE = 0, + ACPI_ERST_BEGIN_READ = 1, + ACPI_ERST_BEGIN_CLEAR = 2, + ACPI_ERST_END = 3, + ACPI_ERST_SET_RECORD_OFFSET = 4, + ACPI_ERST_EXECUTE_OPERATION = 5, + ACPI_ERST_CHECK_BUSY_STATUS = 6, + ACPI_ERST_GET_COMMAND_STATUS = 7, + ACPI_ERST_GET_RECORD_ID = 8, + ACPI_ERST_SET_RECORD_ID = 9, + ACPI_ERST_GET_RECORD_COUNT = 10, + ACPI_ERST_BEGIN_DUMMY_WRIITE = 11, + ACPI_ERST_NOT_USED = 12, + ACPI_ERST_GET_ERROR_RANGE = 13, + ACPI_ERST_GET_ERROR_LENGTH = 14, + ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, + ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ +}; + +/* ERST generic registers offset */ +uint64_t erst_reg_map[] = { + [ACPI_ERST_CHECK_BUSY_STATUS] = 0x130, + [ACPI_ERST_GET_COMMAND_STATUS] = 0x138, + [ACPI_ERST_GET_ERROR_RANGE] = 0x168, + [ACPI_ERST_GET_ERROR_LENGTH] = 0x170, + [ACPI_ERST_GET_ERROR_ATTRIBUTES] = 0x178, +}; + +/* ERST macro helper */ +#define WRITE_LONG(blob, offset, value) { \ + uint64_t *add_ptr; \ + add_ptr = (uint64_t *) (blob + offset); \ + *add_ptr = value; \ +} + +#define WRITE_ERST_REG(blob, reg, value) \ + WRITE_LONG(blob, erst_reg_map[reg], value) + +#endif
Hi Tomasz, Today I see your a APEI test tool patch: https://lists.linaro.org/pipermail/linaro-acpi/2013-September/000706.html, and have a question, whether could you have a confirmation about it? thanks.
+static int bfapei_hest(char **buf, int *size, uint64_t paddr, int status) +{ + struct acpi_hest_generic_status *block_ptr; + struct acpi_hest_generic_data *gdata; + struct cper_sec_mem_err *mem_err; + uint64_t *add_ptr; + int reqr_size = sizeof(uint64_t) + + sizeof(struct acpi_hest_generic_status) + + sizeof(struct acpi_hest_generic_data) + + sizeof (struct cper_sec_mem_err); + + if (*size < reqr_size) { + *buf = realloc(*buf, *size + reqr_size); + if (!(*buf)) { + printf("Error during memory allocation!\n"); + return BFAPEI_FAIL; + } + memset(*buf + *size, 0, reqr_size - *size); + *size += reqr_size; + } + + /* + * Fill in blob which will be parsed by GHES driver. + */ + + /* First point to generic error status block */ + add_ptr = (uint64_t *) *buf; + *add_ptr = paddr + sizeof(uint64_t);
May be this here is not right, please confirm it, thank you. should the add_ptr's content is "paddr" instead of "paddr + sizeof(uint64_t)"?
*add_ptr = paddr;
+ + /* Fill in generic error status block */ + block_ptr = (struct acpi_hest_generic_status *) (++add_ptr); + block_ptr->block_status = status; + block_ptr->data_length = sizeof(struct acpi_hest_generic_data); + block_ptr->error_severity = GHES_SEV_CORRECTED; + + /* Fill in generic error data entry */ + gdata = (struct acpi_hest_generic_data *) (block_ptr + 1); + memcpy(gdata->section_type, (void *) &CPER_SEC_PLATFORM_MEM, + sizeof(uuid_le)); + gdata->error_data_length = sizeof(struct cper_sec_mem_err); + block_ptr->data_length += gdata->error_data_length; + + mem_err = (struct cper_sec_mem_err *) (gdata + 1); + /* Place for more specific err info */ + + return BFAPEI_OK; +} +
--- tools/bfapei/bfapei.h | 192 +---------------------------------- tools/common/include/acpi.h | 204 ++++++++++++++++++++++++++++++++++++++ tools/common/include/check_aml.h | 7 -- 3 files changed, 207 insertions(+), 196 deletions(-) create mode 100644 tools/common/include/acpi.h
diff --git a/tools/bfapei/bfapei.h b/tools/bfapei/bfapei.h index 63b08c5..16b6b3c 100644 --- a/tools/bfapei/bfapei.h +++ b/tools/bfapei/bfapei.h @@ -14,176 +14,12 @@ #ifndef _APEI_H #define _APEI_H
+#include <acpi.h> + /* VERSION a.b.c = <public release>.<functionality changes>.<bug fixes> */ -const char VERSION[] = { "0.1.0" }; +const char VERSION[] = { "0.1.1" }; const char PROGNAME[] = { "bfapei" };
-#define ACPI_NAME_SIZE 4 -#define ACPI_OEM_ID_SIZE 6 -#define ACPI_OEM_TABLE_ID_SIZE 8 - -/* Generic ACPI table header */ - -struct acpi_table_header { - char signature[ACPI_NAME_SIZE]; /* ASCII table signature */ - uint32_t length; /* Length of table in bytes, including this header */ - uint8_t revision; /* ACPI Specification minor version number */ - uint8_t checksum; /* To make sum of entire table == 0 */ - char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ - char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ - uint32_t oem_revision; /* OEM revision number */ - char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */ - uint32_t asl_compiler_revision; /* ASL compiler version */ -}; - -/* HEST - Hardware Error Source Table */ - -struct acpi_table_hest { - struct acpi_table_header header; /* Common ACPI table header */ - uint32_t error_source_count; -}; - -/* HEST subtable header */ - -struct acpi_hest_header { - uint16_t type; - uint16_t source_id; -}; - -/* Values for Type field above for subtables */ - -enum acpi_hest_types { - ACPI_HEST_TYPE_IA32_CHECK = 0, - ACPI_HEST_TYPE_IA32_CORRECTED_CHECK = 1, - ACPI_HEST_TYPE_IA32_NMI = 2, - ACPI_HEST_TYPE_NOT_USED3 = 3, - ACPI_HEST_TYPE_NOT_USED4 = 4, - ACPI_HEST_TYPE_NOT_USED5 = 5, - ACPI_HEST_TYPE_AER_ROOT_PORT = 6, - ACPI_HEST_TYPE_AER_ENDPOINT = 7, - ACPI_HEST_TYPE_AER_BRIDGE = 8, - ACPI_HEST_TYPE_GENERIC_ERROR = 9, - ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ -}; - -/* GAS - Generic Address Structure */ -struct acpi_generic_address { - uint8_t space_id; /* Address space where struct or register exists */ - uint8_t bit_width; /* Size in bits of given register */ - uint8_t bit_offset; /* Bit offset within the register */ - uint8_t access_width; /* Minimum Access size (ACPI 3.0) */ - uint64_t address; /* 64-bit address of struct or register */ -} __attribute__ ((packed)); - -/* Hardware Error Notification */ - -struct acpi_hest_notify { - uint8_t type; - uint8_t length; - uint16_t config_write_enable; - uint32_t poll_interval; - uint32_t vector; - uint32_t polling_threshold_value; - uint32_t polling_threshold_window; - uint32_t error_threshold_value; - uint32_t error_threshold_window; -}; - -/* 9: Generic Hardware Error Source */ - -struct acpi_hest_generic { - struct acpi_hest_header header; - uint16_t related_source_id; - uint8_t reserved; - uint8_t enabled; - uint32_t records_to_preallocate; - uint32_t max_sections_per_record; - uint32_t max_raw_data_length; - struct acpi_generic_address error_status_address; - struct acpi_hest_notify notify; - uint32_t error_block_length; -}; - -enum { - GHES_SEV_NO = 0x0, - GHES_SEV_CORRECTED = 0x1, - GHES_SEV_RECOVERABLE = 0x2, - GHES_SEV_PANIC = 0x3, -}; - -/* Generic Error Status block */ - -struct acpi_hest_generic_status { - uint32_t block_status; - uint32_t raw_data_offset; - uint32_t raw_data_length; - uint32_t data_length; - uint32_t error_severity; -}; - -/* Generic Error Data entry */ - -struct acpi_hest_generic_data { - uint8_t section_type[16]; - uint32_t error_severity; - uint16_t revision; - uint8_t validation_bits; - uint8_t flags; - uint32_t error_data_length; - uint8_t fru_id[16]; - uint8_t fru_text[20]; -}; - -typedef struct { - uint8_t b[16]; -} uuid_le; - -#define UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ -((uuid_le) \ -{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ - (b) & 0xff, ((b) >> 8) & 0xff, \ - (c) & 0xff, ((c) >> 8) & 0xff, \ - (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) - -/* Platform Memory */ -#define CPER_SEC_PLATFORM_MEM \ - UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \ - 0xED, 0x7C, 0x83, 0xB1) - -/* Memory Error Section */ -struct cper_sec_mem_err { - uint64_t validation_bits; - uint64_t error_status; - uint64_t physical_addr; - uint64_t physical_addr_mask; - uint16_t node; - uint16_t card; - uint16_t module; - uint16_t bank; - uint16_t device; - uint16_t row; - uint16_t column; - uint16_t bit_pos; - uint64_t requestor_id; - uint64_t responder_id; - uint64_t target_id; - uint8_t error_type; -} __attribute__ ((packed)); - -/* ERST Error Log Address Range atrributes */ -#define ERST_RANGE_RESERVED 0x0001 -#define ERST_RANGE_NVRAM 0x0002 -#define ERST_RANGE_SLOW 0x0004 - -/* ERST command status */ -#define ERST_STATUS_SUCCESS 0x0 -#define ERST_STATUS_NOT_ENOUGH_SPACE 0x1 -#define ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x2 -#define ERST_STATUS_FAILED 0x3 -#define ERST_STATUS_RECORD_STORE_EMPTY 0x4 -#define ERST_STATUS_RECORD_NOT_FOUND 0x5 - -#define MAX_LINE 1024 #define BFAPEI_OK 0 #define BFAPEI_FAIL 1
@@ -191,28 +27,6 @@ struct cper_sec_mem_err { sizeof(struct acpi_hest_generic_data) + \ sizeof (struct cper_sec_mem_err)
-/* Values for Action field above */ - -enum acpi_erst_actions { - ACPI_ERST_BEGIN_WRITE = 0, - ACPI_ERST_BEGIN_READ = 1, - ACPI_ERST_BEGIN_CLEAR = 2, - ACPI_ERST_END = 3, - ACPI_ERST_SET_RECORD_OFFSET = 4, - ACPI_ERST_EXECUTE_OPERATION = 5, - ACPI_ERST_CHECK_BUSY_STATUS = 6, - ACPI_ERST_GET_COMMAND_STATUS = 7, - ACPI_ERST_GET_RECORD_ID = 8, - ACPI_ERST_SET_RECORD_ID = 9, - ACPI_ERST_GET_RECORD_COUNT = 10, - ACPI_ERST_BEGIN_DUMMY_WRIITE = 11, - ACPI_ERST_NOT_USED = 12, - ACPI_ERST_GET_ERROR_RANGE = 13, - ACPI_ERST_GET_ERROR_LENGTH = 14, - ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, - ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ -}; - /* ERST generic registers offset */ uint64_t erst_reg_map[] = { [ACPI_ERST_CHECK_BUSY_STATUS] = 0x130, diff --git a/tools/common/include/acpi.h b/tools/common/include/acpi.h new file mode 100644 index 0000000..c9380de --- /dev/null +++ b/tools/common/include/acpi.h @@ -0,0 +1,204 @@ +/* + * acpi.h: ACPI table headers, defines, etc. + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (c) 2013, Tomasz Nowicki tomasz.nowicki@linaro.org + * + * NB: all values are assumed to be little-endian in the blob. + * + */ + +#ifndef ACPI_H_ +#define ACPI_H_ + +#define ACPI_NAME_SIZE 4 +#define ACPI_OEM_ID_SIZE 6 +#define ACPI_OEM_TABLE_ID_SIZE 8 + +/* Generic ACPI table header */ + +struct acpi_table_header { + char signature[ACPI_NAME_SIZE]; /* ASCII table signature */ + uint32_t length; /* Length of table in bytes, including this header */ + uint8_t revision; /* ACPI Specification minor version number */ + uint8_t checksum; /* To make sum of entire table == 0 */ + char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ + uint32_t oem_revision; /* OEM revision number */ + char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */ + uint32_t asl_compiler_revision; /* ASL compiler version */ +}; + +/* HEST - Hardware Error Source Table */ + +struct acpi_table_hest { + struct acpi_table_header header; /* Common ACPI table header */ + uint32_t error_source_count; +}; + +/* HEST subtable header */ + +struct acpi_hest_header { + uint16_t type; + uint16_t source_id; +}; + +/* Values for Type field above for subtables */ + +enum acpi_hest_types { + ACPI_HEST_TYPE_IA32_CHECK = 0, + ACPI_HEST_TYPE_IA32_CORRECTED_CHECK = 1, + ACPI_HEST_TYPE_IA32_NMI = 2, + ACPI_HEST_TYPE_NOT_USED3 = 3, + ACPI_HEST_TYPE_NOT_USED4 = 4, + ACPI_HEST_TYPE_NOT_USED5 = 5, + ACPI_HEST_TYPE_AER_ROOT_PORT = 6, + ACPI_HEST_TYPE_AER_ENDPOINT = 7, + ACPI_HEST_TYPE_AER_BRIDGE = 8, + ACPI_HEST_TYPE_GENERIC_ERROR = 9, + ACPI_HEST_TYPE_RESERVED = 10 /* 10 and greater are reserved */ +}; + +/* GAS - Generic Address Structure */ +struct acpi_generic_address { + uint8_t space_id; /* Address space where struct or register exists */ + uint8_t bit_width; /* Size in bits of given register */ + uint8_t bit_offset; /* Bit offset within the register */ + uint8_t access_width; /* Minimum Access size (ACPI 3.0) */ + uint64_t address; /* 64-bit address of struct or register */ +} __attribute__ ((packed)); + +/* Hardware Error Notification */ + +struct acpi_hest_notify { + uint8_t type; + uint8_t length; + uint16_t config_write_enable; + uint32_t poll_interval; + uint32_t vector; + uint32_t polling_threshold_value; + uint32_t polling_threshold_window; + uint32_t error_threshold_value; + uint32_t error_threshold_window; +}; + +/* 9: Generic Hardware Error Source */ + +struct acpi_hest_generic { + struct acpi_hest_header header; + uint16_t related_source_id; + uint8_t reserved; + uint8_t enabled; + uint32_t records_to_preallocate; + uint32_t max_sections_per_record; + uint32_t max_raw_data_length; + struct acpi_generic_address error_status_address; + struct acpi_hest_notify notify; + uint32_t error_block_length; +}; + +enum { + GHES_SEV_NO = 0x0, + GHES_SEV_CORRECTED = 0x1, + GHES_SEV_RECOVERABLE = 0x2, + GHES_SEV_PANIC = 0x3, +}; + +/* Generic Error Status block */ + +struct acpi_hest_generic_status { + uint32_t block_status; + uint32_t raw_data_offset; + uint32_t raw_data_length; + uint32_t data_length; + uint32_t error_severity; +}; + +/* Generic Error Data entry */ + +struct acpi_hest_generic_data { + uint8_t section_type[16]; + uint32_t error_severity; + uint16_t revision; + uint8_t validation_bits; + uint8_t flags; + uint32_t error_data_length; + uint8_t fru_id[16]; + uint8_t fru_text[20]; +}; + +typedef struct { + uint8_t b[16]; +} uuid_le; + +#define UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ +((uuid_le) \ +{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + +/* Platform Memory */ +#define CPER_SEC_PLATFORM_MEM \ + UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \ + 0xED, 0x7C, 0x83, 0xB1) + +/* Memory Error Section */ +struct cper_sec_mem_err { + uint64_t validation_bits; + uint64_t error_status; + uint64_t physical_addr; + uint64_t physical_addr_mask; + uint16_t node; + uint16_t card; + uint16_t module; + uint16_t bank; + uint16_t device; + uint16_t row; + uint16_t column; + uint16_t bit_pos; + uint64_t requestor_id; + uint64_t responder_id; + uint64_t target_id; + uint8_t error_type; +} __attribute__ ((packed)); + +/* ERST Error Log Address Range atrributes */ +#define ERST_RANGE_RESERVED 0x0001 +#define ERST_RANGE_NVRAM 0x0002 +#define ERST_RANGE_SLOW 0x0004 + +/* ERST command status */ +#define ERST_STATUS_SUCCESS 0x0 +#define ERST_STATUS_NOT_ENOUGH_SPACE 0x1 +#define ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x2 +#define ERST_STATUS_FAILED 0x3 +#define ERST_STATUS_RECORD_STORE_EMPTY 0x4 +#define ERST_STATUS_RECORD_NOT_FOUND 0x5 + +/* Values for Action field above */ + +enum acpi_erst_actions { + ACPI_ERST_BEGIN_WRITE = 0, + ACPI_ERST_BEGIN_READ = 1, + ACPI_ERST_BEGIN_CLEAR = 2, + ACPI_ERST_END = 3, + ACPI_ERST_SET_RECORD_OFFSET = 4, + ACPI_ERST_EXECUTE_OPERATION = 5, + ACPI_ERST_CHECK_BUSY_STATUS = 6, + ACPI_ERST_GET_COMMAND_STATUS = 7, + ACPI_ERST_GET_RECORD_ID = 8, + ACPI_ERST_SET_RECORD_ID = 9, + ACPI_ERST_GET_RECORD_COUNT = 10, + ACPI_ERST_BEGIN_DUMMY_WRIITE = 11, + ACPI_ERST_NOT_USED = 12, + ACPI_ERST_GET_ERROR_RANGE = 13, + ACPI_ERST_GET_ERROR_LENGTH = 14, + ACPI_ERST_GET_ERROR_ATTRIBUTES = 15, + ACPI_ERST_ACTION_RESERVED = 16 /* 16 and greater are reserved */ +}; + +#endif /* ACPI_H_ */ diff --git a/tools/common/include/check_aml.h b/tools/common/include/check_aml.h index 69e4ae8..d44d68b 100644 --- a/tools/common/include/check_aml.h +++ b/tools/common/include/check_aml.h @@ -34,15 +34,8 @@ #define FAIL 0 #define INFO (-1)
-#define BLOB_HEADER_SIZE 8 -#define BLOB_MAGIC "ACPI" -#define BLOB_MAGIC_SIZE 4 -#define MAX_LINE 1024 #define MIN_TABLE_LENGTH 36 -#define NOT_REQUIRED 0 -#define REQUIRED 1 #define RSDP_LEN_OFFSET 20 -#define SIG_LENGTH 4 #define TABLE_LEN_OFFSET 4
#define SIG_APIC "APIC"
Signed-off-by: Tomasz Nowicki tomasz.nowicki@linaro.org --- tools/bfapei/bfapei.c | 4 ++-- tools/cab/cab.c | 8 +++++--- tools/common/build_aml.c | 2 +- tools/common/check_aml.c | 10 +++++----- tools/common/include/build_aml.h | 2 +- tools/common/include/check_aml.h | 2 +- tools/mab/mab.c | 7 ++++--- 7 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/tools/bfapei/bfapei.c b/tools/bfapei/bfapei.c index a410076..7b347e9 100644 --- a/tools/bfapei/bfapei.c +++ b/tools/bfapei/bfapei.c @@ -260,11 +260,11 @@ int main(int argc, char *argv[]) { }
/* Save buffer to specified file. */ - write_blob(homedir, apei_blob_name, buf, size); + write_blob(homedir, apei_blob_name, (unsigned char *)buf, size);
if (!quiet) { printf("%s blob for %s APEI table testing created\n", apei_blob_name, blob_type); - printf("Physical address: 0x%llx\n", paddr); + printf("Physical address: 0x%llx\n", (long long unsigned int)paddr); }
return BFAPEI_OK; diff --git a/tools/cab/cab.c b/tools/cab/cab.c index 481c021..1eb5649 100644 --- a/tools/cab/cab.c +++ b/tools/cab/cab.c @@ -78,7 +78,8 @@ int main(int argc, char *argv[]) printf("invalid physical address given\n"); return 1; } else { - printf("assume blob was relocated to 0x%llx\n", paddr); + printf("assume blob was relocated to 0x%llx\n", + (long long unsigned int)paddr); } } else { printf("? missing required physical address parameter\n"); @@ -114,8 +115,9 @@ int main(int argc, char *argv[]) ii = 0; LIST_FOREACH(np, &thead, tables) { printf( - "[%03d] %4s: %d bytes @ 0x%08x, loads @ 0x%016x\n", - ii, np->signature, np->len, np->offset, np->paddr); + "[%03d] %4s: %d bytes @ 0x%08x, loads @ 0x%016llx\n", + ii, np->signature, np->len, np->offset, + (long long unsigned int)np->paddr); ii++; } } diff --git a/tools/common/build_aml.c b/tools/common/build_aml.c index ebfcdc4..34cdfe4 100644 --- a/tools/common/build_aml.c +++ b/tools/common/build_aml.c @@ -89,7 +89,7 @@ struct table *build_table_entry(char *dir, char *buf) break; sig[n++] = buf[ii]; } - if (!valid_sig((unsigned char*)sig)) { + if (!valid_sig(sig)) { free(tmp); return NULL; } diff --git a/tools/common/check_aml.c b/tools/common/check_aml.c index ac47aa6..9e5b0c2 100644 --- a/tools/common/check_aml.c +++ b/tools/common/check_aml.c @@ -1,5 +1,5 @@ /* - * cab.c: helper functions for the tool to Check A Blob of ACPI tables + * check_aml.c: helper functions for the tool to Check A Blob of ACPI tables * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this @@ -238,7 +238,7 @@ void find_all_tables(unsigned char *blob, int size, int base_addr) offset = (int)(p - blob);
while (offset + SIG_LENGTH < size) { - if (valid_sig(p)) { + if (valid_sig((char *)p)) { tp = check_table_entry(p); if (tp) { delta = TABLE_LEN_OFFSET; @@ -260,7 +260,7 @@ void find_all_tables(unsigned char *blob, int size, int base_addr) while (offset + SIG_LENGTH < size) { p++; offset++; - if (isalpha(*p) && valid_sig(p)) + if (isalpha(*p) && valid_sig((char *)p)) break; } } @@ -342,7 +342,7 @@ void check_xsdt_relocs(unsigned char *blob, int size, uint64_t paddr) for (ii = 0; ii < cnt; ii++, tpaddr++) { offset = (*tpaddr - paddr); res = FAIL; - if (valid_sig((unsigned char *)blob + offset)) { + if (valid_sig((char *)blob + offset)) { xp = find_table((char *)blob + offset); if (xp) { xp->ref_cnt++; @@ -505,7 +505,7 @@ int check_print_summary(void) printf("\nTotal tests: %d\n", passed + failed); printf("Passed: %d\n", passed); printf("Failed: %d\n", failed); - printf("Success rate: %0.1f%\n", + printf("Success rate: %0.1f%%\n", (100.0 * (float)passed) / (float)(passed + failed));
return failed; diff --git a/tools/common/include/build_aml.h b/tools/common/include/build_aml.h index 91334d7..ab86b78 100644 --- a/tools/common/include/build_aml.h +++ b/tools/common/include/build_aml.h @@ -1,5 +1,5 @@ /* - * mab.h: tool to Make A Blob of ACPI tables + * build_aml.h: helper functions for the tool to Make A Blob of ACPI tables * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this diff --git a/tools/common/include/check_aml.h b/tools/common/include/check_aml.h index d44d68b..59e0c23 100644 --- a/tools/common/include/check_aml.h +++ b/tools/common/include/check_aml.h @@ -1,5 +1,5 @@ /* - * cab.h: tool to Check A Blob of ACPI tables + * check_aml.h: helper functions for the tool to Check A Blob of ACPI tables * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this diff --git a/tools/mab/mab.c b/tools/mab/mab.c index 060ba72..cc99cb6 100644 --- a/tools/mab/mab.c +++ b/tools/mab/mab.c @@ -112,7 +112,8 @@ int main(int argc, char *argv[]) printf("invalid physical address given\n"); return 1; } else { - printf("relocating blob to 0x%llx\n", paddr); + printf("relocating blob to 0x%llx\n", + (long long unsigned int)paddr); } } else { printf("? missing required physical address parameter\n"); @@ -193,9 +194,9 @@ int main(int argc, char *argv[]) LIST_FOREACH(np, &thead, tables) { printf("[%03d] %4s : %s\n", ii, np->signature, basename(np->aml_name)); - printf(" %d bytes @ 0x%016x, reloc @ 0x%016x\n", + printf(" %d bytes @ 0x%016x, reloc @ 0x%016llx\n", np->file_size, np->offset, - np->offset + paddr); + (long long unsigned int)np->offset + paddr); ii++; } }
On 09/09/2013 03:35 AM, Tomasz Nowicki wrote:
Patch set implement as follows:
- Minor changes around existing tools
- reorganize building process,
- move common code to separate direction,
- no functionality changes.
- Add BFAPEI (Blob For APEI) tool which can create blobs for APEI testing.
- see commit log for more details
Changes for v2:
- compilation regardless of whether APEI is used or not,
- correct file name in comment headers,
- move ACPI structures, defines, etc. to acpi.h headers,
- suppress compiler warnings.
Tomasz Nowicki (4): map, cab: Reorganize building process and tree hierarchy. bfapei: Add tool that can create blobs for APEI table testing. bfapei: Move generic ACPI structures to separated file, remove duplicated defines. Suppress compiler warnings, file comment headers cleanup.
Makefile | 28 +- platforms/Makefile | 9 +- tools/bfapei/Makefile | 11 + tools/bfapei/bfapei.c | 271 +++++++++++++++++++ tools/bfapei/bfapei.h | 49 ++++ tools/cab/Makefile | 12 +- tools/cab/cab.c | 535 +------------------------------------- tools/cab/cab.h | 149 ----------- tools/common/Makefile | 4 + tools/common/build_aml.c | 455 ++++++++++++++++++++++++++++++++ tools/common/check_aml.c | 512 ++++++++++++++++++++++++++++++++++++ tools/common/include/acpi.h | 204 +++++++++++++++ tools/common/include/build_aml.h | 74 ++++++ tools/common/include/check_aml.h | 92 +++++++ tools/mab/Makefile | 13 +- tools/mab/mab.c | 437 +------------------------------ tools/mab/mab.h | 77 ------ 17 files changed, 1734 insertions(+), 1198 deletions(-) create mode 100644 tools/bfapei/Makefile create mode 100644 tools/bfapei/bfapei.c create mode 100644 tools/bfapei/bfapei.h create mode 100644 tools/common/Makefile create mode 100644 tools/common/build_aml.c create mode 100644 tools/common/check_aml.c create mode 100644 tools/common/include/acpi.h create mode 100644 tools/common/include/build_aml.h create mode 100644 tools/common/include/check_aml.h
Good stuff. One minor compilation warning:
make[1]: Entering directory `/srv/figaro/acpi-asl/tools/bfapei' cc -g -Wall -I../common/include -c -o bfapei.o bfapei.c bfapei.c: In function ‘bfapei_hest’: bfapei.c:132:27: warning: variable ‘mem_err’ set but not used [-Wunused-but-set-variable] struct cper_sec_mem_err *mem_err; ^
Other than that:
Acked-by: Al Stone al.stone@linaro.org
Hi Al,
W dniu 09.09.2013 22:33, Al Stone pisze:
On 09/09/2013 03:35 AM, Tomasz Nowicki wrote:
Patch set implement as follows:
- Minor changes around existing tools
- reorganize building process,
- move common code to separate direction,
- no functionality changes.
- Add BFAPEI (Blob For APEI) tool which can create blobs for APEI
testing. - see commit log for more details
Changes for v2: - compilation regardless of whether APEI is used or not, - correct file name in comment headers, - move ACPI structures, defines, etc. to acpi.h headers, - suppress compiler warnings.
Tomasz Nowicki (4): map, cab: Reorganize building process and tree hierarchy. bfapei: Add tool that can create blobs for APEI table testing. bfapei: Move generic ACPI structures to separated file, remove duplicated defines. Suppress compiler warnings, file comment headers cleanup.
Makefile | 28 +- platforms/Makefile | 9 +- tools/bfapei/Makefile | 11 + tools/bfapei/bfapei.c | 271 +++++++++++++++++++ tools/bfapei/bfapei.h | 49 ++++ tools/cab/Makefile | 12 +- tools/cab/cab.c | 535 +------------------------------------- tools/cab/cab.h | 149 ----------- tools/common/Makefile | 4 + tools/common/build_aml.c | 455 ++++++++++++++++++++++++++++++++ tools/common/check_aml.c | 512 ++++++++++++++++++++++++++++++++++++ tools/common/include/acpi.h | 204 +++++++++++++++ tools/common/include/build_aml.h | 74 ++++++ tools/common/include/check_aml.h | 92 +++++++ tools/mab/Makefile | 13 +- tools/mab/mab.c | 437 +------------------------------ tools/mab/mab.h | 77 ------ 17 files changed, 1734 insertions(+), 1198 deletions(-) create mode 100644 tools/bfapei/Makefile create mode 100644 tools/bfapei/bfapei.c create mode 100644 tools/bfapei/bfapei.h create mode 100644 tools/common/Makefile create mode 100644 tools/common/build_aml.c create mode 100644 tools/common/check_aml.c create mode 100644 tools/common/include/acpi.h create mode 100644 tools/common/include/build_aml.h create mode 100644 tools/common/include/check_aml.h
Good stuff. One minor compilation warning:
make[1]: Entering directory `/srv/figaro/acpi-asl/tools/bfapei' cc -g -Wall -I../common/include -c -o bfapei.o bfapei.c bfapei.c: In function ‘bfapei_hest’: bfapei.c:132:27: warning: variable ‘mem_err’ set but not used [-Wunused-but-set-variable] struct cper_sec_mem_err *mem_err; ^
I left "mem_err" pointer unused only for eventual more specific info regarding memory error type. It's conscious decision :).
Thanks for review!
Tomasz