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