]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BdsHelper.c
ArmPlatformPkg/Bds: Upgrade the BDS to be more conformed to the UEFI Specification
[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
71EditHIInputAscii (
72 IN OUT CHAR8 *CmdLine,
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
82 AsciiPrint (CmdLine);
83
84 for (CmdLineIndex = AsciiStrLen(CmdLine); CmdLineIndex < MaxCmdLine; ) {
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';
101 AsciiPrint ("\n\r");
102
103 return EFI_SUCCESS;
104 } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
105 if (CmdLineIndex != 0) {
106 CmdLineIndex--;
107 AsciiPrint ("\b \b");
108 }
109 } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {
110 return EFI_INVALID_PARAMETER;
111 } else {
112 CmdLine[CmdLineIndex++] = Char;
113 AsciiPrint ("%c", Char);
114 }
115 }
116
117 return EFI_SUCCESS;
118}
119
120EFI_STATUS
121GetHIInputAscii (
122 IN OUT CHAR8 *CmdLine,
123 IN UINTN MaxCmdLine
124 )
125{
126 // For a new input just passed an empty string
127 CmdLine[0] = '\0';
128
129 return EditHIInputAscii (CmdLine,MaxCmdLine);
130}
131
132EFI_STATUS
133GetHIInputInteger (
134 OUT UINTN *Integer
135 )
136{
137 CHAR8 CmdLine[255];
138 EFI_STATUS Status;
139
140 CmdLine[0] = '\0';
141 Status = EditHIInputAscii (CmdLine,255);
142 if (!EFI_ERROR(Status)) {
143 *Integer = AsciiStrDecimalToUintn (CmdLine);
144 }
145
146 return Status;
147}
148
149EFI_STATUS
150GetHIInputIP (
151 OUT EFI_IP_ADDRESS *Ip
152 )
153{
154 CHAR8 CmdLine[255];
155 CHAR8 *Str;
156 EFI_STATUS Status;
157
158 CmdLine[0] = '\0';
159 Status = EditHIInputAscii (CmdLine,255);
160 if (!EFI_ERROR(Status)) {
161 Str = CmdLine;
162 Ip->v4.Addr[0] = (UINT8)AsciiStrDecimalToUintn (Str);
163
164 Str = AsciiStrStr (Str, ".");
165 if (Str == NULL) {
166 return EFI_INVALID_PARAMETER;
167 }
168
169 Ip->v4.Addr[1] = (UINT8)AsciiStrDecimalToUintn (++Str);
170
171 Str = AsciiStrStr (Str, ".");
172 if (Str == NULL) {
173 return EFI_INVALID_PARAMETER;
174 }
175
176 Ip->v4.Addr[2] = (UINT8)AsciiStrDecimalToUintn (++Str);
177
178 Str = AsciiStrStr (Str, ".");
179 if (Str == NULL) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 Ip->v4.Addr[3] = (UINT8)AsciiStrDecimalToUintn (++Str);
184 }
185
186 return Status;
187}
188
189EFI_STATUS
190GetHIInputBoolean (
191 OUT BOOLEAN *Value
192 )
193{
194 CHAR8 CmdBoolean[2];
195 EFI_STATUS Status;
196
197 while(1) {
198 Print (L"[y/n] ");
199 Status = GetHIInputAscii (CmdBoolean,2);
200 if (EFI_ERROR(Status)) {
201 return Status;
202 } else if ((CmdBoolean[0] == 'y') || (CmdBoolean[0] == 'Y')) {
203 if (Value) *Value = TRUE;
204 return EFI_SUCCESS;
205 } else if ((CmdBoolean[0] == 'n') || (CmdBoolean[0] == 'N')) {
206 if (Value) *Value = FALSE;
207 return EFI_SUCCESS;
208 }
209 }
210}
211
212BOOLEAN
213HasFilePathEfiExtension (
214 IN CHAR16* FilePath
215 )
216{
217 return (StrCmp (FilePath + (StrSize(FilePath)/sizeof(CHAR16)) - 5, L".efi") == 0);
218}
219
220// Return the last non end-type Device Path Node from a Device Path
221EFI_DEVICE_PATH*
222GetLastDevicePathNode (
223 IN EFI_DEVICE_PATH* DevicePath
224 )
225{
226 EFI_DEVICE_PATH* PrevDevicePathNode;
227
228 PrevDevicePathNode = DevicePath;
229 while (!IsDevicePathEndType (DevicePath)) {
230 PrevDevicePathNode = DevicePath;
231 DevicePath = NextDevicePathNode (DevicePath);
232 }
233
234 return PrevDevicePathNode;
235}
236
237EFI_STATUS
238GenerateDeviceDescriptionName (
239 IN EFI_HANDLE Handle,
240 IN OUT CHAR16* Description
241 )
242{
243 EFI_STATUS Status;
244 EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol;
245 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
246 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
247 CHAR16* DriverName;
248 CHAR16* DevicePathTxt;
249 EFI_DEVICE_PATH* DevicePathNode;
250
251 ComponentName2Protocol = NULL;
252 Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);
253 if (!EFI_ERROR(Status)) {
254 //TODO: Fixme. we must find the best langague
255 Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);
256 if (!EFI_ERROR(Status)) {
257 StrnCpy (Description,DriverName,BOOT_DEVICE_DESCRIPTION_MAX);
258 }
259 }
260
261 if (EFI_ERROR(Status)) {
262 // Use the lastest non null entry of the Device path as a description
263 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
264 if (EFI_ERROR(Status)) {
265 return Status;
266 }
267
268 // Convert the last non end-type Device Path Node in text for the description
269 DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);
270 Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
271 ASSERT_EFI_ERROR(Status);
272 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathNode,TRUE,TRUE);
273 StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);
274 FreePool (DevicePathTxt);
275 }
276
277 return EFI_SUCCESS;
278}
279
280EFI_STATUS
281BdsStartBootOption (
282 IN CHAR16* BootOption
283 )
284{
285 EFI_STATUS Status;
286 EFI_LOAD_OPTION EfiLoadOption;
287 UINTN EfiLoadOptionSize;
288 BDS_LOAD_OPTION *BdsLoadOption;
289
290 Status = GetEnvironmentVariable (BootOption, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
291 if (!EFI_ERROR(Status)) {
292 Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, &BdsLoadOption);
293 if (!EFI_ERROR(Status)) {
294 Status = BootOptionStart (BdsLoadOption);
295 FreePool (BdsLoadOption);
296 }
297
298 if (!EFI_ERROR(Status)) {
299 Status = EFI_SUCCESS;
300 } else {
301 Status = EFI_NOT_STARTED;
302 }
303 } else {
304 Status = EFI_NOT_FOUND;
305 }
306 return Status;
307}