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