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
[];
28 Translate the first n characters of an Ascii string to
29 Unicode characters. The count n is indicated by parameter
30 Size. If Size is greater than the length of string, then
31 the entire string is translated.
34 @param AStr Pointer to input Ascii string.
35 @param Size The number of characters to translate.
36 @param UStr Pointer to output Unicode string buffer.
49 while (AStr
[Idx
] != 0) {
50 UStr
[Idx
] = (CHAR16
) AStr
[Idx
];
61 Build Legacy Device Name String according.
63 @param CurBBSEntry BBS Table.
65 @param BufSize The buffer size.
66 @param BootString The output string.
70 BdsBuildLegacyDevNameString (
71 IN BBS_TABLE
*CurBBSEntry
,
74 OUT CHAR16
*BootString
87 Fmt
= L
"Primary Master %s";
94 Fmt
= L
"Primary Slave %s";
101 Fmt
= L
"Secondary Master %s";
108 Fmt
= L
"Secondary Slave %s";
116 switch (CurBBSEntry
->DeviceType
) {
137 case BBS_EMBED_NETWORK
:
151 // If current BBS entry has its description then use it.
153 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
154 if (NULL
!= StringDesc
) {
156 // Only get fisrt 32 characters, this is suggested by BBS spec
158 AsciiToUnicodeSize (StringDesc
, 32, Temp
);
164 // BbsTable 16 entries are for onboard IDE.
165 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
167 if (Index
>= 5 && Index
<= 16 && (CurBBSEntry
->DeviceType
== BBS_HARDDISK
|| CurBBSEntry
->DeviceType
== BBS_CDROM
)) {
169 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
171 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
176 Check if the boot option is a legacy one.
178 @param BootOptionVar The boot option data payload.
179 @param BbsEntry The BBS Table.
180 @param BbsIndex The table index.
182 @retval TRUE It is a legacy boot option.
183 @retval FALSE It is not a legacy boot option.
187 BdsIsLegacyBootOption (
188 IN UINT8
*BootOptionVar
,
189 OUT BBS_TABLE
**BbsEntry
,
194 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
199 Ptr
+= sizeof (UINT32
);
200 DevPathLen
= *(UINT16
*) Ptr
;
201 Ptr
+= sizeof (UINT16
);
202 Ptr
+= StrSize ((UINT16
*) Ptr
);
203 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
204 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
206 *BbsEntry
= (BBS_TABLE
*) Ptr
;
207 Ptr
+= sizeof (BBS_TABLE
);
208 *BbsIndex
= *(UINT16
*) Ptr
;
219 Find all legacy boot option by device type.
221 @param BootOrder The boot order array.
222 @param BootOptionNum The number of boot option.
223 @param DevType Device type.
224 @param DevName Device name.
225 @param Attribute The boot option attribute.
226 @param BbsIndex The BBS table index.
227 @param OptionNumber The boot option index.
229 @retval TRUE The Legacy boot option is found.
230 @retval FALSE The legacy boot option is not found.
234 BdsFindLegacyBootOptionByDevTypeAndName (
235 IN UINT16
*BootOrder
,
236 IN UINTN BootOptionNum
,
239 OUT UINT32
*Attribute
,
240 OUT UINT16
*BbsIndex
,
241 OUT UINT16
*OptionNumber
245 CHAR16 BootOption
[9];
246 UINTN BootOptionSize
;
247 UINT8
*BootOptionVar
;
254 if (NULL
== BootOrder
) {
259 // Loop all boot option from variable
261 for (Index
= 0; Index
< BootOptionNum
; Index
++) {
262 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", (UINTN
) BootOrder
[Index
]);
263 BootOptionVar
= BdsLibGetVariableAndSize (
265 &gEfiGlobalVariableGuid
,
268 if (NULL
== BootOptionVar
) {
273 // Skip Non-legacy boot option
275 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
276 FreePool (BootOptionVar
);
281 (BbsEntry
->DeviceType
!= DevType
) ||
282 (StrCmp (DevName
, (CHAR16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) != 0)
284 FreePool (BootOptionVar
);
288 *Attribute
= *(UINT32
*) BootOptionVar
;
289 *OptionNumber
= BootOrder
[Index
];
291 FreePool (BootOptionVar
);
300 Create a legacy boot option for the specified entry of
301 BBS table, save it as variable, and append it to the boot
305 @param CurrentBbsEntry Pointer to current BBS table.
306 @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS
307 @param Index Index of the specified entry in BBS table.
308 @param BootOrderList On input, the original boot order list.
309 On output, the new boot order list attached with the
311 @param BootOrderListSize On input, the original size of boot order list.
312 On output, the size of new boot order list.
314 @retval EFI_SUCCESS Boot Option successfully created.
315 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
316 @retval Other Error occurs while setting variable.
320 BdsCreateLegacyBootOption (
321 IN BBS_TABLE
*CurrentBbsEntry
,
322 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
324 IN OUT UINT16
**BootOrderList
,
325 IN OUT UINTN
*BootOrderListSize
329 UINT16 CurrentBootOptionNo
;
330 UINT16 BootString
[10];
331 CHAR16 BootDesc
[100];
332 CHAR8 HelpString
[100];
333 UINT16
*NewBootOrderList
;
338 UINT16 CurrentBbsDevPathSize
;
339 UINTN BootOrderIndex
;
340 UINTN BootOrderLastIndex
;
342 BOOLEAN IndexNotFound
;
343 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
345 if ((*BootOrderList
) == NULL
) {
346 CurrentBootOptionNo
= 0;
348 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
349 IndexNotFound
= TRUE
;
350 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
351 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
352 IndexNotFound
= FALSE
;
357 if (!IndexNotFound
) {
364 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
374 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
377 // Create new BBS device path node with description string
379 UnicodeStrToAsciiStr (BootDesc
, HelpString
);
381 StringLen
= AsciiStrLen (HelpString
);
382 NewBbsDevPathNode
= AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
383 if (NewBbsDevPathNode
== NULL
) {
384 return EFI_OUT_OF_RESOURCES
;
386 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
387 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
388 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
391 // Create entire new CurrentBbsDevPath with end node
393 CurrentBbsDevPath
= AppendDevicePathNode (
395 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
397 if (CurrentBbsDevPath
== NULL
) {
398 FreePool (NewBbsDevPathNode
);
399 return EFI_OUT_OF_RESOURCES
;
402 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
404 BufferSize
= sizeof (UINT32
) +
407 CurrentBbsDevPathSize
+
411 Buffer
= AllocateZeroPool (BufferSize
);
412 if (Buffer
== NULL
) {
413 FreePool (NewBbsDevPathNode
);
414 FreePool (CurrentBbsDevPath
);
415 return EFI_OUT_OF_RESOURCES
;
418 Ptr
= (UINT8
*) Buffer
;
420 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
421 Ptr
+= sizeof (UINT32
);
423 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
424 Ptr
+= sizeof (UINT16
);
431 Ptr
+= StrSize (BootDesc
);
436 CurrentBbsDevPathSize
438 Ptr
+= CurrentBbsDevPathSize
;
446 Ptr
+= sizeof (BBS_TABLE
);
447 *((UINT16
*) Ptr
) = (UINT16
) Index
;
449 Status
= gRT
->SetVariable (
451 &gEfiGlobalVariableGuid
,
461 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
462 if (NULL
== NewBootOrderList
) {
463 FreePool (NewBbsDevPathNode
);
464 FreePool (CurrentBbsDevPath
);
465 return EFI_OUT_OF_RESOURCES
;
468 if (*BootOrderList
!= NULL
) {
469 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
470 FreePool (*BootOrderList
);
473 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
474 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
475 *BootOrderListSize
+= sizeof (UINT16
);
476 *BootOrderList
= NewBootOrderList
;
478 FreePool (NewBbsDevPathNode
);
479 FreePool (CurrentBbsDevPath
);
484 Create a legacy boot option.
486 @param BbsItem The BBS Table entry.
487 @param Index Index of the specified entry in BBS table.
488 @param BootOrderList The boot order list.
489 @param BootOrderListSize The size of boot order list.
491 @retval EFI_OUT_OF_RESOURCE No enough memory.
492 @retval EFI_SUCCESS The function complete successfully.
493 @return Other value if the legacy boot option is not created.
497 BdsCreateOneLegacyBootOption (
498 IN BBS_TABLE
*BbsItem
,
500 IN OUT UINT16
**BootOrderList
,
501 IN OUT UINTN
*BootOrderListSize
504 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
506 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
511 // Create device path node.
513 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
514 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
515 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
516 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
517 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
519 DevPath
= AppendDevicePathNode (
521 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
523 if (NULL
== DevPath
) {
524 return EFI_OUT_OF_RESOURCES
;
527 Status
= BdsCreateLegacyBootOption (
534 BbsItem
->BootPriority
= 0x00;
542 Group the legacy boot options in the BootOption.
544 The routine assumes the boot options in the beginning that covers all the device
545 types are ordered properly and re-position the following boot options just after
546 the corresponding boot options with the same device type.
548 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]
549 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly
550 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]
552 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]
553 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly
554 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]
556 @param BootOption Pointer to buffer containing Boot Option Numbers
557 @param BootOptionCount Count of the Boot Option Numbers
560 GroupMultipleLegacyBootOption4SameType (
562 UINTN BootOptionCount
565 UINTN DeviceTypeIndex
[7];
572 SetMem (DeviceTypeIndex
, sizeof (DeviceTypeIndex
), 0xFF);
574 for (Index
= 0; Index
< BootOptionCount
; Index
++) {
577 // Find the DeviceType
579 for (MappingIndex
= 0; MappingIndex
< mBootOptionBbsMappingCount
; MappingIndex
++) {
580 if (mBootOptionBbsMapping
[MappingIndex
].BootOptionNumber
== BootOption
[Index
]) {
584 if (MappingIndex
== mBootOptionBbsMappingCount
) {
586 // Is not a legacy boot option
591 ASSERT ((mBootOptionBbsMapping
[MappingIndex
].BbsType
& 0xF) <
592 sizeof (DeviceTypeIndex
) / sizeof (DeviceTypeIndex
[0]));
593 NextIndex
= &DeviceTypeIndex
[mBootOptionBbsMapping
[MappingIndex
].BbsType
& 0xF];
594 if (*NextIndex
== (UINTN
) -1) {
596 // *NextIndex is the index in BootOption to put the next Option Number for the same type
598 *NextIndex
= Index
+ 1;
601 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position
603 OptionNumber
= BootOption
[Index
];
604 CopyMem (&BootOption
[*NextIndex
+ 1], &BootOption
[*NextIndex
], (Index
- *NextIndex
) * sizeof (UINT16
));
605 BootOption
[*NextIndex
] = OptionNumber
;
608 // Update the DeviceTypeIndex array to reflect the right shift operation
610 for (DeviceIndex
= 0; DeviceIndex
< sizeof (DeviceTypeIndex
) / sizeof (DeviceTypeIndex
[0]); DeviceIndex
++) {
611 if (DeviceTypeIndex
[DeviceIndex
] != (UINTN
) -1 && DeviceTypeIndex
[DeviceIndex
] >= *NextIndex
) {
612 DeviceTypeIndex
[DeviceIndex
]++;
620 Function returns the value of the specified variable.
623 @param Name A Null-terminated Unicode string that is
624 the name of the vendor's variable.
625 @param VendorGuid A unique identifier for the vendor.
627 @return The payload of the variable.
628 @retval NULL If the variable can't be read.
634 IN EFI_GUID
*VendorGuid
639 return BdsLibGetVariableAndSize (Name
, VendorGuid
, &VarSize
);
643 Function deletes the variable specified by VarName and VarGuid.
645 @param VarName A Null-terminated Unicode string that is
646 the name of the vendor's variable.
648 @param VarGuid A unique identifier for the vendor.
650 @retval EFI_SUCCESS The variable was found and removed
651 @retval EFI_UNSUPPORTED The variable store was inaccessible
652 @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available
653 @retval EFI_NOT_FOUND The variable was not found
657 EfiLibDeleteVariable (
665 VarBuf
= EfiLibGetVariable (VarName
, VarGuid
);
666 Status
= EFI_NOT_FOUND
;
668 if (VarBuf
!= NULL
) {
670 // Delete variable from Storage
672 Status
= gRT
->SetVariable (VarName
, VarGuid
, VAR_FLAG
, 0, NULL
);
673 ASSERT (!EFI_ERROR (Status
));
681 Add the legacy boot options from BBS table if they do not exist.
683 @retval EFI_SUCCESS The boot options are added successfully
684 or they are already in boot options.
685 @retval EFI_NOT_FOUND No legacy boot options is found.
686 @retval EFI_OUT_OF_RESOURCE No enough memory.
687 @return Other value LegacyBoot options are not added.
691 BdsAddNonExistingLegacyBootOptions (
701 HDD_INFO
*LocalHddInfo
;
702 BBS_TABLE
*LocalBbsTable
;
704 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
713 LocalBbsTable
= NULL
;
715 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
716 if (EFI_ERROR (Status
)) {
720 if (mBootOptionBbsMapping
!= NULL
) {
721 FreePool (mBootOptionBbsMapping
);
723 mBootOptionBbsMapping
= NULL
;
724 mBootOptionBbsMappingCount
= 0;
727 LegacyBios
->GetBbsInfo (
735 BootOrder
= BdsLibGetVariableAndSize (
737 &gEfiGlobalVariableGuid
,
740 if (BootOrder
== NULL
) {
744 for (Index
= 0; Index
< BbsCount
; Index
++) {
745 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
746 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
751 BdsBuildLegacyDevNameString (&LocalBbsTable
[Index
], Index
, sizeof (Desc
), Desc
);
753 Exist
= BdsFindLegacyBootOptionByDevTypeAndName (
755 BootOrderSize
/ sizeof (UINT16
),
756 LocalBbsTable
[Index
].DeviceType
,
764 // Not found such type of legacy device in boot options or we found but it's disabled
765 // so we have to create one and put it to the tail of boot order list
767 Status
= BdsCreateOneLegacyBootOption (
768 &LocalBbsTable
[Index
],
773 if (EFI_ERROR (Status
)) {
777 OptionNumber
= BootOrder
[BootOrderSize
/ sizeof (UINT16
) - 1];
780 ASSERT (BbsIndex
== Index
);
784 mBootOptionBbsMapping
= ReallocatePool (
785 mBootOptionBbsMappingCount
* sizeof (BOOT_OPTION_BBS_MAPPING
),
786 (mBootOptionBbsMappingCount
+ 1) * sizeof (BOOT_OPTION_BBS_MAPPING
),
787 mBootOptionBbsMapping
789 ASSERT (mBootOptionBbsMapping
!= NULL
);
790 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BootOptionNumber
= OptionNumber
;
791 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BbsIndex
= Index
;
792 mBootOptionBbsMapping
[mBootOptionBbsMappingCount
].BbsType
= LocalBbsTable
[Index
].DeviceType
;
793 mBootOptionBbsMappingCount
++;
797 // Group the Boot Option Number in BootOrder for the same type devices
799 GroupMultipleLegacyBootOption4SameType (
801 BootOrderSize
/ sizeof (UINT16
)
804 if (BootOrderSize
> 0) {
805 Status
= gRT
->SetVariable (
807 &gEfiGlobalVariableGuid
,
813 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
816 if (BootOrder
!= NULL
) {
817 FreePool (BootOrder
);
824 Deletete the Boot Option from EFI Variable. The Boot Order Arrray
827 @param OptionNumber The number of Boot option want to be deleted.
828 @param BootOrder The Boot Order array.
829 @param BootOrderSize The size of the Boot Order Array.
831 @retval EFI_SUCCESS The Boot Option Variable was found and removed
832 @retval EFI_UNSUPPORTED The Boot Option Variable store was inaccessible
833 @retval EFI_NOT_FOUND The Boot Option Variable was not found
837 BdsDeleteBootOption (
838 IN UINTN OptionNumber
,
839 IN OUT UINT16
*BootOrder
,
840 IN OUT UINTN
*BootOrderSize
843 UINT16 BootOption
[100];
848 Status
= EFI_SUCCESS
;
851 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
852 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
855 // adjust boot order array
857 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
858 if (BootOrder
[Index
] == OptionNumber
) {
864 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
865 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
866 if (Index
>= Index2Del
) {
867 BootOrder
[Index
] = BootOrder
[Index
+ 1];
871 *BootOrderSize
-= sizeof (UINT16
);
879 Delete all the invalid legacy boot options.
881 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
882 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
883 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
887 BdsDeleteAllInvalidLegacyBootOptions (
892 UINT8
*BootOptionVar
;
894 UINTN BootOptionSize
;
898 HDD_INFO
*LocalHddInfo
;
899 BBS_TABLE
*LocalBbsTable
;
902 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
904 UINT16 BootOption
[10];
905 UINT16 BootDesc
[100];
906 BOOLEAN DescStringMatch
;
908 Status
= EFI_SUCCESS
;
914 LocalBbsTable
= NULL
;
917 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
918 if (EFI_ERROR (Status
)) {
922 LegacyBios
->GetBbsInfo (
930 BootOrder
= BdsLibGetVariableAndSize (
932 &gEfiGlobalVariableGuid
,
935 if (BootOrder
== NULL
) {
940 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
941 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
942 BootOptionVar
= BdsLibGetVariableAndSize (
944 &gEfiGlobalVariableGuid
,
947 if (NULL
== BootOptionVar
) {
949 Status
= gRT
->GetVariable (
951 &gEfiGlobalVariableGuid
,
956 if (Status
== EFI_NOT_FOUND
) {
960 BdsDeleteBootOption (
967 FreePool (BootOrder
);
968 return EFI_OUT_OF_RESOURCES
;
973 // Skip Non-Legacy boot option
975 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
976 if (BootOptionVar
!= NULL
) {
977 FreePool (BootOptionVar
);
983 if (BbsIndex
< BbsCount
) {
985 // Check if BBS Description String is changed
987 DescStringMatch
= FALSE
;
988 BdsBuildLegacyDevNameString (
989 &LocalBbsTable
[BbsIndex
],
995 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
996 DescStringMatch
= TRUE
;
999 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1000 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
1001 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
1008 if (BootOptionVar
!= NULL
) {
1009 FreePool (BootOptionVar
);
1014 BdsDeleteBootOption (
1022 // Adjust the number of boot options.
1024 if (BootOrderSize
!= 0) {
1025 Status
= gRT
->SetVariable (
1027 &gEfiGlobalVariableGuid
,
1033 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
1036 if (BootOrder
!= NULL
) {
1037 FreePool (BootOrder
);
1044 Add the legacy boot devices from BBS table into
1045 the legacy device boot order.
1047 @retval EFI_SUCCESS The boot devices are added successfully.
1048 @retval EFI_NOT_FOUND The legacy boot devices are not found.
1049 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.
1050 @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable
1051 because of hardware error.
1055 // BdsUpdateLegacyDevOrder (
1059 // LEGACY_DEV_ORDER_ENTRY *DevOrder;
1060 // LEGACY_DEV_ORDER_ENTRY *NewDevOrder;
1061 // LEGACY_DEV_ORDER_ENTRY *Ptr;
1062 // LEGACY_DEV_ORDER_ENTRY *NewPtr;
1063 // UINTN DevOrderSize;
1064 // EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
1065 // EFI_STATUS Status;
1068 // HDD_INFO *LocalHddInfo;
1069 // BBS_TABLE *LocalBbsTable;
1079 // UINTN HeaderSize;
1080 // UINT16 *NewFDPtr;
1081 // UINT16 *NewHDPtr;
1082 // UINT16 *NewCDPtr;
1083 // UINT16 *NewNETPtr;
1084 // UINT16 *NewBEVPtr;
1085 // UINT16 *NewDevPtr;
1099 // HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
1105 // NewDevPtr = NULL;
1107 // Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
1108 // if (EFI_ERROR (Status)) {
1112 // Status = LegacyBios->GetBbsInfo (
1119 // if (EFI_ERROR (Status)) {
1123 // DevOrder = BdsLibGetVariableAndSize (
1124 // VAR_LEGACY_DEV_ORDER,
1125 // &gEfiLegacyDevOrderVariableGuid,
1128 // if (NULL == DevOrder) {
1129 // return BdsCreateDevOrder (LocalBbsTable, BbsCount);
1132 // // First we figure out how many boot devices with same device type respectively
1134 // for (Index = 0; Index < BbsCount; Index++) {
1135 // if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
1136 // (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
1141 // switch (LocalBbsTable[Index].DeviceType) {
1146 // case BBS_HARDDISK:
1154 // case BBS_EMBED_NETWORK:
1158 // case BBS_BEV_DEVICE:
1167 // TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
1168 // TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
1169 // TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
1170 // TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
1171 // TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
1173 // NewDevOrder = AllocateZeroPool (TotalSize);
1174 // if (NULL == NewDevOrder) {
1175 // return EFI_OUT_OF_RESOURCES;
1184 // NewPtr = NewDevOrder;
1185 // NewPtr->BbsType = Ptr->BbsType;
1186 // NewPtr->Length = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
1187 // for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
1188 // if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
1189 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1190 // LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY
1195 // NewPtr->Data[FDIndex] = Ptr->Data[Index];
1198 // NewFDPtr = NewPtr->Data;
1203 // Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
1204 // NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
1205 // NewPtr->BbsType = Ptr->BbsType;
1206 // NewPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
1207 // for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
1208 // if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
1209 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1210 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
1211 // LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK
1216 // NewPtr->Data[HDIndex] = Ptr->Data[Index];
1219 // NewHDPtr = NewPtr->Data;
1224 // Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
1225 // NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
1226 // NewPtr->BbsType = Ptr->BbsType;
1227 // NewPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
1228 // for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
1229 // if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
1230 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1231 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
1232 // LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM
1237 // NewPtr->Data[CDIndex] = Ptr->Data[Index];
1240 // NewCDPtr = NewPtr->Data;
1245 // Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
1246 // NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
1247 // NewPtr->BbsType = Ptr->BbsType;
1248 // NewPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
1249 // for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
1250 // if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
1251 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1252 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
1253 // LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK
1258 // NewPtr->Data[NETIndex] = Ptr->Data[Index];
1261 // NewNETPtr = NewPtr->Data;
1266 // Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
1267 // NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
1268 // NewPtr->BbsType = Ptr->BbsType;
1269 // NewPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
1270 // for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
1271 // if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
1272 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1273 // LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
1274 // LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE
1279 // NewPtr->Data[BEVIndex] = Ptr->Data[Index];
1282 // NewBEVPtr = NewPtr->Data;
1284 // for (Index = 0; Index < BbsCount; Index++) {
1285 // if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
1286 // (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
1291 // switch (LocalBbsTable[Index].DeviceType) {
1294 // NewDevPtr = NewFDPtr;
1297 // case BBS_HARDDISK:
1299 // NewDevPtr = NewHDPtr;
1304 // NewDevPtr = NewCDPtr;
1307 // case BBS_EMBED_NETWORK:
1309 // NewDevPtr = NewNETPtr;
1312 // case BBS_BEV_DEVICE:
1314 // NewDevPtr = NewBEVPtr;
1322 // // at this point we have copied those valid indexes to new buffer
1323 // // and we should check if there is any new appeared boot device
1325 // if (Idx != NULL) {
1326 // for (Index2 = 0; Index2 < *Idx; Index2++) {
1327 // if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
1332 // if (Index2 == *Idx) {
1334 // // Index2 == *Idx means we didn't find Index
1335 // // so Index is a new appeared device's index in BBS table
1336 // // insert it before disabled indexes.
1338 // for (Index2 = 0; Index2 < *Idx; Index2++) {
1339 // if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {
1343 // CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));
1344 // NewDevPtr[Index2] = (UINT16) (Index & 0xFF);
1350 // FreePool (DevOrder);
1352 // Status = gRT->SetVariable (
1353 // VAR_LEGACY_DEV_ORDER,
1354 // &gEfiLegacyDevOrderVariableGuid,
1359 // FreePool (NewDevOrder);