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
;
259 // Return the last non end-type Device Path Node from a Device Path
261 GetLastDevicePathNode (
262 IN EFI_DEVICE_PATH
* DevicePath
265 EFI_DEVICE_PATH
* PrevDevicePathNode
;
267 PrevDevicePathNode
= DevicePath
;
268 while (!IsDevicePathEndType (DevicePath
)) {
269 PrevDevicePathNode
= DevicePath
;
270 DevicePath
= NextDevicePathNode (DevicePath
);
273 return PrevDevicePathNode
;
277 GenerateDeviceDescriptionName (
278 IN EFI_HANDLE Handle
,
279 IN OUT CHAR16
* Description
283 EFI_COMPONENT_NAME_PROTOCOL
* ComponentName2Protocol
;
284 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
285 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
287 CHAR16
* DevicePathTxt
;
288 EFI_DEVICE_PATH
* DevicePathNode
;
290 ComponentName2Protocol
= NULL
;
291 Status
= gBS
->HandleProtocol (Handle
, &gEfiComponentName2ProtocolGuid
, (VOID
**)&ComponentName2Protocol
);
292 if (!EFI_ERROR(Status
)) {
293 //TODO: Fixme. we must find the best langague
294 Status
= ComponentName2Protocol
->GetDriverName (ComponentName2Protocol
,"en",&DriverName
);
295 if (!EFI_ERROR(Status
)) {
296 StrnCpy (Description
, DriverName
, BOOT_DEVICE_DESCRIPTION_MAX
);
300 if (EFI_ERROR(Status
)) {
301 // Use the lastest non null entry of the Device path as a description
302 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
303 if (EFI_ERROR(Status
)) {
307 // Convert the last non end-type Device Path Node in text for the description
308 DevicePathNode
= GetLastDevicePathNode (DevicePathProtocol
);
309 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
310 ASSERT_EFI_ERROR(Status
);
311 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (DevicePathNode
, TRUE
, TRUE
);
312 StrnCpy (Description
, DevicePathTxt
, BOOT_DEVICE_DESCRIPTION_MAX
);
313 FreePool (DevicePathTxt
);
321 IN CHAR16
* BootOption
325 BDS_LOAD_OPTION
*BdsLoadOption
;
327 Status
= BootOptionFromLoadOptionVariable (BootOption
, &BdsLoadOption
);
328 if (!EFI_ERROR(Status
)) {
329 Status
= BootOptionStart (BdsLoadOption
);
330 FreePool (BdsLoadOption
);
332 if (!EFI_ERROR(Status
)) {
333 Status
= EFI_SUCCESS
;
335 Status
= EFI_NOT_STARTED
;
338 Status
= EFI_NOT_FOUND
;
344 GetUnalignedDevicePathSize (
345 IN EFI_DEVICE_PATH
* DevicePath
349 EFI_DEVICE_PATH
* AlignedDevicePath
;
351 if ((UINTN
)DevicePath
& 0x1) {
352 AlignedDevicePath
= DuplicateDevicePath (DevicePath
);
353 Size
= GetDevicePathSize (AlignedDevicePath
);
354 FreePool (AlignedDevicePath
);
356 Size
= GetDevicePathSize (DevicePath
);
362 GetAlignedDevicePath (
363 IN EFI_DEVICE_PATH
* DevicePath
366 if ((UINTN
)DevicePath
& 0x1) {
367 return DuplicateDevicePath (DevicePath
);
378 // We do not support NULL pointer
379 ASSERT (String
!= NULL
);
381 if (*(CHAR16
*)String
< 0x100) {
382 //Note: We could get issue if the string is an empty Ascii string...
390 * Try to detect if the given string is an ASCII or Unicode string
392 * There are actually few limitation to this function but it is mainly to give
393 * a user friendly output.
396 * - it only supports unicode string that use ASCII character (< 0x100)
397 * - single character ASCII strings are interpreted as Unicode string
398 * - string cannot be longer than BOOT_DEVICE_OPTION_MAX characters and
399 * thus (BOOT_DEVICE_OPTION_MAX*2) bytes for an Unicode string and
400 * BOOT_DEVICE_OPTION_MAX bytes for an ASCII string.
402 * @param String Buffer that might contain a Unicode or Ascii string
403 * @param IsUnicode If not NULL this boolean value returns if the string is an
404 * ASCII or Unicode string.
409 OUT BOOLEAN
*IsUnicode
412 BOOLEAN UnicodeDetected
;
417 // We do not support NULL pointer
418 ASSERT (String
!= NULL
);
421 if (*(CHAR16
*)String
== L
'\0') {
426 } else if (*(CHAR16
*)String
== '\0') {
433 // Limitation: if the string is an ASCII single character string. This comparison
434 // will assume it is a Unicode string.
435 if (*(CHAR16
*)String
< 0x100) {
436 UnicodeDetected
= TRUE
;
438 UnicodeDetected
= FALSE
;
442 for (Index
= 0; Index
< BOOT_DEVICE_OPTION_MAX
; Index
++) {
443 if (UnicodeDetected
) {
444 Character
= ((CHAR16
*)String
)[Index
];
446 Character
= ((CHAR8
*)String
)[Index
];
449 if (Character
== '\0') {
453 } else if ((Character
< 0x20) || (Character
> 0x7f)) {
454 // We only support the range of printable ASCII character
460 if (IsPrintable
&& IsUnicode
) {
461 *IsUnicode
= UnicodeDetected
;