summaryrefslogtreecommitdiffstats
path: root/sys/boot/efi/loader
diff options
context:
space:
mode:
authorsmh <smh@FreeBSD.org>2016-01-15 01:22:36 +0000
committersmh <smh@FreeBSD.org>2016-01-15 01:22:36 +0000
commit97799cc1a6e7cf381d3f16798ccbd1f7559231fe (patch)
tree079ce19f53f7ea26c2dffe6377b2698ecd53ee78 /sys/boot/efi/loader
parenta3974d0c94003fd73cf6d36d76bd5d1493840538 (diff)
downloadFreeBSD-src-97799cc1a6e7cf381d3f16798ccbd1f7559231fe.zip
FreeBSD-src-97799cc1a6e7cf381d3f16798ccbd1f7559231fe.tar.gz
Modularise EFI boot loader
Make EFI boot loader modular in preparation for adding ZFS support. This is a partial commit of the D4515. Submitted by: Eric McCorkle Reviewed by: emaste (in part) MFC after: 2 weeks X-MFC-With: r293268 Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D4515
Diffstat (limited to 'sys/boot/efi/loader')
-rw-r--r--sys/boot/efi/loader/devicename.c37
-rw-r--r--sys/boot/efi/loader/main.c63
2 files changed, 68 insertions, 32 deletions
diff --git a/sys/boot/efi/loader/devicename.c b/sys/boot/efi/loader/devicename.c
index 45f9871..c6591c8 100644
--- a/sys/boot/efi/loader/devicename.c
+++ b/sys/boot/efi/loader/devicename.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
+#include <sys/param.h>
#include <bootstrap.h>
#include <efi.h>
@@ -86,7 +87,7 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
struct devsw *dv;
char *cp;
const char *np;
- int i, err;
+ int i;
/* minimum length check */
if (strlen(devspec) < 2)
@@ -101,24 +102,26 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
if (devsw[i] == NULL)
return (ENOENT);
- idev = malloc(sizeof(struct devdesc));
- if (idev == NULL)
- return (ENOMEM);
-
- idev->d_dev = dv;
- idev->d_type = dv->dv_type;
- idev->d_unit = -1;
-
- err = 0;
np = devspec + strlen(dv->dv_name);
- if (*np != '\0' && *np != ':') {
- idev->d_unit = strtol(np, &cp, 0);
- if (cp == np) {
- idev->d_unit = -1;
- free(idev);
- return (EUNIT);
+
+ {
+ idev = malloc(sizeof(struct devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ idev->d_dev = dv;
+ idev->d_type = dv->dv_type;
+ idev->d_unit = -1;
+ if (*np != '\0' && *np != ':') {
+ idev->d_unit = strtol(np, &cp, 0);
+ if (cp == np) {
+ idev->d_unit = -1;
+ free(idev);
+ return (EUNIT);
+ }
}
}
+
if (*cp != '\0' && *cp != ':') {
free(idev);
return (EINVAL);
@@ -137,7 +140,7 @@ char *
efi_fmtdev(void *vdev)
{
struct devdesc *dev = (struct devdesc *)vdev;
- static char buf[32]; /* XXX device length constant? */
+ static char buf[SPECNAMELEN + 1];
switch(dev->d_type) {
case DEVT_NONE:
diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c
index ddd96b4..43a015d 100644
--- a/sys/boot/efi/loader/main.c
+++ b/sys/boot/efi/loader/main.c
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <stand.h>
#include <string.h>
#include <setjmp.h>
@@ -45,7 +46,6 @@ extern char bootprog_rev[];
extern char bootprog_date[];
extern char bootprog_maker[];
-struct devdesc currdev; /* our current device */
struct arch_switch archsw; /* MI/MD interface boundary */
EFI_GUID acpi = ACPI_TABLE_GUID;
@@ -61,15 +61,36 @@ EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
+/*
+ * Need this because EFI uses UTF-16 unicode string constants, but we
+ * use UTF-8. We can't use printf due to the possiblity of \0 and we
+ * don't support support wide characters either.
+ */
+static void
+print_str16(const CHAR16 *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ printf("%c", (char)str[i]);
+}
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
char var[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i, j, vargood;
+ int i, j, vargood, unit;
+ struct devsw *dev;
UINTN k;
+ archsw.arch_autoload = efi_autoload;
+ archsw.arch_getdev = efi_getdev;
+ archsw.arch_copyin = efi_copyin;
+ archsw.arch_copyout = efi_copyout;
+ archsw.arch_readin = efi_readin;
+
/*
* XXX Chicken-and-egg problem; we want to have console output
* early, but some console attributes may depend on reading from
@@ -116,6 +137,13 @@ main(int argc, CHAR16 *argv[])
/* Get our loaded image protocol interface structure. */
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
+ printf("Command line arguments:");
+ for (i = 0; i < argc; i++) {
+ printf(" ");
+ print_str16(argv[i]);
+ }
+ printf("\n");
+
printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
ST->Hdr.Revision & 0xffff);
@@ -129,9 +157,6 @@ main(int argc, CHAR16 *argv[])
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
- efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
- currdev.d_type = currdev.d_dev->dv_type;
-
/*
* Disable the watchdog timer. By default the boot manager sets
* the timer to 5 minutes before invoking a boot option. If we
@@ -143,19 +168,27 @@ main(int argc, CHAR16 *argv[])
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
- env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
- env_nounset);
+ if (efi_handle_lookup(img->DeviceHandle, &dev, &unit) != 0)
+ return (EFI_NOT_FOUND);
+
+ switch (dev->dv_type) {
+ default: {
+ struct devdesc currdev;
+
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_opendata = NULL;
+ currdev.d_type = currdev.d_dev->dv_type;
+ env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+ efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+ env_nounset);
+ break;
+ }
+ }
setenv("LINES", "24", 1); /* optional */
- archsw.arch_autoload = efi_autoload;
- archsw.arch_getdev = efi_getdev;
- archsw.arch_copyin = efi_copyin;
- archsw.arch_copyout = efi_copyout;
- archsw.arch_readin = efi_readin;
-
for (k = 0; k < ST->NumberOfTableEntries; k++) {
guid = &ST->ConfigurationTable[k].VendorGuid;
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
OpenPOWER on IntegriCloud