Index: stand/efi/boot1/ufs_module.c =================================================================== --- stand/efi/boot1/ufs_module.c +++ stand/efi/boot1/ufs_module.c @@ -36,12 +36,16 @@ #include #include #include +#include #include #include "boot_module.h" +#define BSD_LABEL_OFFSET DEV_BSIZE + static dev_info_t *devinfo; static dev_info_t *devices; +static uint64_t partoff; static int dskread(void *buf, uint64_t lba, int nblk) @@ -49,6 +53,7 @@ int size; EFI_STATUS status; + lba += partoff; lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE); size = nblk * DEV_BSIZE; @@ -73,11 +78,36 @@ static int init_dev(dev_info_t* dev) { + int ok; + struct disklabel *dl; + char buffer[DEV_BSIZE]; devinfo = dev; dmadat = &__dmadat; - return fsread(0, NULL, 0); + /* + * First try offset 0. This is the normal GPT case where we have no + * further partitioning. + */ + partoff = 0; + ok = fsread(0, NULL, 0); + if (ok >= 0) + return (ok); + + /* + * Now try to read a bsdlabel at offset 512. There's others that are + * historic, but we don't probe those. UEFI is little endian only, as + * are BSD labels. We will retry if there's a label found with a + * non-zero offset (otherwise, there'd be no change to the last test). + */ + if (dskread(buffer, BSD_LABEL_OFFSET / DEV_BSIZE, 1) != 0) + return (-1); + dl = (struct disklabel *)buffer; + if (dl->d_magic != BSD_MAGIC || dl->d_magic2 != BSD_MAGIC || + dl->d_partitions[0].p_offset == 0) + return (-1); + partoff = dl->d_partitions[0].p_offset; + return (fsread(0, NULL, 0)); } static EFI_STATUS