From aa74bae70eee74b0c613425ef5d018c3b378bb42 Mon Sep 17 00:00:00 2001 From: YASUOKA Masahiko Date: Wed, 17 Mar 2021 05:41:35 +0000 Subject: 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 --- sys/arch/amd64/stand/efiboot/conf.c | 4 +- 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); -- cgit v1.2.3