Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154937770
D20547.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D20547.diff
View Options
Index: head/stand/efi/boot1/Makefile
===================================================================
--- head/stand/efi/boot1/Makefile
+++ head/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: head/stand/efi/boot1/boot1.c
===================================================================
--- head/stand/efi/boot1/boot1.c
+++ head/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,9 +46,8 @@
&ufs_module
#endif
};
+const UINTN num_boot_modules = nitems(boot_modules);
-#define NUM_BOOT_MODULES nitems(boot_modules)
-
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
@@ -91,65 +91,19 @@
}
/*
- * 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: head/stand/efi/boot1/boot_module.h
===================================================================
--- head/stand/efi/boot1/boot_module.h
+++ head/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: head/stand/efi/boot1/proto.h
===================================================================
--- head/stand/efi/boot1/proto.h
+++ head/stand/efi/boot1/proto.h
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 2019 Netflix, Inc
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+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: head/stand/efi/boot1/proto.c
===================================================================
--- head/stand/efi/boot1/proto.c
+++ head/stand/efi/boot1/proto.c
@@ -0,0 +1,223 @@
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ * Copyright (c) 2001 Robert Drehmel
+ * All rights reserved.
+ * Copyright (c) 2014 Nathan Whitehorn
+ * All rights reserved.
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
+#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);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 1, 4:46 AM (16 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32554975
Default Alt Text
D20547.diff (16 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