Merge tag 'efi-2023-10-rc4' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request efi-2023-10-rc4

Documentation:

* describe TPL/VPL/SPL boot
* Add support for sphinx-prompt and convert TI K3 to use it
* board: sdm845: Explicitly add boot.img flashing command

EFI:

* remove handle from events when deleting it

Others:

* fix gpt sub-commands setenv and enumerate
* add a parameter check in hash_calculate()
diff --git a/cmd/gpt.c b/cmd/gpt.c
index 007a68e..964056b 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -691,12 +691,13 @@
 		int ret;
 		int i;
 
+		if (part_drv->test(desc))
+			continue;
+
 		for (i = 1; i < part_drv->max_entries; i++) {
 			ret = part_drv->get_info(desc, i, &pinfo);
-			if (ret) {
-				/* no more entries in table */
-				break;
-			}
+			if (ret)
+				continue;
 
 			ptr = &part_list[str_len];
 			tmp_len = strlen((const char *)pinfo.name);
@@ -711,9 +712,10 @@
 			/* One byte for space(" ") delimiter */
 			ptr[tmp_len] = ' ';
 		}
+		if (*part_list)
+			part_list[strlen(part_list) - 1] = 0;
+		break;
 	}
-	if (*part_list)
-		part_list[strlen(part_list) - 1] = 0;
 	debug("setenv gpt_partition_list %s\n", part_list);
 
 	return env_set("gpt_partition_list", part_list);
@@ -742,7 +744,7 @@
 	if (ret)
 		goto fail;
 
-	ret = env_set_ulong("gpt_partition_entry", i);
+	ret = env_set_hex("gpt_partition_entry", i);
 	if (ret)
 		goto fail;
 
