summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-01-13 10:17:10 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-01-13 10:17:10 +0000
commitc20fa8a3a4e42a1a90217ae3bf42483b9dc68036 (patch)
tree5d871844d2041fb78a065cb4326c911d1a00893b /sys/arch
parentd390f775e09aee0fd7eb7ae8815fdd19beead564 (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.c9
-rw-r--r--sys/arch/armv7/stand/efiboot/disk.h18
-rw-r--r--sys/arch/armv7/stand/efiboot/efiboot.c75
-rw-r--r--sys/arch/armv7/stand/efiboot/efidev.c429
-rw-r--r--sys/arch/armv7/stand/efiboot/efidev.h3
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 *);