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