summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/efi.rst6
-rw-r--r--MAINTAINERS6
-rw-r--r--Makefile2
-rw-r--r--cmd/bootefi.c93
-rw-r--r--configs/am57xx_evm_defconfig5
-rw-r--r--configs/am57xx_hs_evm_defconfig5
-rw-r--r--configs/brppt1_mmc_defconfig3
-rw-r--r--configs/brppt1_nand_defconfig3
-rw-r--r--configs/brppt1_spi_defconfig3
-rw-r--r--configs/k2g_evm_defconfig1
-rw-r--r--drivers/mmc/mmc-uclass.c19
-rw-r--r--drivers/mmc/mmc.c26
-rw-r--r--drivers/mmc/renesas-sdhi.c3
-rw-r--r--drivers/mmc/tmio-common.c10
-rw-r--r--drivers/video/sunxi/sunxi_display.c42
-rw-r--r--drivers/video/video_bmp.c23
-rw-r--r--include/efi_loader.h10
-rw-r--r--include/mmc.h6
-rw-r--r--lib/efi_loader/efi_bootmgr.c2
-rw-r--r--lib/efi_loader/efi_boottime.c148
-rw-r--r--lib/efi_loader/efi_device_path.c16
-rw-r--r--lib/efi_loader/efi_file.c12
-rw-r--r--lib/efi_loader/efi_image_loader.c67
-rw-r--r--lib/efi_selftest/Makefile3
-rw-r--r--lib/efi_selftest/efi_selftest_block_device.c2
-rw-r--r--lib/efi_selftest/efi_selftest_hii.c102
-rw-r--r--lib/efi_selftest/efi_selftest_loadimage.c529
-rw-r--r--lib/efi_selftest/efi_selftest_startimage_exit.c2
-rw-r--r--lib/efi_selftest/efi_selftest_startimage_return.c2
-rw-r--r--lib/vsprintf.c2
-rw-r--r--test/unicode_ut.c98
31 files changed, 990 insertions, 261 deletions
diff --git a/Documentation/efi.rst b/Documentation/efi.rst
index 51c1de24f8..5337a55c3b 100644
--- a/Documentation/efi.rst
+++ b/Documentation/efi.rst
@@ -9,6 +9,12 @@ Boot services
.. kernel-doc:: lib/efi_loader/efi_boottime.c
:internal:
+Image relocation
+~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: lib/efi_loader/efi_image_loader.c
+ :internal:
+
Runtime services
----------------
diff --git a/MAINTAINERS b/MAINTAINERS
index 29449ffed6..f1f8818d6b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -114,7 +114,7 @@ F: include/configs/meson64.h
N: meson
ARM BROADCOM BCM283X
-M: Alexander Graf <agraf@suse.de>
+M: Matthias Brugger <mbrugger@suse.com>
S: Maintained
F: arch/arm/mach-bcm283x/
F: drivers/gpio/bcm2835_gpio.c
@@ -453,8 +453,8 @@ F: include/dm/
F: test/dm/
EFI PAYLOAD
-M: Alexander Graf <agraf@suse.de>
-R: Heinrich Schuchardt <xypron.glpk@gmx.de>
+M: Heinrich Schuchardt <xypron.glpk@gmx.de>
+R: Alexander Graf <agraf@csgraf.de>
S: Maintained
T: git git://github.com/agraf/u-boot.git
F: doc/README.uefi
diff --git a/Makefile b/Makefile
index 5bc3deed98..75a5c7d171 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
VERSION = 2019
PATCHLEVEL = 04
SUBLEVEL =
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
NAME =
# *DOCUMENTATION*
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index ee685d8644..3619a20e64 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -133,20 +133,6 @@ done:
return ret;
}
-static efi_status_t efi_do_enter(
- efi_handle_t image_handle, struct efi_system_table *st,
- EFIAPI efi_status_t (*entry)(
- efi_handle_t image_handle,
- struct efi_system_table *st))
-{
- efi_status_t ret = EFI_LOAD_ERROR;
-
- if (entry)
- ret = entry(image_handle, st);
- st->boottime->exit(image_handle, ret, 0, NULL);
- return ret;
-}
-
/*
* efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
*
@@ -266,9 +252,6 @@ static efi_status_t do_bootefi_exec(void *efi,
struct efi_loaded_image_obj *image_obj = NULL;
struct efi_loaded_image *loaded_image_info = NULL;
- EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
- struct efi_system_table *st);
-
/*
* Special case for efi payload not loaded from disk, such as
* 'bootefi hello' or for example payload loaded directly into
@@ -300,11 +283,9 @@ static efi_status_t do_bootefi_exec(void *efi,
goto err_prepare;
/* Load the EFI payload */
- entry = efi_load_pe(image_obj, efi, loaded_image_info);
- if (!entry) {
- ret = EFI_LOAD_ERROR;
+ ret = efi_load_pe(image_obj, efi, loaded_image_info);
+ if (ret != EFI_SUCCESS)
goto err_prepare;
- }
if (memdp) {
struct efi_device_path_memory *mdp = (void *)memdp;
@@ -319,14 +300,8 @@ static efi_status_t do_bootefi_exec(void *efi,
"{ro,boot}(blob)0000000000000000");
/* Call our payload! */
- debug("%s: Jumping to 0x%p\n", __func__, entry);
-
- if (setjmp(&image_obj->exit_jmp)) {
- ret = image_obj->exit_status;
- goto err_prepare;
- }
-
- ret = efi_do_enter(&image_obj->header, &systab, entry);
+ debug("%s: Jumping to 0x%p\n", __func__, image_obj->entry);
+ ret = EFI_CALL(efi_start_image(&image_obj->header, NULL, NULL));
err_prepare:
/* image has returned, loaded-image obj goes *poof*: */
@@ -343,38 +318,46 @@ err_add_protocol:
/**
* bootefi_test_prepare() - prepare to run an EFI test
*
- * This sets things up so we can call EFI functions. This involves preparing
- * the 'gd' pointer and setting up the load ed image data structures.
+ * Prepare to run a test as if it were provided by a loaded image.
*
- * @image_objp: loaded_image_infop: Pointer to a struct which will hold the
- * loaded image object. This struct will be inited by this function before
- * use.
- * @loaded_image_infop: Pointer to a struct which will hold the loaded image
- * info. This struct will be inited by this function before use.
- * @path: File path to the test being run (often just the test name with a
- * backslash before it
- * @test_func: Address of the test function that is being run
- * @load_options_path: U-Boot environment variable to use as load options
- * @return 0 if OK, -ve on error
+ * @image_objp: pointer to be set to the loaded image handle
+ * @loaded_image_infop: pointer to be set to the loaded image protocol
+ * @path: dummy file path used to construct the device path
+ * set in the loaded image protocol
+ * @load_options_path: name of a U-Boot environment variable. Its value is
+ * set as load options in the loaded image protocol.
+ * Return: status code
*/
static efi_status_t bootefi_test_prepare
(struct efi_loaded_image_obj **image_objp,
- struct efi_loaded_image **loaded_image_infop, const char *path,
- ulong test_func, const char *load_options_path)
+ struct efi_loaded_image **loaded_image_infop, const char *path,
+ const char *load_options_path)
{
+ efi_status_t ret;
+
/* Construct a dummy device path */
- bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
- (uintptr_t)test_func,
- (uintptr_t)test_func);
+ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0);
if (!bootefi_device_path)
return EFI_OUT_OF_RESOURCES;
+
bootefi_image_path = efi_dp_from_file(NULL, 0, path);
- if (!bootefi_image_path)
- return EFI_OUT_OF_RESOURCES;
+ if (!bootefi_image_path) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto failure;
+ }
- return bootefi_run_prepare(load_options_path, bootefi_device_path,
- bootefi_image_path, image_objp,
- loaded_image_infop);
+ ret = bootefi_run_prepare(load_options_path, bootefi_device_path,
+ bootefi_image_path, image_objp,
+ loaded_image_infop);
+ if (ret == EFI_SUCCESS)
+ return ret;
+
+ efi_free_pool(bootefi_image_path);
+ bootefi_image_path = NULL;
+failure:
+ efi_free_pool(bootefi_device_path);
+ bootefi_device_path = NULL;
+ return ret;
}
#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
@@ -456,13 +439,13 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
struct efi_loaded_image_obj *image_obj;
struct efi_loaded_image *loaded_image_info;
- if (bootefi_test_prepare(&image_obj, &loaded_image_info,
- "\\selftest", (uintptr_t)&efi_selftest,
- "efi_selftest"))
+ r = bootefi_test_prepare(&image_obj, &loaded_image_info,
+ "\\selftest", "efi_selftest");
+ if (r != EFI_SUCCESS)
return CMD_RET_FAILURE;
/* Execute the test */
- r = efi_selftest(&image_obj->header, &systab);
+ r = EFI_CALL(efi_selftest(&image_obj->header, &systab));
bootefi_run_finish(image_obj, loaded_image_info);
return r != EFI_SUCCESS;
} else
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index 8404d71d86..748682036e 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -8,6 +8,7 @@ CONFIG_SPL=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_SUPPORT=y
CONFIG_ARMV7_LPAE=y
+CONFIG_AHCI=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_NR_DRAM_BANKS=2
CONFIG_SPL_LOAD_FIT=y
@@ -39,8 +40,7 @@ CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
-CONFIG_SCSI_AHCI=y
-# CONFIG_BLK is not set
+CONFIG_DWC_AHCI=y
CONFIG_DFU_MMC=y
CONFIG_DFU_RAM=y
CONFIG_USB_FUNCTION_FASTBOOT=y
@@ -70,6 +70,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_PALMAS=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_PALMAS=y
+CONFIG_DM_SCSI=y
CONFIG_DM_SERIAL=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig
index 7a0fd927b8..9124adabdd 100644
--- a/configs/am57xx_hs_evm_defconfig
+++ b/configs/am57xx_hs_evm_defconfig
@@ -12,6 +12,7 @@ CONFIG_SPL=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_SUPPORT=y
CONFIG_ARMV7_LPAE=y
+CONFIG_AHCI=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_NR_DRAM_BANKS=2
CONFIG_FIT_IMAGE_POST_PROCESS=y
@@ -42,8 +43,7 @@ CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
-CONFIG_SCSI_AHCI=y
-# CONFIG_BLK is not set
+CONFIG_DWC_AHCI=y
CONFIG_DFU_MMC=y
CONFIG_DFU_RAM=y
CONFIG_USB_FUNCTION_FASTBOOT=y
@@ -73,6 +73,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_PALMAS=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_PALMAS=y
+CONFIG_DM_SCSI=y
CONFIG_DM_SERIAL=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
diff --git a/configs/brppt1_mmc_defconfig b/configs/brppt1_mmc_defconfig
index f2d8220126..6b0d0242f2 100644
--- a/configs/brppt1_mmc_defconfig
+++ b/configs/brppt1_mmc_defconfig
@@ -75,8 +75,9 @@ CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
CONFIG_MISC=y
CONFIG_DM_MMC=y
CONFIG_MMC_OMAP_HS=y
+CONFIG_PHY_NATSEMI=y
CONFIG_DM_ETH=y
-# CONFIG_NETDEVICES is not set
+CONFIG_DRIVER_TI_CPSW=y
CONFIG_DM_SERIAL=y
CONFIG_USB=y
CONFIG_DM_USB=y
diff --git a/configs/brppt1_nand_defconfig b/configs/brppt1_nand_defconfig
index 275727d11f..4578f74a62 100644
--- a/configs/brppt1_nand_defconfig
+++ b/configs/brppt1_nand_defconfig
@@ -79,8 +79,9 @@ CONFIG_MISC=y
CONFIG_NAND=y
CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
CONFIG_SYS_NAND_U_BOOT_OFFS=0x80000
+CONFIG_PHY_NATSEMI=y
CONFIG_DM_ETH=y
-# CONFIG_NETDEVICES is not set
+CONFIG_DRIVER_TI_CPSW=y
CONFIG_DM_SERIAL=y
CONFIG_USB=y
CONFIG_DM_USB=y
diff --git a/configs/brppt1_spi_defconfig b/configs/brppt1_spi_defconfig
index 668c4c22c2..12bb8cd5cc 100644
--- a/configs/brppt1_spi_defconfig
+++ b/configs/brppt1_spi_defconfig
@@ -86,8 +86,9 @@ CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_PHY_NATSEMI=y
CONFIG_DM_ETH=y
-# CONFIG_NETDEVICES is not set
+CONFIG_DRIVER_TI_CPSW=y
CONFIG_DM_SERIAL=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig
index c518b707a5..838b6f14b6 100644
--- a/configs/k2g_evm_defconfig
+++ b/configs/k2g_evm_defconfig
@@ -34,7 +34,6 @@ CONFIG_DTB_RESELECT=y
CONFIG_MULTI_DTB_FIT=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM=y
-# CONFIG_BLK is not set
CONFIG_DFU_MMC=y
CONFIG_SYS_I2C_DAVINCI=y
CONFIG_MISC=y
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 76225b7939..a9c8f335c1 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -368,6 +368,19 @@ static int mmc_blk_probe(struct udevice *dev)
return 0;
}
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+static int mmc_blk_remove(struct udevice *dev)
+{
+ struct udevice *mmc_dev = dev_get_parent(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
+ struct mmc *mmc = upriv->mmc;
+
+ return mmc_deinit(mmc);
+}
+#endif
+
static const struct blk_ops mmc_blk_ops = {
.read = mmc_bread,
#if CONFIG_IS_ENABLED(MMC_WRITE)
@@ -382,6 +395,12 @@ U_BOOT_DRIVER(mmc_blk) = {
.id = UCLASS_BLK,
.ops = &mmc_blk_ops,
.probe = mmc_blk_probe,
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+ .remove = mmc_blk_remove,
+ .flags = DM_FLAG_OS_PREPARE,
+#endif
};
#endif /* CONFIG_BLK */
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b04345a1e1..1c1527cc74 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2781,6 +2781,32 @@ int mmc_init(struct mmc *mmc)
return err;
}
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+int mmc_deinit(struct mmc *mmc)
+{
+ u32 caps_filtered;
+
+ if (!mmc->has_init)
+ return 0;
+
+ if (IS_SD(mmc)) {
+ caps_filtered = mmc->card_caps &
+ ~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
+ MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
+ MMC_CAP(UHS_SDR104));
+
+ return sd_select_mode_and_width(mmc, caps_filtered);
+ } else {
+ caps_filtered = mmc->card_caps &
+ ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400));
+
+ return mmc_select_mode_and_width(mmc, caps_filtered);
+ }
+}
+#endif
+
int mmc_set_dsr(struct mmc *mmc, u16 val)
{
mmc->dsr = val;
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index a556acd5cb..923f846370 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -148,6 +148,9 @@ static int renesas_sdhi_hs400(struct udevice *dev)
tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
}
+ tmio_sd_writel(priv, hs400 ? 0x704 : 0x300,
+ RENESAS_SDHI_SCC_DT2FF);
+
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 2421915a07..6e656e5a9b 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -705,10 +705,14 @@ static void tmio_sd_host_init(struct tmio_sd_priv *priv)
* This register dropped backward compatibility at version 0x10.
* Write an appropriate value depending on the IP version.
*/
- if (priv->version >= 0x10)
- tmio_sd_writel(priv, 0x101, TMIO_SD_HOST_MODE);
- else
+ if (priv->version >= 0x10) {
+ if (priv->caps & TMIO_SD_CAP_64BIT)
+ tmio_sd_writel(priv, 0x100, TMIO_SD_HOST_MODE);
+ else
+ tmio_sd_writel(priv, 0x101, TMIO_SD_HOST_MODE);
+ } else {
tmio_sd_writel(priv, 0x0, TMIO_SD_HOST_MODE);
+ }
if (priv->caps & TMIO_SD_CAP_DMA_INTERNAL) {
tmp = tmio_sd_readl(priv, TMIO_SD_DMA_MODE);
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index 6dd9bec351..46436b88c5 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -113,6 +113,13 @@ static int sunxi_hdmi_hpd_detect(int hpd_delay)
writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
+ /* Enable PLLs for eventual DDC */
+ writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
+ &hdmi->pad_ctrl1);
+ writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
+ &hdmi->pll_ctrl);
+ writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
+
while (timer_get_us() < tmo) {
if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
return 1;
@@ -203,7 +210,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
return r;
}
-static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
+static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
+ bool verbose_mode)
{
struct edid1_info edid1;
struct edid_cea861_info cea681[4];
@@ -215,13 +223,6 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
int i, r, ext_blocks = 0;
- /* SUNXI_HDMI_CTRL_ENABLE & PAD_CTRL0 are already set by hpd_detect */
- writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
- &hdmi->pad_ctrl1);
- writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
- &hdmi->pll_ctrl);
- writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
-
/* Reset i2c controller */
setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
writel(SUNXI_HMDI_DDC_CTRL_ENABLE |
@@ -241,7 +242,8 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
if (r == 0) {
r = edid_check_info(&edid1);
if (r) {
- printf("EDID: invalid EDID data\n");
+ if (verbose_mode)
+ printf("EDID: invalid EDID data\n");
r = -EINVAL;
}
}
@@ -1082,7 +1084,8 @@ void *video_hw_init(void)
struct ctfb_res_modes custom;
const char *options;
#ifdef CONFIG_VIDEO_HDMI
- int ret, hpd, hpd_delay, edid;
+ int hpd, hpd_delay, edid;
+ bool hdmi_present;
#endif
int i, overscan_offset, overscan_x, overscan_y;
unsigned int fb_dma_addr;
@@ -1118,12 +1121,23 @@ void *video_hw_init(void)
if (sunxi_display.monitor == sunxi_monitor_dvi ||
sunxi_display.monitor == sunxi_monitor_hdmi) {
/* Always call hdp_detect, as it also enables clocks, etc. */
- ret = sunxi_hdmi_hpd_detect(hpd_delay);
- if (ret) {
+ hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1);
+ if (hdmi_present && edid) {
printf("HDMI connected: ");
- if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
+ if (sunxi_hdmi_edid_get_mode(&custom, true) == 0)
mode = &custom;
- } else if (hpd) {
+ else
+ hdmi_present = false;
+ }
+ /* Fall back to EDID in case HPD failed */
+ if (edid && !hdmi_present) {
+ if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) {
+ mode = &custom;
+ hdmi_present = true;
+ }
+ }
+ /* Shut down when display was not found */
+ if ((hpd || edid) && !hdmi_present) {
sunxi_hdmi_shutdown();
sunxi_display.monitor = sunxi_get_default_mon(false);
} /* else continue with hdmi/dvi without a cable connected */
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index 2898b0b55d..193f37d275 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -229,11 +229,12 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
/*
- * We support displaying 8bpp BMPs on 16bpp LCDs
+ * We support displaying 8bpp and 24bpp BMPs on 16bpp LCDs
* and displaying 24bpp BMPs on 32bpp LCDs
- * */
+ */
if (bpix != bmp_bpix &&
!(bmp_bpix == 8 && bpix == 16) &&
+ !(bmp_bpix == 24 && bpix == 16) &&
!(bmp_bpix == 24 && bpix == 32)) {
printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
bpix, get_unaligned_le16(&bmp->header.bit_count));
@@ -318,12 +319,22 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
case 24:
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
- *(fb++) = *(bmap++);
- *(fb++) = *(bmap++);
- *(fb++) = *(bmap++);
- *(fb++) = 0;
+ if (bpix == 16) {
+ /* 16bit 555RGB format */
+ *(u16 *)fb = ((bmap[2] >> 3) << 10) |
+ ((bmap[1] >> 3) << 5) |
+ (bmap[0] >> 3);
+ bmap += 3;
+ fb += 2;
+ } else {
+ *(fb++) = *(bmap++);
+ *(fb++) = *(bmap++);
+ *(fb++) = *(bmap++);
+ *(fb++) = 0;
+ }
}
fb -= priv->line_length + width * (bpix / 8);
+ bmap += (padded_width - width) * 3;
}
break;
#endif /* CONFIG_BMP_24BPP */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 9dd933dae7..512880ab8f 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -301,8 +301,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
/* Called from places to check whether a timer expired */
void efi_timer_check(void);
/* PE loader implementation */
-void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
- struct efi_loaded_image *loaded_image_info);
+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info);
/* Called once to store the pristine gd pointer */
void efi_save_gd(void);
/* Special case handler for error/abort that just tries to dtrt to get
@@ -320,6 +320,10 @@ efi_status_t efi_create_handle(efi_handle_t *handle);
void efi_delete_handle(efi_handle_t obj);
/* Call this to validate a handle and find the EFI object for it */
struct efi_object *efi_search_obj(const efi_handle_t handle);
+/* Start image */
+efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
+ efi_uintn_t *exit_data_size,
+ u16 **exit_data);
/* Find a protocol on a handle */
efi_status_t efi_search_protocol(const efi_handle_t handle,
const efi_guid_t *protocol_guid,
@@ -397,7 +401,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
struct efi_loaded_image_obj **handle_ptr,
struct efi_loaded_image **info_ptr);
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
- void **buffer);
+ void **buffer, efi_uintn_t *size);
/* Print information about all loaded images */
void efi_print_image_infos(void *pc);
diff --git a/include/mmc.h b/include/mmc.h
index d84e4fca73..1f30f71d25 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -690,6 +690,12 @@ int mmc_initialize(bd_t *bis);
int mmc_init(struct mmc *mmc);
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+int mmc_deinit(struct mmc *mmc);
+#endif
+
/**
* mmc_of_parse() - Parse the device tree to get the capabilities of the host
*
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index a095df3f54..196116b547 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -150,7 +150,7 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
debug("%s: trying to load \"%ls\" from %pD\n",
__func__, lo.label, lo.file_path);
- ret = efi_load_image_from_path(lo.file_path, &image);
+ ret = efi_load_image_from_path(lo.file_path, &image, &size);
if (ret != EFI_SUCCESS)
goto error;
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index f74f989e0a..bd8b8a17ae 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -44,7 +44,8 @@ static bool efi_is_direct_boot = true;
static volatile void *efi_gd, *app_gd;
#endif
-static int entry_count;
+/* 1 if inside U-Boot code, 0 if inside EFI payload code */
+static int entry_count = 1;
static int nesting_level;
/* GUID of the device tree table */
const efi_guid_t efi_guid_fdt = EFI_FDT_GUID;
@@ -1497,15 +1498,18 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
/**
* efi_setup_loaded_image() - initialize a loaded image
- * @info: loaded image info to be passed to the entry point of the image
- * @obj: internal object associated with the loaded image
- * @device_path: device path of the loaded image
- * @file_path: file path of the loaded image
*
* Initialize a loaded_image_info and loaded_image_info object with correct
* protocols, boot-device, etc.
*
- * Return: status code
+ * In case of an error *handle_ptr and *info_ptr are set to NULL and an error
+ * code is returned.
+ *
+ * @device_path: device path of the loaded image
+ * @file_path: file path of the loaded image
+ * @handle_ptr: handle of the loaded image
+ * @info_ptr: loaded image protocol
+ * Return: status code
*/
efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
struct efi_device_path *file_path,
@@ -1513,8 +1517,12 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
struct efi_loaded_image **info_ptr)
{
efi_status_t ret;
- struct efi_loaded_image *info;
- struct efi_loaded_image_obj *obj;
+ struct efi_loaded_image *info = NULL;
+ struct efi_loaded_image_obj *obj = NULL;
+
+ /* In case of EFI_OUT_OF_RESOURCES avoid illegal free by caller. */
+ *handle_ptr = NULL;
+ *info_ptr = NULL;
info = calloc(1, sizeof(*info));
if (!info)
@@ -1528,11 +1536,6 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
/* Add internal object to object list */
efi_add_handle(&obj->header);
- if (info_ptr)
- *info_ptr = info;
- if (handle_ptr)
- *handle_ptr = obj;
-
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
info->file_path = file_path;
info->system_table = &systab;
@@ -1578,58 +1581,87 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
goto failure;
#endif
+ if (info_ptr)
+ *info_ptr = info;
+ if (handle_ptr)
+ *handle_ptr = obj;
+
return ret;
failure:
printf("ERROR: Failure to install protocols for loaded image\n");
+ efi_delete_handle(&obj->header);
+ free(info);
return ret;
}
/**
* efi_load_image_from_path() - load an image using a file path
- * @file_path: the path of the image to load
- * @buffer: buffer containing the loaded image
*
- * Return: status code
+ * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the
+ * callers obligation to update the memory type as needed.
+ *
+ * @file_path: the path of the image to load
+ * @buffer: buffer containing the loaded image
+ * @size: size of the loaded image
+ * Return: status code
*/
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
- void **buffer)
+ void **buffer, efi_uintn_t *size)
{
struct efi_file_info *info = NULL;
struct efi_file_handle *f;
static efi_status_t ret;
+ u64 addr;
efi_uintn_t bs;
+ /* In case of failure nothing is returned */
+ *buffer = NULL;
+ *size = 0;
+
+ /* Open file */
f = efi_file_from_path(file_path);
if (!f)
return EFI_DEVICE_ERROR;
+ /* Get file size */
bs = 0;
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
&bs, info));
- if (ret == EFI_BUFFER_TOO_SMALL) {
- info = malloc(bs);
- EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
- &bs, info));
- }
- if (ret != EFI_SUCCESS)
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ ret = EFI_DEVICE_ERROR;
goto error;
+ }
- ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer);
- if (ret)
+ info = malloc(bs);
+ EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
+ info));
+ if (ret != EFI_SUCCESS)
goto error;
+ /*
+ * When reading the file we do not yet know if it contains an
+ * application, a boottime driver, or a runtime driver. So here we
+ * allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
+ * update the reservation according to the image type.
+ */
bs = info->file_size;
- EFI_CALL(ret = f->read(f, &bs, *buffer));
-
-error:
- free(info);
- EFI_CALL(f->close(f));
-
+ ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_BOOT_SERVICES_DATA,
+ efi_size_in_pages(bs), &addr);
if (ret != EFI_SUCCESS) {
- efi_free_pool(*buffer);
- *buffer = NULL;
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
}
+ /* Read file */
+ EFI_CALL(ret = f->read(f, &bs, (void *)(uintptr_t)addr));
+ if (ret != EFI_SUCCESS)
+ efi_free_pages(addr, efi_size_in_pages(bs));
+ *buffer = (void *)(uintptr_t)addr;
+ *size = bs;
+error:
+ EFI_CALL(f->close(f));
+ free(info);
return ret;
}
@@ -1656,6 +1688,7 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
efi_uintn_t source_size,
efi_handle_t *image_handle)
{
+ struct efi_device_path *dp, *fp;
struct efi_loaded_image *info = NULL;
struct efi_loaded_image_obj **image_obj =
(struct efi_loaded_image_obj **)image_handle;
@@ -1675,36 +1708,51 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
}
if (!source_buffer) {
- struct efi_device_path *dp, *fp;
-
- ret = efi_load_image_from_path(file_path, &source_buffer);
+ ret = efi_load_image_from_path(file_path, &source_buffer,
+ &source_size);
if (ret != EFI_SUCCESS)
- goto failure;
+ goto error;
/*
* split file_path which contains both the device and
* file parts:
*/
efi_dp_split_file_path(file_path, &dp, &fp);
- ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
- if (ret != EFI_SUCCESS)
- goto failure;
} else {
/* In this case, file_path is the "device" path, i.e.
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
*/
- ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info);
+ u64 addr;
+ void *dest_buffer;
+
+ ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_RUNTIME_SERVICES_CODE,
+ efi_size_in_pages(source_size), &addr);
if (ret != EFI_SUCCESS)
goto error;
+ dest_buffer = (void *)(uintptr_t)addr;
+ memcpy(dest_buffer, source_buffer, source_size);
+ source_buffer = dest_buffer;
+
+ dp = file_path;
+ fp = NULL;
}
- (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info);
- if (!(*image_obj)->entry) {
- ret = EFI_UNSUPPORTED;
- goto failure;
- }
+ ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
+ if (ret != EFI_SUCCESS)
+ goto error_invalid_image;
+ ret = efi_load_pe(*image_obj, source_buffer, info);
+ if (ret != EFI_SUCCESS)
+ goto error_invalid_image;
+ /* Update the type of the allocated memory */
+ efi_add_memory_map((uintptr_t)source_buffer,
+ efi_size_in_pages(source_size),
+ info->image_code_type, false);
info->system_table = &systab;
info->parent_handle = parent_image;
return EFI_EXIT(EFI_SUCCESS);
-failure:
+error_invalid_image:
+ /* The image is invalid. Release all associated resources. */
+ efi_free_pages((uintptr_t)source_buffer,
+ efi_size_in_pages(source_size));
efi_delete_handle(*image_handle);
*image_handle = NULL;
free(info);
@@ -1725,9 +1773,9 @@ error:
*
* Return: status code
*/
-static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
- efi_uintn_t *exit_data_size,
- u16 **exit_data)
+efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
+ efi_uintn_t *exit_data_size,
+ u16 **exit_data)
{
struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index d94982314a..98c36e798f 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -910,9 +910,17 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
return start;
}
-/*
- * Helper to split a full device path (containing both device and file
- * parts) into it's constituent parts.
+/**
+ * efi_dp_split_file_path() - split of relative file path from device path
+ *
+ * Given a device path indicating a file on a device, separate the device
+ * path in two: the device path of the actual device and the file path
+ * relative to this device.
+ *
+ * @full_path: device path including device and file path
+ * @device_path: path of the device
+ * @file_path: relative path of the file
+ * Return: status code
*/
efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
struct efi_device_path **device_path,
@@ -929,7 +937,7 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
p = efi_dp_next(p);
if (!p)
- return EFI_OUT_OF_RESOURCES;
+ return EFI_INVALID_PARAMETER;
}
fp = efi_dp_dup(p);
if (!fp)
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 4b4422205d..3a7323765b 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -641,6 +641,12 @@ static const struct efi_file_handle efi_file_handle_protocol = {
.flush = efi_file_flush,
};
+/**
+ * efi_file_from_path() - open file via device path
+ *
+ * @fp: device path
+ * @return: EFI_FILE_PROTOCOL for the file or NULL
+ */
struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
{
struct efi_simple_file_system_protocol *v;
@@ -655,10 +661,14 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
if (ret != EFI_SUCCESS)
return NULL;
- /* skip over device-path nodes before the file path: */
+ /* Skip over device-path nodes before the file path. */
while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
fp = efi_dp_next(fp);
+ /*
+ * Step through the nodes of the directory path until the actual file
+ * node is reached which is the final node in the device path.
+ */
while (fp) {
struct efi_device_path_file_path *fdp =
container_of(fp, struct efi_device_path_file_path, dp);
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index a18ce0a570..fe66e7b9ff 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -42,8 +42,8 @@ static int machines[] = {
#endif
0 };
-/*
- * Print information about a loaded image.
+/**
+ * efi_print_image_info() - print information about a loaded image
*
* If the program counter is located within the image the offset to the base
* address is shown.
@@ -51,7 +51,7 @@ static int machines[] = {
* @obj: EFI object
* @image: loaded image
* @pc: program counter (use NULL to suppress offset output)
- * @return: status code
+ * Return: status code
*/
static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
struct efi_loaded_image *image,
@@ -69,8 +69,8 @@ static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
return EFI_SUCCESS;
}
-/*
- * Print information about all loaded images.
+/**
+ * efi_print_image_infos() - print information about all loaded images
*
* @pc: program counter (use NULL to suppress offset output)
*/
@@ -90,6 +90,15 @@ void efi_print_image_infos(void *pc)
}
}
+/**
+ * efi_loader_relocate() - relocate UEFI binary
+ *
+ * @rel: pointer to the relocation table
+ * @rel_size: size of the relocation table in bytes
+ * @efi_reloc: actual load address of the image
+ * @pref_address: preferred load address of the image
+ * Return: status code
+ */
static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
unsigned long rel_size, void *efi_reloc,
unsigned long pref_address)
@@ -102,7 +111,7 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
return EFI_SUCCESS;
end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
- while (rel < end - 1 && rel->SizeOfBlock) {
+ while (rel < end && rel->SizeOfBlock) {
const uint16_t *relocs = (const uint16_t *)(rel + 1);
i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
while (i--) {
@@ -159,11 +168,12 @@ void __weak invalidate_icache_all(void)
/* If the system doesn't support icache_all flush, cross our fingers */
}
-/*
- * Determine the memory types to be used for code and data.
+/**
+ * efi_set_code_and_data_type() - determine the memory types to be used for code
+ * and data.
*
- * @loaded_image_info image descriptor
- * @image_type field Subsystem of the optional header for
+ * @loaded_image_info: image descriptor
+ * @image_type: field Subsystem of the optional header for
* Windows specific field
*/
static void efi_set_code_and_data_type(
@@ -193,13 +203,19 @@ static void efi_set_code_and_data_type(
}
}
-/*
+/**
+ * efi_load_pe() - relocate EFI binary
+ *
* This function loads all sections from a PE binary into a newly reserved
- * piece of memory. On successful load it then returns the entry point for
- * the binary. Otherwise NULL.
+ * piece of memory. On success the entry point is returned as handle->entry.
+ *
+ * @handle: loaded image handle
+ * @efi: pointer to the EFI binary
+ * @loaded_image_info: loaded image protocol
+ * Return: status code
*/
-void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
- struct efi_loaded_image *loaded_image_info)
+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info)
{
IMAGE_NT_HEADERS32 *nt;
IMAGE_DOS_HEADER *dos;
@@ -210,7 +226,6 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
const IMAGE_BASE_RELOCATION *rel;
unsigned long rel_size;
int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
- void *entry;
uint64_t image_base;
uint64_t image_size;
unsigned long virt_size = 0;
@@ -219,13 +234,13 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
dos = efi;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
printf("%s: Invalid DOS Signature\n", __func__);
- return NULL;
+ return EFI_LOAD_ERROR;
}
nt = (void *) ((char *)efi + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE) {
printf("%s: Invalid NT Signature\n", __func__);
- return NULL;
+ return EFI_LOAD_ERROR;
}
for (i = 0; machines[i]; i++)
@@ -237,7 +252,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
if (!supported) {
printf("%s: Machine type 0x%04x is not supported\n",
__func__, nt->FileHeader.Machine);
- return NULL;
+ return EFI_LOAD_ERROR;
}
/* Calculate upper virtual address boundary */
@@ -263,9 +278,9 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
if (!efi_reloc) {
printf("%s: Could not allocate %lu bytes\n",
__func__, virt_size);
- return NULL;
+ return EFI_OUT_OF_RESOURCES;
}
- entry = efi_reloc + opt->AddressOfEntryPoint;
+ handle->entry = efi_reloc + opt->AddressOfEntryPoint;
rel_size = opt->DataDirectory[rel_idx].Size;
rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
virt_size = ALIGN(virt_size, opt->SectionAlignment);
@@ -279,16 +294,16 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
if (!efi_reloc) {
printf("%s: Could not allocate %lu bytes\n",
__func__, virt_size);
- return NULL;
+ return EFI_OUT_OF_RESOURCES;
}
- entry = efi_reloc + opt->AddressOfEntryPoint;
+ handle->entry = efi_reloc + opt->AddressOfEntryPoint;
rel_size = opt->DataDirectory[rel_idx].Size;
rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
virt_size = ALIGN(virt_size, opt->SectionAlignment);
} else {
printf("%s: Invalid optional header magic %x\n", __func__,
nt->OptionalHeader.Magic);
- return NULL;
+ return EFI_LOAD_ERROR;
}
/* Load sections into RAM */
@@ -306,7 +321,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
(unsigned long)image_base) != EFI_SUCCESS) {
efi_free_pages((uintptr_t) efi_reloc,
(virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
- return NULL;
+ return EFI_LOAD_ERROR;
}
/* Flush cache */
@@ -320,5 +335,5 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
handle->reloc_base = efi_reloc;
handle->reloc_size = virt_size;
- return entry;
+ return EFI_SUCCESS;
}
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 7f4eafb2fe..c9720c9da8 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -51,6 +51,7 @@ endif
ifeq ($(CONFIG_SANDBOX)$(CONFIG_CPU_V7M)$(CONFIG_X86_64),)
obj-y += \
+efi_selftest_loadimage.o \
efi_selftest_startimage_exit.o \
efi_selftest_startimage_return.o
@@ -68,6 +69,8 @@ $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
$(obj)/efi_miniapp_file_image_return.h
+$(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
+
$(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
$(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
index 1cdd8307f4..21409aed6f 100644
--- a/lib/efi_selftest/efi_selftest_block_device.c
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -264,7 +264,7 @@ static int teardown(void)
}
if (image) {
- r = efi_free_pool(image);
+ r = boottime->free_pool(image);
if (r != EFI_SUCCESS) {
efi_st_error("Failed to free image\n");
return EFI_ST_FAILURE;
diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
index e38af7dbf8..8a0b3bc353 100644
--- a/lib/efi_selftest/efi_selftest_hii.c
+++ b/lib/efi_selftest/efi_selftest_hii.c
@@ -8,7 +8,6 @@
*/
#include <efi_selftest.h>
-#include <malloc.h>
#include "efi_selftest_hii_data.c"
#define PRINT_TESTNAME efi_st_printf("%s:\n", __func__)
@@ -192,9 +191,10 @@ static int test_hii_database_list_package_lists(void)
(unsigned int)ret);
goto out;
}
- handles = malloc(handles_size);
- if (!handles) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
goto out;
}
ret = hii_database_protocol->list_package_lists(hii_database_protocol,
@@ -205,7 +205,11 @@ static int test_hii_database_list_package_lists(void)
(unsigned int)ret);
goto out;
}
- free(handles);
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
/* STRINGS */
handles = NULL;
@@ -219,9 +223,10 @@ static int test_hii_database_list_package_lists(void)
ret = EFI_ST_FAILURE;
goto out;
}
- handles = malloc(handles_size);
- if (!handles) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
ret = EFI_ST_FAILURE;
goto out;
}
@@ -234,7 +239,11 @@ static int test_hii_database_list_package_lists(void)
ret = EFI_ST_FAILURE;
goto out;
}
- free(handles);
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
/* GUID */
handles = NULL;
@@ -248,9 +257,10 @@ static int test_hii_database_list_package_lists(void)
ret = EFI_ST_FAILURE;
goto out;
}
- handles = malloc(handles_size);
- if (!handles) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
ret = EFI_ST_FAILURE;
goto out;
}
@@ -263,7 +273,12 @@ static int test_hii_database_list_package_lists(void)
ret = EFI_ST_FAILURE;
goto out;
}
- free(handles);
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
/* KEYBOARD_LAYOUT */
handles = NULL;
@@ -277,9 +292,10 @@ static int test_hii_database_list_package_lists(void)
ret = EFI_ST_FAILURE;
goto out;
}
- handles = malloc(handles_size);
- if (!handles) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
ret = EFI_ST_FAILURE;
goto out;
}
@@ -292,7 +308,12 @@ static int test_hii_database_list_package_lists(void)
ret = EFI_ST_FAILURE;
goto out;
}
- free(handles);
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
result = EFI_ST_SUCCESS;
@@ -398,9 +419,10 @@ static int test_hii_database_find_keyboard_layouts(void)
(unsigned int)ret);
goto out;
}
- guids = malloc(guids_size);
- if (!guids) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, guids_size,
+ (void **)&guids);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
goto out;
}
ret = hii_database_protocol->find_keyboard_layouts(
@@ -410,7 +432,11 @@ static int test_hii_database_find_keyboard_layouts(void)
(unsigned int)ret);
goto out;
}
- free(guids);
+ ret = boottime->free_pool(guids);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
result = EFI_ST_SUCCESS;
@@ -479,9 +505,10 @@ static int test_hii_database_get_keyboard_layout(void)
(unsigned int)ret);
goto out;
}
- kb_layout = malloc(kb_layout_size);
- if (!kb_layout) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, kb_layout_size,
+ (void **)&kb_layout);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
goto out;
}
ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
@@ -491,7 +518,11 @@ static int test_hii_database_get_keyboard_layout(void)
(unsigned int)ret);
goto out;
}
- free(kb_layout);
+ ret = boottime->free_pool(kb_layout);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
/* current */
kb_layout = NULL;
@@ -738,9 +769,10 @@ static int test_hii_string_get_string(void)
goto out;
}
string_len += sizeof(u16);
- string = malloc(string_len);
- if (!string) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, string_len,
+ (void **)&string);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
goto out;
}
ret = hii_string_protocol->get_string(hii_string_protocol,
@@ -875,9 +907,10 @@ static int test_hii_string_get_languages(void)
(unsigned int)ret);
goto out;
}
- languages = malloc(languages_len);
- if (!languages) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
+ (void **)&languages);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
goto out;
}
ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
@@ -947,9 +980,10 @@ static int test_hii_string_get_secondary_languages(void)
(unsigned int)ret);
goto out;
}
- languages = malloc(languages_len);
- if (!languages) {
- efi_st_error("malloc failed\n");
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
+ (void **)&languages);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
goto out;
}
ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
diff --git a/lib/efi_selftest/efi_selftest_loadimage.c b/lib/efi_selftest/efi_selftest_loadimage.c
new file mode 100644
index 0000000000..96faa67a15
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_loadimage.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_loadimage
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the LoadImage and StartImage boot service.
+ *
+ * The efi_selftest_miniapp_exit.efi application is loaded via a file device
+ * path and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the efi_selftest_miniapp_exit.efi application */
+#include "efi_miniapp_file_image_exit.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+#define FILE_NAME L"app.efi"
+#define VOLUME_NAME L"EfiDisk"
+
+static struct efi_boot_services *boottime;
+static efi_handle_t handle_image;
+static efi_handle_t handle_volume;
+
+static const efi_guid_t guid_device_path = DEVICE_PATH_GUID;
+static const efi_guid_t guid_simple_file_system_protocol =
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static const efi_guid_t guid_file_info = EFI_FILE_INFO_GUID;
+static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+ size_t length;
+ struct line lines[];
+};
+
+/* File info including file name */
+struct file_info {
+ struct efi_file_info info;
+ u16 file_name[sizeof(FILE_NAME)];
+};
+
+/* File system info including volume name */
+struct file_system_info {
+ struct efi_file_system_info info;
+ u16 file_name[sizeof(VOLUME_NAME)];
+};
+
+/* Compressed file image */
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Pointer to decompressed file image */
+static u8 *image;
+
+/* File info */
+static struct file_info priv_file_info = {
+ {
+ .size = sizeof(struct file_info),
+ .attribute = EFI_FILE_READ_ONLY,
+ },
+ FILE_NAME,
+};
+
+/* Pointer to file info */
+struct efi_file_info *file_info = &priv_file_info.info;
+
+/* Volume device path */
+static struct {
+ struct efi_device_path_vendor vendor;
+ struct efi_device_path end;
+} __packed dp_volume = {
+ .vendor = {
+ .dp = {
+ .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+ .length = sizeof(struct efi_device_path_vendor),
+ },
+ .guid = EFI_GUID(0x4f9a0ebf, 0xa179, 0x88a6, 0x25, 0x68,
+ 0x10, 0x72, 0xb1, 0x93, 0x51, 0x71),
+ },
+ .end = {
+ .type = DEVICE_PATH_TYPE_END,
+ .sub_type = DEVICE_PATH_SUB_TYPE_END,
+ .length = sizeof(struct efi_device_path),
+ }
+};
+
+/* File device path */
+static struct {
+ struct efi_device_path_vendor vendor;
+ struct efi_device_path path;
+ u16 file[sizeof(FILE_NAME)];
+ struct efi_device_path end;
+} __packed dp_file = {
+ .vendor = {
+ .dp = {
+ .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+ .length = sizeof(struct efi_device_path_vendor),
+ },
+ .guid = EFI_GUID(0x4f9a0ebf, 0xa179, 0x88a6, 0x25, 0x68,
+ 0x10, 0x72, 0xb1, 0x93, 0x51, 0x71),
+ },
+ .path = {
+ .type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
+ .length = sizeof(struct efi_device_path) + sizeof(dp_file.file),
+ },
+ .file = FILE_NAME,
+ .end = {
+ .type = DEVICE_PATH_TYPE_END,
+ .sub_type = DEVICE_PATH_SUB_TYPE_END,
+ .length = sizeof(struct efi_device_path),
+ }
+};
+
+/* File system info */
+static struct file_system_info priv_file_system_info = {
+ {
+ .size = sizeof(struct file_system_info),
+ .read_only = true,
+ .volume_size = 0x100000,
+ .free_space = 0x0,
+ .block_size = 0x200,
+ },
+ VOLUME_NAME
+};
+
+/* Pointer to file system info */
+static struct efi_file_system_info *file_system_info =
+ &priv_file_system_info.info;
+
+/* Forward definitions of file and file system functions */
+static efi_status_t EFIAPI open_volume
+ (struct efi_simple_file_system_protocol *this,
+ struct efi_file_handle **root);
+
+static efi_status_t EFIAPI open
+ (struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode, u64 attributes);
+
+static efi_status_t EFIAPI close(struct efi_file_handle *this);
+
+static efi_status_t EFIAPI delete(struct efi_file_handle *this);
+
+static efi_status_t EFIAPI read
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer);
+
+static efi_status_t EFIAPI write
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer);
+
+static efi_status_t EFIAPI getpos(struct efi_file_handle *this, u64 *pos);
+
+static efi_status_t EFIAPI setpos(struct efi_file_handle *this, u64 pos);
+
+static efi_status_t EFIAPI getinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t *buffer_size, void *buffer);
+
+static efi_status_t EFIAPI setinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t buffer_size, void *buffer);
+
+static efi_status_t EFIAPI flush(struct efi_file_handle *this);
+
+/* Internal information about status of file system */
+static struct {
+ /* Difference of volume open count minus volume close count */
+ int volume_open_count;
+ /* Difference of file open count minus file close count */
+ int file_open_count;
+ /* File size */
+ u64 file_size;
+ /* Current position in file */
+ u64 file_pos;
+} priv;
+
+/* EFI_FILE_PROTOCOL for file */
+static struct efi_file_handle file = {
+ .rev = 0x00010000,
+ .open = open,
+ .close = close,
+ .delete = delete,
+ .read = read,
+ .write = write,
+ .getpos = getpos,
+ .setpos = setpos,
+ .getinfo = getinfo,
+ .setinfo = setinfo,
+ .flush = flush,
+};
+
+/* EFI_FILE_PROTOCOL for root directory */
+static struct efi_file_handle volume = {
+ .rev = 0x00010000,
+ .open = open,
+ .close = close,
+ .delete = delete,
+ .read = read,
+ .write = write,
+ .getpos = getpos,
+ .setpos = setpos,
+ .getinfo = getinfo,
+ .setinfo = setinfo,
+ .flush = flush,
+};
+
+/* EFI_SIMPLE_FILE_SYSTEM_PROTOCOL of the block device */
+struct efi_simple_file_system_protocol file_system = {
+ .rev = 0x00010000,
+ .open_volume = open_volume,
+};
+
+static efi_status_t EFIAPI open_volume
+ (struct efi_simple_file_system_protocol *this,
+ struct efi_file_handle **root)
+{
+ if (this != &file_system || !root)
+ return EFI_INVALID_PARAMETER;
+
+ *root = &volume;
+ priv.volume_open_count++;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI open
+ (struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode, u64 attributes)
+{
+ if (this != &volume)
+ return EFI_INVALID_PARAMETER;
+
+ *new_handle = &file;
+ priv.file_pos = 0;
+ priv.file_open_count++;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI close(struct efi_file_handle *this)
+{
+ if (this == &file)
+ priv.file_open_count--;
+ else if (this == &volume)
+ priv.volume_open_count--;
+ else
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI delete(struct efi_file_handle *this)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI read
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ if (priv.file_pos >= img.length)
+ *buffer_size = 0;
+ else if (priv.file_pos + *buffer_size > img.length)
+ *buffer_size = img.length - priv.file_pos;
+
+ boottime->copy_mem(buffer, &image[priv.file_pos], *buffer_size);
+ priv.file_pos += *buffer_size;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI write
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI getpos(struct efi_file_handle *this, u64 *pos)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ *pos = priv.file_pos;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI setpos(struct efi_file_handle *this, u64 pos)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ priv.file_pos = pos;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI getinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ if (this == &file) {
+ if (efi_st_memcmp(info_type, &guid_file_info,
+ sizeof(efi_guid_t)))
+ return EFI_INVALID_PARAMETER;
+ if (*buffer_size >= sizeof(struct file_info)) {
+ boottime->copy_mem(buffer, file_info,
+ sizeof(struct file_info));
+ } else {
+ *buffer_size = sizeof(struct file_info);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ } else if (this == &volume) {
+ if (efi_st_memcmp(info_type, &guid_file_system_info,
+ sizeof(efi_guid_t)))
+ return EFI_INVALID_PARAMETER;
+ if (*buffer_size >= sizeof(struct file_system_info)) {
+ boottime->copy_mem(buffer, file_system_info,
+ sizeof(struct file_system_info));
+ } else {
+ *buffer_size = sizeof(struct file_system_info);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI setinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t buffer_size, void *buffer)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI flush(struct efi_file_handle *this)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+ (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ priv.file_size = img.length;
+ file_info->file_size = img.length;
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Decompress application image and provide a handle for the in memory block
+ * device.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ handle_image = handle;
+ boottime = systable->boottime;
+
+ /* Load the application image into memory */
+ decompress(&image);
+
+ ret = boottime->install_protocol_interface
+ (&handle_volume, &guid_device_path, EFI_NATIVE_INTERFACE,
+ &dp_volume);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install device path\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_protocol_interface
+ (&handle_volume, &guid_simple_file_system_protocol,
+ EFI_NATIVE_INTERFACE, &file_system);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install simple file system protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Uninstall protocols and free memory.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret = EFI_ST_SUCCESS;
+
+ if (handle_volume) {
+ ret = boottime->uninstall_protocol_interface
+ (handle_volume, &guid_simple_file_system_protocol,
+ &file_system);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error
+ ("Failed to uninstall simple file system protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface
+ (handle_volume, &guid_device_path, &dp_volume);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error
+ ("Failed to uninstall device path protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ if (image) {
+ ret = boottime->free_pool(image);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to free image\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+
+ ret = boottime->load_image(false, handle_image, &dp_file.vendor.dp,
+ NULL, 0, &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to load image\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->start_image(handle, NULL, NULL);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("Wrong return value from application\n");
+ return EFI_ST_FAILURE;
+ }
+
+ if (priv.file_open_count) {
+ efi_st_error("File open count = %d, expected 0\n",
+ priv.file_open_count);
+ return EFI_ST_FAILURE;
+ }
+ if (priv.volume_open_count) {
+ efi_st_error("Volume open count = %d, expected 0\n",
+ priv.volume_open_count);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(loadimage) = {
+ .name = "load image from file",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_startimage_exit.c b/lib/efi_selftest/efi_selftest_startimage_exit.c
index 0d9e16437a..fa4b7d4a9b 100644
--- a/lib/efi_selftest/efi_selftest_startimage_exit.c
+++ b/lib/efi_selftest/efi_selftest_startimage_exit.c
@@ -103,7 +103,7 @@ static int teardown(void)
efi_status_t r = EFI_ST_SUCCESS;
if (image) {
- r = efi_free_pool(image);
+ r = boottime->free_pool(image);
if (r != EFI_SUCCESS) {
efi_st_error("Failed to free image\n");
return EFI_ST_FAILURE;
diff --git a/lib/efi_selftest/efi_selftest_startimage_return.c b/lib/efi_selftest/efi_selftest_startimage_return.c
index 3c6249fdf1..fabf53d983 100644
--- a/lib/efi_selftest/efi_selftest_startimage_return.c
+++ b/lib/efi_selftest/efi_selftest_startimage_return.c
@@ -103,7 +103,7 @@ static int teardown(void)
efi_status_t r = EFI_ST_SUCCESS;
if (image) {
- r = efi_free_pool(image);
+ r = boottime->free_pool(image);
if (r != EFI_SUCCESS) {
efi_st_error("Failed to free image\n");
return EFI_ST_FAILURE;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index de5db1aa5c..1b6c154d8d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -288,6 +288,8 @@ static char *string16(char *buf, char *end, u16 *s, int field_width,
for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) {
s32 s = utf16_get(&str);
+ if (s < 0)
+ s = '?';
utf8_put(s, &buf);
}
for (; len < field_width; --field_width)
diff --git a/test/unicode_ut.c b/test/unicode_ut.c
index 84fc9a3b53..8e1efe6f69 100644
--- a/test/unicode_ut.c
+++ b/test/unicode_ut.c
@@ -50,7 +50,7 @@ static const char j1[] = {0x6a, 0x31, 0xa1, 0x6c, 0x00};
static const char j2[] = {0x6a, 0x32, 0xc3, 0xc3, 0x6c, 0x00};
static const char j3[] = {0x6a, 0x33, 0xf0, 0x90, 0xf0, 0x00};
-static int ut_u16_strdup(struct unit_test_state *uts)
+static int unicode_test_u16_strdup(struct unit_test_state *uts)
{
u16 *copy = u16_strdup(c4);
@@ -59,9 +59,9 @@ static int ut_u16_strdup(struct unit_test_state *uts)
free(copy);
return 0;
}
-UNICODE_TEST(ut_u16_strdup);
+UNICODE_TEST(unicode_test_u16_strdup);
-static int ut_u16_strcpy(struct unit_test_state *uts)
+static int unicode_test_u16_strcpy(struct unit_test_state *uts)
{
u16 *r;
u16 copy[10];
@@ -71,11 +71,11 @@ static int ut_u16_strcpy(struct unit_test_state *uts)
ut_assert(!memcmp(copy, c1, sizeof(c1)));
return 0;
}
-UNICODE_TEST(ut_u16_strcpy);
+UNICODE_TEST(unicode_test_u16_strcpy);
/* U-Boot uses UTF-16 strings in the EFI context only. */
#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
-static int ut_string16(struct unit_test_state *uts)
+static int unicode_test_string16(struct unit_test_state *uts)
{
char buf[20];
@@ -113,10 +113,10 @@ static int ut_string16(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_string16);
+UNICODE_TEST(unicode_test_string16);
#endif
-static int ut_utf8_get(struct unit_test_state *uts)
+static int unicode_test_utf8_get(struct unit_test_state *uts)
{
const char *s;
s32 code;
@@ -152,9 +152,9 @@ static int ut_utf8_get(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf8_get);
+UNICODE_TEST(unicode_test_utf8_get);
-static int ut_utf8_put(struct unit_test_state *uts)
+static int unicode_test_utf8_put(struct unit_test_state *uts)
{
char buffer[8] = { 0, };
char *pos;
@@ -190,9 +190,9 @@ static int ut_utf8_put(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf8_put);
+UNICODE_TEST(unicode_test_utf8_put);
-static int ut_utf8_utf16_strlen(struct unit_test_state *uts)
+static int unicode_test_utf8_utf16_strlen(struct unit_test_state *uts)
{
ut_asserteq(6, utf8_utf16_strlen(d1));
ut_asserteq(8, utf8_utf16_strlen(d2));
@@ -206,9 +206,9 @@ static int ut_utf8_utf16_strlen(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf8_utf16_strlen);
+UNICODE_TEST(unicode_test_utf8_utf16_strlen);
-static int ut_utf8_utf16_strnlen(struct unit_test_state *uts)
+static int unicode_test_utf8_utf16_strnlen(struct unit_test_state *uts)
{
ut_asserteq(3, utf8_utf16_strnlen(d1, 3));
ut_asserteq(6, utf8_utf16_strnlen(d1, 13));
@@ -224,7 +224,7 @@ static int ut_utf8_utf16_strnlen(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf8_utf16_strnlen);
+UNICODE_TEST(unicode_test_utf8_utf16_strnlen);
/**
* ut_u16_strcmp() - Compare to u16 strings.
@@ -234,7 +234,7 @@ UNICODE_TEST(ut_utf8_utf16_strnlen);
* @count: number of u16 to compare
* Return: -1 if a1 < a2, 0 if a1 == a2, 1 if a1 > a2
*/
-static int ut_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
+static int unicode_test_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
{
for (; (*a1 || *a2) && count; ++a1, ++a2, --count) {
if (*a1 < *a2)
@@ -245,7 +245,7 @@ static int ut_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
return 0;
}
-static int ut_utf8_utf16_strcpy(struct unit_test_state *uts)
+static int unicode_test_utf8_utf16_strcpy(struct unit_test_state *uts)
{
u16 buf[16];
u16 *pos;
@@ -253,44 +253,44 @@ static int ut_utf8_utf16_strcpy(struct unit_test_state *uts)
pos = buf;
utf8_utf16_strcpy(&pos, d1);
ut_asserteq(6, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, c1, SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, c1, SIZE_MAX));
pos = buf;
utf8_utf16_strcpy(&pos, d2);
ut_asserteq(8, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, c2, SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX));
pos = buf;
utf8_utf16_strcpy(&pos, d3);
ut_asserteq(3, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, c3, SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, c3, SIZE_MAX));
pos = buf;
utf8_utf16_strcpy(&pos, d4);
ut_asserteq(6, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, c4, SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX));
/* Illegal utf-8 strings */
pos = buf;
utf8_utf16_strcpy(&pos, j1);
ut_asserteq(4, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, L"j1?l", SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, L"j1?l", SIZE_MAX));
pos = buf;
utf8_utf16_strcpy(&pos, j2);
ut_asserteq(4, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, L"j2?l", SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, L"j2?l", SIZE_MAX));
pos = buf;
utf8_utf16_strcpy(&pos, j3);
ut_asserteq(3, pos - buf);
- ut_assert(!ut_u16_strcmp(buf, L"j3?", SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, L"j3?", SIZE_MAX));
return 0;
}
-UNICODE_TEST(ut_utf8_utf16_strcpy);
+UNICODE_TEST(unicode_test_utf8_utf16_strcpy);
-int ut_utf8_utf16_strncpy(struct unit_test_state *uts)
+static int unicode_test_utf8_utf16_strncpy(struct unit_test_state *uts)
{
u16 buf[16];
u16 *pos;
@@ -300,41 +300,41 @@ int ut_utf8_utf16_strncpy(struct unit_test_state *uts)
utf8_utf16_strncpy(&pos, d1, 4);
ut_asserteq(4, pos - buf);
ut_assert(!buf[4]);
- ut_assert(!ut_u16_strcmp(buf, c1, 4));
+ ut_assert(!unicode_test_u16_strcmp(buf, c1, 4));
pos = buf;
memset(buf, 0, sizeof(buf));
utf8_utf16_strncpy(&pos, d2, 10);
ut_asserteq(8, pos - buf);
ut_assert(buf[4]);
- ut_assert(!ut_u16_strcmp(buf, c2, SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX));
pos = buf;
memset(buf, 0, sizeof(buf));
utf8_utf16_strncpy(&pos, d3, 2);
ut_asserteq(2, pos - buf);
ut_assert(!buf[2]);
- ut_assert(!ut_u16_strcmp(buf, c3, 2));
+ ut_assert(!unicode_test_u16_strcmp(buf, c3, 2));
pos = buf;
memset(buf, 0, sizeof(buf));
utf8_utf16_strncpy(&pos, d4, 2);
ut_asserteq(4, pos - buf);
ut_assert(!buf[4]);
- ut_assert(!ut_u16_strcmp(buf, c4, 4));
+ ut_assert(!unicode_test_u16_strcmp(buf, c4, 4));
pos = buf;
memset(buf, 0, sizeof(buf));
utf8_utf16_strncpy(&pos, d4, 10);
ut_asserteq(6, pos - buf);
ut_assert(buf[5]);
- ut_assert(!ut_u16_strcmp(buf, c4, SIZE_MAX));
+ ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX));
return 0;
}
-UNICODE_TEST(ut_utf8_utf16_strncpy);
+UNICODE_TEST(unicode_test_utf8_utf16_strncpy);
-static int ut_utf16_get(struct unit_test_state *uts)
+static int unicode_test_utf16_get(struct unit_test_state *uts)
{
const u16 *s;
s32 code;
@@ -358,9 +358,9 @@ static int ut_utf16_get(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf16_get);
+UNICODE_TEST(unicode_test_utf16_get);
-static int ut_utf16_put(struct unit_test_state *uts)
+static int unicode_test_utf16_put(struct unit_test_state *uts)
{
u16 buffer[4] = { 0, };
u16 *pos;
@@ -386,9 +386,9 @@ static int ut_utf16_put(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf16_put);
+UNICODE_TEST(unicode_test_utf16_put);
-int ut_utf16_strnlen(struct unit_test_state *uts)
+static int unicode_test_utf16_strnlen(struct unit_test_state *uts)
{
ut_asserteq(3, utf16_strnlen(c1, 3));
ut_asserteq(6, utf16_strnlen(c1, 13));
@@ -404,9 +404,9 @@ int ut_utf16_strnlen(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf16_strnlen);
+UNICODE_TEST(unicode_test_utf16_strnlen);
-int ut_utf16_utf8_strlen(struct unit_test_state *uts)
+static int unicode_test_utf16_utf8_strlen(struct unit_test_state *uts)
{
ut_asserteq(6, utf16_utf8_strlen(c1));
ut_asserteq(9, utf16_utf8_strlen(c2));
@@ -420,9 +420,9 @@ int ut_utf16_utf8_strlen(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf16_utf8_strlen);
+UNICODE_TEST(unicode_test_utf16_utf8_strlen);
-int ut_utf16_utf8_strnlen(struct unit_test_state *uts)
+static int unicode_test_utf16_utf8_strnlen(struct unit_test_state *uts)
{
ut_asserteq(3, utf16_utf8_strnlen(c1, 3));
ut_asserteq(6, utf16_utf8_strnlen(c1, 13));
@@ -432,9 +432,9 @@ int ut_utf16_utf8_strnlen(struct unit_test_state *uts)
ut_asserteq(12, utf16_utf8_strnlen(c4, 3));
return 0;
}
-UNICODE_TEST(ut_utf16_utf8_strnlen);
+UNICODE_TEST(unicode_test_utf16_utf8_strnlen);
-int ut_utf16_utf8_strcpy(struct unit_test_state *uts)
+static int unicode_test_utf16_utf8_strcpy(struct unit_test_state *uts)
{
char buf[16];
char *pos;
@@ -477,9 +477,9 @@ int ut_utf16_utf8_strcpy(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf16_utf8_strcpy);
+UNICODE_TEST(unicode_test_utf16_utf8_strcpy);
-int ut_utf16_utf8_strncpy(struct unit_test_state *uts)
+static int unicode_test_utf16_utf8_strncpy(struct unit_test_state *uts)
{
char buf[16];
char *pos;
@@ -521,9 +521,9 @@ int ut_utf16_utf8_strncpy(struct unit_test_state *uts)
return 0;
}
-UNICODE_TEST(ut_utf16_utf8_strncpy);
+UNICODE_TEST(unicode_test_utf16_utf8_strncpy);
-int ut_utf_to_lower(struct unit_test_state *uts)
+static int unicode_test_utf_to_lower(struct unit_test_state *uts)
{
ut_asserteq('@', utf_to_lower('@'));
ut_asserteq('a', utf_to_lower('A'));
@@ -538,9 +538,9 @@ int ut_utf_to_lower(struct unit_test_state *uts)
#endif
return 0;
}
-UNICODE_TEST(ut_utf_to_lower);
+UNICODE_TEST(unicode_test_utf_to_lower);
-int ut_utf_to_upper(struct unit_test_state *uts)
+static int unicode_test_utf_to_upper(struct unit_test_state *uts)
{
ut_asserteq('`', utf_to_upper('`'));
ut_asserteq('A', utf_to_upper('a'));
@@ -555,7 +555,7 @@ int ut_utf_to_upper(struct unit_test_state *uts)
#endif
return 0;
}
-UNICODE_TEST(ut_utf_to_upper);
+UNICODE_TEST(unicode_test_utf_to_upper);
int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{