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 - 2009, Intel Corporation. All rights reserved.<BR>
7 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.
405 BdsDeleteAllInvalidLegacyBootOptions (
410 UINT8
*BootOptionVar
;
412 UINTN BootOptionSize
;
416 HDD_INFO
*LocalHddInfo
;
417 BBS_TABLE
*LocalBbsTable
;
420 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
422 UINT16 BootOption
[10];
423 UINT16 BootDesc
[100];
424 BOOLEAN DescStringMatch
;
426 Status
= EFI_SUCCESS
;
432 LocalBbsTable
= NULL
;
435 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
436 if (EFI_ERROR (Status
)) {
440 LegacyBios
->GetBbsInfo (
448 BootOrder
= BdsLibGetVariableAndSize (
450 &gEfiGlobalVariableGuid
,
453 if (NULL
== BootOrder
) {
454 return EFI_NOT_FOUND
;
458 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
459 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
460 BootOptionVar
= BdsLibGetVariableAndSize (
462 &gEfiGlobalVariableGuid
,
465 if (NULL
== BootOptionVar
) {
466 if (BootOrder
!= NULL
) {
467 FreePool (BootOrder
);
469 return EFI_OUT_OF_RESOURCES
;
473 // Skip Non-Legacy boot options
475 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
476 if (BootOptionVar
!= NULL
) {
477 FreePool (BootOptionVar
);
484 // Check if BBS Description String is changed
486 DescStringMatch
= FALSE
;
488 BdsBuildLegacyDevNameString (
489 &LocalBbsTable
[BbsIndex
],
495 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
496 DescStringMatch
= TRUE
;
499 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
500 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
501 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
507 if (BootOptionVar
!= NULL
) {
508 FreePool (BootOptionVar
);
513 BdsDeleteBootOption (
521 // Adjust the number of boot options.
523 if (BootOrderSize
!= 0) {
524 Status
= gRT
->SetVariable (
526 &gEfiGlobalVariableGuid
,
532 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
535 if (BootOrder
!= NULL
) {
536 FreePool (BootOrder
);
543 Find all legacy boot option by device type.
545 @param BootOrder The boot order array.
546 @param BootOptionNum The number of boot option.
547 @param DevType Device type.
548 @param Attribute The boot option attribute.
549 @param BbsIndex The BBS table index.
550 @param OptionNumber The boot option index.
552 @retval TRUE The Legacy boot option is found.
553 @retval FALSE The legacy boot option is not found.
557 BdsFindLegacyBootOptionByDevType (
558 IN UINT16
*BootOrder
,
559 IN UINTN BootOptionNum
,
561 OUT UINT32
*Attribute
,
562 OUT UINT16
*BbsIndex
,
563 OUT UINTN
*OptionNumber
567 UINTN BootOrderIndex
;
568 UINT16 BootOption
[100];
569 UINTN BootOptionSize
;
570 UINT8
*BootOptionVar
;
577 if (NULL
== BootOrder
) {
582 // Loop all boot option from variable
584 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
585 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
586 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
587 BootOptionVar
= BdsLibGetVariableAndSize (
589 &gEfiGlobalVariableGuid
,
592 if (NULL
== BootOptionVar
) {
597 // Skip Non-legacy boot option
599 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
600 FreePool (BootOptionVar
);
604 if (BbsEntry
->DeviceType
!= DevType
) {
605 FreePool (BootOptionVar
);
609 *Attribute
= *(UINT32
*) BootOptionVar
;
610 *OptionNumber
= Index
;
612 FreePool (BootOptionVar
);
620 Create a legacy boot option.
622 @param BbsItem The BBS Table entry.
623 @param Index Index of the specified entry in BBS table.
624 @param BootOrderList The boot order list.
625 @param BootOrderListSize The size of boot order list.
627 @retval EFI_OUT_OF_RESOURCE No enough memory.
628 @retval EFI_SUCCESS The function complete successfully.
629 @return Other value if the legacy boot option is not created.
633 BdsCreateOneLegacyBootOption (
634 IN BBS_TABLE
*BbsItem
,
636 IN OUT UINT16
**BootOrderList
,
637 IN OUT UINTN
*BootOrderListSize
640 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
642 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
647 // Create device path node.
649 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
650 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
651 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
652 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
653 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
655 DevPath
= AppendDevicePathNode (
657 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
659 if (NULL
== DevPath
) {
660 return EFI_OUT_OF_RESOURCES
;
663 Status
= BdsCreateLegacyBootOption (
670 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.
682 @retval EFI_NOT_FOUND No legacy boot options is found.
683 @retval EFI_OUT_OF_RESOURCE No enough memory.
684 @return Other value LegacyBoot options are not added.
688 BdsAddNonExistingLegacyBootOptions (
697 HDD_INFO
*LocalHddInfo
;
698 BBS_TABLE
*LocalBbsTable
;
700 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
710 LocalBbsTable
= NULL
;
712 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
713 if (EFI_ERROR (Status
)) {
717 LegacyBios
->GetBbsInfo (
725 BootOrder
= BdsLibGetVariableAndSize (
727 &gEfiGlobalVariableGuid
,
730 if (NULL
== BootOrder
) {
734 for (Index
= 0; Index
< BbsCount
; Index
++) {
735 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
736 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
741 Ret
= BdsFindLegacyBootOptionByDevType (
743 BootOrderSize
/ sizeof (UINT16
),
744 LocalBbsTable
[Index
].DeviceType
,
754 // Not found such type of legacy device in boot options or we found but it's disabled
755 // so we have to create one and put it to the tail of boot order list
757 Status
= BdsCreateOneLegacyBootOption (
758 &LocalBbsTable
[Index
],
763 if (EFI_ERROR (Status
)) {
768 if (BootOrderSize
> 0) {
769 Status
= gRT
->SetVariable (
771 &gEfiGlobalVariableGuid
,
777 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
780 if (BootOrder
!= NULL
) {
781 FreePool (BootOrder
);
788 Fill the device order buffer.
790 @param BbsTable The BBS table.
791 @param BbsType The BBS Type.
792 @param BbsCount The BBS Count.
793 @param Buf device order buffer.
795 @return The device order buffer.
800 IN BBS_TABLE
*BbsTable
,
808 for (Index
= 0; Index
< BbsCount
; Index
++) {
809 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
813 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
817 *Buf
= (UINT16
) (Index
& 0xFF);
825 Create the device order buffer.
827 @param BbsTable The BBS table.
828 @param BbsCount The BBS Count.
830 @retval EFI_SUCCES The buffer is created and the EFI variable named
831 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
833 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.
834 @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail
835 because of hardware error.
839 IN BBS_TABLE
*BbsTable
,
861 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
864 Status
= EFI_SUCCESS
;
867 // Count all boot devices
869 for (Index
= 0; Index
< BbsCount
; Index
++) {
870 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
874 switch (BbsTable
[Index
].DeviceType
) {
887 case BBS_EMBED_NETWORK
:
900 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
901 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
902 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
903 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
904 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
907 // Create buffer to hold all boot device order
909 DevOrder
= AllocateZeroPool (TotalSize
);
910 if (NULL
== DevOrder
) {
911 return EFI_OUT_OF_RESOURCES
;
916 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
917 Ptr
+= sizeof (BBS_TYPE
);
918 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
919 Ptr
+= sizeof (UINT16
);
921 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
924 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
925 Ptr
+= sizeof (BBS_TYPE
);
926 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
927 Ptr
+= sizeof (UINT16
);
929 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
932 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
933 Ptr
+= sizeof (BBS_TYPE
);
934 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
935 Ptr
+= sizeof (UINT16
);
937 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
940 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
941 Ptr
+= sizeof (BBS_TYPE
);
942 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
943 Ptr
+= sizeof (UINT16
);
945 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
948 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
949 Ptr
+= sizeof (BBS_TYPE
);
950 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
951 Ptr
+= sizeof (UINT16
);
953 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
957 // Save device order for legacy boot device to variable.
959 Status
= gRT
->SetVariable (
960 VAR_LEGACY_DEV_ORDER
,
961 &EfiLegacyDevOrderGuid
,
972 Add the legacy boot devices from BBS table into
973 the legacy device boot order.
975 @retval EFI_SUCCESS The boot devices are added successfully.
976 @retval EFI_NOT_FOUND The legacy boot devices are not found.
977 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.
978 @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable
979 because of hardware error.
983 BdsUpdateLegacyDevOrder (
990 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
994 HDD_INFO
*LocalHddInfo
;
995 BBS_TABLE
*LocalBbsTable
;
1022 LocalHddInfo
= NULL
;
1023 LocalBbsTable
= NULL
;
1031 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1039 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1040 if (EFI_ERROR (Status
)) {
1044 LegacyBios
->GetBbsInfo (
1052 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1053 VAR_LEGACY_DEV_ORDER
,
1054 &EfiLegacyDevOrderGuid
,
1057 if (NULL
== DevOrder
) {
1058 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1061 // First we figure out how many boot devices with same device type respectively
1063 for (Index
= 0; Index
< BbsCount
; Index
++) {
1064 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1065 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1070 switch (LocalBbsTable
[Index
].DeviceType
) {
1083 case BBS_EMBED_NETWORK
:
1087 case BBS_BEV_DEVICE
:
1096 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1097 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1098 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1099 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1100 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1102 NewDevOrder
= AllocateZeroPool (TotalSize
);
1103 if (NULL
== NewDevOrder
) {
1104 return EFI_OUT_OF_RESOURCES
;
1107 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1108 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1109 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1110 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1111 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1117 NewPtr
= NewDevOrder
;
1118 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1119 Ptr
+= sizeof (BBS_TYPE
);
1120 NewPtr
+= sizeof (BBS_TYPE
);
1121 Length
= *((UINT16
*) Ptr
);
1122 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1123 Ptr
+= sizeof (UINT16
);
1125 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1126 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1127 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1128 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1130 Ptr
+= sizeof (UINT16
);
1134 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1136 Ptr
+= sizeof (UINT16
);
1141 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1142 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1143 Ptr
+= sizeof (BBS_TYPE
);
1144 NewPtr
+= sizeof (BBS_TYPE
);
1145 Length
= *((UINT16
*) Ptr
);
1146 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1147 Ptr
+= sizeof (UINT16
);
1149 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1150 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1151 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1152 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1153 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1155 Ptr
+= sizeof (UINT16
);
1159 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1161 Ptr
+= sizeof (UINT16
);
1166 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1167 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1168 Ptr
+= sizeof (BBS_TYPE
);
1169 NewPtr
+= sizeof (BBS_TYPE
);
1170 Length
= *((UINT16
*) Ptr
);
1171 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1172 Ptr
+= sizeof (UINT16
);
1174 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1175 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1176 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1177 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1178 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1180 Ptr
+= sizeof (UINT16
);
1184 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1186 Ptr
+= sizeof (UINT16
);
1191 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1192 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1193 Ptr
+= sizeof (BBS_TYPE
);
1194 NewPtr
+= sizeof (BBS_TYPE
);
1195 Length
= *((UINT16
*) Ptr
);
1196 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1197 Ptr
+= sizeof (UINT16
);
1199 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1200 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1201 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1202 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1203 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1205 Ptr
+= sizeof (UINT16
);
1209 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1211 Ptr
+= sizeof (UINT16
);
1216 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1217 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1218 Ptr
+= sizeof (BBS_TYPE
);
1219 NewPtr
+= sizeof (BBS_TYPE
);
1220 Length
= *((UINT16
*) Ptr
);
1221 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1222 Ptr
+= sizeof (UINT16
);
1224 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1225 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1226 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1227 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1228 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1230 Ptr
+= sizeof (UINT16
);
1234 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1236 Ptr
+= sizeof (UINT16
);
1239 for (Index
= 0; Index
< BbsCount
; Index
++) {
1240 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1241 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1246 switch (LocalBbsTable
[Index
].DeviceType
) {
1249 NewDevPtr
= NewFDPtr
;
1254 NewDevPtr
= NewHDPtr
;
1259 NewDevPtr
= NewCDPtr
;
1262 case BBS_EMBED_NETWORK
:
1264 NewDevPtr
= NewNETPtr
;
1267 case BBS_BEV_DEVICE
:
1269 NewDevPtr
= NewBEVPtr
;
1277 // at this point we have copied those valid indexes to new buffer
1278 // and we should check if there is any new appeared boot device
1281 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1282 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1287 if (Index2
== *Idx
) {
1289 // Index2 == *Idx means we didn't find Index
1290 // so Index is a new appeared device's index in BBS table
1293 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1301 // Just to make sure that disabled indexes are all at the end of the array
1303 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1304 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1308 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1309 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1310 Tmp
= NewFDPtr
[Index
];
1311 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1312 NewFDPtr
[Index2
] = Tmp
;
1321 // Just to make sure that disabled indexes are all at the end of the array
1323 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1324 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1328 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1329 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1330 Tmp
= NewHDPtr
[Index
];
1331 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1332 NewHDPtr
[Index2
] = Tmp
;
1341 // Just to make sure that disabled indexes are all at the end of the array
1343 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1344 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1348 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1349 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1350 Tmp
= NewCDPtr
[Index
];
1351 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1352 NewCDPtr
[Index2
] = Tmp
;
1359 if (NETCount
!= 0) {
1361 // Just to make sure that disabled indexes are all at the end of the array
1363 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1364 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1368 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1369 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1370 Tmp
= NewNETPtr
[Index
];
1371 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1372 NewNETPtr
[Index2
] = Tmp
;
1381 // Just to make sure that disabled indexes are all at the end of the array
1383 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1384 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1388 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1389 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1390 Tmp
= NewBEVPtr
[Index
];
1391 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1392 NewBEVPtr
[Index2
] = Tmp
;
1399 FreePool (DevOrder
);
1401 Status
= gRT
->SetVariable (
1402 VAR_LEGACY_DEV_ORDER
,
1403 &EfiLegacyDevOrderGuid
,
1408 FreePool (NewDevOrder
);
1414 Set Boot Priority for specified device type.
1416 @param DeviceType The device type.
1417 @param LocalBbsTable The BBS table.
1418 @param Priority The prority table.
1420 @retval EFI_SUCCESS The function completes successfully.
1421 @retval EFI_NOT_FOUND Failed to find device.
1422 @retval EFI_OUT_OF_RESOURCES Failed to get the efi variable of device order.
1426 BdsSetBootPriority4SameTypeDev (
1427 IN UINT16 DeviceType
,
1428 IN OUT BBS_TABLE
*LocalBbsTable
,
1429 IN OUT UINT16
*Priority
1440 DevOrder
= BdsLibGetVariableAndSize (
1441 VAR_LEGACY_DEV_ORDER
,
1442 &EfiLegacyDevOrderGuid
,
1445 if (NULL
== DevOrder
) {
1446 return EFI_OUT_OF_RESOURCES
;
1449 OrigBuffer
= DevOrder
;
1450 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1451 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1455 DevOrder
+= sizeof (BBS_TYPE
);
1456 DevOrder
+= *(UINT16
*) DevOrder
;
1459 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1460 FreePool (OrigBuffer
);
1461 return EFI_NOT_FOUND
;
1464 DevOrder
+= sizeof (BBS_TYPE
);
1465 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1466 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1468 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1470 for (Index
= 0; Index
< DevCount
; Index
++) {
1471 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1473 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1476 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1481 FreePool (OrigBuffer
);
1486 Print the BBS Table.
1488 @param LocalBbsTable The BBS table.
1489 @param BbsCount The count of entry in BBS table.
1493 IN BBS_TABLE
*LocalBbsTable
,
1499 DEBUG ((DEBUG_ERROR
, "\n"));
1500 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1501 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1502 for (Idx
= 0; Idx
< BbsCount
; Idx
++) {
1503 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1504 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1505 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1512 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1514 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1515 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1516 (UINTN
) LocalBbsTable
[Idx
].Device
,
1517 (UINTN
) LocalBbsTable
[Idx
].Function
,
1518 (UINTN
) LocalBbsTable
[Idx
].Class
,
1519 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1520 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1521 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1522 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1523 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1524 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1525 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1529 DEBUG ((DEBUG_ERROR
, "\n"));
1533 Set the boot priority for BBS entries based on boot option entry and boot order.
1535 @param Entry The boot option is to be checked for refresh BBS table.
1537 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1538 @retval EFI_NOT_FOUND BBS entries can't be found.
1539 @retval EFI_OUT_OF_RESOURCES Failed to get the legacy device boot order.
1543 BdsRefreshBbsTableForBoot (
1544 IN BDS_COMMON_OPTION
*Entry
1550 HDD_INFO
*LocalHddInfo
;
1551 BBS_TABLE
*LocalBbsTable
;
1553 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1557 UINTN BootOrderSize
;
1558 UINT8
*BootOptionVar
;
1559 UINTN BootOptionSize
;
1560 UINT16 BootOption
[100];
1563 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1567 LocalHddInfo
= NULL
;
1568 LocalBbsTable
= NULL
;
1569 DevType
= BBS_UNKNOWN
;
1571 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1572 if (EFI_ERROR (Status
)) {
1576 LegacyBios
->GetBbsInfo (
1584 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1585 // We will set them according to the settings setup by user
1587 for (Index
= 0; Index
< BbsCount
; Index
++) {
1588 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1589 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1590 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1591 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1595 // boot priority always starts at 0
1598 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1600 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1602 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1603 Status
= BdsSetBootPriority4SameTypeDev (
1608 if (EFI_ERROR (Status
)) {
1613 // we have to set the boot priority for other BBS entries with different device types
1615 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1617 &gEfiGlobalVariableGuid
,
1620 for (Index
= 0; ((BootOrder
!= NULL
) && (Index
< BootOrderSize
/ sizeof (UINT16
))); Index
++) {
1621 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1622 BootOptionVar
= BdsLibGetVariableAndSize (
1624 &gEfiGlobalVariableGuid
,
1627 if (NULL
== BootOptionVar
) {
1631 Ptr
= BootOptionVar
;
1633 Ptr
+= sizeof (UINT32
);
1634 DevPathLen
= *(UINT16
*) Ptr
;
1635 Ptr
+= sizeof (UINT16
);
1636 Ptr
+= StrSize ((UINT16
*) Ptr
);
1637 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1638 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1639 FreePool (BootOptionVar
);
1644 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1646 // We don't want to process twice for a device type
1648 FreePool (BootOptionVar
);
1652 Status
= BdsSetBootPriority4SameTypeDev (
1653 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1657 FreePool (BootOptionVar
);
1658 if (EFI_ERROR (Status
)) {
1663 if (BootOrder
!= NULL
) {
1664 FreePool (BootOrder
);
1668 PrintBbsTable (LocalBbsTable
, BbsCount
);