@@ -786,10 +788,8 @@
 
 		for (i = 1; i < part_drv->max_entries; i++) {
 			ret = part_drv->get_info(desc, i, &pinfo);
-			if (ret) {
-				/* no more entries in table */
-				break;
-			}
+			if (ret)
+				continue;
 
 			if (!strcmp(name, (const char *)pinfo.name)) {
 				/* match found, setup environment variables */
diff --git a/doc/board/qualcomm/sdm845.rst b/doc/board/qualcomm/sdm845.rst
index 71879c2..d3f218e 100644
--- a/doc/board/qualcomm/sdm845.rst
+++ b/doc/board/qualcomm/sdm845.rst
@@ -38,9 +38,10 @@
 with appended dtb, so let's mimic linux to satisfy stock bootloader.
 
 Boards
-------------
+------
+
 starqlte
-^^^^^^^^^^^^
+^^^^^^^^
 
 The starqltechn is a production board for Samsung S9 (SM-G9600) phone,
 based on the Qualcomm SDM845 SoC.
@@ -149,7 +150,11 @@
 	mkbootimg --kernel u-boot.bin.gz-dtb --ramdisk db845c.itb \
 	--output boot.img --pagesize 4096 --base 0x80000000
 
+- Flash boot.img using db845c fastboot method:
+
+  .. code-block:: bash
+
-- Flash boot.img using db845c fastboot method.
+      sudo fastboot flash boot boot.img
 
 More information can be found on the `DragonBoard 845c page`_.
 
diff --git a/doc/board/ti/k3.rst b/doc/board/ti/k3.rst
index 1175b77..ec44735 100644
--- a/doc/board/ti/k3.rst
+++ b/doc/board/ti/k3.rst
@@ -194,13 +194,13 @@
 .. k3_rst_include_end_common_env_vars_desc
 
 .. k3_rst_include_start_common_env_vars_defn
-.. code-block:: bash
+.. prompt:: bash
 
- $ export CC32=arm-linux-gnueabihf-
- $ export CC64=aarch64-linux-gnu-
- $ export LNX_FW_PATH=path/to/ti-linux-firmware
- $ export TFA_PATH=path/to/trusted-firmware-a
- $ export OPTEE_PATH=path/to/optee_os
+ export CC32=arm-linux-gnueabihf-
+ export CC64=aarch64-linux-gnu-
+ export LNX_FW_PATH=path/to/ti-linux-firmware
+ export TFA_PATH=path/to/trusted-firmware-a
+ export OPTEE_PATH=path/to/optee_os
 .. k3_rst_include_end_common_env_vars_defn
 
 We will also need some common environment variables set up for the various
@@ -244,11 +244,11 @@
    uses the split binary flow)
 
 .. k3_rst_include_start_build_steps_spl_r5
-.. code-block:: bash
+.. prompt:: bash
 
- $ # inside u-boot source
- $ make $UBOOT_CFG_CORTEXR
- $ make CROSS_COMPILE=$CC32 BINMAN_INDIRS=$LNX_FW_PATH
+ # inside u-boot source
+ make $UBOOT_CFG_CORTEXR
+ make CROSS_COMPILE=$CC32 BINMAN_INDIRS=$LNX_FW_PATH
 .. k3_rst_include_end_build_steps_spl_r5
 
 At this point you should have all the needed binaries to boot the wakeup
@@ -280,11 +280,11 @@
    application cores on the main domain.
 
 .. k3_rst_include_start_build_steps_tfa
-.. code-block:: bash
+.. prompt:: bash
 
- $ # inside trusted-firmware-a source
- $ make CROSS_COMPILE=$CC64 ARCH=aarch64 PLAT=k3 SPD=opteed $TFA_EXTRA_ARGS \
-        TARGET_BOARD=$TFA_BOARD
+ # inside trusted-firmware-a source
+ make CROSS_COMPILE=$CC64 ARCH=aarch64 PLAT=k3 SPD=opteed $TFA_EXTRA_ARGS \
+      TARGET_BOARD=$TFA_BOARD
 .. k3_rst_include_end_build_steps_tfa
 
 Typically all `j7*` devices will use `TARGET_BOARD=generic` or `TARGET_BOARD
@@ -296,11 +296,11 @@
    using the TrustZone technology built into the core.
 
 .. k3_rst_include_start_build_steps_optee
-.. code-block:: bash
+.. prompt:: bash
 
- $ # inside optee_os source
- $ make CROSS_COMPILE=$CC32 CROSS_COMPILE64=$CC64 CFG_ARM64_core=y $OPTEE_EXTRA_ARGS \
-         PLATFORM=$OPTEE_PLATFORM
+ # inside optee_os source
+ make CROSS_COMPILE=$CC32 CROSS_COMPILE64=$CC64 CFG_ARM64_core=y $OPTEE_EXTRA_ARGS \
+       PLATFORM=$OPTEE_PLATFORM
 .. k3_rst_include_end_build_steps_optee
 
 4. Finally, after TF-A has initialized the main domain and OP-TEE has
@@ -308,11 +308,11 @@
    64bit core in the main domain.
 
 .. k3_rst_include_start_build_steps_uboot
-.. code-block:: bash
+.. prompt:: bash
 
- $ # inside u-boot source
- $ make $UBOOT_CFG_CORTEXA
- $ make CROSS_COMPILE=$CC64 BINMAN_INDIRS=$LNX_FW_PATH \
+ # inside u-boot source
+ make $UBOOT_CFG_CORTEXA
+ make CROSS_COMPILE=$CC64 BINMAN_INDIRS=$LNX_FW_PATH \
         BL31=$TFA_PATH/build/k3/$TFA_BOARD/release/bl31.bin \
         TEE=$OPTEE_PATH/out/arm-plat-k3/core/tee-raw.bin
 .. k3_rst_include_end_build_steps_uboot
@@ -407,14 +407,14 @@
   be passing to mkimage for signing the fitImage and embedding the key in
   the u-boot dtb.
 
-  .. code-block:: bash
+  .. prompt:: bash
 
     mkimage -r -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K
     $UBOOT_PATH/build/a72/dts/dt.dtb
 
   For signing a secondary platform, pass the -K parameter to that DTB
 
-  .. code-block:: bash
+  .. prompt:: bash
 
     mkimage -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K
     $UBOOT_PATH/build/a72/arch/arm/dts/k3-j721e-sk.dtb
@@ -473,10 +473,11 @@
 
 **Writing to MMC/EMMC**
 
-.. code-block::
+.. prompt:: bash
+  :prompts: =>
 
-  => env export -t $loadaddr <list of variables>
-  => fatwrite mmc ${mmcdev} ${loadaddr} ${bootenvfile} ${filesize}
+  env export -t $loadaddr <list of variables>
+  fatwrite mmc ${mmcdev} ${loadaddr} ${bootenvfile} ${filesize}
 
 **Reading from MMC/EMMC**
 
@@ -486,10 +487,11 @@
 If manually needs to be done then the environment can be read from the
 filesystem and then imported
 
-.. code-block::
+.. prompt:: bash
+  :prompts: =>
 
-  => fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
-  => env import -t ${loadaddr} ${filesize}
+  fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
+  env import -t ${loadaddr} ${filesize}
 
 .. _k3_rst_refer_openocd:
 
@@ -546,7 +548,7 @@
   box support by OpenOCD. The board-specific documentation will
   cover the details and any adapter/dongle recommendations.
 
-.. code-block:: bash
+.. prompt:: bash
 
  openocd -v
 
@@ -564,21 +566,21 @@
 other package managers. Please refer to the `OpenOCD Documentation
 <https://openocd.org/>`_ for more recent installation steps.
 
-.. code-block:: bash
+.. prompt:: bash
 
-  $ # Check the packages to be installed: needs deb-src in sources.list
-  $ sudo apt build-dep openocd
-  $ # The following list is NOT complete - please check the latest
-  $ sudo apt-get install libtool pkg-config texinfo libusb-dev \
+  # Check the packages to be installed: needs deb-src in sources.list
+  sudo apt build-dep openocd
+  # The following list is NOT complete - please check the latest
+  sudo apt-get install libtool pkg-config texinfo libusb-dev \
     libusb-1.0.0-dev libftdi-dev libhidapi-dev autoconf automake
-  $ git clone https://github.com/openocd-org/openocd.git openocd
-  $ cd openocd
-  $ git submodule init
-  $ git submodule update
-  $ ./bootstrap
-  $ ./configure --prefix=/usr/local/
-  $ make -j`nproc`
-  $ sudo make install
+  git clone https://github.com/openocd-org/openocd.git openocd
+  cd openocd
+  git submodule init
+  git submodule update
+  ./bootstrap
+  ./configure --prefix=/usr/local/
+  make -j`nproc`
+  sudo make install
 
 .. note::
 
@@ -594,28 +596,28 @@
 if building from a source, ensure that the udev rules are installed
 correctly to ensure a sane system.
 
-.. code-block:: bash
+.. prompt:: bash
 
   # Go to the OpenOCD source directory
-  $ cd openocd
-  # Copy the udev rules to the correct system location
-  $ sudo cp ./contrib/60-openocd.rules \
+  cd openocd
+  Copy the udev rules to the correct system location
+  sudo cp ./contrib/60-openocd.rules \
       ./src/jtag/drivers/libjaylink/contrib/99-libjaylink.rules \
       /etc/udev/rules.d/
   # Get Udev to load the new rules up
-  $ sudo udevadm control --reload-rules
+  sudo udevadm control --reload-rules
   # Use the new rules on existing connected devices
-  $ sudo udevadm trigger
+  sudo udevadm trigger
 
 Step 2: Setup GDB
 ^^^^^^^^^^^^^^^^^
 
 Most systems come with gdb-multiarch package.
 
-.. code-block:: bash
+.. prompt:: bash
 
   # Install gdb-multiarch package
-  $ sudo apt-get install gdb-multiarch
+  sudo apt-get install gdb-multiarch
 
 Though using GDB natively is normal, developers with interest in using IDE
 may find a few of these interesting:
@@ -828,7 +830,7 @@
 
 .. k3_rst_include_start_openocd_cfg_XDS110
 
-.. code-block:: bash
+.. prompt:: bash
 
   openocd -f board/{board_of_choice}.cfg
 
@@ -842,7 +844,7 @@
   <https://github.com/openocd-org/openocd/blob/master/tcl/target/ti_k3.cfg#L59>`_
   to decide if the SoC is supported or not.
 
-.. code-block:: bash
+.. prompt:: bash
 
   openocd -f openocd_connect.cfg
 
@@ -917,7 +919,7 @@
 GDB-based IDE. To start up GDB in the terminal, run the following
 command.
 
-.. code-block:: bash
+.. prompt:: bash
 
   gdb-multiarch
 
diff --git a/doc/conf.py b/doc/conf.py
index 00f2413..5e2ff1c 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -39,7 +39,7 @@
 extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include',
               'kfigure', 'sphinx.ext.ifconfig', # 'automarkup',
               'maintainers_include', 'sphinx.ext.autosectionlabel',
-              'kernel_abi', 'kernel_feat']
+              'kernel_abi', 'kernel_feat', 'sphinx-prompt']
 
 #
 # cdomain is badly broken in Sphinx 3+.  Leaving it out generates *most*
