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