From: Jan Janssen Date: Tue, 18 Jan 2022 12:01:39 +0000 (+0100) Subject: boot: Simplify looking for the xboot hard drive X-Git-Tag: v251-rc1~505^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d81edd5ad7fb856cf4f96cbd6d84d8f0ed3054f8;p=thirdparty%2Fsystemd.git boot: Simplify looking for the xboot hard drive The device path should not contain multiple hard drive nodes in it, so looking at them all should not be needed. If some crazy firmware/driver were to make nested GPT drives available like that, we should be only looking at the last partition and its containing GPT drive anyway. --- diff --git a/src/boot/efi/xbootldr.c b/src/boot/efi/xbootldr.c index 26b77c93448..bee1d3ea4ae 100644 --- a/src/boot/efi/xbootldr.c +++ b/src/boot/efi/xbootldr.c @@ -160,7 +160,6 @@ static EFI_STATUS find_device( UINT64 *ret_part_size, EFI_GUID *ret_part_uuid) { - EFI_DEVICE_PATH *partition_path; EFI_STATUS err; assert(device); @@ -170,78 +169,81 @@ static EFI_STATUS find_device( assert(ret_part_size); assert(ret_part_uuid); - partition_path = DevicePathFromHandle(device); + EFI_DEVICE_PATH *partition_path = DevicePathFromHandle(device); if (!partition_path) return EFI_NOT_FOUND; + /* Find the (last) partition node itself. */ + EFI_DEVICE_PATH *part_node = NULL; for (EFI_DEVICE_PATH *node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { - _cleanup_freepool_ EFI_DEVICE_PATH *disk_path = NULL; - EFI_HANDLE disk_handle; - EFI_BLOCK_IO *block_io; - EFI_DEVICE_PATH *p; - if (DevicePathType(node) != MEDIA_DEVICE_PATH) continue; if (DevicePathSubType(node) != MEDIA_HARDDRIVE_DP) continue; - /* Chop off the partition part, leaving us with the path to the disk itself. */ - disk_path = p = path_chop(partition_path, node); - if (!disk_path) - continue; + part_node = node; + } - err = BS->LocateDevicePath(&BlockIoProtocol, &p, &disk_handle); - if (EFI_ERROR(err)) - continue; + if (!part_node) + return EFI_NOT_FOUND; - err = BS->HandleProtocol(disk_handle, &BlockIoProtocol, (void **)&block_io); - if (EFI_ERROR(err)) - continue; + /* Chop off the partition part, leaving us with the full path to the disk itself. */ + _cleanup_freepool_ EFI_DEVICE_PATH *disk_path = NULL; + EFI_DEVICE_PATH *p = disk_path = path_chop(partition_path, part_node); - /* Filter out some block devices early. (We only care about block devices that aren't - * partitions themselves — we look for GPT partition tables to parse after all —, and only - * those which contain a medium and have at least 2 blocks.) */ - if (block_io->Media->LogicalPartition || - !block_io->Media->MediaPresent || - block_io->Media->LastBlock <= 1) + EFI_HANDLE disk_handle; + EFI_BLOCK_IO *block_io; + err = BS->LocateDevicePath(&BlockIoProtocol, &p, &disk_handle); + if (EFI_ERROR(err)) + return err; + + err = BS->HandleProtocol(disk_handle, &BlockIoProtocol, (void **)&block_io); + if (EFI_ERROR(err)) + return err; + + /* Filter out some block devices early. (We only care about block devices that aren't + * partitions themselves — we look for GPT partition tables to parse after all —, and only + * those which contain a medium and have at least 2 blocks.) */ + if (block_io->Media->LogicalPartition || + !block_io->Media->MediaPresent || + block_io->Media->LastBlock <= 1) + return EFI_NOT_FOUND; + + /* Try several copies of the GPT header, in case one is corrupted */ + EFI_LBA backup_lba = 0; + for (UINTN nr = 0; nr < 3; nr++) { + EFI_LBA lba; + + /* Read the first copy at LBA 1 and then try the backup GPT header pointed + * to by the first header if that one was corrupted. As a last resort, + * try the very last LBA of this block device. */ + if (nr == 0) + lba = 1; + else if (nr == 1 && backup_lba != 0) + lba = backup_lba; + else if (nr == 2 && backup_lba != block_io->Media->LastBlock) + lba = block_io->Media->LastBlock; + else continue; - /* Try several copies of the GPT header, in case one is corrupted */ - EFI_LBA backup_lba = 0; - for (UINTN nr = 0; nr < 3; nr++) { - EFI_LBA lba; - - /* Read the first copy at LBA 1 and then try the backup GPT header pointed - * to by the first header if that one was corrupted. As a last resort, - * try the very last LBA of this block device. */ - if (nr == 0) - lba = 1; - else if (nr == 1 && backup_lba != 0) - lba = backup_lba; - else if (nr == 2 && backup_lba != block_io->Media->LastBlock) - lba = block_io->Media->LastBlock; - else - continue; - - err = try_gpt( - block_io, lba, - nr == 0 ? &backup_lba : NULL, /* Only get backup LBA location from first GPT header. */ - ret_part_number, - ret_part_start, - ret_part_size, - ret_part_uuid); - if (!EFI_ERROR(err)) { - *ret_device_path = DuplicateDevicePath(partition_path); - if (!*ret_device_path) - return EFI_OUT_OF_RESOURCES; - return EFI_SUCCESS; - } - - /* GPT was valid but no XBOOT loader partition found. */ - if (err == EFI_NOT_FOUND) - break; + err = try_gpt( + block_io, lba, + nr == 0 ? &backup_lba : NULL, /* Only get backup LBA location from first GPT header. */ + ret_part_number, + ret_part_start, + ret_part_size, + ret_part_uuid); + if (!EFI_ERROR(err)) { + *ret_device_path = DuplicateDevicePath(partition_path); + if (!*ret_device_path) + return EFI_OUT_OF_RESOURCES; + return EFI_SUCCESS; } + + /* GPT was valid but no XBOOT loader partition found. */ + if (err == EFI_NOT_FOUND) + break; } /* No xbootloader partition found */