summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2019-07-29 14:51:40 +0000
committerYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2019-07-29 14:51:40 +0000
commited9d483a217ef7776bcb12fb7aa535339af9a4a8 (patch)
treea2c9b02d7fc17fb0b620d6042c9c07ec5f8b23e9 /sys/arch
parent066c099230e6d90ed43206033e7ba5c22f754007 (diff)
Support disk write in efiboot. Requested by deraadt.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/stand/efiboot/efidev.c58
1 files changed, 44 insertions, 14 deletions
diff --git a/sys/arch/amd64/stand/efiboot/efidev.c b/sys/arch/amd64/stand/efiboot/efidev.c
index 47f62b92b96..e3ac1fe10ee 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.30 2018/08/10 16:41:35 jsing Exp $ */
+/* $OpenBSD: efidev.c,v 1.31 2019/07/29 14:51:39 yasuoka Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -104,19 +104,19 @@ efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf)
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;
+ }
+ }
switch (rw) {
case F_READ:
- /* 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;
- }
- }
if (i_lblks > 0) {
status = EFI_CALL(ed->blkio->ReadBlocks,
ed->blkio, ed->mediaid, lba - 1,
@@ -147,8 +147,38 @@ efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf)
case F_WRITE:
if (ed->blkio->Media->ReadOnly)
goto on_eio;
- /* XXX not yet */
- goto on_eio;
+ 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(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);
+ }
break;
}
return (EFI_SUCCESS);