Page MenuHomeFreeBSD

D20547.id58344.diff
No OneTemporary

D20547.id58344.diff

Index: stand/efi/Makefile
===================================================================
--- stand/efi/Makefile
+++ stand/efi/Makefile
@@ -9,7 +9,7 @@
.if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500
SUBDIR.${MK_FDT}+= fdt
-SUBDIR.yes+= libefi boot1
+SUBDIR.yes+= libefi boot1 gptboot
SUBDIR.${MK_FORTH}+= loader_4th
SUBDIR.${MK_LOADER_LUA}+= loader_lua
SUBDIR.yes+= loader_simp
Index: stand/efi/boot1/Makefile
===================================================================
--- stand/efi/boot1/Makefile
+++ stand/efi/boot1/Makefile
@@ -5,7 +5,7 @@
BOOT1?= boot1
PROG= ${BOOT1}.sym
INTERNALPROG=
-WARNS?= 6
+WARNS= 6
CFLAGS+= -DEFI_BOOT1
# We implement a slightly non-standard %S in that it always takes a
@@ -28,7 +28,7 @@
CWARNFLAGS.zfs_module.c += -Wno-unused-function
# architecture-specific loader code
-SRCS+= boot1.c self_reloc.c start.S ufs_module.c devpath.c
+SRCS+= boot1.c proto.c self_reloc.c start.S ufs_module.c devpath.c
.if ${MK_LOADER_ZFS} != "no"
SRCS+= zfs_module.c
CFLAGS.zfs_module.c+= -I${ZFSSRC}
Index: stand/efi/boot1/boot1.c
===================================================================
--- stand/efi/boot1/boot1.c
+++ stand/efi/boot1/boot1.c
@@ -33,10 +33,11 @@
#include "boot_module.h"
#include "paths.h"
+#include "proto.h"
static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3);
-static const boot_module_t *boot_modules[] =
+const boot_module_t *boot_modules[] =
{
#ifdef EFI_ZFS_BOOT
&zfs_module,
@@ -45,8 +46,7 @@
&ufs_module
#endif
};
-
-#define NUM_BOOT_MODULES nitems(boot_modules)
+const UINTN num_boot_modules = nitems(boot_modules);
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
@@ -90,66 +90,20 @@
return (res);
}
-/*
- * load_loader attempts to load the loader image data.
- *
- * It tries each module and its respective devices, identified by mod->probe,
- * in order until a successful load occurs at which point it returns EFI_SUCCESS
- * and EFI_NOT_FOUND otherwise.
- *
- * Only devices which have preferred matching the preferred parameter are tried.
- */
-static EFI_STATUS
-load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
- size_t *bufsize, int preferred)
-{
- UINTN i;
- dev_info_t *dev;
- const boot_module_t *mod;
-
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- mod = boot_modules[i];
- for (dev = mod->devices(); dev != NULL; dev = dev->next) {
- if (dev->preferred != preferred)
- continue;
-
- if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
- EFI_SUCCESS) {
- *devinfop = dev;
- *modp = mod;
- return (EFI_SUCCESS);
- }
- }
- }
-
- return (EFI_NOT_FOUND);
-}
-
/*
* try_boot only returns if it fails to load the loader. If it succeeds
* it simply boots, otherwise it returns the status of last EFI call.
*/
-static EFI_STATUS
-try_boot(void)
+EFI_STATUS
+try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t loadersize)
{
- size_t bufsize, loadersize, cmdsize;
- void *buf, *loaderbuf;
+ size_t bufsize, cmdsize;
+ void *buf;
char *cmd;
- dev_info_t *dev;
- const boot_module_t *mod;
EFI_HANDLE loaderhandle;
EFI_LOADED_IMAGE *loaded_image;
EFI_STATUS status;
- status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1);
- if (status != EFI_SUCCESS) {
- status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0);
- if (status != EFI_SUCCESS) {
- printf("Failed to load '%s'\n", PATH_LOADER_EFI);
- return (status);
- }
- }
-
/*
* Read in and parse the command line from /boot.config or /boot/config,
* if present. We'll pass it the next stage via a simple ASCII
@@ -228,84 +182,6 @@
return (status);
}
-/*
- * probe_handle determines if the passed handle represents a logical partition
- * if it does it uses each module in order to probe it and if successful it
- * returns 0.
- */
-static int
-probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
-{
- dev_info_t *devinfo;
- EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath;
- EFI_STATUS status;
- UINTN i;
- int preferred;
-
- /* Figure out if we're dealing with an actual partition. */
- status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
- if (status == EFI_UNSUPPORTED)
- return (0);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query DevicePath (%lu)\n",
- EFI_ERROR_CODE(status));
- return (-1);
- }
-#ifdef EFI_DEBUG
- {
- CHAR16 *text = efi_devpath_name(devpath);
- DPRINTF("probing: %S ", text);
- efi_free_devpath_name(text);
- }
-#endif
- status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
- if (status == EFI_UNSUPPORTED)
- return (0);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
- EFI_ERROR_CODE(status));
- return (-1);
- }
-
- if (!blkio->Media->LogicalPartition)
- return (0);
-
- preferred = efi_devpath_same_disk(imgpath, devpath);
-
- /* Run through each module, see if it can load this partition */
- devinfo = malloc(sizeof(*devinfo));
- if (devinfo == NULL) {
- DPRINTF("\nFailed to allocate devinfo\n");
- return (-1);
- }
- devinfo->dev = blkio;
- devinfo->devpath = devpath;
- devinfo->devhandle = h;
- devinfo->preferred = preferred;
- devinfo->next = NULL;
-
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- devinfo->devdata = NULL;
-
- status = boot_modules[i]->probe(devinfo);
- if (status == EFI_SUCCESS)
- return (preferred + 1);
- }
- free(devinfo);
-
- return (0);
-}
-
-const char *prio_str[] = {
- "error",
- "not supported",
- "good",
- "better"
-};
-
EFI_STATUS
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
{
@@ -317,10 +193,6 @@
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
UINTN i, hsize, nhandles;
CHAR16 *text;
- UINT16 boot_current;
- size_t sz;
- UINT16 boot_order[100];
- int rv;
/* Basic initialization*/
ST = Xsystab;
@@ -348,13 +220,27 @@
printf("\n>> FreeBSD EFI boot block\n");
printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
printf(" Initializing modules:");
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ for (i = 0; i < num_boot_modules; i++) {
printf(" %s", boot_modules[i]->name);
if (boot_modules[i]->init != NULL)
boot_modules[i]->init();
}
putchar('\n');
+ /* Fetch all the block I/O handles, we have to search through them later */
+ hsize = 0;
+ BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
+ &hsize, NULL);
+ handles = malloc(hsize);
+ if (handles == NULL)
+ efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
+ hsize);
+ status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+ NULL, &hsize, handles);
+ if (status != EFI_SUCCESS)
+ efi_panic(status, "Failed to get device handles\n");
+ nhandles = hsize / sizeof(*handles);
+
/* Determine the devpath of our image so we can prefer it. */
status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img);
imgpath = NULL;
@@ -381,64 +267,7 @@
}
}
- boot_current = 0;
- sz = sizeof(boot_current);
- if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) {
- printf(" BootCurrent: %04x\n", boot_current);
-
- sz = sizeof(boot_order);
- if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) {
- printf(" BootOrder:");
- for (i = 0; i < sz / sizeof(boot_order[0]); i++)
- printf(" %04x%s", boot_order[i],
- boot_order[i] == boot_current ? "[*]" : "");
- printf("\n");
- }
- }
-
-#ifdef TEST_FAILURE
- /*
- * For testing failover scenarios, it's nice to be able to fail fast.
- * Define TEST_FAILURE to create a boot1.efi that always fails after
- * reporting the boot manager protocol details.
- */
- BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL);
-#endif
-
- hsize = 0;
- BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
- &hsize, NULL);
- handles = malloc(hsize);
- if (handles == NULL)
- efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
- hsize);
- status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
- NULL, &hsize, handles);
- if (status != EFI_SUCCESS)
- efi_panic(status, "Failed to get device handles\n");
-
- /* Scan all partitions, probing with all modules. */
- nhandles = hsize / sizeof(*handles);
- printf(" Probing %zu block devices...", nhandles);
- DPRINTF("\n");
-
- for (i = 0; i < nhandles; i++) {
- rv = probe_handle(handles[i], imgpath);
-#ifdef EFI_DEBUG
- printf("%c", "x.+*"[rv + 1]);
-#else
- printf("%s\n", prio_str[rv + 1]);
-#endif
- }
- printf(" done\n");
-
- /* Status summary. */
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- printf(" ");
- boot_modules[i]->status();
- }
-
- try_boot();
+ choice_protocol(handles, nhandles, imgpath);
/* If we get here, we're out of luck... */
efi_panic(EFI_LOAD_ERROR, "No bootable partitions found!");
Index: stand/efi/boot1/boot_module.h
===================================================================
--- stand/efi/boot1/boot_module.h
+++ stand/efi/boot1/boot_module.h
@@ -96,6 +96,9 @@
dev_info_t *(*devices)(void);
} boot_module_t;
+extern const boot_module_t *boot_modules[];
+extern const UINTN num_boot_modules;
+
/* Standard boot modules. */
#ifdef EFI_UFS_BOOT
extern const boot_module_t ufs_module;
Index: stand/efi/boot1/proto.h
===================================================================
--- /dev/null
+++ stand/efi/boot1/proto.h
@@ -0,0 +1,2 @@
+void choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath);
+EFI_STATUS try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t loadersize);
Index: stand/efi/boot1/proto.c
===================================================================
--- /dev/null
+++ stand/efi/boot1/proto.c
@@ -0,0 +1,202 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <machine/elf.h>
+#include <machine/stdarg.h>
+#include <stand.h>
+
+#include <efi.h>
+#include <eficonsctl.h>
+#include <efichar.h>
+
+#include "boot_module.h"
+#include "paths.h"
+#include "proto.h"
+
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+
+static const char *prio_str[] = {
+ "error",
+ "not supported",
+ "good",
+ "better"
+};
+
+/*
+ * probe_handle determines if the passed handle represents a logical partition
+ * if it does it uses each module in order to probe it and if successful it
+ * returns EFI_SUCCESS.
+ */
+static int
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
+{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath;
+ EFI_STATUS status;
+ UINTN i;
+ int preferred;
+
+ /* Figure out if we're dealing with an actual partition. */
+ status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status == EFI_UNSUPPORTED)
+ return (0);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+#ifdef EFI_DEBUG
+ {
+ CHAR16 *text = efi_devpath_name(devpath);
+ DPRINTF("probing: %S ", text);
+ efi_free_devpath_name(text);
+ }
+#endif
+ status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status == EFI_UNSUPPORTED)
+ return (0);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+
+ if (!blkio->Media->LogicalPartition)
+ return (0);
+
+ preferred = efi_devpath_same_disk(imgpath, devpath);
+
+ /* Run through each module, see if it can load this partition */
+ devinfo = malloc(sizeof(*devinfo));
+ if (devinfo == NULL) {
+ DPRINTF("\nFailed to allocate devinfo\n");
+ return (-1);
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->preferred = preferred;
+ devinfo->next = NULL;
+
+ for (i = 0; i < num_boot_modules; i++) {
+ devinfo->devdata = NULL;
+
+ status = boot_modules[i]->probe(devinfo);
+ if (status == EFI_SUCCESS)
+ return (preferred + 1);
+ }
+ free(devinfo);
+
+ return (0);
+}
+
+/*
+ * load_loader attempts to load the loader image data.
+ *
+ * It tries each module and its respective devices, identified by mod->probe,
+ * in order until a successful load occurs at which point it returns EFI_SUCCESS
+ * and EFI_NOT_FOUND otherwise.
+ *
+ * Only devices which have preferred matching the preferred parameter are tried.
+ */
+static EFI_STATUS
+load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
+ size_t *bufsize, int preferred)
+{
+ UINTN i;
+ dev_info_t *dev;
+ const boot_module_t *mod;
+
+ for (i = 0; i < num_boot_modules; i++) {
+ mod = boot_modules[i];
+ for (dev = mod->devices(); dev != NULL; dev = dev->next) {
+ if (dev->preferred != preferred)
+ continue;
+
+ if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *devinfop = dev;
+ *modp = mod;
+ return (EFI_SUCCESS);
+ }
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+void
+choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath)
+{
+ UINT16 boot_current;
+ size_t sz;
+ UINT16 boot_order[100];
+ unsigned i;
+ int rv;
+ EFI_STATUS status;
+ const boot_module_t *mod;
+ dev_info_t *dev;
+ void *loaderbuf;
+ size_t loadersize;
+
+ /* Report UEFI Boot Manager Protocol details */
+ boot_current = 0;
+ sz = sizeof(boot_current);
+ if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) {
+ printf(" BootCurrent: %04x\n", boot_current);
+
+ sz = sizeof(boot_order);
+ if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) {
+ printf(" BootOrder:");
+ for (i = 0; i < sz / sizeof(boot_order[0]); i++)
+ printf(" %04x%s", boot_order[i],
+ boot_order[i] == boot_current ? "[*]" : "");
+ printf("\n");
+ }
+ }
+
+#ifdef TEST_FAILURE
+ /*
+ * For testing failover scenarios, it's nice to be able to fail fast.
+ * Define TEST_FAILURE to create a boot1.efi that always fails after
+ * reporting the boot manager protocol details.
+ */
+ BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL);
+#endif
+
+ /* Scan all partitions, probing with all modules. */
+ printf(" Probing %zu block devices...", nhandles);
+ DPRINTF("\n");
+ for (i = 0; i < nhandles; i++) {
+ rv = probe_handle(handles[i], imgpath);
+#ifdef EFI_DEBUG
+ printf("%c", "x.+*"[rv + 1]);
+#else
+ printf("%s\n", prio_str[rv + 1]);
+#endif
+ }
+ printf(" done\n");
+
+
+ /* Status summary. */
+ for (i = 0; i < num_boot_modules; i++) {
+ printf(" ");
+ boot_modules[i]->status();
+ }
+
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1);
+ if (status != EFI_SUCCESS) {
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0);
+ if (status != EFI_SUCCESS) {
+ printf("Failed to load '%s'\n", PATH_LOADER_EFI);
+ return;
+ }
+ }
+
+ try_boot(mod, dev, loaderbuf, loadersize);
+}
Index: stand/efi/gptboot/Makefile
===================================================================
--- /dev/null
+++ stand/efi/gptboot/Makefile
@@ -0,0 +1,13 @@
+MK_LOADER_ZFS=no
+EFI_DEBUG=yes
+NOFAT=yes
+
+BOOT1?= gptboot
+.PATH: ${SRCTOP}/stand/efi/boot1 ${SRCTOP}/stand/libsa
+CFLAGS+= -I${SRCTOP}/stand/efi/boot1
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -DBOOTPROG=\"gptboot.efi\"
+SRCS+= gpt.c
+CWARNFLAGS.gpt.c+= -Wno-sign-compare -Wno-cast-align
+WARNS=6
+.include "${.CURDIR}/../boot1/Makefile"
Index: stand/efi/gptboot/drv.h
===================================================================
--- /dev/null
+++ stand/efi/gptboot/drv.h
@@ -0,0 +1,14 @@
+#ifndef _DRV_H_
+#define _DRV_H_
+
+struct dsk {
+ int part;
+ daddr_t start;
+ void *devinfo;
+};
+
+int drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk);
+int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk);
+uint64_t drvsize(struct dsk *dskp);
+
+#endif /* !_DRV_H_ */
Index: stand/efi/gptboot/proto.c
===================================================================
--- /dev/null
+++ stand/efi/gptboot/proto.c
@@ -0,0 +1,255 @@
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <machine/elf.h>
+#include <machine/stdarg.h>
+#include <stand.h>
+
+#include <efi.h>
+#include <eficonsctl.h>
+#include <efichar.h>
+
+#include "boot_module.h"
+#include "paths.h"
+#include "proto.h"
+
+#include "gpt.h"
+#include <sys/gpt.h>
+static const uuid_t freebsd_ufs_uuid = GPT_ENT_TYPE_FREEBSD_UFS;
+static char secbuf[4096];
+static struct dsk dsk;
+static dev_info_t *devices = NULL;
+static dev_info_t *raw_device = NULL;
+
+static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+
+/*
+ * Shim routine for the gpt code to read in the gpt table. The
+ * devinfo is always going to be for the raw device.
+ */
+int
+drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
+{
+ int size;
+ EFI_STATUS status;
+ dev_info_t *devinfo = (dev_info_t *)dskp->devinfo;
+ EFI_BLOCK_IO *dev = devinfo->dev;
+
+ lba = lba / (dev->Media->BlockSize / DEV_BSIZE);
+ size = nblk * DEV_BSIZE;
+
+ status = dev->ReadBlocks(dev, dev->Media->MediaId, lba, size, buf);
+ if (status != EFI_SUCCESS) {
+ DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, "
+ "status: %lu\n", devinfo->dev,
+ dev->Media->MediaId, (uintmax_t)lba, size,
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Shim routine for the gpt code to write in the gpt table. The
+ * devinfo is always going to be for the raw device.
+ */
+int
+drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
+{
+ int size;
+ EFI_STATUS status;
+ dev_info_t *devinfo = (dev_info_t *)dskp->devinfo;
+ EFI_BLOCK_IO *dev = devinfo->dev;
+
+ if (dev->Media->ReadOnly)
+ return -1;
+
+ lba = lba / (dev->Media->BlockSize / DEV_BSIZE);
+ size = nblk * DEV_BSIZE;
+
+ status = dev->WriteBlocks(dev, dev->Media->MediaId, lba, size, buf);
+ if (status != EFI_SUCCESS) {
+ DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, "
+ "status: %lu\n", devinfo->dev,
+ dev->Media->MediaId, (uintmax_t)lba, size,
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Return the number of LBAs the drive has.
+ */
+uint64_t
+drvsize(struct dsk *dskp)
+{
+ dev_info_t *devinfo = (dev_info_t *)dskp->devinfo;
+ EFI_BLOCK_IO *dev = devinfo->dev;
+
+ return (dev->Media->LastBlock + 1);
+}
+
+static int
+partition_number(EFI_DEVICE_PATH *devpath)
+{
+ EFI_DEVICE_PATH *md;
+ HARDDRIVE_DEVICE_PATH *hd;
+
+ md = efi_devpath_last_node(devpath);
+ if (md == NULL)
+ return (-1);
+ if (DevicePathSubType(md) != MEDIA_HARDDRIVE_DP)
+ return (-1);
+ hd = (HARDDRIVE_DEVICE_PATH *)md;
+ return (hd->PartitionNumber);
+}
+
+/*
+ * Find the raw parittion for the imgpath and save it
+ */
+static void
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
+{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath, *trimmed = NULL;
+ EFI_STATUS status;
+
+ /* Figure out if we're dealing with an actual partition. */
+ status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status != EFI_SUCCESS)
+ return;
+#ifdef EFI_DEBUG
+ {
+ CHAR16 *text = efi_devpath_name(devpath);
+ DPRINTF("probing: %S ", text);
+ efi_free_devpath_name(text);
+ }
+#endif
+ /*
+ * The RAW device is the same as the imgpath with the last
+ * MEDIA_DEVICE bit trimmed off. imgpath will end with the
+ * MEDIA_DEVICE for the ESP we booted off of.
+ */
+ if (!efi_devpath_same_disk(imgpath, devpath)) {
+ trimmed = efi_devpath_trim(imgpath);
+ if (!efi_devpath_match(trimmed, devpath)) {
+ free(trimmed);
+ DPRINTF("Not the same disk\n");
+ return;
+ }
+ }
+ status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status != EFI_SUCCESS) {
+ DPRINTF("Can't get the block I/O protocol block\n");
+ return;
+ }
+ devinfo = malloc(sizeof(*devinfo));
+ if (devinfo == NULL) {
+ DPRINTF("Failed to allocate devinfo\n");
+ return;
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->preferred = 1;
+ devinfo->next = NULL;
+ devinfo->devdata = NULL;
+ if (trimmed == NULL) {
+ DPRINTF("Found partition %d\n", partition_number(devpath));
+ add_device(&devices, devinfo);
+ } else {
+ free(trimmed);
+ DPRINTF("Found raw device\n");
+ if (raw_device) {
+ printf(BOOTPROG": Found two raw devices? WTF?\n");
+ return;
+ }
+ raw_device = devinfo;
+ }
+}
+
+static void
+probe_handles(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath)
+{
+ UINTN i;
+
+ for (i = 0; i < nhandles; i++)
+ probe_handle(handles[i], imgpath);
+}
+
+static dev_info_t *
+find_partition(int part)
+{
+ dev_info_t *dev;
+
+ if (part == 0)
+ return (NULL);
+ for (dev = devices; dev != NULL; dev = dev->next)
+ if (partition_number(dev->devpath) == part)
+ break;
+ return (dev);
+}
+
+void
+choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath)
+{
+ const boot_module_t *mod = &ufs_module;
+ dev_info_t *bootdev;
+ void *loaderbuf;
+ size_t loadersize;
+ int parts;
+ const char *fn = PATH_LOADER_EFI;
+
+ /*
+ * Probe the provided handles to find the partitions that
+ * are on the same drive.
+ */
+ probe_handles(handles, nhandles, imgpath);
+ dsk.devinfo = raw_device;
+ if (dsk.devinfo == NULL) {
+ printf(BOOTPROG": unable to find raw disk to read gpt\n");
+ return;
+ }
+
+ /*
+ * Read in the GPT table, and then find the right partition.
+ * gptread, gptfind and gptfaileboot are shared with the
+ * BIOS version of the gptboot program.
+ */
+ if (gptread(&dsk, secbuf) == -1) {
+ printf(BOOTPROG ": unable to load GPT\n");
+ return;
+ }
+ // XXX:
+ // real gptboot can parse a command line before trying this loop.
+ // But since we don't parse anything at all, hard wire the partition
+ // to be -1 (meaning look for the next one).
+ parts = 0;
+ while (gptfind(&freebsd_ufs_uuid, &dsk, -1) != -1) {
+ parts++;
+ bootdev = find_partition(dsk.part);
+ if (bootdev == NULL) {
+ printf(BOOTPROG": Can't find partition %d\n",
+ dsk.part);
+ goto next;
+ }
+ if (mod->load(fn, bootdev, &loaderbuf, &loadersize) !=
+ EFI_SUCCESS) {
+ printf(BOOTPROG": Can't load %s from partition %d\n",
+ fn, dsk.part);
+ goto next;
+ }
+ try_boot(mod, bootdev, loaderbuf, loadersize);
+next:
+ gptbootfailed(&dsk);
+ }
+ if (parts == 0)
+ printf("%s: no UFS partition was found\n", BOOTPROG);
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 10, 1:29 PM (17 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23532987
Default Alt Text
D20547.id58344.diff (21 KB)

Event Timeline