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

Pull request efi-2023-07-rc3

Documentation:

* update the description of signature algorithms

UEFI:

* fix unaligned access to GUID in HII database protocol
* fix launching EFI binaries loaded via semihosting
* fix filling of file path in loaded image protocol for non-block devices
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 8aa15a6..5c0afec 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -589,7 +589,7 @@
 	if (!bootefi_device_path)
 		return EFI_OUT_OF_RESOURCES;
 
-	bootefi_image_path = efi_dp_from_file(NULL, 0, path);
+	bootefi_image_path = efi_dp_from_file(NULL, path);
 	if (!bootefi_image_path) {
 		ret = EFI_OUT_OF_RESOURCES;
 		goto failure;
diff --git a/doc/develop/devicetree/control.rst b/doc/develop/devicetree/control.rst
index 0b3b32b..cbb65c9 100644
--- a/doc/develop/devicetree/control.rst
+++ b/doc/develop/devicetree/control.rst
@@ -100,7 +100,7 @@
 
 If CONFIG_OF_SEPARATE is defined, then it will be built and placed in
 a u-boot.dtb file alongside u-boot-nodtb.bin with the combined result placed
-in u-boot.bin so you can still just flash u-boot,bin onto your board. If you are
+in u-boot.bin so you can still just flash u-boot.bin onto your board. If you are
 using CONFIG_SPL_FRAMEWORK, then u-boot.img will be built to include the device
 tree binary.
 
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
index c71280b..21eb389 100644
--- a/doc/uImage.FIT/signature.txt
+++ b/doc/uImage.FIT/signature.txt
@@ -42,8 +42,8 @@
 Algorithms
 ----------
 In principle any suitable algorithm can be used to sign and verify a hash.
-At present only one class of algorithms is supported: SHA1 hashing with RSA.
-This works by hashing the image to produce a 20-byte hash.
+U-Boot supports a few hashing and verification algorithms. See below for
+details.
 
 While it is acceptable to bring in large cryptographic libraries such as
 openssl on the host side (e.g. mkimage), it is not desirable for U-Boot.
@@ -56,10 +56,10 @@
 under 5KB on Tegra Seaboard, for example.
 
 It is relatively straightforward to add new algorithms if required. If
-another RSA variant is needed, then it can be added to the table in
-image-sig.c. If another algorithm is needed (such as DSA) then it can be
-placed alongside rsa.c, and its functions added to the table in image-sig.c
-also.
+another RSA variant is needed, then it can be added with the
+U_BOOT_CRYPTO_ALGO() macro. If another algorithm is needed (such as DSA) then
+it can be placed in a directory alongside lib/rsa/, and its functions added
+using U_BOOT_CRYPTO_ALGO().
 
 
 Creating an RSA key pair and certificate
@@ -439,6 +439,7 @@
 
 CONFIG_FIT_SIGNATURE - enable signing and verification in FITs
 CONFIG_RSA - enable RSA algorithm for signing
+CONFIG_ECDSA - enable ECDSA algorithm for signing
 
 WARNING: When relying on signed FIT images with required signature check
 the legacy image format is default disabled by not defining
@@ -694,8 +695,6 @@
 
 Possible Future Work
 --------------------
-- Add support for other RSA/SHA variants, such as rsa4096,sha512.
-- Other algorithms besides RSA
 - More sandbox tests for failure modes
 - Passwords for keys/certificates
 - Perhaps implement OAEP
diff --git a/include/efi_api.h b/include/efi_api.h
index 2fd0221..55a4c98 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1170,7 +1170,33 @@
 
 struct efi_hii_keyboard_layout {
 	u16 layout_length;
-	efi_guid_t guid;
+	/*
+	 * The EFI spec defines this as efi_guid_t.
+	 * clang and gcc both report alignment problems here.
+	 * clang with -Wunaligned-access
+	 * warning: field guid within 'struct efi_hii_keyboard_layout' is less
+	 * aligned than 'efi_guid_t' and is usually due to
+	 * 'struct efi_hii_keyboard_layout' being packed, which can lead to
+	 * unaligned accesses
+	 *
+	 * GCC with -Wpacked-not-aligned -Waddress-of-packed-member
+	 * 'efi_guid_t' offset 2 in 'struct efi_hii_keyboard_layout'
+	 * isn't aligned to 4
+	 *
+	 * Removing the alignment from efi_guid_t is not an option, since
+	 * it is also used in non-packed structs and that would break
+	 * calculations with offsetof
+	 *
+	 * This is the only place we get a report for. That happens because
+	 * all other declarations of efi_guid_t within a packed struct happens
+	 * to be 4-byte aligned.  i.e a u32, a u64 a 2 * u16 or any combination
+	 * that ends up landing efi_guid_t on a 4byte boundary precedes.
+	 *
+	 * Replace this with a 1-byte aligned counterpart of b[16].  This is a
+	 * packed struct so the memory  placement of efi_guid_t should not change
+	 *
+	 */
+	u8 guid[16];
 	u32 layout_descriptor_string_offset;
 	u8 descriptor_count;
 	/* struct efi_key_descriptor descriptors[]; follows here */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index b395eef9..38d7f66 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -810,7 +810,7 @@
 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
 /* Create a device node for a block device partition. */
 struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part);
-struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
+struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp,
 					 const char *path);
 struct efi_device_path *efi_dp_from_eth(void);
 struct efi_device_path *efi_dp_from_mem(uint32_t mem_type,
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 4b24b41..7ac5f89 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -47,7 +47,7 @@
 static
 struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
 {
-	struct efi_device_path *dp, *rem, *full_path;
+	struct efi_device_path *rem, *full_path;
 	efi_handle_t handle;
 
 	if (!device_path)
@@ -58,15 +58,12 @@
 	 * simple file system protocol, append a default file name to support
 	 * booting from removable media.
 	 */
-	dp = device_path;
-	handle = efi_dp_find_obj(dp, &efi_simple_file_system_protocol_guid,
-				 &rem);
+	handle = efi_dp_find_obj(device_path,
+				 &efi_simple_file_system_protocol_guid, &rem);
 	if (handle) {
 		if (rem->type == DEVICE_PATH_TYPE_END) {
-			dp = efi_dp_from_file(NULL, 0,
-					      "/EFI/BOOT/" BOOTEFI_NAME);
-			full_path = efi_dp_append(device_path, dp);
-			efi_free_pool(dp);
+			full_path = efi_dp_from_file(device_path,
+						     "/EFI/BOOT/" BOOTEFI_NAME);
 		} else {
 			full_path = efi_dp_dup(device_path);
 		}
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index e2e98a3..71923b1 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -1002,59 +1002,45 @@
 }
 
 /**
- * efi_dp_from_file() - create device path for file
+ * efi_dp_from_file() - append file path node to device path.
  *
- * The function creates a device path from the block descriptor @desc and the
- * partition number @part and appends a device path node created describing the
- * file path @path.
- *
- * If @desc is NULL, the device path will not contain nodes describing the
- * partition.
- * If @path is an empty string "", the device path will not contain a node
- * for the file path.
- *
- * @desc:	block device descriptor or NULL
- * @part:	partition number
- * @path:	file path on partition or ""
+ * @dp:		device path or NULL
+ * @path:	file path or NULL
  * Return:	device path or NULL in case of an error
  */
-struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
-		const char *path)
+struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp,
+					 const char *path)
 {
 	struct efi_device_path_file_path *fp;
-	void *buf, *start;
-	size_t dpsize = 0, fpsize;
-
-	if (desc)
-		dpsize = dp_part_size(desc, part);
+	void *buf, *pos;
+	size_t dpsize, fpsize;
 
+	dpsize = efi_dp_size(dp);
 	fpsize = sizeof(struct efi_device_path) +
 		 2 * (utf8_utf16_strlen(path) + 1);
 	if (fpsize > U16_MAX)
 		return NULL;
 
-	dpsize += fpsize;
-
-	start = buf = efi_alloc(dpsize + sizeof(END));
+	buf = efi_alloc(dpsize + fpsize + sizeof(END));
 	if (!buf)
 		return NULL;
 
-	if (desc)
-		buf = dp_part_fill(buf, desc, part);
+	memcpy(buf, dp, dpsize);
+	pos = buf + dpsize;
 
 	/* add file-path: */
 	if (*path) {
-		fp = buf;
+		fp = pos;
 		fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
 		fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
 		fp->dp.length = (u16)fpsize;
 		path_to_uefi(fp->str, path);
-		buf += fpsize;
+		pos += fpsize;
 	}
 
-	*((struct efi_device_path *)buf) = END;
+	memcpy(pos, &END, sizeof(END));
 
-	return start;
+	return buf;
 }
 
 struct efi_device_path *efi_dp_from_uart(void)
