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