Dear ARM gurus,

I m trying to tftp boot last snaphots on pine64+.
Not sure if it s possible.
So far I tried loading minitroot like an idiot and then, a boolader,
now I cant get the efi bootloader to do some tftp ( which I guess is normal  )
But maybe I am just missing a small pieces.

I also created etc/boot.conf in the tftp directory.. just in case.

getting some bsd code to boot :

=> dhcp
BOOTP broadcast 1
DHCP client bound to address 172.16.65.55 (1445 ms)
Using ethernet@01c30000 device
TFTP from server 172.16.65.1; our IP address is 172.16.65.55
Filename 'BOOTAA64.EFI'.
Load address: 0x42000000
Loading: ###########
         5.1 MiB/s
done
=> bootefi 0x42000000
## Starting EFI application at 42000000 ...
Scanning disks on usb...
Disk usb0 not ready
Disk usb1 not ready
Disk usb2 not ready
Disk usb3 not ready
Scanning disks on mmc...
MMC Device 1 not found
MMC Device 2 not found
MMC Device 3 not found
Found 3 disks
WARNING: Invalid device tree, expect boot to fail
disks: sd0
>> OpenBSD/arm64 BOOTAA64 0.16
open(tftp0a:/etc/boot.conf): Operation not permitted
boot>
booting tftp0a:/bsd: open tftp0a:/bsd: Operation not permitted
 failed(1). will try /bsd
boot>
booting tftp0a:/bsd: open tftp0a:/bsd: Operation not permitted
 failed(1). will try /bsd
Turning timeout off.
boot> l
stat(tftp0a:/.): Operation not permitted
boot> l
stat(tftp0a:/.): Operation not permitted
boot> l
stat(tftp0a:/.): Operation not permitted
boot> boot tftp:bsd.rd
cannot open tftp:/etc/random.seed: bad drive number
booting tftp:bsd.rd: open tftp:bsd.rd: bad drive number
 failed(98). will try /bsd
boot> boot 172.16.65.1:/bsd.rd
boot> boot tftp:/bsd.rd
cannot open tftp:/etc/random.seed: bad drive number
booting tftp:/bsd.rd: open tftp:/bsd.rd: bad drive number
 failed(98). will try /bsd
boot> boot tftp0a:/bsd.rd
booting tftp0a:/bsd.rd: open tftp0a:/bsd.rd: Operation not permitted
 failed(1). will try /bsd

is there some kind of trick to boot this ?


