3 * CSM/legacy boot support functions
5 * Taken from Tianocore source code (mostly IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c)
7 * Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
8 * This program and the accompanying materials
9 * are licensed and made available under the terms and conditions of the BSD License
10 * which accompanies this distribution. The full text of the license may be found at
11 * http://opensource.org/licenses/bsd-license.php
13 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "../include/tiano_includes.h"
21 BOOT_OPTION_BBS_MAPPING
*mBootOptionBbsMapping
= NULL
;
22 UINTN mBootOptionBbsMappingCount
= 0;
24 extern EFI_DEVICE_PATH EndDevicePath
[];
25 extern EFI_GUID gEfiLegacyBiosProtocolGuid
;
26 EFI_GUID gEfiLegacyDevOrderVariableGuid
= { 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 }};
30 Translate the first n characters of an Ascii string to
31 Unicode characters. The count n is indicated by parameter
32 Size. If Size is greater than the length of string, then
33 the entire string is translated.
36 @param AStr Pointer to input Ascii string.
37 @param Size The number of characters to translate.
38 @param UStr Pointer to output Unicode string buffer.
51 while (AStr
[Idx
] != 0) {
52 UStr
[Idx
] = (CHAR16
) AStr
[Idx
];
63 Build Legacy Device Name String according.
65 @param CurBBSEntry BBS Table.
67 @param BufSize The buffer size.
68 @param BootString The output string.
72 BdsBuildLegacyDevNameString (
73 IN BBS_TABLE
*CurBBSEntry
,
76 OUT CHAR16
*BootString
89 Fmt
= L
"Primary Master %s";
96 Fmt
= L
"Primary Slave %s";
103 Fmt
= L
"Secondary Master %s";
110 Fmt
= L
"Secondary Slave %s";
118 switch (CurBBSEntry
->DeviceType
) {
139 case BBS_EMBED_NETWORK
:
153 // If current BBS entry has its description then use it.
155 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
156 if (NULL
!= StringDesc
) {
158 // Only get fisrt 32 characters, this is suggested by BBS spec
160 AsciiToUnicodeSize (StringDesc
, 32, Temp
);
166 // BbsTable 16 entries are for onboard IDE.
167 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
169 if (Index
>= 5 && Index
<= 16 && (CurBBSEntry
->DeviceType
== BBS_HARDDISK
|| CurBBSEntry
->DeviceType
== BBS_CDROM
)) {
171 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
173 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
178 Check if the boot option is a legacy one.
180 @param BootOptionVar The boot option data payload.
181 @param BbsEntry The BBS Table.
182 @param BbsIndex The table index.
184 @retval TRUE It is a legacy boot option.
185 @retval FALSE It is not a legacy boot option.
189 BdsIsLegacyBootOption (
190 IN UINT8
*BootOptionVar
,
191 OUT BBS_TABLE
**BbsEntry
,
196 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
201 Ptr
+= sizeof (UINT32
);
202 DevPathLen
= *(UINT16
*) Ptr
;
203 Ptr
+= sizeof (UINT16
);
204 Ptr
+= StrSize ((UINT16
*) Ptr
);
205 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
206 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
208 *BbsEntry
= (BBS_TABLE
*) Ptr
;
209 Ptr
+= sizeof (BBS_TABLE
);
210 *BbsIndex
= *(UINT16
*) Ptr
;
221 Find all legacy boot option by device type.
223 @param BootOrder The boot order array.
224 @param BootOptionNum The number of boot option.
225 @param DevType Device type.
226 @param DevName Device name.
227 @param Attribute The boot option attribute.
228 @param BbsIndex The BBS table index.
229 @param OptionNumber The boot option index.
231 @retval TRUE The Legacy boot option is found.
232 @retval FALSE The legacy boot option is not found.
236 BdsFindLegacyBootOptionByDevTypeAndName (
237 IN UINT16
*BootOrder
,
238 IN UINTN BootOptionNum
,
241 OUT UINT32
*Attribute
,
242 OUT UINT16
*BbsIndex
,
243 OUT UINT16
*OptionNumber
247 CHAR16 BootOption
[9];
248 UINTN BootOptionSize
;
249 UINT8
*BootOptionVar
;
256 if (NULL
== BootOrder
) {
261 // Loop all boot option from variable
263 for (Index
= 0; Index
< BootOptionNum
; Index
++) {
264 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", (UINTN
) BootOrder
[Index
]);
265 BootOptionVar
= BdsLibGetVariableAndSize (
267 &gEfiGlobalVariableGuid
,
270 if (NULL
== BootOptionVar
) {
275 // Skip Non-legacy boot option
277 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
278 FreePool (BootOptionVar
);
283 (BbsEntry
->DeviceType
!= DevType
) ||
284 (StrCmp (DevName
, (CHAR16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) != 0)
286 FreePool (BootOptionVar
);
290 *Attribute
= *(UINT32
*) BootOptionVar
;
291 *OptionNumber
= BootOrder
[Index
];
293 FreePool (BootOptionVar
);
302 Create a legacy boot option for the specified entry of
303 BBS table, save it as variable, and append it to the boot
307 @param CurrentBbsEntry Pointer to current BBS table.
308 @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS
309 @param Index Index of the specified entry in BBS table.
310 @param BootOrderList On input, the original boot order list.
311 On output, the new boot order list attached with the
313 @param BootOrderListSize On input, the original size of boot order list.
314 On output, the size of new boot order list.
316 @retval EFI_SUCCESS Boot Option successfully created.
317 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
318 @retval Other Error occurs while setting variable.
322 BdsCreateLegacyBootOption (
323 IN BBS_TABLE
*CurrentBbsEntry
,
324 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
326 IN OUT UINT16
**BootOrderList
,
327 IN OUT UINTN
*BootOrderListSize
331 UINT16 CurrentBootOptionNo
;
332 UINT16 BootString
[10];
333 CHAR16 BootDesc
[100];
334 CHAR8 HelpString
[100];
335 UINT16
*NewBootOrderList
;
340 UINT16 CurrentBbsDevPathSize
;
341 UINTN BootOrderIndex
;
342 UINTN BootOrderLastIndex
;
344 BOOLEAN IndexNotFound
;
345 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
347 if ((*BootOrderList
) == NULL
) {
348 CurrentBootOptionNo
= 0;
350 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
351 IndexNotFound
= TRUE
;
352 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
353 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
354 IndexNotFound
= FALSE
;
359 if (!IndexNotFound
) {
366 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
376 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
379 // Create new BBS device path node with description string
381 UnicodeStrToAsciiStr (BootDesc
, HelpString
);
383 StringLen
= AsciiStrLen (HelpString
);
384 NewBbsDevPathNode
= AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
385 if (NewBbsDevPathNode
== NULL
) {
386 return EFI_OUT_OF_RESOURCES
;
388 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
389 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
390 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
393 // Create entire new CurrentBbsDevPath with end node
395 CurrentBbsDevPath
= AppendDevicePathNode (
397 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
399 if (CurrentBbsDevPath
== NULL
) {
400 FreePool (NewBbsDevPathNode
);
401 return EFI_OUT_OF_RESOURCES
;
404 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
406 BufferSize
= sizeof (UINT32
) +
409 CurrentBbsDevPathSize
+
413 Buffer
= AllocateZeroPool (BufferSize
);
414 if (Buffer
== NULL
) {
415 FreePool (NewBbsDevPathNode
);
416 FreePool (CurrentBbsDevPath
);
417 return EFI_OUT_OF_RESOURCES
;
420 Ptr
= (UINT8
*) Buffer
;
422 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
423 Ptr
+= sizeof (UINT32
);
425 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
426 Ptr
+= sizeof (UINT16
);
433 Ptr
+= StrSize (BootDesc
);
438 CurrentBbsDevPathSize
440 Ptr
+= CurrentBbsDevPathSize
;
448 Ptr
+= sizeof (BBS_TABLE
);
449 *((UINT16
*) Ptr
) = (UINT16
) Index
;
451 Status
= gRT
->SetVariable (
453 &gEfiGlobalVariableGuid
,
463 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
464 if (NULL
== NewBootOrderList
) {
465 FreePool (NewBbsDevPathNode
);
466 FreePool (CurrentBbsDevPath
);
467 return EFI_OUT_OF_RESOURCES
;
470 if (*BootOrderList
!= NULL
) {
471 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
472 FreePool (*BootOrderList
);
475 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
476 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
477 *BootOrderListSize
+= sizeof (UINT16
);
478 *BootOrderList
= NewBootOrderList
;
480 FreePool (NewBbsDevPathNode
);
481 FreePool (CurrentBbsDevPath
);
486 Create a legacy boot option.
488 @param BbsItem The BBS Table entry.
489 @param Index Index of the specified entry in BBS table.
490 @param BootOrderList The boot order list.
491 @param BootOrderListSize The size of boot order list.
493 @retval EFI_OUT_OF_RESOURCE No enough memory.
494 @retval EFI_SUCCESS The function complete successfully.
495 @return Other value if the legacy boot option is not created.
499 BdsCreateOneLegacyBootOption (
500 IN BBS_TABLE
*BbsItem
,
502 IN OUT UINT16
**BootOrderList
,
503 IN OUT UINTN
*BootOrderListSize
506 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
508 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
513 // Create device path node.
515 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
516 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
517 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
518 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
519 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
521 DevPath
= AppendDevicePathNode (
523 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
525 if (NULL
== DevPath
) {
526 return EFI_OUT_OF_RESOURCES
;
529 Status
= BdsCreateLegacyBootOption (
536 BbsItem
->BootPriority
= 0x00;
544 Group the legacy boot options in the BootOption.
546 The routine assumes the boot options in the beginning that covers all the device
547 types are ordered properly and re-position the following boot options just after
548 the corresponding boot options with the same device type.
550 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]
551 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly
552 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]
554 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]
555 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly
556 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]
558 @param BootOption Pointer to buffer containing Boot Option Numbers
559 @param BootOptionCount Count of the Boot Option Numbers
562 GroupMultipleLegacyBootOption4SameType (
564 UINTN BootOptionCount
567 UINTN DeviceTypeIndex
[7];
574 SetMem (DeviceTypeIndex
, sizeof (DeviceTypeIndex
), 0xFF);
576 for (Index
= 0; Index
< BootOptionCount
; Index
++) {
579 // Find the DeviceType
581 for (MappingIndex
= 0; MappingIndex
< mBootOptionBbsMappingCount
; MappingIndex
++) {
582 if (mBootOptionBbsMapping
[MappingIndex
].BootOptionNumber
== BootOption
[Index
]) {
586 if (MappingIndex
== mBootOptionBbsMappingCount
) {
588 // Is not a legacy boot option
593 ASSERT ((mBootOptionBbsMapping
[MappingIndex
].BbsType
& 0xF) <
594 sizeof (DeviceTypeIndex
) / sizeof (DeviceTypeIndex
[0]));
595 NextIndex
= &DeviceTypeIndex
[mBootOptionBbsMapping
[MappingIndex
].BbsType
& 0xF];
596 if (*NextIndex
== (UINTN
) -1) {
598 // *NextIndex is the index in BootOption to put the next Option Number for the same type
600 *NextIndex
= Index
+ 1;
603 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position
605 OptionNumber
= BootOption
[Index
];
606 CopyMem (&BootOption
[*NextIndex
+ 1], &BootOption
[*NextIndex
], (Index
- *NextIndex
) * sizeof (UINT16
));
607 BootOption
[*NextIndex
] = OptionNumber
;
610 // Update the DeviceTypeIndex array to reflect the right shift operation
612 for (DeviceIndex
= 0; DeviceIndex
< sizeof (DeviceTypeIndex
) / sizeof (DeviceTypeIndex
[0]); DeviceIndex
++) {
613 if (DeviceTypeIndex
[DeviceIndex
] != (UINTN
) -1 && DeviceTypeIndex
[DeviceIndex
] >= *NextIndex
) {
614 DeviceTypeIndex
[DeviceIndex
]++;
622 Function returns the value of the specified variable.
625 @param Name A Null-terminated Unicode string that is
626 the name of the vendor's variable.
627 @param VendorGuid A unique identifier for the vendor.
629 @return The payload of the variable.
630 @retval NULL If the variable can't be read.
636 IN EFI_GUID
*VendorGuid
641 return BdsLibGetVariableAndSize (Name
, VendorGuid
, &VarSize
);
645 Function deletes the variable specified by VarName and VarGuid.
647 @param VarName A Null-terminated Unicode string that is
648 the name of the vendor's variable.
650 @param VarGuid A unique identifier for the vendor.
652 @retval EFI_SUCCESS The variable was found and removed
653 @retval EFI_UNSUPPORTED The variable store was inaccessible
654 @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available
655 @retval EFI_NOT_FOUND The variable was not found
659 EfiLibDeleteVariable (
667 VarBuf
= EfiLibGetVariable (VarName
, VarGuid
);
668 Status
= EFI_NOT_FOUND
;
670 if (VarBuf
!= NULL
) {
672 // Delete variable from Storage
674 Status
= gRT
->SetVariable (VarName
, VarGuid
, VAR_FLAG
, 0, NULL
);
675 ASSERT (!EFI_ERROR (Status
));
683 Add the legacy boot options from BBS table if they do not exist.
685 @retval EFI_SUCCESS The boot options are added successfully
686 or they are already in boot options.
687 @retval EFI_NOT_FOUND No legacy boot options is found.
688 @retval EFI_OUT_OF_RESOURCE No enough memory.
689 @return Other value LegacyBoot options are not added.
693 BdsAddNonExistingLegacyBootOptions (
703 HDD_INFO
*LocalHddInfo
;
704 BBS_TABLE
*LocalBbsTable
;
706 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
715 LocalBbsTable
= NULL
;
717 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
718 if (EFI_ERROR (Status
)) {
722 if (mBootOptionBbsMapping
!= NULL
) {
723 FreePool (mBootOptionBbsMapping
);
725 mBootOptionBbsMapping
= NULL
;
726 mBootOptionBbsMappingCount
= 0;
729 LegacyBios
->GetBbsInfo (
737 BootOrder
= BdsLibGetVariableAndSize (
739 &gEfiGlobalVariableGuid
,
742 if (BootOrder
== NULL
) {
746 for (Index
= 0; Index
< BbsCount
; Index
++) {
747 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
748 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
753 BdsBuildLegacyDevNameString (&LocalBbsTable
[Index
], Index
, sizeof (Desc
), Desc
);
755 Exist
= BdsFindLegacyBootOptionByDevTypeAndName (
757 BootOrderSize
/ sizeof (UINT16
),
758 LocalBbsTable
[Index
].DeviceType
,
766 // Not found such type of legacy device in boot options or we found but it's disabled
767 // so we have to create one and put it to the tail of boot order list
769 Status
= BdsCreateOneLegacyBootOption (
770 &LocalBbsTable
[Index
],
775 if (EFI_ERROR (Status
)) {
779 OptionNumber
= BootOrder
[BootOrderSize
/ sizeof (UINT16
) - 1];
782 ASSERT (BbsIndex
== Index
);
786 mBootOptionBbsMapping
= ReallocatePool (
787 mBootOptionBbsMappingCount
* sizeof (BOOT_OPTION_BBS_MAPPING
),
788 (mBootOptionBbsMappingCount
+ 1) * sizeof (BOOT_OPTION_BBS_MAPPING
),
789 mBootOptionBbsMapping
791 ASSERT (mBootOptionBbsMapping
!= NULL
);
792 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BootOptionNumber
= OptionNumber
;
793 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BbsIndex
= Index
;
794 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BbsType
= LocalBbsTable
[Index
].DeviceType
;
795 mBootOptionBbsMappingCount
++;
799 // Group the Boot Option Number in BootOrder for the same type devices
801 GroupMultipleLegacyBootOption4SameType (
803 BootOrderSize
/ sizeof (UINT16
)
806 if (BootOrderSize
> 0) {
807 Status
= gRT
->SetVariable (
809 &gEfiGlobalVariableGuid
,
815 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
818 if (BootOrder
!= NULL
) {
819 FreePool (BootOrder
);
826 Deletete the Boot Option from EFI Variable. The Boot Order Arrray
829 @param OptionNumber The number of Boot option want to be deleted.
830 @param BootOrder The Boot Order array.
831 @param BootOrderSize The size of the Boot Order Array.
833 @retval EFI_SUCCESS The Boot Option Variable was found and removed
834 @retval EFI_UNSUPPORTED The Boot Option Variable store was inaccessible
835 @retval EFI_NOT_FOUND The Boot Option Variable was not found
839 BdsDeleteBootOption (
840 IN UINTN OptionNumber
,
841 IN OUT UINT16
*BootOrder
,
842 IN OUT UINTN
*BootOrderSize
845 UINT16 BootOption
[100];
850 Status
= EFI_SUCCESS
;
853 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
854 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
857 // adjust boot order array
859 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
860 if (BootOrder
[Index
] == OptionNumber
) {
866 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
867 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
868 if (Index
>= Index2Del
) {
869 BootOrder
[Index
] = BootOrder
[Index
+ 1];
873 *BootOrderSize
-= sizeof (UINT16
);
881 Delete all the invalid legacy boot options.
883 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
884 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
885 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
889 BdsDeleteAllInvalidLegacyBootOptions (
894 UINT8
*BootOptionVar
;
896 UINTN BootOptionSize
;
900 HDD_INFO
*LocalHddInfo
;
901 BBS_TABLE
*LocalBbsTable
;
904 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
906 UINT16 BootOption
[10];
907 UINT16 BootDesc
[100];
908 BOOLEAN DescStringMatch
;
910 Status
= EFI_SUCCESS
;
916 LocalBbsTable
= NULL
;
919 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
920 if (EFI_ERROR (Status
)) {
924 LegacyBios
->GetBbsInfo (
932 BootOrder
= BdsLibGetVariableAndSize (
934 &gEfiGlobalVariableGuid
,
937 if (BootOrder
== NULL
) {
942 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
943 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
944 BootOptionVar
= BdsLibGetVariableAndSize (
946 &gEfiGlobalVariableGuid
,
949 if (NULL
== BootOptionVar
) {
951 Status
= gRT
->GetVariable (
953 &gEfiGlobalVariableGuid
,
958 if (Status
== EFI_NOT_FOUND
) {
962 BdsDeleteBootOption (
969 FreePool (BootOrder
);
970 return EFI_OUT_OF_RESOURCES
;
975 // Skip Non-Legacy boot option
977 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
978 if (BootOptionVar
!= NULL
) {
979 FreePool (BootOptionVar
);
985 if (BbsIndex
< BbsCount
) {
987 // Check if BBS Description String is changed
989 DescStringMatch
= FALSE
;
990 BdsBuildLegacyDevNameString (
991 &LocalBbsTable
[BbsIndex
],
997 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
998 DescStringMatch
= TRUE
;
1001 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1002 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
1003 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
1010 if (BootOptionVar
!= NULL
) {
1011 FreePool (BootOptionVar
);
1016 BdsDeleteBootOption (
1024 // Adjust the number of boot options.
1026 if (BootOrderSize
!= 0) {
1027 Status
= gRT
->SetVariable (
1029 &gEfiGlobalVariableGuid
,
1035 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
1038 if (BootOrder
!= NULL
) {
1039 FreePool (BootOrder
);
1046 Fill the device order buffer.
1048 @param BbsTable The BBS table.
1049 @param BbsType The BBS Type.
1050 @param BbsCount The BBS Count.
1051 @param Buf device order buffer.
1053 @return The device order buffer.
1057 BdsFillDevOrderBuf (
1058 IN BBS_TABLE
*BbsTable
,
1059 IN BBS_TYPE BbsType
,
1066 for (Index
= 0; Index
< BbsCount
; Index
++) {
1067 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
1071 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
1075 *Buf
= (UINT16
) (Index
& 0xFF);
1083 Create the device order buffer.
1085 @param BbsTable The BBS table.
1086 @param BbsCount The BBS Count.
1088 @retval EFI_SUCCES The buffer is created and the EFI variable named
1089 VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid is
1091 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.
1092 @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail
1093 because of hardware error.
1097 IN BBS_TABLE
*BbsTable
,
1109 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1110 LEGACY_DEV_ORDER_ENTRY
*DevOrderPtr
;
1119 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1121 Status
= EFI_SUCCESS
;
1124 // Count all boot devices
1126 for (Index
= 0; Index
< BbsCount
; Index
++) {
1127 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
1131 switch (BbsTable
[Index
].DeviceType
) {
1144 case BBS_EMBED_NETWORK
:
1148 case BBS_BEV_DEVICE
:
1157 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
1158 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
1159 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
1160 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
1161 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
1164 // Create buffer to hold all boot device order
1166 DevOrder
= AllocateZeroPool (TotalSize
);
1167 if (NULL
== DevOrder
) {
1168 return EFI_OUT_OF_RESOURCES
;
1170 DevOrderPtr
= DevOrder
;
1172 DevOrderPtr
->BbsType
= BBS_FLOPPY
;
1173 DevOrderPtr
->Length
= (UINT16
) (sizeof (DevOrderPtr
->Length
) + FDCount
* sizeof (UINT16
));
1174 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, DevOrderPtr
->Data
);
1176 DevOrderPtr
->BbsType
= BBS_HARDDISK
;
1177 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1178 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, DevOrderPtr
->Data
);
1180 DevOrderPtr
->BbsType
= BBS_CDROM
;
1181 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1182 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, DevOrderPtr
->Data
);
1184 DevOrderPtr
->BbsType
= BBS_EMBED_NETWORK
;
1185 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1186 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, DevOrderPtr
->Data
);
1188 DevOrderPtr
->BbsType
= BBS_BEV_DEVICE
;
1189 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1190 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, DevOrderPtr
->Data
);
1192 ASSERT (TotalSize
== (UINTN
) ((UINT8
*) DevOrderPtr
- (UINT8
*) DevOrder
));
1195 // Save device order for legacy boot device to variable.
1197 Status
= gRT
->SetVariable (
1198 VAR_LEGACY_DEV_ORDER
,
1199 &gEfiLegacyDevOrderVariableGuid
,
1204 FreePool (DevOrder
);