@@ -1079,8 +1065,7 @@
 	return buf;
 }
 
-#ifdef CONFIG_NETDEVICES
-struct efi_device_path *efi_dp_from_eth(void)
+struct efi_device_path __maybe_unused *efi_dp_from_eth(void)
 {
 	void *buf, *start;
 	unsigned dpsize = 0;
@@ -1099,7 +1084,6 @@
 
 	return start;
 }
-#endif
 
 /* Construct a device-path for memory-mapped image */
 struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
@@ -1185,58 +1169,42 @@
 			      struct efi_device_path **file)
 {
 	struct blk_desc *desc = NULL;
+	struct efi_device_path *dp;
 	struct disk_partition fs_partition;
 	size_t image_size;
 	void *image_addr;
 	int part = 0;
-	char *filename;
-	char *s;
 
 	if (path && !file)
 		return EFI_INVALID_PARAMETER;
 
-	if (!strcmp(dev, "Net")) {
-#ifdef CONFIG_NETDEVICES
-		if (device)
-			*device = efi_dp_from_eth();
-#endif
-	} else if (!strcmp(dev, "Uart")) {
-		if (device)
-			*device = efi_dp_from_uart();
-	} else if (!strcmp(dev, "Mem")) {
+	if (!strcmp(dev, "Mem") || !strcmp(dev, "hostfs"))  {
+		/* loadm command and semihosting */
 		efi_get_image_parameters(&image_addr, &image_size);
 
-		if (device)
-			*device = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
-						  (uintptr_t)image_addr,
-						  image_size);
+		dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
+				     (uintptr_t)image_addr, image_size);
+	} else if (IS_ENABLED(CONFIG_NETDEVICES) && !strcmp(dev, "Net")) {
+		dp = efi_dp_from_eth();
+	} else if (!strcmp(dev, "Uart")) {
+		dp = efi_dp_from_uart();
 	} else {
 		part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
 					       1);
 		if (part < 0 || !desc)
 			return EFI_INVALID_PARAMETER;
 
