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.
44 while (AStr
[Idx
] != 0) {
45 UStr
[Idx
] = (CHAR16
) AStr
[Idx
];
57 change a Unicode string t ASCII string
60 @param UStr Unicode string
61 Lenght - most possible length of AStr
62 @param Length The length of UStr.
63 @param AStr ASCII string to pass out
78 // just buffer copy, not character copy
80 for (Index
= 0; Index
< Length
; Index
++) {
81 *AStr
++ = (CHAR8
) *UStr
++;
88 Build Legacy Device Name String according.
90 @param CurBBSEntry BBS Table.
92 @param BufSize The buffer size.
93 @param BootString The output string.
95 @return VOID No output.
99 BdsBuildLegacyDevNameString (
100 IN BBS_TABLE
*CurBBSEntry
,
103 OUT CHAR16
*BootString
116 Fmt
= L
"Primary Master %s";
123 Fmt
= L
"Primary Slave %s";
130 Fmt
= L
"Secondary Master %s";
137 Fmt
= L
"Secondary Slave %s";
145 switch (CurBBSEntry
->DeviceType
) {
166 case BBS_EMBED_NETWORK
:
180 // If current BBS entry has its description then use it.
182 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
183 if (NULL
!= StringDesc
) {
185 // Only get fisrt 32 characters, this is suggested by BBS spec
187 AsciiToUnicodeSize (StringDesc
, 32, Temp
);
193 // BbsTable 16 entries are for onboard IDE.
194 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
196 if (Index
>= 5 && Index
<= 16 && CurBBSEntry
->DeviceType
== BBS_HARDDISK
) {
198 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
200 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
206 Create a legacy boot option for the specified entry of
207 BBS table, save it as variable, and append it to the boot
211 @param CurrentBbsEntry Pointer to current BBS table.
212 @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS
213 @param Index Index of the specified entry in BBS table.
214 @param BootOrderList On input, the original boot order list.
215 On output, the new boot order list attached with the
217 @param BootOrderListSize On input, the original size of boot order list.
218 - On output, the size of new boot order list.
220 @retval EFI_SUCCESS Boot Option successfully created.
221 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
222 @retval Other Error occurs while setting variable.
226 BdsCreateLegacyBootOption (
227 IN BBS_TABLE
*CurrentBbsEntry
,
228 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
230 IN OUT UINT16
**BootOrderList
,
231 IN OUT UINTN
*BootOrderListSize
235 UINT16 CurrentBootOptionNo
;
236 UINT16 BootString
[10];
237 UINT16 BootDesc
[100];
238 CHAR8 HelpString
[100];
239 UINT16
*NewBootOrderList
;
244 UINT16 CurrentBbsDevPathSize
;
245 UINTN BootOrderIndex
;
246 UINTN BootOrderLastIndex
;
248 BOOLEAN IndexNotFound
;
249 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
251 if (NULL
== (*BootOrderList
)) {
252 CurrentBootOptionNo
= 0;
254 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
255 IndexNotFound
= TRUE
;
256 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
257 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
258 IndexNotFound
= FALSE
;
263 if (!IndexNotFound
) {
270 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
280 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
283 // Create new BBS device path node with description string
285 UnicodeToAscii (BootDesc
, StrSize (BootDesc
), HelpString
);
286 StringLen
= AsciiStrLen (HelpString
);
287 NewBbsDevPathNode
= AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
288 if (NewBbsDevPathNode
== NULL
) {
289 return EFI_OUT_OF_RESOURCES
;
291 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
292 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
293 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
296 // Create entire new CurrentBbsDevPath with end node
298 CurrentBbsDevPath
= AppendDevicePathNode (
300 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
302 if (CurrentBbsDevPath
== NULL
) {
303 FreePool (NewBbsDevPathNode
);
304 return EFI_OUT_OF_RESOURCES
;
307 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
309 BufferSize
= sizeof (UINT32
) +
312 CurrentBbsDevPathSize
+
316 Buffer
= AllocateZeroPool (BufferSize
);
317 if (Buffer
== NULL
) {
318 FreePool (NewBbsDevPathNode
);
319 FreePool (CurrentBbsDevPath
);
320 return EFI_OUT_OF_RESOURCES
;
323 Ptr
= (UINT8
*) Buffer
;
325 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
326 Ptr
+= sizeof (UINT32
);
328 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
329 Ptr
+= sizeof (UINT16
);
336 Ptr
+= StrSize (BootDesc
);
341 CurrentBbsDevPathSize
343 Ptr
+= CurrentBbsDevPathSize
;
351 Ptr
+= sizeof (BBS_TABLE
);
352 *((UINT16
*) Ptr
) = (UINT16
) Index
;
354 Status
= gRT
->SetVariable (
356 &gEfiGlobalVariableGuid
,
362 SafeFreePool (Buffer
);
365 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
366 if (NULL
== NewBootOrderList
) {
367 FreePool (NewBbsDevPathNode
);
368 FreePool (CurrentBbsDevPath
);
369 return EFI_OUT_OF_RESOURCES
;
372 if (NULL
!= *BootOrderList
) {
373 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
376 SafeFreePool (*BootOrderList
);
378 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
379 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
380 *BootOrderListSize
+= sizeof (UINT16
);
381 *BootOrderList
= NewBootOrderList
;
383 FreePool (NewBbsDevPathNode
);
384 FreePool (CurrentBbsDevPath
);
389 Check if the boot option is a legacy one.
391 @param BootOptionVar The boot option data payload.
392 @param BbsEntry The BBS Table.
393 @param BbsIndex The table index.
395 @retval TRUE It is a legacy boot option.
396 @retval FALSE It is not a legacy boot option.
400 BdsIsLegacyBootOption (
401 IN UINT8
*BootOptionVar
,
402 OUT BBS_TABLE
**BbsEntry
,
407 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
412 Ptr
+= sizeof (UINT32
);
413 DevPathLen
= *(UINT16
*) Ptr
;
414 Ptr
+= sizeof (UINT16
);
415 Ptr
+= StrSize ((UINT16
*) Ptr
);
416 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
417 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
419 *BbsEntry
= (BBS_TABLE
*) Ptr
;
420 Ptr
+= sizeof (BBS_TABLE
);
421 *BbsIndex
= *(UINT16
*) Ptr
;
432 Delete all the invalid legacy boot options.
436 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
437 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
438 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
441 BdsDeleteAllInvalidLegacyBootOptions (
446 UINT8
*BootOptionVar
;
448 UINTN BootOptionSize
;
452 HDD_INFO
*LocalHddInfo
;
453 BBS_TABLE
*LocalBbsTable
;
456 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
458 UINT16 BootOption
[10];
459 UINT16 BootDesc
[100];
460 BOOLEAN DescStringMatch
;
462 Status
= EFI_SUCCESS
;
468 LocalBbsTable
= NULL
;
471 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
472 if (EFI_ERROR (Status
)) {
476 LegacyBios
->GetBbsInfo (
484 BootOrder
= BdsLibGetVariableAndSize (
486 &gEfiGlobalVariableGuid
,
489 if (NULL
== BootOrder
) {
490 return EFI_NOT_FOUND
;
494 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
495 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
496 BootOptionVar
= BdsLibGetVariableAndSize (
498 &gEfiGlobalVariableGuid
,
501 if (NULL
== BootOptionVar
) {
502 SafeFreePool (BootOrder
);
503 return EFI_OUT_OF_RESOURCES
;
506 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
507 SafeFreePool (BootOptionVar
);
513 // Check if BBS Description String is changed
515 DescStringMatch
= FALSE
;
517 BdsBuildLegacyDevNameString (
518 &LocalBbsTable
[BbsIndex
],
524 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
525 DescStringMatch
= TRUE
;
528 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
529 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
530 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
536 SafeFreePool (BootOptionVar
);
540 BdsDeleteBootOption (
547 if (BootOrderSize
!= 0) {
548 Status
= gRT
->SetVariable (
550 &gEfiGlobalVariableGuid
,
556 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
559 SafeFreePool (BootOrder
);
565 Find all legacy boot option by device type.
567 @param BootOrder The boot order array.
568 @param BootOptionNum The number of boot option.
569 @param DevType Device type.
570 @param Attribute The boot option attribute.
571 @param BbsIndex The BBS table index.
572 @param OptionNumber The boot option index.
574 @retval TRUE The Legacy boot option is found.
575 @retval FALSE The legacy boot option is not found.
579 BdsFindLegacyBootOptionByDevType (
580 IN UINT16
*BootOrder
,
581 IN UINTN BootOptionNum
,
583 OUT UINT32
*Attribute
,
584 OUT UINT16
*BbsIndex
,
585 OUT UINTN
*OptionNumber
589 UINTN BootOrderIndex
;
590 UINT16 BootOption
[100];
591 UINTN BootOptionSize
;
592 UINT8
*BootOptionVar
;
599 if (NULL
== BootOrder
) {
603 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
604 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
605 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
606 BootOptionVar
= BdsLibGetVariableAndSize (
608 &gEfiGlobalVariableGuid
,
611 if (NULL
== BootOptionVar
) {
615 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
616 SafeFreePool (BootOptionVar
);
620 if (BbsEntry
->DeviceType
!= DevType
) {
621 SafeFreePool (BootOptionVar
);
625 *Attribute
= *(UINT32
*) BootOptionVar
;
626 *OptionNumber
= Index
;
628 SafeFreePool (BootOptionVar
);
636 Create a legacy boot option.
638 @param BbsItem The BBS Table entry.
639 @param Index Index of the specified entry in BBS table.
640 @param BootOrderList The boot order list.
641 @param BootOrderListSize The size of boot order list.
643 @retval EFI_OUT_OF_RESOURCE No enough memory.
644 @retval EFI_SUCCESS The function complete successfully.
645 @return Other value if the legacy boot option is not created.
649 BdsCreateOneLegacyBootOption (
650 IN BBS_TABLE
*BbsItem
,
652 IN OUT UINT16
**BootOrderList
,
653 IN OUT UINTN
*BootOrderListSize
656 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
658 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
662 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
663 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
664 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
665 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
666 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
668 DevPath
= AppendDevicePathNode (
670 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
672 if (NULL
== DevPath
) {
673 return EFI_OUT_OF_RESOURCES
;
676 Status
= BdsCreateLegacyBootOption (
683 BbsItem
->BootPriority
= 0x00;
692 Add the legacy boot options from BBS table if they do not exist.
696 @retval EFI_SUCCESS The boot options are added successfully
697 or they are already in boot options.
701 BdsAddNonExistingLegacyBootOptions (
710 HDD_INFO
*LocalHddInfo
;
711 BBS_TABLE
*LocalBbsTable
;
713 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
723 LocalBbsTable
= NULL
;
725 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
726 if (EFI_ERROR (Status
)) {
730 LegacyBios
->GetBbsInfo (
738 BootOrder
= BdsLibGetVariableAndSize (
740 &gEfiGlobalVariableGuid
,
743 if (NULL
== BootOrder
) {
747 for (Index
= 0; Index
< BbsCount
; Index
++) {
748 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
749 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
754 Ret
= BdsFindLegacyBootOptionByDevType (
756 BootOrderSize
/ sizeof (UINT16
),
757 LocalBbsTable
[Index
].DeviceType
,
767 // Not found such type of legacy device in boot options or we found but it's disabled
768 // so we have to create one and put it to the tail of boot order list
770 Status
= BdsCreateOneLegacyBootOption (
771 &LocalBbsTable
[Index
],
776 if (EFI_ERROR (Status
)) {
781 if (BootOrderSize
> 0) {
782 Status
= gRT
->SetVariable (
784 &gEfiGlobalVariableGuid
,
790 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
793 if (BootOrder
!= NULL
) {
794 SafeFreePool (BootOrder
);
801 Fill the device order buffer.
803 @param BbsTable The BBS table.
804 @param BbsType The BBS Type.
805 @param BbsCount The BBS Count.
806 @param Buf device order buffer.
808 @return The device order buffer.
813 IN BBS_TABLE
*BbsTable
,
821 for (Index
= 0; Index
< BbsCount
; Index
++) {
822 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
826 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
830 *Buf
= (UINT16
) (Index
& 0xFF);
838 Create the device order buffer.
840 @param BbsTable The BBS table.
841 @param BbsCount The BBS Count.
843 @retval EFI_SUCCES The buffer is created and the EFI variable named
844 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
846 @return Other value if the set of EFI variable fails. Check gRT->SetVariable
847 for detailed information.
852 IN BBS_TABLE
*BbsTable
,
874 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
877 Status
= EFI_SUCCESS
;
879 for (Index
= 0; Index
< BbsCount
; Index
++) {
880 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
884 switch (BbsTable
[Index
].DeviceType
) {
897 case BBS_EMBED_NETWORK
:
910 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
911 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
912 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
913 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
914 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
916 DevOrder
= AllocateZeroPool (TotalSize
);
917 if (NULL
== DevOrder
) {
918 return EFI_OUT_OF_RESOURCES
;
923 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
924 Ptr
+= sizeof (BBS_TYPE
);
925 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
926 Ptr
+= sizeof (UINT16
);
928 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
931 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
932 Ptr
+= sizeof (BBS_TYPE
);
933 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
934 Ptr
+= sizeof (UINT16
);
936 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
939 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
940 Ptr
+= sizeof (BBS_TYPE
);
941 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
942 Ptr
+= sizeof (UINT16
);
944 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
947 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
948 Ptr
+= sizeof (BBS_TYPE
);
949 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
950 Ptr
+= sizeof (UINT16
);
952 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
955 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
956 Ptr
+= sizeof (BBS_TYPE
);
957 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
958 Ptr
+= sizeof (UINT16
);
960 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
963 Status
= gRT
->SetVariable (
964 VAR_LEGACY_DEV_ORDER
,
965 &EfiLegacyDevOrderGuid
,
970 SafeFreePool (DevOrder
);
977 Add the legacy boot devices from BBS table into
978 the legacy device boot order.
980 @retval EFI_SUCCESS The boot devices are added successfully.
984 BdsUpdateLegacyDevOrder (
991 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
995 HDD_INFO
*LocalHddInfo
;
996 BBS_TABLE
*LocalBbsTable
;
1023 LocalHddInfo
= NULL
;
1024 LocalBbsTable
= NULL
;
1032 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1040 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1041 if (EFI_ERROR (Status
)) {
1045 LegacyBios
->GetBbsInfo (
1053 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1054 VAR_LEGACY_DEV_ORDER
,
1055 &EfiLegacyDevOrderGuid
,
1058 if (NULL
== DevOrder
) {
1059 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1062 // First we figure out how many boot devices with same device type respectively
1064 for (Index
= 0; Index
< BbsCount
; Index
++) {
1065 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1066 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1071 switch (LocalBbsTable
[Index
].DeviceType
) {
1084 case BBS_EMBED_NETWORK
:
1088 case BBS_BEV_DEVICE
:
1097 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1098 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1099 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1100 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1101 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1103 NewDevOrder
= AllocateZeroPool (TotalSize
);
1104 if (NULL
== NewDevOrder
) {
1105 return EFI_OUT_OF_RESOURCES
;
1108 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1109 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1110 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1111 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1112 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1118 NewPtr
= NewDevOrder
;
1119 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1120 Ptr
+= sizeof (BBS_TYPE
);
1121 NewPtr
+= sizeof (BBS_TYPE
);
1122 Length
= *((UINT16
*) Ptr
);
1123 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1124 Ptr
+= sizeof (UINT16
);
1126 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1127 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1128 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1129 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1131 Ptr
+= sizeof (UINT16
);
1135 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1137 Ptr
+= sizeof (UINT16
);
1142 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1143 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1144 Ptr
+= sizeof (BBS_TYPE
);
1145 NewPtr
+= sizeof (BBS_TYPE
);
1146 Length
= *((UINT16
*) Ptr
);
1147 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1148 Ptr
+= sizeof (UINT16
);
1150 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1151 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1152 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1153 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1154 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1156 Ptr
+= sizeof (UINT16
);
1160 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1162 Ptr
+= sizeof (UINT16
);
1167 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1168 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1169 Ptr
+= sizeof (BBS_TYPE
);
1170 NewPtr
+= sizeof (BBS_TYPE
);
1171 Length
= *((UINT16
*) Ptr
);
1172 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1173 Ptr
+= sizeof (UINT16
);
1175 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1176 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1177 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1178 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1179 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1181 Ptr
+= sizeof (UINT16
);
1185 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1187 Ptr
+= sizeof (UINT16
);
1192 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1193 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1194 Ptr
+= sizeof (BBS_TYPE
);
1195 NewPtr
+= sizeof (BBS_TYPE
);
1196 Length
= *((UINT16
*) Ptr
);
1197 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1198 Ptr
+= sizeof (UINT16
);
1200 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1201 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1202 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1203 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1204 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1206 Ptr
+= sizeof (UINT16
);
1210 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1212 Ptr
+= sizeof (UINT16
);
1217 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1218 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1219 Ptr
+= sizeof (BBS_TYPE
);
1220 NewPtr
+= sizeof (BBS_TYPE
);
1221 Length
= *((UINT16
*) Ptr
);
1222 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1223 Ptr
+= sizeof (UINT16
);
1225 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1226 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1227 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1228 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1229 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1231 Ptr
+= sizeof (UINT16
);
1235 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1237 Ptr
+= sizeof (UINT16
);
1240 for (Index
= 0; Index
< BbsCount
; Index
++) {
1241 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1242 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1247 switch (LocalBbsTable
[Index
].DeviceType
) {
1250 NewDevPtr
= NewFDPtr
;
1255 NewDevPtr
= NewHDPtr
;
1260 NewDevPtr
= NewCDPtr
;
1263 case BBS_EMBED_NETWORK
:
1265 NewDevPtr
= NewNETPtr
;
1268 case BBS_BEV_DEVICE
:
1270 NewDevPtr
= NewBEVPtr
;
1278 // at this point we have copied those valid indexes to new buffer
1279 // and we should check if there is any new appeared boot device
1282 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1283 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1288 if (Index2
== *Idx
) {
1290 // Index2 == *Idx means we didn't find Index
1291 // so Index is a new appeared device's index in BBS table
1294 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1302 // Just to make sure that disabled indexes are all at the end of the array
1304 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1305 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1309 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1310 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1311 Tmp
= NewFDPtr
[Index
];
1312 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1313 NewFDPtr
[Index2
] = Tmp
;
1322 // Just to make sure that disabled indexes are all at the end of the array
1324 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1325 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1329 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1330 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1331 Tmp
= NewHDPtr
[Index
];
1332 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1333 NewHDPtr
[Index2
] = Tmp
;
1342 // Just to make sure that disabled indexes are all at the end of the array
1344 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1345 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1349 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1350 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1351 Tmp
= NewCDPtr
[Index
];
1352 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1353 NewCDPtr
[Index2
] = Tmp
;
1360 if (NETCount
!= 0) {
1362 // Just to make sure that disabled indexes are all at the end of the array
1364 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1365 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1369 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1370 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1371 Tmp
= NewNETPtr
[Index
];
1372 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1373 NewNETPtr
[Index2
] = Tmp
;
1382 // Just to make sure that disabled indexes are all at the end of the array
1384 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1385 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1389 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1390 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1391 Tmp
= NewBEVPtr
[Index
];
1392 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1393 NewBEVPtr
[Index2
] = Tmp
;
1400 SafeFreePool (DevOrder
);
1402 Status
= gRT
->SetVariable (
1403 VAR_LEGACY_DEV_ORDER
,
1404 &EfiLegacyDevOrderGuid
,
1409 SafeFreePool (NewDevOrder
);
1415 Set Boot Priority for specified device type.
1417 @param DeviceType The device type.
1418 @param LocalBbsTable The BBS table.
1419 @param Priority The prority table.
1421 @retval EFI_SUCCESS The function completes successfully.
1422 @retval EFI_NOT_FOUND Failed to find device.
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 SafeFreePool (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 SafeFreePool (OrigBuffer
);
1486 Print the BBS Table.
1488 @param LocalBbsTable The BBS table.
1493 IN BBS_TABLE
*LocalBbsTable
1498 DEBUG ((DEBUG_ERROR
, "\n"));
1499 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1500 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1501 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1502 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1503 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1504 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1511 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1513 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1514 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1515 (UINTN
) LocalBbsTable
[Idx
].Device
,
1516 (UINTN
) LocalBbsTable
[Idx
].Function
,
1517 (UINTN
) LocalBbsTable
[Idx
].Class
,
1518 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1519 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1520 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1521 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1522 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1523 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1524 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1528 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.
1541 BdsRefreshBbsTableForBoot (
1542 IN BDS_COMMON_OPTION
*Entry
1548 HDD_INFO
*LocalHddInfo
;
1549 BBS_TABLE
*LocalBbsTable
;
1551 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1555 UINTN BootOrderSize
;
1556 UINT8
*BootOptionVar
;
1557 UINTN BootOptionSize
;
1558 UINT16 BootOption
[100];
1561 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1565 LocalHddInfo
= NULL
;
1566 LocalBbsTable
= NULL
;
1567 DevType
= BBS_UNKNOWN
;
1569 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1570 if (EFI_ERROR (Status
)) {
1574 LegacyBios
->GetBbsInfo (
1582 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1583 // We will set them according to the settings setup by user
1585 for (Index
= 0; Index
< BbsCount
; Index
++) {
1586 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1587 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1588 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1589 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1593 // boot priority always starts at 0
1596 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1598 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1600 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1601 Status
= BdsSetBootPriority4SameTypeDev (
1606 if (EFI_ERROR (Status
)) {
1611 // we have to set the boot priority for other BBS entries with different device types
1613 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1615 &gEfiGlobalVariableGuid
,
1618 for (Index
= 0; ((BootOrder
!= NULL
) && (Index
< BootOrderSize
/ sizeof (UINT16
))); Index
++) {
1619 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1620 BootOptionVar
= BdsLibGetVariableAndSize (
1622 &gEfiGlobalVariableGuid
,
1625 if (NULL
== BootOptionVar
) {
1629 Ptr
= BootOptionVar
;
1631 Ptr
+= sizeof (UINT32
);
1632 DevPathLen
= *(UINT16
*) Ptr
;
1633 Ptr
+= sizeof (UINT16
);
1634 Ptr
+= StrSize ((UINT16
*) Ptr
);
1635 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1636 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1637 SafeFreePool (BootOptionVar
);
1642 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1644 // We don't want to process twice for a device type
1646 SafeFreePool (BootOptionVar
);
1650 Status
= BdsSetBootPriority4SameTypeDev (
1651 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1655 SafeFreePool (BootOptionVar
);
1656 if (EFI_ERROR (Status
)) {
1661 if (BootOrder
!= NULL
) {
1662 SafeFreePool (BootOrder
);
1667 PrintBbsTable (LocalBbsTable
);