On Thu, Jan 31, 2019 at 7:54 AM Mark Kettenis <mark.kette...@xs4all.nl> wrote:
>
> > Date: Wed, 30 Jan 2019 22:31:31 +0100
> > From: Patrick Wildt <patr...@blueri.se>
> >
> > Hi,
> >
> > to boot a pinebook with softraid crypto there are three parts that need
> > to be implemented, which this diff hopefully does well enough.
> >
> > First, our EFI bootloader so far only supports one disk, so we need to
> > extend this so we can see all connected block devices.  The second part
> > is adding the softraid code, which probes for softraid partitions on the
> > block devices and "spawns" its own block device.  At last, we need to
> > push the softraid uuid and key up to the kernel.
> >
> > Pushing the informaton to the kernel is the easiest part.  We can add
> > another openbsd-specific property in the device tree which we read out
> > early on, so that we can zero the space in the device tree so it can not
> > be read by anyone else.
> >
> > For the other part there's a bit more to do.  Very early on efiboot
> > looks for the boot device.  While doing that, we create a list of block
> > devices.  While there, already try to read the disklabel because after
> > this the softraid probing needs to know the partition table.
> >
> > We then call srprobe() which will go over the disklist to look for a
> > disk that contains RAID volumes, but calling the disk's diskio and
> > strategy function to read from the device.  This creates the sr_volumes
> > list of softraid volumes.  The MI boot code will then look for the boot
> > device name by calling devboot().  If we don't have the device path for
> > the boot device, it's a PXE boot.  Otherwise we will find it in either
> > the disklist or sr_volumes list.
> >
> > The next part is the MI code opening the device, looking for a file-
> > system.  The boot device name now is e.g. sr0a, which will then be
> > looked up in the devsw[] array.  From there it's straight forward.
> > Softraid maps the unit number to a volume, the volume already has a
> > pointer to the diskinfo structure from the actual device and then
> > calls the IO functions of that device.
> >
> > softraid_arm64.[ch] is copied from amd64 and adjusted a little bit
> > for arm64, including adding the small devsw[] abstraction.
> >
> > With this I can successfully boot from softraid crypto on bluhm@'s
> > Pinebook.
> >
> > Feedback?
>
> Apart from the property names, this looks good to me.  So feel free to
> go ahead once you changed those properties.
>
> > diff --git sys/arch/arm64/arm64/machdep.c sys/arch/arm64/arm64/machdep.c
> > index 45f6451066a..03bc8464f3a 100644
> > --- sys/arch/arm64/arm64/machdep.c
> > +++ sys/arch/arm64/arm64/machdep.c
> > @@ -30,6 +30,7 @@
> >  #include <sys/msgbuf.h>
> >  #include <sys/buf.h>
> >  #include <sys/termios.h>
> > +#include <sys/sensors.h>
> >
> >  #include <net/if.h>
> >  #include <uvm/uvm.h>
> > @@ -49,6 +50,11 @@
> >
> >  #include <dev/acpi/efi.h>
> >
> > +#include "softraid.h"
> > +#if NSOFTRAID > 0
> > +#include <dev/softraidvar.h>
> > +#endif
> > +
> >  char *boot_args = NULL;
> >  char *boot_file = "";
> >
> > @@ -826,6 +832,22 @@ initarm(struct arm64_bootparams *abp)
> >                       bootmac = lladdr;
> >               }
> >
> > +             len = fdt_node_property(node, "openbsd,bootsr-uuid", &prop);
> > +#if NSOFTRAID > 0
> > +             if (len == sizeof(sr_bootuuid))
> > +                     memcpy(&sr_bootuuid, prop, sizeof(sr_bootuuid));
> > +#endif
> > +             if (len > 0)
> > +                     explicit_bzero(prop, len);
> > +
> > +             len = fdt_node_property(node, "openbsd,bootsr-maskkey", 
> > &prop);
> > +#if NSOFTRAID > 0
> > +             if (len == sizeof(sr_bootkey))
> > +                     memcpy(&sr_bootkey, prop, sizeof(sr_bootkey));
> > +#endif
> > +             if (len > 0)
> > +                     explicit_bzero(prop, len);
> > +
> >               len = fdt_node_property(node, "openbsd,uefi-mmap-start", 
> > &prop);
> >               if (len == sizeof(mmap_start))
> >                       mmap_start = bemtoh64((uint64_t *)prop);
> > diff --git sys/arch/arm64/stand/efiboot/Makefile 
> > sys/arch/arm64/stand/efiboot/Makefile
> > index 36eecd6ca9c..d0ec46662ee 100644
> > --- sys/arch/arm64/stand/efiboot/Makefile
> > +++ sys/arch/arm64/stand/efiboot/Makefile
> > @@ -10,6 +10,7 @@ INSTALL_STRIP=
> >  BINDIR=              /usr/mdec
> >  SRCS=                start.S self_reloc.c efiboot.c conf.c exec.c efiacpi.c
> >  SRCS+=               efidev.c efipxe.c efirng.c fdt.c dt_blob.S
> > +SRCS+=               softraid_arm64.c
> >
> >  S=           ${.CURDIR}/../../../..
> >  EFIDIR=              ${S}/stand/efi
> > @@ -31,6 +32,8 @@ SRCS+=      close.c closeall.c cons.c cread.c dev.c 
> > disklabel.c dkcksum.c fstat.c \
> >  SRCS+=       loadfile.c
> >  SRCS+=       ufs.c
> >  SRCS+=       arp.c ether.c globals.c in_cksum.c net.c netif.c netudp.c 
> > tftp.c
> > +SRCS+=       aes_xts.c bcrypt_pbkdf.c blowfish.c explicit_bzero.c 
> > hmac_sha1.c \
> > +     pkcs5_pbkdf2.c rijndael.c sha1.c sha2.c softraid.c
> >
> >  .PATH:       ${S}/lib/libkern/arch/arm64 ${S}/lib/libkern
> >  SRCS+=       divdi3.c moddi3.c qdivrem.c strlcpy.c strlen.c
> > diff --git sys/arch/arm64/stand/efiboot/conf.c 
> > sys/arch/arm64/stand/efiboot/conf.c
> > index 5e8fd5fa0e7..be301b4a9d4 100644
> > --- sys/arch/arm64/stand/efiboot/conf.c
> > +++ sys/arch/arm64/stand/efiboot/conf.c
> > @@ -27,14 +27,23 @@
> >   */
> >
> >  #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 <dev/biovar.h>
> > +#include <dev/softraidvar.h>
> > +
> > +#include <efi.h>
> > +
> > +#include "disk.h"
> >  #include "efiboot.h"
> >  #include "efidev.h"
> >  #include "efipxe.h"
> > +#include "softraid_arm64.h"
> >
> >  const char version[] = "0.13";
> >  int  debug = 0;
> > @@ -52,6 +61,7 @@ int nfsys = nitems(file_system);
> >  struct devsw devsw[] = {
> >       { "tftp", tftpstrategy, tftpopen, tftpclose, tftpioctl },
> >       { "sd", efistrategy, efiopen, eficlose, efiioctl },
> > +     { "sr", srstrategy, sropen, srclose, srioctl },
> >  };
> >  int ndevs = nitems(devsw);
> >
> > diff --git sys/arch/arm64/stand/efiboot/disk.h 
> > sys/arch/arm64/stand/efiboot/disk.h
> > index 4007259da32..2a6bf3db93f 100644
> > --- sys/arch/arm64/stand/efiboot/disk.h
> > +++ sys/arch/arm64/stand/efiboot/disk.h
> > @@ -3,6 +3,8 @@
> >  #ifndef _DISK_H
> >  #define _DISK_H
> >
> > +#include <sys/queue.h>
> > +
> >  typedef struct efi_diskinfo {
> >       EFI_BLOCK_IO            *blkio;
> >       UINT32                   mediaid;
> > @@ -11,10 +13,21 @@ typedef struct efi_diskinfo {
> >  struct diskinfo {
> >       struct efi_diskinfo ed;
> >       struct disklabel disklabel;
> > +     struct sr_boot_volume *sr_vol;
> > +
> > +     u_int part;
> > +     u_int flags;
> > +#define DISKINFO_FLAG_GOODLABEL              (1 << 0)
> >
> > -     u_int sc_part;
> > +     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 sys/arch/arm64/stand/efiboot/efiboot.c 
> > sys/arch/arm64/stand/efiboot/efiboot.c
> > index 4dc9d7e32fa..f3045639d91 100644
> > --- sys/arch/arm64/stand/efiboot/efiboot.c
> > +++ sys/arch/arm64/stand/efiboot/efiboot.c
> > @@ -28,14 +28,21 @@
> >  #include <efiprot.h>
> >  #include <eficonsctl.h>
> >
> > +#include <dev/biovar.h>
> > +#include <dev/softraidvar.h>
> > +
> >  #include <lib/libkern/libkern.h>
> > +#include <lib/libsa/softraid.h>
> >  #include <stand/boot/cmd.h>
> >
> > +#include "libsa.h"
> >  #include "disk.h"
> > +#include "softraid_arm64.h"
> > +
> > +#include "efidev.h"
> >  #include "efiboot.h"
> >  #include "eficall.h"
> >  #include "fdt.h"
> > -#include "libsa.h"
> >
> >  EFI_SYSTEM_TABLE     *ST;
> >  EFI_BOOT_SERVICES    *BS;
> > @@ -173,19 +180,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) {
> > @@ -217,20 +228,36 @@ 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 and probe for softraid. */
> > +     i = 0;
> > +     printf("disks:");
> > +     TAILQ_FOREACH(di, &disklist, list) {
> > +             printf(" sd%d%s", i, di == bootdev_dip ? "*" : "");
> > +             i++;
> > +     }
> > +     srprobe();
> > +     printf("\n");
> >  }
> >
> >  /*
> > @@ -370,6 +397,7 @@ static EFI_GUID fdt_guid = FDT_TABLE_GUID;
> >  void *
> >  efi_makebootargs(char *bootargs)
> >  {
> > +     struct sr_boot_volume *bv;
> >       u_char bootduid[8];
> >       u_char zero[8] = { 0 };
> >       uint64_t uefi_system_table = htobe64((uintptr_t)ST);
> > @@ -399,12 +427,27 @@ efi_makebootargs(char *bootargs)
> >       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));
> > +             }
> > +
> > +             if (bootdev_dip->sr_vol != NULL) {
> > +                     bv = bootdev_dip->sr_vol;
> > +                     fdt_node_add_property(node, "openbsd,bootsr-uuid",
> > +                         &bv->sbv_uuid, sizeof(bv->sbv_uuid));
> > +                     if (bv->sbv_maskkey != NULL)
> > +                             fdt_node_add_property(node,
> > +                                 "openbsd,bootsr-maskkey", bv->sbv_maskkey,
> > +                                 SR_CRYPTO_MAXKEYBYTES);
> > +             }
> >       }
> >
> > +     sr_clear_keys();
> > +
> >       /* Pass netboot interface address. */
> >       if (bootmac)
> >               fdt_node_add_property(node, "openbsd,bootmac", bootmac, 6);
> > @@ -558,10 +601,51 @@ getsecs(void)
> >  void
> >  devboot(dev_t dev, char *p)
> >  {
> > -     if (disk)
> > -             strlcpy(p, "sd0a", 5);
> > -     else
> > +     struct sr_boot_volume *bv;
> > +     struct sr_boot_chunk *bc;
> > +     struct diskinfo *dip;
> > +     int sd_boot_vol = 0;
> > +     int sr_boot_vol = -1;
> > +     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;
> > +
> > +     /*
> > +      * See if we booted from a disk that is a member of a bootable
> > +      * softraid volume.
> > +      */
> > +     SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
> > +             SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
> > +                     if (bc->sbc_diskinfo == bootdev_dip)
> > +                             sr_boot_vol = bv->sbv_unit;
> > +             if (sr_boot_vol != -1)
> > +                     break;
> > +     }
> > +
> > +     if (sr_boot_vol != -1 && part_type != FS_BSDFFS) {
> > +             strlcpy(p, "sr0a", 5);
> > +             p[2] = '0' + sr_boot_vol;
> > +             return;
> > +     }
> > +
> > +     strlcpy(p, "sd0a", 5);
> > +     p[2] = '0' + sd_boot_vol;
> >  }
> >
> >  int
> > diff --git sys/arch/arm64/stand/efiboot/efidev.c 
> > sys/arch/arm64/stand/efiboot/efidev.c
> > index 91c1ce5f90d..3cd4fac874b 100644
> > --- sys/arch/arm64/stand/efiboot/efidev.c
> > +++ sys/arch/arm64/stand/efiboot/efidev.c
> > @@ -48,17 +48,30 @@ 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)
> >  {
> > @@ -471,32 +484,33 @@ efi_getdisklabel_cd9660(efi_diskinfo_t ed, struct 
> > disklabel *label)
> >  int
> >  efiopen(struct open_file *f, ...)
> >  {
> > -     struct diskinfo *dip = &diskinfo;
> > +     struct diskinfo *dip = NULL;
> >       va_list ap;
> >       u_int unit, part;
> > -     const char *err;
> > -
> > -     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 || part >= MAXPARTITIONS)
> > +     if (part >= MAXPARTITIONS)
> >               return (ENXIO);
> >
> > -     diskinfo.ed.blkio = disk;
> > -     diskinfo.ed.mediaid = disk->Media->MediaId;
> > -     diskinfo.sc_part = part;
> > -
> > -     err = efi_getdisklabel(&dip->ed, &dip->disklabel);
> > -     if (err) {
> > -             printf("%s\n", err);
> > -             return EINVAL;
> > +     TAILQ_FOREACH(dip, &disklist, list) {
> > +             if (i == unit)
> > +                     break;
> > +             i++;
> >       }
> >
> > +     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;
> > @@ -512,7 +526,7 @@ efistrategy(void *devdata, int rw, daddr32_t blk, 
> > size_t size, void *buf,
> >
> >       nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE;
> >       blk += DL_SECTOBLK(&dip->disklabel,
> > -         dip->disklabel.d_partitions[dip->sc_part].p_offset);
> > +         dip->disklabel.d_partitions[dip->part].p_offset);
> >
> >       if (blk < 0)
> >               error = EINVAL;
> > diff --git sys/arch/arm64/stand/efiboot/efidev.h 
> > sys/arch/arm64/stand/efiboot/efidev.h
> > index a771bfcc1f7..95a09463ab5 100644
> > --- sys/arch/arm64/stand/efiboot/efidev.h
> > +++ sys/arch/arm64/stand/efiboot/efidev.h
> > @@ -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 *);
> > diff --git sys/arch/arm64/stand/efiboot/softraid_arm64.c 
> > sys/arch/arm64/stand/efiboot/softraid_arm64.c
> > new file mode 100644
> > index 00000000000..693198d2357
> > --- /dev/null
> > +++ sys/arch/arm64/stand/efiboot/softraid_arm64.c
> > @@ -0,0 +1,665 @@
> > +/*   $OpenBSD: softraid_amd64.c,v 1.5 2017/12/18 12:53:33 fcambus Exp $    
> >   */
> > +
> > +/*
> > + * Copyright (c) 2012 Joel Sing <js...@openbsd.org>
> > + *
> > + * Permission to use, copy, modify, and distribute this software for any
> > + * purpose with or without fee is hereby granted, provided that the above
> > + * copyright notice and this permission notice appear in all copies.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > + */
> > +
> > +#include <sys/param.h>
> > +#include <sys/queue.h>
> > +#include <sys/disklabel.h>
> > +#include <sys/reboot.h>
> > +
> > +#include <dev/biovar.h>
> > +#include <dev/softraidvar.h>
> > +
> > +#include <lib/libsa/aes_xts.h>
> > +#include <lib/libsa/softraid.h>
> > +#include <lib/libz/zlib.h>
> > +
> > +#include <efi.h>
> > +
> > +#include "libsa.h"
> > +#include "disk.h"
> > +#include "efidev.h"
> > +#include "softraid_arm64.h"
> > +
> > +static int gpt_chk_mbr(struct dos_partition *, u_int64_t);
> > +static uint64_t findopenbsd_gpt(struct sr_boot_volume *, const char **);
> > +
> > +void
> > +srprobe_meta_opt_load(struct sr_metadata *sm, struct sr_meta_opt_head *som)
> > +{
> > +     struct sr_meta_opt_hdr  *omh;
> > +     struct sr_meta_opt_item *omi;
> > +#if 0
> > +     u_int8_t checksum[MD5_DIGEST_LENGTH];
> > +#endif
> > +     int                     i;
> > +
> > +     /* Process optional metadata. */
> > +     omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(sm + 1) +
> > +         sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
> > +     for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
> > +
> > +#ifdef BIOS_DEBUG
> > +             printf("Found optional metadata of type %u, length %u\n",
> > +                 omh->som_type, omh->som_length);
> > +#endif
> > +
> > +             /* Unsupported old fixed length optional metadata. */
> > +             if (omh->som_length == 0) {
> > +                     omh = (struct sr_meta_opt_hdr *)((void *)omh +
> > +                         SR_OLD_META_OPT_SIZE);
> > +                     continue;
> > +             }
> > +
> > +             /* Load variable length optional metadata. */
> > +             omi = alloc(sizeof(struct sr_meta_opt_item));
> > +             bzero(omi, sizeof(struct sr_meta_opt_item));
> > +             SLIST_INSERT_HEAD(som, omi, omi_link);
> > +             omi->omi_som = alloc(omh->som_length);
> > +             bzero(omi->omi_som, omh->som_length);
> > +             bcopy(omh, omi->omi_som, omh->som_length);
> > +
> > +#if 0
> > +             /* XXX - Validate checksum. */
> > +             bcopy(&omi->omi_som->som_checksum, &checksum,
> > +                 MD5_DIGEST_LENGTH);
> > +             bzero(&omi->omi_som->som_checksum, MD5_DIGEST_LENGTH);
> > +             sr_checksum(sc, omi->omi_som,
> > +                 &omi->omi_som->som_checksum, omh->som_length);
> > +             if (bcmp(&checksum, &omi->omi_som->som_checksum,
> > +                 sizeof(checksum)))
> > +                     panic("%s: invalid optional metadata checksum",
> > +                         DEVNAME(sc));
> > +#endif
> > +
> > +             omh = (struct sr_meta_opt_hdr *)((void *)omh +
> > +                 omh->som_length);
> > +     }
> > +}
> > +
> > +void
> > +srprobe_keydisk_load(struct sr_metadata *sm)
> > +{
> > +     struct sr_meta_opt_hdr  *omh;
> > +     struct sr_meta_keydisk  *skm;
> > +     struct sr_boot_keydisk  *kd;
> > +     int i;
> > +
> > +     /* Process optional metadata. */
> > +     omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(sm + 1) +
> > +         sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
> > +     for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
> > +
> > +             /* Unsupported old fixed length optional metadata. */
> > +             if (omh->som_length == 0) {
> > +                     omh = (struct sr_meta_opt_hdr *)((void *)omh +
> > +                         SR_OLD_META_OPT_SIZE);
> > +                     continue;
> > +             }
> > +
> > +             if (omh->som_type != SR_OPT_KEYDISK) {
> > +                     omh = (struct sr_meta_opt_hdr *)((void *)omh +
> > +                         omh->som_length);
> > +                     continue;
> > +             }
> > +
> > +             kd = alloc(sizeof(struct sr_boot_keydisk));
> > +             bcopy(&sm->ssdi.ssd_uuid, &kd->kd_uuid, sizeof(kd->kd_uuid));
> > +             skm = (struct sr_meta_keydisk*)omh;
> > +             bcopy(&skm->skm_maskkey, &kd->kd_key, sizeof(kd->kd_key));
> > +             SLIST_INSERT_HEAD(&sr_keydisks, kd, kd_link);
> > +     }
> > +}
> > +
> > +void
> > +srprobe(void)
> > +{
> > +     struct sr_boot_volume *bv, *bv1, *bv2;
> > +     struct sr_boot_chunk *bc, *bc1, *bc2;
> > +     struct sr_meta_chunk *mc;
> > +     struct sr_metadata *md;
> > +     struct diskinfo *dip;
> > +     struct partition *pp;
> > +     int i, error, volno;
> > +     daddr_t off;
> > +
> > +     /* Probe for softraid volumes. */
> > +     SLIST_INIT(&sr_volumes);
> > +     SLIST_INIT(&sr_keydisks);
> > +
> > +     md = alloc(SR_META_SIZE * DEV_BSIZE);
> > +
> > +     TAILQ_FOREACH(dip, &disklist, list) {
> > +
> > +             /* Make sure disklabel has been read. */
> > +             if ((dip->flags & DISKINFO_FLAG_GOODLABEL) == 0)
> > +                     continue;
> > +
> > +             for (i = 0; i < MAXPARTITIONS; i++) {
> > +
> > +                     pp = &dip->disklabel.d_partitions[i];
> > +                     if (pp->p_fstype != FS_RAID || pp->p_size == 0)
> > +                             continue;
> > +
> > +                     /* Read softraid metadata. */
> > +                     bzero(md, SR_META_SIZE * DEV_BSIZE);
> > +                     off = DL_SECTOBLK(&dip->disklabel, DL_GETPOFFSET(pp));
> > +                     off += SR_META_OFFSET;
> > +                     error = dip->diskio(F_READ, dip, off, SR_META_SIZE, 
> > md);
> > +                     if (error)
> > +                             continue;
> > +
> > +                     /* Is this valid softraid metadata? */
> > +                     if (md->ssdi.ssd_magic != SR_MAGIC)
> > +                             continue;
> > +
> > +                     /* XXX - validate checksum. */
> > +
> > +                     /* Handle key disks separately... */
> > +                     if (md->ssdi.ssd_level == SR_KEYDISK_LEVEL) {
> > +                             srprobe_keydisk_load(md);
> > +                             continue;
> > +                     }
> > +
> > +                     /* Locate chunk-specific metadata for this chunk. */
> > +                     mc = (struct sr_meta_chunk *)(md + 1);
> > +                     mc += md->ssdi.ssd_chunk_id;
> > +
> > +                     bc = alloc(sizeof(struct sr_boot_chunk));
> > +                     bc->sbc_diskinfo = dip;
> > +                     bc->sbc_disk = 0;
> > +                     bc->sbc_part = 'a' + i;
> > +
> > +                     bc->sbc_mm = 0;
> > +
> > +                     bc->sbc_chunk_id = md->ssdi.ssd_chunk_id;
> > +                     bc->sbc_ondisk = md->ssd_ondisk;
> > +                     bc->sbc_state = mc->scm_status;
> > +
> > +                     SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
> > +                             if (bcmp(&md->ssdi.ssd_uuid, &bv->sbv_uuid,
> > +                                 sizeof(md->ssdi.ssd_uuid)) == 0)
> > +                                     break;
> > +                     }
> > +
> > +                     if (bv == NULL) {
> > +                             bv = alloc(sizeof(struct sr_boot_volume));
> > +                             bzero(bv, sizeof(struct sr_boot_volume));
> > +                             bv->sbv_level = md->ssdi.ssd_level;
> > +                             bv->sbv_volid = md->ssdi.ssd_volid;
> > +                             bv->sbv_chunk_no = md->ssdi.ssd_chunk_no;
> > +                             bv->sbv_flags = md->ssdi.ssd_vol_flags;
> > +                             bv->sbv_size = md->ssdi.ssd_size;
> > +                             bv->sbv_secsize = md->ssdi.ssd_secsize;
> > +                             bv->sbv_data_blkno = md->ssd_data_blkno;
> > +                             bcopy(&md->ssdi.ssd_uuid, &bv->sbv_uuid,
> > +                                 sizeof(md->ssdi.ssd_uuid));
> > +                             SLIST_INIT(&bv->sbv_chunks);
> > +                             SLIST_INIT(&bv->sbv_meta_opt);
> > +
> > +                             /* Load optional metadata for this volume. */
> > +                             srprobe_meta_opt_load(md, &bv->sbv_meta_opt);
> > +
> > +                             /* Maintain volume order. */
> > +                             bv2 = NULL;
> > +                             SLIST_FOREACH(bv1, &sr_volumes, sbv_link) {
> > +                                     if (bv1->sbv_volid > bv->sbv_volid)
> > +                                             break;
> > +                                     bv2 = bv1;
> > +                             }
> > +                             if (bv2 == NULL)
> > +                                     SLIST_INSERT_HEAD(&sr_volumes, bv,
> > +                                         sbv_link);
> > +                             else
> > +                                     SLIST_INSERT_AFTER(bv2, bv, sbv_link);
> > +                     }
> > +
> > +                     /* Maintain chunk order. */
> > +                     bc2 = NULL;
> > +                     SLIST_FOREACH(bc1, &bv->sbv_chunks, sbc_link) {
> > +                             if (bc1->sbc_chunk_id > bc->sbc_chunk_id)
> > +                                     break;
> > +                             bc2 = bc1;
> > +                     }
> > +                     if (bc2 == NULL)
> > +                             SLIST_INSERT_HEAD(&bv->sbv_chunks,
> > +                                 bc, sbc_link);
> > +                     else
> > +                             SLIST_INSERT_AFTER(bc2, bc, sbc_link);
> > +
> > +                     bv->sbv_chunks_found++;
> > +             }
> > +     }
> > +
> > +     /*
> > +      * Assemble RAID volumes.
> > +      */
> > +     volno = 0;
> > +     SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
> > +
> > +             /* Skip if this is a hotspare "volume". */
> > +             if (bv->sbv_level == SR_HOTSPARE_LEVEL &&
> > +                 bv->sbv_chunk_no == 1)
> > +                     continue;
> > +
> > +             /* Determine current ondisk version. */
> > +             bv->sbv_ondisk = 0;
> > +             SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) {
> > +                     if (bc->sbc_ondisk > bv->sbv_ondisk)
> > +                             bv->sbv_ondisk = bc->sbc_ondisk;
> > +             }
> > +             SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) {
> > +                     if (bc->sbc_ondisk != bv->sbv_ondisk)
> > +                             bc->sbc_state = BIOC_SDOFFLINE;
> > +             }
> > +
> > +             /* XXX - Check for duplicate chunks. */
> > +
> > +             /*
> > +              * Validate that volume has sufficient chunks for
> > +              * read-only access.
> > +              *
> > +              * XXX - check chunk states.
> > +              */
> > +             bv->sbv_state = BIOC_SVOFFLINE;
> > +             switch (bv->sbv_level) {
> > +             case 0:
> > +             case 'C':
> > +             case 'c':
> > +                     if (bv->sbv_chunk_no == bv->sbv_chunks_found)
> > +                             bv->sbv_state = BIOC_SVONLINE;
> > +                     break;
> > +
> > +             case 1:
> > +                     if (bv->sbv_chunk_no == bv->sbv_chunks_found)
> > +                             bv->sbv_state = BIOC_SVONLINE;
> > +                     else if (bv->sbv_chunks_found > 0)
> > +                             bv->sbv_state = BIOC_SVDEGRADED;
> > +                     break;
> > +             }
> > +
> > +             bv->sbv_unit = volno++;
> > +             if (bv->sbv_state != BIOC_SVOFFLINE)
> > +                     printf(" sr%d%s", bv->sbv_unit,
> > +                         bv->sbv_flags & BIOC_SCBOOTABLE ? "*" : "");
> > +     }
> > +
> > +     explicit_bzero(md, SR_META_SIZE * DEV_BSIZE);
> > +     free(md, SR_META_SIZE * DEV_BSIZE);
> > +}
> > +
> > +int
> > +sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size,
> > +    void *buf, size_t *rsize)
> > +{
> > +     struct diskinfo *sr_dip, *dip;
> > +     struct sr_boot_chunk *bc;
> > +     struct aes_xts_ctx ctx;
> > +     size_t i, j, nsect;
> > +     daddr_t blkno;
> > +     u_char iv[8];
> > +     u_char *bp;
> > +     int err;
> > +
> > +     /* We only support read-only softraid. */
> > +     if (rw != F_READ)
> > +             return ENOTSUP;
> > +
> > +     /* Partition offset within softraid volume. */
> > +     sr_dip = (struct diskinfo *)bv->sbv_diskinfo;
> > +     blk += DL_SECTOBLK(&sr_dip->disklabel,
> > +         sr_dip->disklabel.d_partitions[bv->sbv_part - 'a'].p_offset);
> > +
> > +     if (bv->sbv_level == 0) {
> > +             return ENOTSUP;
> > +     } else if (bv->sbv_level == 1) {
> > +
> > +             /* Select first online chunk. */
> > +             SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
> > +                     if (bc->sbc_state == BIOC_SDONLINE)
> > +                             break;
> > +             if (bc == NULL)
> > +                     return EIO;
> > +
> > +             dip = (struct diskinfo *)bc->sbc_diskinfo;
> > +             blk += bv->sbv_data_blkno;
> > +
> > +             /* XXX - If I/O failed we should try another chunk... */
> > +             return dip->strategy(dip, rw, blk, size, buf, rsize);
> > +
> > +     } else if (bv->sbv_level == 'C') {
> > +
> > +             /* Select first online chunk. */
> > +             SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
> > +                     if (bc->sbc_state == BIOC_SDONLINE)
> > +                             break;
> > +             if (bc == NULL)
> > +                     return EIO;
> > +
> > +             dip = (struct diskinfo *)bc->sbc_diskinfo;
> > +
> > +             /* XXX - select correct key. */
> > +             aes_xts_setkey(&ctx, (u_char *)bv->sbv_keys, 64);
> > +
> > +             nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE;
> > +             for (i = 0; i < nsect; i++) {
> > +                     blkno = blk + i;
> > +                     bp = ((u_char *)buf) + i * DEV_BSIZE;
> > +                     err = dip->strategy(dip, rw, bv->sbv_data_blkno + 
> > blkno,
> > +                         DEV_BSIZE, bp, NULL);
> > +                     if (err != 0)
> > +                             return err;
> > +
> > +                     bcopy(&blkno, iv, sizeof(blkno));
> > +                     aes_xts_reinit(&ctx, iv);
> > +                     for (j = 0; j < DEV_BSIZE; j += AES_XTS_BLOCKSIZE)
> > +                             aes_xts_decrypt(&ctx, bp + j);
> > +             }
> > +             if (rsize != NULL)
> > +                     *rsize = nsect * DEV_BSIZE;
> > +
> > +             return err;
> > +
> > +     } else
> > +             return ENOTSUP;
> > +}
> > +
> > +/*
> > + * 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!**
> > + */
> > +static int
> > +gpt_chk_mbr(struct dos_partition *dp, u_int64_t dsize)
> > +{
> > +     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);
> > +
> > +     return (1);
> > +}
> > +
> > +static uint64_t
> > +findopenbsd_gpt(struct sr_boot_volume *bv, const char **err)
> > +{
> > +     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;
> > +     u_char                  *buf;
> > +
> > +     /* 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 (bv->sbv_secsize > 4096) {
> > +             *err = "disk sector > 4096 bytes\n";
> > +             return (-1);
> > +     }
> > +     buf = alloc(bv->sbv_secsize);
> > +     if (buf == NULL) {
> > +             *err = "out of memory\n";
> > +             return (-1);
> > +     }
> > +     bzero(buf, bv->sbv_secsize);
> > +
> > +     /* LBA1: GPT Header */
> > +     lba = 1;
> > +     sr_strategy(bv, F_READ, lba * (bv->sbv_secsize / DEV_BSIZE), 
> > DEV_BSIZE,
> > +         buf, NULL);
> > +     memcpy(&gh, buf, sizeof(gh));
> > +
> > +     /* Check signature */
> > +     if (letoh64(gh.gh_sig) != GPTSIGNATURE) {
> > +             *err = "bad GPT signature\n";
> > +             free(buf, bv->sbv_secsize);
> > +             return (-1);
> > +     }
> > +
> > +     if (letoh32(gh.gh_rev) != GPTREVISION) {
> > +             *err = "bad GPT revision\n";
> > +             free(buf, bv->sbv_secsize);
> > +             return (-1);
> > +     }
> > +
> > +     ghsize = letoh32(gh.gh_size);
> > +     if (ghsize < GPTMINHDRSIZE || ghsize > sizeof(struct gpt_header)) {
> > +             *err = "bad GPT header size\n";
> > +             free(buf, bv->sbv_secsize);
> > +             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";
> > +             free(buf, bv->sbv_secsize);
> > +             return (-1);
> > +     }
> > +
> > +     lba = letoh64(gh.gh_part_lba);
> > +     ghpartsize = letoh32(gh.gh_part_size);
> > +     ghpartspersec = bv->sbv_secsize / 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++) {
> > +             sr_strategy(bv, F_READ, lba * (bv->sbv_secsize / DEV_BSIZE),
> > +                 bv->sbv_secsize, buf, NULL);
> > +             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;
> > +             }
> > +     }
> > +
> > +     free(buf, bv->sbv_secsize);
> > +
> > +     if (new_csum != letoh32(gh.gh_part_csum)) {
> > +             *err = "bad GPT entries checksum\n";
> > +             return (-1);
> > +     }
> > +     if (found)
> > +             return (letoh64(gp.gp_lba_start));
> > +
> > +     return (-1);
> > +}
> > +
> > +const char *
> > +sr_getdisklabel(struct sr_boot_volume *bv, struct disklabel *label)
> > +{
> > +     struct dos_partition *dp;
> > +     struct dos_mbr mbr;
> > +     const char *err = NULL;
> > +     u_int start = 0;
> > +     char buf[DEV_BSIZE];
> > +     int i;
> > +
> > +     /* Check for MBR to determine partition offset. */
> > +     bzero(&mbr, sizeof(mbr));
> > +     sr_strategy(bv, F_READ, DOSBBSECTOR, sizeof(mbr), &mbr, NULL);
> > +     if (gpt_chk_mbr(mbr.dmbr_parts, bv->sbv_size /
> > +                 (bv->sbv_secsize / DEV_BSIZE)) == 0) {
> > +             start = findopenbsd_gpt(bv, &err);
> > +             if (start == (u_int)-1) {
> > +                     if (err != NULL)
> > +                             return (err);
> > +                     return "no OpenBSD partition\n";
> > +             }
> > +     } else if (mbr.dmbr_sign == DOSMBR_SIGNATURE) {
> > +
> > +             /* Search for OpenBSD partition */
> > +             for (i = 0; i < NDOSPART; i++) {
> > +                     dp = &mbr.dmbr_parts[i];
> > +                     if (!dp->dp_size)
> > +                             continue;
> > +                     if (dp->dp_typ == DOSPTYP_OPENBSD) {
> > +                             start = dp->dp_start;
> > +                             break;
> > +                     }
> > +             }
> > +     }
> > +
> > +     /* Read the disklabel. */
> > +     sr_strategy(bv, F_READ,
> > +         start * (bv->sbv_secsize / DEV_BSIZE) + DOS_LABELSECTOR,
> > +         sizeof(struct disklabel), buf, NULL);
> > +
> > +#ifdef BIOS_DEBUG
> > +     printf("sr_getdisklabel: magic %lx\n",
> > +         ((struct disklabel *)buf)->d_magic);
> > +     for (i = 0; i < MAXPARTITIONS; i++)
> > +             printf("part %c: type = %d, size = %d, offset = %d\n", 'a' + 
> > i,
> > +                 (int)((struct disklabel *)buf)->d_partitions[i].p_fstype,
> > +                 (int)((struct disklabel *)buf)->d_partitions[i].p_size,
> > +                 (int)((struct disklabel *)buf)->d_partitions[i].p_offset);
> > +#endif
> > +
> > +     /* Fill in disklabel */
> > +     return (getdisklabel(buf, label));
> > +}
> > +
> > +int
> > +sropen(struct open_file *f, ...)
> > +{
> > +     struct diskinfo *dip = NULL;
> > +     struct sr_boot_volume *bv;
> > +     va_list ap;
> > +     u_int unit, part;
> > +
> > +     va_start(ap, f);
> > +     unit = va_arg(ap, u_int);
> > +     part = va_arg(ap, u_int);
> > +     va_end(ap);
> > +
> > +     /* Create a fake diskinfo for this softraid volume. */
> > +     SLIST_FOREACH(bv, &sr_volumes, sbv_link)
> > +             if (bv->sbv_unit == unit)
> > +                     break;
> > +     if (bv == NULL) {
> > +             printf("Unknown device: sr%d\n", unit);
> > +             return EADAPT;
> > +     }
> > +
> > +     if (bv->sbv_level == 'C' && bv->sbv_keys == NULL)
> > +             if (sr_crypto_unlock_volume(bv) != 0)
> > +                     return EPERM;
> > +
> > +     if (bv->sbv_diskinfo == NULL) {
> > +             dip = alloc(sizeof(struct diskinfo));
> > +             bzero(dip, sizeof(*dip));
> > +             dip->diskio = srdiskio;
> > +             dip->strategy = srstrategy;
> > +             bv->sbv_diskinfo = dip;
> > +             dip->sr_vol = bv;
> > +     }
> > +
> > +     dip = bv->sbv_diskinfo;
> > +
> > +     if ((dip->flags & DISKINFO_FLAG_GOODLABEL) == 0) {
> > +             /* Attempt to read disklabel. */
> > +             bv->sbv_part = 'c';
> > +             if (sr_getdisklabel(bv, &dip->disklabel))
> > +                     return ERDLAB;
> > +             dip->flags |= DISKINFO_FLAG_GOODLABEL;
> > +     }
> > +
> > +     bv->sbv_part = part + 'a';
> > +
> > +     bootdev_dip = dip;
> > +     f->f_devdata = dip;
> > +
> > +     return 0;
> > +}
> > +
> > +int
> > +srstrategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
> > +    size_t *rsize)
> > +{
> > +     struct diskinfo *dip = (struct diskinfo *)devdata;
> > +     return sr_strategy(dip->sr_vol, rw, blk, size, buf, rsize);
> > +}
> > +
> > +int
> > +srdiskio(int rw, struct diskinfo *dip, u_int off, int nsect, void *buf)
> > +{
> > +     return dip->diskio(rw, dip, off, nsect, buf);
> > +}
> > +
> > +int
> > +srclose(struct open_file *f)
> > +{
> > +     f->f_devdata = NULL;
> > +
> > +     return 0;
> > +}
> > +
> > +int
> > +srioctl(struct open_file *f, u_long cmd, void *data)
> > +{
> > +     return 0;
> > +}
> > diff --git sys/arch/arm64/stand/efiboot/softraid_arm64.h 
> > sys/arch/arm64/stand/efiboot/softraid_arm64.h
> > new file mode 100644
> > index 00000000000..bd6b0f6e4c3
> > --- /dev/null
> > +++ sys/arch/arm64/stand/efiboot/softraid_arm64.h
> > @@ -0,0 +1,33 @@
> > +/*   $OpenBSD: softraid_amd64.h,v 1.3 2016/09/11 17:51:21 jsing Exp $      
> >   */
> > +
> > +/*
> > + * Copyright (c) 2012 Joel Sing <js...@openbsd.org>
> > + *
> > + * Permission to use, copy, modify, and distribute this software for any
> > + * purpose with or without fee is hereby granted, provided that the above
> > + * copyright notice and this permission notice appear in all copies.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > + */
> > +
> > +#ifndef _SOFTRAID_ARM64_H_
> > +#define _SOFTRAID_ARM64_H_
> > +
> > +void srprobe(void);
> > +
> > +const char *sr_getdisklabel(struct sr_boot_volume *, struct disklabel *);
> > +int  sr_strategy(struct sr_boot_volume *, int, daddr32_t, size_t,
> > +         void *, size_t *);
> > +int  sropen(struct open_file *, ...);
> > +int  srstrategy(void *, int, daddr32_t, size_t, void *, size_t *);
> > +int  srdiskio(int, struct diskinfo *, u_int, int, void *);
> > +int  srclose(struct open_file *);
> > +int  srioctl(struct open_file *, u_long, void *);
> > +
> > +#endif /* _SOFTRAID_ARM64_H */
> >
> >
>


-- 
--
---------------------------------------------------------------------------------------------------------------------
Knowing is not enough; we must apply. Willing is not enough; we must do

Reply via email to