From 8c3df0bf2e530c6e6f592f5144ef4f456c9e0260 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 11 Apr 2016 16:16:18 +0200 Subject: [PATCH] efi_loader: Add el torito support When loading an el torito image, uEFI exposes said image as a raw block device to the payload. Let's do the same by creating new block devices with added offsets for the respective el torito partitions. Signed-off-by: Alexander Graf --- cmd/bootefi.c | 14 ++++++++++++++ lib/efi_loader/efi_disk.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3add632bc4..0d09aa1e3b 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -194,12 +194,26 @@ U_BOOT_CMD( void efi_set_bootdev(const char *dev, const char *devnr) { + __maybe_unused struct blk_desc *desc; char devname[16] = { 0 }; /* dp->str is u16[16] long */ char *colon; /* Assemble the condensed device name we use in efi_disk.c */ snprintf(devname, sizeof(devname), "%s%s", dev, devnr); colon = strchr(devname, ':'); + +#ifdef CONFIG_ISO_PARTITION + /* For ISOs we create partition block devices */ + desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); + if (desc && (desc->type != DEV_TYPE_UNKNOWN) && + (desc->part_type == PART_TYPE_ISO)) { + if (!colon) + snprintf(devname, sizeof(devname), "%s%s:1", dev, + devnr); + colon = NULL; + } +#endif + if (colon) *colon = '\0'; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index e30e72817e..b3d56a88f0 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -27,6 +27,8 @@ struct efi_disk_obj { struct efi_block_io_media media; /* EFI device path to this block device */ struct efi_device_path_file_path *dp; + /* Offset into disk for simple partitions */ + lbaint_t offset; }; static efi_status_t efi_disk_open_block(void *handle, efi_guid_t *protocol, @@ -81,6 +83,7 @@ static efi_status_t EFIAPI efi_disk_rw_blocks(struct efi_block_io *this, return EFI_EXIT(EFI_DEVICE_ERROR); blksz = desc->blksz; blocks = buffer_size / blksz; + lba += diskobj->offset; #ifdef DEBUG_EFI printf("EFI: %s:%d blocks=%x lba=%"PRIx64" blksz=%x dir=%d\n", __func__, @@ -159,6 +162,7 @@ static void efi_disk_add_dev(char *name, diskobj->ops = block_io_disk_template; diskobj->ifname = cur_drvr->name; diskobj->dev_index = dev_index; + diskobj->offset = offset; /* Fill in EFI IO Media info (for read/write callbacks) */ diskobj->media.removable_media = desc->removable; @@ -184,6 +188,31 @@ static void efi_disk_add_dev(char *name, list_add_tail(&diskobj->parent.link, &efi_obj_list); } +static int efi_disk_create_eltorito(struct blk_desc *desc, + const struct block_drvr *cur_drvr, + int diskid) +{ + int disks = 0; +#ifdef CONFIG_ISO_PARTITION + char devname[16] = { 0 }; /* dp->str is u16[16] long */ + disk_partition_t info; + int part = 1; + + if (desc->part_type != PART_TYPE_ISO) + return 0; + + while (!part_get_info(desc, part, &info)) { + snprintf(devname, sizeof(devname), "%s%d:%d", cur_drvr->name, + diskid, part); + efi_disk_add_dev(devname, cur_drvr, desc, diskid, info.start); + part++; + disks++; + } +#endif + + return disks; +} + /* * U-Boot doesn't have a list of all online disk devices. So when running our * EFI payload, we scan through all of the potentially available ones and @@ -214,6 +243,12 @@ int efi_disk_register(void) cur_drvr->name, i); efi_disk_add_dev(devname, cur_drvr, desc, i, 0); disks++; + + /* + * El Torito images show up as block devices + * in an EFI world, so let's create them here + */ + disks += efi_disk_create_eltorito(desc, cur_drvr, i); } } printf("Found %d disks\n", disks); -- 2.39.5