]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
IntelFrameworkModulePkg BdsDxe: Remove redundant functions
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMaint / BootOption.c
CommitLineData
5c08e117 1/** @file\r
2 Provide boot option support for Application "BootMaint"\r
3\r
4 Include file system navigation, system handle selection\r
5\r
6 Boot option manipulation\r
7\r
0a6f4824 8Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
180a5a35 9This program and the accompanying materials\r
5c08e117 10are licensed and made available under the terms and conditions of the BSD License\r
11which accompanies this distribution. The full text of the license may be found at\r
12http://opensource.org/licenses/bsd-license.php\r
13\r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include "BootMaint.h"\r
20#include "BBSsupport.h"\r
21\r
22/**\r
23 Create a menu entry by given menu type.\r
24\r
25 @param MenuType The Menu type to be created.\r
26\r
27 @retval NULL If failed to create the menu.\r
28 @return the new menu entry.\r
29\r
30**/\r
31BM_MENU_ENTRY *\r
32BOpt_CreateMenuEntry (\r
33 UINTN MenuType\r
34 )\r
35{\r
36 BM_MENU_ENTRY *MenuEntry;\r
37 UINTN ContextSize;\r
38\r
39 //\r
40 // Get context size according to menu type\r
41 //\r
42 switch (MenuType) {\r
43 case BM_LOAD_CONTEXT_SELECT:\r
44 ContextSize = sizeof (BM_LOAD_CONTEXT);\r
45 break;\r
46\r
47 case BM_FILE_CONTEXT_SELECT:\r
48 ContextSize = sizeof (BM_FILE_CONTEXT);\r
49 break;\r
50\r
51 case BM_CONSOLE_CONTEXT_SELECT:\r
52 ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
53 break;\r
54\r
55 case BM_TERMINAL_CONTEXT_SELECT:\r
56 ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
57 break;\r
58\r
59 case BM_HANDLE_CONTEXT_SELECT:\r
60 ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
61 break;\r
62\r
63 case BM_LEGACY_DEV_CONTEXT_SELECT:\r
64 ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
65 break;\r
66\r
67 default:\r
68 ContextSize = 0;\r
69 break;\r
70 }\r
71\r
72 if (ContextSize == 0) {\r
73 return NULL;\r
74 }\r
75\r
76 //\r
77 // Create new menu entry\r
78 //\r
79 MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
80 if (MenuEntry == NULL) {\r
81 return NULL;\r
82 }\r
83\r
84 MenuEntry->VariableContext = AllocateZeroPool (ContextSize);\r
85 if (MenuEntry->VariableContext == NULL) {\r
86 FreePool (MenuEntry);\r
87 return NULL;\r
88 }\r
89\r
90 MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;\r
91 MenuEntry->ContextSelection = MenuType;\r
92 return MenuEntry;\r
93}\r
94\r
95/**\r
96 Free up all resource allocated for a BM_MENU_ENTRY.\r
97\r
98 @param MenuEntry A pointer to BM_MENU_ENTRY.\r
99\r
100**/\r
101VOID\r
102BOpt_DestroyMenuEntry (\r
103 BM_MENU_ENTRY *MenuEntry\r
104 )\r
105{\r
106 BM_LOAD_CONTEXT *LoadContext;\r
107 BM_FILE_CONTEXT *FileContext;\r
108 BM_CONSOLE_CONTEXT *ConsoleContext;\r
109 BM_TERMINAL_CONTEXT *TerminalContext;\r
110 BM_HANDLE_CONTEXT *HandleContext;\r
111 BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;\r
112\r
113 //\r
114 // Select by the type in Menu entry for current context type\r
115 //\r
116 switch (MenuEntry->ContextSelection) {\r
117 case BM_LOAD_CONTEXT_SELECT:\r
118 LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
119 FreePool (LoadContext->FilePathList);\r
120 FreePool (LoadContext->LoadOption);\r
121 if (LoadContext->OptionalData != NULL) {\r
122 FreePool (LoadContext->OptionalData);\r
123 }\r
124 FreePool (LoadContext);\r
125 break;\r
126\r
127 case BM_FILE_CONTEXT_SELECT:\r
128 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
129\r
130 if (!FileContext->IsRoot) {\r
131 FreePool (FileContext->DevicePath);\r
132 } else {\r
133 if (FileContext->FHandle != NULL) {\r
134 FileContext->FHandle->Close (FileContext->FHandle);\r
135 }\r
136 }\r
137\r
138 if (FileContext->FileName != NULL) {\r
139 FreePool (FileContext->FileName);\r
140 }\r
141 if (FileContext->Info != NULL) {\r
142 FreePool (FileContext->Info);\r
143 }\r
144 FreePool (FileContext);\r
145 break;\r
146\r
147 case BM_CONSOLE_CONTEXT_SELECT:\r
148 ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
149 FreePool (ConsoleContext->DevicePath);\r
150 FreePool (ConsoleContext);\r
151 break;\r
152\r
153 case BM_TERMINAL_CONTEXT_SELECT:\r
154 TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
155 FreePool (TerminalContext->DevicePath);\r
156 FreePool (TerminalContext);\r
157 break;\r
158\r
159 case BM_HANDLE_CONTEXT_SELECT:\r
160 HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
161 FreePool (HandleContext);\r
162 break;\r
163\r
164 case BM_LEGACY_DEV_CONTEXT_SELECT:\r
165 LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
166 FreePool (LegacyDevContext);\r
167\r
168 default:\r
169 break;\r
170 }\r
171\r
172 FreePool (MenuEntry->DisplayString);\r
173 if (MenuEntry->HelpString != NULL) {\r
174 FreePool (MenuEntry->HelpString);\r
175 }\r
176\r
177 FreePool (MenuEntry);\r
178}\r
179\r
180/**\r
181 Get the Menu Entry from the list in Menu Entry List.\r
182\r
183 If MenuNumber is great or equal to the number of Menu\r
184 Entry in the list, then ASSERT.\r
185\r
186 @param MenuOption The Menu Entry List to read the menu entry.\r
187 @param MenuNumber The index of Menu Entry.\r
188\r
189 @return The Menu Entry.\r
190\r
191**/\r
192BM_MENU_ENTRY *\r
193BOpt_GetMenuEntry (\r
194 BM_MENU_OPTION *MenuOption,\r
195 UINTN MenuNumber\r
196 )\r
197{\r
198 BM_MENU_ENTRY *NewMenuEntry;\r
199 UINTN Index;\r
200 LIST_ENTRY *List;\r
201\r
202 ASSERT (MenuNumber < MenuOption->MenuNumber);\r
203\r
204 List = MenuOption->Head.ForwardLink;\r
205 for (Index = 0; Index < MenuNumber; Index++) {\r
206 List = List->ForwardLink;\r
207 }\r
208\r
209 NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
210\r
211 return NewMenuEntry;\r
212}\r
213\r
214/**\r
215 This function build the FsOptionMenu list which records all\r
216 available file system in the system. They includes all instances\r
217 of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
218 and all type of legacy boot device.\r
219\r
220 @param CallbackData BMM context data\r
221\r
222 @retval EFI_SUCCESS Success find the file system\r
223 @retval EFI_OUT_OF_RESOURCES Can not create menu entry\r
224\r
225**/\r
226EFI_STATUS\r
227BOpt_FindFileSystem (\r
228 IN BMM_CALLBACK_DATA *CallbackData\r
229 )\r
230{\r
231 UINTN NoBlkIoHandles;\r
232 UINTN NoSimpleFsHandles;\r
233 UINTN NoLoadFileHandles;\r
234 EFI_HANDLE *BlkIoHandle;\r
235 EFI_HANDLE *SimpleFsHandle;\r
236 EFI_HANDLE *LoadFileHandle;\r
237 UINT16 *VolumeLabel;\r
238 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
239 UINTN Index;\r
240 EFI_STATUS Status;\r
241 BM_MENU_ENTRY *MenuEntry;\r
242 BM_FILE_CONTEXT *FileContext;\r
243 UINT16 *TempStr;\r
244 UINTN OptionNumber;\r
245 VOID *Buffer;\r
246 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
247 UINT16 DeviceType;\r
248 BBS_BBS_DEVICE_PATH BbsDevicePathNode;\r
249 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
250 BOOLEAN RemovableMedia;\r
251\r
252\r
253 NoSimpleFsHandles = 0;\r
254 NoLoadFileHandles = 0;\r
255 OptionNumber = 0;\r
256 InitializeListHead (&FsOptionMenu.Head);\r
257\r
258 //\r
259 // Locate Handles that support BlockIo protocol\r
260 //\r
261 Status = gBS->LocateHandleBuffer (\r
262 ByProtocol,\r
263 &gEfiBlockIoProtocolGuid,\r
264 NULL,\r
265 &NoBlkIoHandles,\r
266 &BlkIoHandle\r
267 );\r
268 if (!EFI_ERROR (Status)) {\r
269\r
270 for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
271 Status = gBS->HandleProtocol (\r
272 BlkIoHandle[Index],\r
273 &gEfiBlockIoProtocolGuid,\r
274 (VOID **) &BlkIo\r
275 );\r
276\r
277 if (EFI_ERROR (Status)) {\r
278 continue;\r
279 }\r
280\r
281 //\r
282 // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
283 //\r
284 if (BlkIo->Media->RemovableMedia) {\r
285 Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);\r
286 if (NULL == Buffer) {\r
287 FreePool (BlkIoHandle);\r
288 return EFI_OUT_OF_RESOURCES;\r
289 }\r
290\r
291 BlkIo->ReadBlocks (\r
292 BlkIo,\r
293 BlkIo->Media->MediaId,\r
294 0,\r
295 BlkIo->Media->BlockSize,\r
296 Buffer\r
297 );\r
298 FreePool (Buffer);\r
299 }\r
300 }\r
301 FreePool (BlkIoHandle);\r
302 }\r
303\r
304 //\r
305 // Locate Handles that support Simple File System protocol\r
306 //\r
307 Status = gBS->LocateHandleBuffer (\r
308 ByProtocol,\r
309 &gEfiSimpleFileSystemProtocolGuid,\r
310 NULL,\r
311 &NoSimpleFsHandles,\r
312 &SimpleFsHandle\r
313 );\r
314 if (!EFI_ERROR (Status)) {\r
315 //\r
316 // Find all the instances of the File System prototocol\r
317 //\r
318 for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
319 Status = gBS->HandleProtocol (\r
320 SimpleFsHandle[Index],\r
321 &gEfiBlockIoProtocolGuid,\r
322 (VOID **) &BlkIo\r
323 );\r
324 if (EFI_ERROR (Status)) {\r
325 //\r
326 // If no block IO exists assume it's NOT a removable media\r
327 //\r
328 RemovableMedia = FALSE;\r
329 } else {\r
330 //\r
331 // If block IO exists check to see if it's remobable media\r
332 //\r
333 RemovableMedia = BlkIo->Media->RemovableMedia;\r
334 }\r
335\r
336 //\r
337 // Allocate pool for this load option\r
338 //\r
339 MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
340 if (NULL == MenuEntry) {\r
341 FreePool (SimpleFsHandle);\r
342 return EFI_OUT_OF_RESOURCES;\r
343 }\r
344\r
345 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
346\r
347 FileContext->Handle = SimpleFsHandle[Index];\r
348 MenuEntry->OptionNumber = Index;\r
349 FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);\r
350 if (FileContext->FHandle == NULL) {\r
351 BOpt_DestroyMenuEntry (MenuEntry);\r
352 continue;\r
353 }\r
354\r
355 MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
356 FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
357 FileContext->FileName = EfiStrDuplicate (L"\\");\r
358 FileContext->DevicePath = FileDevicePath (\r
359 FileContext->Handle,\r
360 FileContext->FileName\r
361 );\r
362 FileContext->IsDir = TRUE;\r
363 FileContext->IsRoot = TRUE;\r
364 FileContext->IsRemovableMedia = RemovableMedia;\r
365 FileContext->IsLoadFile = FALSE;\r
366\r
367 //\r
368 // Get current file system's Volume Label\r
369 //\r
370 if (FileContext->Info == NULL) {\r
371 VolumeLabel = L"NO FILE SYSTEM INFO";\r
372 } else {\r
122d9317
ED
373 VolumeLabel = FileContext->Info->VolumeLabel;\r
374 if (*VolumeLabel == 0x0000) {\r
375 VolumeLabel = L"NO VOLUME LABEL";\r
5c08e117 376 }\r
377 }\r
378\r
379 TempStr = MenuEntry->HelpString;\r
380 MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
381 ASSERT (MenuEntry->DisplayString != NULL);\r
382 UnicodeSPrint (\r
383 MenuEntry->DisplayString,\r
384 MAX_CHAR,\r
385 L"%s, [%s]",\r
386 VolumeLabel,\r
387 TempStr\r
388 );\r
389 OptionNumber++;\r
390 InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
391 }\r
392 }\r
393\r
394 if (NoSimpleFsHandles != 0) {\r
395 FreePool (SimpleFsHandle);\r
396 }\r
397 //\r
398 // Searching for handles that support Load File protocol\r
399 //\r
400 Status = gBS->LocateHandleBuffer (\r
401 ByProtocol,\r
402 &gEfiLoadFileProtocolGuid,\r
403 NULL,\r
404 &NoLoadFileHandles,\r
405 &LoadFileHandle\r
406 );\r
407\r
408 if (!EFI_ERROR (Status)) {\r
409 for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
410 MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
411 if (NULL == MenuEntry) {\r
412 FreePool (LoadFileHandle);\r
413 return EFI_OUT_OF_RESOURCES;\r
414 }\r
415\r
416 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
417 FileContext->IsRemovableMedia = FALSE;\r
418 FileContext->IsLoadFile = TRUE;\r
419 FileContext->Handle = LoadFileHandle[Index];\r
420 FileContext->IsRoot = TRUE;\r
421\r
69533312 422 FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
423 FileContext->FileName = DevicePathToStr (FileContext->DevicePath);\r
5c08e117 424\r
425 MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
426\r
427 TempStr = MenuEntry->HelpString;\r
428 MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
429 ASSERT (MenuEntry->DisplayString != NULL);\r
430 UnicodeSPrint (\r
431 MenuEntry->DisplayString,\r
432 MAX_CHAR,\r
433 L"Load File [%s]",\r
434 TempStr\r
435 );\r
436\r
437 MenuEntry->OptionNumber = OptionNumber;\r
438 OptionNumber++;\r
439 InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
440 }\r
441 }\r
442\r
443 if (NoLoadFileHandles != 0) {\r
444 FreePool (LoadFileHandle);\r
445 }\r
446\r
447 //\r
448 // Add Legacy Boot Option Support Here\r
449 //\r
450 Status = gBS->LocateProtocol (\r
451 &gEfiLegacyBiosProtocolGuid,\r
452 NULL,\r
453 (VOID **) &LegacyBios\r
454 );\r
455 if (!EFI_ERROR (Status)) {\r
456\r
457 for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
458 MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
459 if (NULL == MenuEntry) {\r
460 return EFI_OUT_OF_RESOURCES;\r
461 }\r
462\r
463 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
464\r
465 FileContext->IsRemovableMedia = FALSE;\r
466 FileContext->IsLoadFile = TRUE;\r
467 FileContext->IsBootLegacy = TRUE;\r
468 DeviceType = (UINT16) Index;\r
469 BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
470 BbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
471 SetDevicePathNodeLength (\r
472 &BbsDevicePathNode.Header,\r
473 sizeof (BBS_BBS_DEVICE_PATH)\r
474 );\r
475 BbsDevicePathNode.DeviceType = DeviceType;\r
476 BbsDevicePathNode.StatusFlag = 0;\r
477 BbsDevicePathNode.String[0] = 0;\r
478 DevicePath = AppendDevicePathNode (\r
479 EndDevicePath,\r
480 (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
481 );\r
482\r
483 FileContext->DevicePath = DevicePath;\r
484 MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
485\r
486 TempStr = MenuEntry->HelpString;\r
487 MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
488 ASSERT (MenuEntry->DisplayString != NULL);\r
489 UnicodeSPrint (\r
490 MenuEntry->DisplayString,\r
491 MAX_CHAR,\r
492 L"Boot Legacy [%s]",\r
493 TempStr\r
494 );\r
495 MenuEntry->OptionNumber = OptionNumber;\r
496 OptionNumber++;\r
497 InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
498 }\r
499 }\r
500 //\r
501 // Remember how many file system options are here\r
502 //\r
503 FsOptionMenu.MenuNumber = OptionNumber;\r
504 return EFI_SUCCESS;\r
505}\r
506\r
507/**\r
508 Free resources allocated in Allocate Rountine.\r
509\r
510 @param FreeMenu Menu to be freed\r
511**/\r
512VOID\r
513BOpt_FreeMenu (\r
514 BM_MENU_OPTION *FreeMenu\r
515 )\r
516{\r
517 BM_MENU_ENTRY *MenuEntry;\r
518 while (!IsListEmpty (&FreeMenu->Head)) {\r
519 MenuEntry = CR (\r
520 FreeMenu->Head.ForwardLink,\r
521 BM_MENU_ENTRY,\r
522 Link,\r
523 BM_MENU_ENTRY_SIGNATURE\r
524 );\r
525 RemoveEntryList (&MenuEntry->Link);\r
526 BOpt_DestroyMenuEntry (MenuEntry);\r
527 }\r
22d1f978 528 FreeMenu->MenuNumber = 0;\r
5c08e117 529}\r
530\r
531/**\r
532 Find files under current directory\r
533 All files and sub-directories in current directory\r
534 will be stored in DirectoryMenu for future use.\r
535\r
536 @param CallbackData The BMM context data.\r
537 @param MenuEntry The Menu Entry.\r
538\r
539 @retval EFI_SUCCESS Get files from current dir successfully.\r
540 @return Other value if can't get files from current dir.\r
541\r
542**/\r
543EFI_STATUS\r
544BOpt_FindFiles (\r
545 IN BMM_CALLBACK_DATA *CallbackData,\r
546 IN BM_MENU_ENTRY *MenuEntry\r
547 )\r
548{\r
549 EFI_FILE_HANDLE NewDir;\r
550 EFI_FILE_HANDLE Dir;\r
551 EFI_FILE_INFO *DirInfo;\r
552 UINTN BufferSize;\r
553 UINTN DirBufferSize;\r
554 BM_MENU_ENTRY *NewMenuEntry;\r
555 BM_FILE_CONTEXT *FileContext;\r
556 BM_FILE_CONTEXT *NewFileContext;\r
557 UINTN Pass;\r
558 EFI_STATUS Status;\r
559 UINTN OptionNumber;\r
560\r
561 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
562 Dir = FileContext->FHandle;\r
563 OptionNumber = 0;\r
564 //\r
565 // Open current directory to get files from it\r
566 //\r
567 Status = Dir->Open (\r
568 Dir,\r
569 &NewDir,\r
570 FileContext->FileName,\r
571 EFI_FILE_READ_ONLY,\r
572 0\r
573 );\r
574 if (!FileContext->IsRoot) {\r
575 Dir->Close (Dir);\r
576 }\r
577\r
578 if (EFI_ERROR (Status)) {\r
579 return Status;\r
580 }\r
581\r
582 DirInfo = EfiLibFileInfo (NewDir);\r
583 if (DirInfo == NULL) {\r
584 return EFI_NOT_FOUND;\r
585 }\r
586\r
7ec9caab 587 if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
5c08e117 588 return EFI_INVALID_PARAMETER;\r
589 }\r
590\r
591 FileContext->DevicePath = FileDevicePath (\r
592 FileContext->Handle,\r
593 FileContext->FileName\r
594 );\r
595\r
596 DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
597 DirInfo = AllocateZeroPool (DirBufferSize);\r
598 if (DirInfo == NULL) {\r
599 return EFI_OUT_OF_RESOURCES;\r
600 }\r
601 //\r
602 // Get all files in current directory\r
603 // Pass 1 to get Directories\r
604 // Pass 2 to get files that are EFI images\r
605 //\r
606 for (Pass = 1; Pass <= 2; Pass++) {\r
607 NewDir->SetPosition (NewDir, 0);\r
608 for (;;) {\r
609 BufferSize = DirBufferSize;\r
610 Status = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
611 if (EFI_ERROR (Status) || BufferSize == 0) {\r
612 break;\r
613 }\r
614\r
7ec9caab 615 if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||\r
616 ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)\r
5c08e117 617 ) {\r
618 //\r
619 // Pass 1 is for Directories\r
620 // Pass 2 is for file names\r
621 //\r
622 continue;\r
623 }\r
624\r
7ec9caab 625 if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) {\r
5c08e117 626 //\r
627 // Slip file unless it is a directory entry or a .EFI file\r
628 //\r
629 continue;\r
630 }\r
631\r
632 NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
633 if (NULL == NewMenuEntry) {\r
634 return EFI_OUT_OF_RESOURCES;\r
635 }\r
636\r
637 NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
638 NewFileContext->Handle = FileContext->Handle;\r
639 NewFileContext->FileName = BOpt_AppendFileName (\r
640 FileContext->FileName,\r
641 DirInfo->FileName\r
642 );\r
643 NewFileContext->FHandle = NewDir;\r
644 NewFileContext->DevicePath = FileDevicePath (\r
645 NewFileContext->Handle,\r
646 NewFileContext->FileName\r
647 );\r
648 NewMenuEntry->HelpString = NULL;\r
649\r
650 MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
651 CallbackData,\r
652 FileOptionStrDepository\r
653 );\r
654\r
655 NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
656\r
657 if (NewFileContext->IsDir) {\r
658 BufferSize = StrLen (DirInfo->FileName) * 2 + 6;\r
659 NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
660\r
661 UnicodeSPrint (\r
662 NewMenuEntry->DisplayString,\r
663 BufferSize,\r
664 L"<%s>",\r
665 DirInfo->FileName\r
666 );\r
667\r
668 } else {\r
669 NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
670 }\r
671\r
672 NewFileContext->IsRoot = FALSE;\r
673 NewFileContext->IsLoadFile = FALSE;\r
674 NewFileContext->IsRemovableMedia = FALSE;\r
675\r
676 NewMenuEntry->OptionNumber = OptionNumber;\r
677 OptionNumber++;\r
678 InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
679 }\r
680 }\r
681\r
682 DirectoryMenu.MenuNumber = OptionNumber;\r
683 FreePool (DirInfo);\r
684 return EFI_SUCCESS;\r
685}\r
686\r
687/**\r
688 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
689\r
690 @retval EFI_SUCCESS The function complete successfully.\r
691 @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
692\r
693**/\r
694EFI_STATUS\r
695BOpt_GetLegacyOptions (\r
696 VOID\r
697 )\r
698{\r
699 BM_MENU_ENTRY *NewMenuEntry;\r
700 BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;\r
701 EFI_STATUS Status;\r
702 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
703 UINT16 HddCount;\r
704 HDD_INFO *HddInfo;\r
705 UINT16 BbsCount;\r
706 BBS_TABLE *BbsTable;\r
22d1f978 707 UINT16 Index;\r
5c08e117 708 CHAR16 DescString[100];\r
709 UINTN FDNum;\r
710 UINTN HDNum;\r
711 UINTN CDNum;\r
712 UINTN NETNum;\r
713 UINTN BEVNum;\r
714\r
715 NewMenuEntry = NULL;\r
716 HddInfo = NULL;\r
717 BbsTable = NULL;\r
718 BbsCount = 0;\r
719\r
720 //\r
721 // Initialize Bbs Table Context from BBS info data\r
722 //\r
723 InitializeListHead (&LegacyFDMenu.Head);\r
724 InitializeListHead (&LegacyHDMenu.Head);\r
725 InitializeListHead (&LegacyCDMenu.Head);\r
726 InitializeListHead (&LegacyNETMenu.Head);\r
727 InitializeListHead (&LegacyBEVMenu.Head);\r
728\r
729 Status = gBS->LocateProtocol (\r
730 &gEfiLegacyBiosProtocolGuid,\r
731 NULL,\r
732 (VOID **) &LegacyBios\r
733 );\r
734 if (!EFI_ERROR (Status)) {\r
735 Status = LegacyBios->GetBbsInfo (\r
736 LegacyBios,\r
737 &HddCount,\r
738 &HddInfo,\r
739 &BbsCount,\r
740 &BbsTable\r
741 );\r
742 if (EFI_ERROR (Status)) {\r
743 return Status;\r
744 }\r
745 }\r
746\r
747 FDNum = 0;\r
748 HDNum = 0;\r
749 CDNum = 0;\r
750 NETNum = 0;\r
751 BEVNum = 0;\r
752\r
753 for (Index = 0; Index < BbsCount; Index++) {\r
754 if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
755 (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
756 ) {\r
757 continue;\r
758 }\r
759\r
760 NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
761 if (NULL == NewMenuEntry) {\r
762 break;\r
763 }\r
764\r
765 NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
22d1f978
RN
766 NewLegacyDevContext->BbsEntry = &BbsTable[Index];\r
767 NewLegacyDevContext->BbsIndex = Index;\r
5c08e117 768 NewLegacyDevContext->BbsCount = BbsCount;\r
769 BdsBuildLegacyDevNameString (\r
770 &BbsTable[Index],\r
771 Index,\r
772 sizeof (DescString),\r
773 DescString\r
774 );\r
22d1f978 775 NewLegacyDevContext->Description = AllocateCopyPool (StrSize (DescString), DescString);\r
5c08e117 776 if (NULL == NewLegacyDevContext->Description) {\r
777 break;\r
778 }\r
779\r
5c08e117 780 NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
781 NewMenuEntry->HelpString = NULL;\r
782\r
783 switch (BbsTable[Index].DeviceType) {\r
784 case BBS_FLOPPY:\r
785 InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
786 FDNum++;\r
787 break;\r
788\r
789 case BBS_HARDDISK:\r
790 InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
791 HDNum++;\r
792 break;\r
793\r
794 case BBS_CDROM:\r
795 InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
796 CDNum++;\r
797 break;\r
798\r
799 case BBS_EMBED_NETWORK:\r
800 InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
801 NETNum++;\r
802 break;\r
803\r
804 case BBS_BEV_DEVICE:\r
805 InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
806 BEVNum++;\r
807 break;\r
808 }\r
809 }\r
810\r
811 if (Index != BbsCount) {\r
812 BOpt_FreeLegacyOptions ();\r
813 return EFI_OUT_OF_RESOURCES;\r
814 }\r
815\r
816 LegacyFDMenu.MenuNumber = FDNum;\r
817 LegacyHDMenu.MenuNumber = HDNum;\r
818 LegacyCDMenu.MenuNumber = CDNum;\r
819 LegacyNETMenu.MenuNumber = NETNum;\r
820 LegacyBEVMenu.MenuNumber = BEVNum;\r
821 return EFI_SUCCESS;\r
822}\r
823\r
824/**\r
825 Free out resouce allocated from Legacy Boot Options.\r
826\r
827**/\r
828VOID\r
829BOpt_FreeLegacyOptions (\r
830 VOID\r
831 )\r
832{\r
833 BOpt_FreeMenu (&LegacyFDMenu);\r
834 BOpt_FreeMenu (&LegacyHDMenu);\r
835 BOpt_FreeMenu (&LegacyCDMenu);\r
836 BOpt_FreeMenu (&LegacyNETMenu);\r
837 BOpt_FreeMenu (&LegacyBEVMenu);\r
838}\r
839\r
840/**\r
841\r
842 Build the BootOptionMenu according to BootOrder Variable.\r
843 This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
844\r
845 @param CallbackData The BMM context data.\r
846\r
847 @return EFI_NOT_FOUND Fail to find "BootOrder" variable.\r
848 @return EFI_SUCESS Success build boot option menu.\r
849\r
850**/\r
851EFI_STATUS\r
852BOpt_GetBootOptions (\r
853 IN BMM_CALLBACK_DATA *CallbackData\r
854 )\r
855{\r
856 UINTN Index;\r
857 UINT16 BootString[10];\r
858 UINT8 *LoadOptionFromVar;\r
859 UINT8 *LoadOption;\r
860 UINTN BootOptionSize;\r
861 BOOLEAN BootNextFlag;\r
862 UINT16 *BootOrderList;\r
863 UINTN BootOrderListSize;\r
864 UINT16 *BootNext;\r
865 UINTN BootNextSize;\r
866 BM_MENU_ENTRY *NewMenuEntry;\r
867 BM_LOAD_CONTEXT *NewLoadContext;\r
868 UINT8 *LoadOptionPtr;\r
869 UINTN StringSize;\r
870 UINTN OptionalDataSize;\r
871 UINT8 *LoadOptionEnd;\r
872 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
873 UINTN MenuCount;\r
874 UINT8 *Ptr;\r
0a6f4824 875\r
5c08e117 876 MenuCount = 0;\r
877 BootOrderListSize = 0;\r
878 BootNextSize = 0;\r
879 BootOrderList = NULL;\r
880 BootNext = NULL;\r
881 LoadOptionFromVar = NULL;\r
882 BOpt_FreeMenu (&BootOptionMenu);\r
883 InitializeListHead (&BootOptionMenu.Head);\r
884\r
885 //\r
886 // Get the BootOrder from the Var\r
887 //\r
888 BootOrderList = BdsLibGetVariableAndSize (\r
889 L"BootOrder",\r
890 &gEfiGlobalVariableGuid,\r
891 &BootOrderListSize\r
892 );\r
893 if (BootOrderList == NULL) {\r
894 return EFI_NOT_FOUND;\r
895 }\r
0a6f4824 896\r
5c08e117 897 //\r
898 // Get the BootNext from the Var\r
899 //\r
900 BootNext = BdsLibGetVariableAndSize (\r
901 L"BootNext",\r
902 &gEfiGlobalVariableGuid,\r
903 &BootNextSize\r
904 );\r
905\r
906 if (BootNext != NULL) {\r
907 if (BootNextSize != sizeof (UINT16)) {\r
908 FreePool (BootNext);\r
909 BootNext = NULL;\r
910 }\r
911 }\r
912\r
913 for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
914 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
915 //\r
916 // Get all loadoptions from the VAR\r
917 //\r
918 LoadOptionFromVar = BdsLibGetVariableAndSize (\r
919 BootString,\r
920 &gEfiGlobalVariableGuid,\r
921 &BootOptionSize\r
922 );\r
923 if (LoadOptionFromVar == NULL) {\r
924 continue;\r
925 }\r
926\r
927 LoadOption = AllocateZeroPool (BootOptionSize);\r
928 if (LoadOption == NULL) {\r
929 continue;\r
930 }\r
931\r
932 CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
933 FreePool (LoadOptionFromVar);\r
934\r
935 if (BootNext != NULL) {\r
936 BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
937 } else {\r
938 BootNextFlag = FALSE;\r
939 }\r
940\r
941 if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
942 FreePool (LoadOption);\r
943 continue;\r
944 }\r
945 //\r
946 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
947 // the buffer allocated already should be freed before returning.\r
948 //\r
949 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
950 if (NULL == NewMenuEntry) {\r
951 return EFI_OUT_OF_RESOURCES;\r
952 }\r
953\r
954 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
955\r
956 LoadOptionPtr = LoadOption;\r
957 LoadOptionEnd = LoadOption + BootOptionSize;\r
958\r
959 NewMenuEntry->OptionNumber = BootOrderList[Index];\r
960 NewLoadContext->LoadOptionModified = FALSE;\r
961 NewLoadContext->Deleted = FALSE;\r
962 NewLoadContext->IsBootNext = BootNextFlag;\r
963\r
964 //\r
965 // Is a Legacy Device?\r
966 //\r
967 Ptr = (UINT8 *) LoadOption;\r
968\r
969 //\r
970 // Attribute = *(UINT32 *)Ptr;\r
971 //\r
972 Ptr += sizeof (UINT32);\r
973\r
974 //\r
975 // FilePathSize = *(UINT16 *)Ptr;\r
976 //\r
977 Ptr += sizeof (UINT16);\r
978\r
979 //\r
980 // Description = (CHAR16 *)Ptr;\r
981 //\r
982 Ptr += StrSize ((CHAR16 *) Ptr);\r
983\r
984 //\r
985 // Now Ptr point to Device Path\r
986 //\r
987 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
988 if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
989 NewLoadContext->IsLegacy = TRUE;\r
990 } else {\r
991 NewLoadContext->IsLegacy = FALSE;\r
992 }\r
993 //\r
994 // LoadOption is a pointer type of UINT8\r
995 // for easy use with following LOAD_OPTION\r
996 // embedded in this struct\r
997 //\r
998 NewLoadContext->LoadOption = LoadOption;\r
999 NewLoadContext->LoadOptionSize = BootOptionSize;\r
1000\r
1001 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
1002 NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
1003\r
1004 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
1005\r
1006 LoadOptionPtr += sizeof (UINT32);\r
1007\r
1008 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
1009 LoadOptionPtr += sizeof (UINT16);\r
0a6f4824 1010\r
5caec787 1011 StringSize = StrSize((UINT16*)LoadOptionPtr);\r
9aa7ba01 1012\r
49264dac 1013 NewLoadContext->Description = AllocateCopyPool (StrSize((UINT16*)LoadOptionPtr), LoadOptionPtr);\r
5c08e117 1014 ASSERT (NewLoadContext->Description != NULL);\r
49264dac 1015\r
5c08e117 1016 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
1017\r
1018 LoadOptionPtr += StringSize;\r
1019\r
1020 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
1021 ASSERT (NewLoadContext->FilePathList != NULL);\r
1022 CopyMem (\r
1023 NewLoadContext->FilePathList,\r
1024 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
1025 NewLoadContext->FilePathListLength\r
1026 );\r
1027\r
1028 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
1029 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
1030 CallbackData,\r
1031 BootOptionStrDepository\r
1032 );\r
1033 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
1034 CallbackData,\r
1035 BootOptionHelpStrDepository\r
1036 );\r
1037 LoadOptionPtr += NewLoadContext->FilePathListLength;\r
1038\r
1039 if (LoadOptionPtr < LoadOptionEnd) {\r
1040 OptionalDataSize = BootOptionSize -\r
1041 sizeof (UINT32) -\r
1042 sizeof (UINT16) -\r
1043 StringSize -\r
1044 NewLoadContext->FilePathListLength;\r
1045\r
1046 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
1047 ASSERT (NewLoadContext->OptionalData != NULL);\r
1048 CopyMem (\r
1049 NewLoadContext->OptionalData,\r
1050 LoadOptionPtr,\r
1051 OptionalDataSize\r
1052 );\r
1053\r
1054 NewLoadContext->OptionalDataSize = OptionalDataSize;\r
1055 }\r
1056\r
1057 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
1058 MenuCount++;\r
1059 }\r
1060\r
1061 if (BootNext != NULL) {\r
1062 FreePool (BootNext);\r
1063 }\r
1064 if (BootOrderList != NULL) {\r
1065 FreePool (BootOrderList);\r
1066 }\r
1067 BootOptionMenu.MenuNumber = MenuCount;\r
1068 return EFI_SUCCESS;\r
1069}\r
1070\r
1071/**\r
1072\r
1073 Append file name to existing file name.\r
1074\r
1075 @param Str1 The existing file name\r
1076 @param Str2 The file name to be appended\r
1077\r
1078 @return Allocate a new string to hold the appended result.\r
1079 Caller is responsible to free the returned string.\r
1080\r
1081**/\r
1082CHAR16 *\r
1083BOpt_AppendFileName (\r
1084 IN CHAR16 *Str1,\r
1085 IN CHAR16 *Str2\r
1086 )\r
1087{\r
1088 UINTN Size1;\r
1089 UINTN Size2;\r
49264dac 1090 UINTN MaxLen;\r
5c08e117 1091 CHAR16 *Str;\r
1092 CHAR16 *TmpStr;\r
1093 CHAR16 *Ptr;\r
1094 CHAR16 *LastSlash;\r
1095\r
1096 Size1 = StrSize (Str1);\r
1097 Size2 = StrSize (Str2);\r
49264dac 1098 MaxLen = (Size1 + Size2 + sizeof (CHAR16)) / sizeof (CHAR16);\r
a3c9617e 1099 Str = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
5c08e117 1100 ASSERT (Str != NULL);\r
1101\r
0a6f4824 1102 TmpStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
5c08e117 1103 ASSERT (TmpStr != NULL);\r
1104\r
a3c9617e 1105 StrCatS (Str, MaxLen, Str1);\r
5c08e117 1106 if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
49264dac 1107 StrCatS (Str, MaxLen, L"\\");\r
5c08e117 1108 }\r
1109\r
49264dac 1110 StrCatS (Str, MaxLen, Str2);\r
5c08e117 1111\r
1112 Ptr = Str;\r
1113 LastSlash = Str;\r
1114 while (*Ptr != 0) {\r
1115 if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {\r
1116 //\r
1117 // Convert "\Name\..\" to "\"\r
1118 // DO NOT convert the .. if it is at the end of the string. This will\r
1119 // break the .. behavior in changing directories.\r
1120 //\r
1121\r
1122 //\r
0a6f4824 1123 // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings\r
5c08e117 1124 // that overlap.\r
1125 //\r
49264dac 1126 StrCpyS (TmpStr, MaxLen, Ptr + 3);\r
4ff5fd20 1127 StrCpyS (LastSlash, MaxLen - ((UINTN) LastSlash - (UINTN) Str) / sizeof (CHAR16), TmpStr);\r
5c08e117 1128 Ptr = LastSlash;\r
1129 } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
1130 //\r
1131 // Convert a "\.\" to a "\"\r
1132 //\r
1133\r
1134 //\r
0a6f4824 1135 // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings\r
5c08e117 1136 // that overlap.\r
1137 //\r
49264dac 1138 StrCpyS (TmpStr, MaxLen, Ptr + 2);\r
4ff5fd20 1139 StrCpyS (Ptr, MaxLen - ((UINTN) Ptr - (UINTN) Str) / sizeof (CHAR16), TmpStr);\r
5c08e117 1140 Ptr = LastSlash;\r
1141 } else if (*Ptr == '\\') {\r
1142 LastSlash = Ptr;\r
1143 }\r
1144\r
1145 Ptr++;\r
1146 }\r
1147\r
1148 FreePool (TmpStr);\r
0a6f4824 1149\r
5c08e117 1150 return Str;\r
1151}\r
1152\r
1153/**\r
1154\r
1155 Check whether current FileName point to a valid\r
1156 Efi Image File.\r
1157\r
1158 @param FileName File need to be checked.\r
1159\r
1160 @retval TRUE Is Efi Image\r
1161 @retval FALSE Not a valid Efi Image\r
1162\r
1163**/\r
1164BOOLEAN\r
1165BOpt_IsEfiImageName (\r
1166 IN UINT16 *FileName\r
1167 )\r
1168{\r
1169 //\r
1170 // Search for ".efi" extension\r
1171 //\r
1172 while (*FileName != L'\0') {\r
1173 if (FileName[0] == '.') {\r
1174 if (FileName[1] == 'e' || FileName[1] == 'E') {\r
1175 if (FileName[2] == 'f' || FileName[2] == 'F') {\r
1176 if (FileName[3] == 'i' || FileName[3] == 'I') {\r
1177 return TRUE;\r
1178 } else if (FileName[3] == 0x0000) {\r
1179 return FALSE;\r
1180 }\r
1181 } else if (FileName[2] == 0x0000) {\r
1182 return FALSE;\r
1183 }\r
1184 } else if (FileName[1] == 0x0000) {\r
1185 return FALSE;\r
1186 }\r
1187 }\r
1188\r
1189 FileName += 1;\r
1190 }\r
1191\r
1192 return FALSE;\r
1193}\r
1194\r
5c08e117 1195\r
5c08e117 1196\r
1197/**\r
1198\r
1199 Find drivers that will be added as Driver#### variables from handles\r
1200 in current system environment\r
1201 All valid handles in the system except those consume SimpleFs, LoadFile\r
1202 are stored in DriverMenu for future use.\r
1203\r
1204 @retval EFI_SUCCESS The function complets successfully.\r
1205 @return Other value if failed to build the DriverMenu.\r
1206\r
1207**/\r
1208EFI_STATUS\r
1209BOpt_FindDrivers (\r
1210 VOID\r
1211 )\r
1212{\r
1213 UINTN NoDevicePathHandles;\r
1214 EFI_HANDLE *DevicePathHandle;\r
1215 UINTN Index;\r
1216 EFI_STATUS Status;\r
1217 BM_MENU_ENTRY *NewMenuEntry;\r
1218 BM_HANDLE_CONTEXT *NewHandleContext;\r
1219 EFI_HANDLE CurHandle;\r
1220 UINTN OptionNumber;\r
1221 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
1222 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
1223\r
1224 SimpleFs = NULL;\r
1225 LoadFile = NULL;\r
1226\r
1227 InitializeListHead (&DriverMenu.Head);\r
1228\r
1229 //\r
1230 // At first, get all handles that support Device Path\r
1231 // protocol which is the basic requirement for\r
1232 // Driver####\r
1233 //\r
1234 Status = gBS->LocateHandleBuffer (\r
1235 ByProtocol,\r
1236 &gEfiDevicePathProtocolGuid,\r
1237 NULL,\r
1238 &NoDevicePathHandles,\r
1239 &DevicePathHandle\r
1240 );\r
1241 if (EFI_ERROR (Status)) {\r
1242 return Status;\r
1243 }\r
1244\r
1245 OptionNumber = 0;\r
1246 for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
1247 CurHandle = DevicePathHandle[Index];\r
1248\r
1249 Status = gBS->HandleProtocol (\r
1250 CurHandle,\r
1251 &gEfiSimpleFileSystemProtocolGuid,\r
1252 (VOID **) &SimpleFs\r
1253 );\r
1254 if (Status == EFI_SUCCESS) {\r
1255 continue;\r
1256 }\r
1257\r
1258 Status = gBS->HandleProtocol (\r
1259 CurHandle,\r
1260 &gEfiLoadFileProtocolGuid,\r
1261 (VOID **) &LoadFile\r
1262 );\r
1263 if (Status == EFI_SUCCESS) {\r
1264 continue;\r
1265 }\r
1266\r
1267 NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
1268 if (NULL == NewMenuEntry) {\r
1269 FreePool (DevicePathHandle);\r
1270 return EFI_OUT_OF_RESOURCES;\r
1271 }\r
1272\r
1273 NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
1274 NewHandleContext->Handle = CurHandle;\r
1275 NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);\r
1276 NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
1277 NewMenuEntry->HelpString = NULL;\r
1278 NewMenuEntry->OptionNumber = OptionNumber;\r
1279 OptionNumber++;\r
1280 InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
1281\r
1282 }\r
1283\r
1284 if (DevicePathHandle != NULL) {\r
1285 FreePool (DevicePathHandle);\r
1286 }\r
1287\r
1288 DriverMenu.MenuNumber = OptionNumber;\r
1289 return EFI_SUCCESS;\r
1290}\r
1291\r
1292/**\r
1293\r
1294 Get the Option Number that has not been allocated for use.\r
1295\r
a5c3c546 1296 @param Type The type of Option.\r
1297\r
5c08e117 1298 @return The available Option Number.\r
1299\r
1300**/\r
1301UINT16\r
a5c3c546 1302BOpt_GetOptionNumber (\r
1303 CHAR16 *Type\r
5c08e117 1304 )\r
1305{\r
a5c3c546 1306 UINT16 *OrderList;\r
1307 UINTN OrderListSize;\r
5c08e117 1308 UINTN Index;\r
a5c3c546 1309 CHAR16 StrTemp[20];\r
5c08e117 1310 UINT16 *OptionBuffer;\r
a5c3c546 1311 UINT16 OptionNumber;\r
5c08e117 1312 UINTN OptionSize;\r
1313\r
a5c3c546 1314 OrderListSize = 0;\r
1315 OrderList = NULL;\r
1316 OptionNumber = 0;\r
c6498c1d 1317 Index = 0;\r
5c08e117 1318\r
a5c3c546 1319 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);\r
5c08e117 1320\r
a5c3c546 1321 OrderList = BdsLibGetVariableAndSize (\r
5c08e117 1322 StrTemp,\r
1323 &gEfiGlobalVariableGuid,\r
a5c3c546 1324 &OrderListSize\r
5c08e117 1325 );\r
ce5fad41 1326\r
a5c3c546 1327 for (OptionNumber = 0; ; OptionNumber++) {\r
c6498c1d 1328 if (OrderList != NULL) {\r
1329 for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {\r
1330 if (OptionNumber == OrderList[Index]) {\r
1331 break;\r
1332 }\r
5c08e117 1333 }\r
1334 }\r
a5c3c546 1335\r
1336 if (Index < OrderListSize / sizeof (UINT16)) {\r
1337 //\r
1338 // The OptionNumber occurs in the OrderList, continue to use next one\r
1339 //\r
1340 continue;\r
1341 }\r
1342 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber);\r
1343 DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp));\r
1344 OptionBuffer = BdsLibGetVariableAndSize (\r
1345 StrTemp,\r
1346 &gEfiGlobalVariableGuid,\r
1347 &OptionSize\r
1348 );\r
1349 if (NULL == OptionBuffer) {\r
1350 //\r
1351 // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it\r
1352 //\r
1353 break;\r
1354 }\r
5c08e117 1355 }\r
1356\r
a5c3c546 1357 return OptionNumber;\r
5c08e117 1358}\r
1359\r
1360/**\r
1361\r
a5c3c546 1362 Get the Option Number for Boot#### that does not used.\r
5c08e117 1363\r
a5c3c546 1364 @return The available Option Number.\r
5c08e117 1365\r
1366**/\r
1367UINT16\r
a5c3c546 1368BOpt_GetBootOptionNumber (\r
5c08e117 1369 VOID\r
1370 )\r
1371{\r
a5c3c546 1372 return BOpt_GetOptionNumber (L"Boot");\r
1373}\r
5c08e117 1374\r
a5c3c546 1375/**\r
5c08e117 1376\r
a5c3c546 1377 Get the Option Number for Driver#### that does not used.\r
5c08e117 1378\r
a5c3c546 1379 @return The unused Option Number.\r
5c08e117 1380\r
a5c3c546 1381**/\r
1382UINT16\r
1383BOpt_GetDriverOptionNumber (\r
1384 VOID\r
1385 )\r
1386{\r
1387 return BOpt_GetOptionNumber (L"Driver");\r
5c08e117 1388}\r
1389\r
1390/**\r
1391\r
1392 Build up all DriverOptionMenu\r
1393\r
1394 @param CallbackData The BMM context data.\r
1395\r
1396 @retval EFI_SUCESS The functin completes successfully.\r
1397 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
1398 @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.\r
1399\r
1400**/\r
1401EFI_STATUS\r
1402BOpt_GetDriverOptions (\r
1403 IN BMM_CALLBACK_DATA *CallbackData\r
1404 )\r
1405{\r
1406 UINTN Index;\r
1407 UINT16 DriverString[12];\r
1408 UINT8 *LoadOptionFromVar;\r
1409 UINT8 *LoadOption;\r
1410 UINTN DriverOptionSize;\r
1411\r
1412 UINT16 *DriverOrderList;\r
1413 UINTN DriverOrderListSize;\r
1414 BM_MENU_ENTRY *NewMenuEntry;\r
1415 BM_LOAD_CONTEXT *NewLoadContext;\r
1416 UINT8 *LoadOptionPtr;\r
1417 UINTN StringSize;\r
1418 UINTN OptionalDataSize;\r
1419 UINT8 *LoadOptionEnd;\r
1420\r
1421 DriverOrderListSize = 0;\r
1422 DriverOrderList = NULL;\r
1423 DriverOptionSize = 0;\r
1424 LoadOptionFromVar = NULL;\r
1425 BOpt_FreeMenu (&DriverOptionMenu);\r
1426 InitializeListHead (&DriverOptionMenu.Head);\r
1427 //\r
1428 // Get the DriverOrder from the Var\r
1429 //\r
1430 DriverOrderList = BdsLibGetVariableAndSize (\r
1431 L"DriverOrder",\r
1432 &gEfiGlobalVariableGuid,\r
1433 &DriverOrderListSize\r
1434 );\r
1435 if (DriverOrderList == NULL) {\r
1436 return EFI_NOT_FOUND;\r
1437 }\r
0a6f4824 1438\r
5c08e117 1439 for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
1440 UnicodeSPrint (\r
1441 DriverString,\r
1442 sizeof (DriverString),\r
1443 L"Driver%04x",\r
1444 DriverOrderList[Index]\r
1445 );\r
1446 //\r
1447 // Get all loadoptions from the VAR\r
1448 //\r
1449 LoadOptionFromVar = BdsLibGetVariableAndSize (\r
1450 DriverString,\r
1451 &gEfiGlobalVariableGuid,\r
1452 &DriverOptionSize\r
1453 );\r
1454 if (LoadOptionFromVar == NULL) {\r
1455 continue;\r
1456 }\r
1457\r
1458 LoadOption = AllocateZeroPool (DriverOptionSize);\r
1459 if (LoadOption == NULL) {\r
1460 continue;\r
1461 }\r
1462\r
1463 CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
1464 FreePool (LoadOptionFromVar);\r
1465\r
1466 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
1467 if (NULL == NewMenuEntry) {\r
1468 return EFI_OUT_OF_RESOURCES;\r
1469 }\r
1470\r
1471 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1472 LoadOptionPtr = LoadOption;\r
1473 LoadOptionEnd = LoadOption + DriverOptionSize;\r
1474 NewMenuEntry->OptionNumber = DriverOrderList[Index];\r
1475 NewLoadContext->LoadOptionModified = FALSE;\r
1476 NewLoadContext->Deleted = FALSE;\r
1477 NewLoadContext->IsLegacy = FALSE;\r
1478\r
1479 //\r
1480 // LoadOption is a pointer type of UINT8\r
1481 // for easy use with following LOAD_OPTION\r
1482 // embedded in this struct\r
1483 //\r
1484 NewLoadContext->LoadOption = LoadOption;\r
1485 NewLoadContext->LoadOptionSize = DriverOptionSize;\r
1486\r
1487 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
1488 NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
1489\r
1490 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
1491\r
1492 LoadOptionPtr += sizeof (UINT32);\r
1493\r
1494 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
1495 LoadOptionPtr += sizeof (UINT16);\r
1496\r
1497 StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
1498 NewLoadContext->Description = AllocateZeroPool (StringSize);\r
1499 ASSERT (NewLoadContext->Description != NULL);\r
1500 CopyMem (\r
1501 NewLoadContext->Description,\r
1502 (UINT16 *) LoadOptionPtr,\r
1503 StringSize\r
1504 );\r
1505 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
1506\r
1507 LoadOptionPtr += StringSize;\r
1508\r
1509 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
1510 ASSERT (NewLoadContext->FilePathList != NULL);\r
1511 CopyMem (\r
1512 NewLoadContext->FilePathList,\r
1513 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
1514 NewLoadContext->FilePathListLength\r
1515 );\r
1516\r
1517 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
1518 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
1519 CallbackData,\r
1520 DriverOptionStrDepository\r
1521 );\r
1522 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
1523 CallbackData,\r
1524 DriverOptionHelpStrDepository\r
1525 );\r
1526 LoadOptionPtr += NewLoadContext->FilePathListLength;\r
1527\r
1528 if (LoadOptionPtr < LoadOptionEnd) {\r
1529 OptionalDataSize = DriverOptionSize -\r
1530 sizeof (UINT32) -\r
1531 sizeof (UINT16) -\r
1532 StringSize -\r
1533 NewLoadContext->FilePathListLength;\r
1534\r
1535 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
1536 ASSERT (NewLoadContext->OptionalData != NULL);\r
1537 CopyMem (\r
1538 NewLoadContext->OptionalData,\r
1539 LoadOptionPtr,\r
1540 OptionalDataSize\r
1541 );\r
1542\r
1543 NewLoadContext->OptionalDataSize = OptionalDataSize;\r
1544 }\r
1545\r
1546 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
1547\r
1548 }\r
1549\r
1550 if (DriverOrderList != NULL) {\r
1551 FreePool (DriverOrderList);\r
1552 }\r
1553 DriverOptionMenu.MenuNumber = Index;\r
1554 return EFI_SUCCESS;\r
1555\r
1556}\r
1557\r
be9304f3
ED
1558/**\r
1559 Get option number according to Boot#### and BootOrder variable.\r
1560 The value is saved as #### + 1.\r
1561\r
1562 @param CallbackData The BMM context data.\r
1563**/\r
1564VOID\r
1565GetBootOrder (\r
1566 IN BMM_CALLBACK_DATA *CallbackData\r
1567 )\r
1568{\r
1569 BMM_FAKE_NV_DATA *BmmConfig;\r
1570 UINT16 Index;\r
1571 UINT16 OptionOrderIndex;\r
1572 UINTN DeviceType;\r
1573 BM_MENU_ENTRY *NewMenuEntry;\r
1574 BM_LOAD_CONTEXT *NewLoadContext;\r
1575\r
1576 ASSERT (CallbackData != NULL);\r
1577\r
1578 DeviceType = (UINTN) -1;\r
1579 BmmConfig = &CallbackData->BmmFakeNvData;\r
1580 ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));\r
1581\r
1582 for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&\r
1583 (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));\r
1584 Index++) {\r
1585 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
1586 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1587\r
1588 if (NewLoadContext->IsLegacy) {\r
1589 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {\r
1590 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;\r
1591 } else {\r
1592 //\r
1593 // Only show one legacy boot option for the same device type\r
1594 // assuming the boot options are grouped by the device type\r
1595 //\r
1596 continue;\r
1597 }\r
1598 }\r
1599 BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
1600 }\r
1601}\r
1602\r
1603/**\r
1604 According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV\r
1605 devices list .\r
1606\r
1607 @param CallbackData The BMM context data.\r
1608**/\r
1609VOID\r
1610GetLegacyDeviceOrder (\r
1611 IN BMM_CALLBACK_DATA *CallbackData\r
1612 )\r
1613{\r
1614 UINTN Index;\r
1615 UINTN OptionIndex;\r
720624cc 1616 UINT16 PageIdList[5];\r
0a6f4824 1617 UINTN PageNum;\r
be9304f3 1618 UINTN VarSize;\r
0a6f4824
LG
1619 UINT8 *VarData;\r
1620 UINT8 *WorkingVarData;\r
be9304f3 1621 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
0a6f4824
LG
1622 UINT16 VarDevOrder;\r
1623 UINT8 *DisMap;\r
be9304f3
ED
1624 BM_MENU_OPTION *OptionMenu;\r
1625 BBS_TYPE BbsType;\r
1626 UINT8 *LegacyOrder;\r
0a6f4824 1627 UINT8 *OldData;\r
be9304f3
ED
1628 UINTN Pos;\r
1629 UINTN Bit;\r
0a6f4824 1630\r
be9304f3 1631 ASSERT (CallbackData != NULL);\r
720624cc
ED
1632\r
1633 PageIdList[0] = FORM_SET_FD_ORDER_ID;\r
1634 PageIdList[1] = FORM_SET_HD_ORDER_ID;\r
1635 PageIdList[2] = FORM_SET_CD_ORDER_ID;\r
1636 PageIdList[3] = FORM_SET_NET_ORDER_ID;\r
1637 PageIdList[4] = FORM_SET_BEV_ORDER_ID;\r
be9304f3
ED
1638 OptionMenu = NULL;\r
1639 BbsType = 0;\r
1640 LegacyOrder = NULL;\r
1641 OldData = NULL;\r
1642 DisMap = ZeroMem (CallbackData->BmmFakeNvData.DisableMap, sizeof (CallbackData->BmmFakeNvData.DisableMap));\r
bdb898a5 1643 PageNum = ARRAY_SIZE (PageIdList);\r
be9304f3
ED
1644 VarData = BdsLibGetVariableAndSize (\r
1645 VAR_LEGACY_DEV_ORDER,\r
1646 &gEfiLegacyDevOrderVariableGuid,\r
1647 &VarSize\r
1648 );\r
1649\r
1650 for (Index = 0; Index < PageNum; Index++) {\r
1651 switch (PageIdList[Index]) {\r
0a6f4824 1652\r
be9304f3
ED
1653 case FORM_SET_FD_ORDER_ID:\r
1654 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
1655 BbsType = BBS_FLOPPY;\r
1656 LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
1657 OldData = CallbackData->BmmOldFakeNVData.LegacyFD;\r
1658 break;\r
1659\r
1660 case FORM_SET_HD_ORDER_ID:\r
1661 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
1662 BbsType = BBS_HARDDISK;\r
1663 LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
1664 OldData = CallbackData->BmmOldFakeNVData.LegacyHD;\r
1665 break;\r
0a6f4824 1666\r
be9304f3
ED
1667 case FORM_SET_CD_ORDER_ID:\r
1668 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
1669 BbsType = BBS_CDROM;\r
1670 LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
1671 OldData = CallbackData->BmmOldFakeNVData.LegacyCD;\r
1672 break;\r
0a6f4824 1673\r
be9304f3
ED
1674 case FORM_SET_NET_ORDER_ID:\r
1675 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
1676 BbsType = BBS_EMBED_NETWORK;\r
1677 LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
1678 OldData = CallbackData->BmmOldFakeNVData.LegacyNET;\r
1679 break;\r
45295cf5
ED
1680\r
1681 default:\r
1682 ASSERT (PageIdList[Index] == FORM_SET_BEV_ORDER_ID);\r
be9304f3
ED
1683 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
1684 BbsType = BBS_BEV_DEVICE;\r
1685 LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
1686 OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
1687 break;\r
be9304f3 1688 }\r
0a6f4824 1689\r
be9304f3
ED
1690 if (NULL != VarData) {\r
1691 WorkingVarData = VarData;\r
1692 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;\r
1693 while (WorkingVarData < VarData + VarSize) {\r
1694 if (DevOrder->BbsType == BbsType) {\r
1695 break;\r
1696 }\r
0a6f4824 1697\r
1a45b15e 1698 WorkingVarData = (UINT8 *)((UINTN)WorkingVarData + sizeof (BBS_TYPE));\r
be9304f3
ED
1699 WorkingVarData += *(UINT16 *) WorkingVarData;\r
1700 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;\r
0a6f4824 1701 }\r
be9304f3 1702 for (OptionIndex = 0; OptionIndex < OptionMenu->MenuNumber; OptionIndex++) {\r
1a45b15e 1703 VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + OptionIndex * sizeof (UINT16));\r
be9304f3
ED
1704 if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
1705 LegacyOrder[OptionIndex] = 0xFF;\r
1706 Pos = (VarDevOrder & 0xFF) / 8;\r
1707 Bit = 7 - ((VarDevOrder & 0xFF) % 8);\r
1708 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
1709 } else {\r
1710 LegacyOrder[OptionIndex] = (UINT8) (VarDevOrder & 0xFF);\r
1711 }\r
0a6f4824 1712 }\r
be9304f3
ED
1713 CopyMem (OldData, LegacyOrder, 100);\r
1714 }\r
0a6f4824 1715 }\r
be9304f3
ED
1716}\r
1717\r
1718/**\r
1719 Get driver option order from globalc DriverOptionMenu.\r
1720\r
1721 @param CallbackData The BMM context data.\r
0a6f4824 1722\r
be9304f3
ED
1723**/\r
1724VOID\r
1725GetDriverOrder (\r
1726 IN BMM_CALLBACK_DATA *CallbackData\r
1727 )\r
1728{\r
1729 BMM_FAKE_NV_DATA *BmmConfig;\r
1730 UINT16 Index;\r
1731 UINT16 OptionOrderIndex;\r
1732 UINTN DeviceType;\r
1733 BM_MENU_ENTRY *NewMenuEntry;\r
1734 BM_LOAD_CONTEXT *NewLoadContext;\r
1735\r
1736 ASSERT (CallbackData != NULL);\r
1737\r
1738 DeviceType = (UINTN) -1;\r
1739 BmmConfig = &CallbackData->BmmFakeNvData;\r
1740 ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));\r
1741\r
1742 for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&\r
1743 (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));\r
1744 Index++) {\r
1745 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
1746 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1747\r
1748 if (NewLoadContext->IsLegacy) {\r
1749 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {\r
1750 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;\r
1751 } else {\r
1752 //\r
1753 // Only show one legacy boot option for the same device type\r
1754 // assuming the boot options are grouped by the device type\r
1755 //\r
1756 continue;\r
1757 }\r
1758 }\r
1759 BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
1760 }\r
1761}\r