aboutsummaryrefslogtreecommitdiff
path: root/stand/efi/boot1
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2018-05-29 03:58:29 +0000
committerWarner Losh <imp@FreeBSD.org>2018-05-29 03:58:29 +0000
commit9958932695e95d4f42bbe98a4acd2f84efb4ccb0 (patch)
tree40f82a49c2d88cd6cd97129f6790a454b8a303fd /stand/efi/boot1
parent23d2383783ad04ff89f3c63354e0b28bd457a05b (diff)
downloadsrc-9958932695e95d4f42bbe98a4acd2f84efb4ccb0.tar.gz
src-9958932695e95d4f42bbe98a4acd2f84efb4ccb0.zip
Teach ufs_module.c about bsd labels and probe 'a' partition.
If the check for a UFS partition at offset 0 on the disk fails, check to see if there's a BSD disklabel at block 1 (standard) or at offset 512 (install images assume 512 sector size). If found, probe for UFS on the 'a' partition. This fixes UEFI booting images from a BSD labeled MBR slice when the 'a' partiton isn't at offset 0. This is a stop-gap fix since we plan on removing boot1.efi in FreeBSD 12. We can't easily do that for 11.2, however, hence the short MFC window. Tested by: emaste@ MFC After: 3 days Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D15598
Notes
Notes: svn path=/head/; revision=334310
Diffstat (limited to 'stand/efi/boot1')
-rw-r--r--stand/efi/boot1/boot_module.h1
-rw-r--r--stand/efi/boot1/ufs_module.c46
2 files changed, 46 insertions, 1 deletions
diff --git a/stand/efi/boot1/boot_module.h b/stand/efi/boot1/boot_module.h
index bfade34fe9cb..891694ee101d 100644
--- a/stand/efi/boot1/boot_module.h
+++ b/stand/efi/boot1/boot_module.h
@@ -50,6 +50,7 @@ typedef struct dev_info
EFI_DEVICE_PATH *devpath;
EFI_HANDLE *devhandle;
void *devdata;
+ uint64_t partoff;
BOOLEAN preferred;
struct dev_info *next;
} dev_info_t;
diff --git a/stand/efi/boot1/ufs_module.c b/stand/efi/boot1/ufs_module.c
index 76c15e41b8d5..af50d9217452 100644
--- a/stand/efi/boot1/ufs_module.c
+++ b/stand/efi/boot1/ufs_module.c
@@ -36,10 +36,14 @@
#include <stdbool.h>
#include <sys/cdefs.h>
#include <sys/param.h>
+#include <sys/disk/bsd.h>
#include <efi.h>
#include "boot_module.h"
+#define BSD_LABEL_BUFFER 8192
+#define BSD_LABEL_OFFSET DEV_BSIZE
+
static dev_info_t *devinfo;
static dev_info_t *devices;
@@ -49,6 +53,7 @@ dskread(void *buf, uint64_t lba, int nblk)
int size;
EFI_STATUS status;
+ lba += devinfo->partoff;
lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE);
size = nblk * DEV_BSIZE;
@@ -73,11 +78,50 @@ static struct dmadat __dmadat;
static int
init_dev(dev_info_t* dev)
{
+ char buffer[BSD_LABEL_BUFFER];
+ struct disklabel *dl;
+ uint64_t bs;
+ int ok;
devinfo = dev;
dmadat = &__dmadat;
- return fsread(0, NULL, 0);
+ /*
+ * First try offset 0. This is the typical GPT case where we have no
+ * further partitioning (as well as the degenerate MBR case where
+ * the bsdlabel has a 0 offset).
+ */
+ devinfo->partoff = 0;
+ ok = fsread(0, NULL, 0);
+ if (ok >= 0)
+ return (ok);
+
+ /*
+ * Next, we look for a bsdlabel. This is technically located in sector
+ * 1. For 4k sectors, this offset is 4096, for 512b sectors it's
+ * 512. However, we have to fall back to 512 here because we create
+ * images that assume 512 byte blocks, but these can be put on devices
+ * who have 4k (or other) block sizes. If there's a crazy block size, we
+ * skip the 'at one sector' and go stright to checking at 512 bytes.
+ * There are other offsets that are historic, but we don't probe those
+ * since they were never used for MBR disks on FreeBSD on systems that
+ * could boot UEFI. UEFI is little endian only, as are BSD labels. We
+ * will retry fsread(0) only if there's a label found with a non-zero
+ * offset.
+ */
+ if (dskread(buffer, 0, BSD_LABEL_BUFFER / DEV_BSIZE) != 0)
+ return (-1);
+ dl = NULL;
+ bs = devinfo->dev->Media->BlockSize;
+ if (bs != 0 && bs <= BSD_LABEL_BUFFER / 2)
+ dl = (struct disklabel *)&buffer[bs];
+ if (dl == NULL || dl->d_magic != BSD_MAGIC || dl->d_magic2 != BSD_MAGIC)
+ dl = (struct disklabel *)&buffer[BSD_LABEL_OFFSET];
+ if (dl->d_magic != BSD_MAGIC || dl->d_magic2 != BSD_MAGIC ||
+ dl->d_partitions[0].p_offset == 0)
+ return (-1);
+ devinfo->partoff = dl->d_partitions[0].p_offset;
+ return (fsread(0, NULL, 0));
}
static EFI_STATUS