diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/boot/efi/include/efilib.h | 5 | ||||
-rw-r--r-- | sys/boot/efi/libefi/Makefile | 2 | ||||
-rw-r--r-- | sys/boot/efi/libefi/libefi.c | 131 | ||||
-rw-r--r-- | sys/boot/efi/loader/main.c | 22 | ||||
-rw-r--r-- | sys/boot/ia64/efi/main.c | 22 |
5 files changed, 141 insertions, 41 deletions
diff --git a/sys/boot/efi/include/efilib.h b/sys/boot/efi/include/efilib.h index 9d79939733e1..695f334d48bb 100644 --- a/sys/boot/efi/include/efilib.h +++ b/sys/boot/efi/include/efilib.h @@ -31,4 +31,7 @@ extern EFI_SYSTEM_TABLE *ST; extern EFI_BOOT_SERVICES *BS; extern EFI_RUNTIME_SERVICES *RS; -void efi_init(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); +void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); + +EFI_STATUS main(int argc, CHAR16 *argv[]); +void exit(EFI_STATUS status); diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile index 894b14371c09..6ab48e254bc6 100644 --- a/sys/boot/efi/libefi/Makefile +++ b/sys/boot/efi/libefi/Makefile @@ -5,7 +5,7 @@ LIB= efi INTERNALLIB= true -SRCS= libefi.c efi_console.c time.c copy.c devicename.c module.c exit.c +SRCS= libefi.c efi_console.c time.c copy.c devicename.c module.c SRCS+= delay.c efifs.c efinet.c elf_freebsd.c bootinfo.c pal.s .if ${MACHINE_ARCH} == "ia64" diff --git a/sys/boot/efi/libefi/libefi.c b/sys/boot/efi/libefi/libefi.c index c0bacc8a0bc5..e28d8db71f79 100644 --- a/sys/boot/efi/libefi/libefi.c +++ b/sys/boot/efi/libefi/libefi.c @@ -31,17 +31,146 @@ static const char rcsid[] = #include <efi.h> #include <efilib.h> +#include <stand.h> EFI_HANDLE IH; EFI_SYSTEM_TABLE *ST; EFI_BOOT_SERVICES *BS; EFI_RUNTIME_SERVICES *RS; +static EFI_PHYSICAL_ADDRESS heap; +static UINTN heapsize; + +static CHAR16 * +arg_skipsep(CHAR16 *argp) +{ + + while (*argp == ' ' || *argp == '\t') + argp++; + return (argp); +} + +static CHAR16 * +arg_skipword(CHAR16 *argp) +{ + + while (*argp && *argp != ' ' && *argp != '\t') + argp++; + return (argp); +} + +void exit(EFI_STATUS exit_code) +{ + + BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize)); + BS->Exit(IH, exit_code, 0, NULL); +} + void -efi_init(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) +efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) { + static EFI_GUID image_protocol = LOADED_IMAGE_PROTOCOL; + EFI_LOADED_IMAGE *img; + CHAR16 *argp, *args, **argv; + EFI_STATUS status; + int argc, addprog; + IH = image_handle; ST = system_table; BS = ST->BootServices; RS = ST->RuntimeServices; + + heapsize = 512*1024; + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, + EFI_SIZE_TO_PAGES(heapsize), &heap); + if (status != EFI_SUCCESS) + BS->Exit(IH, status, 0, NULL); + + setheap((void *)heap, (void *)(heap + heapsize)); + + /* Use exit() from here on... */ + + status = BS->HandleProtocol(IH, &image_protocol, (VOID**)&img); + if (status != EFI_SUCCESS) + exit(status); + + /* + * Pre-process the (optional) load options. If the option string + * is given as an ASCII string, we use a poor man's ASCII to + * Unicode-16 translation. The size of the option string as given + * to us includes the terminating null character. We assume the + * string is an ASCII string if strlen() plus the terminating + * '\0' is less than LoadOptionsSize. Even if all Unicode-16 + * characters have the upper 8 bits non-zero, the terminating + * null character will cause a one-off. + * If the string is already in Unicode-16, we make a copy so that + * we know we can always modify the string. + */ + if (img->LoadOptionsSize) { + if (img->LoadOptionsSize == strlen(img->LoadOptions) + 1) { + args = malloc(img->LoadOptionsSize << 1); + for (argc = 0; argc < img->LoadOptionsSize; argc++) + args[argc] = ((char*)img->LoadOptions)[argc]; + } else { + args = malloc(img->LoadOptionsSize); + memcpy(args, img->LoadOptions, img->LoadOptionsSize); + } + } else + args = NULL; + + /* + * Use a quick and dirty algorithm to build the argv vector. We + * first count the number of words. Then, after allocating the + * vector, we split the string up. We don't deal with quotes or + * other more advanced shell features. + * The EFI shell will pas the name of the image as the first + * word in the argument list. This does not happen if we're + * loaded by the boot manager. This is not so easy to figure + * out though. The ParentHandle is not always NULL, because + * there can be a function (=image) that will perform the task + * for the boot manager. + */ + /* Part 1: Figure out if we need to add our program name. */ + addprog = (args == NULL || img->ParentHandle == NULL || + img->FilePath == NULL) ? 1 : 0; + if (!addprog) { + addprog = + (DevicePathType(img->FilePath) != MEDIA_DEVICE_PATH || + DevicePathSubType(img->FilePath) != MEDIA_FILEPATH_DP || + DevicePathNodeLength(img->FilePath) <= + sizeof(FILEPATH_DEVICE_PATH)) ? 1 : 0; + if (!addprog) { + /* XXX todo. */ + } + } + /* Part 2: count words. */ + argc = (addprog) ? 1 : 0; + argp = args; + while (argp != NULL && *argp != 0) { + argp = arg_skipsep(argp); + if (*argp == 0) + break; + argc++; + argp = arg_skipword(argp); + } + /* Part 3: build vector. */ + argv = malloc((argc + 1) * sizeof(CHAR16*)); + argc = 0; + if (addprog) + argv[argc++] = L"loader.efi"; + argp = args; + while (argp != NULL && *argp != 0) { + argp = arg_skipsep(argp); + if (*argp == 0) + break; + argv[argc++] = argp; + argp = arg_skipword(argp); + /* Terminate the words. */ + if (*argp != 0) + *argp++ = 0; + } + argv[argc] = NULL; + + status = main(argc, argv); + exit(status); } diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c index 5a886ed2e805..51ac572b9f3e 100644 --- a/sys/boot/efi/loader/main.c +++ b/sys/boot/efi/loader/main.c @@ -104,27 +104,13 @@ find_pal_proc(void) } EFI_STATUS -efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) +main(int argc, CHAR16 *argv[]) { - EFI_PHYSICAL_ADDRESS mem; EFI_LOADED_IMAGE *img; EFI_SIMPLE_NETWORK *net; EFI_STATUS status; - struct ia64_pal_result res; - char buf[32]; int i; - efi_init(image_handle, system_table); - - /* - * Initialise the heap as early as possible. Once this is done, - * alloc() is usable. The stack is buried inside us, so this is - * safe. - */ - BS->AllocatePages(AllocateAnyPages, EfiLoaderData, - 512*1024/4096, &mem); - setheap((void *)mem, (void *)(mem + 512*1024)); - /* * XXX Chicken-and-egg problem; we want to have console output * early, but some console attributes may depend on reading from @@ -148,7 +134,7 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) (devsw[i]->dv_init)(); efinet_init_driver(); - + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); @@ -156,14 +142,13 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) printf("Memory: %ld k\n", memsize() / 1024); #endif - /* * XXX quick and dirty check to see if we're loaded from the * network. If so, we set the default device to 'net'. In all * other cases we set the default device to 'disk'. We presume * fixed positions in devsw for both net and disk. */ - BS->HandleProtocol(image_handle, &imgid, (VOID**)&img); + BS->HandleProtocol(IH, &imgid, (VOID**)&img); status = BS->HandleProtocol(img->DeviceHandle, &netid, (VOID**)&net); if (status == EFI_SUCCESS && net != NULL) { @@ -177,7 +162,6 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) /* default to 'a' */ currdev.d_kind.efidisk.partition = 0; } - currdev.d_type = currdev.d_dev->dv_type; /* diff --git a/sys/boot/ia64/efi/main.c b/sys/boot/ia64/efi/main.c index 5a886ed2e805..51ac572b9f3e 100644 --- a/sys/boot/ia64/efi/main.c +++ b/sys/boot/ia64/efi/main.c @@ -104,27 +104,13 @@ find_pal_proc(void) } EFI_STATUS -efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) +main(int argc, CHAR16 *argv[]) { - EFI_PHYSICAL_ADDRESS mem; EFI_LOADED_IMAGE *img; EFI_SIMPLE_NETWORK *net; EFI_STATUS status; - struct ia64_pal_result res; - char buf[32]; int i; - efi_init(image_handle, system_table); - - /* - * Initialise the heap as early as possible. Once this is done, - * alloc() is usable. The stack is buried inside us, so this is - * safe. - */ - BS->AllocatePages(AllocateAnyPages, EfiLoaderData, - 512*1024/4096, &mem); - setheap((void *)mem, (void *)(mem + 512*1024)); - /* * XXX Chicken-and-egg problem; we want to have console output * early, but some console attributes may depend on reading from @@ -148,7 +134,7 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) (devsw[i]->dv_init)(); efinet_init_driver(); - + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); @@ -156,14 +142,13 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) printf("Memory: %ld k\n", memsize() / 1024); #endif - /* * XXX quick and dirty check to see if we're loaded from the * network. If so, we set the default device to 'net'. In all * other cases we set the default device to 'disk'. We presume * fixed positions in devsw for both net and disk. */ - BS->HandleProtocol(image_handle, &imgid, (VOID**)&img); + BS->HandleProtocol(IH, &imgid, (VOID**)&img); status = BS->HandleProtocol(img->DeviceHandle, &netid, (VOID**)&net); if (status == EFI_SUCCESS && net != NULL) { @@ -177,7 +162,6 @@ efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) /* default to 'a' */ currdev.d_kind.efidisk.partition = 0; } - currdev.d_type = currdev.d_dev->dv_type; /* |