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