2 This function deal with the legacy boot option, it create, delete
3 and manage the legacy boot option, all legacy boot option is getting from
6 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "BBSsupport.h"
21 Translate the first n characters of an Ascii string to
22 Unicode characters. The count n is indicated by parameter
23 Size. If Size is greater than the length of string, then
24 the entire string is translated.
27 @param AStr Pointer to input Ascii string.
28 @param Size The number of characters to translate.
29 @param UStr Pointer to output Unicode string buffer.
42 while (AStr
[Idx
] != 0) {
43 UStr
[Idx
] = (CHAR16
) AStr
[Idx
];
54 Build Legacy Device Name String according.
56 @param CurBBSEntry BBS Table.
58 @param BufSize The buffer size.
59 @param BootString The output string.
63 BdsBuildLegacyDevNameString (
64 IN BBS_TABLE
*CurBBSEntry
,
67 OUT CHAR16
*BootString
80 Fmt
= L
"Primary Master %s";
87 Fmt
= L
"Primary Slave %s";
94 Fmt
= L
"Secondary Master %s";
101 Fmt
= L
"Secondary Slave %s";
109 switch (CurBBSEntry
->DeviceType
) {
130 case BBS_EMBED_NETWORK
:
144 // If current BBS entry has its description then use it.
146 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
147 if (NULL
!= StringDesc
) {
149 // Only get fisrt 32 characters, this is suggested by BBS spec
151 AsciiToUnicodeSize (StringDesc
, 32, Temp
);
157 // BbsTable 16 entries are for onboard IDE.
158 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
160 if (Index
>= 5 && Index
<= 16 && CurBBSEntry
->DeviceType
== BBS_HARDDISK
) {
162 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
164 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
170 Create a legacy boot option for the specified entry of
171 BBS table, save it as variable, and append it to the boot
175 @param CurrentBbsEntry Pointer to current BBS table.
176 @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS
177 @param Index Index of the specified entry in BBS table.
178 @param BootOrderList On input, the original boot order list.
179 On output, the new boot order list attached with the
181 @param BootOrderListSize On input, the original size of boot order list.
182 On output, the size of new boot order list.
184 @retval EFI_SUCCESS Boot Option successfully created.
185 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
186 @retval Other Error occurs while setting variable.
190 BdsCreateLegacyBootOption (
191 IN BBS_TABLE
*CurrentBbsEntry
,
192 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
194 IN OUT UINT16
**BootOrderList
,
195 IN OUT UINTN
*BootOrderListSize
199 UINT16 CurrentBootOptionNo
;
200 UINT16 BootString
[10];
201 UINT16 BootDesc
[100];
202 CHAR8 HelpString
[100];
203 UINT16
*NewBootOrderList
;
208 UINT16 CurrentBbsDevPathSize
;
209 UINTN BootOrderIndex
;
210 UINTN BootOrderLastIndex
;
212 BOOLEAN IndexNotFound
;
213 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
215 if ((*BootOrderList
) == NULL
) {
216 CurrentBootOptionNo
= 0;
218 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
219 IndexNotFound
= TRUE
;
220 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
221 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
222 IndexNotFound
= FALSE
;
227 if (!IndexNotFound
) {
234 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
244 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
247 // Create new BBS device path node with description string
249 UnicodeStrToAsciiStr ((CONST CHAR16
*)&BootDesc
, (CHAR8
*)&HelpString
);
251 StringLen
= AsciiStrLen (HelpString
);
252 NewBbsDevPathNode
= AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
253 if (NewBbsDevPathNode
== NULL
) {
254 return EFI_OUT_OF_RESOURCES
;
256 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
257 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
258 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
261 // Create entire new CurrentBbsDevPath with end node
263 CurrentBbsDevPath
= AppendDevicePathNode (
265 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
267 if (CurrentBbsDevPath
== NULL
) {
268 FreePool (NewBbsDevPathNode
);
269 return EFI_OUT_OF_RESOURCES
;
272 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
274 BufferSize
= sizeof (UINT32
) +
277 CurrentBbsDevPathSize
+
281 Buffer
= AllocateZeroPool (BufferSize
);
282 if (Buffer
== NULL
) {
283 FreePool (NewBbsDevPathNode
);
284 FreePool (CurrentBbsDevPath
);
285 return EFI_OUT_OF_RESOURCES
;
288 Ptr
= (UINT8
*) Buffer
;
290 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
291 Ptr
+= sizeof (UINT32
);
293 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
294 Ptr
+= sizeof (UINT16
);
301 Ptr
+= StrSize (BootDesc
);
306 CurrentBbsDevPathSize
308 Ptr
+= CurrentBbsDevPathSize
;
316 Ptr
+= sizeof (BBS_TABLE
);
317 *((UINT16
*) Ptr
) = (UINT16
) Index
;
319 Status
= gRT
->SetVariable (
321 &gEfiGlobalVariableGuid
,
331 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
332 if (NULL
== NewBootOrderList
) {
333 FreePool (NewBbsDevPathNode
);
334 FreePool (CurrentBbsDevPath
);
335 return EFI_OUT_OF_RESOURCES
;
338 if (*BootOrderList
!= NULL
) {
339 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
340 FreePool (*BootOrderList
);
343 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
344 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
345 *BootOrderListSize
+= sizeof (UINT16
);
346 *BootOrderList
= NewBootOrderList
;
348 FreePool (NewBbsDevPathNode
);
349 FreePool (CurrentBbsDevPath
);
354 Check if the boot option is a legacy one.
356 @param BootOptionVar The boot option data payload.
357 @param BbsEntry The BBS Table.
358 @param BbsIndex The table index.
360 @retval TRUE It is a legacy boot option.
361 @retval FALSE It is not a legacy boot option.
365 BdsIsLegacyBootOption (
366 IN UINT8
*BootOptionVar
,
367 OUT BBS_TABLE
**BbsEntry
,
372 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
377 Ptr
+= sizeof (UINT32
);
378 DevPathLen
= *(UINT16
*) Ptr
;
379 Ptr
+= sizeof (UINT16
);
380 Ptr
+= StrSize ((UINT16
*) Ptr
);
381 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
382 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
384 *BbsEntry
= (BBS_TABLE
*) Ptr
;
385 Ptr
+= sizeof (BBS_TABLE
);
386 *BbsIndex
= *(UINT16
*) Ptr
;
397 Delete all the invalid legacy boot options.
399 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
400 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
401 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
404 BdsDeleteAllInvalidLegacyBootOptions (
409 UINT8
*BootOptionVar
;
411 UINTN BootOptionSize
;
415 HDD_INFO
*LocalHddInfo
;
416 BBS_TABLE
*LocalBbsTable
;
419 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
421 UINT16 BootOption
[10];
422 UINT16 BootDesc
[100];
423 BOOLEAN DescStringMatch
;
425 Status
= EFI_SUCCESS
;
431 LocalBbsTable
= NULL
;
434 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
435 if (EFI_ERROR (Status
)) {
439 LegacyBios
->GetBbsInfo (
447 BootOrder
= BdsLibGetVariableAndSize (
449 &gEfiGlobalVariableGuid
,
452 if (NULL
== BootOrder
) {
453 return EFI_NOT_FOUND
;
457 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
458 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
459 BootOptionVar
= BdsLibGetVariableAndSize (
461 &gEfiGlobalVariableGuid
,
464 if (NULL
== BootOptionVar
) {
465 if (BootOrder
!= NULL
) {
466 FreePool (BootOrder
);
468 return EFI_OUT_OF_RESOURCES
;
472 // Skip Non-Legacy boot options
474 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
475 if (BootOptionVar
!= NULL
) {
476 FreePool (BootOptionVar
);
483 // Check if BBS Description String is changed
485 DescStringMatch
= FALSE
;
487 BdsBuildLegacyDevNameString (
488 &LocalBbsTable
[BbsIndex
],
494 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
495 DescStringMatch
= TRUE
;
498 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
499 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
500 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
506 if (BootOptionVar
!= NULL
) {
507 FreePool (BootOptionVar
);
512 BdsDeleteBootOption (
520 // Adjust the number of boot options.
522 if (BootOrderSize
!= 0) {
523 Status
= gRT
->SetVariable (
525 &gEfiGlobalVariableGuid
,
531 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
534 if (BootOrder
!= NULL
) {
535 FreePool (BootOrder
);
542 Find all legacy boot option by device type.
544 @param BootOrder The boot order array.
545 @param BootOptionNum The number of boot option.
546 @param DevType Device type.
547 @param Attribute The boot option attribute.
548 @param BbsIndex The BBS table index.
549 @param OptionNumber The boot option index.
551 @retval TRUE The Legacy boot option is found.
552 @retval FALSE The legacy boot option is not found.
556 BdsFindLegacyBootOptionByDevType (
557 IN UINT16
*BootOrder
,
558 IN UINTN BootOptionNum
,
560 OUT UINT32
*Attribute
,
561 OUT UINT16
*BbsIndex
,
562 OUT UINTN
*OptionNumber
566 UINTN BootOrderIndex
;
567 UINT16 BootOption
[100];
568 UINTN BootOptionSize
;
569 UINT8
*BootOptionVar
;
576 if (NULL
== BootOrder
) {
581 // Loop all boot option from variable
583 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
584 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
585 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
586 BootOptionVar
= BdsLibGetVariableAndSize (
588 &gEfiGlobalVariableGuid
,
591 if (NULL
== BootOptionVar
) {
596 // Skip Non-legacy boot option
598 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
599 FreePool (BootOptionVar
);
603 if (BbsEntry
->DeviceType
!= DevType
) {
604 FreePool (BootOptionVar
);
608 *Attribute
= *(UINT32
*) BootOptionVar
;
609 *OptionNumber
= Index
;
611 FreePool (BootOptionVar
);
619 Create a legacy boot option.
621 @param BbsItem The BBS Table entry.
622 @param Index Index of the specified entry in BBS table.
623 @param BootOrderList The boot order list.
624 @param BootOrderListSize The size of boot order list.
626 @retval EFI_OUT_OF_RESOURCE No enough memory.
627 @retval EFI_SUCCESS The function complete successfully.
628 @return Other value if the legacy boot option is not created.
632 BdsCreateOneLegacyBootOption (
633 IN BBS_TABLE
*BbsItem
,
635 IN OUT UINT16
**BootOrderList
,
636 IN OUT UINTN
*BootOrderListSize
639 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
641 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
646 // Create device path node.
648 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
649 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
650 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
651 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
652 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
654 DevPath
= AppendDevicePathNode (
656 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
658 if (NULL
== DevPath
) {
659 return EFI_OUT_OF_RESOURCES
;
662 Status
= BdsCreateLegacyBootOption (
669 BbsItem
->BootPriority
= 0x00;
678 Add the legacy boot options from BBS table if they do not exist.
680 @retval EFI_SUCCESS The boot options are added successfully
681 or they are already in boot options.
685 BdsAddNonExistingLegacyBootOptions (
694 HDD_INFO
*LocalHddInfo
;
695 BBS_TABLE
*LocalBbsTable
;
697 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
707 LocalBbsTable
= NULL
;
709 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
710 if (EFI_ERROR (Status
)) {
714 LegacyBios
->GetBbsInfo (
722 BootOrder
= BdsLibGetVariableAndSize (
724 &gEfiGlobalVariableGuid
,
727 if (NULL
== BootOrder
) {
731 for (Index
= 0; Index
< BbsCount
; Index
++) {
732 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
733 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
738 Ret
= BdsFindLegacyBootOptionByDevType (
740 BootOrderSize
/ sizeof (UINT16
),
741 LocalBbsTable
[Index
].DeviceType
,
751 // Not found such type of legacy device in boot options or we found but it's disabled
752 // so we have to create one and put it to the tail of boot order list
754 Status
= BdsCreateOneLegacyBootOption (
755 &LocalBbsTable
[Index
],
760 if (EFI_ERROR (Status
)) {
765 if (BootOrderSize
> 0) {
766 Status
= gRT
->SetVariable (
768 &gEfiGlobalVariableGuid
,
774 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
777 if (BootOrder
!= NULL
) {
778 FreePool (BootOrder
);
785 Fill the device order buffer.
787 @param BbsTable The BBS table.
788 @param BbsType The BBS Type.
789 @param BbsCount The BBS Count.
790 @param Buf device order buffer.
792 @return The device order buffer.
797 IN BBS_TABLE
*BbsTable
,
805 for (Index
= 0; Index
< BbsCount
; Index
++) {
806 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
810 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
814 *Buf
= (UINT16
) (Index
& 0xFF);
822 Create the device order buffer.
824 @param BbsTable The BBS table.
825 @param BbsCount The BBS Count.
827 @retval EFI_SUCCES The buffer is created and the EFI variable named
828 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
830 @return Other value if the set of EFI variable fails. Check gRT->SetVariable
831 for detailed information.
836 IN BBS_TABLE
*BbsTable
,
858 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
861 Status
= EFI_SUCCESS
;
864 // Count all boot devices
866 for (Index
= 0; Index
< BbsCount
; Index
++) {
867 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
871 switch (BbsTable
[Index
].DeviceType
) {
884 case BBS_EMBED_NETWORK
:
897 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
898 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
899 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
900 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
901 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
904 // Create buffer to hold all boot device order
906 DevOrder
= AllocateZeroPool (TotalSize
);
907 if (NULL
== DevOrder
) {
908 return EFI_OUT_OF_RESOURCES
;
913 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
914 Ptr
+= sizeof (BBS_TYPE
);
915 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
916 Ptr
+= sizeof (UINT16
);
918 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
921 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
922 Ptr
+= sizeof (BBS_TYPE
);
923 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
924 Ptr
+= sizeof (UINT16
);
926 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
929 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
930 Ptr
+= sizeof (BBS_TYPE
);
931 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
932 Ptr
+= sizeof (UINT16
);
934 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
937 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
938 Ptr
+= sizeof (BBS_TYPE
);
939 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
940 Ptr
+= sizeof (UINT16
);
942 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
945 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
946 Ptr
+= sizeof (BBS_TYPE
);
947 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
948 Ptr
+= sizeof (UINT16
);
950 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
954 // Save device order for legacy boot device to variable.
956 Status
= gRT
->SetVariable (
957 VAR_LEGACY_DEV_ORDER
,
958 &EfiLegacyDevOrderGuid
,
970 Add the legacy boot devices from BBS table into
971 the legacy device boot order.
973 @retval EFI_SUCCESS The boot devices are added successfully.
977 BdsUpdateLegacyDevOrder (
984 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
988 HDD_INFO
*LocalHddInfo
;
989 BBS_TABLE
*LocalBbsTable
;
1016 LocalHddInfo
= NULL
;
1017 LocalBbsTable
= NULL
;
1025 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1033 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1034 if (EFI_ERROR (Status
)) {
1038 LegacyBios
->GetBbsInfo (
1046 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1047 VAR_LEGACY_DEV_ORDER
,
1048 &EfiLegacyDevOrderGuid
,
1051 if (NULL
== DevOrder
) {
1052 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1055 // First we figure out how many boot devices with same device type respectively
1057 for (Index
= 0; Index
< BbsCount
; Index
++) {
1058 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1059 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1064 switch (LocalBbsTable
[Index
].DeviceType
) {
1077 case BBS_EMBED_NETWORK
:
1081 case BBS_BEV_DEVICE
:
1090 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1091 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1092 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1093 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1094 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1096 NewDevOrder
= AllocateZeroPool (TotalSize
);
1097 if (NULL
== NewDevOrder
) {
1098 return EFI_OUT_OF_RESOURCES
;
1101 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1102 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1103 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1104 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1105 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1111 NewPtr
= NewDevOrder
;
1112 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1113 Ptr
+= sizeof (BBS_TYPE
);
1114 NewPtr
+= sizeof (BBS_TYPE
);
1115 Length
= *((UINT16
*) Ptr
);
1116 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1117 Ptr
+= sizeof (UINT16
);
1119 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1120 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1121 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1122 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1124 Ptr
+= sizeof (UINT16
);
1128 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1130 Ptr
+= sizeof (UINT16
);
1135 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1136 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1137 Ptr
+= sizeof (BBS_TYPE
);
1138 NewPtr
+= sizeof (BBS_TYPE
);
1139 Length
= *((UINT16
*) Ptr
);
1140 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1141 Ptr
+= sizeof (UINT16
);
1143 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1144 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1145 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1146 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1147 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1149 Ptr
+= sizeof (UINT16
);
1153 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1155 Ptr
+= sizeof (UINT16
);
1160 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1161 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1162 Ptr
+= sizeof (BBS_TYPE
);
1163 NewPtr
+= sizeof (BBS_TYPE
);
1164 Length
= *((UINT16
*) Ptr
);
1165 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1166 Ptr
+= sizeof (UINT16
);
1168 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1169 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1170 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1171 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1172 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1174 Ptr
+= sizeof (UINT16
);
1178 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1180 Ptr
+= sizeof (UINT16
);
1185 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1186 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1187 Ptr
+= sizeof (BBS_TYPE
);
1188 NewPtr
+= sizeof (BBS_TYPE
);
1189 Length
= *((UINT16
*) Ptr
);
1190 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1191 Ptr
+= sizeof (UINT16
);
1193 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1194 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1195 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1196 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1197 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1199 Ptr
+= sizeof (UINT16
);
1203 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1205 Ptr
+= sizeof (UINT16
);
1210 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1211 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1212 Ptr
+= sizeof (BBS_TYPE
);
1213 NewPtr
+= sizeof (BBS_TYPE
);
1214 Length
= *((UINT16
*) Ptr
);
1215 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1216 Ptr
+= sizeof (UINT16
);
1218 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1219 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1220 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1221 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1222 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1224 Ptr
+= sizeof (UINT16
);
1228 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1230 Ptr
+= sizeof (UINT16
);
1233 for (Index
= 0; Index
< BbsCount
; Index
++) {
1234 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1235 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1240 switch (LocalBbsTable
[Index
].DeviceType
) {
1243 NewDevPtr
= NewFDPtr
;
1248 NewDevPtr
= NewHDPtr
;
1253 NewDevPtr
= NewCDPtr
;
1256 case BBS_EMBED_NETWORK
:
1258 NewDevPtr
= NewNETPtr
;
1261 case BBS_BEV_DEVICE
:
1263 NewDevPtr
= NewBEVPtr
;
1271 // at this point we have copied those valid indexes to new buffer
1272 // and we should check if there is any new appeared boot device
1275 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1276 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1281 if (Index2
== *Idx
) {
1283 // Index2 == *Idx means we didn't find Index
1284 // so Index is a new appeared device's index in BBS table
1287 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1295 // Just to make sure that disabled indexes are all at the end of the array
1297 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1298 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1302 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1303 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1304 Tmp
= NewFDPtr
[Index
];
1305 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1306 NewFDPtr
[Index2
] = Tmp
;
1315 // Just to make sure that disabled indexes are all at the end of the array
1317 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1318 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1322 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1323 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1324 Tmp
= NewHDPtr
[Index
];
1325 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1326 NewHDPtr
[Index2
] = Tmp
;
1335 // Just to make sure that disabled indexes are all at the end of the array
1337 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1338 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1342 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1343 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1344 Tmp
= NewCDPtr
[Index
];
1345 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1346 NewCDPtr
[Index2
] = Tmp
;
1353 if (NETCount
!= 0) {
1355 // Just to make sure that disabled indexes are all at the end of the array
1357 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1358 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1362 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1363 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1364 Tmp
= NewNETPtr
[Index
];
1365 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1366 NewNETPtr
[Index2
] = Tmp
;
1375 // Just to make sure that disabled indexes are all at the end of the array
1377 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1378 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1382 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1383 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1384 Tmp
= NewBEVPtr
[Index
];
1385 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1386 NewBEVPtr
[Index2
] = Tmp
;
1393 FreePool (DevOrder
);
1395 Status
= gRT
->SetVariable (
1396 VAR_LEGACY_DEV_ORDER
,
1397 &EfiLegacyDevOrderGuid
,
1402 FreePool (NewDevOrder
);
1408 Set Boot Priority for specified device type.
1410 @param DeviceType The device type.
1411 @param LocalBbsTable The BBS table.
1412 @param Priority The prority table.
1414 @retval EFI_SUCCESS The function completes successfully.
1415 @retval EFI_NOT_FOUND Failed to find device.
1419 BdsSetBootPriority4SameTypeDev (
1420 IN UINT16 DeviceType
,
1421 IN OUT BBS_TABLE
*LocalBbsTable
,
1422 IN OUT UINT16
*Priority
1433 DevOrder
= BdsLibGetVariableAndSize (
1434 VAR_LEGACY_DEV_ORDER
,
1435 &EfiLegacyDevOrderGuid
,
1438 if (NULL
== DevOrder
) {
1439 return EFI_OUT_OF_RESOURCES
;
1442 OrigBuffer
= DevOrder
;
1443 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1444 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1448 DevOrder
+= sizeof (BBS_TYPE
);
1449 DevOrder
+= *(UINT16
*) DevOrder
;
1452 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1453 FreePool (OrigBuffer
);
1454 return EFI_NOT_FOUND
;
1457 DevOrder
+= sizeof (BBS_TYPE
);
1458 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1459 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1461 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1463 for (Index
= 0; Index
< DevCount
; Index
++) {
1464 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1466 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1469 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1474 FreePool (OrigBuffer
);
1479 Print the BBS Table.
1481 @param LocalBbsTable The BBS table.
1486 IN BBS_TABLE
*LocalBbsTable
1491 DEBUG ((DEBUG_ERROR
, "\n"));
1492 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1493 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1494 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1495 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1496 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1497 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1504 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1506 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1507 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1508 (UINTN
) LocalBbsTable
[Idx
].Device
,
1509 (UINTN
) LocalBbsTable
[Idx
].Function
,
1510 (UINTN
) LocalBbsTable
[Idx
].Class
,
1511 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1512 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1513 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1514 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1515 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1516 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1517 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1521 DEBUG ((DEBUG_ERROR
, "\n"));
1526 Set the boot priority for BBS entries based on boot option entry and boot order.
1528 @param Entry The boot option is to be checked for refresh BBS table.
1530 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1531 @return status of BdsSetBootPriority4SameTypeDev()
1534 BdsRefreshBbsTableForBoot (
1535 IN BDS_COMMON_OPTION
*Entry
1541 HDD_INFO
*LocalHddInfo
;
1542 BBS_TABLE
*LocalBbsTable
;
1544 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1548 UINTN BootOrderSize
;
1549 UINT8
*BootOptionVar
;
1550 UINTN BootOptionSize
;
1551 UINT16 BootOption
[100];
1554 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1558 LocalHddInfo
= NULL
;
1559 LocalBbsTable
= NULL
;
1560 DevType
= BBS_UNKNOWN
;
1562 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1563 if (EFI_ERROR (Status
)) {
1567 LegacyBios
->GetBbsInfo (
1575 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1576 // We will set them according to the settings setup by user
1578 for (Index
= 0; Index
< BbsCount
; Index
++) {
1579 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1580 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1581 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1582 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1586 // boot priority always starts at 0
1589 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1591 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1593 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1594 Status
= BdsSetBootPriority4SameTypeDev (
1599 if (EFI_ERROR (Status
)) {
1604 // we have to set the boot priority for other BBS entries with different device types
1606 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1608 &gEfiGlobalVariableGuid
,
1611 for (Index
= 0; ((BootOrder
!= NULL
) && (Index
< BootOrderSize
/ sizeof (UINT16
))); Index
++) {
1612 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1613 BootOptionVar
= BdsLibGetVariableAndSize (
1615 &gEfiGlobalVariableGuid
,
1618 if (NULL
== BootOptionVar
) {
1622 Ptr
= BootOptionVar
;
1624 Ptr
+= sizeof (UINT32
);
1625 DevPathLen
= *(UINT16
*) Ptr
;
1626 Ptr
+= sizeof (UINT16
);
1627 Ptr
+= StrSize ((UINT16
*) Ptr
);
1628 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1629 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1630 FreePool (BootOptionVar
);
1635 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1637 // We don't want to process twice for a device type
1639 FreePool (BootOptionVar
);
1643 Status
= BdsSetBootPriority4SameTypeDev (
1644 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1648 FreePool (BootOptionVar
);
1649 if (EFI_ERROR (Status
)) {
1654 if (BootOrder
!= NULL
) {
1655 FreePool (BootOrder
);
1659 PrintBbsTable (LocalBbsTable
);