]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Merge tag 'v2024.01-rc5' into next
authorTom Rini <trini@konsulko.com>
Mon, 18 Dec 2023 13:31:50 +0000 (08:31 -0500)
committerTom Rini <trini@konsulko.com>
Mon, 18 Dec 2023 14:55:32 +0000 (09:55 -0500)
Prepare v2024.01-rc5

20 files changed:
1  2 
MAINTAINERS
Makefile
arch/arm/dts/Makefile
arch/arm/dts/imx7d-pico-pi-u-boot.dtsi
arch/arm/mach-imx/imx8m/clock_imx8mm.c
arch/sandbox/dts/test.dts
arch/sandbox/include/asm/clk.h
board/emulation/qemu-riscv/Kconfig
board/toradex/colibri_imx7/colibri_imx7.c
boot/bootmeth_efi.c
common/spl/Kconfig
configs/imx8mm_data_modul_edm_sbc_defconfig
configs/imx8mp_data_modul_edm_sbc_defconfig
configs/imx8mp_dhcom_pdk2_defconfig
configs/imx8mp_dhcom_pdk3_defconfig
configs/imx8mp_evk_defconfig
lib/Kconfig
lib/efi_loader/Makefile
lib/efi_loader/efi_bootmgr.c
lib/efi_loader/efi_boottime.c

diff --cc MAINTAINERS
Simple merge
diff --cc Makefile
Simple merge
Simple merge
index 3dd01e36a4afffe46cddb1e34d45d29e609b5934,c6856823c64d2d14e352d3b4264539d374653b4e..3b5f14ecb044bca5d478b6f922cdd1aa1a77627a
@@@ -1,12 -1,17 +1,18 @@@
  #include "imx7s-u-boot.dtsi"
  
  /{
 -    aliases {
 -        mmc0 = &usdhc3;
 -        usb0 = &usbotg1;
 -        display0 = &lcdif;
 -    };
 +      aliases {
 +              mmc0 = &usdhc3;
 +              mmc1 = &usdhc1;
 +              usb0 = &usbotg1;
 +              display0 = &lcdif;
 +      };
+       wdt-reboot {
+               compatible = "wdt-reboot";
+               wdt = <&wdog1>;
+               bootph-pre-ram;
+       };
  };
  
  &usbotg1 {
Simple merge
Simple merge
Simple merge
index d46bff51d8a7a6ec0fbcbf1d960c08e709673ccc,446cb73140eea22c3a12b3046be16a020e3c06c7..00060f7d25a571c91848b7b5073dfb2cd6434ea6
@@@ -441,9 -453,21 +452,18 @@@ static int distro_efi_boot(struct udevi
                fdt = env_get_hex("fdt_addr_r", 0);
        }
  
-       if (efi_binary_run(map_sysmem(kernel, 0), 0, map_sysmem(fdt, 0)))
-               return log_msg_ret("run", -EINVAL);
 -      /*
 -       * At some point we can add a real interface to bootefi so we can call
 -       * this directly. For now, go through the CLI, like distro boot.
 -       */
+       if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) {
+               log_debug("Booting with built-in fdt\n");
 -              snprintf(cmd, sizeof(cmd), "bootefi %lx", kernel);
++              if (efi_binary_run(map_sysmem(kernel, 0), 0,
++                                 EFI_FDT_USE_INTERNAL))
++                      return log_msg_ret("run", -EINVAL);
+       } else {
+               log_debug("Booting with external fdt\n");
 -              snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", kernel, fdt);
++              if (efi_binary_run(map_sysmem(kernel, 0), 0,
++                                 map_sysmem(fdt, 0)))
++                      return log_msg_ret("run", -EINVAL);
+       }
  
 -      if (run_command(cmd, 0))
 -              return log_msg_ret("run", -EINVAL);
 -
        return 0;
  }
  
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc lib/Kconfig
Simple merge
Simple merge
index 56d97f23827bb6a7ac15c10bd5e3ac3a0e037c2b,a40762c74c8380540170c6a8c447ce4a72d1288e..e815fa06c8bd3ff5fc182feb624342ccefa6bebc
                return EFI_SUCCESS;
        return ret;
  }
