NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-evbarm/54554 (Booting via U-Boot fails due to buffer misalignment)
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 (Booting via U-Boot fails due to buffer
misalignment)
Date: Wed, 18 Sep 2019 17:42:48 -0400
This is a multi-part message in MIME format.
--------------6AB8168758FF6A2572F5CA1E
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
On 2019-09-18 9:48 a.m., Jared McNeill wrote:
> According to UEFI IoAlign may be 0 or 1 ("no alignment required"). Can
> you update the patch to take this into consideration?
Here's an updated patch that handles this case. I've also reformatted
the modified code slightly to match the style guide.
I've tested this on my ROCK64 and it seems to work fine.
--
Simon South
simon%simonsouth.net@localhost
--------------6AB8168758FF6A2572F5CA1E
Content-Type: text/x-patch; charset=UTF-8;
name="54554-efiboot-align-buffers-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="54554-efiboot-align-buffers-2.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 18 Sep 2019 21:23:14 -0000
@@ -106,19 +106,28 @@
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);
- if (!buf)
- return ENOMEM;
+
+ if (bdev->bio->Media->IoAlign <= 1) {
+ if ((buf = AllocatePool(sz)) == NULL)
+ return ENOMEM;
+ aligned_buf = buf;
+ } else {
+ if ((buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1)) == NULL)
+ 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 +168,31 @@
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);
- if (!buf)
- return ENOMEM;
- status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, 0, sz, buf);
+ if (bdev->bio->Media->IoAlign <= 1) {
+ if ((buf = AllocatePool(sz)) == NULL)
+ return ENOMEM;
+ aligned_buf = buf;
+ } else {
+ if ((buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1)) == NULL)
+ 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, 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 +259,29 @@
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);
- if (!buf)
- return ENOMEM;
- status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, GPT_HDR_BLKNO, sz, buf);
+ if (bdev->bio->Media->IoAlign <= 1) {
+ if ((buf = AllocatePool(sz)) == NULL)
+ return ENOMEM;
+ aligned_buf = buf;
+ } else {
+ if ((buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1)) == NULL)
+ 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, 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 +291,28 @@
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)
- return ENOMEM;
- status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, le64toh(hdr.hdr_lba_table), sz, buf);
+ if (bdev->bio->Media->IoAlign <= 1) {
+ if ((buf = AllocatePool(sz)) == NULL)
+ return ENOMEM;
+ aligned_buf = buf;
+ } else {
+ if ((buf = AllocatePool(sz + bdev->bio->Media->IoAlign - 1)) == NULL)
+ 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, 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 +530,7 @@
{
struct efi_block_part *bpart = devdata;
EFI_STATUS status;
+ void *allocated_buf, *aligned_buf;
if (rw != F_READ)
return EROFS;
@@ -518,9 +556,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 ((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 = AllocatePool(size +
+ bpart->bdev->bio->Media->IoAlign - 1)) == NULL)
+ 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 != NULL)
+ FreePool(allocated_buf);
return EIO;
+ }
+ if (allocated_buf != NULL) {
+ memcpy(buf, aligned_buf, size);
+ FreePool(allocated_buf);
+ }
*rsize = size;
--------------6AB8168758FF6A2572F5CA1E--
Home |
Main Index |
Thread Index |
Old Index