Home | History | Annotate | Line # | Download | only in libefi
efi.c revision 1.3.90.1
      1  1.3.90.1    yamt /*	$NetBSD: efi.c,v 1.3.90.1 2013/01/23 00:05:51 yamt 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.90.1    yamt #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