diff --git a/doc/sphinx/requirements.txt b/doc/sphinx/requirements.txt
index 4f411f7..6ccbe52 100644
--- a/doc/sphinx/requirements.txt
+++ b/doc/sphinx/requirements.txt
@@ -15,6 +15,7 @@
 six==1.16.0
 snowballstemmer==2.2.0
 Sphinx==3.4.3
+sphinx-prompt==1.5.0
 sphinx-rtd-theme==1.0.0
 sphinxcontrib-applehelp==1.0.2
 sphinxcontrib-devhelp==1.0.2
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 3326ec8..f45a7f5 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -4,6 +4,7 @@
 .. toctree::
    :maxdepth: 1
 
+   spl_boot
    blkmap
    dfu
    environment
diff --git a/doc/usage/spl_boot.rst b/doc/usage/spl_boot.rst
new file mode 100644
index 0000000..93419f1
--- /dev/null
+++ b/doc/usage/spl_boot.rst
@@ -0,0 +1,321 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Booting from TPL/SPL
+====================
+
+The main U-Boot binary may be too large to be loaded directly by the Boot ROM.
+This was the original driver for splitting up U-Boot into multiple boot stages.
+
+U-Boot typically goes through the following boot phases where TPL, VPL, and SPL
+are optional. While many boards use SPL only few use TPL.
+
+TPL
+   Tertiary Program Loader. Very early init, as tiny as possible. This loads SPL
+   (or VPL if enabled).
+
+VPL
+   Verifying Program Loader. Optional verification step, which can select one of
+   several SPL binaries, if A/B verified boot is enabled. Implementation of the
+   VPL logic is work-in-progress. For now it just boots into SPL.
+
+SPL
+   Secondary Program Loader. Sets up SDRAM and loads U-Boot proper. It may also
+   load other firmware components.
+
+U-Boot
+   U-Boot proper. This is the only stage containing command. It also implements
+   logic to load an operating system, e.g. via UEFI.
+
+.. note::
+
+   The naming convention on the PowerPC architecture deviates from the other
+   archtitectures. Here the boot sequence is SPL->TPL->U-Boot.
+
+Further usages for U-Boot SPL comprise:
+
+* launching BL31 of ARM Trusted Firmware which invokes U-Boot as BL33
+* launching EDK II
+* launching Linux, e.g. :doc:`Falcon Mode <../develop/falcon>`
+* launching RISC-V OpenSBI which invokes main U-Boot
+
+Target binaries
+---------------
+
+Binaries loaded by SPL/TPL can be:
+
+* raw binaries where the entry address equals the start address. This is the
+  only binary format supported by TPL.
+* :doc:`FIT <fit/index>` images
+* legacy U-Boot images
+
+Configuration
+~~~~~~~~~~~~~
+
+Raw images are only supported in SPL if CONFIG_SPL_RAW_IMAGE_SUPPORT=y.
+
+CONFIG_SPL_FIT=y and CONFIG_SPL_LOAD_FIT=y are needed to load FIT images.
+
+CONFIG_SPL_LEGACY_IMAGE_FORMAT=y is needed to load legacy U-Boot images.
+CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK=y enables checking the CRC32 of legacy U-Boot
+images.
+
+Image load methods
+------------------
+
+The image boot methods available for a board must be defined in two places:
+
+The board code implements a function board_boot_order() enumerating up to
+five boot methods and the sequence in which they are tried. (The maximum
+number of boot methods is currently hard coded as variable spl_boot_list[]).
+If there is only one boot method function, spl_boot_device() may be implemented
+instead.
+
+The configuration controls which of these boot methods are actually available.
+
+Loading from block devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+MMC1, MMC2, MMC2_2
+    These methods read an image from SD card or eMMC. The first digit after
+    'MMC' indicates the device number. Required configuration settings include:
+
+    * CONFIG_SPL_MMC=y or CONFIG_TPL_MMC=y
+
+    To use a PCI connected MMC controller you need to additionally specify:
+
+    * CONFIG_SPL_PCI=y
+
+    * CONFIG_SPL_PCI_PNP=y
+
+    * CONFIG_MMC=y
+
+    * CONFIG_MMC_PCI=y
+
+    * CONFIG_MMC_SDHCI=y
+
+    To load from a file system use:
+
+    * CONFIG_SPL_FS_FAT=y or CONFIG_SPL_FS_EXT=y
+
+    * CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="<filepath>"
+
+NVMe
+    This methods load the image from an NVMe drive.
+    Required configuration settings include:
+
+    * CONFIG_SPL_PCI=y
+
+    * CONFIG_SPL_PCI_PNP=y
+
+    * CONFIG_SPL_NVME=y
+
+    * CONFIG_SPL_NVME_PCI=y
+
+    * CONFIG_SPL_NVME_BOOT_DEVICE (number of the NVMe device)
+
+    * CONFIG_SYS_NVME_BOOT_PARTITION (partition to read from)
+
+    To load from a file system use:
+
+    * CONFIG_SPL_FS_FAT=y or CONFIG_SPL_FS_EXT=y
+
+    * CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="<filepath>"
+
+SATA
+    This method reads an image from a SATA drive.
+    Required configuration settings include:
+
+    * CONFIG_SPL_SATA=y or CONFIG_TPL_SATA=y
+
+    To use a PCIe connecte SATA controller you additionally need:
+
+    * CONFIG_SPL_PCI=y
+
+    * CONFIG_SPL_SATA=y
+
+    * CONFIG_SPL_AHCI_PCI=y
+
+    * CONFIG_SPL_PCI_PNP=y
+
+    To load from a file system use:
+
+    * CONFIG_SPL_FS_FAT=y
+
+    * CONFIG_SYS_SATA_FAT_BOOT_PARTITION=<partition number>
+
+    * CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="<filepath>"
+
+USB
+    The USB method loads an image from a USB block device.
+    Required configuration settings include:
+
+    * CONFIG_SPL_USB_HOST=y
+
+    * CONFIG_SPL_USB_STORAGE=y
+
+    To use a PCI connected USB 3.0 controller you additionally need:
+
+    * CONFIG_SPL_FS_FAT=y
+
+    * CONFIG_SPL_PCI=y
+
+    * CONFIG_SPL_PCI_PNP=y
+
+    * CONFIG_USB=y
+
+    * CONFIG_USB_XHCI_HCD=y
+
+    * CONFIG_USB_XHCI_PCI=y
+
+    To load from a file system use:
+
+    * CONFIG_SPL_FS_FAT=y or CONFIG_SPL_FS_EXT=y
+
+    * CONFIG_SYS_USB_FAT_BOOT_PARTITION=<partition number>
+
+    * CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="<filepath>"
+
+Loading from raw flash devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+NAND
+    This method loads the image from NAND flash. To read from raw NAND the
+    following configuration settings are required:
+
+    * CONFIG_SPL_NAND_SUPPORT=y or CONFIG_TPL_NAND_SUPPORT=y
+
+    If CONFIG_SPL_NAND_RAW_ONLY=y only raw images can be loaded.
+
+    For using UBI (Unsorted Block Images) volumes to read from NAND the
+    following configuration settings are required:
+
+    * CONFIG_SPL_UBI=y or CONFIG_TPL_UBI=y
+
+    The UBI volume to read can either be specified
+
+    * by name using CONFIG_SPL_UBI_LOAD_BY_VOLNAME or
+
+    * by number using CONFIG_SPL_UBI_LOAD_MONITOR_ID.
+
+NOR
+    This method loads the image from NOR flash.
+    Required configuration settings include:
+
+    * CONFIG_SPL_NOR_SUPPORT=y or CONFIG_TPL_NOR_SUPPORT=y
+
+OneNAND
+    This methods loads the image from a OneNAND device. To read from raw OneNAND
+    the following configuration settings are required:
+
+    * CONFIG_SPL_ONENAND_SUPPORT=y or CONFIG_TPL_ONENAND_SUPPORT=y
+
+    For using the Ubi file system to read from NAND the following configuration
+    settings are required:
+
+    * CONFIG_SPL_UBI=y or CONFIG_TPL_UBI=y
+
+SPI
+    This method loads an image form SPI NOR flash.
+    Required configuration settings include:
+
+    * CONFIG_SPL_DM_SPI=y
+
+    * CONFIG_SPL_SPI_FLASH=y
+
+    * CONFIG_SPI_LOAD=y or CONFIG_TPL_SPI_LOAD=y
+
+
+Sunxi SPI
+    This method which is specific to Allwinner SoCs loads an image form SPI NOR
+    flash. Required configuration settings include:
+
+    * CONFIG_SPL_SPI_SUNXI=y
+
+Loading from other devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BOOTROM
+    The binary is loaded by the boot ROM.
+    Required configuration settings include:
+
+    * CONFIG_SPL_BOOTROM_SUPPORT=y or CONFIG_TPL_BOOTROM_SUPPORT=y
+
+DFU
+    :doc:`Device Firmware Upgrade <dfu>` is used to load the binary into RAM.
+    Required configuration settings include:
+
+    * CONFIG_DFU=y
+
+    * CONFIG_SPL_RAM_SUPPORT=y or CONFIG TPL_RAM_SUPPORT=y
+
+Ethernet
+    This method loads an image over Ethernet. The BOOTP protocol is used to find
+    a TFTP server and binary name. The binary is downloaded via the TFTP
+    protocol. Required configuration settings include:
+
+    * CONFIG_SPL_NET=y or CONFIG_TPL_NET=y
+
+    * CONFIG_SPL_ETH_DEVICE=y or CONFIG_DM_USB_GADGET=y
+
+FEL
+    This method does not actually load an image for U-Boot.
+    FEL is a routine contained in the boot ROM of Allwinner SoCs which serves
+    for the initial programming or recovery via USB
+
+RAM
+    This method uses an image preloaded into RAM.
+    Required configuration settings include:
+
+    * CONFIG_SPL_RAM_SUPPORT=y or CONFIG_TPL_RAM_SUPPORT=y
+
+    * CONFIG_RAM_DEVICE=y
+
+Sandbox file
+    On the sandbox this method loads an image from the host file system.
+
+Sandbox image
+    On the sandbox this method loads an image from the host file system.
+
+Semihosting
+    When running in an ARM or RISC-V virtual machine the semihosting method can
+    be used to load an image from the host file system.
+    Required configuration settings include:
+
+    * CONFIG_SPL_SEMIHOSTING=y
+
+    * CONFIG_SPL_SEMIHOSTING_FALLBACK=y
+
+    * CONFIG_SPL_FS_LOAD_PAYLOAD_NAME=<path to file>
+
+UART
+    This method loads an image via the Y-Modem protocol from the UART.
+    Required configuration settings include:
+
+    * CONFIG_SPL_YMODEM_SUPPORT=y or CONFIG_TPL_YMODEM_SUPPORT=y
+
+USB SDP
+    This method loads the image using the Serial Download Protocol as
+    implemented by the boot ROM of the i.MX family of SoCs.
+
+    Required configuration settings include:
+
+    * CONFIG_SPL_SERIAL=y
+
+    * CONFIG_SPL_USB_SDP_SUPPORT=y or CONFIG_TPL_USB_SDP_SUPPORT
+
+VBE Simple
+    This method is used by the VPL stage to extract the next stage image from
+    the loaded image.
+
+    Required configuration settings include:
+
+    * CONFIG_VPL=y
+
+    * CONFIG_SPL_BOOTMETH_VBE_SIMPLE_FW=y or CONFIG_TPL_BOOTMETH_VBE_SIMPLE_FW=y
+
+XIP
+    This method executes an image in place.
+
+    Required configuration settings include:
+
+    * CONFIG_SPL_XIP_SUPPORT
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 0e89c85..0b7579c 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -61,7 +61,7 @@
 
 static efi_status_t efi_uninstall_protocol
 			(efi_handle_t handle, const efi_guid_t *protocol,
-			 void *protocol_interface);
+			 void *protocol_interface, bool preserve);
 
 /* 1 if inside U-Boot code, 0 if inside EFI payload code */
 static int entry_count = 1;
