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