]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
Refine code to follow good coding style.
[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
be9304f3 8Copyright (c) 2004 - 2014, 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
373 if (FileContext->Info->VolumeLabel == NULL) {\r
374 VolumeLabel = L"NULL VOLUME LABEL";\r
375 } else {\r
376 VolumeLabel = FileContext->Info->VolumeLabel;\r
377 if (*VolumeLabel == 0x0000) {\r
378 VolumeLabel = L"NO VOLUME LABEL";\r
379 }\r
380 }\r
381 }\r
382\r
383 TempStr = MenuEntry->HelpString;\r
384 MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
385 ASSERT (MenuEntry->DisplayString != NULL);\r
386 UnicodeSPrint (\r
387 MenuEntry->DisplayString,\r
388 MAX_CHAR,\r
389 L"%s, [%s]",\r
390 VolumeLabel,\r
391 TempStr\r
392 );\r
393 OptionNumber++;\r
394 InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
395 }\r
396 }\r
397\r
398 if (NoSimpleFsHandles != 0) {\r
399 FreePool (SimpleFsHandle);\r
400 }\r
401 //\r
402 // Searching for handles that support Load File protocol\r
403 //\r
404 Status = gBS->LocateHandleBuffer (\r
405 ByProtocol,\r
406 &gEfiLoadFileProtocolGuid,\r
407 NULL,\r
408 &NoLoadFileHandles,\r
409 &LoadFileHandle\r
410 );\r
411\r
412 if (!EFI_ERROR (Status)) {\r
413 for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
414 MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
415 if (NULL == MenuEntry) {\r
416 FreePool (LoadFileHandle);\r
417 return EFI_OUT_OF_RESOURCES;\r
418 }\r
419\r
420 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
421 FileContext->IsRemovableMedia = FALSE;\r
422 FileContext->IsLoadFile = TRUE;\r
423 FileContext->Handle = LoadFileHandle[Index];\r
424 FileContext->IsRoot = TRUE;\r
425\r
69533312 426 FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
427 FileContext->FileName = DevicePathToStr (FileContext->DevicePath);\r
5c08e117 428\r
429 MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
430\r
431 TempStr = MenuEntry->HelpString;\r
432 MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
433 ASSERT (MenuEntry->DisplayString != NULL);\r
434 UnicodeSPrint (\r
435 MenuEntry->DisplayString,\r
436 MAX_CHAR,\r
437 L"Load File [%s]",\r
438 TempStr\r
439 );\r
440\r
441 MenuEntry->OptionNumber = OptionNumber;\r
442 OptionNumber++;\r
443 InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
444 }\r
445 }\r
446\r
447 if (NoLoadFileHandles != 0) {\r
448 FreePool (LoadFileHandle);\r
449 }\r
450\r
451 //\r
452 // Add Legacy Boot Option Support Here\r
453 //\r
454 Status = gBS->LocateProtocol (\r
455 &gEfiLegacyBiosProtocolGuid,\r
456 NULL,\r
457 (VOID **) &LegacyBios\r
458 );\r
459 if (!EFI_ERROR (Status)) {\r
460\r
461 for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
462 MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
463 if (NULL == MenuEntry) {\r
464 return EFI_OUT_OF_RESOURCES;\r
465 }\r
466\r
467 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
468\r
469 FileContext->IsRemovableMedia = FALSE;\r
470 FileContext->IsLoadFile = TRUE;\r
471 FileContext->IsBootLegacy = TRUE;\r
472 DeviceType = (UINT16) Index;\r
473 BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
474 BbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
475 SetDevicePathNodeLength (\r
476 &BbsDevicePathNode.Header,\r
477 sizeof (BBS_BBS_DEVICE_PATH)\r
478 );\r
479 BbsDevicePathNode.DeviceType = DeviceType;\r
480 BbsDevicePathNode.StatusFlag = 0;\r
481 BbsDevicePathNode.String[0] = 0;\r
482 DevicePath = AppendDevicePathNode (\r
483 EndDevicePath,\r
484 (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
485 );\r
486\r
487 FileContext->DevicePath = DevicePath;\r
488 MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
489\r
490 TempStr = MenuEntry->HelpString;\r
491 MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
492 ASSERT (MenuEntry->DisplayString != NULL);\r
493 UnicodeSPrint (\r
494 MenuEntry->DisplayString,\r
495 MAX_CHAR,\r
496 L"Boot Legacy [%s]",\r
497 TempStr\r
498 );\r
499 MenuEntry->OptionNumber = OptionNumber;\r
500 OptionNumber++;\r
501 InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
502 }\r
503 }\r
504 //\r
505 // Remember how many file system options are here\r
506 //\r
507 FsOptionMenu.MenuNumber = OptionNumber;\r
508 return EFI_SUCCESS;\r
509}\r
510\r
511/**\r
512 Free resources allocated in Allocate Rountine.\r
513\r
514 @param FreeMenu Menu to be freed\r
515**/\r
516VOID\r
517BOpt_FreeMenu (\r
518 BM_MENU_OPTION *FreeMenu\r
519 )\r
520{\r
521 BM_MENU_ENTRY *MenuEntry;\r
522 while (!IsListEmpty (&FreeMenu->Head)) {\r
523 MenuEntry = CR (\r
524 FreeMenu->Head.ForwardLink,\r
525 BM_MENU_ENTRY,\r
526 Link,\r
527 BM_MENU_ENTRY_SIGNATURE\r
528 );\r
529 RemoveEntryList (&MenuEntry->Link);\r
530 BOpt_DestroyMenuEntry (MenuEntry);\r
531 }\r
22d1f978 532 FreeMenu->MenuNumber = 0;\r
5c08e117 533}\r
534\r
535/**\r
536 Find files under current directory\r
537 All files and sub-directories in current directory\r
538 will be stored in DirectoryMenu for future use.\r
539\r
540 @param CallbackData The BMM context data.\r
541 @param MenuEntry The Menu Entry.\r
542\r
543 @retval EFI_SUCCESS Get files from current dir successfully.\r
544 @return Other value if can't get files from current dir.\r
545\r
546**/\r
547EFI_STATUS\r
548BOpt_FindFiles (\r
549 IN BMM_CALLBACK_DATA *CallbackData,\r
550 IN BM_MENU_ENTRY *MenuEntry\r
551 )\r
552{\r
553 EFI_FILE_HANDLE NewDir;\r
554 EFI_FILE_HANDLE Dir;\r
555 EFI_FILE_INFO *DirInfo;\r
556 UINTN BufferSize;\r
557 UINTN DirBufferSize;\r
558 BM_MENU_ENTRY *NewMenuEntry;\r
559 BM_FILE_CONTEXT *FileContext;\r
560 BM_FILE_CONTEXT *NewFileContext;\r
561 UINTN Pass;\r
562 EFI_STATUS Status;\r
563 UINTN OptionNumber;\r
564\r
565 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
566 Dir = FileContext->FHandle;\r
567 OptionNumber = 0;\r
568 //\r
569 // Open current directory to get files from it\r
570 //\r
571 Status = Dir->Open (\r
572 Dir,\r
573 &NewDir,\r
574 FileContext->FileName,\r
575 EFI_FILE_READ_ONLY,\r
576 0\r
577 );\r
578 if (!FileContext->IsRoot) {\r
579 Dir->Close (Dir);\r
580 }\r
581\r
582 if (EFI_ERROR (Status)) {\r
583 return Status;\r
584 }\r
585\r
586 DirInfo = EfiLibFileInfo (NewDir);\r
587 if (DirInfo == NULL) {\r
588 return EFI_NOT_FOUND;\r
589 }\r
590\r
7ec9caab 591 if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
5c08e117 592 return EFI_INVALID_PARAMETER;\r
593 }\r
594\r
595 FileContext->DevicePath = FileDevicePath (\r
596 FileContext->Handle,\r
597 FileContext->FileName\r
598 );\r
599\r
600 DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
601 DirInfo = AllocateZeroPool (DirBufferSize);\r
602 if (DirInfo == NULL) {\r
603 return EFI_OUT_OF_RESOURCES;\r
604 }\r
605 //\r
606 // Get all files in current directory\r
607 // Pass 1 to get Directories\r
608 // Pass 2 to get files that are EFI images\r
609 //\r
610 for (Pass = 1; Pass <= 2; Pass++) {\r
611 NewDir->SetPosition (NewDir, 0);\r
612 for (;;) {\r
613 BufferSize = DirBufferSize;\r
614 Status = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
615 if (EFI_ERROR (Status) || BufferSize == 0) {\r
616 break;\r
617 }\r
618\r
7ec9caab 619 if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||\r
620 ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)\r
5c08e117 621 ) {\r
622 //\r
623 // Pass 1 is for Directories\r
624 // Pass 2 is for file names\r
625 //\r
626 continue;\r
627 }\r
628\r
7ec9caab 629 if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) {\r
5c08e117 630 //\r
631 // Slip file unless it is a directory entry or a .EFI file\r
632 //\r
633 continue;\r
634 }\r
635\r
636 NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
637 if (NULL == NewMenuEntry) {\r
638 return EFI_OUT_OF_RESOURCES;\r
639 }\r
640\r
641 NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
642 NewFileContext->Handle = FileContext->Handle;\r
643 NewFileContext->FileName = BOpt_AppendFileName (\r
644 FileContext->FileName,\r
645 DirInfo->FileName\r
646 );\r
647 NewFileContext->FHandle = NewDir;\r
648 NewFileContext->DevicePath = FileDevicePath (\r
649 NewFileContext->Handle,\r
650 NewFileContext->FileName\r
651 );\r
652 NewMenuEntry->HelpString = NULL;\r
653\r
654 MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
655 CallbackData,\r
656 FileOptionStrDepository\r
657 );\r
658\r
659 NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
660\r
661 if (NewFileContext->IsDir) {\r
662 BufferSize = StrLen (DirInfo->FileName) * 2 + 6;\r
663 NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
664\r
665 UnicodeSPrint (\r
666 NewMenuEntry->DisplayString,\r
667 BufferSize,\r
668 L"<%s>",\r
669 DirInfo->FileName\r
670 );\r
671\r
672 } else {\r
673 NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
674 }\r
675\r
676 NewFileContext->IsRoot = FALSE;\r
677 NewFileContext->IsLoadFile = FALSE;\r
678 NewFileContext->IsRemovableMedia = FALSE;\r
679\r
680 NewMenuEntry->OptionNumber = OptionNumber;\r
681 OptionNumber++;\r
682 InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
683 }\r
684 }\r
685\r
686 DirectoryMenu.MenuNumber = OptionNumber;\r
687 FreePool (DirInfo);\r
688 return EFI_SUCCESS;\r
689}\r
690\r
691/**\r
692 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
693\r
694 @retval EFI_SUCCESS The function complete successfully.\r
695 @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
696\r
697**/\r
698EFI_STATUS\r
699BOpt_GetLegacyOptions (\r
700 VOID\r
701 )\r
702{\r
703 BM_MENU_ENTRY *NewMenuEntry;\r
704 BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;\r
705 EFI_STATUS Status;\r
706 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
707 UINT16 HddCount;\r
708 HDD_INFO *HddInfo;\r
709 UINT16 BbsCount;\r
710 BBS_TABLE *BbsTable;\r
22d1f978 711 UINT16 Index;\r
5c08e117 712 CHAR16 DescString[100];\r
713 UINTN FDNum;\r
714 UINTN HDNum;\r
715 UINTN CDNum;\r
716 UINTN NETNum;\r
717 UINTN BEVNum;\r
718\r
719 NewMenuEntry = NULL;\r
720 HddInfo = NULL;\r
721 BbsTable = NULL;\r
722 BbsCount = 0;\r
723\r
724 //\r
725 // Initialize Bbs Table Context from BBS info data\r
726 //\r
727 InitializeListHead (&LegacyFDMenu.Head);\r
728 InitializeListHead (&LegacyHDMenu.Head);\r
729 InitializeListHead (&LegacyCDMenu.Head);\r
730 InitializeListHead (&LegacyNETMenu.Head);\r
731 InitializeListHead (&LegacyBEVMenu.Head);\r
732\r
733 Status = gBS->LocateProtocol (\r
734 &gEfiLegacyBiosProtocolGuid,\r
735 NULL,\r
736 (VOID **) &LegacyBios\r
737 );\r
738 if (!EFI_ERROR (Status)) {\r
739 Status = LegacyBios->GetBbsInfo (\r
740 LegacyBios,\r
741 &HddCount,\r
742 &HddInfo,\r
743 &BbsCount,\r
744 &BbsTable\r
745 );\r
746 if (EFI_ERROR (Status)) {\r
747 return Status;\r
748 }\r
749 }\r
750\r
751 FDNum = 0;\r
752 HDNum = 0;\r
753 CDNum = 0;\r
754 NETNum = 0;\r
755 BEVNum = 0;\r
756\r
757 for (Index = 0; Index < BbsCount; Index++) {\r
758 if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
759 (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
760 ) {\r
761 continue;\r
762 }\r
763\r
764 NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
765 if (NULL == NewMenuEntry) {\r
766 break;\r
767 }\r
768\r
769 NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
22d1f978
RN
770 NewLegacyDevContext->BbsEntry = &BbsTable[Index];\r
771 NewLegacyDevContext->BbsIndex = Index;\r
5c08e117 772 NewLegacyDevContext->BbsCount = BbsCount;\r
773 BdsBuildLegacyDevNameString (\r
774 &BbsTable[Index],\r
775 Index,\r
776 sizeof (DescString),\r
777 DescString\r
778 );\r
22d1f978 779 NewLegacyDevContext->Description = AllocateCopyPool (StrSize (DescString), DescString);\r
5c08e117 780 if (NULL == NewLegacyDevContext->Description) {\r
781 break;\r
782 }\r
783\r
5c08e117 784 NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
785 NewMenuEntry->HelpString = NULL;\r
786\r
787 switch (BbsTable[Index].DeviceType) {\r
788 case BBS_FLOPPY:\r
789 InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
790 FDNum++;\r
791 break;\r
792\r
793 case BBS_HARDDISK:\r
794 InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
795 HDNum++;\r
796 break;\r
797\r
798 case BBS_CDROM:\r
799 InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
800 CDNum++;\r
801 break;\r
802\r
803 case BBS_EMBED_NETWORK:\r
804 InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
805 NETNum++;\r
806 break;\r
807\r
808 case BBS_BEV_DEVICE:\r
809 InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
810 BEVNum++;\r
811 break;\r
812 }\r
813 }\r
814\r
815 if (Index != BbsCount) {\r
816 BOpt_FreeLegacyOptions ();\r
817 return EFI_OUT_OF_RESOURCES;\r
818 }\r
819\r
820 LegacyFDMenu.MenuNumber = FDNum;\r
821 LegacyHDMenu.MenuNumber = HDNum;\r
822 LegacyCDMenu.MenuNumber = CDNum;\r
823 LegacyNETMenu.MenuNumber = NETNum;\r
824 LegacyBEVMenu.MenuNumber = BEVNum;\r
825 return EFI_SUCCESS;\r
826}\r
827\r
828/**\r
829 Free out resouce allocated from Legacy Boot Options.\r
830\r
831**/\r
832VOID\r
833BOpt_FreeLegacyOptions (\r
834 VOID\r
835 )\r
836{\r
837 BOpt_FreeMenu (&LegacyFDMenu);\r
838 BOpt_FreeMenu (&LegacyHDMenu);\r
839 BOpt_FreeMenu (&LegacyCDMenu);\r
840 BOpt_FreeMenu (&LegacyNETMenu);\r
841 BOpt_FreeMenu (&LegacyBEVMenu);\r
842}\r
843\r
844/**\r
845\r
846 Build the BootOptionMenu according to BootOrder Variable.\r
847 This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
848\r
849 @param CallbackData The BMM context data.\r
850\r
851 @return EFI_NOT_FOUND Fail to find "BootOrder" variable.\r
852 @return EFI_SUCESS Success build boot option menu.\r
853\r
854**/\r
855EFI_STATUS\r
856BOpt_GetBootOptions (\r
857 IN BMM_CALLBACK_DATA *CallbackData\r
858 )\r
859{\r
860 UINTN Index;\r
861 UINT16 BootString[10];\r
862 UINT8 *LoadOptionFromVar;\r
863 UINT8 *LoadOption;\r
864 UINTN BootOptionSize;\r
865 BOOLEAN BootNextFlag;\r
866 UINT16 *BootOrderList;\r
867 UINTN BootOrderListSize;\r
868 UINT16 *BootNext;\r
869 UINTN BootNextSize;\r
870 BM_MENU_ENTRY *NewMenuEntry;\r
871 BM_LOAD_CONTEXT *NewLoadContext;\r
872 UINT8 *LoadOptionPtr;\r
873 UINTN StringSize;\r
874 UINTN OptionalDataSize;\r
875 UINT8 *LoadOptionEnd;\r
876 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
877 UINTN MenuCount;\r
878 UINT8 *Ptr;\r
5caec787 879 \r
5c08e117 880 MenuCount = 0;\r
881 BootOrderListSize = 0;\r
882 BootNextSize = 0;\r
883 BootOrderList = NULL;\r
884 BootNext = NULL;\r
885 LoadOptionFromVar = NULL;\r
886 BOpt_FreeMenu (&BootOptionMenu);\r
887 InitializeListHead (&BootOptionMenu.Head);\r
888\r
889 //\r
890 // Get the BootOrder from the Var\r
891 //\r
892 BootOrderList = BdsLibGetVariableAndSize (\r
893 L"BootOrder",\r
894 &gEfiGlobalVariableGuid,\r
895 &BootOrderListSize\r
896 );\r
897 if (BootOrderList == NULL) {\r
898 return EFI_NOT_FOUND;\r
899 }\r
900 \r
901 //\r
902 // Get the BootNext from the Var\r
903 //\r
904 BootNext = BdsLibGetVariableAndSize (\r
905 L"BootNext",\r
906 &gEfiGlobalVariableGuid,\r
907 &BootNextSize\r
908 );\r
909\r
910 if (BootNext != NULL) {\r
911 if (BootNextSize != sizeof (UINT16)) {\r
912 FreePool (BootNext);\r
913 BootNext = NULL;\r
914 }\r
915 }\r
916\r
917 for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
918 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
919 //\r
920 // Get all loadoptions from the VAR\r
921 //\r
922 LoadOptionFromVar = BdsLibGetVariableAndSize (\r
923 BootString,\r
924 &gEfiGlobalVariableGuid,\r
925 &BootOptionSize\r
926 );\r
927 if (LoadOptionFromVar == NULL) {\r
928 continue;\r
929 }\r
930\r
931 LoadOption = AllocateZeroPool (BootOptionSize);\r
932 if (LoadOption == NULL) {\r
933 continue;\r
934 }\r
935\r
936 CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
937 FreePool (LoadOptionFromVar);\r
938\r
939 if (BootNext != NULL) {\r
940 BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
941 } else {\r
942 BootNextFlag = FALSE;\r
943 }\r
944\r
945 if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
946 FreePool (LoadOption);\r
947 continue;\r
948 }\r
949 //\r
950 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
951 // the buffer allocated already should be freed before returning.\r
952 //\r
953 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
954 if (NULL == NewMenuEntry) {\r
955 return EFI_OUT_OF_RESOURCES;\r
956 }\r
957\r
958 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
959\r
960 LoadOptionPtr = LoadOption;\r
961 LoadOptionEnd = LoadOption + BootOptionSize;\r
962\r
963 NewMenuEntry->OptionNumber = BootOrderList[Index];\r
964 NewLoadContext->LoadOptionModified = FALSE;\r
965 NewLoadContext->Deleted = FALSE;\r
966 NewLoadContext->IsBootNext = BootNextFlag;\r
967\r
968 //\r
969 // Is a Legacy Device?\r
970 //\r
971 Ptr = (UINT8 *) LoadOption;\r
972\r
973 //\r
974 // Attribute = *(UINT32 *)Ptr;\r
975 //\r
976 Ptr += sizeof (UINT32);\r
977\r
978 //\r
979 // FilePathSize = *(UINT16 *)Ptr;\r
980 //\r
981 Ptr += sizeof (UINT16);\r
982\r
983 //\r
984 // Description = (CHAR16 *)Ptr;\r
985 //\r
986 Ptr += StrSize ((CHAR16 *) Ptr);\r
987\r
988 //\r
989 // Now Ptr point to Device Path\r
990 //\r
991 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
992 if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
993 NewLoadContext->IsLegacy = TRUE;\r
994 } else {\r
995 NewLoadContext->IsLegacy = FALSE;\r
996 }\r
997 //\r
998 // LoadOption is a pointer type of UINT8\r
999 // for easy use with following LOAD_OPTION\r
1000 // embedded in this struct\r
1001 //\r
1002 NewLoadContext->LoadOption = LoadOption;\r
1003 NewLoadContext->LoadOptionSize = BootOptionSize;\r
1004\r
1005 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
1006 NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
1007\r
1008 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
1009\r
1010 LoadOptionPtr += sizeof (UINT32);\r
1011\r
1012 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
1013 LoadOptionPtr += sizeof (UINT16);\r
5caec787 1014 \r
1015 StringSize = StrSize((UINT16*)LoadOptionPtr);\r
9aa7ba01 1016\r
1017 NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr));\r
1018 ASSERT (NewLoadContext->Description != NULL);\r
1019 StrCpy (NewLoadContext->Description, (UINT16*)LoadOptionPtr);\r
5caec787 1020 \r
5c08e117 1021 ASSERT (NewLoadContext->Description != NULL);\r
5c08e117 1022 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
1023\r
1024 LoadOptionPtr += StringSize;\r
1025\r
1026 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
1027 ASSERT (NewLoadContext->FilePathList != NULL);\r
1028 CopyMem (\r
1029 NewLoadContext->FilePathList,\r
1030 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
1031 NewLoadContext->FilePathListLength\r
1032 );\r
1033\r
1034 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
1035 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
1036 CallbackData,\r
1037 BootOptionStrDepository\r
1038 );\r
1039 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
1040 CallbackData,\r
1041 BootOptionHelpStrDepository\r
1042 );\r
1043 LoadOptionPtr += NewLoadContext->FilePathListLength;\r
1044\r
1045 if (LoadOptionPtr < LoadOptionEnd) {\r
1046 OptionalDataSize = BootOptionSize -\r
1047 sizeof (UINT32) -\r
1048 sizeof (UINT16) -\r
1049 StringSize -\r
1050 NewLoadContext->FilePathListLength;\r
1051\r
1052 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
1053 ASSERT (NewLoadContext->OptionalData != NULL);\r
1054 CopyMem (\r
1055 NewLoadContext->OptionalData,\r
1056 LoadOptionPtr,\r
1057 OptionalDataSize\r
1058 );\r
1059\r
1060 NewLoadContext->OptionalDataSize = OptionalDataSize;\r
1061 }\r
1062\r
1063 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
1064 MenuCount++;\r
1065 }\r
1066\r
1067 if (BootNext != NULL) {\r
1068 FreePool (BootNext);\r
1069 }\r
1070 if (BootOrderList != NULL) {\r
1071 FreePool (BootOrderList);\r
1072 }\r
1073 BootOptionMenu.MenuNumber = MenuCount;\r
1074 return EFI_SUCCESS;\r
1075}\r
1076\r
1077/**\r
1078\r
1079 Append file name to existing file name.\r
1080\r
1081 @param Str1 The existing file name\r
1082 @param Str2 The file name to be appended\r
1083\r
1084 @return Allocate a new string to hold the appended result.\r
1085 Caller is responsible to free the returned string.\r
1086\r
1087**/\r
1088CHAR16 *\r
1089BOpt_AppendFileName (\r
1090 IN CHAR16 *Str1,\r
1091 IN CHAR16 *Str2\r
1092 )\r
1093{\r
1094 UINTN Size1;\r
1095 UINTN Size2;\r
1096 CHAR16 *Str;\r
1097 CHAR16 *TmpStr;\r
1098 CHAR16 *Ptr;\r
1099 CHAR16 *LastSlash;\r
1100\r
1101 Size1 = StrSize (Str1);\r
1102 Size2 = StrSize (Str2);\r
1103 Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
1104 ASSERT (Str != NULL);\r
1105\r
1106 TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); \r
1107 ASSERT (TmpStr != NULL);\r
1108\r
1109 StrCat (Str, Str1);\r
1110 if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
1111 StrCat (Str, L"\\");\r
1112 }\r
1113\r
1114 StrCat (Str, Str2);\r
1115\r
1116 Ptr = Str;\r
1117 LastSlash = Str;\r
1118 while (*Ptr != 0) {\r
1119 if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {\r
1120 //\r
1121 // Convert "\Name\..\" to "\"\r
1122 // DO NOT convert the .. if it is at the end of the string. This will\r
1123 // break the .. behavior in changing directories.\r
1124 //\r
1125\r
1126 //\r
1127 // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
1128 // that overlap.\r
1129 //\r
1130 StrCpy (TmpStr, Ptr + 3);\r
1131 StrCpy (LastSlash, TmpStr);\r
1132 Ptr = LastSlash;\r
1133 } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
1134 //\r
1135 // Convert a "\.\" to a "\"\r
1136 //\r
1137\r
1138 //\r
1139 // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
1140 // that overlap.\r
1141 //\r
1142 StrCpy (TmpStr, Ptr + 2);\r
1143 StrCpy (Ptr, TmpStr);\r
1144 Ptr = LastSlash;\r
1145 } else if (*Ptr == '\\') {\r
1146 LastSlash = Ptr;\r
1147 }\r
1148\r
1149 Ptr++;\r
1150 }\r
1151\r
1152 FreePool (TmpStr);\r
1153 \r
1154 return Str;\r
1155}\r
1156\r
1157/**\r
1158\r
1159 Check whether current FileName point to a valid\r
1160 Efi Image File.\r
1161\r
1162 @param FileName File need to be checked.\r
1163\r
1164 @retval TRUE Is Efi Image\r
1165 @retval FALSE Not a valid Efi Image\r
1166\r
1167**/\r
1168BOOLEAN\r
1169BOpt_IsEfiImageName (\r
1170 IN UINT16 *FileName\r
1171 )\r
1172{\r
1173 //\r
1174 // Search for ".efi" extension\r
1175 //\r
1176 while (*FileName != L'\0') {\r
1177 if (FileName[0] == '.') {\r
1178 if (FileName[1] == 'e' || FileName[1] == 'E') {\r
1179 if (FileName[2] == 'f' || FileName[2] == 'F') {\r
1180 if (FileName[3] == 'i' || FileName[3] == 'I') {\r
1181 return TRUE;\r
1182 } else if (FileName[3] == 0x0000) {\r
1183 return FALSE;\r
1184 }\r
1185 } else if (FileName[2] == 0x0000) {\r
1186 return FALSE;\r
1187 }\r
1188 } else if (FileName[1] == 0x0000) {\r
1189 return FALSE;\r
1190 }\r
1191 }\r
1192\r
1193 FileName += 1;\r
1194 }\r
1195\r
1196 return FALSE;\r
1197}\r
1198\r
1199/**\r
1200\r
1201 Check whether current FileName point to a valid Efi Application\r
1202\r
1203 @param Dir Pointer to current Directory\r
1204 @param FileName Pointer to current File name.\r
1205\r
1206 @retval TRUE Is a valid Efi Application\r
1207 @retval FALSE not a valid Efi Application\r
1208\r
1209**/\r
1210BOOLEAN\r
1211BOpt_IsEfiApp (\r
1212 IN EFI_FILE_HANDLE Dir,\r
1213 IN UINT16 *FileName\r
1214 )\r
1215{\r
1216 UINTN BufferSize;\r
1217 EFI_IMAGE_DOS_HEADER DosHdr;\r
1218 UINT16 Subsystem;\r
1219 EFI_FILE_HANDLE File;\r
1220 EFI_STATUS Status;\r
1221 EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;\r
1222\r
1223 Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);\r
1224\r
1225 if (EFI_ERROR (Status)) {\r
1226 return FALSE;\r
1227 }\r
1228\r
1229 BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
1230 File->Read (File, &BufferSize, &DosHdr);\r
1231 if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1232 File->Close (File);\r
1233 return FALSE;\r
1234 }\r
1235\r
1236 File->SetPosition (File, DosHdr.e_lfanew);\r
1237 BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
1238 File->Read (File, &BufferSize, &PeHdr);\r
1239 if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1240 File->Close (File);\r
1241 return FALSE;\r
1242 }\r
1243 //\r
1244 // Determine PE type and read subsytem\r
1245 //\r
1246 if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1247 Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem;\r
1248 } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1249 Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;\r
1250 } else {\r
1251 return FALSE;\r
1252 }\r
1253\r
1254 if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1255 File->Close (File);\r
1256 return TRUE;\r
1257 } else {\r
1258 File->Close (File);\r
1259 return FALSE;\r
1260 }\r
1261}\r
1262\r
1263/**\r
1264\r
1265 Find drivers that will be added as Driver#### variables from handles\r
1266 in current system environment\r
1267 All valid handles in the system except those consume SimpleFs, LoadFile\r
1268 are stored in DriverMenu for future use.\r
1269\r
1270 @retval EFI_SUCCESS The function complets successfully.\r
1271 @return Other value if failed to build the DriverMenu.\r
1272\r
1273**/\r
1274EFI_STATUS\r
1275BOpt_FindDrivers (\r
1276 VOID\r
1277 )\r
1278{\r
1279 UINTN NoDevicePathHandles;\r
1280 EFI_HANDLE *DevicePathHandle;\r
1281 UINTN Index;\r
1282 EFI_STATUS Status;\r
1283 BM_MENU_ENTRY *NewMenuEntry;\r
1284 BM_HANDLE_CONTEXT *NewHandleContext;\r
1285 EFI_HANDLE CurHandle;\r
1286 UINTN OptionNumber;\r
1287 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
1288 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
1289\r
1290 SimpleFs = NULL;\r
1291 LoadFile = NULL;\r
1292\r
1293 InitializeListHead (&DriverMenu.Head);\r
1294\r
1295 //\r
1296 // At first, get all handles that support Device Path\r
1297 // protocol which is the basic requirement for\r
1298 // Driver####\r
1299 //\r
1300 Status = gBS->LocateHandleBuffer (\r
1301 ByProtocol,\r
1302 &gEfiDevicePathProtocolGuid,\r
1303 NULL,\r
1304 &NoDevicePathHandles,\r
1305 &DevicePathHandle\r
1306 );\r
1307 if (EFI_ERROR (Status)) {\r
1308 return Status;\r
1309 }\r
1310\r
1311 OptionNumber = 0;\r
1312 for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
1313 CurHandle = DevicePathHandle[Index];\r
1314\r
1315 Status = gBS->HandleProtocol (\r
1316 CurHandle,\r
1317 &gEfiSimpleFileSystemProtocolGuid,\r
1318 (VOID **) &SimpleFs\r
1319 );\r
1320 if (Status == EFI_SUCCESS) {\r
1321 continue;\r
1322 }\r
1323\r
1324 Status = gBS->HandleProtocol (\r
1325 CurHandle,\r
1326 &gEfiLoadFileProtocolGuid,\r
1327 (VOID **) &LoadFile\r
1328 );\r
1329 if (Status == EFI_SUCCESS) {\r
1330 continue;\r
1331 }\r
1332\r
1333 NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
1334 if (NULL == NewMenuEntry) {\r
1335 FreePool (DevicePathHandle);\r
1336 return EFI_OUT_OF_RESOURCES;\r
1337 }\r
1338\r
1339 NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
1340 NewHandleContext->Handle = CurHandle;\r
1341 NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);\r
1342 NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
1343 NewMenuEntry->HelpString = NULL;\r
1344 NewMenuEntry->OptionNumber = OptionNumber;\r
1345 OptionNumber++;\r
1346 InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
1347\r
1348 }\r
1349\r
1350 if (DevicePathHandle != NULL) {\r
1351 FreePool (DevicePathHandle);\r
1352 }\r
1353\r
1354 DriverMenu.MenuNumber = OptionNumber;\r
1355 return EFI_SUCCESS;\r
1356}\r
1357\r
1358/**\r
1359\r
1360 Get the Option Number that has not been allocated for use.\r
1361\r
a5c3c546 1362 @param Type The type of Option.\r
1363\r
5c08e117 1364 @return The available Option Number.\r
1365\r
1366**/\r
1367UINT16\r
a5c3c546 1368BOpt_GetOptionNumber (\r
1369 CHAR16 *Type\r
5c08e117 1370 )\r
1371{\r
a5c3c546 1372 UINT16 *OrderList;\r
1373 UINTN OrderListSize;\r
5c08e117 1374 UINTN Index;\r
a5c3c546 1375 CHAR16 StrTemp[20];\r
5c08e117 1376 UINT16 *OptionBuffer;\r
a5c3c546 1377 UINT16 OptionNumber;\r
5c08e117 1378 UINTN OptionSize;\r
1379\r
a5c3c546 1380 OrderListSize = 0;\r
1381 OrderList = NULL;\r
1382 OptionNumber = 0;\r
c6498c1d 1383 Index = 0;\r
5c08e117 1384\r
a5c3c546 1385 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);\r
5c08e117 1386\r
a5c3c546 1387 OrderList = BdsLibGetVariableAndSize (\r
5c08e117 1388 StrTemp,\r
1389 &gEfiGlobalVariableGuid,\r
a5c3c546 1390 &OrderListSize\r
5c08e117 1391 );\r
ce5fad41 1392\r
a5c3c546 1393 for (OptionNumber = 0; ; OptionNumber++) {\r
c6498c1d 1394 if (OrderList != NULL) {\r
1395 for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {\r
1396 if (OptionNumber == OrderList[Index]) {\r
1397 break;\r
1398 }\r
5c08e117 1399 }\r
1400 }\r
a5c3c546 1401\r
1402 if (Index < OrderListSize / sizeof (UINT16)) {\r
1403 //\r
1404 // The OptionNumber occurs in the OrderList, continue to use next one\r
1405 //\r
1406 continue;\r
1407 }\r
1408 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber);\r
1409 DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp));\r
1410 OptionBuffer = BdsLibGetVariableAndSize (\r
1411 StrTemp,\r
1412 &gEfiGlobalVariableGuid,\r
1413 &OptionSize\r
1414 );\r
1415 if (NULL == OptionBuffer) {\r
1416 //\r
1417 // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it\r
1418 //\r
1419 break;\r
1420 }\r
5c08e117 1421 }\r
1422\r
a5c3c546 1423 return OptionNumber;\r
5c08e117 1424}\r
1425\r
1426/**\r
1427\r
a5c3c546 1428 Get the Option Number for Boot#### that does not used.\r
5c08e117 1429\r
a5c3c546 1430 @return The available Option Number.\r
5c08e117 1431\r
1432**/\r
1433UINT16\r
a5c3c546 1434BOpt_GetBootOptionNumber (\r
5c08e117 1435 VOID\r
1436 )\r
1437{\r
a5c3c546 1438 return BOpt_GetOptionNumber (L"Boot");\r
1439}\r
5c08e117 1440\r
a5c3c546 1441/**\r
5c08e117 1442\r
a5c3c546 1443 Get the Option Number for Driver#### that does not used.\r
5c08e117 1444\r
a5c3c546 1445 @return The unused Option Number.\r
5c08e117 1446\r
a5c3c546 1447**/\r
1448UINT16\r
1449BOpt_GetDriverOptionNumber (\r
1450 VOID\r
1451 )\r
1452{\r
1453 return BOpt_GetOptionNumber (L"Driver");\r
5c08e117 1454}\r
1455\r
1456/**\r
1457\r
1458 Build up all DriverOptionMenu\r
1459\r
1460 @param CallbackData The BMM context data.\r
1461\r
1462 @retval EFI_SUCESS The functin completes successfully.\r
1463 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
1464 @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.\r
1465\r
1466**/\r
1467EFI_STATUS\r
1468BOpt_GetDriverOptions (\r
1469 IN BMM_CALLBACK_DATA *CallbackData\r
1470 )\r
1471{\r
1472 UINTN Index;\r
1473 UINT16 DriverString[12];\r
1474 UINT8 *LoadOptionFromVar;\r
1475 UINT8 *LoadOption;\r
1476 UINTN DriverOptionSize;\r
1477\r
1478 UINT16 *DriverOrderList;\r
1479 UINTN DriverOrderListSize;\r
1480 BM_MENU_ENTRY *NewMenuEntry;\r
1481 BM_LOAD_CONTEXT *NewLoadContext;\r
1482 UINT8 *LoadOptionPtr;\r
1483 UINTN StringSize;\r
1484 UINTN OptionalDataSize;\r
1485 UINT8 *LoadOptionEnd;\r
1486\r
1487 DriverOrderListSize = 0;\r
1488 DriverOrderList = NULL;\r
1489 DriverOptionSize = 0;\r
1490 LoadOptionFromVar = NULL;\r
1491 BOpt_FreeMenu (&DriverOptionMenu);\r
1492 InitializeListHead (&DriverOptionMenu.Head);\r
1493 //\r
1494 // Get the DriverOrder from the Var\r
1495 //\r
1496 DriverOrderList = BdsLibGetVariableAndSize (\r
1497 L"DriverOrder",\r
1498 &gEfiGlobalVariableGuid,\r
1499 &DriverOrderListSize\r
1500 );\r
1501 if (DriverOrderList == NULL) {\r
1502 return EFI_NOT_FOUND;\r
1503 }\r
1504 \r
1505 for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
1506 UnicodeSPrint (\r
1507 DriverString,\r
1508 sizeof (DriverString),\r
1509 L"Driver%04x",\r
1510 DriverOrderList[Index]\r
1511 );\r
1512 //\r
1513 // Get all loadoptions from the VAR\r
1514 //\r
1515 LoadOptionFromVar = BdsLibGetVariableAndSize (\r
1516 DriverString,\r
1517 &gEfiGlobalVariableGuid,\r
1518 &DriverOptionSize\r
1519 );\r
1520 if (LoadOptionFromVar == NULL) {\r
1521 continue;\r
1522 }\r
1523\r
1524 LoadOption = AllocateZeroPool (DriverOptionSize);\r
1525 if (LoadOption == NULL) {\r
1526 continue;\r
1527 }\r
1528\r
1529 CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
1530 FreePool (LoadOptionFromVar);\r
1531\r
1532 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
1533 if (NULL == NewMenuEntry) {\r
1534 return EFI_OUT_OF_RESOURCES;\r
1535 }\r
1536\r
1537 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1538 LoadOptionPtr = LoadOption;\r
1539 LoadOptionEnd = LoadOption + DriverOptionSize;\r
1540 NewMenuEntry->OptionNumber = DriverOrderList[Index];\r
1541 NewLoadContext->LoadOptionModified = FALSE;\r
1542 NewLoadContext->Deleted = FALSE;\r
1543 NewLoadContext->IsLegacy = FALSE;\r
1544\r
1545 //\r
1546 // LoadOption is a pointer type of UINT8\r
1547 // for easy use with following LOAD_OPTION\r
1548 // embedded in this struct\r
1549 //\r
1550 NewLoadContext->LoadOption = LoadOption;\r
1551 NewLoadContext->LoadOptionSize = DriverOptionSize;\r
1552\r
1553 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
1554 NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
1555\r
1556 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
1557\r
1558 LoadOptionPtr += sizeof (UINT32);\r
1559\r
1560 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
1561 LoadOptionPtr += sizeof (UINT16);\r
1562\r
1563 StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
1564 NewLoadContext->Description = AllocateZeroPool (StringSize);\r
1565 ASSERT (NewLoadContext->Description != NULL);\r
1566 CopyMem (\r
1567 NewLoadContext->Description,\r
1568 (UINT16 *) LoadOptionPtr,\r
1569 StringSize\r
1570 );\r
1571 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
1572\r
1573 LoadOptionPtr += StringSize;\r
1574\r
1575 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
1576 ASSERT (NewLoadContext->FilePathList != NULL);\r
1577 CopyMem (\r
1578 NewLoadContext->FilePathList,\r
1579 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
1580 NewLoadContext->FilePathListLength\r
1581 );\r
1582\r
1583 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
1584 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
1585 CallbackData,\r
1586 DriverOptionStrDepository\r
1587 );\r
1588 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
1589 CallbackData,\r
1590 DriverOptionHelpStrDepository\r
1591 );\r
1592 LoadOptionPtr += NewLoadContext->FilePathListLength;\r
1593\r
1594 if (LoadOptionPtr < LoadOptionEnd) {\r
1595 OptionalDataSize = DriverOptionSize -\r
1596 sizeof (UINT32) -\r
1597 sizeof (UINT16) -\r
1598 StringSize -\r
1599 NewLoadContext->FilePathListLength;\r
1600\r
1601 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
1602 ASSERT (NewLoadContext->OptionalData != NULL);\r
1603 CopyMem (\r
1604 NewLoadContext->OptionalData,\r
1605 LoadOptionPtr,\r
1606 OptionalDataSize\r
1607 );\r
1608\r
1609 NewLoadContext->OptionalDataSize = OptionalDataSize;\r
1610 }\r
1611\r
1612 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
1613\r
1614 }\r
1615\r
1616 if (DriverOrderList != NULL) {\r
1617 FreePool (DriverOrderList);\r
1618 }\r
1619 DriverOptionMenu.MenuNumber = Index;\r
1620 return EFI_SUCCESS;\r
1621\r
1622}\r
1623\r
be9304f3
ED
1624/**\r
1625 Get option number according to Boot#### and BootOrder variable.\r
1626 The value is saved as #### + 1.\r
1627\r
1628 @param CallbackData The BMM context data.\r
1629**/\r
1630VOID\r
1631GetBootOrder (\r
1632 IN BMM_CALLBACK_DATA *CallbackData\r
1633 )\r
1634{\r
1635 BMM_FAKE_NV_DATA *BmmConfig;\r
1636 UINT16 Index;\r
1637 UINT16 OptionOrderIndex;\r
1638 UINTN DeviceType;\r
1639 BM_MENU_ENTRY *NewMenuEntry;\r
1640 BM_LOAD_CONTEXT *NewLoadContext;\r
1641\r
1642 ASSERT (CallbackData != NULL);\r
1643\r
1644 DeviceType = (UINTN) -1;\r
1645 BmmConfig = &CallbackData->BmmFakeNvData;\r
1646 ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));\r
1647\r
1648 for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&\r
1649 (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));\r
1650 Index++) {\r
1651 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
1652 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1653\r
1654 if (NewLoadContext->IsLegacy) {\r
1655 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {\r
1656 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;\r
1657 } else {\r
1658 //\r
1659 // Only show one legacy boot option for the same device type\r
1660 // assuming the boot options are grouped by the device type\r
1661 //\r
1662 continue;\r
1663 }\r
1664 }\r
1665 BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
1666 }\r
1667}\r
1668\r
1669/**\r
1670 According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV\r
1671 devices list .\r
1672\r
1673 @param CallbackData The BMM context data.\r
1674**/\r
1675VOID\r
1676GetLegacyDeviceOrder (\r
1677 IN BMM_CALLBACK_DATA *CallbackData\r
1678 )\r
1679{\r
1680 UINTN Index;\r
1681 UINTN OptionIndex;\r
720624cc 1682 UINT16 PageIdList[5];\r
be9304f3
ED
1683 UINTN PageNum; \r
1684 UINTN VarSize;\r
1685 UINT8 *VarData; \r
1686 UINT8 *WorkingVarData; \r
1687 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
1688 UINT16 VarDevOrder; \r
1689 UINT8 *DisMap; \r
1690 BM_MENU_OPTION *OptionMenu;\r
1691 BBS_TYPE BbsType;\r
1692 UINT8 *LegacyOrder;\r
1693 UINT8 *OldData; \r
1694 UINTN Pos;\r
1695 UINTN Bit;\r
1696 \r
1697 ASSERT (CallbackData != NULL);\r
720624cc
ED
1698\r
1699 PageIdList[0] = FORM_SET_FD_ORDER_ID;\r
1700 PageIdList[1] = FORM_SET_HD_ORDER_ID;\r
1701 PageIdList[2] = FORM_SET_CD_ORDER_ID;\r
1702 PageIdList[3] = FORM_SET_NET_ORDER_ID;\r
1703 PageIdList[4] = FORM_SET_BEV_ORDER_ID;\r
be9304f3
ED
1704 OptionMenu = NULL;\r
1705 BbsType = 0;\r
1706 LegacyOrder = NULL;\r
1707 OldData = NULL;\r
1708 DisMap = ZeroMem (CallbackData->BmmFakeNvData.DisableMap, sizeof (CallbackData->BmmFakeNvData.DisableMap));\r
1709 PageNum = sizeof (PageIdList) / sizeof (PageIdList[0]);\r
1710 VarData = BdsLibGetVariableAndSize (\r
1711 VAR_LEGACY_DEV_ORDER,\r
1712 &gEfiLegacyDevOrderVariableGuid,\r
1713 &VarSize\r
1714 );\r
1715\r
1716 for (Index = 0; Index < PageNum; Index++) {\r
1717 switch (PageIdList[Index]) {\r
1718 \r
1719 case FORM_SET_FD_ORDER_ID:\r
1720 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
1721 BbsType = BBS_FLOPPY;\r
1722 LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
1723 OldData = CallbackData->BmmOldFakeNVData.LegacyFD;\r
1724 break;\r
1725\r
1726 case FORM_SET_HD_ORDER_ID:\r
1727 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
1728 BbsType = BBS_HARDDISK;\r
1729 LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
1730 OldData = CallbackData->BmmOldFakeNVData.LegacyHD;\r
1731 break;\r
1732 \r
1733 case FORM_SET_CD_ORDER_ID:\r
1734 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
1735 BbsType = BBS_CDROM;\r
1736 LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
1737 OldData = CallbackData->BmmOldFakeNVData.LegacyCD;\r
1738 break;\r
1739 \r
1740 case FORM_SET_NET_ORDER_ID:\r
1741 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
1742 BbsType = BBS_EMBED_NETWORK;\r
1743 LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
1744 OldData = CallbackData->BmmOldFakeNVData.LegacyNET;\r
1745 break;\r
45295cf5
ED
1746\r
1747 default:\r
1748 ASSERT (PageIdList[Index] == FORM_SET_BEV_ORDER_ID);\r
be9304f3
ED
1749 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
1750 BbsType = BBS_BEV_DEVICE;\r
1751 LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
1752 OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
1753 break;\r
be9304f3
ED
1754 }\r
1755 \r
1756 if (NULL != VarData) {\r
1757 WorkingVarData = VarData;\r
1758 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;\r
1759 while (WorkingVarData < VarData + VarSize) {\r
1760 if (DevOrder->BbsType == BbsType) {\r
1761 break;\r
1762 }\r
1763 \r
1764 WorkingVarData += sizeof (BBS_TYPE);\r
1765 WorkingVarData += *(UINT16 *) WorkingVarData;\r
1766 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;\r
1767 } \r
1768 for (OptionIndex = 0; OptionIndex < OptionMenu->MenuNumber; OptionIndex++) {\r
1769 VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + OptionIndex * sizeof (UINT16));\r
1770 if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
1771 LegacyOrder[OptionIndex] = 0xFF;\r
1772 Pos = (VarDevOrder & 0xFF) / 8;\r
1773 Bit = 7 - ((VarDevOrder & 0xFF) % 8);\r
1774 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
1775 } else {\r
1776 LegacyOrder[OptionIndex] = (UINT8) (VarDevOrder & 0xFF);\r
1777 }\r
1778 } \r
1779 CopyMem (OldData, LegacyOrder, 100);\r
1780 }\r
1781 } \r
1782}\r
1783\r
1784/**\r
1785 Get driver option order from globalc DriverOptionMenu.\r
1786\r
1787 @param CallbackData The BMM context data.\r
1788 \r
1789**/\r
1790VOID\r
1791GetDriverOrder (\r
1792 IN BMM_CALLBACK_DATA *CallbackData\r
1793 )\r
1794{\r
1795 BMM_FAKE_NV_DATA *BmmConfig;\r
1796 UINT16 Index;\r
1797 UINT16 OptionOrderIndex;\r
1798 UINTN DeviceType;\r
1799 BM_MENU_ENTRY *NewMenuEntry;\r
1800 BM_LOAD_CONTEXT *NewLoadContext;\r
1801\r
1802 ASSERT (CallbackData != NULL);\r
1803\r
1804 DeviceType = (UINTN) -1;\r
1805 BmmConfig = &CallbackData->BmmFakeNvData;\r
1806 ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));\r
1807\r
1808 for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&\r
1809 (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));\r
1810 Index++) {\r
1811 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
1812 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
1813\r
1814 if (NewLoadContext->IsLegacy) {\r
1815 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {\r
1816 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;\r
1817 } else {\r
1818 //\r
1819 // Only show one legacy boot option for the same device type\r
1820 // assuming the boot options are grouped by the device type\r
1821 //\r
1822 continue;\r
1823 }\r
1824 }\r
1825 BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
1826 }\r
1827}\r