NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-evbarm/54554
The following reply was made to PR port-evbarm/54554; it has been noted by GNATS.
From: Simon South <simon%simonsouth.net@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc:
Subject: Re: port-evbarm/54554
Date: Tue, 17 Sep 2019 11:27:50 -0400
This is a multi-part message in MIME format.
--------------42AFB12FB7BE06A1DACFB984
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Here's a patch that fixes this problem by ensuring calls to ReadBlocks
in efiblock.c always pass a buffer aligned as requested by the device.
In the case of efi_block_strategy(), this is done by checking the
alignment of the buffer passed by the caller and, if necessary,
allocating a second buffer, writing into it at the correct alignment and
copying the result back into the caller's buffer.
Note I've taken the liberty of wrapping at 80 columns the lines I modified.
I've tested this successfully on a PINE64 ROCK64 (only).
--
Simon South
simon%simonsouth.net@localhost
--------------42AFB12FB7BE06A1DACFB984
Content-Type: text/x-patch; charset=UTF-8;
name="54554-efiboot-align-buffers.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="54554-efiboot-align-buffers.patch"
Index: sys/stand/efiboot/efiblock.c
===================================================================
RCS file: /cvsroot/src/sys/stand/efiboot/efiblock.c,v
retrieving revision 1.5
diff -u -r1.5 efiblock.c
--- sys/stand/efiboot/efiblock.c 9 Mar 2019 13:16:42 -0000 1.5
+++ sys/stand/efiboot/efiblock.c 17 Sep 2019 15:23:59 -0000
@@ -106,19 +106,22 @@
struct partition *p;
EFI_STATUS status;
EFI_LBA lba;
- uint8_t *buf;
+ uint8_t *buf, *aligned_buf;
UINT32 sz;
int n;
sz = __MAX(sizeof(d), bdev->bio->Media->BlockSize);
sz = roundup(sz, bdev->bio->Media->BlockSize);
- buf = AllocatePool(sz);
+ buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1);
if (!buf)
return ENOMEM;
+ aligned_buf = (uint8_t *)(((intptr_t)buf + bdev->bio->Media->IoAlign - 1) &
+ ~(bdev->bio->Media->IoAlign - 1));
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, aligned_buf);
+ if (EFI_ERROR(status) || getdisklabel(aligned_buf, &d) != NULL) {
FreePool(buf);
return EIO;
}
@@ -159,22 +162,25 @@
struct mbr_sector mbr;
struct mbr_partition *mbr_part;
EFI_STATUS status;
- uint8_t *buf;
+ uint8_t *buf, *aligned_buf;
UINT32 sz;
int n;
sz = __MAX(sizeof(mbr), bdev->bio->Media->BlockSize);
sz = roundup(sz, bdev->bio->Media->BlockSize);
- buf = AllocatePool(sz);
+ buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1);
if (!buf)
return ENOMEM;
+ aligned_buf = (uint8_t *)(((intptr_t)buf + bdev->bio->Media->IoAlign - 1) &
+ ~(bdev->bio->Media->IoAlign - 1));
- 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, aligned_buf);
if (EFI_ERROR(status)) {
FreePool(buf);
return EIO;
}
- memcpy(&mbr, buf, sizeof(mbr));
+ memcpy(&mbr, aligned_buf, sizeof(mbr));
FreePool(buf);
if (le32toh(mbr.mbr_magic) != MBR_MAGIC)
@@ -241,20 +247,23 @@
struct gpt_ent ent;
EFI_STATUS status;
UINT32 sz, entry;
- uint8_t *buf;
+ uint8_t *buf, *aligned_buf;
sz = __MAX(sizeof(hdr), bdev->bio->Media->BlockSize);
sz = roundup(sz, bdev->bio->Media->BlockSize);
- buf = AllocatePool(sz);
+ buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1);
if (!buf)
return ENOMEM;
+ aligned_buf = (uint8_t *)(((intptr_t)buf + bdev->bio->Media->IoAlign - 1) &
+ ~(bdev->bio->Media->IoAlign - 1));
- 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, aligned_buf);
if (EFI_ERROR(status)) {
FreePool(buf);
return EIO;
}
- memcpy(&hdr, buf, sizeof(hdr));
+ memcpy(&hdr, aligned_buf, sizeof(hdr));
FreePool(buf);
if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0)
@@ -264,18 +273,22 @@
sz = __MAX(le32toh(hdr.hdr_entsz) * le32toh(hdr.hdr_entries), bdev->bio->Media->BlockSize);
sz = roundup(sz, bdev->bio->Media->BlockSize);
- buf = AllocatePool(sz);
+ buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1);
if (!buf)
return ENOMEM;
+ aligned_buf = (uint8_t *)(((intptr_t)buf + bdev->bio->Media->IoAlign - 1) &
+ ~(bdev->bio->Media->IoAlign - 1));
- 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, aligned_buf);
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, aligned_buf + (entry * le32toh(hdr.hdr_entsz)),
+ sizeof(ent));
efi_block_find_partitions_gpt_entry(bdev, &hdr, &ent, entry);
}
@@ -493,6 +506,7 @@
{
struct efi_block_part *bpart = devdata;
EFI_STATUS status;
+ void *allocated_buf, *aligned_buf;
if (rw != F_READ)
return EROFS;
@@ -518,9 +532,30 @@
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 (((intptr_t)buf & ~(bpart->bdev->bio->Media->IoAlign - 1)) == 0) {
+ allocated_buf = NULL;
+ aligned_buf = buf;
+ } else {
+ allocated_buf = AllocatePool(size +
+ bpart->bdev->bio->Media->IoAlign - 1);
+ if (!allocated_buf)
+ return ENOMEM;
+ aligned_buf = (void *)(((intptr_t)allocated_buf +
+ bpart->bdev->bio->Media->IoAlign - 1) &
+ ~(bpart->bdev->bio->Media->IoAlign - 1));
+ }
+
+ 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)
+ FreePool(allocated_buf);
return EIO;
+ }
+ if (allocated_buf) {
+ memcpy(buf, aligned_buf, size);
+ FreePool(allocated_buf);
+ }
*rsize = size;
--------------42AFB12FB7BE06A1DACFB984--
Home |
Main Index |
Thread Index |
Old Index