Module Name: src Committed By: jmcneill Date: Mon Jun 21 11:11:33 UTC 2021
Modified Files: src/sys/stand/efiboot: efiblock.c efiblock.h version Log Message: efiboot: Use disk I/O protocol for block device access. EFI_DISK_IO_PROTOCOL is a simplified interface to block devices. Use this instead of EFI_BLOCK_IO_PROTOCOL for accessing block devices to simplify the code -- we no longer need to worry about the underlying media's block I/O size and alignment requirements. To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/sys/stand/efiboot/efiblock.c cvs rdiff -u -r1.4 -r1.5 src/sys/stand/efiboot/efiblock.h cvs rdiff -u -r1.26 -r1.27 src/sys/stand/efiboot/version Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/stand/efiboot/efiblock.c diff -u src/sys/stand/efiboot/efiblock.c:1.12 src/sys/stand/efiboot/efiblock.c:1.13 --- src/sys/stand/efiboot/efiblock.c:1.12 Sun Jun 20 19:10:47 2021 +++ src/sys/stand/efiboot/efiblock.c Mon Jun 21 11:11:33 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: efiblock.c,v 1.12 2021/06/20 19:10:47 jmcneill Exp $ */ +/* $NetBSD: efiblock.c,v 1.13 2021/06/21 11:11:33 jmcneill Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -110,68 +110,41 @@ efi_block_generate_hash_mbr(struct efi_b MD5Final(bpart->hash, &md5ctx); } -static void * -efi_block_allocate_device_buffer(struct efi_block_dev *bdev, UINTN size, - void **buf_start) +static EFI_STATUS +efi_block_disk_read(struct efi_block_dev *bdev, UINT64 off, void *buf, + UINTN bufsize) { - void *buf; - - if (bdev->bio->Media->IoAlign <= 1) - *buf_start = buf = AllocatePool(size); - else { - buf = AllocatePool(size + bdev->bio->Media->IoAlign - 1); - *buf_start = (buf == NULL) ? NULL : - (void *)roundup2((intptr_t)buf, bdev->bio->Media->IoAlign); - } - - return buf; + return uefi_call_wrapper(bdev->dio->ReadDisk, 5, bdev->dio, + bdev->media_id, off, bufsize, buf); } static int efi_block_find_partitions_cd9660(struct efi_block_dev *bdev) { struct efi_block_part *bpart; - struct iso_primary_descriptor *vd; - void *buf, *buf_start; + struct iso_primary_descriptor vd; EFI_STATUS status; EFI_LBA lba; - UINT32 sz; - - if (bdev->bio->Media->BlockSize != DEV_BSIZE && - bdev->bio->Media->BlockSize != ISO_DEFAULT_BLOCK_SIZE) { - return ENXIO; - } - - sz = __MAX(sizeof(*vd), bdev->bio->Media->BlockSize); - sz = roundup(sz, bdev->bio->Media->BlockSize); - if ((buf = efi_block_allocate_device_buffer(bdev, sz, &buf_start)) == NULL) { - return ENOMEM; - } for (lba = 16;; lba++) { - status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, - bdev->bio, - bdev->media_id, - lba * ISO_DEFAULT_BLOCK_SIZE / bdev->bio->Media->BlockSize, - sz, - buf_start); + status = efi_block_disk_read(bdev, + lba * ISO_DEFAULT_BLOCK_SIZE, &vd, sizeof(vd)); if (EFI_ERROR(status)) { goto io_error; } - vd = (struct iso_primary_descriptor *)buf_start; - if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) { + if (memcmp(vd.id, ISO_STANDARD_ID, sizeof vd.id) != 0) { goto io_error; } - if (isonum_711(vd->type) == ISO_VD_END) { + if (isonum_711(vd.type) == ISO_VD_END) { goto io_error; } - if (isonum_711(vd->type) == ISO_VD_PRIMARY) { + if (isonum_711(vd.type) == ISO_VD_PRIMARY) { break; } } - if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) { + if (isonum_723(vd.logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) { goto io_error; } @@ -181,39 +154,29 @@ efi_block_find_partitions_cd9660(struct bpart->type = EFI_BLOCK_PART_CD9660; TAILQ_INSERT_TAIL(&bdev->partitions, bpart, entries); - FreePool(buf); return 0; io_error: - FreePool(buf); return EIO; } static int -efi_block_find_partitions_disklabel(struct efi_block_dev *bdev, struct mbr_sector *mbr, uint32_t start, uint32_t size) +efi_block_find_partitions_disklabel(struct efi_block_dev *bdev, + struct mbr_sector *mbr, uint32_t start, uint32_t size) { struct efi_block_part *bpart; + char buf[DEV_BSIZE]; struct disklabel d; struct partition *p; EFI_STATUS status; - EFI_LBA lba; - void *buf, *buf_start; - UINT32 sz; int n; - sz = __MAX(sizeof(d), bdev->bio->Media->BlockSize); - sz = roundup(sz, bdev->bio->Media->BlockSize); - if ((buf = efi_block_allocate_device_buffer(bdev, sz, &buf_start)) == NULL) - return ENOMEM; - - lba = (((EFI_LBA)start + LABELSECTOR) * DEV_BSIZE) / bdev->bio->Media->BlockSize; - status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, - lba, sz, buf_start); - if (EFI_ERROR(status) || getdisklabel(buf_start, &d) != NULL) { + status = efi_block_disk_read(bdev, + ((EFI_LBA)start + LABELSECTOR) * DEV_BSIZE, buf, sizeof(buf)); + if (EFI_ERROR(status) || getdisklabel(buf, &d) != NULL) { FreePool(buf); return EIO; } - FreePool(buf); if (le32toh(d.d_magic) != DISKMAGIC || le32toh(d.d_magic2) != DISKMAGIC) return EINVAL; @@ -254,23 +217,11 @@ efi_block_find_partitions_mbr(struct efi struct mbr_sector mbr; struct mbr_partition *mbr_part; EFI_STATUS status; - void *buf, *buf_start; - UINT32 sz; int n; - sz = __MAX(sizeof(mbr), bdev->bio->Media->BlockSize); - sz = roundup(sz, bdev->bio->Media->BlockSize); - if ((buf = efi_block_allocate_device_buffer(bdev, sz, &buf_start)) == NULL) - return ENOMEM; - - status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, - 0, sz, buf_start); - if (EFI_ERROR(status)) { - FreePool(buf); + status = efi_block_disk_read(bdev, 0, &mbr, sizeof(mbr)); + if (EFI_ERROR(status)) return EIO; - } - memcpy(&mbr, buf_start, sizeof(mbr)); - FreePool(buf); if (le32toh(mbr.mbr_magic) != MBR_MAGIC) return ENOENT; @@ -280,7 +231,9 @@ efi_block_find_partitions_mbr(struct efi if (le32toh(mbr_part->mbrp_size) == 0) continue; if (mbr_part->mbrp_type == MBR_PTYPE_NETBSD) { - efi_block_find_partitions_disklabel(bdev, &mbr, le32toh(mbr_part->mbrp_start), le32toh(mbr_part->mbrp_size)); + efi_block_find_partitions_disklabel(bdev, &mbr, + le32toh(mbr_part->mbrp_start), + le32toh(mbr_part->mbrp_size)); break; } } @@ -302,7 +255,8 @@ static const struct { }; static int -efi_block_find_partitions_gpt_entry(struct efi_block_dev *bdev, struct gpt_hdr *hdr, struct gpt_ent *ent, UINT32 index) +efi_block_find_partitions_gpt_entry(struct efi_block_dev *bdev, + struct gpt_hdr *hdr, struct gpt_ent *ent, UINT32 index) { struct efi_block_part *bpart; uint8_t fstype = FS_UNUSED; @@ -311,7 +265,8 @@ efi_block_find_partitions_gpt_entry(stru memcpy(&uuid, ent->ent_type, sizeof(uuid)); for (n = 0; n < __arraycount(gpt_guid_to_str); n++) - if (memcmp(ent->ent_type, &gpt_guid_to_str[n].guid, sizeof(ent->ent_type)) == 0) { + if (memcmp(ent->ent_type, &gpt_guid_to_str[n].guid, + sizeof(ent->ent_type)) == 0) { fstype = gpt_guid_to_str[n].fstype; break; } @@ -340,42 +295,35 @@ efi_block_find_partitions_gpt(struct efi struct gpt_hdr hdr; struct gpt_ent ent; EFI_STATUS status; - void *buf, *buf_start; - UINT32 sz, entry; - - sz = __MAX(sizeof(hdr), bdev->bio->Media->BlockSize); - sz = roundup(sz, bdev->bio->Media->BlockSize); - if ((buf = efi_block_allocate_device_buffer(bdev, sz, &buf_start)) == NULL) - return ENOMEM; + UINT32 entry; + void *buf; + UINTN sz; - status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, - GPT_HDR_BLKNO, sz, buf_start); + status = efi_block_disk_read(bdev, GPT_HDR_BLKNO * DEV_BSIZE, &hdr, + sizeof(hdr)); if (EFI_ERROR(status)) { - FreePool(buf); return EIO; } - memcpy(&hdr, buf_start, sizeof(hdr)); - FreePool(buf); if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0) return ENOENT; if (le32toh(hdr.hdr_entsz) < sizeof(ent)) return EINVAL; - sz = __MAX(le32toh(hdr.hdr_entsz) * le32toh(hdr.hdr_entries), bdev->bio->Media->BlockSize); - sz = roundup(sz, bdev->bio->Media->BlockSize); - if ((buf = efi_block_allocate_device_buffer(bdev, sz, &buf_start)) == NULL) + sz = le32toh(hdr.hdr_entsz) * le32toh(hdr.hdr_entries); + buf = AllocatePool(sz); + if (buf == NULL) return ENOMEM; - status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, - le64toh(hdr.hdr_lba_table), sz, buf_start); + status = efi_block_disk_read(bdev, + le64toh(hdr.hdr_lba_table) * DEV_BSIZE, buf, sz); if (EFI_ERROR(status)) { FreePool(buf); return EIO; } for (entry = 0; entry < le32toh(hdr.hdr_entries); entry++) { - memcpy(&ent, buf_start + (entry * le32toh(hdr.hdr_entsz)), + memcpy(&ent, buf + (entry * le32toh(hdr.hdr_entsz)), sizeof(ent)); efi_block_find_partitions_gpt_entry(bdev, &hdr, &ent, entry); } @@ -405,6 +353,7 @@ efi_block_probe(void) struct efi_block_dev *bdev; struct efi_block_part *bpart; EFI_BLOCK_IO *bio; + EFI_DISK_IO *dio; EFI_STATUS status; uint16_t devindex = 0; int depth = -1; @@ -423,16 +372,23 @@ efi_block_probe(void) } for (n = 0; n < efi_nblock; n++) { - status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_block[n], &BlockIoProtocol, (void **)&bio); + status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_block[n], + &BlockIoProtocol, (void **)&bio); if (EFI_ERROR(status) || !bio->Media->MediaPresent) continue; if (bio->Media->LogicalPartition) continue; + status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_block[n], + &DiskIoProtocol, (void **)&dio); + if (EFI_ERROR(status)) + continue; + bdev = alloc(sizeof(*bdev)); bdev->index = devindex++; bdev->bio = bio; + bdev->dio = dio; bdev->media_id = bio->Media->MediaId; bdev->path = DevicePathFromHandle(efi_block[n]); TAILQ_INIT(&bdev->partitions); @@ -529,7 +485,7 @@ efi_block_show(void) } else { Print(L"\"%s\"", bpart->gpt.ent.ent_name); } - + /* Size in MB */ size = (le64toh(bpart->gpt.ent.ent_lba_end) - le64toh(bpart->gpt.ent.ent_lba_start)) * bdev->bio->Media->BlockSize; size /= (1024 * 1024); @@ -565,7 +521,7 @@ efi_block_open(struct open_file *f, ...) char *path; va_list ap; int rv, n; - + va_start(ap, f); fname = va_arg(ap, const char *); file = va_arg(ap, char **); @@ -603,7 +559,7 @@ efi_block_strategy(void *devdata, int rw { struct efi_block_part *bpart = devdata; EFI_STATUS status; - void *allocated_buf, *aligned_buf; + UINT64 off; if (rw != F_READ) return EROFS; @@ -612,48 +568,21 @@ efi_block_strategy(void *devdata, int rw switch (bpart->type) { case EFI_BLOCK_PART_DISKLABEL: - if (bpart->bdev->bio->Media->BlockSize != bpart->disklabel.secsize) { - printf("%s: unsupported block size %d (expected %d)\n", __func__, - bpart->bdev->bio->Media->BlockSize, bpart->disklabel.secsize); - return EIO; - } - dblk += bpart->disklabel.part.p_offset; + off = (dblk + bpart->disklabel.part.p_offset) * DEV_BSIZE; break; case EFI_BLOCK_PART_GPT: - if (bpart->bdev->bio->Media->BlockSize != DEV_BSIZE) { - printf("%s: unsupported block size %d (expected %d)\n", __func__, - bpart->bdev->bio->Media->BlockSize, DEV_BSIZE); - return EIO; - } - dblk += le64toh(bpart->gpt.ent.ent_lba_start); + off = (dblk + le64toh(bpart->gpt.ent.ent_lba_start)) * DEV_BSIZE; break; case EFI_BLOCK_PART_CD9660: - dblk *= ISO_DEFAULT_BLOCK_SIZE / bpart->bdev->bio->Media->BlockSize; + off = dblk * ISO_DEFAULT_BLOCK_SIZE; break; default: return EINVAL; } - if ((bpart->bdev->bio->Media->IoAlign <= 1) || - ((intptr_t)buf & (bpart->bdev->bio->Media->IoAlign - 1)) == 0) { - allocated_buf = NULL; - aligned_buf = buf; - } else if ((allocated_buf = efi_block_allocate_device_buffer(bpart->bdev, - size, &aligned_buf)) == NULL) { - return ENOMEM; - } - - status = uefi_call_wrapper(bpart->bdev->bio->ReadBlocks, 5, - bpart->bdev->bio, bpart->bdev->media_id, dblk, size, aligned_buf); - if (EFI_ERROR(status)) { - if (allocated_buf != NULL) - FreePool(allocated_buf); + status = efi_block_disk_read(bpart->bdev, off, buf, size); + if (EFI_ERROR(status)) return EIO; - } - if (allocated_buf != NULL) { - memcpy(buf, aligned_buf, size); - FreePool(allocated_buf); - } *rsize = size; Index: src/sys/stand/efiboot/efiblock.h diff -u src/sys/stand/efiboot/efiblock.h:1.4 src/sys/stand/efiboot/efiblock.h:1.5 --- src/sys/stand/efiboot/efiblock.h:1.4 Sun Oct 11 14:03:33 2020 +++ src/sys/stand/efiboot/efiblock.h Mon Jun 21 11:11:33 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: efiblock.h,v 1.4 2020/10/11 14:03:33 jmcneill Exp $ */ +/* $NetBSD: efiblock.h,v 1.5 2021/06/21 11:11:33 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -43,6 +43,7 @@ struct efi_block_dev { uint16_t index; EFI_DEVICE_PATH *path; EFI_BLOCK_IO *bio; + EFI_DISK_IO *dio; UINT32 media_id; TAILQ_HEAD(, efi_block_part) partitions; Index: src/sys/stand/efiboot/version diff -u src/sys/stand/efiboot/version:1.26 src/sys/stand/efiboot/version:1.27 --- src/sys/stand/efiboot/version:1.26 Sun Jun 20 19:10:47 2021 +++ src/sys/stand/efiboot/version Mon Jun 21 11:11:33 2021 @@ -1,4 +1,4 @@ -$NetBSD: version,v 1.26 2021/06/20 19:10:47 jmcneill Exp $ +$NetBSD: version,v 1.27 2021/06/21 11:11:33 jmcneill Exp $ NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this file is important - make sure the entries are appended on end, last item @@ -30,3 +30,4 @@ is taken as the current. 2.7: Add basic support for booting from RAID1 volumes. 2.8: Add bi-endian disklabel and FFS support. 2.9: Watchdog support. +2.10: Use disk I/O protocol for block devices.