Index: sys/boot/efi/boot1/boot1.c =================================================================== --- sys/boot/efi/boot1/boot1.c +++ sys/boot/efi/boot1/boot1.c @@ -29,10 +29,14 @@ #include #include +typedef CHAR16 efi_char; +#include #include "boot_module.h" #include "paths.h" +static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3); + static const boot_module_t *boot_modules[] = { #ifdef EFI_ZFS_BOOT @@ -51,6 +55,7 @@ static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; +static EFI_GUID FreeBSDBootVarGUID = FREEBSD_BOOT_VAR_GUID; /* * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures @@ -75,6 +80,34 @@ (void)BS->FreePool(buf); } +static int +wcslen(const CHAR16 *str) +{ + int i; + + i = 0; + while (*str++) + i++; + return i; +} + +static EFI_STATUS +efi_setenv_freebsd_wcs(const char *varname, CHAR16 *valstr) +{ + CHAR16 *var = NULL; + size_t len; + EFI_STATUS rv; + + utf8_to_ucs2(varname, &var, &len); + if (var == NULL) + return (EFI_OUT_OF_RESOURCES); + rv = RS->SetVariable(var, &FreeBSDBootVarGUID, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + wcslen(valstr) * 2, valstr); + free(var); + return (rv); +} + /* * devpath_last returns the last non-path end node in devpath. */ @@ -275,11 +308,9 @@ /* Run through each module, see if it can load this partition */ for (i = 0; i < NUM_BOOT_MODULES; i++) { - if ((status = BS->AllocatePool(EfiLoaderData, - sizeof(*devinfo), (void **)&devinfo)) != - EFI_SUCCESS) { - DPRINTF("\nFailed to allocate devinfo (%lu)\n", - EFI_ERROR_CODE(status)); + devinfo = malloc(sizeof(*devinfo)); + if (devinfo == NULL) { + DPRINTF("\nFailed to allocate devinfo\n"); continue; } devinfo->dev = blkio; @@ -292,7 +323,7 @@ status = boot_modules[i]->probe(devinfo); if (status == EFI_SUCCESS) return (EFI_SUCCESS); - (void)BS->FreePool(devinfo); + free(devinfo); } return (EFI_UNSUPPORTED); @@ -344,6 +375,7 @@ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; + CHAR16 *text; /* Basic initialization*/ ST = Xsystab; @@ -387,12 +419,35 @@ } putchar('\n'); + /* Determine the devpath of our image so we can prefer it. */ + status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img); + imgpath = NULL; + if (status == EFI_SUCCESS) { + text = efi_devpath_name(img->FilePath); + printf(" Load Path: %S\n", text); + efi_setenv_freebsd_wcs("Boot1Path", text); + efi_free_devpath_name(text); + + status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID, + (void **)&imgpath); + if (status != EFI_SUCCESS) { + DPRINTF("Failed to get image DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + } else { + text = efi_devpath_name(imgpath); + printf(" Load Device: %S\n", text); + efi_setenv_freebsd_wcs("Boot1Dev", text); + efi_free_devpath_name(text); + } + + } + /* Get all the device handles */ hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE); - if ((status = BS->AllocatePool(EfiLoaderData, hsize, (void **)&handles)) - != EFI_SUCCESS) - panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT, - EFI_ERROR_CODE(status)); + handles = malloc(hsize); + if (handles == NULL) { + printf("Failed to allocate %d handles\n", NUM_HANDLES_INIT); + } status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, &hsize, handles); @@ -400,21 +455,19 @@ case EFI_SUCCESS: break; case EFI_BUFFER_TOO_SMALL: - (void)BS->FreePool(handles); - if ((status = BS->AllocatePool(EfiLoaderData, hsize, - (void **)&handles)) != EFI_SUCCESS) { - panic("Failed to allocate %zu handles (%lu)", hsize / - sizeof(*handles), EFI_ERROR_CODE(status)); - } + free(handles); + handles = malloc(hsize); + if (handles == NULL) + efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n", + NUM_HANDLES_INIT); status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, &hsize, handles); if (status != EFI_SUCCESS) - panic("Failed to get device handles (%lu)\n", - EFI_ERROR_CODE(status)); + efi_panic(status, "Failed to get device handles\n"); break; default: - panic("Failed to get device handles (%lu)", - EFI_ERROR_CODE(status)); + efi_panic(status, "Failed to get device handles\n"); + break; } /* Scan all partitions, probing with all modules. */ @@ -422,24 +475,6 @@ printf(" Probing %zu block devices...", nhandles); DPRINTF("\n"); - /* Determine the devpath of our image so we can prefer it. */ - status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img); - imgpath = NULL; - if (status == EFI_SUCCESS) { - status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID, - (void **)&imgpath); - if (status != EFI_SUCCESS) - DPRINTF("Failed to get image DevicePath (%lu)\n", - EFI_ERROR_CODE(status)); -#ifdef EFI_DEBUG - { - CHAR16 *text = efi_devpath_name(imgpath); - DPRINTF("boot1 imagepath: %S\n", text); - efi_free_devpath_name(text); - } -#endif - } - for (i = 0; i < nhandles; i++) probe_handle_status(handles[i], imgpath); printf(" done\n"); @@ -453,7 +488,7 @@ try_boot(); /* If we get here, we're out of luck... */ - panic("No bootable partitions found!"); + efi_panic(EFI_LOAD_ERROR, "No bootable partitions found!"); } /* @@ -475,8 +510,12 @@ dev->next = devinfo; } -void -panic(const char *fmt, ...) +/* + * OK. We totally give up. Exit back to EFI with a sensible status so + * it can try the next option on the list. + */ +static void +efi_panic(EFI_STATUS s, const char *fmt, ...) { va_list ap; @@ -486,7 +525,7 @@ va_end(ap); printf("\n"); - while (1) {} + BS->Exit(IH, s, 0, NULL); } void Index: sys/boot/efi/include/efiapi.h =================================================================== --- sys/boot/efi/include/efiapi.h +++ sys/boot/efi/include/efiapi.h @@ -247,7 +247,7 @@ typedef EFI_STATUS (EFIAPI *EFI_SET_VARIABLE) ( - IN CHAR16 *VariableName, + IN const CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, Index: sys/boot/efi/libefi/Makefile =================================================================== --- sys/boot/efi/libefi/Makefile +++ sys/boot/efi/libefi/Makefile @@ -11,7 +11,7 @@ INTERNALLIB= WARNS?= 2 -SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c env.c errno.c \ +SRCS= delay.c devpath.c efi_console.c efichar.c efinet.c efipart.c env.c errno.c \ handles.c wchar.c libefi.c efi_driver_utils.c efizfs.c devicename.c .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" @@ -56,4 +56,6 @@ CFLAGS+= -DTERM_EMU .endif +CFLAGS+= -DLIBEFI + .include Index: sys/boot/efi/libefi/efichar.c =================================================================== --- sys/boot/efi/libefi/efichar.c +++ sys/boot/efi/libefi/efichar.c @@ -29,10 +29,14 @@ #include #include +#ifdef LIBEFI +#include +#else #include #include #include #include +#endif #include #include