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