1 | /** @file
|
---|
2 | Provide boot option support for Application "BootMaint"
|
---|
3 |
|
---|
4 | Include file system navigation, system handle selection
|
---|
5 |
|
---|
6 | Boot option manipulation
|
---|
7 |
|
---|
8 | Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
---|
9 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
10 |
|
---|
11 | **/
|
---|
12 |
|
---|
13 | #include "BootMaintenanceManager.h"
|
---|
14 |
|
---|
15 | ///
|
---|
16 | /// Define the maximum characters that will be accepted.
|
---|
17 | ///
|
---|
18 | #define MAX_CHAR 480
|
---|
19 |
|
---|
20 | /**
|
---|
21 |
|
---|
22 | Check whether a reset is needed, if reset is needed, Popup a menu to notice user.
|
---|
23 |
|
---|
24 | **/
|
---|
25 | VOID
|
---|
26 | BmmSetupResetReminder (
|
---|
27 | VOID
|
---|
28 | )
|
---|
29 | {
|
---|
30 | EFI_INPUT_KEY Key;
|
---|
31 | CHAR16 *StringBuffer1;
|
---|
32 | CHAR16 *StringBuffer2;
|
---|
33 | EFI_STATUS Status;
|
---|
34 | EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;
|
---|
35 |
|
---|
36 | //
|
---|
37 | // Use BrowserEx2 protocol to check whether reset is required.
|
---|
38 | //
|
---|
39 | Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);
|
---|
40 |
|
---|
41 | //
|
---|
42 | //check any reset required change is applied? if yes, reset system
|
---|
43 | //
|
---|
44 | if (!EFI_ERROR(Status) && FormBrowserEx2->IsResetRequired()) {
|
---|
45 | StringBuffer1 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16));
|
---|
46 | ASSERT (StringBuffer1 != NULL);
|
---|
47 | StringBuffer2 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16));
|
---|
48 | ASSERT (StringBuffer2 != NULL);
|
---|
49 | StrCpyS (StringBuffer1, MAX_CHAR, L"Configuration changed. Reset to apply it Now.");
|
---|
50 | StrCpyS (StringBuffer2, MAX_CHAR, L"Press ENTER to reset");
|
---|
51 | //
|
---|
52 | // Popup a menu to notice user
|
---|
53 | //
|
---|
54 | do {
|
---|
55 | CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);
|
---|
56 | } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
---|
57 |
|
---|
58 | FreePool (StringBuffer1);
|
---|
59 | FreePool (StringBuffer2);
|
---|
60 |
|
---|
61 | gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
|
---|
62 | }
|
---|
63 | }
|
---|
64 |
|
---|
65 | /**
|
---|
66 | Create a menu entry by given menu type.
|
---|
67 |
|
---|
68 | @param MenuType The Menu type to be created.
|
---|
69 |
|
---|
70 | @retval NULL If failed to create the menu.
|
---|
71 | @return the new menu entry.
|
---|
72 |
|
---|
73 | **/
|
---|
74 | BM_MENU_ENTRY *
|
---|
75 | BOpt_CreateMenuEntry (
|
---|
76 | UINTN MenuType
|
---|
77 | )
|
---|
78 | {
|
---|
79 | BM_MENU_ENTRY *MenuEntry;
|
---|
80 | UINTN ContextSize;
|
---|
81 |
|
---|
82 | //
|
---|
83 | // Get context size according to menu type
|
---|
84 | //
|
---|
85 | switch (MenuType) {
|
---|
86 | case BM_LOAD_CONTEXT_SELECT:
|
---|
87 | ContextSize = sizeof (BM_LOAD_CONTEXT);
|
---|
88 | break;
|
---|
89 |
|
---|
90 | case BM_FILE_CONTEXT_SELECT:
|
---|
91 | ContextSize = sizeof (BM_FILE_CONTEXT);
|
---|
92 | break;
|
---|
93 |
|
---|
94 | case BM_CONSOLE_CONTEXT_SELECT:
|
---|
95 | ContextSize = sizeof (BM_CONSOLE_CONTEXT);
|
---|
96 | break;
|
---|
97 |
|
---|
98 | case BM_TERMINAL_CONTEXT_SELECT:
|
---|
99 | ContextSize = sizeof (BM_TERMINAL_CONTEXT);
|
---|
100 | break;
|
---|
101 |
|
---|
102 | case BM_HANDLE_CONTEXT_SELECT:
|
---|
103 | ContextSize = sizeof (BM_HANDLE_CONTEXT);
|
---|
104 | break;
|
---|
105 |
|
---|
106 | default:
|
---|
107 | ContextSize = 0;
|
---|
108 | break;
|
---|
109 | }
|
---|
110 |
|
---|
111 | if (ContextSize == 0) {
|
---|
112 | return NULL;
|
---|
113 | }
|
---|
114 |
|
---|
115 | //
|
---|
116 | // Create new menu entry
|
---|
117 | //
|
---|
118 | MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));
|
---|
119 | if (MenuEntry == NULL) {
|
---|
120 | return NULL;
|
---|
121 | }
|
---|
122 |
|
---|
123 | MenuEntry->VariableContext = AllocateZeroPool (ContextSize);
|
---|
124 | if (MenuEntry->VariableContext == NULL) {
|
---|
125 | FreePool (MenuEntry);
|
---|
126 | return NULL;
|
---|
127 | }
|
---|
128 |
|
---|
129 | MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;
|
---|
130 | MenuEntry->ContextSelection = MenuType;
|
---|
131 | return MenuEntry;
|
---|
132 | }
|
---|
133 |
|
---|
134 | /**
|
---|
135 | Free up all resource allocated for a BM_MENU_ENTRY.
|
---|
136 |
|
---|
137 | @param MenuEntry A pointer to BM_MENU_ENTRY.
|
---|
138 |
|
---|
139 | **/
|
---|
140 | VOID
|
---|
141 | BOpt_DestroyMenuEntry (
|
---|
142 | BM_MENU_ENTRY *MenuEntry
|
---|
143 | )
|
---|
144 | {
|
---|
145 | BM_LOAD_CONTEXT *LoadContext;
|
---|
146 | BM_FILE_CONTEXT *FileContext;
|
---|
147 | BM_CONSOLE_CONTEXT *ConsoleContext;
|
---|
148 | BM_TERMINAL_CONTEXT *TerminalContext;
|
---|
149 | BM_HANDLE_CONTEXT *HandleContext;
|
---|
150 |
|
---|
151 | //
|
---|
152 | // Select by the type in Menu entry for current context type
|
---|
153 | //
|
---|
154 | switch (MenuEntry->ContextSelection) {
|
---|
155 | case BM_LOAD_CONTEXT_SELECT:
|
---|
156 | LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;
|
---|
157 | FreePool (LoadContext->FilePathList);
|
---|
158 | if (LoadContext->OptionalData != NULL) {
|
---|
159 | FreePool (LoadContext->OptionalData);
|
---|
160 | }
|
---|
161 | FreePool (LoadContext);
|
---|
162 | break;
|
---|
163 |
|
---|
164 | case BM_FILE_CONTEXT_SELECT:
|
---|
165 | FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
|
---|
166 |
|
---|
167 | if (!FileContext->IsRoot) {
|
---|
168 | FreePool (FileContext->DevicePath);
|
---|
169 | } else {
|
---|
170 | if (FileContext->FHandle != NULL) {
|
---|
171 | FileContext->FHandle->Close (FileContext->FHandle);
|
---|
172 | }
|
---|
173 | }
|
---|
174 |
|
---|
175 | if (FileContext->FileName != NULL) {
|
---|
176 | FreePool (FileContext->FileName);
|
---|
177 | }
|
---|
178 | if (FileContext->Info != NULL) {
|
---|
179 | FreePool (FileContext->Info);
|
---|
180 | }
|
---|
181 | FreePool (FileContext);
|
---|
182 | break;
|
---|
183 |
|
---|
184 | case BM_CONSOLE_CONTEXT_SELECT:
|
---|
185 | ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;
|
---|
186 | FreePool (ConsoleContext->DevicePath);
|
---|
187 | FreePool (ConsoleContext);
|
---|
188 | break;
|
---|
189 |
|
---|
190 | case BM_TERMINAL_CONTEXT_SELECT:
|
---|
191 | TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;
|
---|
192 | FreePool (TerminalContext->DevicePath);
|
---|
193 | FreePool (TerminalContext);
|
---|
194 | break;
|
---|
195 |
|
---|
196 | case BM_HANDLE_CONTEXT_SELECT:
|
---|
197 | HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;
|
---|
198 | FreePool (HandleContext);
|
---|
199 | break;
|
---|
200 |
|
---|
201 | default:
|
---|
202 | break;
|
---|
203 | }
|
---|
204 |
|
---|
205 | FreePool (MenuEntry->DisplayString);
|
---|
206 | if (MenuEntry->HelpString != NULL) {
|
---|
207 | FreePool (MenuEntry->HelpString);
|
---|
208 | }
|
---|
209 |
|
---|
210 | FreePool (MenuEntry);
|
---|
211 | }
|
---|
212 |
|
---|
213 | /**
|
---|
214 | Get the Menu Entry from the list in Menu Entry List.
|
---|
215 |
|
---|
216 | If MenuNumber is great or equal to the number of Menu
|
---|
217 | Entry in the list, then ASSERT.
|
---|
218 |
|
---|
219 | @param MenuOption The Menu Entry List to read the menu entry.
|
---|
220 | @param MenuNumber The index of Menu Entry.
|
---|
221 |
|
---|
222 | @return The Menu Entry.
|
---|
223 |
|
---|
224 | **/
|
---|
225 | BM_MENU_ENTRY *
|
---|
226 | BOpt_GetMenuEntry (
|
---|
227 | BM_MENU_OPTION *MenuOption,
|
---|
228 | UINTN MenuNumber
|
---|
229 | )
|
---|
230 | {
|
---|
231 | BM_MENU_ENTRY *NewMenuEntry;
|
---|
232 | UINTN Index;
|
---|
233 | LIST_ENTRY *List;
|
---|
234 |
|
---|
235 | ASSERT (MenuNumber < MenuOption->MenuNumber);
|
---|
236 |
|
---|
237 | List = MenuOption->Head.ForwardLink;
|
---|
238 | for (Index = 0; Index < MenuNumber; Index++) {
|
---|
239 | List = List->ForwardLink;
|
---|
240 | }
|
---|
241 |
|
---|
242 | NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);
|
---|
243 |
|
---|
244 | return NewMenuEntry;
|
---|
245 | }
|
---|
246 |
|
---|
247 | /**
|
---|
248 | Free resources allocated in Allocate Rountine.
|
---|
249 |
|
---|
250 | @param FreeMenu Menu to be freed
|
---|
251 | **/
|
---|
252 | VOID
|
---|
253 | BOpt_FreeMenu (
|
---|
254 | BM_MENU_OPTION *FreeMenu
|
---|
255 | )
|
---|
256 | {
|
---|
257 | BM_MENU_ENTRY *MenuEntry;
|
---|
258 | while (!IsListEmpty (&FreeMenu->Head)) {
|
---|
259 | MenuEntry = CR (
|
---|
260 | FreeMenu->Head.ForwardLink,
|
---|
261 | BM_MENU_ENTRY,
|
---|
262 | Link,
|
---|
263 | BM_MENU_ENTRY_SIGNATURE
|
---|
264 | );
|
---|
265 | RemoveEntryList (&MenuEntry->Link);
|
---|
266 | BOpt_DestroyMenuEntry (MenuEntry);
|
---|
267 | }
|
---|
268 | FreeMenu->MenuNumber = 0;
|
---|
269 | }
|
---|
270 |
|
---|
271 | /**
|
---|
272 |
|
---|
273 | Build the BootOptionMenu according to BootOrder Variable.
|
---|
274 | This Routine will access the Boot#### to get EFI_LOAD_OPTION.
|
---|
275 |
|
---|
276 | @param CallbackData The BMM context data.
|
---|
277 |
|
---|
278 | @return EFI_NOT_FOUND Fail to find "BootOrder" variable.
|
---|
279 | @return EFI_SUCESS Success build boot option menu.
|
---|
280 |
|
---|
281 | **/
|
---|
282 | EFI_STATUS
|
---|
283 | BOpt_GetBootOptions (
|
---|
284 | IN BMM_CALLBACK_DATA *CallbackData
|
---|
285 | )
|
---|
286 | {
|
---|
287 | UINTN Index;
|
---|
288 | UINT16 BootString[10];
|
---|
289 | UINT8 *LoadOptionFromVar;
|
---|
290 | UINTN BootOptionSize;
|
---|
291 | BOOLEAN BootNextFlag;
|
---|
292 | UINT16 *BootOrderList;
|
---|
293 | UINTN BootOrderListSize;
|
---|
294 | UINT16 *BootNext;
|
---|
295 | UINTN BootNextSize;
|
---|
296 | BM_MENU_ENTRY *NewMenuEntry;
|
---|
297 | BM_LOAD_CONTEXT *NewLoadContext;
|
---|
298 | UINT8 *LoadOptionPtr;
|
---|
299 | UINTN StringSize;
|
---|
300 | UINTN OptionalDataSize;
|
---|
301 | UINT8 *LoadOptionEnd;
|
---|
302 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
---|
303 | UINTN MenuCount;
|
---|
304 | UINT8 *Ptr;
|
---|
305 | EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
|
---|
306 | UINTN BootOptionCount;
|
---|
307 |
|
---|
308 | MenuCount = 0;
|
---|
309 | BootOrderListSize = 0;
|
---|
310 | BootNextSize = 0;
|
---|
311 | BootOrderList = NULL;
|
---|
312 | BootNext = NULL;
|
---|
313 | LoadOptionFromVar = NULL;
|
---|
314 | BOpt_FreeMenu (&BootOptionMenu);
|
---|
315 | InitializeListHead (&BootOptionMenu.Head);
|
---|
316 |
|
---|
317 | //
|
---|
318 | // Get the BootOrder from the Var
|
---|
319 | //
|
---|
320 | GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
|
---|
321 | if (BootOrderList == NULL) {
|
---|
322 | return EFI_NOT_FOUND;
|
---|
323 | }
|
---|
324 |
|
---|
325 | //
|
---|
326 | // Get the BootNext from the Var
|
---|
327 | //
|
---|
328 | GetEfiGlobalVariable2 (L"BootNext", (VOID **) &BootNext, &BootNextSize);
|
---|
329 | if (BootNext != NULL) {
|
---|
330 | if (BootNextSize != sizeof (UINT16)) {
|
---|
331 | FreePool (BootNext);
|
---|
332 | BootNext = NULL;
|
---|
333 | }
|
---|
334 | }
|
---|
335 | BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
|
---|
336 | for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
|
---|
337 | //
|
---|
338 | // Don't display the hidden/inactive boot option
|
---|
339 | //
|
---|
340 | if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
|
---|
341 | continue;
|
---|
342 | }
|
---|
343 |
|
---|
344 | UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
|
---|
345 | //
|
---|
346 | // Get all loadoptions from the VAR
|
---|
347 | //
|
---|
348 | GetEfiGlobalVariable2 (BootString, (VOID **) &LoadOptionFromVar, &BootOptionSize);
|
---|
349 | if (LoadOptionFromVar == NULL) {
|
---|
350 | continue;
|
---|
351 | }
|
---|
352 |
|
---|
353 | if (BootNext != NULL) {
|
---|
354 | BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);
|
---|
355 | } else {
|
---|
356 | BootNextFlag = FALSE;
|
---|
357 | }
|
---|
358 |
|
---|
359 | NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
|
---|
360 | ASSERT (NULL != NewMenuEntry);
|
---|
361 |
|
---|
362 | NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
|
---|
363 |
|
---|
364 | LoadOptionPtr = LoadOptionFromVar;
|
---|
365 | LoadOptionEnd = LoadOptionFromVar + BootOptionSize;
|
---|
366 |
|
---|
367 | NewMenuEntry->OptionNumber = BootOrderList[Index];
|
---|
368 | NewLoadContext->Deleted = FALSE;
|
---|
369 | NewLoadContext->IsBootNext = BootNextFlag;
|
---|
370 |
|
---|
371 | //
|
---|
372 | // Is a Legacy Device?
|
---|
373 | //
|
---|
374 | Ptr = (UINT8 *) LoadOptionFromVar;
|
---|
375 |
|
---|
376 | //
|
---|
377 | // Attribute = *(UINT32 *)Ptr;
|
---|
378 | //
|
---|
379 | Ptr += sizeof (UINT32);
|
---|
380 |
|
---|
381 | //
|
---|
382 | // FilePathSize = *(UINT16 *)Ptr;
|
---|
383 | //
|
---|
384 | Ptr += sizeof (UINT16);
|
---|
385 |
|
---|
386 | //
|
---|
387 | // Description = (CHAR16 *)Ptr;
|
---|
388 | //
|
---|
389 | Ptr += StrSize ((CHAR16 *) Ptr);
|
---|
390 |
|
---|
391 | //
|
---|
392 | // Now Ptr point to Device Path
|
---|
393 | //
|
---|
394 | DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
|
---|
395 | if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
|
---|
396 | NewLoadContext->IsLegacy = TRUE;
|
---|
397 | } else {
|
---|
398 | NewLoadContext->IsLegacy = FALSE;
|
---|
399 | }
|
---|
400 | //
|
---|
401 | // LoadOption is a pointer type of UINT8
|
---|
402 | // for easy use with following LOAD_OPTION
|
---|
403 | // embedded in this struct
|
---|
404 | //
|
---|
405 |
|
---|
406 | NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
|
---|
407 |
|
---|
408 | LoadOptionPtr += sizeof (UINT32);
|
---|
409 |
|
---|
410 | NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
|
---|
411 | LoadOptionPtr += sizeof (UINT16);
|
---|
412 |
|
---|
413 | StringSize = StrSize((UINT16*)LoadOptionPtr);
|
---|
414 |
|
---|
415 | NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr));
|
---|
416 | ASSERT (NewLoadContext->Description != NULL);
|
---|
417 | StrCpyS (NewLoadContext->Description, StrSize((UINT16*)LoadOptionPtr) / sizeof (UINT16), (UINT16*)LoadOptionPtr);
|
---|
418 |
|
---|
419 | ASSERT (NewLoadContext->Description != NULL);
|
---|
420 | NewMenuEntry->DisplayString = NewLoadContext->Description;
|
---|
421 | NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
|
---|
422 |
|
---|
423 | LoadOptionPtr += StringSize;
|
---|
424 |
|
---|
425 | NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
|
---|
426 | ASSERT (NewLoadContext->FilePathList != NULL);
|
---|
427 | CopyMem (
|
---|
428 | NewLoadContext->FilePathList,
|
---|
429 | (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
|
---|
430 | NewLoadContext->FilePathListLength
|
---|
431 | );
|
---|
432 |
|
---|
433 | NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
|
---|
434 | NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
|
---|
435 |
|
---|
436 | LoadOptionPtr += NewLoadContext->FilePathListLength;
|
---|
437 |
|
---|
438 | if (LoadOptionPtr < LoadOptionEnd) {
|
---|
439 | OptionalDataSize = BootOptionSize -
|
---|
440 | sizeof (UINT32) -
|
---|
441 | sizeof (UINT16) -
|
---|
442 | StringSize -
|
---|
443 | NewLoadContext->FilePathListLength;
|
---|
444 |
|
---|
445 | NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
|
---|
446 | ASSERT (NewLoadContext->OptionalData != NULL);
|
---|
447 | CopyMem (
|
---|
448 | NewLoadContext->OptionalData,
|
---|
449 | LoadOptionPtr,
|
---|
450 | OptionalDataSize
|
---|
451 | );
|
---|
452 | }
|
---|
453 |
|
---|
454 | InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
|
---|
455 | MenuCount++;
|
---|
456 | FreePool (LoadOptionFromVar);
|
---|
457 | }
|
---|
458 | EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
|
---|
459 |
|
---|
460 | if (BootNext != NULL) {
|
---|
461 | FreePool (BootNext);
|
---|
462 | }
|
---|
463 | if (BootOrderList != NULL) {
|
---|
464 | FreePool (BootOrderList);
|
---|
465 | }
|
---|
466 |
|
---|
467 | BootOptionMenu.MenuNumber = MenuCount;
|
---|
468 | return EFI_SUCCESS;
|
---|
469 | }
|
---|
470 |
|
---|
471 | /**
|
---|
472 |
|
---|
473 | Find drivers that will be added as Driver#### variables from handles
|
---|
474 | in current system environment
|
---|
475 | All valid handles in the system except those consume SimpleFs, LoadFile
|
---|
476 | are stored in DriverMenu for future use.
|
---|
477 |
|
---|
478 | @retval EFI_SUCCESS The function complets successfully.
|
---|
479 | @return Other value if failed to build the DriverMenu.
|
---|
480 |
|
---|
481 | **/
|
---|
482 | EFI_STATUS
|
---|
483 | BOpt_FindDrivers (
|
---|
484 | VOID
|
---|
485 | )
|
---|
486 | {
|
---|
487 | UINTN NoDevicePathHandles;
|
---|
488 | EFI_HANDLE *DevicePathHandle;
|
---|
489 | UINTN Index;
|
---|
490 | EFI_STATUS Status;
|
---|
491 | BM_MENU_ENTRY *NewMenuEntry;
|
---|
492 | BM_HANDLE_CONTEXT *NewHandleContext;
|
---|
493 | EFI_HANDLE CurHandle;
|
---|
494 | UINTN OptionNumber;
|
---|
495 | EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
|
---|
496 | EFI_LOAD_FILE_PROTOCOL *LoadFile;
|
---|
497 |
|
---|
498 | SimpleFs = NULL;
|
---|
499 | LoadFile = NULL;
|
---|
500 |
|
---|
501 | InitializeListHead (&DriverMenu.Head);
|
---|
502 |
|
---|
503 | //
|
---|
504 | // At first, get all handles that support Device Path
|
---|
505 | // protocol which is the basic requirement for
|
---|
506 | // Driver####
|
---|
507 | //
|
---|
508 | Status = gBS->LocateHandleBuffer (
|
---|
509 | ByProtocol,
|
---|
510 | &gEfiDevicePathProtocolGuid,
|
---|
511 | NULL,
|
---|
512 | &NoDevicePathHandles,
|
---|
513 | &DevicePathHandle
|
---|
514 | );
|
---|
515 | if (EFI_ERROR (Status)) {
|
---|
516 | return Status;
|
---|
517 | }
|
---|
518 |
|
---|
519 | OptionNumber = 0;
|
---|
520 | for (Index = 0; Index < NoDevicePathHandles; Index++) {
|
---|
521 | CurHandle = DevicePathHandle[Index];
|
---|
522 |
|
---|
523 | Status = gBS->HandleProtocol (
|
---|
524 | CurHandle,
|
---|
525 | &gEfiSimpleFileSystemProtocolGuid,
|
---|
526 | (VOID **) &SimpleFs
|
---|
527 | );
|
---|
528 | if (Status == EFI_SUCCESS) {
|
---|
529 | continue;
|
---|
530 | }
|
---|
531 |
|
---|
532 | Status = gBS->HandleProtocol (
|
---|
533 | CurHandle,
|
---|
534 | &gEfiLoadFileProtocolGuid,
|
---|
535 | (VOID **) &LoadFile
|
---|
536 | );
|
---|
537 | if (Status == EFI_SUCCESS) {
|
---|
538 | continue;
|
---|
539 | }
|
---|
540 |
|
---|
541 | NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);
|
---|
542 | if (NULL == NewMenuEntry) {
|
---|
543 | FreePool (DevicePathHandle);
|
---|
544 | return EFI_OUT_OF_RESOURCES;
|
---|
545 | }
|
---|
546 |
|
---|
547 | NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
|
---|
548 | NewHandleContext->Handle = CurHandle;
|
---|
549 | NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);
|
---|
550 | NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath);
|
---|
551 | NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle,0,NewMenuEntry->DisplayString,NULL);
|
---|
552 | NewMenuEntry->HelpString = NULL;
|
---|
553 | NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
|
---|
554 | NewMenuEntry->OptionNumber = OptionNumber;
|
---|
555 | OptionNumber++;
|
---|
556 | InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);
|
---|
557 |
|
---|
558 | }
|
---|
559 |
|
---|
560 | if (DevicePathHandle != NULL) {
|
---|
561 | FreePool (DevicePathHandle);
|
---|
562 | }
|
---|
563 |
|
---|
564 | DriverMenu.MenuNumber = OptionNumber;
|
---|
565 | return EFI_SUCCESS;
|
---|
566 | }
|
---|
567 |
|
---|
568 | /**
|
---|
569 |
|
---|
570 | Get the Option Number that has not been allocated for use.
|
---|
571 |
|
---|
572 | @param Type The type of Option.
|
---|
573 |
|
---|
574 | @return The available Option Number.
|
---|
575 |
|
---|
576 | **/
|
---|
577 | UINT16
|
---|
578 | BOpt_GetOptionNumber (
|
---|
579 | CHAR16 *Type
|
---|
580 | )
|
---|
581 | {
|
---|
582 | UINT16 *OrderList;
|
---|
583 | UINTN OrderListSize;
|
---|
584 | UINTN Index;
|
---|
585 | CHAR16 StrTemp[20];
|
---|
586 | UINT16 *OptionBuffer;
|
---|
587 | UINT16 OptionNumber;
|
---|
588 | UINTN OptionSize;
|
---|
589 |
|
---|
590 | OrderListSize = 0;
|
---|
591 | OrderList = NULL;
|
---|
592 | OptionNumber = 0;
|
---|
593 | Index = 0;
|
---|
594 |
|
---|
595 | UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);
|
---|
596 |
|
---|
597 | GetEfiGlobalVariable2 (StrTemp, (VOID **) &OrderList, &OrderListSize);
|
---|
598 | for (OptionNumber = 0; ; OptionNumber++) {
|
---|
599 | if (OrderList != NULL) {
|
---|
600 | for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {
|
---|
601 | if (OptionNumber == OrderList[Index]) {
|
---|
602 | break;
|
---|
603 | }
|
---|
604 | }
|
---|
605 | }
|
---|
606 |
|
---|
607 | if (Index < OrderListSize / sizeof (UINT16)) {
|
---|
608 | //
|
---|
609 | // The OptionNumber occurs in the OrderList, continue to use next one
|
---|
610 | //
|
---|
611 | continue;
|
---|
612 | }
|
---|
613 | UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber);
|
---|
614 | DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp));
|
---|
615 | GetEfiGlobalVariable2 (StrTemp, (VOID **) &OptionBuffer, &OptionSize);
|
---|
616 | if (NULL == OptionBuffer) {
|
---|
617 | //
|
---|
618 | // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it
|
---|
619 | //
|
---|
620 | break;
|
---|
621 | }
|
---|
622 | }
|
---|
623 |
|
---|
624 | return OptionNumber;
|
---|
625 | }
|
---|
626 |
|
---|
627 | /**
|
---|
628 |
|
---|
629 | Get the Option Number for Boot#### that does not used.
|
---|
630 |
|
---|
631 | @return The available Option Number.
|
---|
632 |
|
---|
633 | **/
|
---|
634 | UINT16
|
---|
635 | BOpt_GetBootOptionNumber (
|
---|
636 | VOID
|
---|
637 | )
|
---|
638 | {
|
---|
639 | return BOpt_GetOptionNumber (L"Boot");
|
---|
640 | }
|
---|
641 |
|
---|
642 | /**
|
---|
643 |
|
---|
644 | Get the Option Number for Driver#### that does not used.
|
---|
645 |
|
---|
646 | @return The unused Option Number.
|
---|
647 |
|
---|
648 | **/
|
---|
649 | UINT16
|
---|
650 | BOpt_GetDriverOptionNumber (
|
---|
651 | VOID
|
---|
652 | )
|
---|
653 | {
|
---|
654 | return BOpt_GetOptionNumber (L"Driver");
|
---|
655 | }
|
---|
656 |
|
---|
657 | /**
|
---|
658 |
|
---|
659 | Build up all DriverOptionMenu
|
---|
660 |
|
---|
661 | @param CallbackData The BMM context data.
|
---|
662 |
|
---|
663 | @retval EFI_SUCESS The functin completes successfully.
|
---|
664 | @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
|
---|
665 | @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.
|
---|
666 |
|
---|
667 | **/
|
---|
668 | EFI_STATUS
|
---|
669 | BOpt_GetDriverOptions (
|
---|
670 | IN BMM_CALLBACK_DATA *CallbackData
|
---|
671 | )
|
---|
672 | {
|
---|
673 | UINTN Index;
|
---|
674 | UINT16 DriverString[12];
|
---|
675 | UINT8 *LoadOptionFromVar;
|
---|
676 | UINTN DriverOptionSize;
|
---|
677 |
|
---|
678 | UINT16 *DriverOrderList;
|
---|
679 | UINTN DriverOrderListSize;
|
---|
680 | BM_MENU_ENTRY *NewMenuEntry;
|
---|
681 | BM_LOAD_CONTEXT *NewLoadContext;
|
---|
682 | UINT8 *LoadOptionPtr;
|
---|
683 | UINTN StringSize;
|
---|
684 | UINTN OptionalDataSize;
|
---|
685 | UINT8 *LoadOptionEnd;
|
---|
686 |
|
---|
687 | DriverOrderListSize = 0;
|
---|
688 | DriverOrderList = NULL;
|
---|
689 | DriverOptionSize = 0;
|
---|
690 | LoadOptionFromVar = NULL;
|
---|
691 | BOpt_FreeMenu (&DriverOptionMenu);
|
---|
692 | InitializeListHead (&DriverOptionMenu.Head);
|
---|
693 | //
|
---|
694 | // Get the DriverOrder from the Var
|
---|
695 | //
|
---|
696 | GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
|
---|
697 | if (DriverOrderList == NULL) {
|
---|
698 | return EFI_NOT_FOUND;
|
---|
699 | }
|
---|
700 |
|
---|
701 | for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
|
---|
702 | UnicodeSPrint (
|
---|
703 | DriverString,
|
---|
704 | sizeof (DriverString),
|
---|
705 | L"Driver%04x",
|
---|
706 | DriverOrderList[Index]
|
---|
707 | );
|
---|
708 | //
|
---|
709 | // Get all loadoptions from the VAR
|
---|
710 | //
|
---|
711 | GetEfiGlobalVariable2 (DriverString, (VOID **) &LoadOptionFromVar, &DriverOptionSize);
|
---|
712 | if (LoadOptionFromVar == NULL) {
|
---|
713 | continue;
|
---|
714 | }
|
---|
715 |
|
---|
716 |
|
---|
717 | NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
|
---|
718 | if (NULL == NewMenuEntry) {
|
---|
719 | return EFI_OUT_OF_RESOURCES;
|
---|
720 | }
|
---|
721 |
|
---|
722 | NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
|
---|
723 | LoadOptionPtr = LoadOptionFromVar;
|
---|
724 | LoadOptionEnd = LoadOptionFromVar + DriverOptionSize;
|
---|
725 | NewMenuEntry->OptionNumber = DriverOrderList[Index];
|
---|
726 | NewLoadContext->Deleted = FALSE;
|
---|
727 | NewLoadContext->IsLegacy = FALSE;
|
---|
728 |
|
---|
729 | //
|
---|
730 | // LoadOption is a pointer type of UINT8
|
---|
731 | // for easy use with following LOAD_OPTION
|
---|
732 | // embedded in this struct
|
---|
733 | //
|
---|
734 |
|
---|
735 | NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
|
---|
736 |
|
---|
737 | LoadOptionPtr += sizeof (UINT32);
|
---|
738 |
|
---|
739 | NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
|
---|
740 | LoadOptionPtr += sizeof (UINT16);
|
---|
741 |
|
---|
742 | StringSize = StrSize ((UINT16 *) LoadOptionPtr);
|
---|
743 | NewLoadContext->Description = AllocateZeroPool (StringSize);
|
---|
744 | ASSERT (NewLoadContext->Description != NULL);
|
---|
745 | CopyMem (
|
---|
746 | NewLoadContext->Description,
|
---|
747 | (UINT16 *) LoadOptionPtr,
|
---|
748 | StringSize
|
---|
749 | );
|
---|
750 | NewMenuEntry->DisplayString = NewLoadContext->Description;
|
---|
751 | NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
|
---|
752 |
|
---|
753 | LoadOptionPtr += StringSize;
|
---|
754 |
|
---|
755 | NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
|
---|
756 | ASSERT (NewLoadContext->FilePathList != NULL);
|
---|
757 | CopyMem (
|
---|
758 | NewLoadContext->FilePathList,
|
---|
759 | (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
|
---|
760 | NewLoadContext->FilePathListLength
|
---|
761 | );
|
---|
762 |
|
---|
763 | NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
|
---|
764 | NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
|
---|
765 |
|
---|
766 | LoadOptionPtr += NewLoadContext->FilePathListLength;
|
---|
767 |
|
---|
768 | if (LoadOptionPtr < LoadOptionEnd) {
|
---|
769 | OptionalDataSize = DriverOptionSize -
|
---|
770 | sizeof (UINT32) -
|
---|
771 | sizeof (UINT16) -
|
---|
772 | StringSize -
|
---|
773 | NewLoadContext->FilePathListLength;
|
---|
774 |
|
---|
775 | NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
|
---|
776 | ASSERT (NewLoadContext->OptionalData != NULL);
|
---|
777 | CopyMem (
|
---|
778 | NewLoadContext->OptionalData,
|
---|
779 | LoadOptionPtr,
|
---|
780 | OptionalDataSize
|
---|
781 | );
|
---|
782 |
|
---|
783 | }
|
---|
784 |
|
---|
785 | InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
|
---|
786 | FreePool (LoadOptionFromVar);
|
---|
787 |
|
---|
788 | }
|
---|
789 |
|
---|
790 | if (DriverOrderList != NULL) {
|
---|
791 | FreePool (DriverOrderList);
|
---|
792 | }
|
---|
793 |
|
---|
794 | DriverOptionMenu.MenuNumber = Index;
|
---|
795 | return EFI_SUCCESS;
|
---|
796 |
|
---|
797 | }
|
---|
798 |
|
---|
799 | /**
|
---|
800 | Get option number according to Boot#### and BootOrder variable.
|
---|
801 | The value is saved as #### + 1.
|
---|
802 |
|
---|
803 | @param CallbackData The BMM context data.
|
---|
804 | **/
|
---|
805 | VOID
|
---|
806 | GetBootOrder (
|
---|
807 | IN BMM_CALLBACK_DATA *CallbackData
|
---|
808 | )
|
---|
809 | {
|
---|
810 | BMM_FAKE_NV_DATA *BmmConfig;
|
---|
811 | UINT16 Index;
|
---|
812 | UINT16 OptionOrderIndex;
|
---|
813 | UINTN DeviceType;
|
---|
814 | BM_MENU_ENTRY *NewMenuEntry;
|
---|
815 | BM_LOAD_CONTEXT *NewLoadContext;
|
---|
816 |
|
---|
817 | ASSERT (CallbackData != NULL);
|
---|
818 |
|
---|
819 | DeviceType = (UINTN) -1;
|
---|
820 | BmmConfig = &CallbackData->BmmFakeNvData;
|
---|
821 | ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));
|
---|
822 |
|
---|
823 | for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&
|
---|
824 | (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));
|
---|
825 | Index++) {
|
---|
826 | NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
|
---|
827 | NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
|
---|
828 |
|
---|
829 | if (NewLoadContext->IsLegacy) {
|
---|
830 | if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {
|
---|
831 | DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;
|
---|
832 | } else {
|
---|
833 | //
|
---|
834 | // Only show one legacy boot option for the same device type
|
---|
835 | // assuming the boot options are grouped by the device type
|
---|
836 | //
|
---|
837 | continue;
|
---|
838 | }
|
---|
839 | }
|
---|
840 | BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);
|
---|
841 | }
|
---|
842 | }
|
---|
843 |
|
---|
844 | /**
|
---|
845 | Get driver option order from globalc DriverOptionMenu.
|
---|
846 |
|
---|
847 | @param CallbackData The BMM context data.
|
---|
848 |
|
---|
849 | **/
|
---|
850 | VOID
|
---|
851 | GetDriverOrder (
|
---|
852 | IN BMM_CALLBACK_DATA *CallbackData
|
---|
853 | )
|
---|
854 | {
|
---|
855 | BMM_FAKE_NV_DATA *BmmConfig;
|
---|
856 | UINT16 Index;
|
---|
857 | UINT16 OptionOrderIndex;
|
---|
858 | UINTN DeviceType;
|
---|
859 | BM_MENU_ENTRY *NewMenuEntry;
|
---|
860 | BM_LOAD_CONTEXT *NewLoadContext;
|
---|
861 |
|
---|
862 |
|
---|
863 | ASSERT (CallbackData != NULL);
|
---|
864 |
|
---|
865 | DeviceType = (UINTN) -1;
|
---|
866 | BmmConfig = &CallbackData->BmmFakeNvData;
|
---|
867 | ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));
|
---|
868 |
|
---|
869 | for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&
|
---|
870 | (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));
|
---|
871 | Index++) {
|
---|
872 | NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
|
---|
873 | NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
|
---|
874 |
|
---|
875 | if (NewLoadContext->IsLegacy) {
|
---|
876 | if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {
|
---|
877 | DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;
|
---|
878 | } else {
|
---|
879 | //
|
---|
880 | // Only show one legacy boot option for the same device type
|
---|
881 | // assuming the boot options are grouped by the device type
|
---|
882 | //
|
---|
883 | continue;
|
---|
884 | }
|
---|
885 | }
|
---|
886 | BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);
|
---|
887 | }
|
---|
888 | }
|
---|
889 |
|
---|
890 | /**
|
---|
891 | Boot the file specified by the input file path info.
|
---|
892 |
|
---|
893 | @param FilePath Point to the file path.
|
---|
894 |
|
---|
895 | @retval TRUE Exit caller function.
|
---|
896 | @retval FALSE Not exit caller function.
|
---|
897 | **/
|
---|
898 | BOOLEAN
|
---|
899 | EFIAPI
|
---|
900 | BootFromFile (
|
---|
901 | IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
---|
902 | )
|
---|
903 | {
|
---|
904 | EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
|
---|
905 | CHAR16 *FileName;
|
---|
906 |
|
---|
907 | FileName = NULL;
|
---|
908 |
|
---|
909 | FileName = ExtractFileNameFromDevicePath(FilePath);
|
---|
910 | if (FileName != NULL) {
|
---|
911 | EfiBootManagerInitializeLoadOption (
|
---|
912 | &BootOption,
|
---|
913 | 0,
|
---|
914 | LoadOptionTypeBoot,
|
---|
915 | LOAD_OPTION_ACTIVE,
|
---|
916 | FileName,
|
---|
917 | FilePath,
|
---|
918 | NULL,
|
---|
919 | 0
|
---|
920 | );
|
---|
921 | //
|
---|
922 | // Since current no boot from removable media directly is allowed */
|
---|
923 | //
|
---|
924 | gST->ConOut->ClearScreen (gST->ConOut);
|
---|
925 | //
|
---|
926 | // Check whether need to reset system.
|
---|
927 | //
|
---|
928 | BmmSetupResetReminder ();
|
---|
929 |
|
---|
930 | BmmSetConsoleMode (FALSE);
|
---|
931 | EfiBootManagerBoot (&BootOption);
|
---|
932 | BmmSetConsoleMode (TRUE);
|
---|
933 |
|
---|
934 | FreePool(FileName);
|
---|
935 |
|
---|
936 | EfiBootManagerFreeLoadOption (&BootOption);
|
---|
937 | }
|
---|
938 |
|
---|
939 | return FALSE;
|
---|
940 | }
|
---|
941 |
|
---|
942 | /**
|
---|
943 | Display the form base on the selected file.
|
---|
944 |
|
---|
945 | @param FilePath Point to the file path.
|
---|
946 | @param FormId The form need to display.
|
---|
947 |
|
---|
948 | **/
|
---|
949 | BOOLEAN
|
---|
950 | ReSendForm(
|
---|
951 | IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
---|
952 | IN EFI_FORM_ID FormId
|
---|
953 | )
|
---|
954 | {
|
---|
955 | gBootMaintenancePrivate.LoadContext->FilePathList = FilePath;
|
---|
956 |
|
---|
957 | UpdateOptionPage(&gBootMaintenancePrivate, FormId, FilePath);
|
---|
958 |
|
---|
959 | gBootMaintenancePrivate.FormBrowser2->SendForm (
|
---|
960 | gBootMaintenancePrivate.FormBrowser2,
|
---|
961 | &gBootMaintenancePrivate.BmmHiiHandle,
|
---|
962 | 1,
|
---|
963 | &mBootMaintGuid,
|
---|
964 | FormId,
|
---|
965 | NULL,
|
---|
966 | NULL
|
---|
967 | );
|
---|
968 | return TRUE;
|
---|
969 | }
|
---|
970 |
|
---|
971 | /**
|
---|
972 | Create boot option base on the input file path info.
|
---|
973 |
|
---|
974 | @param FilePath Point to the file path.
|
---|
975 |
|
---|
976 | @retval TRUE Exit caller function.
|
---|
977 | @retval FALSE Not exit caller function.
|
---|
978 | **/
|
---|
979 | BOOLEAN
|
---|
980 | EFIAPI
|
---|
981 | CreateBootOptionFromFile (
|
---|
982 | IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
---|
983 | )
|
---|
984 | {
|
---|
985 | return ReSendForm(FilePath, FORM_BOOT_ADD_ID);
|
---|
986 | }
|
---|
987 |
|
---|
988 | /**
|
---|
989 | Create driver option base on the input file path info.
|
---|
990 |
|
---|
991 | @param FilePath Point to the file path.
|
---|
992 |
|
---|
993 | @retval TRUE Exit caller function.
|
---|
994 | @retval FALSE Not exit caller function.
|
---|
995 |
|
---|
996 | **/
|
---|
997 | BOOLEAN
|
---|
998 | EFIAPI
|
---|
999 | CreateDriverOptionFromFile (
|
---|
1000 | IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
---|
1001 | )
|
---|
1002 | {
|
---|
1003 | return ReSendForm(FilePath, FORM_DRV_ADD_FILE_ID);
|
---|
1004 | }
|
---|
1005 |
|
---|