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