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
[] = {
29 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
31 END_DEVICE_PATH_LENGTH
,
47 Translate the first n characters of an Ascii string to
48 Unicode characters. The count n is indicated by parameter
49 Size. If Size is greater than the length of string, then
50 the entire string is translated.
54 a - Pointer to input Ascii string.
55 Size - The number of characters to translate.
56 u - Pointer to output Unicode string buffer.
79 BdsBuildLegacyDevNameString (
80 IN BBS_TABLE
*CurBBSEntry
,
83 OUT CHAR16
*BootString
96 Fmt
= L
"Primary Master %s";
103 Fmt
= L
"Primary Slave %s";
110 Fmt
= L
"Secondary Master %s";
117 Fmt
= L
"Secondary Slave %s";
125 switch (CurBBSEntry
->DeviceType
) {
146 case BBS_EMBED_NETWORK
:
160 // If current BBS entry has its description then use it.
162 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
163 if (NULL
!= StringDesc
) {
165 // Only get fisrt 32 characters, this is suggested by BBS spec
167 AsciiToUnicodeSize (StringDesc
, 32, temp
);
172 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
176 BdsCreateLegacyBootOption (
177 IN BBS_TABLE
*CurrentBbsEntry
,
178 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
180 IN OUT UINT16
**BootOrderList
,
181 IN OUT UINTN
*BootOrderListSize
187 Create a legacy boot option for the specified entry of
188 BBS table, save it as variable, and append it to the boot
193 CurrentBbsEntry - Pointer to current BBS table.
194 CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
195 Index - Index of the specified entry in BBS table.
196 BootOrderList - On input, the original boot order list.
197 On output, the new boot order list attached with the
199 BootOrderListSize - On input, the original size of boot order list.
200 - On output, the size of new boot order list.
204 EFI_SUCCESS - Boot Option successfully created.
205 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
206 Other - Error occurs while setting variable.
211 UINT16 CurrentBootOptionNo
;
212 UINT16 BootString
[10];
213 UINT16 BootDesc
[100];
214 UINT16
*NewBootOrderList
;
218 UINT16 CurrentBbsDevPathSize
;
219 UINTN BootOrderIndex
;
220 UINTN BootOrderLastIndex
;
222 BOOLEAN IndexNotFound
;
224 if (NULL
== (*BootOrderList
)) {
225 CurrentBootOptionNo
= 0;
227 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
228 IndexNotFound
= TRUE
;
229 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
230 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
231 IndexNotFound
= FALSE
;
236 if (!IndexNotFound
) {
243 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
253 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
255 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
257 BufferSize
= sizeof (UINT32
) +
260 CurrentBbsDevPathSize
+
264 Buffer
= AllocateZeroPool (BufferSize
);
265 if (Buffer
== NULL
) {
266 return EFI_OUT_OF_RESOURCES
;
269 Ptr
= (UINT8
*) Buffer
;
271 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
272 Ptr
+= sizeof (UINT32
);
274 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
275 Ptr
+= sizeof (UINT16
);
282 Ptr
+= StrSize (BootDesc
);
287 CurrentBbsDevPathSize
289 Ptr
+= CurrentBbsDevPathSize
;
297 Ptr
+= sizeof (BBS_TABLE
);
298 *((UINT16
*) Ptr
) = (UINT16
) Index
;
300 Status
= gRT
->SetVariable (
302 &gEfiGlobalVariableGuid
,
308 SafeFreePool (Buffer
);
311 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
312 if (NULL
== NewBootOrderList
) {
313 return EFI_OUT_OF_RESOURCES
;
316 if (NULL
!= *BootOrderList
) {
317 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
320 SafeFreePool (*BootOrderList
);
322 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
323 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
324 *BootOrderListSize
+= sizeof (UINT16
);
325 *BootOrderList
= NewBootOrderList
;
331 BdsIsLegacyBootOption (
332 IN UINT8
*BootOptionVar
,
333 OUT BBS_TABLE
**BbsEntry
,
338 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
343 Ptr
+= sizeof (UINT32
);
344 DevPathLen
= *(UINT16
*) Ptr
;
345 Ptr
+= sizeof (UINT16
);
346 Ptr
+= StrSize ((UINT16
*) Ptr
);
347 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
348 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
350 *BbsEntry
= (BBS_TABLE
*) Ptr
;
351 Ptr
+= sizeof (BBS_TABLE
);
352 *BbsIndex
= *(UINT16
*) Ptr
;
363 BdsDeleteBootOption (
364 IN UINTN OptionNumber
,
365 IN OUT UINT16
*BootOrder
,
366 IN OUT UINTN
*BootOrderSize
369 UINT16 BootOption
[100];
374 Status
= EFI_SUCCESS
;
377 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
378 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
380 // adjust boot order array
382 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
383 if (BootOrder
[Index
] == OptionNumber
) {
389 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
390 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
391 if (Index
>= Index2Del
) {
392 BootOrder
[Index
] = BootOrder
[Index
+ 1];
396 *BootOrderSize
-= sizeof (UINT16
);
404 BdsDeleteAllInvalidLegacyBootOptions (
411 Delete all the invalid legacy boot options.
419 EFI_SUCCESS - All invalide legacy boot options are deleted.
420 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
421 EFI_NOT_FOUND - Fail to retrive variable of boot order.
422 Other - Error occurs while setting variable or locating
428 UINT8
*BootOptionVar
;
430 UINTN BootOptionSize
;
434 HDD_INFO
*LocalHddInfo
;
435 BBS_TABLE
*LocalBbsTable
;
438 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
440 UINT16 BootOption
[10];
441 UINT16 BootDesc
[100];
442 BOOLEAN DescStringMatch
;
444 Status
= EFI_SUCCESS
;
450 LocalBbsTable
= NULL
;
453 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
454 if (EFI_ERROR (Status
)) {
458 LegacyBios
->GetBbsInfo (
466 BootOrder
= BdsLibGetVariableAndSize (
468 &gEfiGlobalVariableGuid
,
471 if (NULL
== BootOrder
) {
472 return EFI_NOT_FOUND
;
476 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
477 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
478 BootOptionVar
= BdsLibGetVariableAndSize (
480 &gEfiGlobalVariableGuid
,
483 if (NULL
== BootOptionVar
) {
484 SafeFreePool (BootOrder
);
485 return EFI_OUT_OF_RESOURCES
;
488 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
489 SafeFreePool (BootOptionVar
);
495 // Check if BBS Description String is changed
497 DescStringMatch
= FALSE
;
499 BdsBuildLegacyDevNameString (
500 &LocalBbsTable
[BbsIndex
],
506 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
507 DescStringMatch
= TRUE
;
510 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
511 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
512 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_LOWEST_PRIORITY
)) &&
513 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
519 SafeFreePool (BootOptionVar
);
523 BdsDeleteBootOption (
531 Status
= gRT
->SetVariable (
533 &gEfiGlobalVariableGuid
,
539 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
542 SafeFreePool (BootOrder
);
548 BdsFindLegacyBootOptionByDevType (
549 IN UINT16
*BootOrder
,
550 IN UINTN BootOptionNum
,
552 OUT UINT32
*Attribute
,
553 OUT UINT16
*BbsIndex
,
554 OUT UINTN
*OptionNumber
558 UINTN BootOrderIndex
;
559 UINT16 BootOption
[100];
560 UINTN BootOptionSize
;
561 UINT8
*BootOptionVar
;
568 if (NULL
== BootOrder
) {
572 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
573 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
574 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
575 BootOptionVar
= BdsLibGetVariableAndSize (
577 &gEfiGlobalVariableGuid
,
580 if (NULL
== BootOptionVar
) {
584 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
585 SafeFreePool (BootOptionVar
);
589 if (BbsEntry
->DeviceType
!= DevType
) {
590 SafeFreePool (BootOptionVar
);
594 *Attribute
= *(UINT32
*) BootOptionVar
;
595 *OptionNumber
= Index
;
597 SafeFreePool (BootOptionVar
);
605 BdsCreateOneLegacyBootOption (
606 IN BBS_TABLE
*BbsItem
,
608 IN OUT UINT16
**BootOrderList
,
609 IN OUT UINTN
*BootOrderListSize
612 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
614 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
618 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
619 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
620 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
621 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
622 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
624 DevPath
= AppendDevicePathNode (
626 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
628 if (NULL
== DevPath
) {
629 return EFI_OUT_OF_RESOURCES
;
632 Status
= BdsCreateLegacyBootOption (
639 BbsItem
->BootPriority
= 0x00;
641 gBS
->FreePool (DevPath
);
647 BdsAddNonExistingLegacyBootOptions (
654 Add the legacy boot options from BBS table if they do not exist.
662 EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
663 others - An error occurred when creating legacy boot options.
672 HDD_INFO
*LocalHddInfo
;
673 BBS_TABLE
*LocalBbsTable
;
675 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
685 LocalBbsTable
= NULL
;
687 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**)&LegacyBios
);
688 if (EFI_ERROR (Status
)) {
692 LegacyBios
->GetBbsInfo (
700 BootOrder
= BdsLibGetVariableAndSize (
702 &gEfiGlobalVariableGuid
,
705 if (NULL
== BootOrder
) {
709 for (Index
= 0; Index
< BbsCount
; Index
++) {
710 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
711 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
716 Ret
= BdsFindLegacyBootOptionByDevType (
718 BootOrderSize
/ sizeof (UINT16
),
719 LocalBbsTable
[Index
].DeviceType
,
724 if (Ret
&& (Attribute
& LOAD_OPTION_ACTIVE
) != 0) {
729 if (Index
!= BbsIndex
) {
730 BdsDeleteBootOption (
740 // Not found such type of legacy device in boot options or we found but it's disabled
741 // so we have to create one and put it to the tail of boot order list
743 Status
= BdsCreateOneLegacyBootOption (
744 &LocalBbsTable
[Index
],
749 if (EFI_ERROR (Status
)) {
754 if (BootOrderSize
> 0) {
755 Status
= gRT
->SetVariable (
757 &gEfiGlobalVariableGuid
,
763 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
766 if (BootOrder
!= NULL
) {
767 SafeFreePool (BootOrder
);
775 IN BBS_TABLE
*BbsTable
,
783 for (Index
= 0; Index
< BbsCount
; Index
++) {
784 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
788 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
792 *Buf
= (UINT16
) (Index
& 0xFF);
801 IN BBS_TABLE
*BbsTable
,
823 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
826 Status
= EFI_SUCCESS
;
828 for (Index
= 0; Index
< BbsCount
; Index
++) {
829 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
833 switch (BbsTable
[Index
].DeviceType
) {
846 case BBS_EMBED_NETWORK
:
859 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
860 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
861 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
862 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
863 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
865 DevOrder
= AllocateZeroPool (TotalSize
);
866 if (NULL
== DevOrder
) {
867 return EFI_OUT_OF_RESOURCES
;
872 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
873 Ptr
+= sizeof (BBS_TYPE
);
874 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
875 Ptr
+= sizeof (UINT16
);
877 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
880 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
881 Ptr
+= sizeof (BBS_TYPE
);
882 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
883 Ptr
+= sizeof (UINT16
);
885 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
888 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
889 Ptr
+= sizeof (BBS_TYPE
);
890 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
891 Ptr
+= sizeof (UINT16
);
893 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
896 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
897 Ptr
+= sizeof (BBS_TYPE
);
898 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
899 Ptr
+= sizeof (UINT16
);
901 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
904 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
905 Ptr
+= sizeof (BBS_TYPE
);
906 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
907 Ptr
+= sizeof (UINT16
);
909 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
912 Status
= gRT
->SetVariable (
914 &EfiLegacyDevOrderGuid
,
919 SafeFreePool (DevOrder
);
925 BdsUpdateLegacyDevOrder (
929 Format of LegacyDevOrder variable:
930 |-----------------------------------------------------------------------------------------------------------------
931 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
932 |-----------------------------------------------------------------------------------------------------------------
934 Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
935 Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
936 the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
943 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
947 HDD_INFO
*LocalHddInfo
;
948 BBS_TABLE
*LocalBbsTable
;
976 LocalBbsTable
= NULL
;
984 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
992 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
993 if (EFI_ERROR (Status
)) {
997 LegacyBios
->GetBbsInfo (
1005 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1007 &EfiLegacyDevOrderGuid
,
1010 if (NULL
== DevOrder
) {
1011 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1014 // First we figure out how many boot devices with same device type respectively
1016 for (Index
= 0; Index
< BbsCount
; Index
++) {
1017 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1018 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1019 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1024 switch (LocalBbsTable
[Index
].DeviceType
) {
1037 case BBS_EMBED_NETWORK
:
1041 case BBS_BEV_DEVICE
:
1050 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1051 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1052 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1053 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1054 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1056 NewDevOrder
= AllocateZeroPool (TotalSize
);
1057 if (NULL
== NewDevOrder
) {
1058 return EFI_OUT_OF_RESOURCES
;
1061 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1062 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1063 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1064 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1065 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1071 NewPtr
= NewDevOrder
;
1072 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1073 Ptr
+= sizeof (BBS_TYPE
);
1074 NewPtr
+= sizeof (BBS_TYPE
);
1075 Length
= *((UINT16
*) Ptr
);
1076 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1077 Ptr
+= sizeof (UINT16
);
1079 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1080 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1081 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1082 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1083 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1085 Ptr
+= sizeof (UINT16
);
1089 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1091 Ptr
+= sizeof (UINT16
);
1096 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1097 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1098 Ptr
+= sizeof (BBS_TYPE
);
1099 NewPtr
+= sizeof (BBS_TYPE
);
1100 Length
= *((UINT16
*) Ptr
);
1101 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1102 Ptr
+= sizeof (UINT16
);
1104 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1105 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1106 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1107 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1108 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1110 Ptr
+= sizeof (UINT16
);
1114 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1116 Ptr
+= sizeof (UINT16
);
1121 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1122 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1123 Ptr
+= sizeof (BBS_TYPE
);
1124 NewPtr
+= sizeof (BBS_TYPE
);
1125 Length
= *((UINT16
*) Ptr
);
1126 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1127 Ptr
+= sizeof (UINT16
);
1129 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1130 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1131 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1132 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1133 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1135 Ptr
+= sizeof (UINT16
);
1139 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1141 Ptr
+= sizeof (UINT16
);
1146 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1147 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1148 Ptr
+= sizeof (BBS_TYPE
);
1149 NewPtr
+= sizeof (BBS_TYPE
);
1150 Length
= *((UINT16
*) Ptr
);
1151 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1152 Ptr
+= sizeof (UINT16
);
1154 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1155 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1156 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1157 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1158 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1160 Ptr
+= sizeof (UINT16
);
1164 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1166 Ptr
+= sizeof (UINT16
);
1171 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1172 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1173 Ptr
+= sizeof (BBS_TYPE
);
1174 NewPtr
+= sizeof (BBS_TYPE
);
1175 Length
= *((UINT16
*) Ptr
);
1176 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1177 Ptr
+= sizeof (UINT16
);
1179 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1180 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1181 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1182 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1183 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1185 Ptr
+= sizeof (UINT16
);
1189 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1191 Ptr
+= sizeof (UINT16
);
1194 for (Index
= 0; Index
< BbsCount
; Index
++) {
1195 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1196 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1197 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1202 switch (LocalBbsTable
[Index
].DeviceType
) {
1205 NewDevPtr
= NewFDPtr
;
1210 NewDevPtr
= NewHDPtr
;
1215 NewDevPtr
= NewCDPtr
;
1218 case BBS_EMBED_NETWORK
:
1220 NewDevPtr
= NewNETPtr
;
1223 case BBS_BEV_DEVICE
:
1225 NewDevPtr
= NewBEVPtr
;
1233 // at this point we have copied those valid indexes to new buffer
1234 // and we should check if there is any new appeared boot device
1237 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1238 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1243 if (Index2
== *Idx
) {
1245 // Index2 == *Idx means we didn't find Index
1246 // so Index is a new appeared device's index in BBS table
1249 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1257 // Just to make sure that disabled indexes are all at the end of the array
1259 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1260 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1264 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1265 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1266 tmp
= NewFDPtr
[Index
];
1267 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1268 NewFDPtr
[Index2
] = tmp
;
1277 // Just to make sure that disabled indexes are all at the end of the array
1279 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1280 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1284 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1285 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1286 tmp
= NewHDPtr
[Index
];
1287 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1288 NewHDPtr
[Index2
] = tmp
;
1297 // Just to make sure that disabled indexes are all at the end of the array
1299 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1300 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1304 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1305 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1306 tmp
= NewCDPtr
[Index
];
1307 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1308 NewCDPtr
[Index2
] = tmp
;
1317 // Just to make sure that disabled indexes are all at the end of the array
1319 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1320 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1324 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1325 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1326 tmp
= NewNETPtr
[Index
];
1327 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1328 NewNETPtr
[Index2
] = tmp
;
1337 // Just to make sure that disabled indexes are all at the end of the array
1339 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1340 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1344 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1345 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1346 tmp
= NewBEVPtr
[Index
];
1347 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1348 NewBEVPtr
[Index2
] = tmp
;
1355 SafeFreePool (DevOrder
);
1357 Status
= gRT
->SetVariable (
1359 &EfiLegacyDevOrderGuid
,
1364 SafeFreePool (NewDevOrder
);
1370 BdsSetBootPriority4SameTypeDev (
1371 IN UINT16 DeviceType
,
1372 IN OUT BBS_TABLE
*LocalBbsTable
,
1373 IN OUT UINT16
*Priority
1376 DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
1377 LocalBbsTable - BBS table instance
1378 Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
1379 priority can be used next time.
1390 DevOrder
= BdsLibGetVariableAndSize (
1392 &EfiLegacyDevOrderGuid
,
1395 if (NULL
== DevOrder
) {
1396 return EFI_OUT_OF_RESOURCES
;
1399 OrigBuffer
= DevOrder
;
1400 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1401 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1405 DevOrder
+= sizeof (BBS_TYPE
);
1406 DevOrder
+= *(UINT16
*) DevOrder
;
1409 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1410 SafeFreePool (OrigBuffer
);
1411 return EFI_NOT_FOUND
;
1414 DevOrder
+= sizeof (BBS_TYPE
);
1415 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1416 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1418 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1420 for (Index
= 0; Index
< DevCount
; Index
++) {
1421 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1423 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1426 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1431 SafeFreePool (OrigBuffer
);
1437 IN BBS_TABLE
*LocalBbsTable
1442 DEBUG ((EFI_D_ERROR
, "\n"));
1443 DEBUG ((EFI_D_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1444 DEBUG ((EFI_D_ERROR
, "=============================================\n"));
1445 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1446 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1447 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1448 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1455 " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
1457 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1458 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1459 (UINTN
) LocalBbsTable
[Idx
].Device
,
1460 (UINTN
) LocalBbsTable
[Idx
].Function
,
1461 (UINTN
) LocalBbsTable
[Idx
].Class
,
1462 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1463 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1464 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1465 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1466 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1467 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1468 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1472 DEBUG ((EFI_D_ERROR
, "\n"));
1476 BdsRefreshBbsTableForBoot (
1477 IN BDS_COMMON_OPTION
*Entry
1483 HDD_INFO
*LocalHddInfo
;
1484 BBS_TABLE
*LocalBbsTable
;
1486 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1490 UINTN BootOrderSize
;
1491 UINT8
*BootOptionVar
;
1492 UINTN BootOptionSize
;
1493 UINT16 BootOption
[100];
1496 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1500 LocalHddInfo
= NULL
;
1501 LocalBbsTable
= NULL
;
1502 DevType
= BBS_UNKNOWN
;
1504 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1505 if (EFI_ERROR (Status
)) {
1509 LegacyBios
->GetBbsInfo (
1517 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1518 // We will set them according to the settings setup by user
1520 for (Index
= 0; Index
< BbsCount
; Index
++) {
1521 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1522 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1523 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1524 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1528 // boot priority always starts at 0
1531 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1533 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1535 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1536 Status
= BdsSetBootPriority4SameTypeDev (
1541 if (EFI_ERROR (Status
)) {
1546 // we have to set the boot priority for other BBS entries with different device types
1548 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1550 &gEfiGlobalVariableGuid
,
1553 for (Index
= 0; BootOrder
&& Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
1554 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1555 BootOptionVar
= BdsLibGetVariableAndSize (
1557 &gEfiGlobalVariableGuid
,
1560 if (NULL
== BootOptionVar
) {
1564 Ptr
= BootOptionVar
;
1566 Ptr
+= sizeof (UINT32
);
1567 DevPathLen
= *(UINT16
*) Ptr
;
1568 Ptr
+= sizeof (UINT16
);
1569 Ptr
+= StrSize ((UINT16
*) Ptr
);
1570 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1571 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1572 SafeFreePool (BootOptionVar
);
1577 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1579 // We don't want to process twice for a device type
1581 SafeFreePool (BootOptionVar
);
1585 Status
= BdsSetBootPriority4SameTypeDev (
1586 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1590 SafeFreePool (BootOptionVar
);
1591 if (EFI_ERROR (Status
)) {
1597 SafeFreePool (BootOrder
);
1602 PrintBbsTable (LocalBbsTable
);