]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c
Merge EDK tracker 892 to EDK II.
[mirror_edk2.git] / Nt32Pkg / Library / EdkGenericBdsLib / BdsBoot.c
CommitLineData
869f8e34 1/*++\r
2\r
3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 BdsBoot.c\r
15\r
16Abstract:\r
17\r
18 BDS Lib functions which relate with create or process the boot\r
19 option.\r
20\r
21--*/\r
869f8e34 22\r
e1001af1 23#include "EdkGenericBdsLibInternal.h"\r
869f8e34 24\r
25BOOLEAN mEnumBootDevice = FALSE;\r
26\r
27EFI_STATUS\r
28BdsLibDoLegacyBoot (\r
29 IN BDS_COMMON_OPTION *Option\r
30 )\r
31/*++\r
32\r
33Routine Description:\r
34\r
35 Boot the legacy system with the boot option\r
36\r
37Arguments:\r
38\r
39 Option - The legacy boot option which have BBS device path\r
40\r
41Returns:\r
42\r
43 EFI_UNSUPPORTED - There is no legacybios protocol, do not support\r
44 legacy boot.\r
45\r
46 EFI_STATUS - Return the status of LegacyBios->LegacyBoot ().\r
47\r
48--*/\r
49{\r
50 EFI_STATUS Status;\r
51 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
52\r
53 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);\r
54 if (EFI_ERROR (Status)) {\r
55 //\r
56 // If no LegacyBios protocol we do not support legacy boot\r
57 //\r
58 return EFI_UNSUPPORTED;\r
59 }\r
60 //\r
61 // Notes: if we seperate the int 19, then we don't need to refresh BBS\r
62 //\r
63 BdsRefreshBbsTableForBoot (Option);\r
64\r
65 //\r
66 // Write boot to OS performance data to a file\r
67 //\r
68 PERF_CODE (\r
69 WriteBootToOsPerformanceData ();\r
70 );\r
71\r
72\r
73 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Legacy Boot: %S\n", Option->Description));\r
74 return LegacyBios->LegacyBoot (\r
75 LegacyBios,\r
76 (BBS_BBS_DEVICE_PATH *) Option->DevicePath,\r
77 Option->LoadOptionsSize,\r
78 Option->LoadOptions\r
79 );\r
80}\r
81\r
82EFI_STATUS\r
83BdsLibBootViaBootOption (\r
84 IN BDS_COMMON_OPTION * Option,\r
85 IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,\r
86 OUT UINTN *ExitDataSize,\r
87 OUT CHAR16 **ExitData OPTIONAL\r
88 )\r
89/*++\r
90\r
91Routine Description:\r
92\r
93 Process the boot option follow the EFI 1.1 specification and\r
94 special treat the legacy boot option with BBS_DEVICE_PATH.\r
95\r
96Arguments:\r
97\r
98 Option - The boot option need to be processed\r
99\r
100 DevicePath - The device path which describe where to load\r
101 the boot image or the legcy BBS device path\r
102 to boot the legacy OS\r
103\r
104 ExitDataSize - Returned directly from gBS->StartImage ()\r
105\r
106 ExitData - Returned directly from gBS->StartImage ()\r
107\r
108Returns:\r
109\r
110 EFI_SUCCESS - Status from gBS->StartImage (),\r
111 or BdsBootByDiskSignatureAndPartition ()\r
112\r
113 EFI_NOT_FOUND - If the Device Path is not found in the system\r
114\r
115--*/\r
116{\r
117 EFI_STATUS Status;\r
118 EFI_HANDLE Handle;\r
119 EFI_HANDLE ImageHandle;\r
120 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
121 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
122 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
869f8e34 123 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
124 VOID *Buffer;\r
76bb6efe 125 LIST_ENTRY TempBootLists;\r
869f8e34 126\r
127 //\r
128 // Record the performance data for End of BDS\r
129 //\r
130 PERF_END (0, BDS_TOK, NULL, 0);\r
131\r
132 *ExitDataSize = 0;\r
133 *ExitData = NULL;\r
134\r
135 //\r
136 // Notes: put EFI64 ROM Shadow Solution\r
137 //\r
138 EFI64_SHADOW_ALL_LEGACY_ROM ();\r
139\r
869f8e34 140 //\r
141 // If it's Device Path that starts with a hard drive path,\r
142 // this routine will do the booting.\r
143 //\r
144 Status = BdsBootByDiskSignatureAndPartition (\r
145 Option,\r
146 (HARDDRIVE_DEVICE_PATH *) DevicePath,\r
147 Option->LoadOptionsSize,\r
148 Option->LoadOptions,\r
149 ExitDataSize,\r
150 ExitData\r
151 );\r
152 if (!EFI_ERROR (Status)) {\r
153 //\r
154 // If we found a disk signature and partition device path return success\r
155 //\r
156 return EFI_SUCCESS;\r
157 }\r
158 //\r
159 // Signal the EFI_EVENT_SIGNAL_READY_TO_BOOT event\r
160 //\r
161 EfiSignalEventReadyToBoot ();\r
162\r
163 //\r
164 // Set Boot Current\r
165 //\r
166 gRT->SetVariable (\r
167 L"BootCurrent",\r
168 &gEfiGlobalVariableGuid,\r
169 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
170 sizeof (UINT16),\r
171 &Option->BootCurrent\r
172 );\r
173\r
174 if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
175 (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
176 ) {\r
177 //\r
178 // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
179 //\r
180 return BdsLibDoLegacyBoot (Option);\r
181 }\r
76bb6efe
LG
182 \r
183 //\r
184 // If the boot option point to Internal FV shell, make sure it is valid\r
185 //\r
186 Status = UpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);\r
187 if (!EFI_ERROR(Status)) {\r
188 if (Option->DevicePath != NULL) {\r
189 FreePool (Option->DevicePath);\r
190 }\r
191 Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
192 CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
193 //\r
194 // Update the shell boot option\r
195 //\r
196 InitializeListHead (&TempBootLists);\r
197 BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder"); \r
198 }\r
869f8e34 199\r
200 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Booting EFI 1.1 way %S\n", Option->Description));\r
201\r
202 Status = gBS->LoadImage (\r
203 TRUE,\r
204 mBdsImageHandle,\r
205 DevicePath,\r
206 NULL,\r
207 0,\r
208 &ImageHandle\r
209 );\r
210\r
211 //\r
212 // If we didn't find an image, we may need to load the default\r
213 // boot behavior for the device.\r
214 //\r
215 if (EFI_ERROR (Status)) {\r
216 //\r
217 // Find a Simple File System protocol on the device path. If the remaining\r
218 // device path is set to end then no Files are being specified, so try\r
219 // the removable media file name.\r
220 //\r
221 TempDevicePath = DevicePath;\r
222 Status = gBS->LocateDevicePath (\r
223 &gEfiSimpleFileSystemProtocolGuid,\r
224 &TempDevicePath,\r
225 &Handle\r
226 );\r
227 if (!EFI_ERROR (Status) && IsDevicePathEnd (TempDevicePath)) {\r
228 FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
229 if (FilePath) {\r
230 //\r
231 // Issue a dummy read to the device to check for media change.\r
232 // When the removable media is changed, any Block IO read/write will\r
233 // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is\r
234 // returned. After the Block IO protocol is reinstalled, subsequent\r
235 // Block IO read/write will success.\r
236 //\r
237 Status = gBS->HandleProtocol (\r
238 Handle,\r
239 &gEfiBlockIoProtocolGuid,\r
240 (VOID **) &BlkIo\r
241 );\r
242 if (!EFI_ERROR (Status)) {\r
243 Buffer = AllocatePool (BlkIo->Media->BlockSize);\r
244 if (Buffer != NULL) {\r
245 BlkIo->ReadBlocks (\r
246 BlkIo,\r
247 BlkIo->Media->MediaId,\r
248 0,\r
249 BlkIo->Media->BlockSize,\r
250 Buffer\r
251 );\r
252 FreePool (Buffer);\r
253 }\r
254 }\r
255\r
256 Status = gBS->LoadImage (\r
257 TRUE,\r
258 mBdsImageHandle,\r
259 FilePath,\r
260 NULL,\r
261 0,\r
262 &ImageHandle\r
263 );\r
264 if (EFI_ERROR (Status)) {\r
265 //\r
266 // The DevicePath failed, and it's not a valid\r
267 // removable media device.\r
268 //\r
269 goto Done;\r
270 }\r
271 }\r
272 } else {\r
273 Status = EFI_NOT_FOUND;\r
274 }\r
275 }\r
276\r
277 if (EFI_ERROR (Status)) {\r
278 //\r
279 // It there is any error from the Boot attempt exit now.\r
280 //\r
281 goto Done;\r
282 }\r
283 //\r
284 // Provide the image with it's load options\r
285 //\r
286 Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &ImageInfo);\r
287 ASSERT_EFI_ERROR (Status);\r
288\r
289 if (Option->LoadOptionsSize != 0) {\r
290 ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
291 ImageInfo->LoadOptions = Option->LoadOptions;\r
292 }\r
293 //\r
294 // Before calling the image, enable the Watchdog Timer for\r
295 // the 5 Minute period\r
296 //\r
297 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
298\r
299 Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
300 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Image Return Status = %r\n", Status));\r
301\r
302 //\r
303 // Clear the Watchdog Timer after the image returns\r
304 //\r
305 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
306\r
307Done:\r
308 //\r
309 // Clear Boot Current\r
310 //\r
311 gRT->SetVariable (\r
312 L"BootCurrent",\r
313 &gEfiGlobalVariableGuid,\r
314 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
315 0,\r
316 &Option->BootCurrent\r
317 );\r
318\r
319 return Status;\r
320}\r
321\r
322EFI_STATUS\r
323BdsBootByDiskSignatureAndPartition (\r
324 IN BDS_COMMON_OPTION * Option,\r
325 IN HARDDRIVE_DEVICE_PATH * HardDriveDevicePath,\r
326 IN UINT32 LoadOptionsSize,\r
327 IN VOID *LoadOptions,\r
328 OUT UINTN *ExitDataSize,\r
329 OUT CHAR16 **ExitData OPTIONAL\r
330 )\r
331/*++\r
332\r
333Routine Description:\r
334\r
335 Check to see if a hard ware device path was passed in. If it was then search\r
336 all the block IO devices for the passed in hard drive device path.\r
337\r
338Arguments:\r
339\r
340 Option - The current processing boot option.\r
341\r
342 HardDriveDevicePath - EFI Device Path to boot, if it starts with a hard\r
343 drive device path.\r
344\r
345 LoadOptionsSize - Passed into gBS->StartImage ()\r
346 via the loaded image protocol.\r
347\r
348 LoadOptions - Passed into gBS->StartImage ()\r
349 via the loaded image protocol.\r
350\r
351 ExitDataSize - returned directly from gBS->StartImage ()\r
352\r
353 ExitData - returned directly from gBS->StartImage ()\r
354\r
355Returns:\r
356\r
357 EFI_SUCCESS - Status from gBS->StartImage (),\r
358 or BootByDiskSignatureAndPartition ()\r
359\r
360 EFI_NOT_FOUND - If the Device Path is not found in the system\r
361\r
362--*/\r
363{\r
364 EFI_STATUS Status;\r
365 UINTN BlockIoHandleCount;\r
366 EFI_HANDLE *BlockIoBuffer;\r
367 EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;\r
368 EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePath;\r
369 HARDDRIVE_DEVICE_PATH *TmpHdPath;\r
370 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
371 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
372 UINTN Index;\r
373 BOOLEAN DevicePathMatch;\r
374 HARDDRIVE_DEVICE_PATH *TempPath;\r
375\r
376 *ExitDataSize = 0;\r
377 *ExitData = NULL;\r
378\r
379 if ( !((DevicePathType (&HardDriveDevicePath->Header) == MEDIA_DEVICE_PATH) &&\r
380 (DevicePathSubType (&HardDriveDevicePath->Header) == MEDIA_HARDDRIVE_DP))\r
381 ) {\r
382 //\r
383 // If the HardDriveDevicePath does not start with a Hard Drive Device Path\r
384 // exit.\r
385 //\r
386 return EFI_NOT_FOUND;\r
387 }\r
388 //\r
389 // The boot device have already been connected\r
390 //\r
391 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
392 if (EFI_ERROR (Status) || BlockIoHandleCount == 0) {\r
393 //\r
394 // If there was an error or there are no device handles that support\r
395 // the BLOCK_IO Protocol, then return.\r
396 //\r
397 return EFI_NOT_FOUND;\r
398 }\r
399 //\r
400 // Loop through all the device handles that support the BLOCK_IO Protocol\r
401 //\r
402 for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
403\r
404 Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);\r
405 if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {\r
406 continue;\r
407 }\r
408 //\r
409 // Make PreviousDevicePath == the device path node before the end node\r
410 //\r
411 DevicePath = BlockIoDevicePath;\r
412 BlockIoHdDevicePath = NULL;\r
413\r
414 //\r
415 // find HardDriver device path node\r
416 //\r
417 while (!IsDevicePathEnd (DevicePath)) {\r
418 if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
419 (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
420 ) {\r
421 BlockIoHdDevicePath = DevicePath;\r
422 break;\r
423 }\r
424\r
425 DevicePath = NextDevicePathNode (DevicePath);\r
426 }\r
427\r
428 if (BlockIoHdDevicePath == NULL) {\r
429 continue;\r
430 }\r
431 //\r
432 // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
433 //\r
434 DevicePathMatch = FALSE;\r
435\r
436 TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePath;\r
437 TempPath = (HARDDRIVE_DEVICE_PATH *) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
438\r
439 //\r
440 // Only several fields will be checked. NOT whole NODE\r
441 //\r
442 if ( TmpHdPath->PartitionNumber == TempPath->PartitionNumber &&\r
443 TmpHdPath->MBRType == TempPath->MBRType &&\r
444 TmpHdPath->SignatureType == TempPath->SignatureType &&\r
445 CompareGuid ((EFI_GUID *) TmpHdPath->Signature, (EFI_GUID *) TempPath->Signature)) {\r
446 //\r
447 // Get the matched device path\r
448 //\r
449 DevicePathMatch = TRUE;\r
450 }\r
451 //\r
452 // Only do the boot, when devicepath match\r
453 //\r
454 if (DevicePathMatch) {\r
455 //\r
456 // Combine the Block IO and Hard Drive Device path together and try\r
457 // to boot from it.\r
458 //\r
459 DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
460 NewDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
461\r
462 //\r
463 // Recursive boot with new device path\r
464 //\r
465 Status = BdsLibBootViaBootOption (Option, NewDevicePath, ExitDataSize, ExitData);\r
466 if (!EFI_ERROR (Status)) {\r
467 break;\r
468 }\r
469 }\r
470 }\r
471\r
472 FreePool (BlockIoBuffer);\r
473 return Status;\r
474}\r
475\r
476EFI_STATUS\r
477BdsLibDeleteOptionFromHandle (\r
478 IN EFI_HANDLE Handle\r
479 )\r
480/*++\r
481\r
482Routine Description:\r
483\r
484 Delete the boot option associated with the handle passed in\r
485\r
486Arguments:\r
487\r
488 Handle - The handle which present the device path to create boot option\r
489\r
490Returns:\r
491\r
492 EFI_SUCCESS - Delete the boot option success\r
493\r
494 EFI_NOT_FOUND - If the Device Path is not found in the system\r
495\r
496 EFI_OUT_OF_RESOURCES - Lack of memory resource\r
497\r
498 Other - Error return value from SetVariable()\r
499\r
500--*/\r
501{\r
502 UINT16 *BootOrder;\r
503 UINT8 *BootOptionVar;\r
504 UINTN BootOrderSize;\r
505 UINTN BootOptionSize;\r
506 EFI_STATUS Status;\r
507 UINTN Index;\r
508 UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
509 UINTN DevicePathSize;\r
510 UINTN OptionDevicePathSize;\r
511 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
512 EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
513 UINT8 *TempPtr;\r
514 CHAR16 *Description;\r
515\r
516 Status = EFI_SUCCESS;\r
517 BootOrder = NULL;\r
518 BootOrderSize = 0;\r
519\r
520 BootOrder = BdsLibGetVariableAndSize (\r
521 L"BootOrder",\r
522 &gEfiGlobalVariableGuid,\r
523 &BootOrderSize\r
524 );\r
525 if (NULL == BootOrder) {\r
526 return EFI_NOT_FOUND;\r
527 }\r
528\r
529 DevicePath = DevicePathFromHandle (Handle);\r
530 if (DevicePath == NULL) {\r
531 return EFI_NOT_FOUND;\r
532 }\r
533 DevicePathSize = GetDevicePathSize (DevicePath);\r
534\r
535 Index = 0;\r
536 while (Index < BootOrderSize / sizeof (UINT16)) {\r
537 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
538 BootOptionVar = BdsLibGetVariableAndSize (\r
539 BootOption,\r
540 &gEfiGlobalVariableGuid,\r
541 &BootOptionSize\r
542 );\r
543 if (NULL == BootOptionVar) {\r
544 FreePool (BootOrder);\r
545 return EFI_OUT_OF_RESOURCES;\r
546 }\r
547\r
548 TempPtr = BootOptionVar;\r
549 TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
550 Description = (CHAR16 *) TempPtr;\r
551 TempPtr += StrSize ((CHAR16 *) TempPtr);\r
552 OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
553 OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);\r
554\r
555 //\r
556 // Check whether the device path match\r
557 //\r
558 if ((OptionDevicePathSize == DevicePathSize) &&\r
559 (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {\r
560 BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
561 FreePool (BootOptionVar);\r
562 break;\r
563 }\r
564\r
565 FreePool (BootOptionVar);\r
566 Index++;\r
567 }\r
568\r
569 Status = gRT->SetVariable (\r
570 L"BootOrder",\r
571 &gEfiGlobalVariableGuid,\r
572 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
573 BootOrderSize,\r
574 BootOrder\r
575 );\r
576\r
577 FreePool (BootOrder);\r
578\r
579 return Status;\r
580}\r
581\r
582EFI_STATUS\r
583BdsDeleteAllInvalidEfiBootOption (\r
584 VOID\r
585 )\r
586/*++\r
587\r
588Routine Description:\r
589\r
590 Delete all invalid EFI boot options. The probable invalid boot option could\r
591 be Removable media or Network boot device.\r
592\r
593Arguments:\r
594\r
595 VOID\r
596\r
597Returns:\r
598\r
599 EFI_SUCCESS - Delete all invalid boot option success\r
600\r
601 EFI_NOT_FOUND - Variable "BootOrder" is not found\r
602\r
603 EFI_OUT_OF_RESOURCES - Lack of memory resource\r
604\r
605 Other - Error return value from SetVariable()\r
606\r
607--*/\r
608{\r
609 UINT16 *BootOrder;\r
610 UINT8 *BootOptionVar;\r
611 UINTN BootOrderSize;\r
612 UINTN BootOptionSize;\r
613 EFI_STATUS Status;\r
614 UINTN Index;\r
615 UINTN Index2;\r
616 UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
617 UINTN OptionDevicePathSize;\r
618 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
619 EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
620 EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
621 UINT8 *TempPtr;\r
622 CHAR16 *Description;\r
623 EFI_HANDLE Handle;\r
624 BOOLEAN NeedDelete;\r
625\r
626 Status = EFI_SUCCESS;\r
627 BootOrder = NULL;\r
628 BootOrderSize = 0;\r
629\r
630 BootOrder = BdsLibGetVariableAndSize (\r
631 L"BootOrder",\r
632 &gEfiGlobalVariableGuid,\r
633 &BootOrderSize\r
634 );\r
635 if (NULL == BootOrder) {\r
636 return EFI_NOT_FOUND;\r
637 }\r
638\r
639 Index = 0;\r
640 while (Index < BootOrderSize / sizeof (UINT16)) {\r
641 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
642 BootOptionVar = BdsLibGetVariableAndSize (\r
643 BootOption,\r
644 &gEfiGlobalVariableGuid,\r
645 &BootOptionSize\r
646 );\r
647 if (NULL == BootOptionVar) {\r
648 FreePool (BootOrder);\r
649 return EFI_OUT_OF_RESOURCES;\r
650 }\r
651\r
652 TempPtr = BootOptionVar;\r
653 TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
654 Description = (CHAR16 *) TempPtr;\r
655 TempPtr += StrSize ((CHAR16 *) TempPtr);\r
656 OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
657 OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);\r
658\r
659 //\r
660 // Skip legacy boot option (BBS boot device)\r
661 //\r
662 if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&\r
663 (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {\r
664 FreePool (BootOptionVar);\r
665 Index++;\r
666 continue;\r
667 }\r
668\r
669 TempDevicePath = OptionDevicePath;\r
670 LastDeviceNode = OptionDevicePath;\r
671 while (!EfiIsDevicePathEnd (TempDevicePath)) {\r
672 LastDeviceNode = TempDevicePath;\r
673 TempDevicePath = EfiNextDevicePathNode (TempDevicePath);\r
674 }\r
675 //\r
676 // Skip the boot option that point to a file, since the device path in\r
677 // removable media boot option doesn't contains a file name.\r
678 //\r
679 if (((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&\r
680 (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) ||\r
681 //\r
682 // Skip boot option for internal Shell, it's always valid\r
683 //\r
684 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL)) {\r
685 FreePool (BootOptionVar);\r
686 Index++;\r
687 continue;\r
688 }\r
689\r
690 NeedDelete = TRUE;\r
691 //\r
692 // Check if it's a valid boot option for removable media\r
693 //\r
694 TempDevicePath = OptionDevicePath;\r
695 Status = gBS->LocateDevicePath (\r
696 &gEfiSimpleFileSystemProtocolGuid,\r
697 &TempDevicePath,\r
698 &Handle\r
699 );\r
700 if (!EFI_ERROR (Status)) {\r
701 NeedDelete = FALSE;\r
702 }\r
703 //\r
704 // Check if it's a valid boot option for network boot device\r
705 //\r
706 TempDevicePath = OptionDevicePath;\r
707 Status = gBS->LocateDevicePath (\r
708 &gEfiLoadFileProtocolGuid,\r
709 &TempDevicePath,\r
710 &Handle\r
711 );\r
712 if (!EFI_ERROR (Status)) {\r
713 NeedDelete = FALSE;\r
714 }\r
715\r
716 if (NeedDelete) {\r
717 //\r
718 // Delete this invalid boot option "Boot####"\r
719 //\r
720 Status = gRT->SetVariable (\r
721 BootOption,\r
722 &gEfiGlobalVariableGuid,\r
723 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
724 0,\r
725 NULL\r
726 );\r
727 //\r
728 // Mark this boot option in boot order as deleted\r
729 //\r
730 BootOrder[Index] = 0xffff;\r
731 }\r
732\r
733 FreePool (BootOptionVar);\r
734 Index++;\r
735 }\r
736\r
737 //\r
738 // Adjust boot order array\r
739 //\r
740 Index2 = 0;\r
741 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
742 if (BootOrder[Index] != 0xffff) {\r
743 BootOrder[Index2] = BootOrder[Index];\r
744 Index2 ++;\r
745 }\r
746 }\r
747 Status = gRT->SetVariable (\r
748 L"BootOrder",\r
749 &gEfiGlobalVariableGuid,\r
750 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
751 Index2 * sizeof (UINT16),\r
752 BootOrder\r
753 );\r
754\r
755 FreePool (BootOrder);\r
756\r
757 return Status;\r
758}\r
759\r
760EFI_STATUS\r
761BdsLibEnumerateAllBootOption (\r
762 IN OUT LIST_ENTRY *BdsBootOptionList\r
763 )\r
764/*++\r
765\r
766Routine Description:\r
767\r
768 This function will enumerate all possible boot device in the system,\r
769 it will only excute once of every boot.\r
770\r
771Arguments:\r
772\r
773 BdsBootOptionList - The header of the link list which indexed all\r
774 current boot options\r
775\r
776Returns:\r
777\r
778 EFI_SUCCESS - Finished all the boot device enumerate and create\r
779 the boot option base on that boot device\r
780\r
781--*/\r
782{\r
783 EFI_STATUS Status;\r
784 UINT16 BootOptionNumber;\r
785 UINTN NumberFileSystemHandles;\r
786 EFI_HANDLE *FileSystemHandles;\r
787 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
788 UINTN Index;\r
789 UINTN NumberLoadFileHandles;\r
790 EFI_HANDLE *LoadFileHandles;\r
791 VOID *ProtocolInstance;\r
e1001af1 792 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
869f8e34 793 UINTN FvHandleCount;\r
794 EFI_HANDLE *FvHandleBuffer;\r
795 EFI_FV_FILETYPE Type;\r
796 UINTN Size;\r
797 EFI_FV_FILE_ATTRIBUTES Attributes;\r
798 UINT32 AuthenticationStatus;\r
799 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
800 EFI_HANDLE ImageHandle;\r
801 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
802 BOOLEAN NeedDelete;\r
803\r
804 BootOptionNumber = 0;\r
805\r
806 //\r
807 // If the boot device enumerate happened, just get the boot\r
808 // device from the boot order variable\r
809 //\r
810 if (mEnumBootDevice) {\r
811 BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
812 return EFI_SUCCESS;\r
813 }\r
814 //\r
815 // Notes: this dirty code is to get the legacy boot option from the\r
816 // BBS table and create to variable as the EFI boot option, it should\r
817 // be removed after the CSM can provide legacy boot option directly\r
818 //\r
819 REFRESH_LEGACY_BOOT_OPTIONS;\r
820\r
821 //\r
822 // Delete invalid boot option\r
823 //\r
824 BdsDeleteAllInvalidEfiBootOption ();\r
825 //\r
826 // Parse removable media\r
827 //\r
828 gBS->LocateHandleBuffer (\r
829 ByProtocol,\r
830 &gEfiSimpleFileSystemProtocolGuid,\r
831 NULL,\r
832 &NumberFileSystemHandles,\r
833 &FileSystemHandles\r
834 );\r
835 for (Index = 0; Index < NumberFileSystemHandles; Index++) {\r
836 Status = gBS->HandleProtocol (\r
837 FileSystemHandles[Index],\r
838 &gEfiBlockIoProtocolGuid,\r
839 (VOID **) &BlkIo\r
840 );\r
841 if (!EFI_ERROR (Status)) {\r
842 if (!BlkIo->Media->RemovableMedia) {\r
843 //\r
844 // If the file system handle supports a BlkIo protocol,\r
845 // skip the removable media devices\r
846 //\r
847 continue;\r
848 }\r
849 }\r
850\r
851 //\r
852 // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI\r
853 // machinename is ia32, ia64, x64, ...\r
854 //\r
855 FilePath = FileDevicePath (FileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);\r
856 NeedDelete = TRUE;\r
857 Status = gBS->LoadImage (\r
858 TRUE,\r
859 mBdsImageHandle,\r
860 FilePath,\r
861 NULL,\r
862 0,\r
863 &ImageHandle\r
864 );\r
865 if (!EFI_ERROR(Status)) {\r
866 //\r
867 // Verify the image is a EFI application (and not a driver)\r
868 //\r
869 Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
870 ASSERT (!EFI_ERROR(Status));\r
871\r
872 if (ImageInfo->ImageCodeType == EfiLoaderCode) {\r
873 NeedDelete = FALSE;\r
874 }\r
875 }\r
876\r
877 if (NeedDelete) {\r
878 //\r
879 // No such file or the file is not a EFI application, delete this boot option\r
880 //\r
881 BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
882 } else {\r
883 BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList);\r
884 BootOptionNumber++;\r
885 }\r
886 }\r
887\r
888 if (NumberFileSystemHandles) {\r
889 FreePool (FileSystemHandles);\r
890 }\r
891 //\r
892 // Parse Network Boot Device\r
893 //\r
894 gBS->LocateHandleBuffer (\r
895 ByProtocol,\r
896 &gEfiSimpleNetworkProtocolGuid,\r
897 NULL,\r
898 &NumberLoadFileHandles,\r
899 &LoadFileHandles\r
900 );\r
901 for (Index = 0; Index < NumberLoadFileHandles; Index++) {\r
902 Status = gBS->HandleProtocol (\r
903 LoadFileHandles[Index],\r
904 &gEfiLoadFileProtocolGuid,\r
905 (VOID **) &ProtocolInstance\r
906 );\r
907 if (EFI_ERROR (Status)) {\r
908 continue;\r
909 }\r
910\r
911 BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList);\r
912 BootOptionNumber++;\r
913 }\r
914\r
915 if (NumberLoadFileHandles) {\r
916 FreePool (LoadFileHandles);\r
917 }\r
918 //\r
919 // Check if we have on flash shell\r
920 //\r
921 gBS->LocateHandleBuffer (\r
922 ByProtocol,\r
e1001af1 923 &gEfiFirmwareVolume2ProtocolGuid,\r
869f8e34 924 NULL,\r
925 &FvHandleCount,\r
926 &FvHandleBuffer\r
927 );\r
928 for (Index = 0; Index < FvHandleCount; Index++) {\r
929 gBS->HandleProtocol (\r
930 FvHandleBuffer[Index],\r
e1001af1 931 &gEfiFirmwareVolume2ProtocolGuid,\r
869f8e34 932 (VOID **) &Fv\r
933 );\r
934\r
935 Status = Fv->ReadFile (\r
936 Fv,\r
937 &gEfiShellFileGuid,\r
938 NULL,\r
939 &Size,\r
940 &Type,\r
941 &Attributes,\r
942 &AuthenticationStatus\r
943 );\r
944 if (EFI_ERROR (Status)) {\r
945 //\r
946 // Skip if no shell file in the FV\r
947 //\r
948 continue;\r
949 }\r
950 //\r
951 // Build the shell boot option\r
952 //\r
953 BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);\r
954 BootOptionNumber++;\r
955 }\r
956\r
957 if (FvHandleCount) {\r
958 FreePool (FvHandleBuffer);\r
959 }\r
960 //\r
961 // Make sure every boot only have one time\r
962 // boot device enumerate\r
963 //\r
964 BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
965 mEnumBootDevice = TRUE;\r
966\r
967 return EFI_SUCCESS;\r
968}\r
969\r
970VOID\r
971BdsLibBuildOptionFromHandle (\r
972 IN EFI_HANDLE Handle,\r
973 IN LIST_ENTRY *BdsBootOptionList\r
974 )\r
975/*++\r
976\r
977Routine Description:\r
978\r
979 Build the boot option with the handle parsed in\r
980\r
981Arguments:\r
982\r
983 Handle - The handle which present the device path to create boot option\r
984\r
985 BdsBootOptionList - The header of the link list which indexed all current\r
986 boot options\r
987\r
988Returns:\r
989\r
990 VOID\r
991\r
992--*/\r
993{\r
994 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
995 CHAR16 *TempString;\r
996\r
997 DevicePath = DevicePathFromHandle (Handle);\r
998 TempString = DevicePathToStr (DevicePath);\r
999\r
1000 //\r
1001 // Create and register new boot option\r
1002 //\r
1003 BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, TempString, L"BootOrder");\r
1004}\r
1005\r
1006VOID\r
1007BdsLibBuildOptionFromShell (\r
1008 IN EFI_HANDLE Handle,\r
1009 IN OUT LIST_ENTRY *BdsBootOptionList\r
1010 )\r
1011/*++\r
1012\r
1013Routine Description:\r
1014\r
1015 Build the on flash shell boot option with the handle parsed in\r
1016\r
1017Arguments:\r
1018\r
1019 Handle - The handle which present the device path to create on flash shell\r
1020 boot option\r
1021\r
1022 BdsBootOptionList - The header of the link list which indexed all current\r
1023 boot options\r
1024\r
1025Returns:\r
1026\r
1027 None\r
1028\r
1029--*/\r
1030{\r
1031 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1032 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;\r
1033\r
1034 DevicePath = DevicePathFromHandle (Handle);\r
1035\r
1036 //\r
1037 // Build the shell device path\r
1038 //\r
1039 EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);\r
1040 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
1041\r
1042 //\r
1043 // Create and register the shell boot option\r
1044 //\r
1045 BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"Internal EFI Shell", L"BootOrder");\r
1046\r
1047}\r
1048\r
1049VOID\r
1050BdsLibBootNext (\r
1051 VOID\r
1052 )\r
1053/*++\r
1054\r
1055Routine Description:\r
1056\r
1057 Boot from the EFI1.1 spec defined "BootNext" variable\r
1058\r
1059Arguments:\r
1060\r
1061 None\r
1062\r
1063Returns:\r
1064\r
1065 None\r
1066\r
1067--*/\r
1068{\r
1069 UINT16 *BootNext;\r
1070 UINTN BootNextSize;\r
1071 CHAR16 Buffer[20];\r
1072 BDS_COMMON_OPTION *BootOption;\r
1073 LIST_ENTRY TempList;\r
1074 UINTN ExitDataSize;\r
1075 CHAR16 *ExitData;\r
1076\r
1077 //\r
1078 // Init the boot option name buffer and temp link list\r
1079 //\r
1080 InitializeListHead (&TempList);\r
1081 ZeroMem (Buffer, sizeof (Buffer));\r
1082\r
1083 BootNext = BdsLibGetVariableAndSize (\r
1084 L"BootNext",\r
1085 &gEfiGlobalVariableGuid,\r
1086 &BootNextSize\r
1087 );\r
1088\r
1089 //\r
1090 // Clear the boot next variable first\r
1091 //\r
1092 if (BootNext != NULL) {\r
1093 gRT->SetVariable (\r
1094 L"BootNext",\r
1095 &gEfiGlobalVariableGuid,\r
1096 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1097 0,\r
1098 BootNext\r
1099 );\r
1100\r
1101 //\r
1102 // Start to build the boot option and try to boot\r
1103 //\r
1104 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);\r
1105 BootOption = BdsLibVariableToOption (&TempList, Buffer);\r
1106 BdsLibConnectDevicePath (BootOption->DevicePath);\r
1107 BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
1108 }\r
1109\r
1110}\r
76bb6efe
LG
1111\r
1112EFI_STATUS\r
1113EFIAPI\r
1114UpdateFvFileDevicePath (\r
1115 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
1116 IN EFI_GUID *FileGuid\r
1117 )\r
1118/*++\r
1119\r
1120Routine Description:\r
1121 According to a file guild, check a Fv file device path is valid. If it is invalid,\r
1122 try to return the valid device path.\r
1123 FV address maybe changes for memory layout adjust from time to time, use this funciton \r
1124 could promise the Fv file device path is right.\r
1125\r
1126Arguments:\r
1127 DevicePath - on input, the Fv file device path need to check\r
1128 on output, the updated valid Fv file device path\r
1129 \r
1130 FileGuid - the Fv file guild\r
1131 \r
1132Returns:\r
1133 EFI_INVALID_PARAMETER - the input DevicePath or FileGuid is invalid parameter\r
1134 EFI_UNSUPPORTED - the input DevicePath does not contain Fv file guild at all\r
1135 EFI_ALREADY_STARTED - the input DevicePath has pointed to Fv file, it is valid\r
1136 EFI_SUCCESS - has successfully updated the invalid DevicePath, and return the updated\r
1137 device path in DevicePath\r
1138 \r
1139--*/\r
1140{\r
1141 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1142 EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
1143 EFI_STATUS Status;\r
1144 EFI_GUID *GuidPoint;\r
1145 UINTN Index;\r
1146 UINTN FvHandleCount;\r
1147 EFI_HANDLE *FvHandleBuffer;\r
1148 EFI_FV_FILETYPE Type;\r
1149 UINTN Size;\r
1150 EFI_FV_FILE_ATTRIBUTES Attributes;\r
1151 UINT32 AuthenticationStatus;\r
1152 BOOLEAN FindFvFile;\r
1153 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
1154 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
1155 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;\r
1156 EFI_HANDLE FoundFvHandle;\r
1157 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
1158 \r
1159 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
1160 return EFI_INVALID_PARAMETER;\r
1161 }\r
1162 if (FileGuid == NULL) {\r
1163 return EFI_INVALID_PARAMETER;\r
1164 }\r
1165 //\r
1166 // Check whether the device path point to the default the input Fv file\r
1167 //\r
1168 TempDevicePath = *DevicePath; \r
1169 LastDeviceNode = TempDevicePath;\r
1170 while (!EfiIsDevicePathEnd (TempDevicePath)) {\r
1171 LastDeviceNode = TempDevicePath;\r
1172 TempDevicePath = EfiNextDevicePathNode (TempDevicePath);\r
1173 }\r
1174\r
1175 GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LastDeviceNode);\r
1176\r
1177 if (GuidPoint == NULL) {\r
1178 //\r
1179 // if this option does not points to a Fv file, just return EFI_UNSUPPORTED\r
1180 //\r
1181 return EFI_UNSUPPORTED;\r
1182 }\r
1183\r
1184 if (!CompareGuid (GuidPoint, FileGuid)) {\r
1185 //\r
1186 // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED\r
1187 //\r
1188 return EFI_UNSUPPORTED;\r
1189 }\r
1190 \r
1191 //\r
1192 // Check whether the input Fv file device path is valid\r
1193 //\r
1194 TempDevicePath = *DevicePath; \r
1195 FoundFvHandle = NULL;\r
1196 Status = gBS->LocateDevicePath (\r
1197 &gEfiFirmwareVolume2ProtocolGuid,\r
1198 &TempDevicePath, \r
1199 &FoundFvHandle\r
1200 );\r
1201 if (!EFI_ERROR (Status)) {\r
1202 Status = gBS->HandleProtocol (\r
1203 FoundFvHandle,\r
1204 &gEfiFirmwareVolume2ProtocolGuid,\r
1205 (VOID **) &Fv\r
1206 );\r
1207 if (!EFI_ERROR (Status)) {\r
1208 //\r
1209 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there\r
1210 //\r
1211 Status = Fv->ReadFile (\r
1212 Fv,\r
1213 FileGuid,\r
1214 NULL,\r
1215 &Size,\r
1216 &Type,\r
1217 &Attributes,\r
1218 &AuthenticationStatus\r
1219 );\r
1220 if (!EFI_ERROR (Status)) {\r
1221 return EFI_ALREADY_STARTED;\r
1222 }\r
1223 }\r
1224 }\r
1225 \r
1226 //\r
1227 // Look for the input wanted FV file in current FV\r
1228 // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV\r
1229 //\r
1230 FindFvFile = FALSE;\r
1231 FoundFvHandle = NULL;\r
1232 Status = gBS->HandleProtocol (\r
1233 mBdsImageHandle,\r
1234 &gEfiLoadedImageProtocolGuid,\r
1235 &LoadedImage\r
1236 );\r
1237 if (!EFI_ERROR (Status)) {\r
1238 Status = gBS->HandleProtocol (\r
1239 LoadedImage->DeviceHandle,\r
1240 &gEfiFirmwareVolume2ProtocolGuid,\r
1241 (VOID **) &Fv\r
1242 );\r
1243 if (!EFI_ERROR (Status)) {\r
1244 Status = Fv->ReadFile (\r
1245 Fv,\r
1246 FileGuid,\r
1247 NULL,\r
1248 &Size,\r
1249 &Type,\r
1250 &Attributes,\r
1251 &AuthenticationStatus\r
1252 );\r
1253 if (!EFI_ERROR (Status)) {\r
1254 FindFvFile = TRUE;\r
1255 FoundFvHandle = LoadedImage->DeviceHandle;\r
1256 }\r
1257 }\r
1258 }\r
1259 //\r
1260 // Second, if fail to find, try to enumerate all FV\r
1261 //\r
1262 if (!FindFvFile) {\r
1263 gBS->LocateHandleBuffer (\r
1264 ByProtocol,\r
1265 &gEfiFirmwareVolume2ProtocolGuid,\r
1266 NULL,\r
1267 &FvHandleCount,\r
1268 &FvHandleBuffer\r
1269 );\r
1270 for (Index = 0; Index < FvHandleCount; Index++) {\r
1271 gBS->HandleProtocol (\r
1272 FvHandleBuffer[Index],\r
1273 &gEfiFirmwareVolume2ProtocolGuid,\r
1274 (VOID **) &Fv\r
1275 );\r
1276\r
1277 Status = Fv->ReadFile (\r
1278 Fv,\r
1279 FileGuid,\r
1280 NULL,\r
1281 &Size,\r
1282 &Type,\r
1283 &Attributes,\r
1284 &AuthenticationStatus\r
1285 );\r
1286 if (EFI_ERROR (Status)) {\r
1287 //\r
1288 // Skip if input Fv file not in the FV\r
1289 //\r
1290 continue;\r
1291 }\r
1292 FindFvFile = TRUE;\r
1293 FoundFvHandle = FvHandleBuffer[Index];\r
1294 break;\r
1295 } \r
1296 }\r
1297\r
1298 if (FindFvFile) {\r
1299 //\r
1300 // Build the shell device path\r
1301 //\r
1302 NewDevicePath = DevicePathFromHandle (FoundFvHandle);\r
1303 EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);\r
1304 NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);\r
1305 *DevicePath = NewDevicePath;\r
1306 return EFI_SUCCESS;\r
1307 }\r
1308\r
1309 return EFI_NOT_FOUND;\r
1310}\r