@@ -208,6 +208,36 @@
 }
 
 /**
+ * efi_purge_handle() - Clean the deleted handle from the various lists
+ * @handle: handle to remove
+ *
+ * Return: status code
+ */
+static efi_status_t efi_purge_handle(efi_handle_t handle)
+{
+	struct efi_register_notify_event *item;
+
+	if (!list_empty(&handle->protocols))
+		return EFI_ACCESS_DENIED;
+	/* The handle is about to be freed. Remove it from events */
+	list_for_each_entry(item, &efi_register_notify_events, link) {
+		struct efi_protocol_notification *hitem, *hnext;
+
+		list_for_each_entry_safe(hitem, hnext, &item->handles, link) {
+			if (handle == hitem->handle) {
+				list_del(&hitem->link);
+				free(hitem);
+			}
+		}
+	}
+	/* The last protocol has been removed, delete the handle. */
+	list_del(&handle->link);
+	free(handle);
+
+	return EFI_SUCCESS;
+}
+
+/**
  * efi_process_event_queue() - process event queue
  */
 static void efi_process_event_queue(void)
@@ -615,7 +645,7 @@
 		efi_status_t ret;
 
 		ret = efi_uninstall_protocol(handle, &protocol->guid,
-					     protocol->protocol_interface);
+					     protocol->protocol_interface, true);
 		if (ret != EFI_SUCCESS)
 			return ret;
 	}