- #if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
 +
 +static struct efi_device_path *bootefi_image_path;
 +static struct efi_device_path *bootefi_device_path;
 +static void *image_addr;
 +static size_t image_size;
 +
 +/**
 + * efi_get_image_parameters() - return image parameters
 + *
 + * @img_addr:         address of loaded image in memory
 + * @img_size:         size of loaded image
 + */
 +void efi_get_image_parameters(void **img_addr, size_t *img_size)
 +{
 +      *img_addr = image_addr;
 +      *img_size = image_size;
 +}
 +
 +/**
 + * efi_clear_bootdev() - clear boot device
 + */
 +void efi_clear_bootdev(void)
 +{
 +      efi_free_pool(bootefi_device_path);
 +      efi_free_pool(bootefi_image_path);
 +      bootefi_device_path = NULL;
 +      bootefi_image_path = NULL;
 +      image_addr = NULL;
 +      image_size = 0;
 +}
 +
 +/**
 + * efi_set_bootdev() - set boot device
 + *
 + * This function is called when a file is loaded, e.g. via the 'load' command.
 + * We use the path to this file to inform the UEFI binary about the boot device.
 + *
 + * @dev:              device, e.g. "MMC"
 + * @devnr:            number of the device, e.g. "1:2"
 + * @path:             path to file loaded
 + * @buffer:           buffer with file loaded
 + * @buffer_size:      size of file loaded
 + */
 +void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
 +                   void *buffer, size_t buffer_size)
 +{
 +      struct efi_device_path *device, *image;
 +      efi_status_t ret;
 +
 +      log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev,
 +                devnr, path, buffer, buffer_size);
 +
 +      /* Forget overwritten image */
 +      if (buffer + buffer_size >= image_addr &&
 +          image_addr + image_size >= buffer)
 +              efi_clear_bootdev();
 +
 +      /* Remember only PE-COFF and FIT images */
 +      if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
 +              if (IS_ENABLED(CONFIG_FIT) &&
 +                  !fit_check_format(buffer, IMAGE_SIZE_INVAL)) {
 +                      /*
 +                       * FIT images of type EFI_OS are started via command
 +                       * bootm. We should not use their boot device with the
 +                       * bootefi command.
 +                       */
 +                      buffer = 0;
 +                      buffer_size = 0;
 +              } else {
 +                      log_debug("- not remembering image\n");
 +                      return;
 +              }
 +      }
 +
 +      /* efi_set_bootdev() is typically called repeatedly, recover memory */
 +      efi_clear_bootdev();
 +
 +      image_addr = buffer;
 +      image_size = buffer_size;
 +
 +      ret = efi_dp_from_name(dev, devnr, path, &device, &image);
 +      if (ret == EFI_SUCCESS) {
 +              bootefi_device_path = device;
 +              if (image) {
 +                      /* FIXME: image should not contain device */
 +                      struct efi_device_path *image_tmp = image;
 +
 +                      efi_dp_split_file_path(image, &device, &image);
 +                      efi_free_pool(image_tmp);
 +              }
 +              bootefi_image_path = image;
 +              log_debug("- boot device %pD\n", device);
 +              if (image)
 +                      log_debug("- image %pD\n", image);
 +      } else {
 +              log_debug("- efi_dp_from_name() failed, err=%lx\n", ret);
 +              efi_clear_bootdev();
 +      }
 +}
 +
 +/**
 + * efi_env_set_load_options() - set load options from environment variable
 + *
 + * @handle:           the image handle
 + * @env_var:          name of the environment variable
 + * @load_options:     pointer to load options (output)
 + * Return:            status code
 + */
 +efi_status_t efi_env_set_load_options(efi_handle_t handle,
 +                                    const char *env_var,
 +                                    u16 **load_options)
 +{
 +      const char *env = env_get(env_var);
 +      size_t size;
 +      u16 *pos;
 +      efi_status_t ret;
 +
 +      *load_options = NULL;
 +      if (!env)
 +              return EFI_SUCCESS;
 +      size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
 +      pos = calloc(size, 1);
 +      if (!pos)
 +              return EFI_OUT_OF_RESOURCES;
 +      *load_options = pos;
 +      utf8_utf16_strcpy(&pos, env);
 +      ret = efi_set_load_options(handle, size, *load_options);
 +      if (ret != EFI_SUCCESS) {
 +              free(*load_options);
 +              *load_options = NULL;
 +      }
 +      return ret;
 +}
 +
