summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2021-03-17 05:41:35 +0000
committerYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2021-03-17 05:41:35 +0000
commitaa74bae70eee74b0c613425ef5d018c3b378bb42 (patch)
treee68da89755b8918a8265549f6afb52cc8cc055c5 /sys/arch
parent72f165bcd4d46206d9526acc629912b0e0d13d5a (diff)
Always use an allocated buffer for {Read,Write}Blocks() to make
efid_io() simpler. Also fixes the problem on some machines when boot from CD-ROM. It happened because the previous version passed unaligned pointers to the functions even if it is restricted by the IoAlign property of the media. idea from kettenis, work with asou ok kettenis
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/stand/efiboot/conf.c4
-rw-r--r--sys/arch/amd64/stand/efiboot/efidev.c110
2 files changed, 34 insertions, 80 deletions
diff --git a/sys/arch/amd64/stand/efiboot/conf.c b/sys/arch/amd64/stand/efiboot/conf.c
index f6eb1e2b8e2..3304a443f5b 100644
--- a/sys/arch/amd64/stand/efiboot/conf.c
+++ b/sys/arch/amd64/stand/efiboot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.33 2020/12/09 18:10:18 krw Exp $ */
+/* $OpenBSD: conf.c,v 1.34 2021/03/17 05:41:34 yasuoka Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -40,7 +40,7 @@
#include "efidev.h"
#include "efipxe.h"
-const char version[] = "3.56";
+const char version[] = "3.57";
#ifdef EFI_DEBUG
int debug = 0;
diff --git a/sys/arch/amd64/stand/efiboot/efidev.c b/sys/arch/amd64/stand/efiboot/efidev.c
index 480f5f52e10..a6ce8fb5bc6 100644
--- a/sys/arch/amd64/stand/efiboot/efidev.c
+++ b/sys/arch/amd64/stand/efiboot/efidev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: efidev.c,v 1.32 2020/12/09 18:10:18 krw Exp $ */
+/* $OpenBSD: efidev.c,v 1.33 2021/03/17 05:41:34 yasuoka Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -84,10 +84,10 @@ efid_init(struct diskinfo *dip, void *handle)
static EFI_STATUS
efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf)
{
- u_int blks, lba, i_lblks, i_tblks, i_nblks;
+ u_int blks, start, end;
EFI_STATUS status = EFI_SUCCESS;
- static u_char *iblk = NULL;
- static u_int iblksz = 0;
+ static u_char *ibuf = NULL;
+ static u_int ibufsz = 0;
/* block count of the intrisic block size in DEV_BSIZE */
blks = EFI_BLKSPERSEC(ed);
@@ -95,90 +95,44 @@ efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf)
/* block size < 512. HP Stream 13 actually has such a disk. */
return (EFI_UNSUPPORTED);
- /* leading and trailing unaligned blocks in intrisic block */
- i_lblks = ((off % blks) == 0)? 0 : blks - (off % blks);
- i_tblks = (nsect > i_lblks)? (off + nsect) % blks : 0;
+ start = off / blks;
+ end = (off + nsect + blks - 1) / blks;
- /* aligned blocks in intrisic block */
- i_nblks = (nsect > i_lblks + i_tblks)? nsect - (i_lblks + i_tblks) : 0;
-
- lba = (off + i_lblks) / blks;
-
- /* allocate the space for reading unaligned blocks */
- if (ed->blkio->Media->BlockSize != DEV_BSIZE) {
- if (iblk && iblksz < ed->blkio->Media->BlockSize) {
- free(iblk, iblksz);
- iblk = NULL;
- }
- if (iblk == NULL) {
- iblk = alloc(ed->blkio->Media->BlockSize);
- iblksz = ed->blkio->Media->BlockSize;
- }
+ /* always use an aligned buffer as some media require this */
+ if (ibuf && ibufsz < (end - start) * ed->blkio->Media->BlockSize) {
+ free(ibuf, ibufsz);
+ ibuf = NULL;
}
+ if (ibuf == NULL) {
+ ibufsz = (end - start) * ed->blkio->Media->BlockSize;
+ ibuf = alloc(ibufsz);
+ }
+
switch (rw) {
case F_READ:
- if (i_lblks > 0) {
- status = EFI_CALL(ed->blkio->ReadBlocks,
- ed->blkio, ed->mediaid, lba - 1,
- ed->blkio->Media->BlockSize, iblk);
- if (EFI_ERROR(status))
- goto on_eio;
- memcpy(buf, iblk + (blks - i_lblks) * DEV_BSIZE,
- min(nsect, i_lblks) * DEV_BSIZE);
- }
- if (i_nblks > 0) {
- status = EFI_CALL(ed->blkio->ReadBlocks,
- ed->blkio, ed->mediaid, lba,
- ed->blkio->Media->BlockSize * (i_nblks / blks),
- buf + (i_lblks * DEV_BSIZE));
- if (EFI_ERROR(status))
- goto on_eio;
- }
- if (i_tblks > 0) {
- status = EFI_CALL(ed->blkio->ReadBlocks,
- ed->blkio, ed->mediaid, lba + (i_nblks / blks),
- ed->blkio->Media->BlockSize, iblk);
- if (EFI_ERROR(status))
- goto on_eio;
- memcpy(buf + (i_lblks + i_nblks) * DEV_BSIZE, iblk,
- i_tblks * DEV_BSIZE);
- }
+ status = EFI_CALL(ed->blkio->ReadBlocks,
+ ed->blkio, ed->mediaid, start,
+ (end - start) * ed->blkio->Media->BlockSize, ibuf);
+ if (EFI_ERROR(status))
+ goto on_eio;
+ memcpy(buf, ibuf + DEV_BSIZE * (off - start * blks),
+ DEV_BSIZE * nsect);
break;
case F_WRITE:
- if (ed->blkio->Media->ReadOnly)
- goto on_eio;
- if (i_lblks > 0) {
+ if (off % blks != 0 || nsect % blks != 0) {
status = EFI_CALL(ed->blkio->ReadBlocks,
- ed->blkio, ed->mediaid, lba - 1,
- ed->blkio->Media->BlockSize, iblk);
+ ed->blkio, ed->mediaid, start,
+ (end - start) * ed->blkio->Media->BlockSize, ibuf);
if (EFI_ERROR(status))
goto on_eio;
- memcpy(iblk + (blks - i_lblks) * DEV_BSIZE, buf,
- min(nsect, i_lblks) * DEV_BSIZE);
- status = EFI_CALL(ed->blkio->WriteBlocks,
- ed->blkio, ed->mediaid, lba - 1,
- ed->blkio->Media->BlockSize, iblk);
- }
- if (i_nblks > 0) {
- status = EFI_CALL(ed->blkio->WriteBlocks,
- ed->blkio, ed->mediaid, lba,
- ed->blkio->Media->BlockSize * (i_nblks / blks),
- buf + (i_lblks * DEV_BSIZE));
- if (EFI_ERROR(status))
- goto on_eio;
- }
- if (i_tblks > 0) {
- status = EFI_CALL(ed->blkio->ReadBlocks,
- ed->blkio, ed->mediaid, lba + (i_nblks / blks),
- ed->blkio->Media->BlockSize, iblk);
- if (EFI_ERROR(status))
- goto on_eio;
- memcpy(iblk, buf + (i_lblks + i_nblks) * DEV_BSIZE,
- i_tblks * DEV_BSIZE);
- status = EFI_CALL(ed->blkio->WriteBlocks,
- ed->blkio, ed->mediaid, lba + (i_nblks / blks),
- ed->blkio->Media->BlockSize, iblk);
}
+ memcpy(ibuf + DEV_BSIZE * (off - start * blks), buf,
+ DEV_BSIZE * nsect);
+ status = EFI_CALL(ed->blkio->WriteBlocks,
+ ed->blkio, ed->mediaid, start,
+ (end - start) * ed->blkio->Media->BlockSize, ibuf);
+ if (EFI_ERROR(status))
+ goto on_eio;
break;
}
return (EFI_SUCCESS);