Module Name: src Committed By: martin Date: Sun Sep 22 12:37:39 UTC 2019
Modified Files: src/sys/stand/efiboot [netbsd-9]: efiblock.c Log Message: Pull up following revision(s) (requested by jmcneill in ticket #225): sys/stand/efiboot/efiblock.c: revision 1.6 Honour block device's IO alignment requirements. Patch from Simon South <simon%simonsouth.net@localhost> in PR# 54554 To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.5.6.1 src/sys/stand/efiboot/efiblock.c 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.5 src/sys/stand/efiboot/efiblock.c:1.5.6.1 --- src/sys/stand/efiboot/efiblock.c:1.5 Sat Mar 9 13:16:42 2019 +++ src/sys/stand/efiboot/efiblock.c Sun Sep 22 12:37:39 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: efiblock.c,v 1.5 2019/03/09 13:16:42 jmcneill Exp $ */ +/* $NetBSD: efiblock.c,v 1.5.6.1 2019/09/22 12:37:39 martin Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -98,6 +98,23 @@ 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) +{ + 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 @@ efi_block_find_partitions_disklabel(stru 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 @@ efi_block_find_partitions_mbr(struct efi 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 @@ 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; - 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 @@ efi_block_find_partitions_gpt(struct efi 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 @@ efi_block_strategy(void *devdata, int rw { struct efi_block_part *bpart = devdata; EFI_STATUS status; + void *allocated_buf, *aligned_buf; if (rw != F_READ) return EROFS; @@ -518,9 +537,25 @@ efi_block_strategy(void *devdata, int rw 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;