diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-01-13 10:17:10 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-01-13 10:17:10 +0000 |
commit | c20fa8a3a4e42a1a90217ae3bf42483b9dc68036 (patch) | |
tree | 5d871844d2041fb78a065cb4326c911d1a00893b /sys/arch | |
parent | d390f775e09aee0fd7eb7ae8815fdd19beead564 (diff) |
Add the capability to boot from another block device than the one that
efiboot was loaded from. Code taken from arm64 with softraid support
dropped for now.
ok jsg@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/armv7/stand/efiboot/conf.c | 9 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/disk.h | 18 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/efiboot.c | 75 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/efidev.c | 429 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/efidev.h | 3 |
5 files changed, 461 insertions, 73 deletions
diff --git a/sys/arch/armv7/stand/efiboot/conf.c b/sys/arch/armv7/stand/efiboot/conf.c index 929e063e0ea..02fc2781c92 100644 --- a/sys/arch/armv7/stand/efiboot/conf.c +++ b/sys/arch/armv7/stand/efiboot/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.21 2019/10/29 02:55:51 deraadt Exp $ */ +/* $OpenBSD: conf.c,v 1.22 2020/01/13 10:17:09 kettenis Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -27,16 +27,21 @@ */ #include <sys/param.h> +#include <sys/queue.h> +#include <sys/disklabel.h> #include <lib/libsa/stand.h> #include <lib/libsa/tftp.h> #include <lib/libsa/ufs.h> #include <dev/cons.h> +#include <efi.h> + +#include "disk.h" #include "efiboot.h" #include "efidev.h" #include "efipxe.h" -const char version[] = "1.8"; +const char version[] = "1.9"; int debug = 0; struct fs_ops file_system[] = { diff --git a/sys/arch/armv7/stand/efiboot/disk.h b/sys/arch/armv7/stand/efiboot/disk.h index ff3eb26a888..8832ab519a3 100644 --- a/sys/arch/armv7/stand/efiboot/disk.h +++ b/sys/arch/armv7/stand/efiboot/disk.h @@ -1,8 +1,10 @@ -/* $OpenBSD: disk.h,v 1.2 2018/03/31 18:07:14 patrick Exp $ */ +/* $OpenBSD: disk.h,v 1.3 2020/01/13 10:17:09 kettenis Exp $ */ #ifndef _DISK_H #define _DISK_H +#include <sys/queue.h> + typedef struct efi_diskinfo { EFI_BLOCK_IO *blkio; UINT32 mediaid; @@ -12,9 +14,19 @@ struct diskinfo { struct efi_diskinfo ed; struct disklabel disklabel; - u_int sc_part; + u_int part; + u_int flags; +#define DISKINFO_FLAG_GOODLABEL (1 << 0) + + int (*diskio)(int, struct diskinfo *, u_int, int, void *); + int (*strategy)(void *, int, daddr32_t, size_t, void *, size_t *); + + TAILQ_ENTRY(diskinfo) list; }; +TAILQ_HEAD(disklist_lh, diskinfo); + +extern struct diskinfo *bootdev_dip; -extern struct diskinfo diskinfo; +extern struct disklist_lh disklist; #endif /* _DISK_H */ diff --git a/sys/arch/armv7/stand/efiboot/efiboot.c b/sys/arch/armv7/stand/efiboot/efiboot.c index b26734ca581..0b55ec254ae 100644 --- a/sys/arch/armv7/stand/efiboot/efiboot.c +++ b/sys/arch/armv7/stand/efiboot/efiboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efiboot.c,v 1.25 2019/10/25 10:06:40 kettenis Exp $ */ +/* $OpenBSD: efiboot.c,v 1.26 2020/01/13 10:17:09 kettenis Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net> @@ -19,6 +19,7 @@ #include <sys/param.h> #include <sys/queue.h> +#include <sys/stat.h> #include <dev/cons.h> #include <sys/disklabel.h> @@ -30,11 +31,13 @@ #include <lib/libkern/libkern.h> #include <stand/boot/cmd.h> +#include "libsa.h" #include "disk.h" + +#include "efidev.h" #include "efiboot.h" #include "eficall.h" #include "fdt.h" -#include "libsa.h" EFI_SYSTEM_TABLE *ST; EFI_BOOT_SERVICES *BS; @@ -205,19 +208,23 @@ efi_heap_init(void) panic("BS->AllocatePages()"); } -EFI_BLOCK_IO *disk; +struct disklist_lh disklist; +struct diskinfo *bootdev_dip; void efi_diskprobe(void) { - int i, depth = -1; + int i, bootdev = 0, depth = -1; UINTN sz; EFI_STATUS status; EFI_HANDLE *handles = NULL; EFI_BLOCK_IO *blkio; EFI_BLOCK_IO_MEDIA *media; + struct diskinfo *di; EFI_DEVICE_PATH *dp; + TAILQ_INIT(&disklist); + sz = 0; status = EFI_CALL(BS->LocateHandle, ByProtocol, &blkio_guid, 0, &sz, 0); if (status == EFI_BUFFER_TOO_SMALL) { @@ -249,20 +256,35 @@ efi_diskprobe(void) media = blkio->Media; if (media->LogicalPartition || !media->MediaPresent) continue; + di = alloc(sizeof(struct diskinfo)); + efid_init(di, blkio); - if (efi_bootdp == NULL || depth == -1) - continue; + if (efi_bootdp == NULL || depth == -1 || bootdev != 0) + goto next; status = EFI_CALL(BS->HandleProtocol, handles[i], &devp_guid, (void **)&dp); if (EFI_ERROR(status)) - continue; + goto next; if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) { - disk = blkio; - break; + TAILQ_INSERT_HEAD(&disklist, di, list); + bootdev_dip = di; + bootdev = 1; + continue; } +next: + TAILQ_INSERT_TAIL(&disklist, di, list); } free(handles, sz); + + /* Print available disks. */ + i = 0; + printf("disks:"); + TAILQ_FOREACH(di, &disklist, list) { + printf(" sd%d%s", i, di == bootdev_dip ? "*" : ""); + i++; + } + printf("\n"); } /* @@ -477,10 +499,13 @@ efi_makebootargs(char *bootargs, uint32_t *board_id) fdt_node_add_property(node, "bootargs", bootargs, len); /* Pass DUID of the boot disk. */ - memcpy(&bootduid, diskinfo.disklabel.d_uid, sizeof(bootduid)); - if (memcmp(bootduid, zero, sizeof(bootduid)) != 0) { - fdt_node_add_property(node, "openbsd,bootduid", bootduid, + if (bootdev_dip) { + memcpy(&bootduid, bootdev_dip->disklabel.d_uid, sizeof(bootduid)); + if (memcmp(bootduid, zero, sizeof(bootduid)) != 0) { + fdt_node_add_property(node, "openbsd,bootduid", + bootduid, sizeof(bootduid)); + } } /* Pass netboot interface address. */ @@ -662,10 +687,30 @@ getsecs(void) void devboot(dev_t dev, char *p) { - if (disk) - strlcpy(p, "sd0a", 5); - else + struct diskinfo *dip; + int sd_boot_vol = 0; + int part_type = FS_UNUSED; + + if (bootdev_dip == NULL) { strlcpy(p, "tftp0a", 7); + return; + } + + TAILQ_FOREACH(dip, &disklist, list) { + if (bootdev_dip == dip) + break; + sd_boot_vol++; + } + + /* + * Determine the partition type for the 'a' partition of the + * boot device. + */ + if ((bootdev_dip->flags & DISKINFO_FLAG_GOODLABEL) != 0) + part_type = bootdev_dip->disklabel.d_partitions[0].p_fstype; + + strlcpy(p, "sd0a", 5); + p[2] = '0' + sd_boot_vol; } const char cdevs[][4] = { "com", "fb" }; diff --git a/sys/arch/armv7/stand/efiboot/efidev.c b/sys/arch/armv7/stand/efiboot/efidev.c index 4cd77553a9e..928c57d7d7a 100644 --- a/sys/arch/armv7/stand/efiboot/efidev.c +++ b/sys/arch/armv7/stand/efiboot/efidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efidev.c,v 1.4 2019/09/03 10:00:19 jsg Exp $ */ +/* $OpenBSD: efidev.c,v 1.5 2020/01/13 10:17:09 kettenis Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net> @@ -31,6 +31,7 @@ #include <sys/reboot.h> #include <sys/disklabel.h> #include <lib/libz/zlib.h> +#include <isofs/cd9660/iso.h> #include "libsa.h" @@ -47,12 +48,29 @@ extern int debug; #define EFI_BLKSPERSEC(_ed) ((_ed)->blkio->Media->BlockSize / DEV_BSIZE) #define EFI_SECTOBLK(_ed, _n) ((_n) * EFI_BLKSPERSEC(_ed)) -extern EFI_BLOCK_IO *disk; -struct diskinfo diskinfo; - static EFI_STATUS efid_io(int, efi_diskinfo_t, u_int, int, void *); static int efid_diskio(int, struct diskinfo *, u_int, int, void *); +const char * efi_getdisklabel(efi_diskinfo_t, struct disklabel *); +static int efi_getdisklabel_cd9660(efi_diskinfo_t, struct disklabel *); +static u_int findopenbsd(efi_diskinfo_t, const char **); +static u_int findopenbsd_gpt(efi_diskinfo_t, const char **); +static int gpt_chk_mbr(struct dos_partition *, u_int64_t); + +void +efid_init(struct diskinfo *dip, void *handle) +{ + EFI_BLOCK_IO *blkio = handle; + + memset(dip, 0, sizeof(struct diskinfo)); + dip->ed.blkio = blkio; + dip->ed.mediaid = blkio->Media->MediaId; + dip->diskio = efid_diskio; + dip->strategy = efistrategy; + + if (efi_getdisklabel(&dip->ed, &dip->disklabel) == NULL) + dip->flags |= DISKINFO_FLAG_GOODLABEL; +} static EFI_STATUS efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf) @@ -109,88 +127,394 @@ efid_diskio(int rw, struct diskinfo *dip, u_int off, int nsect, void *buf) } /* - * Read disk label from the device. + * Returns 0 if the MBR with the provided partition array is a GPT protective + * MBR, and returns 1 otherwise. A GPT protective MBR would have one and only + * one MBR partition, an EFI partition that either covers the whole disk or as + * much of it as is possible with a 32bit size field. + * + * Taken from kern/subr_disk.c. + * + * NOTE: MS always uses a size of UINT32_MAX for the EFI partition!** */ -int -efi_getdisklabel(struct diskinfo *dip) +static int +gpt_chk_mbr(struct dos_partition *dp, u_int64_t dsize) { - char *msg; - int sector; - size_t rsize; - struct disklabel *lp; - unsigned char buf[DEV_BSIZE]; + struct dos_partition *dp2; + int efi, found, i; + u_int32_t psize; + + found = efi = 0; + for (dp2=dp, i=0; i < NDOSPART; i++, dp2++) { + if (dp2->dp_typ == DOSPTYP_UNUSED) + continue; + found++; + if (dp2->dp_typ != DOSPTYP_EFI) + continue; + psize = letoh32(dp2->dp_size); + if (psize == (dsize - 1) || + psize == UINT32_MAX) { + if (letoh32(dp2->dp_start) == 1) + efi++; + } + } + if (found == 1 && efi == 1) + return (0); - /* - * Find OpenBSD Partition in DOS partition table. - */ - sector = 0; - if (efistrategy(dip, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize)) - return EOFFSET; + return (1); +} + +/* + * Try to find the disk address of the first MBR OpenBSD partition. + * + * N.B.: must boot from a partition within first 2^32-1 sectors! + * + * Called only if the MBR on sector 0 is *not* a protective MBR + * and *does* have a valid signature. + * + * We don't check the signatures of EBR's, and they cannot be + * protective MBR's so there is no need to check for that. + */ +static u_int +findopenbsd(efi_diskinfo_t ed, const char **err) +{ + EFI_STATUS status; + struct dos_mbr mbr; + struct dos_partition *dp; + u_int mbroff = DOSBBSECTOR; + u_int mbr_eoff = DOSBBSECTOR; /* Offset of MBR extended partition. */ + int i, maxebr = DOS_MAXEBR, nextebr; + +again: + if (!maxebr--) { + *err = "too many extended partitions"; + return (-1); + } - if (*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF] == DOSMBR_SIGNATURE) { - int i; - struct dos_partition *dp = (struct dos_partition *)buf; + /* Read MBR */ + bzero(&mbr, sizeof(mbr)); + status = efid_io(F_READ, ed, mbroff, 1, &mbr); + if (EFI_ERROR(status)) { + *err = "Disk I/O Error"; + return (-1); + } + + /* Search for OpenBSD partition */ + nextebr = 0; + for (i = 0; i < NDOSPART; i++) { + dp = &mbr.dmbr_parts[i]; + if (!dp->dp_size) + continue; +#ifdef BIOS_DEBUG + if (debug) + printf("found partition %u: " + "type %u (0x%x) offset %u (0x%x)\n", + (int)(dp - mbr.dmbr_parts), + dp->dp_typ, dp->dp_typ, + dp->dp_start, dp->dp_start); +#endif + if (dp->dp_typ == DOSPTYP_OPENBSD) { + if (dp->dp_start > (dp->dp_start + mbroff)) + continue; + return (dp->dp_start + mbroff); + } /* - * Lookup OpenBSD slice. If there is none, go ahead - * and try to read the disklabel off sector #0. + * Record location of next ebr if and only if this is the first + * extended partition in this boot record! */ + if (!nextebr && (dp->dp_typ == DOSPTYP_EXTEND || + dp->dp_typ == DOSPTYP_EXTENDL)) { + nextebr = dp->dp_start + mbr_eoff; + if (nextebr < dp->dp_start) + nextebr = (u_int)-1; + if (mbr_eoff == DOSBBSECTOR) + mbr_eoff = dp->dp_start; + } + } + + if (nextebr && nextebr != (u_int)-1) { + mbroff = nextebr; + goto again; + } + + return (-1); +} + +/* + * Try to find the disk address of the first GPT OpenBSD partition. + * + * N.B.: must boot from a partition within first 2^32-1 sectors! + * + * Called only if the MBR on sector 0 *is* a protective MBR + * with a valid signature and sector 1 is a valid GPT header. + */ +static u_int +findopenbsd_gpt(efi_diskinfo_t ed, const char **err) +{ + EFI_STATUS status; + struct gpt_header gh; + int i, part, found; + uint64_t lba; + uint32_t orig_csum, new_csum; + uint32_t ghsize, ghpartsize, ghpartnum, ghpartspersec; + uint32_t gpsectors; + const char openbsd_uuid_code[] = GPT_UUID_OPENBSD; + struct gpt_partition gp; + static struct uuid *openbsd_uuid = NULL, openbsd_uuid_space; + static u_char buf[4096]; + + /* Prepare OpenBSD UUID */ + if (openbsd_uuid == NULL) { + /* XXX: should be replaced by uuid_dec_be() */ + memcpy(&openbsd_uuid_space, openbsd_uuid_code, + sizeof(openbsd_uuid_space)); + openbsd_uuid_space.time_low = + betoh32(openbsd_uuid_space.time_low); + openbsd_uuid_space.time_mid = + betoh16(openbsd_uuid_space.time_mid); + openbsd_uuid_space.time_hi_and_version = + betoh16(openbsd_uuid_space.time_hi_and_version); + + openbsd_uuid = &openbsd_uuid_space; + } + + if (EFI_BLKSPERSEC(ed) > 8) { + *err = "disk sector > 4096 bytes\n"; + return (-1); + } + + /* LBA1: GPT Header */ + lba = 1; + status = efid_io(F_READ, ed, EFI_SECTOBLK(ed, lba), EFI_BLKSPERSEC(ed), + buf); + if (EFI_ERROR(status)) { + *err = "Disk I/O Error"; + return (-1); + } + memcpy(&gh, buf, sizeof(gh)); + + /* Check signature */ + if (letoh64(gh.gh_sig) != GPTSIGNATURE) { + *err = "bad GPT signature\n"; + return (-1); + } + + if (letoh32(gh.gh_rev) != GPTREVISION) { + *err = "bad GPT revision\n"; + return (-1); + } - memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp)); - for (i = 0; i < NDOSPART; i++) { - if (dp[i].dp_typ == DOSPTYP_OPENBSD) { - sector = letoh32(dp[i].dp_start); + ghsize = letoh32(gh.gh_size); + if (ghsize < GPTMINHDRSIZE || ghsize > sizeof(struct gpt_header)) { + *err = "bad GPT header size\n"; + return (-1); + } + + /* Check checksum */ + orig_csum = gh.gh_csum; + gh.gh_csum = 0; + new_csum = crc32(0, (unsigned char *)&gh, ghsize); + gh.gh_csum = orig_csum; + if (letoh32(orig_csum) != new_csum) { + *err = "bad GPT header checksum\n"; + return (-1); + } + + lba = letoh64(gh.gh_part_lba); + ghpartsize = letoh32(gh.gh_part_size); + ghpartspersec = ed->blkio->Media->BlockSize / ghpartsize; + ghpartnum = letoh32(gh.gh_part_num); + gpsectors = (ghpartnum + ghpartspersec - 1) / ghpartspersec; + new_csum = crc32(0L, Z_NULL, 0); + found = 0; + for (i = 0; i < gpsectors; i++, lba++) { + status = efid_io(F_READ, ed, EFI_SECTOBLK(ed, lba), + EFI_BLKSPERSEC(ed), buf); + if (EFI_ERROR(status)) { + *err = "Disk I/O Error"; + return (-1); + } + for (part = 0; part < ghpartspersec; part++) { + if (ghpartnum == 0) break; - } + new_csum = crc32(new_csum, buf + part * sizeof(gp), + sizeof(gp)); + ghpartnum--; + if (found) + continue; + memcpy(&gp, buf + part * sizeof(gp), sizeof(gp)); + if (memcmp(&gp.gp_type, openbsd_uuid, + sizeof(struct uuid)) == 0) + found = 1; + } + } + if (new_csum != letoh32(gh.gh_part_csum)) { + *err = "bad GPT entries checksum\n"; + return (-1); + } + if (found) { + lba = letoh64(gp.gp_lba_start); + /* Bootloaders do not current handle addresses > UINT_MAX! */ + if (lba > UINT_MAX || EFI_SECTOBLK(ed, lba) > UINT_MAX) { + *err = "OpenBSD Partition LBA > 2**32 - 1"; + return (-1); } + return (u_int)lba; } - if (efistrategy(dip, F_READ, sector + DOS_LABELSECTOR, DEV_BSIZE, - buf, &rsize)) - return EOFFSET; + return (-1); +} + +const char * +efi_getdisklabel(efi_diskinfo_t ed, struct disklabel *label) +{ + u_int start = 0; + uint8_t buf[DEV_BSIZE]; + struct dos_partition dosparts[NDOSPART]; + EFI_STATUS status; + const char *err = NULL; + int error; + + /* + * Read sector 0. Ensure it has a valid MBR signature. + * + * If it's a protective MBR then try to find the disklabel via + * GPT. If it's not a protective MBR, try to find the disklabel + * via MBR. + */ + memset(buf, 0, sizeof(buf)); + status = efid_io(F_READ, ed, DOSBBSECTOR, 1, buf); + if (EFI_ERROR(status)) + return ("Disk I/O Error"); - if ((msg = getdisklabel(buf + LABELOFFSET, &dip->disklabel))) - printf("sd%d: getdisklabel: %s\n", 0, msg); + /* Check MBR signature. */ + if (buf[510] != 0x55 || buf[511] != 0xaa) { + if (efi_getdisklabel_cd9660(ed, label) == 0) + return (NULL); + return ("invalid MBR signature"); + } - lp = &dip->disklabel; + memcpy(dosparts, buf+DOSPARTOFF, sizeof(dosparts)); - /* check partition */ - if ((dip->sc_part >= lp->d_npartitions) || - (lp->d_partitions[dip->sc_part].p_fstype == FS_UNUSED)) { - DPRINTF(("illegal partition\n")); - return (EPART); + /* check for GPT protective MBR. */ + if (gpt_chk_mbr(dosparts, ed->blkio->Media->LastBlock + 1) == 0) { + start = findopenbsd_gpt(ed, &err); + if (start == (u_int)-1) { + if (err != NULL) + return (err); + return ("no OpenBSD GPT partition"); + } + } else { + start = findopenbsd(ed, &err); + if (start == (u_int)-1) { + if (err != NULL) + return (err); + return "no OpenBSD MBR partition\n"; + } } + /* Load BSD disklabel */ +#ifdef BIOS_DEBUG + if (debug) + printf("loading disklabel @ %u\n", start + DOS_LABELSECTOR); +#endif + /* read disklabel */ + error = efid_io(F_READ, ed, EFI_SECTOBLK(ed, start) + DOS_LABELSECTOR, + 1, buf); + + if (error) + return "failed to read disklabel"; + + /* Fill in disklabel */ + return (getdisklabel(buf, label)); +} + +static int +efi_getdisklabel_cd9660(efi_diskinfo_t ed, struct disklabel *label) +{ + int off; + uint8_t buf[DEV_BSIZE]; + EFI_STATUS status; + + for (off = 0; off < 100; off++) { + status = efid_io(F_READ, ed, + EFI_BLKSPERSEC(ed) * (16 + off), 1, buf); + if (EFI_ERROR(status)) + return (-1); + if (bcmp(buf + 1, ISO_STANDARD_ID, 5) != 0 || + buf[0] == ISO_VD_END) + return (-1); + if (buf[0] == ISO_VD_PRIMARY) + break; + } + if (off >= 100) + return (-1); + + /* Create an imaginary disk label */ + label->d_secsize = 2048; + label->d_ntracks = 1; + label->d_nsectors = 100; + label->d_ncylinders = 1; + label->d_secpercyl = label->d_ntracks * label->d_nsectors; + + strncpy(label->d_typename, "ATAPI CD-ROM", sizeof(label->d_typename)); + label->d_type = DTYPE_ATAPI; + + strncpy(label->d_packname, "fictitious", sizeof(label->d_packname)); + DL_SETDSIZE(label, 100); + + label->d_bbsize = 2048; + label->d_sbsize = 2048; + + /* 'a' partition covering the "whole" disk */ + DL_SETPOFFSET(&label->d_partitions[0], 0); + DL_SETPSIZE(&label->d_partitions[0], 100); + label->d_partitions[0].p_fstype = FS_UNUSED; + + /* The raw partition is special */ + DL_SETPOFFSET(&label->d_partitions[RAW_PART], 0); + DL_SETPSIZE(&label->d_partitions[RAW_PART], 100); + label->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + + label->d_npartitions = MAXPARTITIONS; + + label->d_magic = DISKMAGIC; + label->d_magic2 = DISKMAGIC; + label->d_checksum = dkcksum(label); + return (0); } int efiopen(struct open_file *f, ...) { - struct diskinfo *dip = &diskinfo; + struct diskinfo *dip = NULL; va_list ap; u_int unit, part; - int error; - - if (disk == NULL) - return (ENXIO); + int i = 0; va_start(ap, f); unit = va_arg(ap, u_int); part = va_arg(ap, u_int); va_end(ap); - if (unit != 0) + if (part >= MAXPARTITIONS) return (ENXIO); - diskinfo.ed.blkio = disk; - diskinfo.ed.mediaid = disk->Media->MediaId; - diskinfo.sc_part = part; + TAILQ_FOREACH(dip, &disklist, list) { + if (i == unit) + break; + i++; + } - error = efi_getdisklabel(&diskinfo); - if (error) - return (error); + if (dip == NULL) + return (ENXIO); + + if ((dip->flags & DISKINFO_FLAG_GOODLABEL) == 0) + return (ENXIO); + dip->part = part; + bootdev_dip = dip; f->f_devdata = dip; return 0; @@ -205,7 +529,8 @@ efistrategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, size_t nsect; nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE; - blk += dip->disklabel.d_partitions[B_PARTITION(dip->sc_part)].p_offset; + blk += DL_SECTOBLK(&dip->disklabel, + dip->disklabel.d_partitions[dip->part].p_offset); if (blk < 0) error = EINVAL; diff --git a/sys/arch/armv7/stand/efiboot/efidev.h b/sys/arch/armv7/stand/efiboot/efidev.h index f7e1c0731e8..a7d5dcac90b 100644 --- a/sys/arch/armv7/stand/efiboot/efidev.h +++ b/sys/arch/armv7/stand/efiboot/efidev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: efidev.h,v 1.2 2019/05/06 03:47:40 mlarkin Exp $ */ +/* $OpenBSD: efidev.h,v 1.3 2020/01/13 10:17:09 kettenis Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -29,6 +29,7 @@ */ /* efidev.c */ +void efid_init(struct diskinfo *, void *handle); int efiopen(struct open_file *, ...); int efistrategy(void *, int, daddr32_t, size_t, void *, size_t *); int eficlose(struct open_file *); |