From 6182495e101f2d3da29e632632c3d6e5035fef8b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 20 Apr 2019 13:33:55 +0200 Subject: [PATCH] efi_loader: need either ACPI table or device tree The EBBR specification prescribes that we should have either an ACPI table or a device tree but not both. Let us enforce this condition in the `bootefi` command. If the bootefi command is called without a device tree parameter use a previously device tree or fall back to the internal device tree. The fdt unit test should not be run on boards with an ACPI table. Signed-off-by: Heinrich Schuchardt --- cmd/bootefi.c | 98 ++++++++++++++++++++++++++++----------- lib/efi_selftest/Makefile | 1 - 2 files changed, 72 insertions(+), 27 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index be55751830..efaa548be4 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -84,6 +84,8 @@ out: efi_root, NULL)); } +#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) + /** * copy_fdt() - Copy the device tree to a new location available to EFI * @@ -185,6 +187,25 @@ static void efi_carve_out_dt_rsv(void *fdt) } } +/** + * get_config_table() - get configuration table + * + * @guid: GUID of the configuration table + * Return: pointer to configuration table or NULL + */ +static void *get_config_table(const efi_guid_t *guid) +{ + size_t i; + + for (i = 0; i < systab.nr_tables; i++) { + if (!guidcmp(guid, &systab.tables[i].guid)) + return systab.tables[i].table; + } + return NULL; +} + +#endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */ + /** * efi_install_fdt() - install fdt passed by a command argument * @fdt_opt: pointer to argument @@ -195,46 +216,71 @@ static void efi_carve_out_dt_rsv(void *fdt) */ static efi_status_t efi_install_fdt(const char *fdt_opt) { + /* + * The EBBR spec requires that we have either an FDT or an ACPI table + * but not both. + */ +#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) + if (fdt_opt) { + printf("ERROR: can't have ACPI table and device tree.\n"); + return EFI_LOAD_ERROR; + } +#else unsigned long fdt_addr; void *fdt; bootm_headers_t img = { 0 }; efi_status_t ret; if (fdt_opt) { - /* Install device tree */ fdt_addr = simple_strtoul(fdt_opt, NULL, 16); - if (!fdt_addr && *fdt_opt != '0') - return EFI_INVALID_PARAMETER; - - fdt = map_sysmem(fdt_addr, 0); - if (fdt_check_header(fdt)) { - printf("ERROR: invalid device tree\n"); + if (!fdt_addr) return EFI_INVALID_PARAMETER; + } else { + /* Look for device tree that is already installed */ + if (get_config_table(&efi_guid_fdt)) + return EFI_SUCCESS; + /* Use our own device tree as default */ + fdt_opt = env_get("fdtcontroladdr"); + if (!fdt_opt) { + printf("ERROR: need device tree\n"); + return EFI_NOT_FOUND; } + fdt_addr = simple_strtoul(fdt_opt, NULL, 16); + if (!fdt_addr) { + printf("ERROR: invalid $fdtcontroladdr\n"); + return EFI_LOAD_ERROR; + } + } - /* Create memory reservation as indicated by the device tree */ - efi_carve_out_dt_rsv(fdt); + /* Install device tree */ + fdt = map_sysmem(fdt_addr, 0); + if (fdt_check_header(fdt)) { + printf("ERROR: invalid device tree\n"); + return EFI_LOAD_ERROR; + } - /* Prepare fdt for payload */ - ret = copy_fdt(&fdt); - if (ret) - return ret; + /* Create memory reservations as indicated by the device tree */ + efi_carve_out_dt_rsv(fdt); - if (image_setup_libfdt(&img, fdt, 0, NULL)) { - printf("ERROR: failed to process device tree\n"); - return EFI_LOAD_ERROR; - } + /* Prepare device tree for payload */ + ret = copy_fdt(&fdt); + if (ret) { + printf("ERROR: out of memory\n"); + return EFI_OUT_OF_RESOURCES; + } - /* Link to it in the efi tables */ - ret = efi_install_configuration_table(&efi_guid_fdt, fdt); - if (ret != EFI_SUCCESS) { - printf("ERROR: failed to install device tree\n"); - return ret; - } - } else { - /* Remove device tree. EFI_NOT_FOUND can be ignored here */ - efi_install_configuration_table(&efi_guid_fdt, NULL); + if (image_setup_libfdt(&img, fdt, 0, NULL)) { + printf("ERROR: failed to process device tree\n"); + return EFI_LOAD_ERROR; + } + + /* Install device tree as UEFI table */ + ret = efi_install_configuration_table(&efi_guid_fdt, fdt); + if (ret != EFI_SUCCESS) { + printf("ERROR: failed to install device tree\n"); + return ret; } +#endif /* GENERATE_ACPI_TABLE */ return EFI_SUCCESS; } diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index fb82e71976..4945691e67 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -23,7 +23,6 @@ efi_selftest_events.o \ efi_selftest_event_groups.o \ efi_selftest_exception.o \ efi_selftest_exitbootservices.o \ -efi_selftest_fdt.o \ efi_selftest_gop.o \ efi_selftest_loaded_image.o \ efi_selftest_manageprotocols.o \ -- 2.25.1