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