diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2021-03-17 05:41:35 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2021-03-17 05:41:35 +0000 |
commit | aa74bae70eee74b0c613425ef5d018c3b378bb42 (patch) | |
tree | e68da89755b8918a8265549f6afb52cc8cc055c5 /sys/arch/amd64/stand/efiboot | |
parent | 72f165bcd4d46206d9526acc629912b0e0d13d5a (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/amd64/stand/efiboot')
-rw-r--r-- | sys/arch/amd64/stand/efiboot/conf.c | 4 | ||||
-rw-r--r-- | sys/arch/amd64/stand/efiboot/efidev.c | 110 |
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); |