Do not clear debug register. New performance code does not use Debug register to...
[mirror_edk2.git] / EdkNt32Pkg / Library / EdkGenericBdsLib / BdsBoot.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, 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
22#include "Performance.h"\r
23\r
24BOOLEAN mEnumBootDevice = FALSE;\r
25\r
26EFI_STATUS\r
27BdsLibDoLegacyBoot (\r
28 IN BDS_COMMON_OPTION *Option\r
29 )\r
30/*++\r
31\r
32Routine Description:\r
33 \r
34 Boot the legacy system with the boot option\r
35\r
36Arguments:\r
37\r
38 Option - The legacy boot option which have BBS device path\r
39\r
40Returns:\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
81EFI_STATUS\r
82BdsLibBootViaBootOption (\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
90Routine 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
95Arguments:\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
107Returns:\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
263Done:\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
278EFI_STATUS\r
279BdsBootByDiskSignatureAndPartition (\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
289Routine 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
294Arguments:\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
311Returns:\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
432EFI_STATUS\r
433BdsLibEnumerateAllBootOption (\r
434 IN OUT LIST_ENTRY *BdsBootOptionList\r
435 )\r
436/*++\r
437\r
438Routine 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
443Arguments:\r
444\r
445 BdsBootOptionList - The header of the link list which indexed all\r
446 current boot options\r
447\r
448Returns:\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
655VOID\r
656BdsLibBuildOptionFromHandle (\r
657 IN EFI_HANDLE Handle,\r
658 IN LIST_ENTRY *BdsBootOptionList\r
659 )\r
660/*++\r
661\r
662Routine Description:\r
663 \r
664 Build the boot option with the handle parsed in\r
665 \r
666Arguments:\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
673Returns:\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
691VOID\r
692BdsLibBuildOptionFromShell (\r
693 IN EFI_HANDLE Handle,\r
694 IN OUT LIST_ENTRY *BdsBootOptionList\r
695 )\r
696/*++\r
697\r
698Routine Description:\r
699 \r
700 Build the on flash shell boot option with the handle parsed in\r
701 \r
702Arguments:\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
710Returns:\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
734VOID\r
735BdsLibBootNext (\r
736 VOID\r
737 )\r
738/*++\r
739\r
740Routine Description:\r
741 \r
742 Boot from the EFI1.1 spec defined "BootNext" variable\r
743 \r
744Arguments:\r
745\r
746 None\r
747 \r
748Returns:\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