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
149 @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if
150 and only if the returned value
151 is equal to EFI_SUCCESS
153 @retval EFI_SUCCESS Input completed
154 @retval EFI_ABORTED Editing aborted by the user
155 @retval EFI_INVALID_PARAMETER The string returned by the user is
157 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to
162 OUT EFI_IP_ADDRESS
*OutIpAddr
169 Status
= EditHIInputStr (CmdLine
, 48);
170 if (EFI_ERROR (Status
)) {
174 Status
= NetLibStrToIp4 (CmdLine
, &OutIpAddr
->v4
);
182 The function displays as a string following the "%d.%d.%d.%d" format the
183 IPv4 address that is passed in and asks the user to modify it. If the
184 resulting string defines a valid IPv4 address, the four bytes of the
185 corresponding IPv4 address are extracted from the string and returned by
188 @param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address
189 @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if
190 and only if the returned value
191 is equal to EFI_SUCCESS
193 @retval EFI_SUCCESS Update completed
194 @retval EFI_ABORTED Editing aborted by the user
195 @retval EFI_INVALID_PARAMETER The string returned by the user is
197 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to
202 IN EFI_IP_ADDRESS
*InIpAddr
,
203 OUT EFI_IP_ADDRESS
*OutIpAddr
210 CmdLine
, 48, L
"%d.%d.%d.%d",
211 InIpAddr
->v4
.Addr
[0], InIpAddr
->v4
.Addr
[1],
212 InIpAddr
->v4
.Addr
[2], InIpAddr
->v4
.Addr
[3]
215 Status
= EditHIInputStr (CmdLine
, 48);
216 if (EFI_ERROR (Status
)) {
220 Status
= NetLibStrToIp4 (CmdLine
, &OutIpAddr
->v4
);
230 CHAR16 CmdBoolean
[2];
235 Status
= GetHIInputStr (CmdBoolean
, 2);
236 if (EFI_ERROR(Status
)) {
238 } else if ((CmdBoolean
[0] == L
'y') || (CmdBoolean
[0] == L
'Y')) {
239 if (Value
) *Value
= TRUE
;
241 } else if ((CmdBoolean
[0] == L
'n') || (CmdBoolean
[0] == L
'N')) {
242 if (Value
) *Value
= FALSE
;
249 HasFilePathEfiExtension (
253 return (StrCmp (FilePath
+ (StrSize (FilePath
) / sizeof (CHAR16
)) - 5, L
".EFI") == 0) ||
254 (StrCmp (FilePath
+ (StrSize (FilePath
) / sizeof (CHAR16
)) - 5, L
".efi") == 0);
257 // Return the last non end-type Device Path Node from a Device Path
259 GetLastDevicePathNode (
260 IN EFI_DEVICE_PATH
* DevicePath
263 EFI_DEVICE_PATH
* PrevDevicePathNode
;
265 PrevDevicePathNode
= DevicePath
;
266 while (!IsDevicePathEndType (DevicePath
)) {
267 PrevDevicePathNode
= DevicePath
;
268 DevicePath
= NextDevicePathNode (DevicePath
);
271 return PrevDevicePathNode
;
275 GenerateDeviceDescriptionName (
276 IN EFI_HANDLE Handle
,
277 IN OUT CHAR16
* Description
281 EFI_COMPONENT_NAME_PROTOCOL
* ComponentName2Protocol
;
282 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
283 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
285 CHAR16
* DevicePathTxt
;
286 EFI_DEVICE_PATH
* DevicePathNode
;
288 ComponentName2Protocol
= NULL
;
289 Status
= gBS
->HandleProtocol (Handle
, &gEfiComponentName2ProtocolGuid
, (VOID
**)&ComponentName2Protocol
);
290 if (!EFI_ERROR(Status
)) {
291 //TODO: Fixme. we must find the best langague
292 Status
= ComponentName2Protocol
->GetDriverName (ComponentName2Protocol
,"en",&DriverName
);
293 if (!EFI_ERROR(Status
)) {
294 StrnCpy (Description
, DriverName
, BOOT_DEVICE_DESCRIPTION_MAX
);
298 if (EFI_ERROR(Status
)) {
299 // Use the lastest non null entry of the Device path as a description
300 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
301 if (EFI_ERROR(Status
)) {
305 // Convert the last non end-type Device Path Node in text for the description
306 DevicePathNode
= GetLastDevicePathNode (DevicePathProtocol
);
307 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
308 ASSERT_EFI_ERROR(Status
);
309 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (DevicePathNode
, TRUE
, TRUE
);
310 StrnCpy (Description
, DevicePathTxt
, BOOT_DEVICE_DESCRIPTION_MAX
);
311 FreePool (DevicePathTxt
);
319 IN CHAR16
* BootOption
323 BDS_LOAD_OPTION
*BdsLoadOption
;
325 Status
= BootOptionFromLoadOptionVariable (BootOption
, &BdsLoadOption
);
326 if (!EFI_ERROR(Status
)) {
327 Status
= BootOptionStart (BdsLoadOption
);
328 FreePool (BdsLoadOption
);
330 if (!EFI_ERROR(Status
)) {
331 Status
= EFI_SUCCESS
;
333 Status
= EFI_NOT_STARTED
;
336 Status
= EFI_NOT_FOUND
;
342 GetUnalignedDevicePathSize (
343 IN EFI_DEVICE_PATH
* DevicePath
347 EFI_DEVICE_PATH
* AlignedDevicePath
;
349 if ((UINTN
)DevicePath
& 0x1) {
350 AlignedDevicePath
= DuplicateDevicePath (DevicePath
);
351 Size
= GetDevicePathSize (AlignedDevicePath
);
352 FreePool (AlignedDevicePath
);
354 Size
= GetDevicePathSize (DevicePath
);
360 GetAlignedDevicePath (
361 IN EFI_DEVICE_PATH
* DevicePath
364 if ((UINTN
)DevicePath
& 0x1) {
365 return DuplicateDevicePath (DevicePath
);
376 // We do not support NULL pointer
377 ASSERT (String
!= NULL
);
379 if (*(CHAR16
*)String
< 0x100) {
380 //Note: We could get issue if the string is an empty Ascii string...
388 * Try to detect if the given string is an ASCII or Unicode string
390 * There are actually few limitation to this function but it is mainly to give
391 * a user friendly output.
394 * - it only supports unicode string that use ASCII character (< 0x100)
395 * - single character ASCII strings are interpreted as Unicode string
396 * - string cannot be longer than 2 x BOOT_DEVICE_OPTION_MAX (600 bytes)
398 * @param String Buffer that might contain a Unicode or Ascii string
399 * @param IsUnicode If not NULL this boolean value returns if the string is an
400 * ASCII or Unicode string.
405 OUT BOOLEAN
*IsUnicode
408 BOOLEAN UnicodeDetected
;
413 // We do not support NULL pointer
414 ASSERT (String
!= NULL
);
417 if (*(CHAR16
*)String
== L
'\0') {
422 } else if (*(CHAR16
*)String
== '\0') {
429 // Limitation: if the string is an ASCII single character string. This comparison
430 // will assume it is a Unicode string.
431 if (*(CHAR16
*)String
< 0x100) {
432 UnicodeDetected
= TRUE
;
434 UnicodeDetected
= FALSE
;
438 for (Index
= 0; Index
< BOOT_DEVICE_OPTION_MAX
* 2; Index
++) {
439 if (UnicodeDetected
) {
440 Character
= ((CHAR16
*)String
)[Index
];
442 Character
= ((CHAR8
*)String
)[Index
];
445 if (Character
== '\0') {
449 } else if ((Character
< 0x20) || (Character
> 0x7f)) {
450 // We only support the range of printable ASCII character
456 if (IsPrintable
&& IsUnicode
) {
457 *IsUnicode
= UnicodeDetected
;