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