3 * Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
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
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.
15 #include <Library/NetLib.h>
16 #include "BdsInternal.h"
20 IN OUT CHAR16
*CmdLine
,
30 // The command line must be at least one character long
31 ASSERT (MaxCmdLine
> 0);
33 // Ensure the last character of the buffer is the NULL character
34 CmdLine
[MaxCmdLine
- 1] = '\0';
38 // To prevent a buffer overflow, we only allow to enter (MaxCmdLine-1) characters
39 for (CmdLineIndex
= StrLen (CmdLine
); CmdLineIndex
< MaxCmdLine
; ) {
40 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &WaitIndex
);
41 ASSERT_EFI_ERROR (Status
);
43 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
44 ASSERT_EFI_ERROR (Status
);
46 // Unicode character is valid when Scancode is NUll
47 if (Key
.ScanCode
== SCAN_NULL
) {
48 // Scan code is NUll, hence read Unicode character
49 Char
= (CHAR8
)Key
.UnicodeChar
;
54 if ((Char
== CHAR_LINEFEED
) || (Char
== CHAR_CARRIAGE_RETURN
) || (Char
== 0x7f)) {
55 CmdLine
[CmdLineIndex
] = '\0';
59 } else if ((Key
.UnicodeChar
== L
'\b') || (Key
.ScanCode
== SCAN_LEFT
) || (Key
.ScanCode
== SCAN_DELETE
)){
60 if (CmdLineIndex
!= 0) {
64 } else if ((Key
.ScanCode
== SCAN_ESC
) || (Char
== 0x1B) || (Char
== 0x0)) {
65 return EFI_INVALID_PARAMETER
;
66 } else if (CmdLineIndex
< (MaxCmdLine
-1)) {
67 CmdLine
[CmdLineIndex
++] = Key
.UnicodeChar
;
68 Print (L
"%c", Key
.UnicodeChar
);
77 IN OUT CHAR16
*CmdLine
,
83 // For a new input just passed an empty string
86 Status
= EditHIInputStr (CmdLine
, MaxCmdLine
);
93 IN OUT CHAR8
*CmdLine
,
100 Str
= (CHAR16
*)AllocatePool (MaxCmdLine
* sizeof(CHAR16
));
101 AsciiStrToUnicodeStr (CmdLine
, Str
);
103 Status
= EditHIInputStr (Str
, MaxCmdLine
);
104 if (!EFI_ERROR(Status
)) {
105 UnicodeStrToAsciiStr (Str
, CmdLine
);
114 IN OUT CHAR8
*CmdLine
,
118 // For a new input just passed an empty string
121 return EditHIInputAscii (CmdLine
,MaxCmdLine
);
133 Status
= EditHIInputStr (CmdLine
, 255);
134 if (!EFI_ERROR(Status
)) {
135 *Integer
= StrDecimalToUintn (CmdLine
);
144 The function asks the user for an IPv4 address. If the input
145 string defines a valid IPv4 address, the four bytes of the
146 corresponding IPv4 address are extracted from the string and returned by
147 the function. As long as the user does not define a valid IP
148 address, he is asked for one. He can always escape by
151 @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if
152 and only if the returned value
153 is equal to EFI_SUCCESS
155 @retval EFI_SUCCESS Input completed
156 @retval EFI_ABORTED Editing aborted by the user
157 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to
162 OUT EFI_IP_ADDRESS
*OutIpAddr
170 Status
= EditHIInputStr (CmdLine
, 48);
171 if (EFI_ERROR (Status
)) {
175 Status
= NetLibStrToIp4 (CmdLine
, &OutIpAddr
->v4
);
176 if (Status
== EFI_INVALID_PARAMETER
) {
177 Print (L
"Invalid address\n");
187 The function displays as a string following the "%d.%d.%d.%d" format the
188 IPv4 address that is passed in and asks the user to modify it. If the
189 resulting string defines a valid IPv4 address, the four bytes of the
190 corresponding IPv4 address are extracted from the string and returned by
191 the function. As long as the user does not define a valid IP
192 address, he is asked for one. He can always escape by
195 @param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address
196 @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if
197 and only if the returned value
198 is equal to EFI_SUCCESS
200 @retval EFI_SUCCESS Update completed
201 @retval EFI_ABORTED Editing aborted by the user
202 @retval EFI_INVALID_PARAMETER The string returned by the user is
204 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to
209 IN EFI_IP_ADDRESS
*InIpAddr
,
210 OUT EFI_IP_ADDRESS
*OutIpAddr
218 CmdLine
, 48, L
"%d.%d.%d.%d",
219 InIpAddr
->v4
.Addr
[0], InIpAddr
->v4
.Addr
[1],
220 InIpAddr
->v4
.Addr
[2], InIpAddr
->v4
.Addr
[3]
223 Status
= EditHIInputStr (CmdLine
, 48);
224 if (EFI_ERROR (Status
)) {
227 Status
= NetLibStrToIp4 (CmdLine
, &OutIpAddr
->v4
);
228 if (Status
== EFI_INVALID_PARAMETER
) {
229 Print (L
"Invalid address\n");
241 CHAR16 CmdBoolean
[2];
246 Status
= GetHIInputStr (CmdBoolean
, 2);
247 if (EFI_ERROR(Status
)) {
249 } else if ((CmdBoolean
[0] == L
'y') || (CmdBoolean
[0] == L
'Y')) {
250 if (Value
) *Value
= TRUE
;
252 } else if ((CmdBoolean
[0] == L
'n') || (CmdBoolean
[0] == L
'N')) {
253 if (Value
) *Value
= FALSE
;
260 HasFilePathEfiExtension (
264 return (StrCmp (FilePath
+ (StrSize (FilePath
) / sizeof (CHAR16
)) - 5, L
".EFI") == 0) ||
265 (StrCmp (FilePath
+ (StrSize (FilePath
) / sizeof (CHAR16
)) - 5, L
".efi") == 0);
268 // Return the last non end-type Device Path Node from a Device Path
270 GetLastDevicePathNode (
271 IN EFI_DEVICE_PATH
* DevicePath
274 EFI_DEVICE_PATH
* PrevDevicePathNode
;
276 PrevDevicePathNode
= DevicePath
;
277 while (!IsDevicePathEndType (DevicePath
)) {
278 PrevDevicePathNode
= DevicePath
;
279 DevicePath
= NextDevicePathNode (DevicePath
);
282 return PrevDevicePathNode
;
286 GenerateDeviceDescriptionName (
287 IN EFI_HANDLE Handle
,
288 IN OUT CHAR16
* Description
292 EFI_COMPONENT_NAME_PROTOCOL
* ComponentName2Protocol
;
293 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
294 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
296 CHAR16
* DevicePathTxt
;
297 EFI_DEVICE_PATH
* DevicePathNode
;
299 ComponentName2Protocol
= NULL
;
300 Status
= gBS
->HandleProtocol (Handle
, &gEfiComponentName2ProtocolGuid
, (VOID
**)&ComponentName2Protocol
);
301 if (!EFI_ERROR(Status
)) {
302 //TODO: Fixme. we must find the best langague
303 Status
= ComponentName2Protocol
->GetDriverName (ComponentName2Protocol
,"en",&DriverName
);
304 if (!EFI_ERROR(Status
)) {
305 StrnCpy (Description
, DriverName
, BOOT_DEVICE_DESCRIPTION_MAX
);
309 if (EFI_ERROR(Status
)) {
310 // Use the lastest non null entry of the Device path as a description
311 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
312 if (EFI_ERROR(Status
)) {
316 // Convert the last non end-type Device Path Node in text for the description
317 DevicePathNode
= GetLastDevicePathNode (DevicePathProtocol
);
318 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
319 ASSERT_EFI_ERROR(Status
);
320 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (DevicePathNode
, TRUE
, TRUE
);
321 StrnCpy (Description
, DevicePathTxt
, BOOT_DEVICE_DESCRIPTION_MAX
);
322 FreePool (DevicePathTxt
);
330 IN CHAR16
* BootOption
334 BDS_LOAD_OPTION
*BdsLoadOption
;
336 Status
= BootOptionFromLoadOptionVariable (BootOption
, &BdsLoadOption
);
337 if (!EFI_ERROR(Status
)) {
338 Status
= BootOptionStart (BdsLoadOption
);
339 FreePool (BdsLoadOption
);
341 if (!EFI_ERROR(Status
)) {
342 Status
= EFI_SUCCESS
;
344 Status
= EFI_NOT_STARTED
;
347 Status
= EFI_NOT_FOUND
;
353 GetUnalignedDevicePathSize (
354 IN EFI_DEVICE_PATH
* DevicePath
358 EFI_DEVICE_PATH
* AlignedDevicePath
;
360 if ((UINTN
)DevicePath
& 0x1) {
361 AlignedDevicePath
= DuplicateDevicePath (DevicePath
);
362 Size
= GetDevicePathSize (AlignedDevicePath
);
363 FreePool (AlignedDevicePath
);
365 Size
= GetDevicePathSize (DevicePath
);
371 GetAlignedDevicePath (
372 IN EFI_DEVICE_PATH
* DevicePath
375 if ((UINTN
)DevicePath
& 0x1) {
376 return DuplicateDevicePath (DevicePath
);
387 // We do not support NULL pointer
388 ASSERT (String
!= NULL
);
390 if (*(CHAR16
*)String
< 0x100) {
391 //Note: We could get issue if the string is an empty Ascii string...
399 * Try to detect if the given string is an ASCII or Unicode string
401 * There are actually few limitation to this function but it is mainly to give
402 * a user friendly output.
405 * - it only supports unicode string that use ASCII character (< 0x100)
406 * - single character ASCII strings are interpreted as Unicode string
407 * - string cannot be longer than BOOT_DEVICE_OPTION_MAX characters and
408 * thus (BOOT_DEVICE_OPTION_MAX*2) bytes for an Unicode string and
409 * BOOT_DEVICE_OPTION_MAX bytes for an ASCII string.
411 * @param String Buffer that might contain a Unicode or Ascii string
412 * @param IsUnicode If not NULL this boolean value returns if the string is an
413 * ASCII or Unicode string.
418 OUT BOOLEAN
*IsUnicode
421 BOOLEAN UnicodeDetected
;
426 // We do not support NULL pointer
427 ASSERT (String
!= NULL
);
430 if (*(CHAR16
*)String
== L
'\0') {
435 } else if (*(CHAR16
*)String
== '\0') {
442 // Limitation: if the string is an ASCII single character string. This comparison
443 // will assume it is a Unicode string.
444 if (*(CHAR16
*)String
< 0x100) {
445 UnicodeDetected
= TRUE
;
447 UnicodeDetected
= FALSE
;
451 for (Index
= 0; Index
< BOOT_DEVICE_OPTION_MAX
; Index
++) {
452 if (UnicodeDetected
) {
453 Character
= ((CHAR16
*)String
)[Index
];
455 Character
= ((CHAR8
*)String
)[Index
];
458 if (Character
== '\0') {
462 } else if ((Character
< 0x20) || (Character
> 0x7f)) {
463 // We only support the range of printable ASCII character
469 if (IsPrintable
&& IsUnicode
) {
470 *IsUnicode
= UnicodeDetected
;