2 This function deal with the legacy boot option, it create, delete
3 and manage the legacy boot option, all legacy boot option is getting from
6 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "BBSsupport.h"
21 Translate the first n characters of an Ascii string to
22 Unicode characters. The count n is indicated by parameter
23 Size. If Size is greater than the length of string, then
24 the entire string is translated.
27 @param AStr Pointer to input Ascii string.
28 @param Size The number of characters to translate.
29 @param UStr Pointer to output Unicode string buffer.
42 while (AStr
[Idx
] != 0) {
43 UStr
[Idx
] = (CHAR16
) AStr
[Idx
];
54 Build Legacy Device Name String according.
56 @param CurBBSEntry BBS Table.
58 @param BufSize The buffer size.
59 @param BootString The output string.
63 BdsBuildLegacyDevNameString (
64 IN BBS_TABLE
*CurBBSEntry
,
67 OUT CHAR16
*BootString
80 Fmt
= L
"Primary Master %s";
87 Fmt
= L
"Primary Slave %s";
94 Fmt
= L
"Secondary Master %s";
101 Fmt
= L
"Secondary Slave %s";
109 switch (CurBBSEntry
->DeviceType
) {
130 case BBS_EMBED_NETWORK
:
144 // If current BBS entry has its description then use it.
146 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
147 if (NULL
!= StringDesc
) {
149 // Only get fisrt 32 characters, this is suggested by BBS spec
151 AsciiToUnicodeSize (StringDesc
, 32, Temp
);
157 // BbsTable 16 entries are for onboard IDE.
158 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
160 if (Index
>= 5 && Index
<= 16 && CurBBSEntry
->DeviceType
== BBS_HARDDISK
) {
162 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
164 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
170 Create a legacy boot option for the specified entry of
171 BBS table, save it as variable, and append it to the boot
175 @param CurrentBbsEntry Pointer to current BBS table.
176 @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS
177 @param Index Index of the specified entry in BBS table.
178 @param BootOrderList On input, the original boot order list.
179 On output, the new boot order list attached with the
181 @param BootOrderListSize On input, the original size of boot order list.
182 On output, the size of new boot order list.
184 @retval EFI_SUCCESS Boot Option successfully created.
185 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
186 @retval Other Error occurs while setting variable.
190 BdsCreateLegacyBootOption (
191 IN BBS_TABLE
*CurrentBbsEntry
,
192 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
194 IN OUT UINT16
**BootOrderList
,
195 IN OUT UINTN
*BootOrderListSize
199 UINT16 CurrentBootOptionNo
;
200 UINT16 BootString
[10];
201 UINT16 BootDesc
[100];
202 CHAR8 HelpString
[100];
203 UINT16
*NewBootOrderList
;
208 UINT16 CurrentBbsDevPathSize
;
209 UINTN BootOrderIndex
;
210 UINTN BootOrderLastIndex
;
212 BOOLEAN IndexNotFound
;
213 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
215 if ((*BootOrderList
) == NULL
) {
216 CurrentBootOptionNo
= 0;
218 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
219 IndexNotFound
= TRUE
;
220 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
221 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
222 IndexNotFound
= FALSE
;
227 if (!IndexNotFound
) {
234 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
244 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
247 // Create new BBS device path node with description string
249 UnicodeStrToAsciiStr ((CONST CHAR16
*)&BootDesc
, (CHAR8
*)&HelpString
);
251 StringLen
= AsciiStrLen (HelpString
);
252 NewBbsDevPathNode
= AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
253 if (NewBbsDevPathNode
== NULL
) {
254 return EFI_OUT_OF_RESOURCES
;
256 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
257 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
258 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
261 // Create entire new CurrentBbsDevPath with end node
263 CurrentBbsDevPath
= AppendDevicePathNode (
265 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
267 if (CurrentBbsDevPath
== NULL
) {
268 FreePool (NewBbsDevPathNode
);
269 return EFI_OUT_OF_RESOURCES
;
272 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
274 BufferSize
= sizeof (UINT32
) +
277 CurrentBbsDevPathSize
+
281 Buffer
= AllocateZeroPool (BufferSize
);
282 if (Buffer
== NULL
) {
283 FreePool (NewBbsDevPathNode
);
284 FreePool (CurrentBbsDevPath
);
285 return EFI_OUT_OF_RESOURCES
;
288 Ptr
= (UINT8
*) Buffer
;
290 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
291 Ptr
+= sizeof (UINT32
);
293 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
294 Ptr
+= sizeof (UINT16
);
301 Ptr
+= StrSize (BootDesc
);
306 CurrentBbsDevPathSize
308 Ptr
+= CurrentBbsDevPathSize
;
316 Ptr
+= sizeof (BBS_TABLE
);
317 *((UINT16
*) Ptr
) = (UINT16
) Index
;
319 Status
= gRT
->SetVariable (
321 &gEfiGlobalVariableGuid
,
331 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
332 if (NULL
== NewBootOrderList
) {
333 FreePool (NewBbsDevPathNode
);
334 FreePool (CurrentBbsDevPath
);
335 return EFI_OUT_OF_RESOURCES
;
338 if (*BootOrderList
!= NULL
) {
339 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
340 FreePool (*BootOrderList
);
343 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
344 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
345 *BootOrderListSize
+= sizeof (UINT16
);
346 *BootOrderList
= NewBootOrderList
;
348 FreePool (NewBbsDevPathNode
);
349 FreePool (CurrentBbsDevPath
);
354 Check if the boot option is a legacy one.
356 @param BootOptionVar The boot option data payload.
357 @param BbsEntry The BBS Table.
358 @param BbsIndex The table index.
360 @retval TRUE It is a legacy boot option.
361 @retval FALSE It is not a legacy boot option.
365 BdsIsLegacyBootOption (
366 IN UINT8
*BootOptionVar
,
367 OUT BBS_TABLE
**BbsEntry
,
372 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
377 Ptr
+= sizeof (UINT32
);
378 DevPathLen
= *(UINT16
*) Ptr
;
379 Ptr
+= sizeof (UINT16
);
380 Ptr
+= StrSize ((UINT16
*) Ptr
);
381 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
382 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
384 *BbsEntry
= (BBS_TABLE
*) Ptr
;
385 Ptr
+= sizeof (BBS_TABLE
);
386 *BbsIndex
= *(UINT16
*) Ptr
;
397 Delete all the invalid legacy boot options.
399 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
400 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
401 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
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;
679 Add the legacy boot options from BBS table if they do not exist.
681 @retval EFI_SUCCESS The boot options are added successfully
682 or they are already in boot options.
687 BdsAddNonExistingLegacyBootOptions (
696 HDD_INFO
*LocalHddInfo
;
697 BBS_TABLE
*LocalBbsTable
;
699 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
709 LocalBbsTable
= NULL
;
711 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
712 if (EFI_ERROR (Status
)) {
716 LegacyBios
->GetBbsInfo (
724 BootOrder
= BdsLibGetVariableAndSize (
726 &gEfiGlobalVariableGuid
,
729 if (NULL
== BootOrder
) {
733 for (Index
= 0; Index
< BbsCount
; Index
++) {
734 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
735 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
740 Ret
= BdsFindLegacyBootOptionByDevType (
742 BootOrderSize
/ sizeof (UINT16
),
743 LocalBbsTable
[Index
].DeviceType
,
753 // Not found such type of legacy device in boot options or we found but it's disabled
754 // so we have to create one and put it to the tail of boot order list
756 Status
= BdsCreateOneLegacyBootOption (
757 &LocalBbsTable
[Index
],
762 if (EFI_ERROR (Status
)) {
767 if (BootOrderSize
> 0) {
768 Status
= gRT
->SetVariable (
770 &gEfiGlobalVariableGuid
,
776 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
779 if (BootOrder
!= NULL
) {
780 FreePool (BootOrder
);
787 Fill the device order buffer.
789 @param BbsTable The BBS table.
790 @param BbsType The BBS Type.
791 @param BbsCount The BBS Count.
792 @param Buf device order buffer.
794 @return The device order buffer.
799 IN BBS_TABLE
*BbsTable
,
807 for (Index
= 0; Index
< BbsCount
; Index
++) {
808 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
812 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
816 *Buf
= (UINT16
) (Index
& 0xFF);
824 Create the device order buffer.
826 @param BbsTable The BBS table.
827 @param BbsCount The BBS Count.
829 @retval EFI_SUCCES The buffer is created and the EFI variable named
830 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
832 @return Other value if the set of EFI variable fails. Check gRT->SetVariable
833 for detailed information.
838 IN BBS_TABLE
*BbsTable
,
860 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
863 Status
= EFI_SUCCESS
;
866 // Count all boot devices
868 for (Index
= 0; Index
< BbsCount
; Index
++) {
869 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
873 switch (BbsTable
[Index
].DeviceType
) {
886 case BBS_EMBED_NETWORK
:
899 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
900 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
901 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
902 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
903 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
906 // Create buffer to hold all boot device order
908 DevOrder
= AllocateZeroPool (TotalSize
);
909 if (NULL
== DevOrder
) {
910 return EFI_OUT_OF_RESOURCES
;
915 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
916 Ptr
+= sizeof (BBS_TYPE
);
917 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
918 Ptr
+= sizeof (UINT16
);
920 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
923 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
924 Ptr
+= sizeof (BBS_TYPE
);
925 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
926 Ptr
+= sizeof (UINT16
);
928 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
931 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
932 Ptr
+= sizeof (BBS_TYPE
);
933 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
934 Ptr
+= sizeof (UINT16
);
936 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
939 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
940 Ptr
+= sizeof (BBS_TYPE
);
941 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
942 Ptr
+= sizeof (UINT16
);
944 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
947 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
948 Ptr
+= sizeof (BBS_TYPE
);
949 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
950 Ptr
+= sizeof (UINT16
);
952 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
956 // Save device order for legacy boot device to variable.
958 Status
= gRT
->SetVariable (
959 VAR_LEGACY_DEV_ORDER
,
960 &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.
980 BdsUpdateLegacyDevOrder (
987 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
991 HDD_INFO
*LocalHddInfo
;
992 BBS_TABLE
*LocalBbsTable
;
1019 LocalHddInfo
= NULL
;
1020 LocalBbsTable
= NULL
;
1028 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1036 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1037 if (EFI_ERROR (Status
)) {
1041 LegacyBios
->GetBbsInfo (
1049 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1050 VAR_LEGACY_DEV_ORDER
,
1051 &EfiLegacyDevOrderGuid
,
1054 if (NULL
== DevOrder
) {
1055 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1058 // First we figure out how many boot devices with same device type respectively
1060 for (Index
= 0; Index
< BbsCount
; Index
++) {
1061 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1062 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1067 switch (LocalBbsTable
[Index
].DeviceType
) {
1080 case BBS_EMBED_NETWORK
:
1084 case BBS_BEV_DEVICE
:
1093 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1094 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1095 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1096 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1097 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1099 NewDevOrder
= AllocateZeroPool (TotalSize
);
1100 if (NULL
== NewDevOrder
) {
1101 return EFI_OUT_OF_RESOURCES
;
1104 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1105 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1106 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1107 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1108 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1114 NewPtr
= NewDevOrder
;
1115 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1116 Ptr
+= sizeof (BBS_TYPE
);
1117 NewPtr
+= sizeof (BBS_TYPE
);
1118 Length
= *((UINT16
*) Ptr
);
1119 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1120 Ptr
+= sizeof (UINT16
);
1122 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1123 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1124 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1125 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1127 Ptr
+= sizeof (UINT16
);
1131 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1133 Ptr
+= sizeof (UINT16
);
1138 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1139 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1140 Ptr
+= sizeof (BBS_TYPE
);
1141 NewPtr
+= sizeof (BBS_TYPE
);
1142 Length
= *((UINT16
*) Ptr
);
1143 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1144 Ptr
+= sizeof (UINT16
);
1146 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1147 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1148 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1149 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1150 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1152 Ptr
+= sizeof (UINT16
);
1156 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1158 Ptr
+= sizeof (UINT16
);
1163 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1164 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1165 Ptr
+= sizeof (BBS_TYPE
);
1166 NewPtr
+= sizeof (BBS_TYPE
);
1167 Length
= *((UINT16
*) Ptr
);
1168 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1169 Ptr
+= sizeof (UINT16
);
1171 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1172 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1173 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1174 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1175 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1177 Ptr
+= sizeof (UINT16
);
1181 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1183 Ptr
+= sizeof (UINT16
);
1188 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1189 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1190 Ptr
+= sizeof (BBS_TYPE
);
1191 NewPtr
+= sizeof (BBS_TYPE
);
1192 Length
= *((UINT16
*) Ptr
);
1193 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1194 Ptr
+= sizeof (UINT16
);
1196 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1197 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1198 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1199 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1200 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1202 Ptr
+= sizeof (UINT16
);
1206 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1208 Ptr
+= sizeof (UINT16
);
1213 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1214 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1215 Ptr
+= sizeof (BBS_TYPE
);
1216 NewPtr
+= sizeof (BBS_TYPE
);
1217 Length
= *((UINT16
*) Ptr
);
1218 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1219 Ptr
+= sizeof (UINT16
);
1221 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1222 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1223 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1224 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1225 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1227 Ptr
+= sizeof (UINT16
);
1231 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1233 Ptr
+= sizeof (UINT16
);
1236 for (Index
= 0; Index
< BbsCount
; Index
++) {
1237 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1238 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1243 switch (LocalBbsTable
[Index
].DeviceType
) {
1246 NewDevPtr
= NewFDPtr
;
1251 NewDevPtr
= NewHDPtr
;
1256 NewDevPtr
= NewCDPtr
;
1259 case BBS_EMBED_NETWORK
:
1261 NewDevPtr
= NewNETPtr
;
1264 case BBS_BEV_DEVICE
:
1266 NewDevPtr
= NewBEVPtr
;
1274 // at this point we have copied those valid indexes to new buffer
1275 // and we should check if there is any new appeared boot device
1278 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1279 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1284 if (Index2
== *Idx
) {
1286 // Index2 == *Idx means we didn't find Index
1287 // so Index is a new appeared device's index in BBS table
1290 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1298 // Just to make sure that disabled indexes are all at the end of the array
1300 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1301 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1305 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1306 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1307 Tmp
= NewFDPtr
[Index
];
1308 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1309 NewFDPtr
[Index2
] = Tmp
;
1318 // Just to make sure that disabled indexes are all at the end of the array
1320 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1321 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1325 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1326 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1327 Tmp
= NewHDPtr
[Index
];
1328 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1329 NewHDPtr
[Index2
] = Tmp
;
1338 // Just to make sure that disabled indexes are all at the end of the array
1340 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1341 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1345 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1346 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1347 Tmp
= NewCDPtr
[Index
];
1348 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1349 NewCDPtr
[Index2
] = Tmp
;
1356 if (NETCount
!= 0) {
1358 // Just to make sure that disabled indexes are all at the end of the array
1360 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1361 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1365 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1366 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1367 Tmp
= NewNETPtr
[Index
];
1368 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1369 NewNETPtr
[Index2
] = Tmp
;
1378 // Just to make sure that disabled indexes are all at the end of the array
1380 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1381 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1385 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1386 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1387 Tmp
= NewBEVPtr
[Index
];
1388 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1389 NewBEVPtr
[Index2
] = Tmp
;
1396 FreePool (DevOrder
);
1398 Status
= gRT
->SetVariable (
1399 VAR_LEGACY_DEV_ORDER
,
1400 &EfiLegacyDevOrderGuid
,
1405 FreePool (NewDevOrder
);
1411 Set Boot Priority for specified device type.
1413 @param DeviceType The device type.
1414 @param LocalBbsTable The BBS table.
1415 @param Priority The prority table.
1417 @retval EFI_SUCCESS The function completes successfully.
1418 @retval EFI_NOT_FOUND Failed to find device.
1422 BdsSetBootPriority4SameTypeDev (
1423 IN UINT16 DeviceType
,
1424 IN OUT BBS_TABLE
*LocalBbsTable
,
1425 IN OUT UINT16
*Priority
1436 DevOrder
= BdsLibGetVariableAndSize (
1437 VAR_LEGACY_DEV_ORDER
,
1438 &EfiLegacyDevOrderGuid
,
1441 if (NULL
== DevOrder
) {
1442 return EFI_OUT_OF_RESOURCES
;
1445 OrigBuffer
= DevOrder
;
1446 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1447 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1451 DevOrder
+= sizeof (BBS_TYPE
);
1452 DevOrder
+= *(UINT16
*) DevOrder
;
1455 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1456 FreePool (OrigBuffer
);
1457 return EFI_NOT_FOUND
;
1460 DevOrder
+= sizeof (BBS_TYPE
);
1461 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1462 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1464 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1466 for (Index
= 0; Index
< DevCount
; Index
++) {
1467 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1469 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1472 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1477 FreePool (OrigBuffer
);
1482 Print the BBS Table.
1484 @param LocalBbsTable The BBS table.
1489 IN BBS_TABLE
*LocalBbsTable
1494 DEBUG ((DEBUG_ERROR
, "\n"));
1495 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1496 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1497 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1498 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1499 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1500 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1507 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1509 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1510 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1511 (UINTN
) LocalBbsTable
[Idx
].Device
,
1512 (UINTN
) LocalBbsTable
[Idx
].Function
,
1513 (UINTN
) LocalBbsTable
[Idx
].Class
,
1514 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1515 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1516 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1517 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1518 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1519 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1520 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1524 DEBUG ((DEBUG_ERROR
, "\n"));
1529 Set the boot priority for BBS entries based on boot option entry and boot order.
1531 @param Entry The boot option is to be checked for refresh BBS table.
1533 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1534 @return status of BdsSetBootPriority4SameTypeDev()
1538 BdsRefreshBbsTableForBoot (
1539 IN BDS_COMMON_OPTION
*Entry
1545 HDD_INFO
*LocalHddInfo
;
1546 BBS_TABLE
*LocalBbsTable
;
1548 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1552 UINTN BootOrderSize
;
1553 UINT8
*BootOptionVar
;
1554 UINTN BootOptionSize
;
1555 UINT16 BootOption
[100];
1558 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1562 LocalHddInfo
= NULL
;
1563 LocalBbsTable
= NULL
;
1564 DevType
= BBS_UNKNOWN
;
1566 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1567 if (EFI_ERROR (Status
)) {
1571 LegacyBios
->GetBbsInfo (
1579 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1580 // We will set them according to the settings setup by user
1582 for (Index
= 0; Index
< BbsCount
; Index
++) {
1583 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1584 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1585 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1586 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1590 // boot priority always starts at 0
1593 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1595 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1597 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1598 Status
= BdsSetBootPriority4SameTypeDev (
1603 if (EFI_ERROR (Status
)) {
1608 // we have to set the boot priority for other BBS entries with different device types
1610 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1612 &gEfiGlobalVariableGuid
,
1615 for (Index
= 0; ((BootOrder
!= NULL
) && (Index
< BootOrderSize
/ sizeof (UINT16
))); Index
++) {
1616 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1617 BootOptionVar
= BdsLibGetVariableAndSize (
1619 &gEfiGlobalVariableGuid
,
1622 if (NULL
== BootOptionVar
) {
1626 Ptr
= BootOptionVar
;
1628 Ptr
+= sizeof (UINT32
);
1629 DevPathLen
= *(UINT16
*) Ptr
;
1630 Ptr
+= sizeof (UINT16
);
1631 Ptr
+= StrSize ((UINT16
*) Ptr
);
1632 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1633 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1634 FreePool (BootOptionVar
);
1639 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1641 // We don't want to process twice for a device type
1643 FreePool (BootOptionVar
);
1647 Status
= BdsSetBootPriority4SameTypeDev (
1648 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1652 FreePool (BootOptionVar
);
1653 if (EFI_ERROR (Status
)) {
1658 if (BootOrder
!= NULL
) {
1659 FreePool (BootOrder
);
1663 PrintBbsTable (LocalBbsTable
);