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