1 /* $NetBSD: efi.c,v 1.2 2006/04/22 07:58:53 cherry Exp $ */
4 * Copyright (c) 2000 Doug Rabson
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 /* __FBSDID("$FreeBSD: src/sys/boot/efi/libefi/libefi.c,v 1.6 2003/04/03 21:36:29 obrien Exp $"); */
34 #include <lib/libsa/stand.h>
38 EFI_BOOT_SERVICES
*BS
;
39 EFI_RUNTIME_SERVICES
*RS
;
41 static EFI_PHYSICAL_ADDRESS heap
;
42 static UINTN heapsize
;
45 arg_skipsep(CHAR16
*argp
)
48 while (*argp
== ' ' || *argp
== '\t')
54 arg_skipword(CHAR16
*argp
)
57 while (*argp
&& *argp
!= ' ' && *argp
!= '\t')
63 efi_get_table(EFI_GUID
*tbl
)
68 for (i
= 0; i
< ST
->NumberOfTableEntries
; i
++) {
69 id
= &ST
->ConfigurationTable
[i
].VendorGuid
;
70 if (!memcmp(id
, tbl
, sizeof(EFI_GUID
)))
71 return (ST
->ConfigurationTable
[i
].VendorTable
);
76 void efi_exit(EFI_STATUS exit_code
)
79 BS
->FreePages(heap
, EFI_SIZE_TO_PAGES(heapsize
));
80 BS
->Exit(IH
, exit_code
, 0, NULL
);
84 efi_main(EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
*system_table
)
86 static EFI_GUID image_protocol
= LOADED_IMAGE_PROTOCOL
;
87 EFI_LOADED_IMAGE
*img
;
88 CHAR16
*argp
, *args
, **argv
;
94 BS
= ST
->BootServices
;
95 RS
= ST
->RuntimeServices
;
98 status
= BS
->AllocatePages(AllocateAnyPages
, EfiLoaderData
,
99 EFI_SIZE_TO_PAGES(heapsize
), &heap
);
100 if (status
!= EFI_SUCCESS
)
101 BS
->Exit(IH
, status
, 0, NULL
);
103 setheap((void *)heap
, (void *)(heap
+ heapsize
));
105 /* Use efi_exit() from here on... */
107 status
= BS
->HandleProtocol(IH
, &image_protocol
, (VOID
**)&img
);
108 if (status
!= EFI_SUCCESS
)
112 * Pre-process the (optional) load options. If the option string
113 * is given as an ASCII string, we use a poor man's ASCII to
114 * Unicode-16 translation. The size of the option string as given
115 * to us includes the terminating null character. We assume the
116 * string is an ASCII string if strlen() plus the terminating
117 * '\0' is less than LoadOptionsSize. Even if all Unicode-16
118 * characters have the upper 8 bits non-zero, the terminating
119 * null character will cause a one-off.
120 * If the string is already in Unicode-16, we make a copy so that
121 * we know we can always modify the string.
123 if (img
->LoadOptionsSize
> 0 && img
->LoadOptions
!= NULL
) {
124 if (img
->LoadOptionsSize
== strlen(img
->LoadOptions
) + 1) {
125 args
= alloc(img
->LoadOptionsSize
<< 1);
126 for (argc
= 0; argc
< img
->LoadOptionsSize
; argc
++)
127 args
[argc
] = ((char*)img
->LoadOptions
)[argc
];
129 args
= alloc(img
->LoadOptionsSize
);
130 memcpy(args
, img
->LoadOptions
, img
->LoadOptionsSize
);
136 * Use a quick and dirty algorithm to build the argv vector. We
137 * first count the number of words. Then, after allocating the
138 * vector, we split the string up. We don't deal with quotes or
139 * other more advanced shell features.
140 * The EFI shell will pas the name of the image as the first
141 * word in the argument list. This does not happen if we're
142 * loaded by the boot manager. This is not so easy to figure
143 * out though. The ParentHandle is not always NULL, because
144 * there can be a function (=image) that will perform the task
145 * for the boot manager.
147 /* Part 1: Figure out if we need to add our program name. */
148 addprog
= (args
== NULL
|| img
->ParentHandle
== NULL
||
149 img
->FilePath
== NULL
) ? 1 : 0;
152 (DevicePathType(img
->FilePath
) != MEDIA_DEVICE_PATH
||
153 DevicePathSubType(img
->FilePath
) != MEDIA_FILEPATH_DP
||
154 DevicePathNodeLength(img
->FilePath
) <=
155 sizeof(FILEPATH_DEVICE_PATH
)) ? 1 : 0;
160 /* Part 2: count words. */
161 argc
= (addprog
) ? 1 : 0;
163 while (argp
!= NULL
&& *argp
!= 0) {
164 argp
= arg_skipsep(argp
);
168 argp
= arg_skipword(argp
);
170 /* Part 3: build vector. */
171 argv
= alloc((argc
+ 1) * sizeof(CHAR16
*));
174 argv
[argc
++] = L
"loader.efi";
176 while (argp
!= NULL
&& *argp
!= 0) {
177 argp
= arg_skipsep(argp
);
181 argp
= arg_skipword(argp
);
182 /* Terminate the words. */
188 status
= main(argc
, argv
);