[PATCH 1/1] efi_loader: correct EFI_BLOCK_IO_PROTOCOL.Media.LastBlock

Heinrich Schuchardt xypron.glpk at gmx.de
Sat Jan 23 07:42:23 CET 2021


The field Media.LastBlock of the EFI_BLOCK_IO_PROTOCOL.Media was filled
incorrectly both for block devices as well as for partitions.

The field must be filled with the index of the last logical block (LBA):

* block devices: device size minus 1
* partitions: partition size minus 1

Reported-by: Alexander von Gluck IV <kallisti5 at unixzen.com>
Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 lib/efi_loader/efi_disk.c | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 26b953461b..c0804effde 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -343,7 +343,7 @@ static int efi_fs_exists(struct blk_desc *desc, int part)
  * @if_typename:	interface name for block device
  * @desc:		internal block device
  * @dev_index:		device index for block device
- * @offset:		offset into disk for simple partitions
+ * @part_info:		partition info
  * @part:		partition
  * @disk:		pointer to receive the created handle
  * Return:		disk object
@@ -354,7 +354,7 @@ static efi_status_t efi_disk_add_dev(
 				const char *if_typename,
 				struct blk_desc *desc,
 				int dev_index,
-				lbaint_t offset,
+				struct disk_partition *part_info,
 				unsigned int part,
 				struct efi_disk_obj **disk)
 {
@@ -374,7 +374,7 @@ static efi_status_t efi_disk_add_dev(
 	efi_add_handle(&diskobj->header);

 	/* Fill in object data */
-	if (part) {
+	if (part_info) {
 		struct efi_device_path *node = efi_dp_part_node(desc, part);
 		struct efi_handler *handler;
 		void *protocol_interface;
@@ -396,8 +396,12 @@ static efi_status_t efi_disk_add_dev(

 		diskobj->dp = efi_dp_append_node(dp_parent, node);
 		efi_free_pool(node);
+		diskobj->offset = part_info->start;
+		diskobj->media.last_block = part_info->size - 1;
 	} else {
 		diskobj->dp = efi_dp_from_part(desc, part);
+		diskobj->offset = 0;
+		diskobj->media.last_block = desc->lba - 1;
 	}
 	diskobj->part = part;

@@ -432,7 +436,6 @@ static efi_status_t efi_disk_add_dev(
 	diskobj->ops = block_io_disk_template;
 	diskobj->ifname = if_typename;
 	diskobj->dev_index = dev_index;
-	diskobj->offset = offset;
 	diskobj->desc = desc;

 	/* Fill in EFI IO Media info (for read/write callbacks) */
@@ -445,13 +448,21 @@ static efi_status_t efi_disk_add_dev(
 	diskobj->media.media_id = 1;
 	diskobj->media.block_size = desc->blksz;
 	diskobj->media.io_align = desc->blksz;
-	diskobj->media.last_block = desc->lba - offset;
 	if (part)
 		diskobj->media.logical_partition = 1;
 	diskobj->ops.media = &diskobj->media;
 	if (disk)
 		*disk = diskobj;

+	EFI_PRINT("BlockIO: part %u, present %d, logical %d, removable %d"
+		  ", offset " LBAF ", last_block %llu\n",
+		  diskobj->part,
+		  diskobj->media.media_present,
+		  diskobj->media.logical_partition,
+		  diskobj->media.removable_media,
+		  diskobj->offset,
+		  diskobj->media.last_block);
+
 	/* Store first EFI system partition */
 	if (part && !efi_system_partition.if_type) {
 		int r;
@@ -493,7 +504,6 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
 {
 	int disks = 0;
 	char devname[32] = { 0 }; /* dp->str is u16[32] long */
-	struct disk_partition info;
 	int part;
 	struct efi_device_path *dp = NULL;
 	efi_status_t ret;
@@ -506,12 +516,14 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,

 	/* Add devices for each partition */
 	for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
+		struct disk_partition info;
+
 		if (part_get_info(desc, part, &info))
 			continue;
 		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
 			 part);
 		ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
-				       info.start, part, NULL);
+				       &info, part, NULL);
 		if (ret != EFI_SUCCESS) {
 			log_err("Adding partition %s failed\n", pdevname);
 			continue;
@@ -553,7 +565,7 @@ efi_status_t efi_disk_register(void)
 		/* Add block device for the full device */
 		log_info("Scanning disk %s...\n", dev->name);
 		ret = efi_disk_add_dev(NULL, NULL, if_typename,
-					desc, desc->devnum, 0, 0, &disk);
+					desc, desc->devnum, NULL, 0, &disk);
 		if (ret == EFI_NOT_READY) {
 			log_notice("Disk %s not ready\n", dev->name);
 			continue;
@@ -599,7 +611,7 @@ efi_status_t efi_disk_register(void)

 			/* Add block device for the full device */
 			ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
-					       i, 0, 0, &disk);
+					       i, NULL, 0, &disk);
 			if (ret == EFI_NOT_READY) {
 				log_notice("Disk %s not ready\n", devname);
 				continue;
--
2.29.2



More information about the U-Boot mailing list