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