From: Heinrich Schuchardt Date: Sat, 23 Jan 2021 05:52:21 +0000 (+0100) Subject: efi_loader: correct EFI_BLOCK_IO_PROTOCOL.Media.LastBlock X-Git-Url: http://git.dujemihanovic.xyz/img/static/git-favicon.png?a=commitdiff_plain;h=8d0949b3ed6985377682d7ec260be07ef26ef6d4;p=u-boot.git efi_loader: correct EFI_BLOCK_IO_PROTOCOL.Media.LastBlock 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 Signed-off-by: Heinrich Schuchardt --- 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;