- #endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */
 +/**
 + * copy_fdt() - Copy the device tree to a new location available to EFI
 + *
 + * The FDT is copied to a suitable location within the EFI memory map.
 + * Additional 12 KiB are added to the space in case the device tree needs to be
 + * expanded later with fdt_open_into().
 + *
 + * @fdtp:     On entry a pointer to the flattened device tree.
 + *            On exit a pointer to the copy of the flattened device tree.
 + *            FDT start
 + * Return:    status code
 + */
 +static efi_status_t copy_fdt(void **fdtp)
 +{
 +      unsigned long fdt_ram_start = -1L, fdt_pages;
 +      efi_status_t ret = 0;
 +      void *fdt, *new_fdt;
 +      u64 new_fdt_addr;
 +      uint fdt_size;
 +      int i;
 +
 +      for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 +              u64 ram_start = gd->bd->bi_dram[i].start;
 +              u64 ram_size = gd->bd->bi_dram[i].size;
 +
 +              if (!ram_size)
 +                      continue;
 +
 +              if (ram_start < fdt_ram_start)
 +                      fdt_ram_start = ram_start;
 +      }
 +
 +      /*
 +       * Give us at least 12 KiB of breathing room in case the device tree
 +       * needs to be expanded later.
 +       */
 +      fdt = *fdtp;
 +      fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
 +      fdt_size = fdt_pages << EFI_PAGE_SHIFT;
 +
 +      ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
 +                               EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
 +                               &new_fdt_addr);
 +      if (ret != EFI_SUCCESS) {
 +              log_err("ERROR: Failed to reserve space for FDT\n");
 +              goto done;
 +      }
 +      new_fdt = (void *)(uintptr_t)new_fdt_addr;
 +      memcpy(new_fdt, fdt, fdt_totalsize(fdt));
 +      fdt_set_totalsize(new_fdt, fdt_size);
 +
 +      *fdtp = (void *)(uintptr_t)new_fdt_addr;
 +done:
 +      return ret;
 +}
 +
 +/**
 + * 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;
 +}
 +
- #if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
-       if (fdt) {
 +/**
 + * efi_install_fdt() - install device tree
 + *
 + * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory
 + * address will be installed as configuration table, otherwise the device
 + * tree located at the address indicated by environment variable fdt_addr or as
 + * fallback fdtcontroladdr will be used.
 + *
 + * On architectures using ACPI tables device trees shall not be installed as
 + * configuration table.
 + *
 + * @fdt:      address of device tree or EFI_FDT_USE_INTERNAL to use
 + *            the hardware device tree as indicated by environment variable
 + *            fdt_addr or as fallback the internal device tree as indicated by
 + *            the environment variable fdtcontroladdr
 + * Return:    status code
 + */
 +efi_status_t efi_install_fdt(void *fdt)
 +{
++      struct bootm_headers img = { 0 };
++      efi_status_t ret;
++
 +      /*
 +       * The EBBR spec requires that we have either an FDT or an ACPI table
 +       * but not both.
 +       */
-               return EFI_SUCCESS;
-       }
- #else
-       struct bootm_headers img = { 0 };
-       efi_status_t ret;
++      if (CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) && fdt)
 +              log_warning("WARNING: Can't have ACPI table and device tree - ignoring DT.\n");
-       /* Create memory reservations as indicated by the device tree */
-       efi_carve_out_dt_rsv(fdt);
 +
 +      if (fdt == EFI_FDT_USE_INTERNAL) {
 +              const char *fdt_opt;
 +              uintptr_t fdt_addr;
 +
 +              /* Look for device tree that is already installed */
 +              if (get_config_table(&efi_guid_fdt))
 +                      return EFI_SUCCESS;
 +              /* Check if there is a hardware device tree */
 +              fdt_opt = env_get("fdt_addr");
 +              /* Use our own device tree as fallback */
 +              if (!fdt_opt) {
 +                      fdt_opt = env_get("fdtcontroladdr");
 +                      if (!fdt_opt) {
 +                              log_err("ERROR: need device tree\n");
 +                              return EFI_NOT_FOUND;
 +                      }
 +              }
 +              fdt_addr = hextoul(fdt_opt, NULL);
 +              if (!fdt_addr) {
 +                      log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n");
 +                      return EFI_LOAD_ERROR;
 +              }
 +              fdt = map_sysmem(fdt_addr, 0);
 +      }
 +
 +      /* Install device tree */
 +      if (fdt_check_header(fdt)) {
 +              log_err("ERROR: invalid device tree\n");
 +              return EFI_LOAD_ERROR;
 +      }
 +
