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