NACK: [PATCH] Allow RSDP to be provided manually or scan for it in klog (LP: #1260400)
Colin Ian King
colin.king at canonical.com
Thu Dec 12 20:18:41 UTC 2013
On 12/12/13 19:47, Colin King wrote:
> From: Colin Ian King <colin.king at 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 at 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..0549d1b 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 (((uint64_t)rsdp_addr & 0xf))
> + return FWTS_ERROR;
That's from an earlier bit of work and clearly not the patch I intended
to send out, will resend.
>
> /* 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;
> }
>
More information about the fwts-devel
mailing list