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
;
712 Print(L
"Entering BdsAddNonExistingLegacyBootOptions()\n");
716 LocalBbsTable
= NULL
;
718 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
719 if (EFI_ERROR (Status
)) {
723 if (mBootOptionBbsMapping
!= NULL
) {
724 FreePool (mBootOptionBbsMapping
);
726 mBootOptionBbsMapping
= NULL
;
727 mBootOptionBbsMappingCount
= 0;
730 LegacyBios
->GetBbsInfo (
738 BootOrder
= BdsLibGetVariableAndSize (
740 &gEfiGlobalVariableGuid
,
743 if (BootOrder
== NULL
) {
747 for (Index
= 0; Index
< BbsCount
; Index
++) {
748 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
749 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
754 BdsBuildLegacyDevNameString (&LocalBbsTable
[Index
], Index
, sizeof (Desc
), Desc
);
756 Exist
= BdsFindLegacyBootOptionByDevTypeAndName (
758 BootOrderSize
/ sizeof (UINT16
),
759 LocalBbsTable
[Index
].DeviceType
,
765 Print(L
"Boot entry #%d %s exist.\n", Index
, Exist
? L
"does" : L
"does not");
768 // Not found such type of legacy device in boot options or we found but it's disabled
769 // so we have to create one and put it to the tail of boot order list
771 Status
= BdsCreateOneLegacyBootOption (
772 &LocalBbsTable
[Index
],
777 if (EFI_ERROR (Status
)) {
781 OptionNumber
= BootOrder
[BootOrderSize
/ sizeof (UINT16
) - 1];
784 ASSERT (BbsIndex
== Index
);
788 mBootOptionBbsMapping
= ReallocatePool (
789 mBootOptionBbsMappingCount
* sizeof (BOOT_OPTION_BBS_MAPPING
),
790 (mBootOptionBbsMappingCount
+ 1) * sizeof (BOOT_OPTION_BBS_MAPPING
),
791 mBootOptionBbsMapping
793 ASSERT (mBootOptionBbsMapping
!= NULL
);
794 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BootOptionNumber
= OptionNumber
;
795 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BbsIndex
= Index
;
796 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BbsType
= LocalBbsTable
[Index
].DeviceType
;
797 mBootOptionBbsMappingCount
++;
801 // Group the Boot Option Number in BootOrder for the same type devices
803 GroupMultipleLegacyBootOption4SameType (
805 BootOrderSize
/ sizeof (UINT16
)
808 if (BootOrderSize
> 0) {
809 Status
= gRT
->SetVariable (
811 &gEfiGlobalVariableGuid
,
817 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
820 if (BootOrder
!= NULL
) {
821 FreePool (BootOrder
);
824 Print(L
"Exiting BdsAddNonExistingLegacyBootOptions()\n");
830 Deletete the Boot Option from EFI Variable. The Boot Order Arrray
833 @param OptionNumber The number of Boot option want to be deleted.
834 @param BootOrder The Boot Order array.
835 @param BootOrderSize The size of the Boot Order Array.
837 @retval EFI_SUCCESS The Boot Option Variable was found and removed
838 @retval EFI_UNSUPPORTED The Boot Option Variable store was inaccessible
839 @retval EFI_NOT_FOUND The Boot Option Variable was not found
843 BdsDeleteBootOption (
844 IN UINTN OptionNumber
,
845 IN OUT UINT16
*BootOrder
,
846 IN OUT UINTN
*BootOrderSize
849 UINT16 BootOption
[100];
854 Status
= EFI_SUCCESS
;
857 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
858 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
861 // adjust boot order array
863 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
864 if (BootOrder
[Index
] == OptionNumber
) {
870 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
871 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
872 if (Index
>= Index2Del
) {
873 BootOrder
[Index
] = BootOrder
[Index
+ 1];
877 *BootOrderSize
-= sizeof (UINT16
);
885 Delete all the invalid legacy boot options.
887 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
888 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
889 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
893 BdsDeleteAllInvalidLegacyBootOptions (
898 UINT8
*BootOptionVar
;
900 UINTN BootOptionSize
;
904 HDD_INFO
*LocalHddInfo
;
905 BBS_TABLE
*LocalBbsTable
;
908 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
910 UINT16 BootOption
[10];
911 UINT16 BootDesc
[100];
912 BOOLEAN DescStringMatch
;
914 Status
= EFI_SUCCESS
;
920 LocalBbsTable
= NULL
;
923 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
924 if (EFI_ERROR (Status
)) {
928 LegacyBios
->GetBbsInfo (
936 BootOrder
= BdsLibGetVariableAndSize (
938 &gEfiGlobalVariableGuid
,
941 if (BootOrder
== NULL
) {
946 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
947 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
948 BootOptionVar
= BdsLibGetVariableAndSize (
950 &gEfiGlobalVariableGuid
,
953 if (NULL
== BootOptionVar
) {
955 Status
= gRT
->GetVariable (
957 &gEfiGlobalVariableGuid
,
962 if (Status
== EFI_NOT_FOUND
) {
966 Print(L
"About to call BdsDeleteBootOption() on Index == %d\n", Index
);
967 BdsDeleteBootOption (
974 FreePool (BootOrder
);
975 return EFI_OUT_OF_RESOURCES
;
980 // Skip Non-Legacy boot option
982 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
983 if (BootOptionVar
!= NULL
) {
984 FreePool (BootOptionVar
);
990 if (BbsIndex
< BbsCount
) {
992 // Check if BBS Description String is changed
994 DescStringMatch
= FALSE
;
995 BdsBuildLegacyDevNameString (
996 &LocalBbsTable
[BbsIndex
],
1002 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
1003 DescStringMatch
= TRUE
;
1006 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1007 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
1008 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
1015 if (BootOptionVar
!= NULL
) {
1016 FreePool (BootOptionVar
);
1021 Print(L
"Second About to call BdsDeleteBootOption(), Index = %d\n", Index
);
1022 BdsDeleteBootOption (
1030 // Adjust the number of boot options.
1032 if (BootOrderSize
!= 0) {
1033 Status
= gRT
->SetVariable (
1035 &gEfiGlobalVariableGuid
,
1041 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
1044 if (BootOrder
!= NULL
) {
1045 FreePool (BootOrder
);
1052 Fill the device order buffer.
1054 @param BbsTable The BBS table.
1055 @param BbsType The BBS Type.
1056 @param BbsCount The BBS Count.
1057 @param Buf device order buffer.
1059 @return The device order buffer.
1063 BdsFillDevOrderBuf (
1064 IN BBS_TABLE
*BbsTable
,
1065 IN BBS_TYPE BbsType
,
1072 for (Index
= 0; Index
< BbsCount
; Index
++) {
1073 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
1077 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
1081 *Buf
= (UINT16
) (Index
& 0xFF);
1089 Create the device order buffer.
1091 @param BbsTable The BBS table.
1092 @param BbsCount The BBS Count.
1094 @retval EFI_SUCCES The buffer is created and the EFI variable named
1095 VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid is
1097 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.
1098 @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail
1099 because of hardware error.
1103 IN BBS_TABLE
*BbsTable
,
1115 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1116 LEGACY_DEV_ORDER_ENTRY
*DevOrderPtr
;
1125 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1127 Status
= EFI_SUCCESS
;
1130 // Count all boot devices
1132 for (Index
= 0; Index
< BbsCount
; Index
++) {
1133 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
1137 switch (BbsTable
[Index
].DeviceType
) {
1150 case BBS_EMBED_NETWORK
:
1154 case BBS_BEV_DEVICE
:
1163 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
1164 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
1165 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
1166 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
1167 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
1170 // Create buffer to hold all boot device order
1172 DevOrder
= AllocateZeroPool (TotalSize
);
1173 if (NULL
== DevOrder
) {
1174 return EFI_OUT_OF_RESOURCES
;
1176 DevOrderPtr
= DevOrder
;
1178 DevOrderPtr
->BbsType
= BBS_FLOPPY
;
1179 DevOrderPtr
->Length
= (UINT16
) (sizeof (DevOrderPtr
->Length
) + FDCount
* sizeof (UINT16
));
1180 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, DevOrderPtr
->Data
);
1182 DevOrderPtr
->BbsType
= BBS_HARDDISK
;
1183 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1184 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, DevOrderPtr
->Data
);
1186 DevOrderPtr
->BbsType
= BBS_CDROM
;
1187 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1188 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, DevOrderPtr
->Data
);
1190 DevOrderPtr
->BbsType
= BBS_EMBED_NETWORK
;
1191 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1192 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, DevOrderPtr
->Data
);
1194 DevOrderPtr
->BbsType
= BBS_BEV_DEVICE
;
1195 DevOrderPtr
->Length
= (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1196 DevOrderPtr
= (LEGACY_DEV_ORDER_ENTRY
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, DevOrderPtr
->Data
);
1198 ASSERT (TotalSize
== (UINTN
) ((UINT8
*) DevOrderPtr
- (UINT8
*) DevOrder
));
1201 // Save device order for legacy boot device to variable.
1203 Status
= gRT
->SetVariable (
1204 VAR_LEGACY_DEV_ORDER
,
1205 &gEfiLegacyDevOrderVariableGuid
,
1210 FreePool (DevOrder
);
1216 Add the legacy boot devices from BBS table into
1217 the legacy device boot order.
1219 @retval EFI_SUCCESS The boot devices are added successfully.
1220 @retval EFI_NOT_FOUND The legacy boot devices are not found.
1221 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.
1222 @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable
1223 because of hardware error.
1227 BdsUpdateLegacyDevOrder (
1231 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1232 LEGACY_DEV_ORDER_ENTRY
*NewDevOrder
;
1233 LEGACY_DEV_ORDER_ENTRY
*Ptr
;
1234 LEGACY_DEV_ORDER_ENTRY
*NewPtr
;
1236 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1240 HDD_INFO
*LocalHddInfo
;
1241 BBS_TABLE
*LocalBbsTable
;
1264 Print(L
"Entering BdsUpdateLegacyDevOrder()\n");
1273 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1281 Print(L
"About to call EfiLibLocateProtocol()\n");
1282 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1283 if (EFI_ERROR (Status
)) {
1287 Print(L
"About to call GetBbsInfo()\n");
1288 Status
= LegacyBios
->GetBbsInfo (
1295 if (EFI_ERROR (Status
)) {
1299 Print(L
"About to call BdsLibGetVariableAndSize()\n");
1300 DevOrder
= BdsLibGetVariableAndSize (
1301 VAR_LEGACY_DEV_ORDER
,
1302 &gEfiLegacyDevOrderVariableGuid
,
1305 if (NULL
== DevOrder
) {
1306 Print(L
"DevOrder was NULL\n");
1307 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1310 // First we figure out how many boot devices with same device type respectively
1312 Print(L
"About to enter for() loop, BbsCount = %d\n", BbsCount
);
1313 for (Index
= 0; Index
< BbsCount
; Index
++) {
1314 // Print(L" Loop: %d\n", Index);
1315 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1316 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1321 switch (LocalBbsTable
[Index
].DeviceType
) {
1334 case BBS_EMBED_NETWORK
:
1338 case BBS_BEV_DEVICE
:
1347 Print(L
"Done with for() loop; counted:\n Floppies: %d\n Hard disks: %d\n CD-ROMs: %d\n", FDCount
, HDCount
, CDCount
);
1348 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1349 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1350 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1351 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1352 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1354 Print(L
"About to allocate memory for NewDevOrder\n");
1355 NewDevOrder
= AllocateZeroPool (TotalSize
);
1356 if (NULL
== NewDevOrder
) {
1357 return EFI_OUT_OF_RESOURCES
;
1361 Print(L
"About to copy FD entries\n");
1366 NewPtr
= NewDevOrder
;
1367 NewPtr
->BbsType
= Ptr
->BbsType
;
1368 NewPtr
->Length
= (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1369 Print(L
" Copying FD entries; about to loop from 0 to %d\n", Ptr
->Length
/ sizeof (UINT16
) - 1);
1370 for (Index
= 0; Index
< (INTN
) (Ptr
->Length
/ sizeof (UINT16
) - 1); Index
++) {
1371 // Print(L" Looping: Index = %d\n", Index);
1372 if (LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_IGNORE_ENTRY
||
1373 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1374 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].DeviceType
!= BBS_FLOPPY
1379 // Print(L" About to set data\n");
1380 NewPtr
->Data
[FDIndex
] = Ptr
->Data
[Index
];
1383 Print(L
" Done with for() loop\n");
1384 NewFDPtr
= NewPtr
->Data
;
1386 Print(L
"About to copy HD entries\n");
1390 Ptr
= (LEGACY_DEV_ORDER_ENTRY
*) (&Ptr
->Data
[Ptr
->Length
/ sizeof (UINT16
) - 1]);
1391 NewPtr
= (LEGACY_DEV_ORDER_ENTRY
*) (&NewPtr
->Data
[NewPtr
->Length
/ sizeof (UINT16
) -1]);
1392 NewPtr
->BbsType
= Ptr
->BbsType
;
1393 NewPtr
->Length
= (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1394 for (Index
= 0; Index
< (INTN
) (Ptr
->Length
/ sizeof (UINT16
) - 1); Index
++) {
1395 if (LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_IGNORE_ENTRY
||
1396 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1397 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_LOWEST_PRIORITY
||
1398 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].DeviceType
!= BBS_HARDDISK
1403 NewPtr
->Data
[HDIndex
] = Ptr
->Data
[Index
];
1406 NewHDPtr
= NewPtr
->Data
;
1408 Print(L
"About to copy CD entries\n");
1412 Ptr
= (LEGACY_DEV_ORDER_ENTRY
*) (&Ptr
->Data
[Ptr
->Length
/ sizeof (UINT16
) - 1]);
1413 NewPtr
= (LEGACY_DEV_ORDER_ENTRY
*) (&NewPtr
->Data
[NewPtr
->Length
/ sizeof (UINT16
) -1]);
1414 NewPtr
->BbsType
= Ptr
->BbsType
;
1415 NewPtr
->Length
= (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1416 for (Index
= 0; Index
< (INTN
) (Ptr
->Length
/ sizeof (UINT16
) - 1); Index
++) {
1417 if (LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_IGNORE_ENTRY
||
1418 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1419 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_LOWEST_PRIORITY
||
1420 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].DeviceType
!= BBS_CDROM
1425 NewPtr
->Data
[CDIndex
] = Ptr
->Data
[Index
];
1428 NewCDPtr
= NewPtr
->Data
;
1433 Ptr
= (LEGACY_DEV_ORDER_ENTRY
*) (&Ptr
->Data
[Ptr
->Length
/ sizeof (UINT16
) - 1]);
1434 NewPtr
= (LEGACY_DEV_ORDER_ENTRY
*) (&NewPtr
->Data
[NewPtr
->Length
/ sizeof (UINT16
) -1]);
1435 NewPtr
->BbsType
= Ptr
->BbsType
;
1436 NewPtr
->Length
= (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1437 for (Index
= 0; Index
< (INTN
) (Ptr
->Length
/ sizeof (UINT16
) - 1); Index
++) {
1438 if (LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_IGNORE_ENTRY
||
1439 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1440 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_LOWEST_PRIORITY
||
1441 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].DeviceType
!= BBS_EMBED_NETWORK
1446 NewPtr
->Data
[NETIndex
] = Ptr
->Data
[Index
];
1449 NewNETPtr
= NewPtr
->Data
;
1454 Ptr
= (LEGACY_DEV_ORDER_ENTRY
*) (&Ptr
->Data
[Ptr
->Length
/ sizeof (UINT16
) - 1]);
1455 NewPtr
= (LEGACY_DEV_ORDER_ENTRY
*) (&NewPtr
->Data
[NewPtr
->Length
/ sizeof (UINT16
) -1]);
1456 NewPtr
->BbsType
= Ptr
->BbsType
;
1457 NewPtr
->Length
= (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1458 for (Index
= 0; Index
< (INTN
) (Ptr
->Length
/ sizeof (UINT16
) - 1); Index
++) {
1459 if (LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_IGNORE_ENTRY
||
1460 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1461 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].BootPriority
== BBS_LOWEST_PRIORITY
||
1462 LocalBbsTable
[Ptr
->Data
[Index
] & 0xFF].DeviceType
!= BBS_BEV_DEVICE
1467 NewPtr
->Data
[BEVIndex
] = Ptr
->Data
[Index
];
1470 NewBEVPtr
= NewPtr
->Data
;
1472 Print(L
"About to enter another loop; BbsCount = %d\n", BbsCount
);
1473 for (Index
= 0; Index
< BbsCount
; Index
++) {
1474 // Print(L" Looping: Index = %d\n", Index);
1475 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1476 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1481 switch (LocalBbsTable
[Index
].DeviceType
) {
1484 NewDevPtr
= NewFDPtr
;
1489 NewDevPtr
= NewHDPtr
;
1494 NewDevPtr
= NewCDPtr
;
1497 case BBS_EMBED_NETWORK
:
1499 NewDevPtr
= NewNETPtr
;
1502 case BBS_BEV_DEVICE
:
1504 NewDevPtr
= NewBEVPtr
;
1512 // at this point we have copied those valid indexes to new buffer
1513 // and we should check if there is any new appeared boot device
1515 Print(L
" Checking for new devices\n");
1517 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1518 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1523 if (Index2
== *Idx
) {
1525 // Index2 == *Idx means we didn't find Index
1526 // so Index is a new appeared device's index in BBS table
1527 // insert it before disabled indexes.
1529 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1530 if ((NewDevPtr
[Index2
] & 0xFF00) == 0xFF00) {
1534 CopyMem (&NewDevPtr
[Index2
+ 1], &NewDevPtr
[Index2
], (*Idx
- Index2
) * sizeof (UINT16
));
1535 NewDevPtr
[Index2
] = (UINT16
) (Index
& 0xFF);
1541 FreePool (DevOrder
);
1543 Print(L
"About to call SetVariable()\n");
1544 Status
= gRT
->SetVariable (
1545 VAR_LEGACY_DEV_ORDER
,
1546 &gEfiLegacyDevOrderVariableGuid
,
1551 FreePool (NewDevOrder
);
1553 Print(L
"Returning from BdsUpdateLegacyDevOrder()\n");