c9b1eede1c4a2794fa5e5bb4d9d414529afd380c
[people/mcb30/edk2.git] / edk2 / EdkNt32Pkg / Library / EdkGenericBdsLib / BdsBoot.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   BdsBoot.c\r
15 \r
16 Abstract:\r
17 \r
18   BDS Lib functions which relate with create or process the boot\r
19   option.\r
20 \r
21 --*/\r
22 #include "Performance.h"\r
23 \r
24 BOOLEAN mEnumBootDevice = FALSE;\r
25 \r
26 EFI_STATUS\r
27 BdsLibDoLegacyBoot (\r
28   IN  BDS_COMMON_OPTION           *Option\r
29   )\r
30 /*++\r
31 \r
32 Routine Description:\r
33  \r
34   Boot the legacy system with the boot option\r
35 \r
36 Arguments:\r
37 \r
38   Option           - The legacy boot option which have BBS device path\r
39 \r
40 Returns:\r
41 \r
42   EFI_UNSUPPORTED  - There is no legacybios protocol, do not support\r
43                      legacy boot.\r
44                          \r
45   EFI_STATUS       - Return the status of LegacyBios->LegacyBoot ().\r
46 \r
47 --*/\r
48 {\r
49   EFI_STATUS                Status;\r
50   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
51 \r
52   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);\r
53   if (EFI_ERROR (Status)) {\r
54     //\r
55     // If no LegacyBios protocol we do not support legacy boot\r
56     //\r
57     return EFI_UNSUPPORTED;\r
58   }\r
59   //\r
60   // Notes: if we seperate the int 19, then we don't need to refresh BBS\r
61   //\r
62   BdsRefreshBbsTableForBoot (Option);\r
63 \r
64   //\r
65   // Write boot to OS performance data to a file\r
66   //\r
67   PERF_CODE (\r
68     WriteBootToOsPerformanceData ();\r
69   );\r
70 \r
71 \r
72   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Legacy Boot: %S\n", Option->Description));\r
73   return LegacyBios->LegacyBoot (\r
74                       LegacyBios,\r
75                       (BBS_BBS_DEVICE_PATH *) Option->DevicePath,\r
76                       Option->LoadOptionsSize,\r
77                       Option->LoadOptions\r
78                       );\r
79 }\r
80 \r
81 EFI_STATUS\r
82 BdsLibBootViaBootOption (\r
83   IN  BDS_COMMON_OPTION             * Option,\r
84   IN  EFI_DEVICE_PATH_PROTOCOL      * DevicePath,\r
85   OUT UINTN                         *ExitDataSize,\r
86   OUT CHAR16                        **ExitData OPTIONAL\r
87   )\r
88 /*++\r
89 \r
90 Routine Description:\r
91 \r
92   Process the boot option follow the EFI 1.1 specification and \r
93   special treat the legacy boot option with BBS_DEVICE_PATH.\r
94 \r
95 Arguments:\r
96 \r
97   Option       - The boot option need to be processed\r
98   \r
99   DevicePath   - The device path which describe where to load \r
100                  the boot image or the legcy BBS device path \r
101                  to boot the legacy OS\r
102 \r
103   ExitDataSize - Returned directly from gBS->StartImage ()\r
104 \r
105   ExitData     - Returned directly from gBS->StartImage ()\r
106 \r
107 Returns:\r
108 \r
109   EFI_SUCCESS   - Status from gBS->StartImage (),\r
110                   or BdsBootByDiskSignatureAndPartition ()\r
111 \r
112   EFI_NOT_FOUND - If the Device Path is not found in the system\r
113 \r
114 --*/\r
115 {\r
116   EFI_STATUS                Status;\r
117   EFI_HANDLE                Handle;\r
118   EFI_HANDLE                ImageHandle;\r
119   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
120   EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
121   EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
122   EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;\r
123 \r
124   *ExitDataSize = 0;\r
125   *ExitData     = NULL;\r
126 \r
127   //\r
128   // Notes: put EFI64 ROM Shadow Solution\r
129   //\r
130   EFI64_SHADOW_ALL_LEGACY_ROM ();\r
131 \r
132   //\r
133   // Notes: this code can be remove after the s3 script table\r
134   // hook on the event EFI_EVENT_SIGNAL_READY_TO_BOOT or\r
135   // EFI_EVENT_SIGNAL_LEGACY_BOOT\r
136   //\r
137   Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, &AcpiS3Save);\r
138   if (!EFI_ERROR (Status)) {\r
139     AcpiS3Save->S3Save (AcpiS3Save, NULL);\r
140   }\r
141   //\r
142   // If it's Device Path that starts with a hard drive path,\r
143   // this routine will do the booting.\r
144   //\r
145   Status = BdsBootByDiskSignatureAndPartition (\r
146             Option,\r
147             (HARDDRIVE_DEVICE_PATH *) DevicePath,\r
148             Option->LoadOptionsSize,\r
149             Option->LoadOptions,\r
150             ExitDataSize,\r
151             ExitData\r
152             );\r
153   if (!EFI_ERROR (Status)) {\r
154     //\r
155     // If we found a disk signature and partition device path return success\r
156     //\r
157     return EFI_SUCCESS;\r
158   }\r
159 \r
160   EfiSignalEventReadyToBoot ();\r
161 \r
162   //\r
163   // Set Boot Current\r
164   //\r
165   gRT->SetVariable (\r
166         L"BootCurrent",\r
167         &gEfiGlobalVariableGuid,\r
168         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
169         sizeof (UINT16),\r
170         &Option->BootCurrent\r
171         );\r
172 \r
173   if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
174       (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
175     ) {\r
176     //\r
177     // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
178     //\r
179     return BdsLibDoLegacyBoot (Option);\r
180   }\r
181 \r
182   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Booting EFI 1.1 way %S\n", Option->Description));\r
183 \r
184   Status = gBS->LoadImage (\r
185                   TRUE,\r
186                   mBdsImageHandle,\r
187                   DevicePath,\r
188                   NULL,\r
189                   0,\r
190                   &ImageHandle\r
191                   );\r
192 \r
193   //\r
194   // If we didn't find an image, we may need to load the default\r
195   // boot behavior for the device.\r
196   //\r
197   if (EFI_ERROR (Status)) {\r
198     //\r
199     // Find a Simple File System protocol on the device path. If the remaining\r
200     // device path is set to end then no Files are being specified, so try\r
201     // the removable media file name.\r
202     //\r
203     TempDevicePath = DevicePath;\r
204     Status = gBS->LocateDevicePath (\r
205                     &gEfiSimpleFileSystemProtocolGuid,\r
206                     &TempDevicePath,\r
207                     &Handle\r
208                     );\r
209     if (!EFI_ERROR (Status) && IsDevicePathEnd (TempDevicePath)) {\r
210       FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
211       if (FilePath) {\r
212         Status = gBS->LoadImage (\r
213                         TRUE,\r
214                         mBdsImageHandle,\r
215                         FilePath,\r
216                         NULL,\r
217                         0,\r
218                         &ImageHandle\r
219                         );\r
220         if (EFI_ERROR (Status)) {\r
221           //\r
222           // The DevicePath failed, and it's not a valid\r
223           // removable media device.\r
224           //\r
225           goto Done;\r
226         }\r
227       }\r
228     } else {\r
229       Status = EFI_NOT_FOUND;\r
230     }\r
231   }\r
232 \r
233   if (EFI_ERROR (Status)) {\r
234     //\r
235     // It there is any error from the Boot attempt exit now.\r
236     //\r
237     goto Done;\r
238   }\r
239   //\r
240   // Provide the image with it's load options\r
241   //\r
242   Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &ImageInfo);\r
243   ASSERT_EFI_ERROR (Status);\r
244 \r
245   if (Option->LoadOptionsSize != 0) {\r
246     ImageInfo->LoadOptionsSize  = Option->LoadOptionsSize;\r
247     ImageInfo->LoadOptions      = Option->LoadOptions;\r
248   }\r
249   //\r
250   // Before calling the image, enable the Watchdog Timer for\r
251   // the 5 Minute period\r
252   //\r
253   gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
254 \r
255   Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
256   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Image Return Status = %r\n", Status));\r
257 \r
258   //\r
259   // Clear the Watchdog Timer after the image returns\r
260   //\r
261   gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
262 \r
263 Done:\r
264   //\r
265   // Clear Boot Current\r
266   //\r
267   gRT->SetVariable (\r
268         L"BootCurrent",\r
269         &gEfiGlobalVariableGuid,\r
270         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
271         0,\r
272         &Option->BootCurrent\r
273         );\r
274 \r
275   return Status;\r
276 }\r
277 \r
278 EFI_STATUS\r
279 BdsBootByDiskSignatureAndPartition (\r
280   IN  BDS_COMMON_OPTION          * Option,\r
281   IN  HARDDRIVE_DEVICE_PATH      * HardDriveDevicePath,\r
282   IN  UINT32                     LoadOptionsSize,\r
283   IN  VOID                       *LoadOptions,\r
284   OUT UINTN                      *ExitDataSize,\r
285   OUT CHAR16                     **ExitData OPTIONAL\r
286   )\r
287 /*++\r
288 \r
289 Routine Description:\r
290 \r
291   Check to see if a hard ware device path was passed in. If it was then search\r
292   all the block IO devices for the passed in hard drive device path. \r
293   \r
294 Arguments:\r
295 \r
296   Option - The current processing boot option.\r
297 \r
298   HardDriveDevicePath - EFI Device Path to boot, if it starts with a hard\r
299                         drive device path.\r
300 \r
301   LoadOptionsSize - Passed into gBS->StartImage ()\r
302                     via the loaded image protocol.\r
303 \r
304   LoadOptions     - Passed into gBS->StartImage ()\r
305                     via the loaded image protocol.\r
306 \r
307   ExitDataSize - returned directly from gBS->StartImage ()\r
308 \r
309   ExitData     - returned directly from gBS->StartImage ()\r
310 \r
311 Returns:\r
312 \r
313   EFI_SUCCESS   - Status from gBS->StartImage (),\r
314                   or BootByDiskSignatureAndPartition ()\r
315                   \r
316   EFI_NOT_FOUND - If the Device Path is not found in the system\r
317 \r
318 --*/\r
319 {\r
320   EFI_STATUS                Status;\r
321   UINTN                     BlockIoHandleCount;\r
322   EFI_HANDLE                *BlockIoBuffer;\r
323   EFI_DEVICE_PATH_PROTOCOL  *BlockIoDevicePath;\r
324   EFI_DEVICE_PATH_PROTOCOL  *BlockIoHdDevicePath;\r
325   HARDDRIVE_DEVICE_PATH     *TmpHdPath;\r
326   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
327   EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
328   UINTN                     Index;\r
329   BOOLEAN                   DevicePathMatch;\r
330   HARDDRIVE_DEVICE_PATH     *TempPath;\r
331 \r
332   *ExitDataSize = 0;\r
333   *ExitData     = NULL;\r
334 \r
335   if ( !((DevicePathType (&HardDriveDevicePath->Header) == MEDIA_DEVICE_PATH) &&\r
336           (DevicePathSubType (&HardDriveDevicePath->Header) == MEDIA_HARDDRIVE_DP))\r
337         ) {\r
338     //\r
339     // If the HardDriveDevicePath does not start with a Hard Drive Device Path\r
340     // exit.\r
341     //\r
342     return EFI_NOT_FOUND;\r
343   }\r
344   //\r
345   // The boot device have already been connected\r
346   //\r
347   Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
348   if (EFI_ERROR (Status) || BlockIoHandleCount == 0) {\r
349     //\r
350     // If there was an error or there are no device handles that support\r
351     // the BLOCK_IO Protocol, then return.\r
352     //\r
353     return EFI_NOT_FOUND;\r
354   }\r
355   //\r
356   // Loop through all the device handles that support the BLOCK_IO Protocol\r
357   //\r
358   for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
359 \r
360     Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);\r
361     if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {\r
362       continue;\r
363     }\r
364     //\r
365     // Make PreviousDevicePath == the device path node before the end node\r
366     //\r
367     DevicePath          = BlockIoDevicePath;\r
368     BlockIoHdDevicePath = NULL;\r
369 \r
370     //\r
371     // find HardDriver device path node\r
372     //\r
373     while (!IsDevicePathEnd (DevicePath)) {\r
374       if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && \r
375           (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
376           ) {\r
377         BlockIoHdDevicePath = DevicePath;\r
378         break;\r
379       }\r
380 \r
381       DevicePath = NextDevicePathNode (DevicePath);\r
382     }\r
383 \r
384     if (BlockIoHdDevicePath == NULL) {\r
385       continue;\r
386     }\r
387     //\r
388     // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
389     //\r
390     DevicePathMatch = FALSE;\r
391 \r
392     TmpHdPath       = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePath;\r
393     TempPath        = (HARDDRIVE_DEVICE_PATH *) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
394 \r
395     //\r
396     // Only several fields will be checked. NOT whole NODE\r
397     //\r
398     if ( TmpHdPath->PartitionNumber == TempPath->PartitionNumber &&\r
399         TmpHdPath->MBRType == TempPath->MBRType &&\r
400         TmpHdPath->SignatureType == TempPath->SignatureType &&\r
401         CompareGuid ((EFI_GUID *) TmpHdPath->Signature, (EFI_GUID *) TempPath->Signature)) {\r
402       //\r
403       // Get the matched device path\r
404       //\r
405       DevicePathMatch = TRUE;\r
406     }\r
407     //\r
408     // Only do the boot, when devicepath match\r
409     //\r
410     if (DevicePathMatch) {\r
411       //\r
412       // Combine the Block IO and Hard Drive Device path together and try\r
413       // to boot from it.\r
414       //\r
415       DevicePath    = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
416       NewDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
417 \r
418       //\r
419       // Recursive boot with new device path\r
420       //\r
421       Status = BdsLibBootViaBootOption (Option, NewDevicePath, ExitDataSize, ExitData);\r
422       if (!EFI_ERROR (Status)) {\r
423         break;\r
424       }\r
425     }\r
426   }\r
427 \r
428   gBS->FreePool (BlockIoBuffer);\r
429   return Status;\r
430 }\r
431 \r
432 EFI_STATUS\r
433 BdsLibEnumerateAllBootOption (\r
434   IN OUT LIST_ENTRY      *BdsBootOptionList\r
435   )\r
436 /*++\r
437 \r
438 Routine Description:\r
439 \r
440   This function will enumerate all possible boot device in the system,\r
441   it will only excute once of every boot.\r
442 \r
443 Arguments:\r
444 \r
445   BdsBootOptionList - The header of the link list which indexed all\r
446                       current boot options\r
447 \r
448 Returns:\r
449 \r
450   EFI_SUCCESS - Finished all the boot device enumerate and create\r
451                 the boot option base on that boot device\r
452 \r
453 --*/\r
454 {\r
455   EFI_STATUS                    Status;\r
456   UINT16                        BootOptionNumber;\r
457   UINTN                         NumberFileSystemHandles;\r
458   EFI_HANDLE                    *FileSystemHandles;\r
459   UINTN                         NumberBlkIoHandles;\r
460   EFI_HANDLE                    *BlkIoHandles;\r
461   EFI_BLOCK_IO_PROTOCOL         *BlkIo;\r
462   UINTN                         Index;\r
463   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;\r
464   UINTN                         NumberLoadFileHandles;\r
465   EFI_HANDLE                    *LoadFileHandles;\r
466   VOID                          *ProtocolInstance;\r
467   EFI_FIRMWARE_VOLUME_PROTOCOL  *Fv;\r
468   UINTN                         FvHandleCount;\r
469   EFI_HANDLE                    *FvHandleBuffer;\r
470   EFI_FV_FILETYPE               Type;\r
471   UINTN                         Size;\r
472   EFI_FV_FILE_ATTRIBUTES        Attributes;\r
473   UINT32                        AuthenticationStatus;\r
474 \r
475   BootOptionNumber = 0;\r
476 \r
477   //\r
478   // If the boot device enumerate happened, just get the boot\r
479   // device from the boot order variable\r
480   //\r
481   if (mEnumBootDevice) {\r
482     BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
483     return EFI_SUCCESS;\r
484   }\r
485   //\r
486   // Notes: this dirty code is to get the legacy boot option from the\r
487   // BBS table and create to variable as the EFI boot option, it should\r
488   // be removed after the CSM can provide legacy boot option directly\r
489   //\r
490   REFRESH_LEGACY_BOOT_OPTIONS;\r
491 \r
492   //\r
493   // Check all the block IO to create boot option\r
494   //\r
495   gBS->LocateHandleBuffer (\r
496         ByProtocol,\r
497         &gEfiBlockIoProtocolGuid,\r
498         NULL,\r
499         &NumberBlkIoHandles,\r
500         &BlkIoHandles\r
501         );\r
502   for (Index = 0; Index < NumberBlkIoHandles; Index++) {\r
503     Status = gBS->HandleProtocol (\r
504                     BlkIoHandles[Index],\r
505                     &gEfiBlockIoProtocolGuid,\r
506                     (VOID **) &BlkIo\r
507                     );\r
508     if (EFI_ERROR (Status)) {\r
509       continue;\r
510     }\r
511 \r
512     if (!BlkIo->Media->RemovableMedia) {\r
513       //\r
514       // Skip fixed Media device on first loop interration\r
515       //\r
516       continue;\r
517     }\r
518 \r
519     DevicePath = DevicePathFromHandle (BlkIoHandles[Index]);\r
520     if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && \r
521         (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
522         ) {\r
523       //\r
524       // Build the boot option\r
525       //\r
526       BdsLibBuildOptionFromHandle (BlkIoHandles[Index], BdsBootOptionList);\r
527       BootOptionNumber++;\r
528     }\r
529   }\r
530 \r
531   if (NumberBlkIoHandles) {\r
532     gBS->FreePool (BlkIoHandles);\r
533   }\r
534   //\r
535   // Parse Fixed Disk Devices.\r
536   //\r
537   gBS->LocateHandleBuffer (\r
538         ByProtocol,\r
539         &gEfiSimpleFileSystemProtocolGuid,\r
540         NULL,\r
541         &NumberFileSystemHandles,\r
542         &FileSystemHandles\r
543         );\r
544   for (Index = 0; Index < NumberFileSystemHandles; Index++) {\r
545     Status = gBS->HandleProtocol (\r
546                     FileSystemHandles[Index],\r
547                     &gEfiBlockIoProtocolGuid,\r
548                     (VOID **) &BlkIo\r
549                     );\r
550     if (!EFI_ERROR (Status)) {\r
551       if (BlkIo->Media->RemovableMedia) {\r
552         //\r
553         // If the file system handle supports a BlkIo protocol,\r
554         // skip the removable media devices\r
555         //\r
556         continue;\r
557       }\r
558     }\r
559 \r
560     DevicePath = DevicePathFromHandle (FileSystemHandles[Index]);\r
561     if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && \r
562         (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
563         ) {\r
564       //\r
565       // If the FileSystem protocol does not contain a BlkIo protocol,\r
566       // then build it\r
567       //\r
568       BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList);\r
569       BootOptionNumber++;\r
570     }\r
571   }\r
572 \r
573   if (NumberFileSystemHandles) {\r
574     gBS->FreePool (FileSystemHandles);\r
575   }\r
576   //\r
577   // Parse Network Boot Device\r
578   //\r
579   gBS->LocateHandleBuffer (\r
580         ByProtocol,\r
581         &gEfiSimpleNetworkProtocolGuid,\r
582         NULL,\r
583         &NumberLoadFileHandles,\r
584         &LoadFileHandles\r
585         );\r
586   for (Index = 0; Index < NumberLoadFileHandles; Index++) {\r
587     Status = gBS->HandleProtocol (\r
588                     LoadFileHandles[Index],\r
589                     &gEfiLoadFileProtocolGuid,\r
590                     (VOID **) &ProtocolInstance\r
591                     );\r
592     if (EFI_ERROR (Status)) {\r
593       continue;\r
594     }\r
595 \r
596     BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList);\r
597     BootOptionNumber++;\r
598   }\r
599 \r
600   if (NumberLoadFileHandles) {\r
601     gBS->FreePool (LoadFileHandles);\r
602   }\r
603   //\r
604   // Check if we have on flash shell\r
605   //\r
606   gBS->LocateHandleBuffer (\r
607         ByProtocol,\r
608         &gEfiFirmwareVolumeProtocolGuid,\r
609         NULL,\r
610         &FvHandleCount,\r
611         &FvHandleBuffer\r
612         );\r
613   for (Index = 0; Index < FvHandleCount; Index++) {\r
614     gBS->HandleProtocol (\r
615           FvHandleBuffer[Index],\r
616           &gEfiFirmwareVolumeProtocolGuid,\r
617           (VOID **) &Fv\r
618           );\r
619 \r
620     Status = Fv->ReadFile (\r
621                   Fv,\r
622                   &gEfiShellFileGuid,\r
623                   NULL,\r
624                   &Size,\r
625                   &Type,\r
626                   &Attributes,\r
627                   &AuthenticationStatus\r
628                   );\r
629     if (EFI_ERROR (Status)) {\r
630       //\r
631       // Skip if no shell file in the FV\r
632       //\r
633       continue;\r
634     }\r
635     //\r
636     // Build the shell boot option\r
637     //\r
638     BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);\r
639     BootOptionNumber++;\r
640   }\r
641 \r
642   if (FvHandleCount) {\r
643     gBS->FreePool (FvHandleBuffer);\r
644   }\r
645   //\r
646   // Make sure every boot only have one time\r
647   // boot device enumerate\r
648   //\r
649   BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
650   mEnumBootDevice = TRUE;\r
651 \r
652   return EFI_SUCCESS;\r
653 }\r
654 \r
655 VOID\r
656 BdsLibBuildOptionFromHandle (\r
657   IN  EFI_HANDLE             Handle,\r
658   IN  LIST_ENTRY             *BdsBootOptionList\r
659   )\r
660 /*++\r
661 \r
662 Routine Description:\r
663   \r
664   Build the boot option with the handle parsed in\r
665   \r
666 Arguments:\r
667 \r
668   Handle - The handle which present the device path to create boot option\r
669   \r
670   BdsBootOptionList - The header of the link list which indexed all current\r
671                       boot options\r
672 \r
673 Returns:\r
674 \r
675   VOID\r
676 \r
677 --*/\r
678 {\r
679   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
680   CHAR16                    *TempString;\r
681 \r
682   DevicePath  = DevicePathFromHandle (Handle);\r
683   TempString  = DevicePathToStr (DevicePath);\r
684 \r
685   //\r
686   // Create and register new boot option\r
687   //\r
688   BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, TempString, L"BootOrder");\r
689 }\r
690 \r
691 VOID\r
692 BdsLibBuildOptionFromShell (\r
693   IN EFI_HANDLE              Handle,\r
694   IN OUT LIST_ENTRY          *BdsBootOptionList\r
695   )\r
696 /*++\r
697 \r
698 Routine Description:\r
699   \r
700   Build the on flash shell boot option with the handle parsed in\r
701   \r
702 Arguments:\r
703 \r
704   Handle - The handle which present the device path to create on flash shell\r
705            boot option\r
706   \r
707   BdsBootOptionList - The header of the link list which indexed all current\r
708                       boot options\r
709 \r
710 Returns:\r
711 \r
712   None\r
713 \r
714 --*/\r
715 {\r
716   EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
717   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;\r
718 \r
719   DevicePath = DevicePathFromHandle (Handle);\r
720 \r
721   //\r
722   // Build the shell device path\r
723   //\r
724   EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);\r
725   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
726 \r
727   //\r
728   // Create and register the shell boot option\r
729   //\r
730   BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"Internal EFI Shell", L"BootOrder");\r
731 \r
732 }\r
733 \r
734 VOID\r
735 BdsLibBootNext (\r
736   VOID\r
737   )\r
738 /*++\r
739 \r
740 Routine Description:\r
741   \r
742   Boot from the EFI1.1 spec defined "BootNext" variable\r
743   \r
744 Arguments:\r
745 \r
746   None\r
747   \r
748 Returns:\r
749 \r
750   None\r
751 \r
752 --*/\r
753 {\r
754   UINT16            *BootNext;\r
755   UINTN             BootNextSize;\r
756   CHAR16            Buffer[20];\r
757   BDS_COMMON_OPTION *BootOption;\r
758   LIST_ENTRY        TempList;\r
759   UINTN             ExitDataSize;\r
760   CHAR16            *ExitData;\r
761 \r
762   //\r
763   // Init the boot option name buffer and temp link list\r
764   //\r
765   InitializeListHead (&TempList);\r
766   ZeroMem (Buffer, sizeof (Buffer));\r
767 \r
768   BootNext = BdsLibGetVariableAndSize (\r
769               L"BootNext",\r
770               &gEfiGlobalVariableGuid,\r
771               &BootNextSize\r
772               );\r
773 \r
774   //\r
775   // Clear the boot next variable first\r
776   //\r
777   if (BootNext != NULL) {\r
778     gRT->SetVariable (\r
779           L"BootNext",\r
780           &gEfiGlobalVariableGuid,\r
781           EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
782           0,\r
783           BootNext\r
784           );\r
785 \r
786     //\r
787     // Start to build the boot option and try to boot\r
788     //\r
789     UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);\r
790     BootOption = BdsLibVariableToOption (&TempList, Buffer);\r
791     BdsLibConnectDevicePath (BootOption->DevicePath);\r
792     BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
793   }\r
794 \r
795 }\r