Home | History | Annotate | Line # | Download | only in libefi
efi.c revision 1.3.100.1
      1  1.3.100.1     tls /*	$NetBSD: efi.c,v 1.3.100.1 2013/02/25 00:28:46 tls Exp $	*/
      2        1.1  cherry 
      3        1.1  cherry /*-
      4        1.1  cherry  * Copyright (c) 2000 Doug Rabson
      5        1.1  cherry  * All rights reserved.
      6        1.1  cherry  *
      7        1.1  cherry  * Redistribution and use in source and binary forms, with or without
      8        1.1  cherry  * modification, are permitted provided that the following conditions
      9        1.1  cherry  * are met:
     10        1.1  cherry  * 1. Redistributions of source code must retain the above copyright
     11        1.1  cherry  *    notice, this list of conditions and the following disclaimer.
     12        1.1  cherry  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1  cherry  *    notice, this list of conditions and the following disclaimer in the
     14        1.1  cherry  *    documentation and/or other materials provided with the distribution.
     15        1.1  cherry  *
     16        1.1  cherry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17        1.1  cherry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18        1.1  cherry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19        1.1  cherry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20        1.1  cherry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21        1.1  cherry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22        1.1  cherry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23        1.1  cherry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24        1.1  cherry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25        1.1  cherry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26        1.1  cherry  * SUCH DAMAGE.
     27        1.1  cherry  */
     28        1.1  cherry 
     29        1.1  cherry #include <sys/cdefs.h>
     30        1.3   kochi /* __FBSDID("$FreeBSD: src/sys/boot/efi/libefi/libefi.c,v 1.6 2003/04/03 21:36:29 obrien Exp $"); */
     31        1.1  cherry 
     32        1.1  cherry #include <efi.h>
     33        1.1  cherry #include <efilib.h>
     34        1.1  cherry #include <lib/libsa/stand.h>
     35  1.3.100.1     tls #include <lib/libkern/libkern.h>
     36        1.1  cherry 
     37        1.1  cherry EFI_HANDLE		IH;
     38        1.1  cherry EFI_SYSTEM_TABLE	*ST;
     39        1.1  cherry EFI_BOOT_SERVICES	*BS;
     40        1.1  cherry EFI_RUNTIME_SERVICES	*RS;
     41        1.1  cherry 
     42        1.1  cherry static EFI_PHYSICAL_ADDRESS heap;
     43        1.1  cherry static UINTN heapsize;
     44        1.1  cherry 
     45        1.1  cherry static CHAR16 *
     46        1.1  cherry arg_skipsep(CHAR16 *argp)
     47        1.1  cherry {
     48        1.1  cherry 
     49        1.1  cherry 	while (*argp == ' ' || *argp == '\t')
     50        1.1  cherry 		argp++;
     51        1.1  cherry 	return (argp);
     52        1.1  cherry }
     53        1.1  cherry 
     54        1.1  cherry static CHAR16 *
     55        1.1  cherry arg_skipword(CHAR16 *argp)
     56        1.1  cherry {
     57        1.1  cherry 
     58        1.1  cherry 	while (*argp && *argp != ' ' && *argp != '\t')
     59        1.1  cherry 		argp++;
     60        1.1  cherry 	return (argp);
     61        1.1  cherry }
     62        1.1  cherry 
     63        1.1  cherry void *
     64        1.1  cherry efi_get_table(EFI_GUID *tbl)
     65        1.1  cherry {
     66        1.1  cherry 	EFI_GUID *id;
     67        1.1  cherry 	int i;
     68        1.1  cherry 
     69        1.1  cherry 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
     70        1.1  cherry 		id = &ST->ConfigurationTable[i].VendorGuid;
     71        1.1  cherry 		if (!memcmp(id, tbl, sizeof(EFI_GUID)))
     72        1.1  cherry 			return (ST->ConfigurationTable[i].VendorTable);
     73        1.1  cherry 	}
     74        1.1  cherry 	return (NULL);
     75        1.1  cherry }
     76        1.1  cherry 
     77        1.1  cherry void efi_exit(EFI_STATUS exit_code)
     78        1.1  cherry {
     79        1.1  cherry 
     80        1.1  cherry 	BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize));
     81        1.1  cherry 	BS->Exit(IH, exit_code, 0, NULL);
     82        1.1  cherry }
     83        1.1  cherry 
     84        1.1  cherry void
     85        1.1  cherry efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
     86        1.1  cherry {
     87        1.1  cherry 	static EFI_GUID image_protocol = LOADED_IMAGE_PROTOCOL;
     88        1.1  cherry 	EFI_LOADED_IMAGE *img;
     89        1.1  cherry 	CHAR16 *argp, *args, **argv;
     90        1.1  cherry 	EFI_STATUS status;
     91        1.1  cherry 	int argc, addprog;
     92        1.1  cherry 
     93        1.1  cherry 	IH = image_handle;
     94        1.1  cherry 	ST = system_table;
     95        1.1  cherry 	BS = ST->BootServices;
     96        1.1  cherry 	RS = ST->RuntimeServices;
     97        1.1  cherry 
     98        1.1  cherry 	heapsize = 512*1024;
     99        1.1  cherry 	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
    100        1.1  cherry 	    EFI_SIZE_TO_PAGES(heapsize), &heap);
    101        1.1  cherry 	if (status != EFI_SUCCESS)
    102        1.1  cherry 		BS->Exit(IH, status, 0, NULL);
    103        1.1  cherry 
    104        1.1  cherry 	setheap((void *)heap, (void *)(heap + heapsize));
    105        1.1  cherry 
    106        1.1  cherry 	/* Use efi_exit() from here on... */
    107        1.1  cherry 
    108        1.1  cherry 	status = BS->HandleProtocol(IH, &image_protocol, (VOID**)&img);
    109        1.1  cherry 	if (status != EFI_SUCCESS)
    110        1.1  cherry 		efi_exit(status);
    111        1.1  cherry 
    112        1.1  cherry 	/*
    113        1.1  cherry 	 * Pre-process the (optional) load options. If the option string
    114        1.1  cherry 	 * is given as an ASCII string, we use a poor man's ASCII to
    115        1.1  cherry 	 * Unicode-16 translation. The size of the option string as given
    116        1.1  cherry 	 * to us includes the terminating null character. We assume the
    117        1.1  cherry 	 * string is an ASCII string if strlen() plus the terminating
    118        1.1  cherry 	 * '\0' is less than LoadOptionsSize. Even if all Unicode-16
    119        1.1  cherry 	 * characters have the upper 8 bits non-zero, the terminating
    120        1.1  cherry 	 * null character will cause a one-off.
    121        1.1  cherry 	 * If the string is already in Unicode-16, we make a copy so that
    122        1.1  cherry 	 * we know we can always modify the string.
    123        1.1  cherry 	 */
    124        1.1  cherry 	if (img->LoadOptionsSize > 0 && img->LoadOptions != NULL) {
    125        1.1  cherry 		if (img->LoadOptionsSize == strlen(img->LoadOptions) + 1) {
    126        1.1  cherry 			args = alloc(img->LoadOptionsSize << 1);
    127        1.1  cherry 			for (argc = 0; argc < img->LoadOptionsSize; argc++)
    128        1.1  cherry 				args[argc] = ((char*)img->LoadOptions)[argc];
    129        1.1  cherry 		} else {
    130        1.1  cherry 			args = alloc(img->LoadOptionsSize);
    131        1.1  cherry 			memcpy(args, img->LoadOptions, img->LoadOptionsSize);
    132        1.1  cherry 		}
    133        1.1  cherry 	} else
    134        1.1  cherry 		args = NULL;
    135        1.1  cherry 
    136        1.1  cherry 	/*
    137        1.1  cherry 	 * Use a quick and dirty algorithm to build the argv vector. We
    138        1.1  cherry 	 * first count the number of words. Then, after allocating the
    139        1.1  cherry 	 * vector, we split the string up. We don't deal with quotes or
    140        1.1  cherry 	 * other more advanced shell features.
    141        1.1  cherry 	 * The EFI shell will pas the name of the image as the first
    142        1.1  cherry 	 * word in the argument list. This does not happen if we're
    143        1.1  cherry 	 * loaded by the boot manager. This is not so easy to figure
    144        1.1  cherry 	 * out though. The ParentHandle is not always NULL, because
    145        1.1  cherry 	 * there can be a function (=image) that will perform the task
    146        1.1  cherry 	 * for the boot manager.
    147        1.1  cherry 	 */
    148        1.1  cherry 	/* Part 1: Figure out if we need to add our program name. */
    149        1.1  cherry 	addprog = (args == NULL || img->ParentHandle == NULL ||
    150        1.1  cherry 	    img->FilePath == NULL) ? 1 : 0;
    151        1.1  cherry 	if (!addprog) {
    152        1.1  cherry 		addprog =
    153        1.1  cherry 		    (DevicePathType(img->FilePath) != MEDIA_DEVICE_PATH ||
    154        1.1  cherry 		     DevicePathSubType(img->FilePath) != MEDIA_FILEPATH_DP ||
    155        1.1  cherry 		     DevicePathNodeLength(img->FilePath) <=
    156        1.1  cherry 			sizeof(FILEPATH_DEVICE_PATH)) ? 1 : 0;
    157        1.1  cherry 		if (!addprog) {
    158        1.1  cherry 			/* XXX todo. */
    159        1.1  cherry 		}
    160        1.1  cherry 	}
    161        1.1  cherry 	/* Part 2: count words. */
    162        1.1  cherry 	argc = (addprog) ? 1 : 0;
    163        1.1  cherry 	argp = args;
    164        1.1  cherry 	while (argp != NULL && *argp != 0) {
    165        1.1  cherry 		argp = arg_skipsep(argp);
    166        1.1  cherry 		if (*argp == 0)
    167        1.1  cherry 			break;
    168        1.1  cherry 		argc++;
    169        1.1  cherry 		argp = arg_skipword(argp);
    170        1.1  cherry 	}
    171        1.1  cherry 	/* Part 3: build vector. */
    172        1.1  cherry 	argv = alloc((argc + 1) * sizeof(CHAR16*));
    173        1.1  cherry 	argc = 0;
    174        1.1  cherry 	if (addprog)
    175        1.1  cherry 		argv[argc++] = L"loader.efi";
    176        1.1  cherry 	argp = args;
    177        1.1  cherry 	while (argp != NULL && *argp != 0) {
    178        1.1  cherry 		argp = arg_skipsep(argp);
    179        1.1  cherry 		if (*argp == 0)
    180        1.1  cherry 			break;
    181        1.1  cherry 		argv[argc++] = argp;
    182        1.1  cherry 		argp = arg_skipword(argp);
    183        1.1  cherry 		/* Terminate the words. */
    184        1.1  cherry 		if (*argp != 0)
    185        1.1  cherry 			*argp++ = 0;
    186        1.1  cherry 	}
    187        1.1  cherry 	argv[argc] = NULL;
    188        1.1  cherry 
    189        1.1  cherry 	status = main(argc, argv);
    190        1.1  cherry 	efi_exit(status);
    191        1.1  cherry }
    192