]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BdsHelper.c
ArmPkg/BdsLib: Add support to pass argument to a loaded EFI application
[mirror_edk2.git] / ArmPlatformPkg / Bds / BdsHelper.c
CommitLineData
ea46ebbe 1/** @file
2*
3* Copyright (c) 2011, ARM Limited. All rights reserved.
4*
5* This program and the accompanying materials
6* are licensed and made available under the terms and conditions of the BSD License
7* which accompanies this distribution. The full text of the license may be found at
8* http://opensource.org/licenses/bsd-license.php
9*
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12*
13**/
14
15#include "BdsInternal.h"
16
17EFI_STATUS
18GetEnvironmentVariable (
19 IN CONST CHAR16* VariableName,
20 IN VOID* DefaultValue,
21 IN OUT UINTN* Size,
22 OUT VOID** Value
23 )
24{
25 EFI_STATUS Status;
26 UINTN VariableSize;
27
28 // Try to get the variable size.
29 *Value = NULL;
30 VariableSize = 0;
31 Status = gRT->GetVariable ((CHAR16 *) VariableName, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
32 if (Status == EFI_NOT_FOUND) {
33 if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) {
34 // If the environment variable does not exist yet then set it with the default value
35 Status = gRT->SetVariable (
36 (CHAR16*)VariableName,
37 &gEfiGlobalVariableGuid,
38 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
39 *Size,
40 DefaultValue
41 );
42 *Value = DefaultValue;
43 } else {
44 return EFI_NOT_FOUND;
45 }
46 } else if (Status == EFI_BUFFER_TOO_SMALL) {
47 // Get the environment variable value
48 *Value = AllocatePool (VariableSize);
49 if (*Value == NULL) {
50 return EFI_OUT_OF_RESOURCES;
51 }
52
53 Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
54 if (EFI_ERROR (Status)) {
55 FreePool(*Value);
56 return EFI_INVALID_PARAMETER;
57 }
58
59 if (Size) {
60 *Size = VariableSize;
61 }
62 } else {
63 *Value = DefaultValue;
64 return Status;
65 }
66
67 return EFI_SUCCESS;
68}
69
70EFI_STATUS
74b96132 71EditHIInputStr (
72 IN OUT CHAR16 *CmdLine,
ea46ebbe 73 IN UINTN MaxCmdLine
74 )
75{
76 UINTN CmdLineIndex;
77 UINTN WaitIndex;
78 CHAR8 Char;
79 EFI_INPUT_KEY Key;
80 EFI_STATUS Status;
81
74b96132 82 Print (CmdLine);
ea46ebbe 83
74b96132 84 for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {
ea46ebbe 85 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);
86 ASSERT_EFI_ERROR (Status);
87
88 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
89 ASSERT_EFI_ERROR (Status);
90
91 // Unicode character is valid when Scancode is NUll
92 if (Key.ScanCode == SCAN_NULL) {
93 // Scan code is NUll, hence read Unicode character
94 Char = (CHAR8)Key.UnicodeChar;
95 } else {
96 Char = CHAR_NULL;
97 }
98
99 if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {
100 CmdLine[CmdLineIndex] = '\0';
74b96132 101 Print (L"\n\r");
ea46ebbe 102
103 return EFI_SUCCESS;
74b96132 104 } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
ea46ebbe 105 if (CmdLineIndex != 0) {
106 CmdLineIndex--;
74b96132 107 Print (L"\b \b");
ea46ebbe 108 }
109 } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {
110 return EFI_INVALID_PARAMETER;
111 } else {
74b96132 112 CmdLine[CmdLineIndex++] = Key.UnicodeChar;
113 Print (L"%c", Key.UnicodeChar);
ea46ebbe 114 }
115 }
116
117 return EFI_SUCCESS;
118}
119
74b96132 120EFI_STATUS
121GetHIInputStr (
122 IN OUT CHAR16 *CmdLine,
123 IN UINTN MaxCmdLine
124 )
125{
126 EFI_STATUS Status;
127
128 // For a new input just passed an empty string
129 CmdLine[0] = L'\0';
130
131 Status = EditHIInputStr (CmdLine, MaxCmdLine);
132
133 return Status;
134}
135
136EFI_STATUS
137EditHIInputAscii (
138 IN OUT CHAR8 *CmdLine,
139 IN UINTN MaxCmdLine
140 )
141{
142 CHAR16* Str;
143 EFI_STATUS Status;
144
145 Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));
146 AsciiStrToUnicodeStr (CmdLine, Str);
147
148 Status = EditHIInputStr (Str, MaxCmdLine);
149
150 if (!EFI_ERROR(Status)) {
151 UnicodeStrToAsciiStr (Str, CmdLine);
152 }
153 FreePool (Str);
154
155 return Status;
156}
157
ea46ebbe 158EFI_STATUS
159GetHIInputAscii (
160 IN OUT CHAR8 *CmdLine,
161 IN UINTN MaxCmdLine
162 )
163{
164 // For a new input just passed an empty string
165 CmdLine[0] = '\0';
166
167 return EditHIInputAscii (CmdLine,MaxCmdLine);
168}
169
170EFI_STATUS
171GetHIInputInteger (
172 OUT UINTN *Integer
173 )
174{
74b96132 175 CHAR16 CmdLine[255];
ea46ebbe 176 EFI_STATUS Status;
177
178 CmdLine[0] = '\0';
74b96132 179 Status = EditHIInputStr (CmdLine, 255);
ea46ebbe 180 if (!EFI_ERROR(Status)) {
74b96132 181 *Integer = StrDecimalToUintn (CmdLine);
ea46ebbe 182 }
183
184 return Status;
185}
186
187EFI_STATUS
188GetHIInputIP (
189 OUT EFI_IP_ADDRESS *Ip
190 )
191{
74b96132 192 CHAR16 CmdLine[255];
193 CHAR16 *Str;
ea46ebbe 194 EFI_STATUS Status;
195
196 CmdLine[0] = '\0';
74b96132 197 Status = EditHIInputStr (CmdLine,255);
ea46ebbe 198 if (!EFI_ERROR(Status)) {
199 Str = CmdLine;
74b96132 200 Ip->v4.Addr[0] = (UINT8)StrDecimalToUintn (Str);
ea46ebbe 201
74b96132 202 Str = StrStr (Str, L".");
ea46ebbe 203 if (Str == NULL) {
204 return EFI_INVALID_PARAMETER;
205 }
206
74b96132 207 Ip->v4.Addr[1] = (UINT8)StrDecimalToUintn (++Str);
ea46ebbe 208
74b96132 209 Str = StrStr (Str, L".");
ea46ebbe 210 if (Str == NULL) {
211 return EFI_INVALID_PARAMETER;
212 }
213
74b96132 214 Ip->v4.Addr[2] = (UINT8)StrDecimalToUintn (++Str);
ea46ebbe 215
74b96132 216 Str = StrStr (Str, L".");
ea46ebbe 217 if (Str == NULL) {
218 return EFI_INVALID_PARAMETER;
219 }
220
74b96132 221 Ip->v4.Addr[3] = (UINT8)StrDecimalToUintn (++Str);
ea46ebbe 222 }
223
224 return Status;
225}
226
227EFI_STATUS
228GetHIInputBoolean (
229 OUT BOOLEAN *Value
230 )
231{
74b96132 232 CHAR16 CmdBoolean[2];
ea46ebbe 233 EFI_STATUS Status;
234
235 while(1) {
236 Print (L"[y/n] ");
74b96132 237 Status = GetHIInputStr (CmdBoolean,2);
ea46ebbe 238 if (EFI_ERROR(Status)) {
239 return Status;
74b96132 240 } else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {
ea46ebbe 241 if (Value) *Value = TRUE;
242 return EFI_SUCCESS;
74b96132 243 } else if ((CmdBoolean[0] == L'n') || (CmdBoolean[0] == L'N')) {
ea46ebbe 244 if (Value) *Value = FALSE;
245 return EFI_SUCCESS;
246 }
247 }
248}
249
250BOOLEAN
251HasFilePathEfiExtension (
252 IN CHAR16* FilePath
253 )
254{
255 return (StrCmp (FilePath + (StrSize(FilePath)/sizeof(CHAR16)) - 5, L".efi") == 0);
256}
257
258// Return the last non end-type Device Path Node from a Device Path
259EFI_DEVICE_PATH*
260GetLastDevicePathNode (
261 IN EFI_DEVICE_PATH* DevicePath
262 )
263{
264 EFI_DEVICE_PATH* PrevDevicePathNode;
265
266 PrevDevicePathNode = DevicePath;
267 while (!IsDevicePathEndType (DevicePath)) {
268 PrevDevicePathNode = DevicePath;
269 DevicePath = NextDevicePathNode (DevicePath);
270 }
271
272 return PrevDevicePathNode;
273}
274
275EFI_STATUS
276GenerateDeviceDescriptionName (
277 IN EFI_HANDLE Handle,
278 IN OUT CHAR16* Description
279 )
280{
281 EFI_STATUS Status;
282 EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol;
283 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
284 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
285 CHAR16* DriverName;
286 CHAR16* DevicePathTxt;
287 EFI_DEVICE_PATH* DevicePathNode;
288
289 ComponentName2Protocol = NULL;
290 Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);
291 if (!EFI_ERROR(Status)) {
292 //TODO: Fixme. we must find the best langague
293 Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);
294 if (!EFI_ERROR(Status)) {
295 StrnCpy (Description,DriverName,BOOT_DEVICE_DESCRIPTION_MAX);
296 }
297 }
298
299 if (EFI_ERROR(Status)) {
300 // Use the lastest non null entry of the Device path as a description
301 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
302 if (EFI_ERROR(Status)) {
303 return Status;
304 }
305
306 // Convert the last non end-type Device Path Node in text for the description
307 DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);
308 Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
309 ASSERT_EFI_ERROR(Status);
310 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathNode,TRUE,TRUE);
311 StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);
312 FreePool (DevicePathTxt);
313 }
314
315 return EFI_SUCCESS;
316}
317
318EFI_STATUS
319BdsStartBootOption (
320 IN CHAR16* BootOption
321 )
322{
323 EFI_STATUS Status;
324 EFI_LOAD_OPTION EfiLoadOption;
325 UINTN EfiLoadOptionSize;
326 BDS_LOAD_OPTION *BdsLoadOption;
327
328 Status = GetEnvironmentVariable (BootOption, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
329 if (!EFI_ERROR(Status)) {
330 Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, &BdsLoadOption);
331 if (!EFI_ERROR(Status)) {
332 Status = BootOptionStart (BdsLoadOption);
333 FreePool (BdsLoadOption);
334 }
335
336 if (!EFI_ERROR(Status)) {
337 Status = EFI_SUCCESS;
338 } else {
339 Status = EFI_NOT_STARTED;
340 }
341 } else {
342 Status = EFI_NOT_FOUND;
343 }
344 return Status;
345}
2ccfb71e 346
347UINTN
348GetUnalignedDevicePathSize (
349 IN EFI_DEVICE_PATH* DevicePath
350 )
351{
352 UINTN Size;
353 EFI_DEVICE_PATH* AlignedDevicePath;
354
355 if ((UINTN)DevicePath & 0x1) {
356 AlignedDevicePath = DuplicateDevicePath (DevicePath);
357 Size = GetDevicePathSize (AlignedDevicePath);
358 FreePool (AlignedDevicePath);
359 } else {
360 Size = GetDevicePathSize (DevicePath);
361 }
362 return Size;
363}
364
365EFI_DEVICE_PATH*
366GetAlignedDevicePath (
367 IN EFI_DEVICE_PATH* DevicePath
368 )
369{
370 if ((UINTN)DevicePath & 0x1) {
371 return DuplicateDevicePath (DevicePath);
372 } else {
373 return DevicePath;
374 }
375}
376