@@ -639,10 +669,7 @@
 		return ret;
 	}
 
-	list_del(&handle->link);
-	free(handle);
-
-	return ret;
+	return efi_purge_handle(handle);
 }
 
 /**
@@ -1356,6 +1383,8 @@
  * @handle:             handle from which the protocol shall be removed
  * @protocol:           GUID of the protocol to be removed
  * @protocol_interface: interface to be removed
+ * @preserve:		preserve or delete the handle and remove it from any
+ *			list it participates if no protocols remain
  *
  * This function DOES NOT delete a handle without installed protocol.
  *
@@ -1363,7 +1392,7 @@
  */
 static efi_status_t efi_uninstall_protocol
 			(efi_handle_t handle, const efi_guid_t *protocol,
-			 void *protocol_interface)
+			 void *protocol_interface, bool preserve)
 {
 	struct efi_handler *handler;
 	struct efi_open_protocol_info_item *item;
@@ -1397,6 +1426,14 @@
 		goto out;
 	}
 	r = efi_remove_protocol(handle, protocol, protocol_interface);
+	if (r != EFI_SUCCESS)
+		return r;
+	/*
+	 * We don't care about the return value here since the
+	 * handle might have more protocols installed
+	 */
+	if (!preserve)
+		efi_purge_handle(handle);
 out:
 	return r;
 }
