Source-Changes-HG archive

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

[src/trunk]: src/sys/stand/efiboot Honour block device's IO alignment require...



details:   https://anonhg.NetBSD.org/src/rev/bac9618db85f
branches:  trunk
changeset: 459682:bac9618db85f
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Sep 21 10:19:37 2019 +0000

description:
Honour block device's IO alignment requirements.

Patch from Simon South <simon%simonsouth.net@localhost> in PR# 54554

diffstat:

 sys/stand/efiboot/efiblock.c |  79 +++++++++++++++++++++++++++++++------------
 1 files changed, 57 insertions(+), 22 deletions(-)

diffs (173 lines):

diff -r 8af9b23cc1f4 -r bac9618db85f sys/stand/efiboot/efiblock.c
--- a/sys/stand/efiboot/efiblock.c      Sat Sep 21 09:23:11 2019 +0000
+++ b/sys/stand/efiboot/efiblock.c      Sat Sep 21 10:19:37 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efiblock.c,v 1.5 2019/03/09 13:16:42 jmcneill Exp $ */
+/* $NetBSD: efiblock.c,v 1.6 2019/09/21 10:19:37 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -98,6 +98,23 @@
        MD5Final(bpart->hash, &md5ctx);
 }
 
+static void *
+efi_block_allocate_device_buffer(struct efi_block_dev *bdev, UINTN size,
+       void **buf_start)
+{
+       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 *)(((intptr_t)buf +
+                       bdev->bio->Media->IoAlign - 1) & ~(bdev->bio->Media->IoAlign - 1));
+       }
+
+       return buf;
+}
+
 static int
 efi_block_find_partitions_disklabel(struct efi_block_dev *bdev, struct mbr_sector *mbr, uint32_t start, uint32_t size)
 {
@@ -106,19 +123,19 @@
        struct partition *p;
        EFI_STATUS status;
        EFI_LBA lba;
-       uint8_t *buf;
+       void *buf, *buf_start;
        UINT32 sz;
        int n;
 
        sz = __MAX(sizeof(d), bdev->bio->Media->BlockSize);
        sz = roundup(sz, bdev->bio->Media->BlockSize);
-       buf = AllocatePool(sz);
-       if (!buf)
+       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);
-       if (EFI_ERROR(status) || getdisklabel(buf, &d) != NULL) {
+       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) {
                FreePool(buf);
                return EIO;
        }
@@ -159,22 +176,22 @@
        struct mbr_sector mbr;
        struct mbr_partition *mbr_part;
        EFI_STATUS status;
-       uint8_t *buf;
+       void *buf, *buf_start;
        UINT32 sz;
        int n;
 
        sz = __MAX(sizeof(mbr), bdev->bio->Media->BlockSize);
        sz = roundup(sz, bdev->bio->Media->BlockSize);
-       buf = AllocatePool(sz);
-       if (!buf)
+       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);
+       status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id,
+               0, sz, buf_start);
        if (EFI_ERROR(status)) {
                FreePool(buf);
                return EIO;
        }
-       memcpy(&mbr, buf, sizeof(mbr));
+       memcpy(&mbr, buf_start, sizeof(mbr));
        FreePool(buf);
 
        if (le32toh(mbr.mbr_magic) != MBR_MAGIC)
@@ -240,21 +257,21 @@
        struct gpt_hdr hdr;
        struct gpt_ent ent;
        EFI_STATUS status;
+       void *buf, *buf_start;
        UINT32 sz, entry;
-       uint8_t *buf;
 
        sz = __MAX(sizeof(hdr), bdev->bio->Media->BlockSize);
        sz = roundup(sz, bdev->bio->Media->BlockSize);
-       buf = AllocatePool(sz);
-       if (!buf)
+       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, GPT_HDR_BLKNO, sz, buf);
+       status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id,
+               GPT_HDR_BLKNO, sz, buf_start);
        if (EFI_ERROR(status)) {
                FreePool(buf);
                return EIO;
        }
-       memcpy(&hdr, buf, sizeof(hdr));
+       memcpy(&hdr, buf_start, sizeof(hdr));
        FreePool(buf);
 
        if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0)
@@ -264,18 +281,19 @@
 
        sz = __MAX(le32toh(hdr.hdr_entsz) * le32toh(hdr.hdr_entries), bdev->bio->Media->BlockSize);
        sz = roundup(sz, bdev->bio->Media->BlockSize);
-       buf = AllocatePool(sz);
-       if (!buf)
+       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, le64toh(hdr.hdr_lba_table), sz, buf);
+       status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id,
+               le64toh(hdr.hdr_lba_table), sz, buf_start);
        if (EFI_ERROR(status)) {
                FreePool(buf);
                return EIO;
        }
 
        for (entry = 0; entry < le32toh(hdr.hdr_entries); entry++) {
-               memcpy(&ent, buf + (entry * le32toh(hdr.hdr_entsz)), sizeof(ent));
+               memcpy(&ent, buf_start + (entry * le32toh(hdr.hdr_entsz)),
+                       sizeof(ent));
                efi_block_find_partitions_gpt_entry(bdev, &hdr, &ent, entry);
        }
 
@@ -493,6 +511,7 @@
 {
        struct efi_block_part *bpart = devdata;
        EFI_STATUS status;
+       void *allocated_buf, *aligned_buf;
 
        if (rw != F_READ)
                return EROFS;
@@ -518,9 +537,25 @@
                return EINVAL;
        }
 
-       status = uefi_call_wrapper(bpart->bdev->bio->ReadBlocks, 5, bpart->bdev->bio, bpart->bdev->media_id, dblk, size, buf);
-       if (EFI_ERROR(status))
+       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);
                return EIO;
+       }
+       if (allocated_buf != NULL) {
+               memcpy(buf, aligned_buf, size);
+               FreePool(allocated_buf);
+       }
 
        *rsize = size;
 



Home | Main Index | Thread Index | Old Index