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
,
327 SafeFreePool (Buffer
);
330 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
331 if (NULL
== NewBootOrderList
) {
332 FreePool (NewBbsDevPathNode
);
333 FreePool (CurrentBbsDevPath
);
334 return EFI_OUT_OF_RESOURCES
;
337 if (NULL
!= *BootOrderList
) {
338 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
341 SafeFreePool (*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 SafeFreePool (BootOrder
);
466 return EFI_OUT_OF_RESOURCES
;
470 // Skip Non-Legacy boot options
472 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
473 SafeFreePool (BootOptionVar
);
479 // Check if BBS Description String is changed
481 DescStringMatch
= FALSE
;
483 BdsBuildLegacyDevNameString (
484 &LocalBbsTable
[BbsIndex
],
490 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
491 DescStringMatch
= TRUE
;
494 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
495 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
496 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
502 SafeFreePool (BootOptionVar
);
506 BdsDeleteBootOption (
514 // Adjust the number of boot options.
516 if (BootOrderSize
!= 0) {
517 Status
= gRT
->SetVariable (
519 &gEfiGlobalVariableGuid
,
525 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
528 SafeFreePool (BootOrder
);
534 Find all legacy boot option by device type.
536 @param BootOrder The boot order array.
537 @param BootOptionNum The number of boot option.
538 @param DevType Device type.
539 @param Attribute The boot option attribute.
540 @param BbsIndex The BBS table index.
541 @param OptionNumber The boot option index.
543 @retval TRUE The Legacy boot option is found.
544 @retval FALSE The legacy boot option is not found.
548 BdsFindLegacyBootOptionByDevType (
549 IN UINT16
*BootOrder
,
550 IN UINTN BootOptionNum
,
552 OUT UINT32
*Attribute
,
553 OUT UINT16
*BbsIndex
,
554 OUT UINTN
*OptionNumber
558 UINTN BootOrderIndex
;
559 UINT16 BootOption
[100];
560 UINTN BootOptionSize
;
561 UINT8
*BootOptionVar
;
568 if (NULL
== BootOrder
) {
573 // Loop all boot option from variable
575 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
576 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
577 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
578 BootOptionVar
= BdsLibGetVariableAndSize (
580 &gEfiGlobalVariableGuid
,
583 if (NULL
== BootOptionVar
) {
588 // Skip Non-legacy boot option
590 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
591 SafeFreePool (BootOptionVar
);
595 if (BbsEntry
->DeviceType
!= DevType
) {
596 SafeFreePool (BootOptionVar
);
600 *Attribute
= *(UINT32
*) BootOptionVar
;
601 *OptionNumber
= Index
;
603 SafeFreePool (BootOptionVar
);
611 Create a legacy boot option.
613 @param BbsItem The BBS Table entry.
614 @param Index Index of the specified entry in BBS table.
615 @param BootOrderList The boot order list.
616 @param BootOrderListSize The size of boot order list.
618 @retval EFI_OUT_OF_RESOURCE No enough memory.
619 @retval EFI_SUCCESS The function complete successfully.
620 @return Other value if the legacy boot option is not created.
624 BdsCreateOneLegacyBootOption (
625 IN BBS_TABLE
*BbsItem
,
627 IN OUT UINT16
**BootOrderList
,
628 IN OUT UINTN
*BootOrderListSize
631 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
633 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
638 // Create device path node.
640 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
641 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
642 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
643 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
644 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
646 DevPath
= AppendDevicePathNode (
648 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
650 if (NULL
== DevPath
) {
651 return EFI_OUT_OF_RESOURCES
;
654 Status
= BdsCreateLegacyBootOption (
661 BbsItem
->BootPriority
= 0x00;
670 Add the legacy boot options from BBS table if they do not exist.
672 @retval EFI_SUCCESS The boot options are added successfully
673 or they are already in boot options.
677 BdsAddNonExistingLegacyBootOptions (
686 HDD_INFO
*LocalHddInfo
;
687 BBS_TABLE
*LocalBbsTable
;
689 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
699 LocalBbsTable
= NULL
;
701 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
702 if (EFI_ERROR (Status
)) {
706 LegacyBios
->GetBbsInfo (
714 BootOrder
= BdsLibGetVariableAndSize (
716 &gEfiGlobalVariableGuid
,
719 if (NULL
== BootOrder
) {
723 for (Index
= 0; Index
< BbsCount
; Index
++) {
724 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
725 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
730 Ret
= BdsFindLegacyBootOptionByDevType (
732 BootOrderSize
/ sizeof (UINT16
),
733 LocalBbsTable
[Index
].DeviceType
,
743 // Not found such type of legacy device in boot options or we found but it's disabled
744 // so we have to create one and put it to the tail of boot order list
746 Status
= BdsCreateOneLegacyBootOption (
747 &LocalBbsTable
[Index
],
752 if (EFI_ERROR (Status
)) {
757 if (BootOrderSize
> 0) {
758 Status
= gRT
->SetVariable (
760 &gEfiGlobalVariableGuid
,
766 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
769 if (BootOrder
!= NULL
) {
770 SafeFreePool (BootOrder
);
777 Fill the device order buffer.
779 @param BbsTable The BBS table.
780 @param BbsType The BBS Type.
781 @param BbsCount The BBS Count.
782 @param Buf device order buffer.
784 @return The device order buffer.
789 IN BBS_TABLE
*BbsTable
,
797 for (Index
= 0; Index
< BbsCount
; Index
++) {
798 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
802 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
806 *Buf
= (UINT16
) (Index
& 0xFF);
814 Create the device order buffer.
816 @param BbsTable The BBS table.
817 @param BbsCount The BBS Count.
819 @retval EFI_SUCCES The buffer is created and the EFI variable named
820 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
822 @return Other value if the set of EFI variable fails. Check gRT->SetVariable
823 for detailed information.
828 IN BBS_TABLE
*BbsTable
,
850 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
853 Status
= EFI_SUCCESS
;
856 // Count all boot devices
858 for (Index
= 0; Index
< BbsCount
; Index
++) {
859 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
863 switch (BbsTable
[Index
].DeviceType
) {
876 case BBS_EMBED_NETWORK
:
889 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
890 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
891 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
892 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
893 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
896 // Create buffer to hold all boot device order
898 DevOrder
= AllocateZeroPool (TotalSize
);
899 if (NULL
== DevOrder
) {
900 return EFI_OUT_OF_RESOURCES
;
905 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
906 Ptr
+= sizeof (BBS_TYPE
);
907 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
908 Ptr
+= sizeof (UINT16
);
910 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
913 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
914 Ptr
+= sizeof (BBS_TYPE
);
915 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
916 Ptr
+= sizeof (UINT16
);
918 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
921 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
922 Ptr
+= sizeof (BBS_TYPE
);
923 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
924 Ptr
+= sizeof (UINT16
);
926 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
929 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
930 Ptr
+= sizeof (BBS_TYPE
);
931 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
932 Ptr
+= sizeof (UINT16
);
934 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
937 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
938 Ptr
+= sizeof (BBS_TYPE
);
939 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
940 Ptr
+= sizeof (UINT16
);
942 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
946 // Save device order for legacy boot device to variable.
948 Status
= gRT
->SetVariable (
949 VAR_LEGACY_DEV_ORDER
,
950 &EfiLegacyDevOrderGuid
,
955 SafeFreePool (DevOrder
);
962 Add the legacy boot devices from BBS table into
963 the legacy device boot order.
965 @retval EFI_SUCCESS The boot devices are added successfully.
969 BdsUpdateLegacyDevOrder (
976 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
980 HDD_INFO
*LocalHddInfo
;
981 BBS_TABLE
*LocalBbsTable
;
1008 LocalHddInfo
= NULL
;
1009 LocalBbsTable
= NULL
;
1017 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1025 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1026 if (EFI_ERROR (Status
)) {
1030 LegacyBios
->GetBbsInfo (
1038 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1039 VAR_LEGACY_DEV_ORDER
,
1040 &EfiLegacyDevOrderGuid
,
1043 if (NULL
== DevOrder
) {
1044 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1047 // First we figure out how many boot devices with same device type respectively
1049 for (Index
= 0; Index
< BbsCount
; Index
++) {
1050 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1051 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1056 switch (LocalBbsTable
[Index
].DeviceType
) {
1069 case BBS_EMBED_NETWORK
:
1073 case BBS_BEV_DEVICE
:
1082 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1083 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1084 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1085 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1086 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1088 NewDevOrder
= AllocateZeroPool (TotalSize
);
1089 if (NULL
== NewDevOrder
) {
1090 return EFI_OUT_OF_RESOURCES
;
1093 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1094 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1095 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1096 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1097 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1103 NewPtr
= NewDevOrder
;
1104 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1105 Ptr
+= sizeof (BBS_TYPE
);
1106 NewPtr
+= sizeof (BBS_TYPE
);
1107 Length
= *((UINT16
*) Ptr
);
1108 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1109 Ptr
+= sizeof (UINT16
);
1111 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1112 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1113 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1114 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1116 Ptr
+= sizeof (UINT16
);
1120 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1122 Ptr
+= sizeof (UINT16
);
1127 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1128 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1129 Ptr
+= sizeof (BBS_TYPE
);
1130 NewPtr
+= sizeof (BBS_TYPE
);
1131 Length
= *((UINT16
*) Ptr
);
1132 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1133 Ptr
+= sizeof (UINT16
);
1135 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1136 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1137 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1138 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1139 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1141 Ptr
+= sizeof (UINT16
);
1145 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1147 Ptr
+= sizeof (UINT16
);
1152 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1153 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1154 Ptr
+= sizeof (BBS_TYPE
);
1155 NewPtr
+= sizeof (BBS_TYPE
);
1156 Length
= *((UINT16
*) Ptr
);
1157 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1158 Ptr
+= sizeof (UINT16
);
1160 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1161 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1162 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1163 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1164 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1166 Ptr
+= sizeof (UINT16
);
1170 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1172 Ptr
+= sizeof (UINT16
);
1177 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1178 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1179 Ptr
+= sizeof (BBS_TYPE
);
1180 NewPtr
+= sizeof (BBS_TYPE
);
1181 Length
= *((UINT16
*) Ptr
);
1182 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1183 Ptr
+= sizeof (UINT16
);
1185 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1186 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1187 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1188 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1189 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1191 Ptr
+= sizeof (UINT16
);
1195 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1197 Ptr
+= sizeof (UINT16
);
1202 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1203 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1204 Ptr
+= sizeof (BBS_TYPE
);
1205 NewPtr
+= sizeof (BBS_TYPE
);
1206 Length
= *((UINT16
*) Ptr
);
1207 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1208 Ptr
+= sizeof (UINT16
);
1210 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1211 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1212 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1213 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1214 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1216 Ptr
+= sizeof (UINT16
);
1220 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1222 Ptr
+= sizeof (UINT16
);
1225 for (Index
= 0; Index
< BbsCount
; Index
++) {
1226 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1227 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1232 switch (LocalBbsTable
[Index
].DeviceType
) {
1235 NewDevPtr
= NewFDPtr
;
1240 NewDevPtr
= NewHDPtr
;
1245 NewDevPtr
= NewCDPtr
;
1248 case BBS_EMBED_NETWORK
:
1250 NewDevPtr
= NewNETPtr
;
1253 case BBS_BEV_DEVICE
:
1255 NewDevPtr
= NewBEVPtr
;
1263 // at this point we have copied those valid indexes to new buffer
1264 // and we should check if there is any new appeared boot device
1267 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1268 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1273 if (Index2
== *Idx
) {
1275 // Index2 == *Idx means we didn't find Index
1276 // so Index is a new appeared device's index in BBS table
1279 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1287 // Just to make sure that disabled indexes are all at the end of the array
1289 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1290 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1294 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1295 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1296 Tmp
= NewFDPtr
[Index
];
1297 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1298 NewFDPtr
[Index2
] = Tmp
;
1307 // Just to make sure that disabled indexes are all at the end of the array
1309 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1310 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1314 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1315 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1316 Tmp
= NewHDPtr
[Index
];
1317 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1318 NewHDPtr
[Index2
] = Tmp
;
1327 // Just to make sure that disabled indexes are all at the end of the array
1329 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1330 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1334 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1335 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1336 Tmp
= NewCDPtr
[Index
];
1337 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1338 NewCDPtr
[Index2
] = Tmp
;
1345 if (NETCount
!= 0) {
1347 // Just to make sure that disabled indexes are all at the end of the array
1349 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1350 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1354 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1355 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1356 Tmp
= NewNETPtr
[Index
];
1357 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1358 NewNETPtr
[Index2
] = Tmp
;
1367 // Just to make sure that disabled indexes are all at the end of the array
1369 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1370 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1374 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1375 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1376 Tmp
= NewBEVPtr
[Index
];
1377 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1378 NewBEVPtr
[Index2
] = Tmp
;
1385 SafeFreePool (DevOrder
);
1387 Status
= gRT
->SetVariable (
1388 VAR_LEGACY_DEV_ORDER
,
1389 &EfiLegacyDevOrderGuid
,
1394 SafeFreePool (NewDevOrder
);
1400 Set Boot Priority for specified device type.
1402 @param DeviceType The device type.
1403 @param LocalBbsTable The BBS table.
1404 @param Priority The prority table.
1406 @retval EFI_SUCCESS The function completes successfully.
1407 @retval EFI_NOT_FOUND Failed to find device.
1411 BdsSetBootPriority4SameTypeDev (
1412 IN UINT16 DeviceType
,
1413 IN OUT BBS_TABLE
*LocalBbsTable
,
1414 IN OUT UINT16
*Priority
1425 DevOrder
= BdsLibGetVariableAndSize (
1426 VAR_LEGACY_DEV_ORDER
,
1427 &EfiLegacyDevOrderGuid
,
1430 if (NULL
== DevOrder
) {
1431 return EFI_OUT_OF_RESOURCES
;
1434 OrigBuffer
= DevOrder
;
1435 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1436 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1440 DevOrder
+= sizeof (BBS_TYPE
);
1441 DevOrder
+= *(UINT16
*) DevOrder
;
1444 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1445 SafeFreePool (OrigBuffer
);
1446 return EFI_NOT_FOUND
;
1449 DevOrder
+= sizeof (BBS_TYPE
);
1450 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1451 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1453 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1455 for (Index
= 0; Index
< DevCount
; Index
++) {
1456 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1458 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1461 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1466 SafeFreePool (OrigBuffer
);
1471 Print the BBS Table.
1473 @param LocalBbsTable The BBS table.
1478 IN BBS_TABLE
*LocalBbsTable
1483 DEBUG ((DEBUG_ERROR
, "\n"));
1484 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1485 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1486 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1487 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1488 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1489 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1496 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1498 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1499 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1500 (UINTN
) LocalBbsTable
[Idx
].Device
,
1501 (UINTN
) LocalBbsTable
[Idx
].Function
,
1502 (UINTN
) LocalBbsTable
[Idx
].Class
,
1503 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1504 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1505 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1506 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1507 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1508 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1509 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1513 DEBUG ((DEBUG_ERROR
, "\n"));
1518 Set the boot priority for BBS entries based on boot option entry and boot order.
1520 @param Entry The boot option is to be checked for refresh BBS table.
1522 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1523 @return status of BdsSetBootPriority4SameTypeDev()
1526 BdsRefreshBbsTableForBoot (
1527 IN BDS_COMMON_OPTION
*Entry
1533 HDD_INFO
*LocalHddInfo
;
1534 BBS_TABLE
*LocalBbsTable
;
1536 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1540 UINTN BootOrderSize
;
1541 UINT8
*BootOptionVar
;
1542 UINTN BootOptionSize
;
1543 UINT16 BootOption
[100];
1546 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1550 LocalHddInfo
= NULL
;
1551 LocalBbsTable
= NULL
;
1552 DevType
= BBS_UNKNOWN
;
1554 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1555 if (EFI_ERROR (Status
)) {
1559 LegacyBios
->GetBbsInfo (
1567 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1568 // We will set them according to the settings setup by user
1570 for (Index
= 0; Index
< BbsCount
; Index
++) {
1571 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1572 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1573 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1574 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1578 // boot priority always starts at 0
1581 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1583 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1585 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1586 Status
= BdsSetBootPriority4SameTypeDev (
1591 if (EFI_ERROR (Status
)) {
1596 // we have to set the boot priority for other BBS entries with different device types
1598 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1600 &gEfiGlobalVariableGuid
,
1603 for (Index
= 0; ((BootOrder
!= NULL
) && (Index
< BootOrderSize
/ sizeof (UINT16
))); Index
++) {
1604 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1605 BootOptionVar
= BdsLibGetVariableAndSize (
1607 &gEfiGlobalVariableGuid
,
1610 if (NULL
== BootOptionVar
) {
1614 Ptr
= BootOptionVar
;
1616 Ptr
+= sizeof (UINT32
);
1617 DevPathLen
= *(UINT16
*) Ptr
;
1618 Ptr
+= sizeof (UINT16
);
1619 Ptr
+= StrSize ((UINT16
*) Ptr
);
1620 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1621 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1622 SafeFreePool (BootOptionVar
);
1627 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1629 // We don't want to process twice for a device type
1631 SafeFreePool (BootOptionVar
);
1635 Status
= BdsSetBootPriority4SameTypeDev (
1636 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1640 SafeFreePool (BootOptionVar
);
1641 if (EFI_ERROR (Status
)) {
1646 if (BootOrder
!= NULL
) {
1647 SafeFreePool (BootOrder
);
1652 PrintBbsTable (LocalBbsTable
);