Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131590643
D20547.id58344.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D20547.id58344.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D20547: Split boot1 in half and use the useful half for gptboot.efi
Attached
Detach File
Event Timeline
Log In to Comment