]>
Commit | Line | Data |
---|---|---|
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 | ||
17 | EFI_STATUS | |
18 | GetEnvironmentVariable ( | |
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 | ||
70 | EFI_STATUS | |
71 | EditHIInputAscii ( | |
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 | ||
120 | EFI_STATUS | |
121 | GetHIInputAscii ( | |
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 | ||
132 | EFI_STATUS | |
133 | GetHIInputInteger ( | |
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 | ||
149 | EFI_STATUS | |
150 | GetHIInputIP ( | |
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 | ||
189 | EFI_STATUS | |
190 | GetHIInputBoolean ( | |
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 | ||
212 | BOOLEAN | |
213 | HasFilePathEfiExtension ( | |
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 | |
221 | EFI_DEVICE_PATH* | |
222 | GetLastDevicePathNode ( | |
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 | ||
237 | EFI_STATUS | |
238 | GenerateDeviceDescriptionName ( | |
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 | ||
280 | EFI_STATUS | |
281 | BdsStartBootOption ( | |
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 | } |