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