Break out the disk selection protocol from the rest of boot1.
Segregate the disk probing and selection protocol from the rest of the boot loader. Reviewed by: tsoome, bcran Differential Revision: https://reviews.freebsd.org/D20547
This commit is contained in:
parent
ca8929d2a3
commit
f46eb75217
@ -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-parameter
|
||||
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}
|
||||
|
@ -33,10 +33,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#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 @@ static const boot_module_t *boot_modules[] =
|
||||
&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 @@ Calloc(size_t n1, size_t n2, const char *file, int line)
|
||||
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 @@ try_boot(void)
|
||||
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 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
|
||||
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 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
|
||||
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 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
|
||||
}
|
||||
}
|
||||
|
||||
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!");
|
||||
|
@ -96,6 +96,9 @@ typedef struct boot_module_t
|
||||
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;
|
||||
|
223
stand/efi/boot1/proto.c
Normal file
223
stand/efi/boot1/proto.c
Normal file
@ -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);
|
||||
}
|
29
stand/efi/boot1/proto.h
Normal file
29
stand/efi/boot1/proto.h
Normal file
@ -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);
|
Loading…
Reference in New Issue
Block a user