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