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