Message ID | 1386879568-31608-1-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
On 12/13/2013 04:19 AM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > During work on an early development machine we found a situation where > the RSDP could not be automatically probed using the current methods. > So, allow the RSDP to be specified either manually using the new -R or > --rsdp options or found by scanning the kernel log (ugly, but is our > final easy option). > > We should also sanity check the RDSP by ensuring it lies on a 16 byte > boundary and contains a valid signature. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > doc/fwts.1 | 4 +++ > src/lib/include/fwts_framework.h | 1 + > src/lib/src/fwts_acpi_tables.c | 64 +++++++++++++++++++++++++++++++++------- > src/lib/src/fwts_framework.c | 7 +++++ > 4 files changed, 66 insertions(+), 10 deletions(-) > > diff --git a/doc/fwts.1 b/doc/fwts.1 > index 234278d..a12aca9 100644 > --- a/doc/fwts.1 > +++ b/doc/fwts.1 > @@ -201,6 +201,10 @@ no pretty printing of horizontal separators in the results log file. > specify the results output log file. > One can also specify stdout and stderr to redirect to these output streams. > .TP > +.B \-R, \-\-rsdp=physaddr > +specify the physical address of ACPI RSDP. This is useful on some systems where > +it cannot be automatically detected. > +.TP > .B \-\-s3\-delay\-delta=N > time to be added onto delay between each S3 iteration. > .TP > diff --git a/src/lib/include/fwts_framework.h b/src/lib/include/fwts_framework.h > index f365d74..1e5171c 100644 > --- a/src/lib/include/fwts_framework.h > +++ b/src/lib/include/fwts_framework.h > @@ -144,6 +144,7 @@ typedef struct { > fwts_list errors_filter_discard; /* Results to discard, empty = discard none */ > bool error_filtered_out; /* True if a klog message has been filtered out */ > fwts_acpica_mode acpica_mode; /* ACPICA mode flags */ > + void *rsdp; /* ACPI RSDP address */ > } fwts_framework; > > typedef struct { > diff --git a/src/lib/src/fwts_acpi_tables.c b/src/lib/src/fwts_acpi_tables.c > index 6f1e964..f9f6ba0 100644 > --- a/src/lib/src/fwts_acpi_tables.c > +++ b/src/lib/src/fwts_acpi_tables.c > @@ -52,6 +52,34 @@ static void *fwts_acpi_find_rsdp_efi(void) > } > > /* > + * fwts_acpi_find_rsdp_klog() > + * Get RSDP by parsing kernel log > + */ > +static void *fwts_acpi_find_rsdp_klog(void) > +{ > + fwts_list *klog; > + fwts_list_link *item; > + void *rsdp = NULL; > + > + if ((klog = fwts_klog_read()) == NULL) > + return NULL; > + > + fwts_list_foreach(item, klog) { > + char *text = fwts_text_list_text(item); > + char *ptr = strstr(text, "ACPI: RSDP"); > + > + if (ptr) { > + rsdp = (void *)strtoul(ptr + 11, NULL, 16); > + break; > + } > + } > + > + fwts_text_list_free(klog); > + > + return rsdp; > +} > + > +/* > * fwts_acpi_find_rsdp_bios() > * Find RSDP address by scanning BIOS memory > */ > @@ -94,21 +122,26 @@ static void *fwts_acpi_find_rsdp_bios(void) > static fwts_acpi_table_rsdp *fwts_acpi_get_rsdp(void *addr, size_t *rsdp_len) > { > uint8_t *mem; > - fwts_acpi_table_rsdp *rsdp; > + fwts_acpi_table_rsdp *rsdp = NULL; > *rsdp_len = 0; > > if ((mem = fwts_mmap((off_t)addr, sizeof(fwts_acpi_table_rsdp))) == FWTS_MAP_FAILED) > return NULL; > > - /* Determine original RSDP size from revision. */ > rsdp = (fwts_acpi_table_rsdp*)mem; > + /* Determine original RSDP size from revision. */ > *rsdp_len = (rsdp->revision < 1) ? 20 : 36; > > + /* Must have the correct signature */ > + if (strncmp(rsdp->signature, "RSD PTR ", 8)) > + goto out; > + > /* Assume version 2.0 size, we don't care about a few bytes over allocation if it's version 1.0 */ > if ((rsdp = (fwts_acpi_table_rsdp*)fwts_low_calloc(1, sizeof(fwts_acpi_table_rsdp))) == NULL) > - return NULL; > + goto out; > > memcpy(rsdp, mem, *rsdp_len); > +out: > (void)fwts_munmap(mem, sizeof(fwts_acpi_table_rsdp)); > > return rsdp; > @@ -238,22 +271,33 @@ static void fwts_acpi_handle_fadt(fwts_acpi_table_fadt *fadt, fwts_acpi_table_pr > * fwts_acpi_load_tables_from_firmware() > * Load up cached copies of all the ACPI tables > */ > -static int fwts_acpi_load_tables_from_firmware(void) > +static int fwts_acpi_load_tables_from_firmware(fwts_framework *fw) > { > fwts_acpi_table_rsdp *rsdp; > fwts_acpi_table_xsdt *xsdt; > fwts_acpi_table_rsdt *rsdt; > fwts_acpi_table_header *header; > > - void * rsdp_addr; > + void * rsdp_addr = NULL; > size_t rsdp_len; > int num_entries; > int i; > > - /* Check for RSDP in EFI, then BIOS, if not found, give up */ > - if ((rsdp_addr = fwts_acpi_find_rsdp_efi()) == NULL) > - if ((rsdp_addr = fwts_acpi_find_rsdp_bios()) == NULL) > - return FWTS_ERROR; > + /* Check for RSDP as EFI, then BIOS, parsed klog, if not found, give up */ > + if (fw->rsdp) > + rsdp_addr = (void*)fw->rsdp; > + if (!rsdp_addr) > + rsdp_addr = fwts_acpi_find_rsdp_efi(); > + if (!rsdp_addr) > + rsdp_addr = fwts_acpi_find_rsdp_bios(); > + if (!rsdp_addr) > + rsdp_addr = fwts_acpi_find_rsdp_klog(); > + if (!rsdp_addr) > + return FWTS_ERROR; > + > + /* Must be on a 16 byte boundary */ > + if (((unsigned long)rsdp_addr & 0xf)) > + return FWTS_ERROR; > > /* Load and save cached RSDP */ > if ((rsdp = fwts_acpi_get_rsdp(rsdp_addr, &rsdp_len)) == NULL) > @@ -712,7 +756,7 @@ int fwts_acpi_load_tables(fwts_framework *fw) > else if (fw->acpi_table_acpidump_file != NULL) > ret = fwts_acpi_load_tables_from_acpidump(fw); > else if (fwts_check_root_euid(fw, true) == FWTS_OK) > - ret = fwts_acpi_load_tables_from_firmware(); > + ret = fwts_acpi_load_tables_from_firmware(fw); > else > ret = FWTS_ERROR_NO_PRIV; > > diff --git a/src/lib/src/fwts_framework.c b/src/lib/src/fwts_framework.c > index eae5907..92aa74d 100644 > --- a/src/lib/src/fwts_framework.c > +++ b/src/lib/src/fwts_framework.c > @@ -83,6 +83,7 @@ static fwts_option fwts_framework_options[] = { > { "acpica-debug", "", 0, "Enable ACPICA debug/warning messages." }, > { "acpica", "", 1, "Enable ACPICA run time options." }, > { "uefi", "", 0, "Run UEFI tests." }, > + { "rsdp", "R:", 1, "Specify the physical address of the ACPI RSDP." }, > { NULL, NULL, 0, NULL } > }; > > @@ -1138,6 +1139,9 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar > case 38: /* --uefi */ > fw->flags |= FWTS_FLAG_TEST_UEFI; > break; > + case 39: /* --rsdp */ > + fw->rsdp = (void *)strtoul(optarg, NULL, 0); > + break; > } > break; > case 'a': /* --all */ > @@ -1214,6 +1218,9 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar > case 'w': /* --log-width=N */ > fwts_log_set_line_width(atoi(optarg)); > break; > + case 'R': /* --rsdp=addr */ > + fw->rsdp = (void *)strtoul(optarg, NULL, 0); > + break; > } > return FWTS_OK; > } > Acked-by: Ivan Hu <ivan.hu@canonical.com>
On Mon, Dec 16, 2013 at 11:29 AM, IvanHu <ivan.hu@canonical.com> wrote: > On 12/13/2013 04:19 AM, Colin King wrote: >> >> From: Colin Ian King <colin.king@canonical.com> >> >> During work on an early development machine we found a situation where >> the RSDP could not be automatically probed using the current methods. >> So, allow the RSDP to be specified either manually using the new -R or >> --rsdp options or found by scanning the kernel log (ugly, but is our >> final easy option). >> >> We should also sanity check the RDSP by ensuring it lies on a 16 byte >> boundary and contains a valid signature. >> >> Signed-off-by: Colin Ian King <colin.king@canonical.com> >> --- >> doc/fwts.1 | 4 +++ >> src/lib/include/fwts_framework.h | 1 + >> src/lib/src/fwts_acpi_tables.c | 64 >> +++++++++++++++++++++++++++++++++------- >> src/lib/src/fwts_framework.c | 7 +++++ >> 4 files changed, 66 insertions(+), 10 deletions(-) >> >> diff --git a/doc/fwts.1 b/doc/fwts.1 >> index 234278d..a12aca9 100644 >> --- a/doc/fwts.1 >> +++ b/doc/fwts.1 >> @@ -201,6 +201,10 @@ no pretty printing of horizontal separators in the >> results log file. >> specify the results output log file. >> One can also specify stdout and stderr to redirect to these output >> streams. >> .TP >> +.B \-R, \-\-rsdp=physaddr >> +specify the physical address of ACPI RSDP. This is useful on some systems >> where >> +it cannot be automatically detected. >> +.TP >> .B \-\-s3\-delay\-delta=N >> time to be added onto delay between each S3 iteration. >> .TP >> diff --git a/src/lib/include/fwts_framework.h >> b/src/lib/include/fwts_framework.h >> index f365d74..1e5171c 100644 >> --- a/src/lib/include/fwts_framework.h >> +++ b/src/lib/include/fwts_framework.h >> @@ -144,6 +144,7 @@ typedef struct { >> fwts_list errors_filter_discard; /* Results to discard, >> empty = discard none */ >> bool error_filtered_out; /* True if a klog message >> has been filtered out */ >> fwts_acpica_mode acpica_mode; /* ACPICA mode flags */ >> + void *rsdp; /* ACPI RSDP address */ >> } fwts_framework; >> >> typedef struct { >> diff --git a/src/lib/src/fwts_acpi_tables.c >> b/src/lib/src/fwts_acpi_tables.c >> index 6f1e964..f9f6ba0 100644 >> --- a/src/lib/src/fwts_acpi_tables.c >> +++ b/src/lib/src/fwts_acpi_tables.c >> @@ -52,6 +52,34 @@ static void *fwts_acpi_find_rsdp_efi(void) >> } >> >> /* >> + * fwts_acpi_find_rsdp_klog() >> + * Get RSDP by parsing kernel log >> + */ >> +static void *fwts_acpi_find_rsdp_klog(void) >> +{ >> + fwts_list *klog; >> + fwts_list_link *item; >> + void *rsdp = NULL; >> + >> + if ((klog = fwts_klog_read()) == NULL) >> + return NULL; >> + >> + fwts_list_foreach(item, klog) { >> + char *text = fwts_text_list_text(item); >> + char *ptr = strstr(text, "ACPI: RSDP"); >> + >> + if (ptr) { >> + rsdp = (void *)strtoul(ptr + 11, NULL, 16); >> + break; >> + } >> + } >> + >> + fwts_text_list_free(klog); >> + >> + return rsdp; >> +} >> + >> +/* >> * fwts_acpi_find_rsdp_bios() >> * Find RSDP address by scanning BIOS memory >> */ >> @@ -94,21 +122,26 @@ static void *fwts_acpi_find_rsdp_bios(void) >> static fwts_acpi_table_rsdp *fwts_acpi_get_rsdp(void *addr, size_t >> *rsdp_len) >> { >> uint8_t *mem; >> - fwts_acpi_table_rsdp *rsdp; >> + fwts_acpi_table_rsdp *rsdp = NULL; >> *rsdp_len = 0; >> >> if ((mem = fwts_mmap((off_t)addr, sizeof(fwts_acpi_table_rsdp))) >> == FWTS_MAP_FAILED) >> return NULL; >> >> - /* Determine original RSDP size from revision. */ >> rsdp = (fwts_acpi_table_rsdp*)mem; >> + /* Determine original RSDP size from revision. */ >> *rsdp_len = (rsdp->revision < 1) ? 20 : 36; >> >> + /* Must have the correct signature */ >> + if (strncmp(rsdp->signature, "RSD PTR ", 8)) >> + goto out; >> + >> /* Assume version 2.0 size, we don't care about a few bytes over >> allocation if it's version 1.0 */ >> if ((rsdp = (fwts_acpi_table_rsdp*)fwts_low_calloc(1, >> sizeof(fwts_acpi_table_rsdp))) == NULL) >> - return NULL; >> + goto out; >> >> memcpy(rsdp, mem, *rsdp_len); >> +out: >> (void)fwts_munmap(mem, sizeof(fwts_acpi_table_rsdp)); >> >> return rsdp; >> @@ -238,22 +271,33 @@ static void >> fwts_acpi_handle_fadt(fwts_acpi_table_fadt *fadt, fwts_acpi_table_pr >> * fwts_acpi_load_tables_from_firmware() >> * Load up cached copies of all the ACPI tables >> */ >> -static int fwts_acpi_load_tables_from_firmware(void) >> +static int fwts_acpi_load_tables_from_firmware(fwts_framework *fw) >> { >> fwts_acpi_table_rsdp *rsdp; >> fwts_acpi_table_xsdt *xsdt; >> fwts_acpi_table_rsdt *rsdt; >> fwts_acpi_table_header *header; >> >> - void * rsdp_addr; >> + void * rsdp_addr = NULL; >> size_t rsdp_len; >> int num_entries; >> int i; >> >> - /* Check for RSDP in EFI, then BIOS, if not found, give up */ >> - if ((rsdp_addr = fwts_acpi_find_rsdp_efi()) == NULL) >> - if ((rsdp_addr = fwts_acpi_find_rsdp_bios()) == NULL) >> - return FWTS_ERROR; >> + /* Check for RSDP as EFI, then BIOS, parsed klog, if not found, >> give up */ >> + if (fw->rsdp) >> + rsdp_addr = (void*)fw->rsdp; >> + if (!rsdp_addr) >> + rsdp_addr = fwts_acpi_find_rsdp_efi(); >> + if (!rsdp_addr) >> + rsdp_addr = fwts_acpi_find_rsdp_bios(); >> + if (!rsdp_addr) >> + rsdp_addr = fwts_acpi_find_rsdp_klog(); >> + if (!rsdp_addr) >> + return FWTS_ERROR; >> + >> + /* Must be on a 16 byte boundary */ >> + if (((unsigned long)rsdp_addr & 0xf)) >> + return FWTS_ERROR; >> >> /* Load and save cached RSDP */ >> if ((rsdp = fwts_acpi_get_rsdp(rsdp_addr, &rsdp_len)) == NULL) >> @@ -712,7 +756,7 @@ int fwts_acpi_load_tables(fwts_framework *fw) >> else if (fw->acpi_table_acpidump_file != NULL) >> ret = fwts_acpi_load_tables_from_acpidump(fw); >> else if (fwts_check_root_euid(fw, true) == FWTS_OK) >> - ret = fwts_acpi_load_tables_from_firmware(); >> + ret = fwts_acpi_load_tables_from_firmware(fw); >> else >> ret = FWTS_ERROR_NO_PRIV; >> >> diff --git a/src/lib/src/fwts_framework.c b/src/lib/src/fwts_framework.c >> index eae5907..92aa74d 100644 >> --- a/src/lib/src/fwts_framework.c >> +++ b/src/lib/src/fwts_framework.c >> @@ -83,6 +83,7 @@ static fwts_option fwts_framework_options[] = { >> { "acpica-debug", "", 0, "Enable ACPICA debug/warning >> messages." }, >> { "acpica", "", 1, "Enable ACPICA run time options." >> }, >> { "uefi", "", 0, "Run UEFI tests." }, >> + { "rsdp", "R:", 1, "Specify the physical address of >> the ACPI RSDP." }, >> { NULL, NULL, 0, NULL } >> }; >> >> @@ -1138,6 +1139,9 @@ int fwts_framework_options_handler(fwts_framework >> *fw, int argc, char * const ar >> case 38: /* --uefi */ >> fw->flags |= FWTS_FLAG_TEST_UEFI; >> break; >> + case 39: /* --rsdp */ >> + fw->rsdp = (void *)strtoul(optarg, NULL, 0); >> + break; >> } >> break; >> case 'a': /* --all */ >> @@ -1214,6 +1218,9 @@ int fwts_framework_options_handler(fwts_framework >> *fw, int argc, char * const ar >> case 'w': /* --log-width=N */ >> fwts_log_set_line_width(atoi(optarg)); >> break; >> + case 'R': /* --rsdp=addr */ >> + fw->rsdp = (void *)strtoul(optarg, NULL, 0); >> + break; >> } >> return FWTS_OK; >> } >> > > Acked-by: Ivan Hu <ivan.hu@canonical.com> > Acked-by: Keng-Yu Lin <kengyu@canonical.com>
diff --git a/doc/fwts.1 b/doc/fwts.1 index 234278d..a12aca9 100644 --- a/doc/fwts.1 +++ b/doc/fwts.1 @@ -201,6 +201,10 @@ no pretty printing of horizontal separators in the results log file. specify the results output log file. One can also specify stdout and stderr to redirect to these output streams. .TP +.B \-R, \-\-rsdp=physaddr +specify the physical address of ACPI RSDP. This is useful on some systems where +it cannot be automatically detected. +.TP .B \-\-s3\-delay\-delta=N time to be added onto delay between each S3 iteration. .TP diff --git a/src/lib/include/fwts_framework.h b/src/lib/include/fwts_framework.h index f365d74..1e5171c 100644 --- a/src/lib/include/fwts_framework.h +++ b/src/lib/include/fwts_framework.h @@ -144,6 +144,7 @@ typedef struct { fwts_list errors_filter_discard; /* Results to discard, empty = discard none */ bool error_filtered_out; /* True if a klog message has been filtered out */ fwts_acpica_mode acpica_mode; /* ACPICA mode flags */ + void *rsdp; /* ACPI RSDP address */ } fwts_framework; typedef struct { diff --git a/src/lib/src/fwts_acpi_tables.c b/src/lib/src/fwts_acpi_tables.c index 6f1e964..f9f6ba0 100644 --- a/src/lib/src/fwts_acpi_tables.c +++ b/src/lib/src/fwts_acpi_tables.c @@ -52,6 +52,34 @@ static void *fwts_acpi_find_rsdp_efi(void) } /* + * fwts_acpi_find_rsdp_klog() + * Get RSDP by parsing kernel log + */ +static void *fwts_acpi_find_rsdp_klog(void) +{ + fwts_list *klog; + fwts_list_link *item; + void *rsdp = NULL; + + if ((klog = fwts_klog_read()) == NULL) + return NULL; + + fwts_list_foreach(item, klog) { + char *text = fwts_text_list_text(item); + char *ptr = strstr(text, "ACPI: RSDP"); + + if (ptr) { + rsdp = (void *)strtoul(ptr + 11, NULL, 16); + break; + } + } + + fwts_text_list_free(klog); + + return rsdp; +} + +/* * fwts_acpi_find_rsdp_bios() * Find RSDP address by scanning BIOS memory */ @@ -94,21 +122,26 @@ static void *fwts_acpi_find_rsdp_bios(void) static fwts_acpi_table_rsdp *fwts_acpi_get_rsdp(void *addr, size_t *rsdp_len) { uint8_t *mem; - fwts_acpi_table_rsdp *rsdp; + fwts_acpi_table_rsdp *rsdp = NULL; *rsdp_len = 0; if ((mem = fwts_mmap((off_t)addr, sizeof(fwts_acpi_table_rsdp))) == FWTS_MAP_FAILED) return NULL; - /* Determine original RSDP size from revision. */ rsdp = (fwts_acpi_table_rsdp*)mem; + /* Determine original RSDP size from revision. */ *rsdp_len = (rsdp->revision < 1) ? 20 : 36; + /* Must have the correct signature */ + if (strncmp(rsdp->signature, "RSD PTR ", 8)) + goto out; + /* Assume version 2.0 size, we don't care about a few bytes over allocation if it's version 1.0 */ if ((rsdp = (fwts_acpi_table_rsdp*)fwts_low_calloc(1, sizeof(fwts_acpi_table_rsdp))) == NULL) - return NULL; + goto out; memcpy(rsdp, mem, *rsdp_len); +out: (void)fwts_munmap(mem, sizeof(fwts_acpi_table_rsdp)); return rsdp; @@ -238,22 +271,33 @@ static void fwts_acpi_handle_fadt(fwts_acpi_table_fadt *fadt, fwts_acpi_table_pr * fwts_acpi_load_tables_from_firmware() * Load up cached copies of all the ACPI tables */ -static int fwts_acpi_load_tables_from_firmware(void) +static int fwts_acpi_load_tables_from_firmware(fwts_framework *fw) { fwts_acpi_table_rsdp *rsdp; fwts_acpi_table_xsdt *xsdt; fwts_acpi_table_rsdt *rsdt; fwts_acpi_table_header *header; - void * rsdp_addr; + void * rsdp_addr = NULL; size_t rsdp_len; int num_entries; int i; - /* Check for RSDP in EFI, then BIOS, if not found, give up */ - if ((rsdp_addr = fwts_acpi_find_rsdp_efi()) == NULL) - if ((rsdp_addr = fwts_acpi_find_rsdp_bios()) == NULL) - return FWTS_ERROR; + /* Check for RSDP as EFI, then BIOS, parsed klog, if not found, give up */ + if (fw->rsdp) + rsdp_addr = (void*)fw->rsdp; + if (!rsdp_addr) + rsdp_addr = fwts_acpi_find_rsdp_efi(); + if (!rsdp_addr) + rsdp_addr = fwts_acpi_find_rsdp_bios(); + if (!rsdp_addr) + rsdp_addr = fwts_acpi_find_rsdp_klog(); + if (!rsdp_addr) + return FWTS_ERROR; + + /* Must be on a 16 byte boundary */ + if (((unsigned long)rsdp_addr & 0xf)) + return FWTS_ERROR; /* Load and save cached RSDP */ if ((rsdp = fwts_acpi_get_rsdp(rsdp_addr, &rsdp_len)) == NULL) @@ -712,7 +756,7 @@ int fwts_acpi_load_tables(fwts_framework *fw) else if (fw->acpi_table_acpidump_file != NULL) ret = fwts_acpi_load_tables_from_acpidump(fw); else if (fwts_check_root_euid(fw, true) == FWTS_OK) - ret = fwts_acpi_load_tables_from_firmware(); + ret = fwts_acpi_load_tables_from_firmware(fw); else ret = FWTS_ERROR_NO_PRIV; diff --git a/src/lib/src/fwts_framework.c b/src/lib/src/fwts_framework.c index eae5907..92aa74d 100644 --- a/src/lib/src/fwts_framework.c +++ b/src/lib/src/fwts_framework.c @@ -83,6 +83,7 @@ static fwts_option fwts_framework_options[] = { { "acpica-debug", "", 0, "Enable ACPICA debug/warning messages." }, { "acpica", "", 1, "Enable ACPICA run time options." }, { "uefi", "", 0, "Run UEFI tests." }, + { "rsdp", "R:", 1, "Specify the physical address of the ACPI RSDP." }, { NULL, NULL, 0, NULL } }; @@ -1138,6 +1139,9 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar case 38: /* --uefi */ fw->flags |= FWTS_FLAG_TEST_UEFI; break; + case 39: /* --rsdp */ + fw->rsdp = (void *)strtoul(optarg, NULL, 0); + break; } break; case 'a': /* --all */ @@ -1214,6 +1218,9 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar case 'w': /* --log-width=N */ fwts_log_set_line_width(atoi(optarg)); break; + case 'R': /* --rsdp=addr */ + fw->rsdp = (void *)strtoul(optarg, NULL, 0); + break; } return FWTS_OK; }