-		if (device)
-			*device = efi_dp_from_part(desc, part);
+		dp = efi_dp_from_part(desc, part);
 	}
+	if (device)
+		*device = dp;
 
 	if (!path)
 		return EFI_SUCCESS;
 
-	filename = calloc(1, strlen(path) + 1);
-	if (!filename)
-		return EFI_OUT_OF_RESOURCES;
-
-	sprintf(filename, "%s", path);
-	/* DOS style file path: */
-	s = filename;
-	while ((s = strchr(s, '/')))
-		*s++ = '\\';
-	*file = efi_dp_from_file(desc, part, filename);
-	free(filename);
-
+	*file = efi_dp_from_file(dp, path);
 	if (!*file)
-		return EFI_INVALID_PARAMETER;
+		return EFI_OUT_OF_RESOURCES;
 
 	return EFI_SUCCESS;
 }
diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
index 6405f58..bd72822 100644
--- a/lib/efi_loader/helloworld.c
+++ b/lib/efi_loader/helloworld.c
@@ -216,6 +216,10 @@
 			(con_out, u"Cannot open device path to text protocol\r\n");
 		goto out;
 	}
+	con_out->output_string(con_out, u"File path: ");
+	ret = print_device_path(loaded_image->file_path, device_path_to_text);
+	if (ret != EFI_SUCCESS)
+		goto out;
 	if (!loaded_image->device_handle) {
 		con_out->output_string
 			(con_out, u"Missing device handle\r\n");
@@ -234,10 +238,6 @@
 	ret = print_device_path(device_path, device_path_to_text);
 	if (ret != EFI_SUCCESS)
 		goto out;
-	con_out->output_string(con_out, u"File path: ");
-	ret = print_device_path(loaded_image->file_path, device_path_to_text);
-	if (ret != EFI_SUCCESS)
-		goto out;
 
 out:
 	boottime->exit(handle, ret, 0, NULL);
diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig
index 78759e6..71f3479 100644
--- a/lib/fwu_updates/Kconfig
+++ b/lib/fwu_updates/Kconfig
@@ -2,7 +2,7 @@
 	bool "Enable FWU Multi Bank Update Feature"
 	depends on EFI_CAPSULE_ON_DISK
 	select PARTITION_TYPE_GUID
-	select EFI_SETUP_EARLY
+	select FWU_MDATA
 	imply EFI_CAPSULE_ON_DISK_EARLY
 	select EVENT
 	help