3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This function deal with the legacy boot option, it create, delete
19 and manage the legacy boot option, all legacy boot option is getting from
24 #include "BBSsupport.h"
26 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
[] = {
28 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
29 END_DEVICE_PATH_LENGTH
,
55 BdsBuildLegacyDevNameString (
56 IN BBS_TABLE
*CurBBSEntry
,
59 OUT CHAR16
*BootString
72 Fmt
= L
"Primary Master %s";
79 Fmt
= L
"Primary Slave %s";
86 Fmt
= L
"Secondary Master %s";
93 Fmt
= L
"Secondary Slave %s";
101 switch (CurBBSEntry
->DeviceType
) {
122 case BBS_EMBED_NETWORK
:
136 // If current BBS entry has its description then use it.
138 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
139 if (NULL
!= StringDesc
) {
141 // Only get fisrt 32 characters, this is suggested by BBS spec
143 AsciiToUnicodeSize (StringDesc
, 32, temp
);
148 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
152 BdsCreateLegacyBootOption (
153 IN BBS_TABLE
*CurrentBbsEntry
,
154 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
156 IN OUT UINT16
**BootOrderList
,
157 IN OUT UINTN
*BootOrderListSize
161 UINT16 CurrentBootOptionNo
;
162 UINT16 BootString
[10];
163 UINT16 BootDesc
[100];
164 UINT16
*NewBootOrderList
;
168 UINT16 CurrentBbsDevPathSize
;
169 UINTN BootOrderIndex
;
170 UINTN BootOrderLastIndex
;
172 BOOLEAN IndexNotFound
;
174 if (NULL
== (*BootOrderList
)) {
175 CurrentBootOptionNo
= 0;
177 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
178 IndexNotFound
= TRUE
;
179 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
180 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
181 IndexNotFound
= FALSE
;
186 if (!IndexNotFound
) {
193 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
203 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
205 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
207 BufferSize
= sizeof (UINT32
) +
210 CurrentBbsDevPathSize
+
214 Buffer
= AllocateZeroPool (BufferSize
);
215 if (Buffer
== NULL
) {
216 return EFI_OUT_OF_RESOURCES
;
219 Ptr
= (UINT8
*) Buffer
;
221 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
222 Ptr
+= sizeof (UINT32
);
224 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
225 Ptr
+= sizeof (UINT16
);
232 Ptr
+= StrSize (BootDesc
);
237 CurrentBbsDevPathSize
239 Ptr
+= CurrentBbsDevPathSize
;
247 Ptr
+= sizeof (BBS_TABLE
);
248 *((UINT16
*) Ptr
) = (UINT16
) Index
;
250 Status
= gRT
->SetVariable (
252 &gEfiGlobalVariableGuid
,
258 SafeFreePool (Buffer
);
261 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
262 if (NULL
== NewBootOrderList
) {
263 return EFI_OUT_OF_RESOURCES
;
266 if (NULL
!= *BootOrderList
) {
267 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
270 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
271 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
272 *BootOrderListSize
+= sizeof (UINT16
);
273 *BootOrderList
= NewBootOrderList
;
279 BdsIsLegacyBootOption (
280 IN UINT8
*BootOptionVar
,
281 OUT BBS_TABLE
**BbsEntry
,
286 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
291 Ptr
+= sizeof (UINT32
);
292 DevPathLen
= *(UINT16
*) Ptr
;
293 Ptr
+= sizeof (UINT16
);
294 Ptr
+= StrSize ((UINT16
*) Ptr
);
295 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
296 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
298 *BbsEntry
= (BBS_TABLE
*) Ptr
;
299 Ptr
+= sizeof (BBS_TABLE
);
300 *BbsIndex
= *(UINT16
*) Ptr
;
311 BdsDeleteBootOption (
312 IN UINTN OptionNumber
,
313 IN OUT UINT16
*BootOrder
,
314 IN OUT UINTN
*BootOrderSize
317 UINT16 BootOption
[100];
322 Status
= EFI_SUCCESS
;
325 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
326 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
328 // adjust boot order array
330 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
331 if (BootOrder
[Index
] == OptionNumber
) {
337 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
338 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
339 if (Index
>= Index2Del
) {
340 BootOrder
[Index
] = BootOrder
[Index
+ 1];
344 *BootOrderSize
-= sizeof (UINT16
);
352 BdsDeleteAllInvalidLegacyBootOptions (
357 UINT8
*BootOptionVar
;
359 UINTN BootOptionSize
;
363 HDD_INFO
*LocalHddInfo
;
364 BBS_TABLE
*LocalBbsTable
;
367 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
369 UINT16 BootOption
[10];
371 Status
= EFI_SUCCESS
;
377 LocalBbsTable
= NULL
;
380 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
381 if (EFI_ERROR (Status
)) {
385 LegacyBios
->GetBbsInfo (
393 BootOrder
= BdsLibGetVariableAndSize (
395 &gEfiGlobalVariableGuid
,
398 if (NULL
== BootOrder
) {
399 return EFI_NOT_FOUND
;
403 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
404 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
405 BootOptionVar
= BdsLibGetVariableAndSize (
407 &gEfiGlobalVariableGuid
,
410 if (NULL
== BootOptionVar
) {
411 SafeFreePool (BootOrder
);
412 return EFI_OUT_OF_RESOURCES
;
415 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
416 SafeFreePool (BootOptionVar
);
421 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
422 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
423 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_LOWEST_PRIORITY
)) &&
424 LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) {
429 SafeFreePool (BootOptionVar
);
433 BdsDeleteBootOption (
441 Status
= gRT
->SetVariable (
443 &gEfiGlobalVariableGuid
,
449 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
452 SafeFreePool (BootOrder
);
458 BdsFindLegacyBootOptionByDevType (
459 IN UINT16
*BootOrder
,
460 IN UINTN BootOptionNum
,
462 OUT UINT32
*Attribute
,
463 OUT UINT16
*BbsIndex
,
464 OUT UINTN
*OptionNumber
468 UINTN BootOrderIndex
;
469 UINT16 BootOption
[100];
470 UINTN BootOptionSize
;
471 UINT8
*BootOptionVar
;
478 if (NULL
== BootOrder
) {
482 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
483 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
484 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
485 BootOptionVar
= BdsLibGetVariableAndSize (
487 &gEfiGlobalVariableGuid
,
490 if (NULL
== BootOptionVar
) {
494 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
495 SafeFreePool (BootOptionVar
);
499 if (BbsEntry
->DeviceType
!= DevType
) {
500 SafeFreePool (BootOptionVar
);
504 *Attribute
= *(UINT32
*) BootOptionVar
;
505 *OptionNumber
= Index
;
507 SafeFreePool (BootOptionVar
);
515 BdsCreateOneLegacyBootOption (
516 IN BBS_TABLE
*BbsItem
,
518 IN OUT UINT16
**BootOrderList
,
519 IN OUT UINTN
*BootOrderListSize
522 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
524 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
528 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
529 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
530 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
531 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
532 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
534 DevPath
= AppendDevicePathNode (
536 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
538 if (NULL
== DevPath
) {
539 return EFI_OUT_OF_RESOURCES
;
542 Status
= BdsCreateLegacyBootOption (
549 BbsItem
->BootPriority
= 0x00;
551 gBS
->FreePool (DevPath
);
557 BdsAddNonExistingLegacyBootOptions (
564 Add the legacy boot options from BBS table if they do not exist.
572 EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
573 others - An error occurred when creating legacy boot options.
582 HDD_INFO
*LocalHddInfo
;
583 BBS_TABLE
*LocalBbsTable
;
585 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
595 LocalBbsTable
= NULL
;
597 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
598 if (EFI_ERROR (Status
)) {
602 LegacyBios
->GetBbsInfo (
610 BootOrder
= BdsLibGetVariableAndSize (
612 &gEfiGlobalVariableGuid
,
615 if (NULL
== BootOrder
) {
619 for (Index
= 0; Index
< BbsCount
; Index
++) {
620 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
621 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
626 Ret
= BdsFindLegacyBootOptionByDevType (
628 BootOrderSize
/ sizeof (UINT16
),
629 LocalBbsTable
[Index
].DeviceType
,
634 if (Ret
&& (Attribute
& LOAD_OPTION_ACTIVE
) != 0) {
639 if (Index
!= BbsIndex
) {
640 BdsDeleteBootOption (
650 // Not found such type of legacy device in boot options or we found but it's disabled
651 // so we have to create one and put it to the tail of boot order list
653 Status
= BdsCreateOneLegacyBootOption (
654 &LocalBbsTable
[Index
],
659 if (EFI_ERROR (Status
)) {
664 if (BootOrderSize
> 0) {
665 Status
= gRT
->SetVariable (
667 &gEfiGlobalVariableGuid
,
673 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
676 if (BootOrder
!= NULL
) {
677 SafeFreePool (BootOrder
);
685 IN BBS_TABLE
*BbsTable
,
693 for (Index
= 0; Index
< BbsCount
; Index
++) {
694 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
698 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
702 *Buf
= (UINT16
) (Index
& 0xFF);
711 IN BBS_TABLE
*BbsTable
,
733 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
736 Status
= EFI_SUCCESS
;
738 for (Index
= 0; Index
< BbsCount
; Index
++) {
739 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
743 switch (BbsTable
[Index
].DeviceType
) {
756 case BBS_EMBED_NETWORK
:
769 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
770 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
771 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
772 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
773 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
775 DevOrder
= AllocateZeroPool (TotalSize
);
776 if (NULL
== DevOrder
) {
777 return EFI_OUT_OF_RESOURCES
;
782 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
783 Ptr
+= sizeof (BBS_TYPE
);
784 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
785 Ptr
+= sizeof (UINT16
);
787 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
790 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
791 Ptr
+= sizeof (BBS_TYPE
);
792 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
793 Ptr
+= sizeof (UINT16
);
795 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
798 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
799 Ptr
+= sizeof (BBS_TYPE
);
800 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
801 Ptr
+= sizeof (UINT16
);
803 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
806 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
807 Ptr
+= sizeof (BBS_TYPE
);
808 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
809 Ptr
+= sizeof (UINT16
);
811 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
814 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
815 Ptr
+= sizeof (BBS_TYPE
);
816 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
817 Ptr
+= sizeof (UINT16
);
819 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
822 Status
= gRT
->SetVariable (
824 &EfiLegacyDevOrderGuid
,
829 SafeFreePool (DevOrder
);
835 BdsUpdateLegacyDevOrder (
839 Format of LegacyDevOrder variable:
840 |-----------------------------------------------------------------------------------------------------------------
841 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
842 |-----------------------------------------------------------------------------------------------------------------
844 Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
845 Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
846 the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
853 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
857 HDD_INFO
*LocalHddInfo
;
858 BBS_TABLE
*LocalBbsTable
;
886 LocalBbsTable
= NULL
;
894 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
902 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
903 if (EFI_ERROR (Status
)) {
907 LegacyBios
->GetBbsInfo (
915 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
917 &EfiLegacyDevOrderGuid
,
920 if (NULL
== DevOrder
) {
921 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
924 // First we figure out how many boot devices with same device type respectively
926 for (Index
= 0; Index
< BbsCount
; Index
++) {
927 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
928 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
929 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
934 switch (LocalBbsTable
[Index
].DeviceType
) {
947 case BBS_EMBED_NETWORK
:
960 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
961 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
962 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
963 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
964 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
966 NewDevOrder
= AllocateZeroPool (TotalSize
);
967 if (NULL
== NewDevOrder
) {
968 return EFI_OUT_OF_RESOURCES
;
971 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
972 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
973 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
974 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
975 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
981 NewPtr
= NewDevOrder
;
982 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
983 Ptr
+= sizeof (BBS_TYPE
);
984 NewPtr
+= sizeof (BBS_TYPE
);
985 Length
= *((UINT16
*) Ptr
);
986 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
987 Ptr
+= sizeof (UINT16
);
989 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
990 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
991 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
992 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
993 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
995 Ptr
+= sizeof (UINT16
);
999 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1001 Ptr
+= sizeof (UINT16
);
1006 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1007 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1008 Ptr
+= sizeof (BBS_TYPE
);
1009 NewPtr
+= sizeof (BBS_TYPE
);
1010 Length
= *((UINT16
*) Ptr
);
1011 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1012 Ptr
+= sizeof (UINT16
);
1014 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1015 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1016 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1017 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1018 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1020 Ptr
+= sizeof (UINT16
);
1024 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1026 Ptr
+= sizeof (UINT16
);
1031 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1032 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1033 Ptr
+= sizeof (BBS_TYPE
);
1034 NewPtr
+= sizeof (BBS_TYPE
);
1035 Length
= *((UINT16
*) Ptr
);
1036 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1037 Ptr
+= sizeof (UINT16
);
1039 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1040 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1041 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1042 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1043 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1045 Ptr
+= sizeof (UINT16
);
1049 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1051 Ptr
+= sizeof (UINT16
);
1056 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1057 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1058 Ptr
+= sizeof (BBS_TYPE
);
1059 NewPtr
+= sizeof (BBS_TYPE
);
1060 Length
= *((UINT16
*) Ptr
);
1061 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1062 Ptr
+= sizeof (UINT16
);
1064 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1065 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1066 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1067 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1068 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1070 Ptr
+= sizeof (UINT16
);
1074 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1076 Ptr
+= sizeof (UINT16
);
1081 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1082 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1083 Ptr
+= sizeof (BBS_TYPE
);
1084 NewPtr
+= sizeof (BBS_TYPE
);
1085 Length
= *((UINT16
*) Ptr
);
1086 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1087 Ptr
+= sizeof (UINT16
);
1089 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1090 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1091 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1092 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1093 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1095 Ptr
+= sizeof (UINT16
);
1099 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1101 Ptr
+= sizeof (UINT16
);
1104 for (Index
= 0; Index
< BbsCount
; Index
++) {
1105 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1106 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1107 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1112 switch (LocalBbsTable
[Index
].DeviceType
) {
1115 NewDevPtr
= NewFDPtr
;
1120 NewDevPtr
= NewHDPtr
;
1125 NewDevPtr
= NewCDPtr
;
1128 case BBS_EMBED_NETWORK
:
1130 NewDevPtr
= NewNETPtr
;
1133 case BBS_BEV_DEVICE
:
1135 NewDevPtr
= NewBEVPtr
;
1143 // at this point we have copied those valid indexes to new buffer
1144 // and we should check if there is any new appeared boot device
1147 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1148 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1153 if (Index2
== *Idx
) {
1155 // Index2 == *Idx means we didn't find Index
1156 // so Index is a new appeared device's index in BBS table
1159 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1167 // Just to make sure that disabled indexes are all at the end of the array
1169 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1170 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1174 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1175 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1176 tmp
= NewFDPtr
[Index
];
1177 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1178 NewFDPtr
[Index2
] = tmp
;
1187 // Just to make sure that disabled indexes are all at the end of the array
1189 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1190 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1194 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1195 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1196 tmp
= NewHDPtr
[Index
];
1197 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1198 NewHDPtr
[Index2
] = tmp
;
1207 // Just to make sure that disabled indexes are all at the end of the array
1209 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1210 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1214 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1215 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1216 tmp
= NewCDPtr
[Index
];
1217 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1218 NewCDPtr
[Index2
] = tmp
;
1227 // Just to make sure that disabled indexes are all at the end of the array
1229 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1230 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1234 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1235 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1236 tmp
= NewNETPtr
[Index
];
1237 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1238 NewNETPtr
[Index2
] = tmp
;
1247 // Just to make sure that disabled indexes are all at the end of the array
1249 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1250 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1254 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1255 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1256 tmp
= NewBEVPtr
[Index
];
1257 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1258 NewBEVPtr
[Index2
] = tmp
;
1265 SafeFreePool (DevOrder
);
1267 Status
= gRT
->SetVariable (
1269 &EfiLegacyDevOrderGuid
,
1274 SafeFreePool (NewDevOrder
);
1280 BdsSetBootPriority4SameTypeDev (
1281 IN UINT16 DeviceType
,
1282 IN OUT BBS_TABLE
*LocalBbsTable
,
1283 IN OUT UINT16
*Priority
1286 DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
1287 LocalBbsTable - BBS table instance
1288 Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
1289 priority can be used next time.
1300 DevOrder
= BdsLibGetVariableAndSize (
1302 &EfiLegacyDevOrderGuid
,
1305 if (NULL
== DevOrder
) {
1306 return EFI_OUT_OF_RESOURCES
;
1309 OrigBuffer
= DevOrder
;
1310 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1311 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1315 DevOrder
+= sizeof (BBS_TYPE
);
1316 DevOrder
+= *(UINT16
*) DevOrder
;
1319 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1320 SafeFreePool (OrigBuffer
);
1321 return EFI_NOT_FOUND
;
1324 DevOrder
+= sizeof (BBS_TYPE
);
1325 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1326 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1328 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1330 for (Index
= 0; Index
< DevCount
; Index
++) {
1331 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1333 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1336 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1341 SafeFreePool (OrigBuffer
);
1347 IN BBS_TABLE
*LocalBbsTable
1352 DEBUG ((EFI_D_ERROR
, "\n"));
1353 DEBUG ((EFI_D_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1354 DEBUG ((EFI_D_ERROR
, "=============================================\n"));
1355 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1356 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1357 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1358 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1365 " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
1367 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1368 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1369 (UINTN
) LocalBbsTable
[Idx
].Device
,
1370 (UINTN
) LocalBbsTable
[Idx
].Function
,
1371 (UINTN
) LocalBbsTable
[Idx
].Class
,
1372 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1373 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1374 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1375 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1376 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1377 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1378 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1382 DEBUG ((EFI_D_ERROR
, "\n"));
1386 BdsRefreshBbsTableForBoot (
1387 IN BDS_COMMON_OPTION
*Entry
1393 HDD_INFO
*LocalHddInfo
;
1394 BBS_TABLE
*LocalBbsTable
;
1396 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1400 UINTN BootOrderSize
;
1401 UINT8
*BootOptionVar
;
1402 UINTN BootOptionSize
;
1403 UINT16 BootOption
[100];
1406 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1410 LocalHddInfo
= NULL
;
1411 LocalBbsTable
= NULL
;
1412 DevType
= BBS_UNKNOWN
;
1414 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
1415 if (EFI_ERROR (Status
)) {
1419 LegacyBios
->GetBbsInfo (
1427 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1428 // We will set them according to the settings setup by user
1430 for (Index
= 0; Index
< BbsCount
; Index
++) {
1431 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1432 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1433 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1434 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1438 // boot priority always starts at 0
1441 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1443 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1445 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1446 Status
= BdsSetBootPriority4SameTypeDev (
1451 if (EFI_ERROR (Status
)) {
1456 // we have to set the boot priority for other BBS entries with different device types
1458 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1460 &gEfiGlobalVariableGuid
,
1463 for (Index
= 0; BootOrder
&& Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
1464 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1465 BootOptionVar
= BdsLibGetVariableAndSize (
1467 &gEfiGlobalVariableGuid
,
1470 if (NULL
== BootOptionVar
) {
1474 Ptr
= BootOptionVar
;
1476 Ptr
+= sizeof (UINT32
);
1477 DevPathLen
= *(UINT16
*) Ptr
;
1478 Ptr
+= sizeof (UINT16
);
1479 Ptr
+= StrSize ((UINT16
*) Ptr
);
1480 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1481 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1482 SafeFreePool (BootOptionVar
);
1487 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1489 // We don't want to process twice for a device type
1491 SafeFreePool (BootOptionVar
);
1495 Status
= BdsSetBootPriority4SameTypeDev (
1496 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1500 SafeFreePool (BootOptionVar
);
1501 if (EFI_ERROR (Status
)) {
1507 SafeFreePool (BootOrder
);
1512 PrintBbsTable (LocalBbsTable
);