++      /* Create memory reservations as indicated by the device tree */
++      efi_carve_out_dt_rsv(fdt);
++
++      if (CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE))
++              return EFI_SUCCESS;
++
 +      /* Prepare device tree for payload */
 +      ret = copy_fdt(&fdt);
 +      if (ret) {
 +              log_err("ERROR: out of memory\n");
 +              return EFI_OUT_OF_RESOURCES;
 +      }
 +
 +      if (image_setup_libfdt(&img, fdt, NULL)) {
 +              log_err("ERROR: failed to process device tree\n");
 +              return EFI_LOAD_ERROR;
 +      }
 +
- #endif /* GENERATE_ACPI_TABLE */
 +      efi_try_purge_kaslr_seed(fdt);
 +
 +      if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
 +              ret = efi_tcg2_measure_dtb(fdt);
 +              if (ret == EFI_SECURITY_VIOLATION) {
 +                      log_err("ERROR: failed to measure DTB\n");
 +                      return ret;
 +              }
 +      }
 +
 +      /* Install device tree as UEFI table */
 +      ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
 +      if (ret != EFI_SUCCESS) {
 +              log_err("ERROR: failed to install device tree\n");
 +              return ret;
 +      }
 +
 +      return EFI_SUCCESS;
 +}
 +
 +/**
 + * do_bootefi_exec() - execute EFI binary
 + *
 + * The image indicated by @handle is started. When it returns the allocated
 + * memory for the @load_options is freed.
 + *
 + * @handle:           handle of loaded image
 + * @load_options:     load options
 + * Return:            status code
 + *
 + * Load the EFI binary into a newly assigned memory unwinding the relocation
 + * information, install the loaded image protocol, and call the binary.
 + */
 +static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
 +{
 +      efi_status_t ret;
 +      efi_uintn_t exit_data_size = 0;
 +      u16 *exit_data = NULL;
 +      struct efi_event *evt;
 +
 +      /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
 +      switch_to_non_secure_mode();
 +
 +      /*
 +       * The UEFI standard requires that the watchdog timer is set to five
 +       * minutes when invoking an EFI boot option.
 +       *
 +       * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
 +       * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
 +       */
 +      ret = efi_set_watchdog(300);
 +      if (ret != EFI_SUCCESS) {
 +              log_err("ERROR: Failed to set watchdog timer\n");
 +              goto out;
 +      }
 +
 +      /* Call our payload! */
 +      ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
 +      if (ret != EFI_SUCCESS) {
 +              log_err("## Application failed, r = %lu\n",
 +                      ret & ~EFI_ERROR_MASK);
 +              if (exit_data) {
 +                      log_err("## %ls\n", exit_data);
 +                      efi_free_pool(exit_data);
 +              }
 +      }
 +
 +      efi_restore_gd();
 +
 +out:
 +      free(load_options);
 +
 +      if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
 +              if (efi_initrd_deregister() != EFI_SUCCESS)
 +                      log_err("Failed to remove loadfile2 for initrd\n");
 +      }
 +
 +      /* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */
 +      list_for_each_entry(evt, &efi_events, link) {
 +              if (evt->group &&
 +                  !guidcmp(evt->group,
 +                           &efi_guid_event_group_return_to_efibootmgr)) {
 +                      efi_signal_event(evt);
 +                      EFI_CALL(systab.boottime->close_event(evt));
 +                      break;
 +              }
 +      }
 +
 +      /* Control is returned to U-Boot, disable EFI watchdog */
 +      efi_set_watchdog(0);
 +
 +      return ret;
 +}
 +
 +/**
 + * efi_bootmgr_run() - execute EFI boot manager
 + * @fdt:      Flat device tree
 + *
 + * Invoke EFI boot manager and execute a binary depending on
 + * boot options. If @fdt is not NULL, it will be passed to
 + * the executed binary.
 + *
 + * Return:    status code
 + */
 +efi_status_t efi_bootmgr_run(void *fdt)
 +{
 +      efi_handle_t handle;
 +      void *load_options;
 +      efi_status_t ret;
 +
 +      /* Initialize EFI drivers */
 +      ret = efi_init_obj_list();
 +      if (ret != EFI_SUCCESS) {
 +              log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
 +                      ret & ~EFI_ERROR_MASK);
 +              return CMD_RET_FAILURE;
 +      }
 +
 +      ret = efi_install_fdt(fdt);
 +      if (ret != EFI_SUCCESS)
 +              return ret;
 +
 +      ret = efi_bootmgr_load(&handle, &load_options);
 +      if (ret != EFI_SUCCESS) {
 +              log_notice("EFI boot manager: Cannot load any image\n");
 +              return ret;
 +      }
 +
 +      return do_bootefi_exec(handle, load_options);
 +}
 +
 +/**
 + * efi_run_image() - run loaded UEFI image
 + *
 + * @source_buffer:    memory address of the UEFI image
 + * @source_size:      size of the UEFI image
 + * Return:            status code
 + */
 +efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size)
 +{
 +      efi_handle_t mem_handle = NULL, handle;
 +      struct efi_device_path *file_path = NULL;
 +      struct efi_device_path *msg_path;
 +      efi_status_t ret, ret2;
 +      u16 *load_options;
 +
 +      if (!bootefi_device_path || !bootefi_image_path) {
 +              log_debug("Not loaded from disk\n");
 +              /*
 +               * Special case for efi payload not loaded from disk,
 +               * such as 'bootefi hello' or for example payload
 +               * loaded directly into memory via JTAG, etc:
 +               */
 +              file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
 +                                          (uintptr_t)source_buffer,
 +                                          source_size);
 +              /*
 +               * Make sure that device for device_path exist
 +               * in load_image(). Otherwise, shell and grub will fail.
 +               */
 +              ret = efi_install_multiple_protocol_interfaces(&mem_handle,
 +                                                             &efi_guid_device_path,
 +                                                             file_path, NULL);
 +              if (ret != EFI_SUCCESS)
 +                      goto out;
 +              msg_path = file_path;
 +      } else {
 +              file_path = efi_dp_append(bootefi_device_path,
 +                                        bootefi_image_path);
 +              msg_path = bootefi_image_path;
 +              log_debug("Loaded from disk\n");
 +      }
 +
 +      log_info("Booting %pD\n", msg_path);
 +
 +      ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer,
 +                                    source_size, &handle));
 +      if (ret != EFI_SUCCESS) {
 +              log_err("Loading image failed\n");
 +              goto out;
 +      }
 +
 +      /* Transfer environment variable as load options */
 +      ret = efi_env_set_load_options(handle, "bootargs", &load_options);
 +      if (ret != EFI_SUCCESS)
 +              goto out;
 +
 +      ret = do_bootefi_exec(handle, load_options);
 +
 +out:
 +      ret2 = efi_uninstall_multiple_protocol_interfaces(mem_handle,
 +                                                        &efi_guid_device_path,
 +                                                        file_path, NULL);
 +      efi_free_pool(file_path);
 +      return (ret != EFI_SUCCESS) ? ret : ret2;
 +}
 +
 +/**
 + * efi_binary_run() - run loaded UEFI image
 + *
 + * @image:    memory address of the UEFI image
 + * @size:     size of the UEFI image
 + * @fdt:      device-tree
 + *
 + * Execute an EFI binary image loaded at @image.
 + * @size may be zero if the binary is loaded with U-Boot load command.
 + *
 + * Return:    status code
 + */
 +efi_status_t efi_binary_run(void *image, size_t size, void *fdt)
 +{
 +      efi_status_t ret;
 +
 +      /* Initialize EFI drivers */
 +      ret = efi_init_obj_list();
 +      if (ret != EFI_SUCCESS) {
 +              log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
 +                      ret & ~EFI_ERROR_MASK);
 +              return -1;
 +      }
 +
 +      ret = efi_install_fdt(fdt);
 +      if (ret != EFI_SUCCESS)
 +              return ret;
 +
 +      return efi_run_image(image, size);
 +}
Simple merge