@@ -1422,15 +1459,10 @@
 
 	EFI_ENTRY("%p, %pUs, %p", handle, protocol, protocol_interface);
 
-	ret = efi_uninstall_protocol(handle, protocol, protocol_interface);
+	ret = efi_uninstall_protocol(handle, protocol, protocol_interface, false);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	/* If the last protocol has been removed, delete the handle. */
-	if (list_empty(&handle->protocols)) {
-		list_del(&handle->link);
-		free(handle);
-	}
 out:
 	return EFI_EXIT(ret);
 }
@@ -2785,7 +2817,7 @@
 efi_uninstall_multiple_protocol_interfaces_int(efi_handle_t handle,
 					       efi_va_list argptr)
 {
-	const efi_guid_t *protocol;
+	const efi_guid_t *protocol, *next_protocol;
 	void *protocol_interface;
 	efi_status_t ret = EFI_SUCCESS;
 	size_t i = 0;
@@ -2795,25 +2827,34 @@
 		return EFI_INVALID_PARAMETER;
 
 	efi_va_copy(argptr_copy, argptr);
+	protocol = efi_va_arg(argptr, efi_guid_t*);
 	for (;;) {
-		protocol = efi_va_arg(argptr, efi_guid_t*);
+		/*
+		 * If efi_uninstall_protocol() fails we need to be able to
+		 * reinstall the previously uninstalled protocols on the same
+		 * handle.
+		 * Instead of calling efi_uninstall_protocol(...,..., false)
+		 * and potentially removing the handle, only allow the handle
+		 * removal on the last protocol that we requested to uninstall.
+		 * That way we can preserve  the handle in case the latter fails
+		 */
+		bool preserve = true;
+
 		if (!protocol)
 			break;
 		protocol_interface = efi_va_arg(argptr, void*);
+		next_protocol = efi_va_arg(argptr, efi_guid_t*);
+		if (!next_protocol)
+			preserve = false;
 		ret = efi_uninstall_protocol(handle, protocol,
-					     protocol_interface);
+					     protocol_interface, preserve);
 		if (ret != EFI_SUCCESS)
 			break;
 		i++;
+		protocol = next_protocol;
 	}
-	if (ret == EFI_SUCCESS) {
-		/* If the last protocol has been removed, delete the handle. */
-		if (list_empty(&handle->protocols)) {
-			list_del(&handle->link);
-			free(handle);
-		}
+	if (ret == EFI_SUCCESS)
 		goto out;
-	}
 
 	/* If an error occurred undo all changes. */
 	for (; i; --i) {
@@ -3712,7 +3753,7 @@
 		  new_interface);
 
 	/* Uninstall protocol but do not delete handle */
-	ret = efi_uninstall_protocol(handle, protocol, old_interface);
+	ret = efi_uninstall_protocol(handle, protocol, old_interface, true);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
diff --git a/lib/hash-checksum.c b/lib/hash-checksum.c
index 8f2a42f..68c290d 100644
--- a/lib/hash-checksum.c
+++ b/lib/hash-checksum.c
@@ -23,8 +23,10 @@
 	struct hash_algo *algo;
 	int ret = 0;
 	void *ctx;
-	uint32_t i;
-	i = 0;
+	int i;
+
+	if (region_count < 1)
+		return -EINVAL;
 
 	ret = hash_progressive_lookup_algo(name, &algo);
 	if (ret)