2 * Copyright (c) 2000 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $DragonFly: src/sys/boot/efi/libefi/libefi.c,v 1.1 2003/11/10 06:08:33 dillon Exp $
35 EFI_BOOT_SERVICES
*BS
;
36 EFI_RUNTIME_SERVICES
*RS
;
38 static EFI_PHYSICAL_ADDRESS heap
;
39 static UINTN heapsize
;
42 arg_skipsep(CHAR16
*argp
)
45 while (*argp
== ' ' || *argp
== '\t')
51 arg_skipword(CHAR16
*argp
)
54 while (*argp
&& *argp
!= ' ' && *argp
!= '\t')
60 efi_get_table(EFI_GUID
*tbl
)
65 for (i
= 0; i
< ST
->NumberOfTableEntries
; i
++) {
66 id
= &ST
->ConfigurationTable
[i
].VendorGuid
;
67 if (!memcmp(id
, tbl
, sizeof(EFI_GUID
)))
68 return (ST
->ConfigurationTable
[i
].VendorTable
);
73 void exit(EFI_STATUS exit_code
)
76 BS
->FreePages(heap
, EFI_SIZE_TO_PAGES(heapsize
));
77 BS
->Exit(IH
, exit_code
, 0, NULL
);
81 efi_main(EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
*system_table
)
83 static EFI_GUID image_protocol
= LOADED_IMAGE_PROTOCOL
;
84 EFI_LOADED_IMAGE
*img
;
85 CHAR16
*argp
, *args
, **argv
;
91 BS
= ST
->BootServices
;
92 RS
= ST
->RuntimeServices
;
95 status
= BS
->AllocatePages(AllocateAnyPages
, EfiLoaderData
,
96 EFI_SIZE_TO_PAGES(heapsize
), &heap
);
97 if (status
!= EFI_SUCCESS
)
98 BS
->Exit(IH
, status
, 0, NULL
);
100 setheap((void *)heap
, (void *)(heap
+ heapsize
));
102 /* Use exit() from here on... */
104 status
= BS
->HandleProtocol(IH
, &image_protocol
, (VOID
**)&img
);
105 if (status
!= EFI_SUCCESS
)
109 * Pre-process the (optional) load options. If the option string
110 * is given as an ASCII string, we use a poor man's ASCII to
111 * Unicode-16 translation. The size of the option string as given
112 * to us includes the terminating null character. We assume the
113 * string is an ASCII string if strlen() plus the terminating
114 * '\0' is less than LoadOptionsSize. Even if all Unicode-16
115 * characters have the upper 8 bits non-zero, the terminating
116 * null character will cause a one-off.
117 * If the string is already in Unicode-16, we make a copy so that
118 * we know we can always modify the string.
120 if (img
->LoadOptionsSize
> 0 && img
->LoadOptions
!= NULL
) {
121 if (img
->LoadOptionsSize
== strlen(img
->LoadOptions
) + 1) {
122 args
= malloc(img
->LoadOptionsSize
<< 1);
123 for (argc
= 0; argc
< img
->LoadOptionsSize
; argc
++)
124 args
[argc
] = ((char*)img
->LoadOptions
)[argc
];
126 args
= malloc(img
->LoadOptionsSize
);
127 memcpy(args
, img
->LoadOptions
, img
->LoadOptionsSize
);
133 * Use a quick and dirty algorithm to build the argv vector. We
134 * first count the number of words. Then, after allocating the
135 * vector, we split the string up. We don't deal with quotes or
136 * other more advanced shell features.
137 * The EFI shell will pas the name of the image as the first
138 * word in the argument list. This does not happen if we're
139 * loaded by the boot manager. This is not so easy to figure
140 * out though. The ParentHandle is not always NULL, because
141 * there can be a function (=image) that will perform the task
142 * for the boot manager.
144 /* Part 1: Figure out if we need to add our program name. */
145 addprog
= (args
== NULL
|| img
->ParentHandle
== NULL
||
146 img
->FilePath
== NULL
) ? 1 : 0;
149 (DevicePathType(img
->FilePath
) != MEDIA_DEVICE_PATH
||
150 DevicePathSubType(img
->FilePath
) != MEDIA_FILEPATH_DP
||
151 DevicePathNodeLength(img
->FilePath
) <=
152 sizeof(FILEPATH_DEVICE_PATH
)) ? 1 : 0;
157 /* Part 2: count words. */
158 argc
= (addprog
) ? 1 : 0;
160 while (argp
!= NULL
&& *argp
!= 0) {
161 argp
= arg_skipsep(argp
);
165 argp
= arg_skipword(argp
);
167 /* Part 3: build vector. */
168 argv
= malloc((argc
+ 1) * sizeof(CHAR16
*));
171 argv
[argc
++] = L
"loader.efi";
173 while (argp
!= NULL
&& *argp
!= 0) {
174 argp
= arg_skipsep(argp
);
178 argp
= arg_skipword(argp
);
179 /* Terminate the words. */
185 status
= main(argc
, argv
);