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 a Pointer to input Ascii string.
28 @param Size The number of characters to translate.
29 @param u Pointer to output Unicode string buffer.
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 EDES_TODO: Add function description.
90 @param CurBBSEntry EDES_TODO: Add parameter description
91 @param Index EDES_TODO: Add parameter description
92 @param BufSize EDES_TODO: Add parameter description
93 @param BootString EDES_TODO: Add parameter description
95 @return EDES_TODO: Add description for return value
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 EDES_TODO: Add function description.
391 @param BootOptionVar EDES_TODO: Add parameter description
392 @param BbsEntry EDES_TODO: Add parameter description
393 @param BbsIndex EDES_TODO: Add parameter description
395 @return EDES_TODO: Add description for return value
399 BdsIsLegacyBootOption (
400 IN UINT8
*BootOptionVar
,
401 OUT BBS_TABLE
**BbsEntry
,
406 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
411 Ptr
+= sizeof (UINT32
);
412 DevPathLen
= *(UINT16
*) Ptr
;
413 Ptr
+= sizeof (UINT16
);
414 Ptr
+= StrSize ((UINT16
*) Ptr
);
415 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
416 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
418 *BbsEntry
= (BBS_TABLE
*) Ptr
;
419 Ptr
+= sizeof (BBS_TABLE
);
420 *BbsIndex
= *(UINT16
*) Ptr
;
432 Delete boot option specified by OptionNumber and adjust the boot order.
434 @param OptionNumber The boot option to be deleted.
435 @param BootOrder Boot order list to be adjusted by remove this boot option.
436 @param BootOrderSize The size of Boot order list will be modified.
438 @retval EFI_SUCCESS The boot option is deleted successfully.
443 BdsDeleteBootOption (
444 IN UINTN OptionNumber
,
445 IN OUT UINT16
*BootOrder
,
446 IN OUT UINTN
*BootOrderSize
449 UINT16 BootOption
[100];
454 Status
= EFI_SUCCESS
;
457 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
458 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
460 // adjust boot order array
462 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
463 if (BootOrder
[Index
] == OptionNumber
) {
469 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
470 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
471 if (Index
>= Index2Del
) {
472 BootOrder
[Index
] = BootOrder
[Index
+ 1];
476 *BootOrderSize
-= sizeof (UINT16
);
484 Delete all the invalid legacy boot options.
486 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
487 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
488 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
492 BdsDeleteAllInvalidLegacyBootOptions (
497 UINT8
*BootOptionVar
;
499 UINTN BootOptionSize
;
503 HDD_INFO
*LocalHddInfo
;
504 BBS_TABLE
*LocalBbsTable
;
507 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
509 UINT16 BootOption
[10];
510 UINT16 BootDesc
[100];
511 BOOLEAN DescStringMatch
;
513 Status
= EFI_SUCCESS
;
519 LocalBbsTable
= NULL
;
522 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
523 if (EFI_ERROR (Status
)) {
527 LegacyBios
->GetBbsInfo (
535 BootOrder
= BdsLibGetVariableAndSize (
537 &gEfiGlobalVariableGuid
,
540 if (NULL
== BootOrder
) {
541 return EFI_NOT_FOUND
;
545 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
546 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
547 BootOptionVar
= BdsLibGetVariableAndSize (
549 &gEfiGlobalVariableGuid
,
552 if (NULL
== BootOptionVar
) {
553 SafeFreePool (BootOrder
);
554 return EFI_OUT_OF_RESOURCES
;
557 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
558 SafeFreePool (BootOptionVar
);
564 // Check if BBS Description String is changed
566 DescStringMatch
= FALSE
;
568 BdsBuildLegacyDevNameString (
569 &LocalBbsTable
[BbsIndex
],
575 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
576 DescStringMatch
= TRUE
;
579 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
580 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
581 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
587 SafeFreePool (BootOptionVar
);
591 BdsDeleteBootOption (
598 if (BootOrderSize
!= 0) {
599 Status
= gRT
->SetVariable (
601 &gEfiGlobalVariableGuid
,
607 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
610 SafeFreePool (BootOrder
);
616 EDES_TODO: Add function description.
618 @param BootOrder EDES_TODO: Add parameter description
619 @param BootOptionNum EDES_TODO: Add parameter description
620 @param DevType EDES_TODO: Add parameter description
621 @param Attribute EDES_TODO: Add parameter description
622 @param BbsIndex EDES_TODO: Add parameter description
623 @param OptionNumber EDES_TODO: Add parameter description
625 @return EDES_TODO: Add description for return value
629 BdsFindLegacyBootOptionByDevType (
630 IN UINT16
*BootOrder
,
631 IN UINTN BootOptionNum
,
633 OUT UINT32
*Attribute
,
634 OUT UINT16
*BbsIndex
,
635 OUT UINTN
*OptionNumber
639 UINTN BootOrderIndex
;
640 UINT16 BootOption
[100];
641 UINTN BootOptionSize
;
642 UINT8
*BootOptionVar
;
649 if (NULL
== BootOrder
) {
653 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
654 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
655 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
656 BootOptionVar
= BdsLibGetVariableAndSize (
658 &gEfiGlobalVariableGuid
,
661 if (NULL
== BootOptionVar
) {
665 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
666 SafeFreePool (BootOptionVar
);
670 if (BbsEntry
->DeviceType
!= DevType
) {
671 SafeFreePool (BootOptionVar
);
675 *Attribute
= *(UINT32
*) BootOptionVar
;
676 *OptionNumber
= Index
;
678 SafeFreePool (BootOptionVar
);
686 EDES_TODO: Add function description.
688 @param BbsItem EDES_TODO: Add parameter description
689 @param Index EDES_TODO: Add parameter description
690 @param BootOrderList EDES_TODO: Add parameter description
691 @param BootOrderListSize EDES_TODO: Add parameter description
693 @return EDES_TODO: Add description for return value
697 BdsCreateOneLegacyBootOption (
698 IN BBS_TABLE
*BbsItem
,
700 IN OUT UINT16
**BootOrderList
,
701 IN OUT UINTN
*BootOrderListSize
704 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
706 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
710 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
711 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
712 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
713 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
714 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
716 DevPath
= AppendDevicePathNode (
718 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
720 if (NULL
== DevPath
) {
721 return EFI_OUT_OF_RESOURCES
;
724 Status
= BdsCreateLegacyBootOption (
731 BbsItem
->BootPriority
= 0x00;
740 Add the legacy boot options from BBS table if they do not exist.
742 @retval EFI_SUCCESS The boot options are added successfully
743 or they are already in boot options.
748 BdsAddNonExistingLegacyBootOptions (
757 HDD_INFO
*LocalHddInfo
;
758 BBS_TABLE
*LocalBbsTable
;
760 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
770 LocalBbsTable
= NULL
;
772 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
773 if (EFI_ERROR (Status
)) {
777 LegacyBios
->GetBbsInfo (
785 BootOrder
= BdsLibGetVariableAndSize (
787 &gEfiGlobalVariableGuid
,
790 if (NULL
== BootOrder
) {
794 for (Index
= 0; Index
< BbsCount
; Index
++) {
795 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
796 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
801 Ret
= BdsFindLegacyBootOptionByDevType (
803 BootOrderSize
/ sizeof (UINT16
),
804 LocalBbsTable
[Index
].DeviceType
,
814 // Not found such type of legacy device in boot options or we found but it's disabled
815 // so we have to create one and put it to the tail of boot order list
817 Status
= BdsCreateOneLegacyBootOption (
818 &LocalBbsTable
[Index
],
823 if (EFI_ERROR (Status
)) {
828 if (BootOrderSize
> 0) {
829 Status
= gRT
->SetVariable (
831 &gEfiGlobalVariableGuid
,
837 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
840 if (BootOrder
!= NULL
) {
841 SafeFreePool (BootOrder
);
848 EDES_TODO: Add function description.
850 @param BbsTable EDES_TODO: Add parameter description
851 @param BbsType EDES_TODO: Add parameter description
852 @param BbsCount EDES_TODO: Add parameter description
853 @param Buf EDES_TODO: Add parameter description
855 @return EDES_TODO: Add description for return value
860 IN BBS_TABLE
*BbsTable
,
868 for (Index
= 0; Index
< BbsCount
; Index
++) {
869 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
873 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
877 *Buf
= (UINT16
) (Index
& 0xFF);
885 EDES_TODO: Add function description.
887 @param BbsTable EDES_TODO: Add parameter description
888 @param BbsCount EDES_TODO: Add parameter description
890 @return EDES_TODO: Add description for return value
895 IN BBS_TABLE
*BbsTable
,
917 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
920 Status
= EFI_SUCCESS
;
922 for (Index
= 0; Index
< BbsCount
; Index
++) {
923 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
927 switch (BbsTable
[Index
].DeviceType
) {
940 case BBS_EMBED_NETWORK
:
953 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
954 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
955 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
956 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
957 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
959 DevOrder
= AllocateZeroPool (TotalSize
);
960 if (NULL
== DevOrder
) {
961 return EFI_OUT_OF_RESOURCES
;
966 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
967 Ptr
+= sizeof (BBS_TYPE
);
968 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
969 Ptr
+= sizeof (UINT16
);
971 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
974 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
975 Ptr
+= sizeof (BBS_TYPE
);
976 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
977 Ptr
+= sizeof (UINT16
);
979 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
982 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
983 Ptr
+= sizeof (BBS_TYPE
);
984 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
985 Ptr
+= sizeof (UINT16
);
987 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
990 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
991 Ptr
+= sizeof (BBS_TYPE
);
992 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
993 Ptr
+= sizeof (UINT16
);
995 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
998 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
999 Ptr
+= sizeof (BBS_TYPE
);
1000 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1001 Ptr
+= sizeof (UINT16
);
1002 if (BEVCount
!= 0) {
1003 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
1006 Status
= gRT
->SetVariable (
1007 VAR_LEGACY_DEV_ORDER
,
1008 &EfiLegacyDevOrderGuid
,
1013 SafeFreePool (DevOrder
);
1020 Add the legacy boot devices from BBS table into
1021 the legacy device boot order.
1023 @retval EFI_SUCCESS The boot devices are added successfully.
1028 BdsUpdateLegacyDevOrder (
1035 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1039 HDD_INFO
*LocalHddInfo
;
1040 BBS_TABLE
*LocalBbsTable
;
1067 LocalHddInfo
= NULL
;
1068 LocalBbsTable
= NULL
;
1076 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1084 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1085 if (EFI_ERROR (Status
)) {
1089 LegacyBios
->GetBbsInfo (
1097 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1098 VAR_LEGACY_DEV_ORDER
,
1099 &EfiLegacyDevOrderGuid
,
1102 if (NULL
== DevOrder
) {
1103 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1106 // First we figure out how many boot devices with same device type respectively
1108 for (Index
= 0; Index
< BbsCount
; Index
++) {
1109 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1110 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1115 switch (LocalBbsTable
[Index
].DeviceType
) {
1128 case BBS_EMBED_NETWORK
:
1132 case BBS_BEV_DEVICE
:
1141 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1142 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1143 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1144 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1145 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1147 NewDevOrder
= AllocateZeroPool (TotalSize
);
1148 if (NULL
== NewDevOrder
) {
1149 return EFI_OUT_OF_RESOURCES
;
1152 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1153 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1154 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1155 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1156 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1162 NewPtr
= NewDevOrder
;
1163 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1164 Ptr
+= sizeof (BBS_TYPE
);
1165 NewPtr
+= sizeof (BBS_TYPE
);
1166 Length
= *((UINT16
*) Ptr
);
1167 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1168 Ptr
+= sizeof (UINT16
);
1170 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1171 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1172 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1173 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1175 Ptr
+= sizeof (UINT16
);
1179 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1181 Ptr
+= sizeof (UINT16
);
1186 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1187 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1188 Ptr
+= sizeof (BBS_TYPE
);
1189 NewPtr
+= sizeof (BBS_TYPE
);
1190 Length
= *((UINT16
*) Ptr
);
1191 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1192 Ptr
+= sizeof (UINT16
);
1194 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1195 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1196 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1197 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1198 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1200 Ptr
+= sizeof (UINT16
);
1204 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1206 Ptr
+= sizeof (UINT16
);
1211 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1212 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1213 Ptr
+= sizeof (BBS_TYPE
);
1214 NewPtr
+= sizeof (BBS_TYPE
);
1215 Length
= *((UINT16
*) Ptr
);
1216 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1217 Ptr
+= sizeof (UINT16
);
1219 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1220 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1221 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1222 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1223 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1225 Ptr
+= sizeof (UINT16
);
1229 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1231 Ptr
+= sizeof (UINT16
);
1236 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1237 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1238 Ptr
+= sizeof (BBS_TYPE
);
1239 NewPtr
+= sizeof (BBS_TYPE
);
1240 Length
= *((UINT16
*) Ptr
);
1241 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1242 Ptr
+= sizeof (UINT16
);
1244 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1245 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1246 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1247 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1248 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1250 Ptr
+= sizeof (UINT16
);
1254 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1256 Ptr
+= sizeof (UINT16
);
1261 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1262 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1263 Ptr
+= sizeof (BBS_TYPE
);
1264 NewPtr
+= sizeof (BBS_TYPE
);
1265 Length
= *((UINT16
*) Ptr
);
1266 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1267 Ptr
+= sizeof (UINT16
);
1269 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1270 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1271 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1272 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1273 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1275 Ptr
+= sizeof (UINT16
);
1279 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1281 Ptr
+= sizeof (UINT16
);
1284 for (Index
= 0; Index
< BbsCount
; Index
++) {
1285 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1286 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1291 switch (LocalBbsTable
[Index
].DeviceType
) {
1294 NewDevPtr
= NewFDPtr
;
1299 NewDevPtr
= NewHDPtr
;
1304 NewDevPtr
= NewCDPtr
;
1307 case BBS_EMBED_NETWORK
:
1309 NewDevPtr
= NewNETPtr
;
1312 case BBS_BEV_DEVICE
:
1314 NewDevPtr
= NewBEVPtr
;
1322 // at this point we have copied those valid indexes to new buffer
1323 // and we should check if there is any new appeared boot device
1326 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1327 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1332 if (Index2
== *Idx
) {
1334 // Index2 == *Idx means we didn't find Index
1335 // so Index is a new appeared device's index in BBS table
1338 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1346 // Just to make sure that disabled indexes are all at the end of the array
1348 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1349 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1353 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1354 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1355 tmp
= NewFDPtr
[Index
];
1356 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1357 NewFDPtr
[Index2
] = tmp
;
1366 // Just to make sure that disabled indexes are all at the end of the array
1368 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1369 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1373 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1374 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1375 tmp
= NewHDPtr
[Index
];
1376 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1377 NewHDPtr
[Index2
] = tmp
;
1386 // Just to make sure that disabled indexes are all at the end of the array
1388 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1389 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1393 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1394 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1395 tmp
= NewCDPtr
[Index
];
1396 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1397 NewCDPtr
[Index2
] = tmp
;
1404 if (NETCount
!= 0) {
1406 // Just to make sure that disabled indexes are all at the end of the array
1408 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1409 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1413 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1414 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1415 tmp
= NewNETPtr
[Index
];
1416 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1417 NewNETPtr
[Index2
] = tmp
;
1426 // Just to make sure that disabled indexes are all at the end of the array
1428 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1429 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1433 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1434 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1435 tmp
= NewBEVPtr
[Index
];
1436 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1437 NewBEVPtr
[Index2
] = tmp
;
1444 SafeFreePool (DevOrder
);
1446 Status
= gRT
->SetVariable (
1447 VAR_LEGACY_DEV_ORDER
,
1448 &EfiLegacyDevOrderGuid
,
1453 SafeFreePool (NewDevOrder
);
1459 EDES_TODO: Add function description.
1461 @param DeviceType EDES_TODO: Add parameter description
1462 @param LocalBbsTable EDES_TODO: Add parameter description
1463 @param Priority EDES_TODO: Add parameter description
1465 @return EDES_TODO: Add description for return value
1469 BdsSetBootPriority4SameTypeDev (
1470 IN UINT16 DeviceType
,
1471 IN OUT BBS_TABLE
*LocalBbsTable
,
1472 IN OUT UINT16
*Priority
1483 DevOrder
= BdsLibGetVariableAndSize (
1484 VAR_LEGACY_DEV_ORDER
,
1485 &EfiLegacyDevOrderGuid
,
1488 if (NULL
== DevOrder
) {
1489 return EFI_OUT_OF_RESOURCES
;
1492 OrigBuffer
= DevOrder
;
1493 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1494 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1498 DevOrder
+= sizeof (BBS_TYPE
);
1499 DevOrder
+= *(UINT16
*) DevOrder
;
1502 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1503 SafeFreePool (OrigBuffer
);
1504 return EFI_NOT_FOUND
;
1507 DevOrder
+= sizeof (BBS_TYPE
);
1508 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1509 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1511 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1513 for (Index
= 0; Index
< DevCount
; Index
++) {
1514 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1516 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1519 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1524 SafeFreePool (OrigBuffer
);
1529 EDES_TODO: Add function description.
1531 @param LocalBbsTable EDES_TODO: Add parameter description
1533 @return EDES_TODO: Add description for return value
1538 IN BBS_TABLE
*LocalBbsTable
1543 DEBUG ((DEBUG_ERROR
, "\n"));
1544 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1545 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1546 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1547 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1548 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1549 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1556 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1558 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1559 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1560 (UINTN
) LocalBbsTable
[Idx
].Device
,
1561 (UINTN
) LocalBbsTable
[Idx
].Function
,
1562 (UINTN
) LocalBbsTable
[Idx
].Class
,
1563 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1564 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1565 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1566 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1567 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1568 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1569 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1573 DEBUG ((DEBUG_ERROR
, "\n"));
1578 Set the boot priority for BBS entries based on boot option entry and boot order.
1580 @param Entry The boot option is to be checked for refresh BBS table.
1582 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1587 BdsRefreshBbsTableForBoot (
1588 IN BDS_COMMON_OPTION
*Entry
1594 HDD_INFO
*LocalHddInfo
;
1595 BBS_TABLE
*LocalBbsTable
;
1597 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1601 UINTN BootOrderSize
;
1602 UINT8
*BootOptionVar
;
1603 UINTN BootOptionSize
;
1604 UINT16 BootOption
[100];
1607 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1611 LocalHddInfo
= NULL
;
1612 LocalBbsTable
= NULL
;
1613 DevType
= BBS_UNKNOWN
;
1615 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1616 if (EFI_ERROR (Status
)) {
1620 LegacyBios
->GetBbsInfo (
1628 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1629 // We will set them according to the settings setup by user
1631 for (Index
= 0; Index
< BbsCount
; Index
++) {
1632 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1633 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1634 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1635 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1639 // boot priority always starts at 0
1642 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1644 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1646 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1647 Status
= BdsSetBootPriority4SameTypeDev (
1652 if (EFI_ERROR (Status
)) {
1657 // we have to set the boot priority for other BBS entries with different device types
1659 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1661 &gEfiGlobalVariableGuid
,
1664 for (Index
= 0; ((BootOrder
!= NULL
) && (Index
< BootOrderSize
/ sizeof (UINT16
))); Index
++) {
1665 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1666 BootOptionVar
= BdsLibGetVariableAndSize (
1668 &gEfiGlobalVariableGuid
,
1671 if (NULL
== BootOptionVar
) {
1675 Ptr
= BootOptionVar
;
1677 Ptr
+= sizeof (UINT32
);
1678 DevPathLen
= *(UINT16
*) Ptr
;
1679 Ptr
+= sizeof (UINT16
);
1680 Ptr
+= StrSize ((UINT16
*) Ptr
);
1681 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1682 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1683 SafeFreePool (BootOptionVar
);
1688 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1690 // We don't want to process twice for a device type
1692 SafeFreePool (BootOptionVar
);
1696 Status
= BdsSetBootPriority4SameTypeDev (
1697 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1701 SafeFreePool (BootOptionVar
);
1702 if (EFI_ERROR (Status
)) {
1707 if (BootOrder
!= NULL
) {
1708 SafeFreePool (BootOrder
);
1713 PrintBbsTable (LocalBbsTable
);