Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/stand/efiboot efiboot: Use EFI_BLOCK_IO_PROTOCOL if EFI_...



details: https://anonhg.NetBSD.org/src/rev/06edf87d8d8f
branches: trunk
changeset: 379859:06edf87d8d8f
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Tue Jun 22 21:56:51 2021 +0000
description:
efiboot: Use EFI_BLOCK_IO_PROTOCOL if EFI_DISK_IO_PROTOCOL is missing
UEFI spec says that firmware should automatically add EFI_DISK_IO_PROTOCOL
for all produced EFI_BLOCK_IO_PROTOCOL interfaces. Unfortunately U-Boot
doesn't do this, so fallback to block I/O if disk I/O is not there.
diffstat:
 sys/stand/efiboot/efiblock.c | 101 ++++++++++++++++++++++++++++++++++++------
 1 files changed, 85 insertions(+), 16 deletions(-)
diffs (193 lines):
diff -r f59254293717 -r 06edf87d8d8f sys/stand/efiboot/efiblock.c
--- a/sys/stand/efiboot/efiblock.c Tue Jun 22 19:53:58 2021 +0000
+++ b/sys/stand/efiboot/efiblock.c Tue Jun 22 21:56:51 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efiblock.c,v 1.14 2021年06月21日 21:18:47 jmcneill Exp $ */
+/* $NetBSD: efiblock.c,v 1.15 2021年06月22日 21:56:51 jmcneill Exp $ */
 
 /*-
 * Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -118,7 +118,74 @@ efi_block_generate_hash_mbr(struct efi_b
 }
 
 static EFI_STATUS
-efi_block_disk_readahead(struct efi_block_dev *bdev, UINT64 off, void *buf,
+efi_block_do_read_blockio(struct efi_block_dev *bdev, UINT64 off, void *buf,
+ UINTN bufsize)
+{
+ UINT8 *blkbuf, *blkbuf_start;
+ EFI_STATUS status;
+ EFI_LBA lba_start, lba_end;
+ UINT64 blkbuf_offset;
+ UINT64 blkbuf_size;
+
+ lba_start = off / bdev->bio->Media->BlockSize;
+ lba_end = (off + bufsize + bdev->bio->Media->BlockSize - 1) /
+ bdev->bio->Media->BlockSize;
+ blkbuf_offset = off % bdev->bio->Media->BlockSize;
+ blkbuf_size = (lba_end - lba_start) * bdev->bio->Media->BlockSize;
+ if (bdev->bio->Media->IoAlign > 1) {
+ blkbuf_size += bdev->bio->Media->IoAlign - 1;
+ }
+
+ blkbuf = AllocatePool(blkbuf_size);
+ if (blkbuf == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (bdev->bio->Media->IoAlign > 1) {
+ blkbuf_start = (void *)roundup2((intptr_t)blkbuf,
+ bdev->bio->Media->IoAlign);
+ } else {
+ blkbuf_start = blkbuf;
+ }
+
+ status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio,
+ bdev->media_id, lba_start, blkbuf_size, blkbuf_start);
+ if (EFI_ERROR(status)) {
+ goto done;
+ }
+
+ memcpy(buf, blkbuf_start + blkbuf_offset, bufsize);
+
+done:
+ FreePool(blkbuf);
+ return status;
+}
+
+static EFI_STATUS
+efi_block_do_read_diskio(struct efi_block_dev *bdev, UINT64 off, void *buf,
+ UINTN bufsize)
+{
+ return uefi_call_wrapper(bdev->dio->ReadDisk, 5, bdev->dio,
+ bdev->media_id, off, bufsize, buf);
+}
+
+static EFI_STATUS
+efi_block_do_read(struct efi_block_dev *bdev, UINT64 off, void *buf,
+ UINTN bufsize)
+{
+ /*
+ * Perform read access using EFI_DISK_IO_PROTOCOL if available,
+ * otherwise use EFI_BLOCK_IO_PROTOCOL.
+ */
+ if (bdev->dio != NULL) {
+ return efi_block_do_read_diskio(bdev, off, buf, bufsize);
+ } else {
+ return efi_block_do_read_blockio(bdev, off, buf, bufsize);
+ }
+}
+
+static EFI_STATUS
+efi_block_readahead(struct efi_block_dev *bdev, UINT64 off, void *buf,
 UINTN bufsize)
 {
 EFI_STATUS status;
@@ -140,8 +207,7 @@ efi_block_disk_readahead(struct efi_bloc
 if (len > mediasize - off) {
 len = mediasize - off;
 }
- status = uefi_call_wrapper(bdev->dio->ReadDisk, 5, bdev->dio,
- bdev->media_id, off, len, efi_ra_buffer);
+ status = efi_block_do_read(bdev, off, efi_ra_buffer, len);
 if (EFI_ERROR(status)) {
 efi_ra_start = efi_ra_length = 0;
 return status;
@@ -156,15 +222,14 @@ efi_block_disk_readahead(struct efi_bloc
 }
 
 static EFI_STATUS
-efi_block_disk_read(struct efi_block_dev *bdev, UINT64 off, void *buf,
+efi_block_read(struct efi_block_dev *bdev, UINT64 off, void *buf,
 UINTN bufsize)
 {
 if (efi_ra_enable) {
- return efi_block_disk_readahead(bdev, off, buf, bufsize);
+ return efi_block_readahead(bdev, off, buf, bufsize);
 }
 
- return uefi_call_wrapper(bdev->dio->ReadDisk, 5, bdev->dio,
- bdev->media_id, off, bufsize, buf);
+ return efi_block_do_read(bdev, off, buf, bufsize);
 }
 
 static int
@@ -176,7 +241,7 @@ efi_block_find_partitions_cd9660(struct 
 EFI_LBA lba;
 
 for (lba = 16;; lba++) {
- status = efi_block_disk_read(bdev,
+ status = efi_block_read(bdev,
 lba * ISO_DEFAULT_BLOCK_SIZE, &vd, sizeof(vd));
 if (EFI_ERROR(status)) {
 goto io_error;
@@ -220,7 +285,7 @@ efi_block_find_partitions_disklabel(stru
 EFI_STATUS status;
 int n;
 
- status = efi_block_disk_read(bdev,
+ status = efi_block_read(bdev,
 ((EFI_LBA)start + LABELSECTOR) * DEV_BSIZE, buf, sizeof(buf));
 if (EFI_ERROR(status) || getdisklabel(buf, &d) != NULL) {
 FreePool(buf);
@@ -268,7 +333,7 @@ efi_block_find_partitions_mbr(struct efi
 EFI_STATUS status;
 int n;
 
- status = efi_block_disk_read(bdev, 0, &mbr, sizeof(mbr));
+ status = efi_block_read(bdev, 0, &mbr, sizeof(mbr));
 if (EFI_ERROR(status))
 return EIO;
 
@@ -348,7 +413,7 @@ efi_block_find_partitions_gpt(struct efi
 void *buf;
 UINTN sz;
 
- status = efi_block_disk_read(bdev, GPT_HDR_BLKNO * DEV_BSIZE, &hdr,
+ status = efi_block_read(bdev, GPT_HDR_BLKNO * DEV_BSIZE, &hdr,
 sizeof(hdr));
 if (EFI_ERROR(status)) {
 return EIO;
@@ -364,7 +429,7 @@ efi_block_find_partitions_gpt(struct efi
 if (buf == NULL)
 return ENOMEM;
 
- status = efi_block_disk_read(bdev,
+ status = efi_block_read(bdev,
 le64toh(hdr.hdr_lba_table) * DEV_BSIZE, buf, sz);
 if (EFI_ERROR(status)) {
 FreePool(buf);
@@ -421,18 +486,22 @@ efi_block_probe(void)
 }
 
 for (n = 0; n < efi_nblock; n++) {
+ /* EFI_BLOCK_IO_PROTOCOL is required */
 status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_block[n],
 &BlockIoProtocol, (void **)&bio);
 if (EFI_ERROR(status) || !bio->Media->MediaPresent)
 continue;
 
+ /* Ignore logical partitions (we do our own partition discovery) */
 if (bio->Media->LogicalPartition)
 continue;
 
+ /* EFI_DISK_IO_PROTOCOL is optional */
 status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_block[n],
 &DiskIoProtocol, (void **)&dio);
- if (EFI_ERROR(status))
- continue;
+ if (EFI_ERROR(status)) {
+ dio = NULL;
+ }
 
 bdev = alloc(sizeof(*bdev));
 bdev->index = devindex++;
@@ -629,7 +698,7 @@ efi_block_strategy(void *devdata, int rw
 return EINVAL;
 }
 
- status = efi_block_disk_read(bpart->bdev, off, buf, size);
+ status = efi_block_read(bpart->bdev, off, buf, size);
 if (EFI_ERROR(status))
 return EIO;
 


Home | Main Index | Thread Index | Old Index

AltStyle によって変換されたページ (->オリジナル) /