Home | History | Annotate | Line # | Download | only in libefi
efi.c revision 1.4.18.1
      1  1.4.18.1  pgoyette /*	$NetBSD: efi.c,v 1.4.18.1 2016/08/06 00:19:05 pgoyette 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.4    martin #include <lib/libkern/libkern.h>
     36       1.1    cherry 
     37  1.4.18.1  pgoyette #include <machine/efilib.h>
     38  1.4.18.1  pgoyette 
     39       1.1    cherry EFI_HANDLE		IH;
     40       1.1    cherry EFI_SYSTEM_TABLE	*ST;
     41       1.1    cherry EFI_BOOT_SERVICES	*BS;
     42       1.1    cherry EFI_RUNTIME_SERVICES	*RS;
     43       1.1    cherry 
     44       1.1    cherry static EFI_PHYSICAL_ADDRESS heap;
     45       1.1    cherry static UINTN heapsize;
     46       1.1    cherry 
     47       1.1    cherry static CHAR16 *
     48       1.1    cherry arg_skipsep(CHAR16 *argp)
     49       1.1    cherry {
     50       1.1    cherry 
     51       1.1    cherry 	while (*argp == ' ' || *argp == '\t')
     52       1.1    cherry 		argp++;
     53       1.1    cherry 	return (argp);
     54       1.1    cherry }
     55       1.1    cherry 
     56       1.1    cherry static CHAR16 *
     57       1.1    cherry arg_skipword(CHAR16 *argp)
     58       1.1    cherry {
     59       1.1    cherry 
     60       1.1    cherry 	while (*argp && *argp != ' ' && *argp != '\t')
     61       1.1    cherry 		argp++;
     62       1.1    cherry 	return (argp);
     63       1.1    cherry }
     64       1.1    cherry 
     65       1.1    cherry void *
     66       1.1    cherry efi_get_table(EFI_GUID *tbl)
     67       1.1    cherry {
     68       1.1    cherry 	EFI_GUID *id;
     69       1.1    cherry 	int i;
     70       1.1    cherry 
     71       1.1    cherry 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
     72       1.1    cherry 		id = &ST->ConfigurationTable[i].VendorGuid;
     73       1.1    cherry 		if (!memcmp(id, tbl, sizeof(EFI_GUID)))
     74       1.1    cherry 			return (ST->ConfigurationTable[i].VendorTable);
     75       1.1    cherry 	}
     76       1.1    cherry 	return (NULL);
     77       1.1    cherry }
     78       1.1    cherry 
     79       1.1    cherry void efi_exit(EFI_STATUS exit_code)
     80       1.1    cherry {
     81       1.1    cherry 
     82       1.1    cherry 	BS->FreePages(heap, EFI_SIZE_TO_PAGES(heapsize));
     83       1.1    cherry 	BS->Exit(IH, exit_code, 0, NULL);
     84       1.1    cherry }
     85       1.1    cherry 
     86       1.1    cherry void
     87       1.1    cherry efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
     88       1.1    cherry {
     89       1.1    cherry 	static EFI_GUID image_protocol = LOADED_IMAGE_PROTOCOL;
     90       1.1    cherry 	EFI_LOADED_IMAGE *img;
     91       1.1    cherry 	CHAR16 *argp, *args, **argv;
     92       1.1    cherry 	EFI_STATUS status;
     93       1.1    cherry 	int argc, addprog;
     94       1.1    cherry 
     95       1.1    cherry 	IH = image_handle;
     96       1.1    cherry 	ST = system_table;
     97       1.1    cherry 	BS = ST->BootServices;
     98       1.1    cherry 	RS = ST->RuntimeServices;
     99       1.1    cherry 
    100       1.1    cherry 	heapsize = 512*1024;
    101       1.1    cherry 	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
    102       1.1    cherry 	    EFI_SIZE_TO_PAGES(heapsize), &heap);
    103       1.1    cherry 	if (status != EFI_SUCCESS)
    104       1.1    cherry 		BS->Exit(IH, status, 0, NULL);
    105       1.1    cherry 
    106       1.1    cherry 	setheap((void *)heap, (void *)(heap + heapsize));
    107       1.1    cherry 
    108       1.1    cherry 	/* Use efi_exit() from here on... */
    109       1.1    cherry 
    110       1.1    cherry 	status = BS->HandleProtocol(IH, &image_protocol, (VOID**)&img);
    111       1.1    cherry 	if (status != EFI_SUCCESS)
    112       1.1    cherry 		efi_exit(status);
    113       1.1    cherry 
    114       1.1    cherry 	/*
    115       1.1    cherry 	 * Pre-process the (optional) load options. If the option string
    116       1.1    cherry 	 * is given as an ASCII string, we use a poor man's ASCII to
    117       1.1    cherry 	 * Unicode-16 translation. The size of the option string as given
    118       1.1    cherry 	 * to us includes the terminating null character. We assume the
    119       1.1    cherry 	 * string is an ASCII string if strlen() plus the terminating
    120       1.1    cherry 	 * '\0' is less than LoadOptionsSize. Even if all Unicode-16
    121       1.1    cherry 	 * characters have the upper 8 bits non-zero, the terminating
    122       1.1    cherry 	 * null character will cause a one-off.
    123       1.1    cherry 	 * If the string is already in Unicode-16, we make a copy so that
    124       1.1    cherry 	 * we know we can always modify the string.
    125       1.1    cherry 	 */
    126       1.1    cherry 	if (img->LoadOptionsSize > 0 && img->LoadOptions != NULL) {
    127       1.1    cherry 		if (img->LoadOptionsSize == strlen(img->LoadOptions) + 1) {
    128       1.1    cherry 			args = alloc(img->LoadOptionsSize << 1);
    129       1.1    cherry 			for (argc = 0; argc < img->LoadOptionsSize; argc++)
    130       1.1    cherry 				args[argc] = ((char*)img->LoadOptions)[argc];
    131       1.1    cherry 		} else {
    132       1.1    cherry 			args = alloc(img->LoadOptionsSize);
    133       1.1    cherry 			memcpy(args, img->LoadOptions, img->LoadOptionsSize);
    134       1.1    cherry 		}
    135       1.1    cherry 	} else
    136       1.1    cherry 		args = NULL;
    137       1.1    cherry 
    138       1.1    cherry 	/*
    139       1.1    cherry 	 * Use a quick and dirty algorithm to build the argv vector. We
    140       1.1    cherry 	 * first count the number of words. Then, after allocating the
    141       1.1    cherry 	 * vector, we split the string up. We don't deal with quotes or
    142       1.1    cherry 	 * other more advanced shell features.
    143       1.1    cherry 	 * The EFI shell will pas the name of the image as the first
    144       1.1    cherry 	 * word in the argument list. This does not happen if we're
    145       1.1    cherry 	 * loaded by the boot manager. This is not so easy to figure
    146       1.1    cherry 	 * out though. The ParentHandle is not always NULL, because
    147       1.1    cherry 	 * there can be a function (=image) that will perform the task
    148       1.1    cherry 	 * for the boot manager.
    149       1.1    cherry 	 */
    150       1.1    cherry 	/* Part 1: Figure out if we need to add our program name. */
    151       1.1    cherry 	addprog = (args == NULL || img->ParentHandle == NULL ||
    152       1.1    cherry 	    img->FilePath == NULL) ? 1 : 0;
    153       1.1    cherry 	if (!addprog) {
    154       1.1    cherry 		addprog =
    155       1.1    cherry 		    (DevicePathType(img->FilePath) != MEDIA_DEVICE_PATH ||
    156       1.1    cherry 		     DevicePathSubType(img->FilePath) != MEDIA_FILEPATH_DP ||
    157       1.1    cherry 		     DevicePathNodeLength(img->FilePath) <=
    158       1.1    cherry 			sizeof(FILEPATH_DEVICE_PATH)) ? 1 : 0;
    159       1.1    cherry 		if (!addprog) {
    160       1.1    cherry 			/* XXX todo. */
    161       1.1    cherry 		}
    162       1.1    cherry 	}
    163       1.1    cherry 	/* Part 2: count words. */
    164       1.1    cherry 	argc = (addprog) ? 1 : 0;
    165       1.1    cherry 	argp = args;
    166       1.1    cherry 	while (argp != NULL && *argp != 0) {
    167       1.1    cherry 		argp = arg_skipsep(argp);
    168       1.1    cherry 		if (*argp == 0)
    169       1.1    cherry 			break;
    170       1.1    cherry 		argc++;
    171       1.1    cherry 		argp = arg_skipword(argp);
    172       1.1    cherry 	}
    173       1.1    cherry 	/* Part 3: build vector. */
    174       1.1    cherry 	argv = alloc((argc + 1) * sizeof(CHAR16*));
    175       1.1    cherry 	argc = 0;
    176       1.1    cherry 	if (addprog)
    177       1.1    cherry 		argv[argc++] = L"loader.efi";
    178       1.1    cherry 	argp = args;
    179       1.1    cherry 	while (argp != NULL && *argp != 0) {
    180       1.1    cherry 		argp = arg_skipsep(argp);
    181       1.1    cherry 		if (*argp == 0)
    182       1.1    cherry 			break;
    183       1.1    cherry 		argv[argc++] = argp;
    184       1.1    cherry 		argp = arg_skipword(argp);
    185       1.1    cherry 		/* Terminate the words. */
    186       1.1    cherry 		if (*argp != 0)
    187       1.1    cherry 			*argp++ = 0;
    188       1.1    cherry 	}
    189       1.1    cherry 	argv[argc] = NULL;
    190       1.1    cherry 
    191       1.1    cherry 	status = main(argc, argv);
    192       1.1    cherry 	efi_exit(status);
    193       1.1    cherry }
    194