]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BdsHelper.c
ArmPlatformPkg/Bds: Got rid of RequestBootType argument
[mirror_edk2.git] / ArmPlatformPkg / Bds / BdsHelper.c
CommitLineData
1e57a462 1/** @file\r
2*\r
135b09a2 3* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.\r
1e57a462 4* \r
5* This program and the accompanying materials \r
6* are licensed and made available under the terms and conditions of the BSD License \r
7* which accompanies this distribution. The full text of the license may be found at \r
8* http://opensource.org/licenses/bsd-license.php \r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12*\r
13**/\r
14\r
8bf4ad44 15#include <Library/NetLib.h>\r
1e57a462 16#include "BdsInternal.h"\r
17\r
18EFI_STATUS\r
19EditHIInputStr (\r
20 IN OUT CHAR16 *CmdLine,\r
21 IN UINTN MaxCmdLine\r
22 )\r
23{\r
24 UINTN CmdLineIndex;\r
25 UINTN WaitIndex;\r
26 CHAR8 Char;\r
27 EFI_INPUT_KEY Key;\r
28 EFI_STATUS Status;\r
29\r
7ff3b949
RH
30 // The command line must be at least one character long\r
31 ASSERT (MaxCmdLine > 0);\r
32\r
7ff3b949
RH
33 // Ensure the last character of the buffer is the NULL character\r
34 CmdLine[MaxCmdLine - 1] = '\0';\r
35\r
40761653
OM
36 Print (CmdLine);\r
37\r
7ff3b949 38 // To prevent a buffer overflow, we only allow to enter (MaxCmdLine-1) characters\r
7ffa9c61 39 for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {
1e57a462 40 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
41 ASSERT_EFI_ERROR (Status);\r
42\r
43 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
44 ASSERT_EFI_ERROR (Status);\r
45\r
46 // Unicode character is valid when Scancode is NUll\r
47 if (Key.ScanCode == SCAN_NULL) {\r
48 // Scan code is NUll, hence read Unicode character\r
49 Char = (CHAR8)Key.UnicodeChar;\r
50 } else {\r
51 Char = CHAR_NULL;\r
52 }\r
53\r
54 if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {\r
55 CmdLine[CmdLineIndex] = '\0';\r
e30acb47 56 Print (L"\r\n");\r
1e57a462 57\r
58 return EFI_SUCCESS;\r
59 } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){\r
60 if (CmdLineIndex != 0) {\r
61 CmdLineIndex--;\r
62 Print (L"\b \b");\r
63 }\r
64 } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {\r
65 return EFI_INVALID_PARAMETER;\r
7ffa9c61 66 } else if (CmdLineIndex < (MaxCmdLine-1)) {
1e57a462 67 CmdLine[CmdLineIndex++] = Key.UnicodeChar;\r
68 Print (L"%c", Key.UnicodeChar);\r
69 }\r
70 }\r
71\r
72 return EFI_SUCCESS;\r
73}\r
74\r
75EFI_STATUS\r
76GetHIInputStr (\r
77 IN OUT CHAR16 *CmdLine,\r
78 IN UINTN MaxCmdLine\r
79 )\r
80{\r
81 EFI_STATUS Status;\r
82\r
83 // For a new input just passed an empty string\r
84 CmdLine[0] = L'\0';\r
85\r
86 Status = EditHIInputStr (CmdLine, MaxCmdLine);\r
87\r
88 return Status;\r
89}\r
90\r
91EFI_STATUS\r
92EditHIInputAscii (\r
93 IN OUT CHAR8 *CmdLine,\r
94 IN UINTN MaxCmdLine\r
95 )\r
96{\r
97 CHAR16* Str;\r
98 EFI_STATUS Status;\r
99\r
100 Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));\r
101 AsciiStrToUnicodeStr (CmdLine, Str);\r
102\r
103 Status = EditHIInputStr (Str, MaxCmdLine);\r
104 if (!EFI_ERROR(Status)) {\r
105 UnicodeStrToAsciiStr (Str, CmdLine);\r
106 }\r
107 FreePool (Str);\r
108\r
109 return Status;\r
110}\r
111\r
112EFI_STATUS\r
113GetHIInputAscii (\r
114 IN OUT CHAR8 *CmdLine,\r
115 IN UINTN MaxCmdLine\r
116 )\r
117{\r
118 // For a new input just passed an empty string\r
119 CmdLine[0] = '\0';\r
120\r
121 return EditHIInputAscii (CmdLine,MaxCmdLine);\r
122}\r
123\r
124EFI_STATUS\r
125GetHIInputInteger (\r
126 OUT UINTN *Integer\r
127 )\r
128{\r
129 CHAR16 CmdLine[255];\r
130 EFI_STATUS Status;\r
131\r
132 CmdLine[0] = '\0';\r
133 Status = EditHIInputStr (CmdLine, 255);\r
134 if (!EFI_ERROR(Status)) {\r
135 *Integer = StrDecimalToUintn (CmdLine);\r
136 }\r
137\r
138 return Status;\r
139}\r
140\r
8bf4ad44
RC
141/**\r
142 Get an IPv4 address\r
143\r
144 The function asks the user for an IPv4 address. If the input\r
145 string defines a valid IPv4 address, the four bytes of the\r
146 corresponding IPv4 address are extracted from the string and returned by\r
147 the function.\r
148\r
149 @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if\r
150 and only if the returned value\r
151 is equal to EFI_SUCCESS\r
152
153 @retval EFI_SUCCESS Input completed\r
154 @retval EFI_ABORTED Editing aborted by the user\r
155 @retval EFI_INVALID_PARAMETER The string returned by the user is\r
156 mal-formated\r
157 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to\r
158 lack of resource\r
159**/\r
1e57a462 160EFI_STATUS\r
161GetHIInputIP (\r
8bf4ad44 162 OUT EFI_IP_ADDRESS *OutIpAddr\r
1e57a462 163 )\r
164{\r
1e57a462 165 EFI_STATUS Status;\r
8bf4ad44 166 CHAR16 CmdLine[48];\r
1e57a462 167\r
168 CmdLine[0] = '\0';\r
8bf4ad44
RC
169 Status = EditHIInputStr (CmdLine, 48);\r
170 if (EFI_ERROR (Status)) {\r
171 return EFI_ABORTED;\r
172 }\r
1e57a462 173\r
8bf4ad44 174 Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);\r
1e57a462 175\r
8bf4ad44
RC
176 return Status;\r
177}\r
1e57a462 178\r
8bf4ad44
RC
179/**\r
180 Edit an IPv4 address\r
181\r
182 The function displays as a string following the "%d.%d.%d.%d" format the\r
183 IPv4 address that is passed in and asks the user to modify it. If the\r
184 resulting string defines a valid IPv4 address, the four bytes of the\r
185 corresponding IPv4 address are extracted from the string and returned by\r
186 the function.\r
187\r
188 @param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address\r
189 @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if\r
190 and only if the returned value\r
191 is equal to EFI_SUCCESS\r
192
193 @retval EFI_SUCCESS Update completed\r
194 @retval EFI_ABORTED Editing aborted by the user\r
195 @retval EFI_INVALID_PARAMETER The string returned by the user is\r
196 mal-formated\r
197 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to\r
198 lack of resource\r
199**/\r
200EFI_STATUS\r
201EditHIInputIP (\r
202 IN EFI_IP_ADDRESS *InIpAddr,\r
203 OUT EFI_IP_ADDRESS *OutIpAddr\r
204 )\r
205{\r
206 EFI_STATUS Status;\r
207 CHAR16 CmdLine[48];\r
1e57a462 208\r
8bf4ad44
RC
209 UnicodeSPrint (
210 CmdLine, 48, L"%d.%d.%d.%d",\r
211 InIpAddr->v4.Addr[0], InIpAddr->v4.Addr[1],\r
212 InIpAddr->v4.Addr[2], InIpAddr->v4.Addr[3]\r
213 );\r
1e57a462 214\r
8bf4ad44
RC
215 Status = EditHIInputStr (CmdLine, 48);\r
216 if (EFI_ERROR (Status)) {\r
217 return EFI_ABORTED;\r
1e57a462 218 }\r
219\r
8bf4ad44
RC
220 Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);\r
221\r
1e57a462 222 return Status;\r
223}\r
224\r
225EFI_STATUS\r
226GetHIInputBoolean (\r
227 OUT BOOLEAN *Value\r
228 )\r
229{\r
230 CHAR16 CmdBoolean[2];\r
231 EFI_STATUS Status;\r
232\r
233 while(1) {\r
234 Print (L"[y/n] ");\r
7ffa9c61 235 Status = GetHIInputStr (CmdBoolean, 2);
1e57a462 236 if (EFI_ERROR(Status)) {\r
237 return Status;\r
238 } else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {\r
239 if (Value) *Value = TRUE;\r
240 return EFI_SUCCESS;\r
241 } else if ((CmdBoolean[0] == L'n') || (CmdBoolean[0] == L'N')) {\r
242 if (Value) *Value = FALSE;\r
243 return EFI_SUCCESS;\r
244 }\r
245 }\r
246}\r
247\r
248BOOLEAN\r
249HasFilePathEfiExtension (\r
250 IN CHAR16* FilePath\r
251 )\r
252{\r
0d304bef
LL
253 return (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".EFI") == 0) ||\r
254 (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".efi") == 0);\r
1e57a462 255}\r
256\r
257// Return the last non end-type Device Path Node from a Device Path\r
258EFI_DEVICE_PATH*\r
259GetLastDevicePathNode (\r
260 IN EFI_DEVICE_PATH* DevicePath\r
261 )\r
262{\r
263 EFI_DEVICE_PATH* PrevDevicePathNode;\r
264\r
265 PrevDevicePathNode = DevicePath;\r
266 while (!IsDevicePathEndType (DevicePath)) {\r
267 PrevDevicePathNode = DevicePath;\r
268 DevicePath = NextDevicePathNode (DevicePath);\r
269 }\r
270\r
271 return PrevDevicePathNode;\r
272}\r
273\r
274EFI_STATUS\r
275GenerateDeviceDescriptionName (\r
276 IN EFI_HANDLE Handle,\r
277 IN OUT CHAR16* Description\r
278 )\r
279{\r
280 EFI_STATUS Status;\r
281 EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol;\r
282 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
283 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
284 CHAR16* DriverName;\r
285 CHAR16* DevicePathTxt;\r
286 EFI_DEVICE_PATH* DevicePathNode;\r
287\r
288 ComponentName2Protocol = NULL;\r
289 Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);\r
290 if (!EFI_ERROR(Status)) {\r
291 //TODO: Fixme. we must find the best langague\r
292 Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);\r
293 if (!EFI_ERROR(Status)) {\r
294 StrnCpy (Description, DriverName, BOOT_DEVICE_DESCRIPTION_MAX);\r
295 }\r
296 }\r
297\r
298 if (EFI_ERROR(Status)) {\r
299 // Use the lastest non null entry of the Device path as a description\r
300 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
301 if (EFI_ERROR(Status)) {\r
302 return Status;\r
303 }\r
304\r
305 // Convert the last non end-type Device Path Node in text for the description\r
306 DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);\r
307 Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
308 ASSERT_EFI_ERROR(Status);\r
309 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePathNode, TRUE, TRUE);\r
310 StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);\r
311 FreePool (DevicePathTxt);\r
312 }\r
313\r
314 return EFI_SUCCESS;\r
315}\r
316\r
317EFI_STATUS\r
318BdsStartBootOption (\r
319 IN CHAR16* BootOption\r
320 )\r
321{\r
322 EFI_STATUS Status;\r
323 BDS_LOAD_OPTION *BdsLoadOption;\r
324\r
325 Status = BootOptionFromLoadOptionVariable (BootOption, &BdsLoadOption);\r
326 if (!EFI_ERROR(Status)) {\r
327 Status = BootOptionStart (BdsLoadOption);\r
328 FreePool (BdsLoadOption);\r
329\r
330 if (!EFI_ERROR(Status)) {\r
331 Status = EFI_SUCCESS;\r
332 } else {\r
333 Status = EFI_NOT_STARTED;\r
334 }\r
335 } else {\r
336 Status = EFI_NOT_FOUND;\r
337 }\r
338 return Status;\r
339}\r
340\r
341UINTN\r
342GetUnalignedDevicePathSize (\r
343 IN EFI_DEVICE_PATH* DevicePath\r
344 )\r
345{\r
346 UINTN Size;\r
347 EFI_DEVICE_PATH* AlignedDevicePath;\r
348\r
349 if ((UINTN)DevicePath & 0x1) {\r
350 AlignedDevicePath = DuplicateDevicePath (DevicePath);\r
351 Size = GetDevicePathSize (AlignedDevicePath);\r
352 FreePool (AlignedDevicePath);\r
353 } else {\r
354 Size = GetDevicePathSize (DevicePath);\r
355 }\r
356 return Size;\r
357}\r
358\r
359EFI_DEVICE_PATH*\r
360GetAlignedDevicePath (\r
361 IN EFI_DEVICE_PATH* DevicePath\r
362 )\r
363{\r
364 if ((UINTN)DevicePath & 0x1) {\r
365 return DuplicateDevicePath (DevicePath);\r
366 } else {\r
367 return DevicePath;\r
368 }\r
369}\r
370\r
9fc9aa46
OM
371BOOLEAN\r
372IsUnicodeString (\r
373 IN VOID* String\r
374 )\r
375{\r
376 // We do not support NULL pointer\r
377 ASSERT (String != NULL);\r
378\r
379 if (*(CHAR16*)String < 0x100) {\r
380 //Note: We could get issue if the string is an empty Ascii string...\r
381 return TRUE;\r
382 } else {\r
383 return FALSE;\r
384 }\r
385}\r
135b09a2
OM
386\r
387/*\r
388 * Try to detect if the given string is an ASCII or Unicode string\r
389 *\r
390 * There are actually few limitation to this function but it is mainly to give\r
391 * a user friendly output.\r
392 *\r
393 * Some limitations:\r
394 * - it only supports unicode string that use ASCII character (< 0x100)\r
395 * - single character ASCII strings are interpreted as Unicode string\r
396 * - string cannot be longer than 2 x BOOT_DEVICE_OPTION_MAX (600 bytes)\r
397 *\r
398 * @param String Buffer that might contain a Unicode or Ascii string\r
399 * @param IsUnicode If not NULL this boolean value returns if the string is an\r
400 * ASCII or Unicode string.\r
401 */\r
402BOOLEAN\r
403IsPrintableString (\r
404 IN VOID* String,\r
405 OUT BOOLEAN *IsUnicode\r
406 )\r
407{\r
408 BOOLEAN UnicodeDetected;\r
409 BOOLEAN IsPrintable;\r
410 UINTN Index;\r
411 CHAR16 Character;\r
412\r
413 // We do not support NULL pointer\r
414 ASSERT (String != NULL);\r
415\r
416 // Test empty string\r
417 if (*(CHAR16*)String == L'\0') {\r
418 if (IsUnicode) {\r
419 *IsUnicode = TRUE;\r
420 }\r
421 return TRUE;\r
422 } else if (*(CHAR16*)String == '\0') {\r
423 if (IsUnicode) {\r
424 *IsUnicode = FALSE;\r
425 }\r
426 return TRUE;\r
427 }\r
428\r
429 // Limitation: if the string is an ASCII single character string. This comparison\r
430 // will assume it is a Unicode string.\r
431 if (*(CHAR16*)String < 0x100) {\r
432 UnicodeDetected = TRUE;\r
433 } else {\r
434 UnicodeDetected = FALSE;\r
435 }\r
436\r
437 IsPrintable = FALSE;\r
438 for (Index = 0; Index < BOOT_DEVICE_OPTION_MAX * 2; Index++) {\r
439 if (UnicodeDetected) {\r
440 Character = ((CHAR16*)String)[Index];\r
441 } else {\r
442 Character = ((CHAR8*)String)[Index];\r
443 }\r
444\r
445 if (Character == '\0') {\r
446 // End of the string\r
447 IsPrintable = TRUE;\r
448 break;\r
449 } else if ((Character < 0x20) || (Character > 0x7f)) {\r
450 // We only support the range of printable ASCII character\r
451 IsPrintable = FALSE;\r
452 break;\r
453 }\r
454 }\r
455\r
456 if (IsPrintable && IsUnicode) {\r
457 *IsUnicode = UnicodeDetected;\r
458 }\r
459\r
460 return IsPrintable;\r
461}\r