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"
19 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
[] = {
21 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
22 END_DEVICE_PATH_LENGTH
,
36 Translate the first n characters of an Ascii string to
37 Unicode characters. The count n is indicated by parameter
38 Size. If Size is greater than the length of string, then
39 the entire string is translated.
43 a - Pointer to input Ascii string.
44 Size - The number of characters to translate.
45 u - Pointer to output Unicode string buffer.
76 change a Unicode string t ASCII string
81 Lenght - most possible length of AStr
82 AStr - ASCII string to pass out
93 // just buffer copy, not character copy
95 for (Index
= 0; Index
< Length
; Index
++) {
96 *AStr
++ = (CHAR8
) *UStr
++;
103 BdsBuildLegacyDevNameString (
104 IN BBS_TABLE
*CurBBSEntry
,
107 OUT CHAR16
*BootString
120 Fmt
= L
"Primary Master %s";
127 Fmt
= L
"Primary Slave %s";
134 Fmt
= L
"Secondary Master %s";
141 Fmt
= L
"Secondary Slave %s";
149 switch (CurBBSEntry
->DeviceType
) {
170 case BBS_EMBED_NETWORK
:
184 // If current BBS entry has its description then use it.
186 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
187 if (NULL
!= StringDesc
) {
189 // Only get fisrt 32 characters, this is suggested by BBS spec
191 AsciiToUnicodeSize (StringDesc
, 32, temp
);
197 // BbsTable 16 entries are for onboard IDE.
198 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
200 if (Index
>= 5 && Index
<= 16 && CurBBSEntry
->DeviceType
== BBS_HARDDISK
) {
202 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
204 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
209 BdsCreateLegacyBootOption (
210 IN BBS_TABLE
*CurrentBbsEntry
,
211 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
213 IN OUT UINT16
**BootOrderList
,
214 IN OUT UINTN
*BootOrderListSize
220 Create a legacy boot option for the specified entry of
221 BBS table, save it as variable, and append it to the boot
226 CurrentBbsEntry - Pointer to current BBS table.
227 CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
228 Index - Index of the specified entry in BBS table.
229 BootOrderList - On input, the original boot order list.
230 On output, the new boot order list attached with the
232 BootOrderListSize - On input, the original size of boot order list.
233 - On output, the size of new boot order list.
237 EFI_SUCCESS - Boot Option successfully created.
238 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
239 Other - Error occurs while setting variable.
244 UINT16 CurrentBootOptionNo
;
245 UINT16 BootString
[10];
246 UINT16 BootDesc
[100];
247 CHAR8 HelpString
[100];
248 UINT16
*NewBootOrderList
;
253 UINT16 CurrentBbsDevPathSize
;
254 UINTN BootOrderIndex
;
255 UINTN BootOrderLastIndex
;
257 BOOLEAN IndexNotFound
;
258 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
260 if (NULL
== (*BootOrderList
)) {
261 CurrentBootOptionNo
= 0;
263 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
264 IndexNotFound
= TRUE
;
265 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
266 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
267 IndexNotFound
= FALSE
;
272 if (!IndexNotFound
) {
279 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
289 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
292 // Create new BBS device path node with description string
294 UnicodeToAscii (BootDesc
, StrSize (BootDesc
), HelpString
);
295 StringLen
= AsciiStrLen (HelpString
);
296 NewBbsDevPathNode
= EfiAllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
297 if (NewBbsDevPathNode
== NULL
) {
298 return EFI_OUT_OF_RESOURCES
;
300 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
301 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
302 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
305 // Create entire new CurrentBbsDevPath with end node
307 CurrentBbsDevPath
= AppendDevicePathNode (
309 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
311 if (CurrentBbsDevPath
== NULL
) {
312 FreePool (NewBbsDevPathNode
);
313 return EFI_OUT_OF_RESOURCES
;
316 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
318 BufferSize
= sizeof (UINT32
) +
321 CurrentBbsDevPathSize
+
325 Buffer
= EfiAllocateZeroPool (BufferSize
);
326 if (Buffer
== NULL
) {
327 FreePool (NewBbsDevPathNode
);
328 FreePool (CurrentBbsDevPath
);
329 return EFI_OUT_OF_RESOURCES
;
332 Ptr
= (UINT8
*) Buffer
;
334 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
335 Ptr
+= sizeof (UINT32
);
337 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
338 Ptr
+= sizeof (UINT16
);
345 Ptr
+= StrSize (BootDesc
);
350 CurrentBbsDevPathSize
352 Ptr
+= CurrentBbsDevPathSize
;
360 Ptr
+= sizeof (BBS_TABLE
);
361 *((UINT16
*) Ptr
) = (UINT16
) Index
;
363 Status
= gRT
->SetVariable (
365 &gEfiGlobalVariableGuid
,
371 SafeFreePool (Buffer
);
374 NewBootOrderList
= EfiAllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
375 if (NULL
== NewBootOrderList
) {
376 FreePool (NewBbsDevPathNode
);
377 FreePool (CurrentBbsDevPath
);
378 return EFI_OUT_OF_RESOURCES
;
381 if (NULL
!= *BootOrderList
) {
382 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
385 SafeFreePool (*BootOrderList
);
387 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
388 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
389 *BootOrderListSize
+= sizeof (UINT16
);
390 *BootOrderList
= NewBootOrderList
;
392 FreePool (NewBbsDevPathNode
);
393 FreePool (CurrentBbsDevPath
);
398 BdsIsLegacyBootOption (
399 IN UINT8
*BootOptionVar
,
400 OUT BBS_TABLE
**BbsEntry
,
405 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
410 Ptr
+= sizeof (UINT32
);
411 DevPathLen
= *(UINT16
*) Ptr
;
412 Ptr
+= sizeof (UINT16
);
413 Ptr
+= StrSize ((UINT16
*) Ptr
);
414 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
415 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
417 *BbsEntry
= (BBS_TABLE
*) Ptr
;
418 Ptr
+= sizeof (BBS_TABLE
);
419 *BbsIndex
= *(UINT16
*) Ptr
;
430 BdsDeleteBootOption (
431 IN UINTN OptionNumber
,
432 IN OUT UINT16
*BootOrder
,
433 IN OUT UINTN
*BootOrderSize
436 UINT16 BootOption
[100];
441 Status
= EFI_SUCCESS
;
444 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
445 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
447 // adjust boot order array
449 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
450 if (BootOrder
[Index
] == OptionNumber
) {
456 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
457 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
458 if (Index
>= Index2Del
) {
459 BootOrder
[Index
] = BootOrder
[Index
+ 1];
463 *BootOrderSize
-= sizeof (UINT16
);
471 BdsDeleteAllInvalidLegacyBootOptions (
478 Delete all the invalid legacy boot options.
486 EFI_SUCCESS - All invalide legacy boot options are deleted.
487 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
488 EFI_NOT_FOUND - Fail to retrive variable of boot order.
489 Other - Error occurs while setting variable or locating
495 UINT8
*BootOptionVar
;
497 UINTN BootOptionSize
;
501 HDD_INFO
*LocalHddInfo
;
502 BBS_TABLE
*LocalBbsTable
;
505 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
507 UINT16 BootOption
[10];
508 UINT16 BootDesc
[100];
509 BOOLEAN DescStringMatch
;
511 Status
= EFI_SUCCESS
;
517 LocalBbsTable
= NULL
;
520 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
521 if (EFI_ERROR (Status
)) {
525 LegacyBios
->GetBbsInfo (
533 BootOrder
= BdsLibGetVariableAndSize (
535 &gEfiGlobalVariableGuid
,
538 if (NULL
== BootOrder
) {
539 return EFI_NOT_FOUND
;
543 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
544 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
545 BootOptionVar
= BdsLibGetVariableAndSize (
547 &gEfiGlobalVariableGuid
,
550 if (NULL
== BootOptionVar
) {
551 SafeFreePool (BootOrder
);
552 return EFI_OUT_OF_RESOURCES
;
555 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
556 SafeFreePool (BootOptionVar
);
562 // Check if BBS Description String is changed
564 DescStringMatch
= FALSE
;
566 BdsBuildLegacyDevNameString (
567 &LocalBbsTable
[BbsIndex
],
573 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
574 DescStringMatch
= TRUE
;
577 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
578 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
579 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
585 SafeFreePool (BootOptionVar
);
589 BdsDeleteBootOption (
597 Status
= gRT
->SetVariable (
599 &gEfiGlobalVariableGuid
,
605 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
608 SafeFreePool (BootOrder
);
614 BdsFindLegacyBootOptionByDevType (
615 IN UINT16
*BootOrder
,
616 IN UINTN BootOptionNum
,
618 OUT UINT32
*Attribute
,
619 OUT UINT16
*BbsIndex
,
620 OUT UINTN
*OptionNumber
624 UINTN BootOrderIndex
;
625 UINT16 BootOption
[100];
626 UINTN BootOptionSize
;
627 UINT8
*BootOptionVar
;
634 if (NULL
== BootOrder
) {
638 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
639 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
640 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
641 BootOptionVar
= BdsLibGetVariableAndSize (
643 &gEfiGlobalVariableGuid
,
646 if (NULL
== BootOptionVar
) {
650 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
651 SafeFreePool (BootOptionVar
);
655 if (BbsEntry
->DeviceType
!= DevType
) {
656 SafeFreePool (BootOptionVar
);
660 *Attribute
= *(UINT32
*) BootOptionVar
;
661 *OptionNumber
= Index
;
663 SafeFreePool (BootOptionVar
);
671 BdsCreateOneLegacyBootOption (
672 IN BBS_TABLE
*BbsItem
,
674 IN OUT UINT16
**BootOrderList
,
675 IN OUT UINTN
*BootOrderListSize
678 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
680 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
684 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
685 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
686 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
687 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
688 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
690 DevPath
= AppendDevicePathNode (
692 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
694 if (NULL
== DevPath
) {
695 return EFI_OUT_OF_RESOURCES
;
698 Status
= BdsCreateLegacyBootOption (
705 BbsItem
->BootPriority
= 0x00;
713 BdsAddNonExistingLegacyBootOptions (
720 Add the legacy boot options from BBS table if they do not exist.
728 EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
729 others - An error occurred when creating legacy boot options.
738 HDD_INFO
*LocalHddInfo
;
739 BBS_TABLE
*LocalBbsTable
;
741 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
751 LocalBbsTable
= NULL
;
753 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
754 if (EFI_ERROR (Status
)) {
758 LegacyBios
->GetBbsInfo (
766 BootOrder
= BdsLibGetVariableAndSize (
768 &gEfiGlobalVariableGuid
,
771 if (NULL
== BootOrder
) {
775 for (Index
= 0; Index
< BbsCount
; Index
++) {
776 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
777 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
782 Ret
= BdsFindLegacyBootOptionByDevType (
784 BootOrderSize
/ sizeof (UINT16
),
785 LocalBbsTable
[Index
].DeviceType
,
795 // Not found such type of legacy device in boot options or we found but it's disabled
796 // so we have to create one and put it to the tail of boot order list
798 Status
= BdsCreateOneLegacyBootOption (
799 &LocalBbsTable
[Index
],
804 if (EFI_ERROR (Status
)) {
809 if (BootOrderSize
> 0) {
810 Status
= gRT
->SetVariable (
812 &gEfiGlobalVariableGuid
,
818 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
821 if (BootOrder
!= NULL
) {
822 SafeFreePool (BootOrder
);
830 IN BBS_TABLE
*BbsTable
,
838 for (Index
= 0; Index
< BbsCount
; Index
++) {
839 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
843 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
847 *Buf
= (UINT16
) (Index
& 0xFF);
856 IN BBS_TABLE
*BbsTable
,
878 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
881 Status
= EFI_SUCCESS
;
883 for (Index
= 0; Index
< BbsCount
; Index
++) {
884 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
888 switch (BbsTable
[Index
].DeviceType
) {
901 case BBS_EMBED_NETWORK
:
914 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
915 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
916 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
917 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
918 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
920 DevOrder
= EfiAllocateZeroPool (TotalSize
);
921 if (NULL
== DevOrder
) {
922 return EFI_OUT_OF_RESOURCES
;
927 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
928 Ptr
+= sizeof (BBS_TYPE
);
929 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
930 Ptr
+= sizeof (UINT16
);
932 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
935 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
936 Ptr
+= sizeof (BBS_TYPE
);
937 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
938 Ptr
+= sizeof (UINT16
);
940 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
943 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
944 Ptr
+= sizeof (BBS_TYPE
);
945 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
946 Ptr
+= sizeof (UINT16
);
948 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
951 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
952 Ptr
+= sizeof (BBS_TYPE
);
953 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
954 Ptr
+= sizeof (UINT16
);
956 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
959 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
960 Ptr
+= sizeof (BBS_TYPE
);
961 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
962 Ptr
+= sizeof (UINT16
);
964 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
967 Status
= gRT
->SetVariable (
969 &EfiLegacyDevOrderGuid
,
974 SafeFreePool (DevOrder
);
980 BdsUpdateLegacyDevOrder (
984 Format of LegacyDevOrder variable:
985 |-----------------------------------------------------------------------------------------------------------------
986 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
987 |-----------------------------------------------------------------------------------------------------------------
989 Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
990 Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
991 the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
998 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1002 HDD_INFO
*LocalHddInfo
;
1003 BBS_TABLE
*LocalBbsTable
;
1030 LocalHddInfo
= NULL
;
1031 LocalBbsTable
= NULL
;
1039 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1047 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1048 if (EFI_ERROR (Status
)) {
1052 LegacyBios
->GetBbsInfo (
1060 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1062 &EfiLegacyDevOrderGuid
,
1065 if (NULL
== DevOrder
) {
1066 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1069 // First we figure out how many boot devices with same device type respectively
1071 for (Index
= 0; Index
< BbsCount
; Index
++) {
1072 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1073 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1078 switch (LocalBbsTable
[Index
].DeviceType
) {
1091 case BBS_EMBED_NETWORK
:
1095 case BBS_BEV_DEVICE
:
1104 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1105 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1106 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1107 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1108 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1110 NewDevOrder
= EfiAllocateZeroPool (TotalSize
);
1111 if (NULL
== NewDevOrder
) {
1112 return EFI_OUT_OF_RESOURCES
;
1115 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1116 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1117 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1118 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1119 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1125 NewPtr
= NewDevOrder
;
1126 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1127 Ptr
+= sizeof (BBS_TYPE
);
1128 NewPtr
+= sizeof (BBS_TYPE
);
1129 Length
= *((UINT16
*) Ptr
);
1130 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1131 Ptr
+= sizeof (UINT16
);
1133 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1134 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1135 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1136 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1138 Ptr
+= sizeof (UINT16
);
1142 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1144 Ptr
+= sizeof (UINT16
);
1149 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1150 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1151 Ptr
+= sizeof (BBS_TYPE
);
1152 NewPtr
+= sizeof (BBS_TYPE
);
1153 Length
= *((UINT16
*) Ptr
);
1154 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1155 Ptr
+= sizeof (UINT16
);
1157 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1158 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1159 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1160 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1161 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1163 Ptr
+= sizeof (UINT16
);
1167 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1169 Ptr
+= sizeof (UINT16
);
1174 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1175 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1176 Ptr
+= sizeof (BBS_TYPE
);
1177 NewPtr
+= sizeof (BBS_TYPE
);
1178 Length
= *((UINT16
*) Ptr
);
1179 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1180 Ptr
+= sizeof (UINT16
);
1182 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1183 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1184 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1185 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1186 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1188 Ptr
+= sizeof (UINT16
);
1192 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1194 Ptr
+= sizeof (UINT16
);
1199 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1200 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1201 Ptr
+= sizeof (BBS_TYPE
);
1202 NewPtr
+= sizeof (BBS_TYPE
);
1203 Length
= *((UINT16
*) Ptr
);
1204 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1205 Ptr
+= sizeof (UINT16
);
1207 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1208 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1209 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1210 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1211 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1213 Ptr
+= sizeof (UINT16
);
1217 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1219 Ptr
+= sizeof (UINT16
);
1224 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1225 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1226 Ptr
+= sizeof (BBS_TYPE
);
1227 NewPtr
+= sizeof (BBS_TYPE
);
1228 Length
= *((UINT16
*) Ptr
);
1229 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1230 Ptr
+= sizeof (UINT16
);
1232 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1233 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1234 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1235 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1236 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1238 Ptr
+= sizeof (UINT16
);
1242 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1244 Ptr
+= sizeof (UINT16
);
1247 for (Index
= 0; Index
< BbsCount
; Index
++) {
1248 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1249 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1254 switch (LocalBbsTable
[Index
].DeviceType
) {
1257 NewDevPtr
= NewFDPtr
;
1262 NewDevPtr
= NewHDPtr
;
1267 NewDevPtr
= NewCDPtr
;
1270 case BBS_EMBED_NETWORK
:
1272 NewDevPtr
= NewNETPtr
;
1275 case BBS_BEV_DEVICE
:
1277 NewDevPtr
= NewBEVPtr
;
1285 // at this point we have copied those valid indexes to new buffer
1286 // and we should check if there is any new appeared boot device
1289 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1290 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1295 if (Index2
== *Idx
) {
1297 // Index2 == *Idx means we didn't find Index
1298 // so Index is a new appeared device's index in BBS table
1301 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1309 // Just to make sure that disabled indexes are all at the end of the array
1311 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1312 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1316 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1317 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1318 tmp
= NewFDPtr
[Index
];
1319 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1320 NewFDPtr
[Index2
] = tmp
;
1329 // Just to make sure that disabled indexes are all at the end of the array
1331 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1332 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1336 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1337 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1338 tmp
= NewHDPtr
[Index
];
1339 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1340 NewHDPtr
[Index2
] = tmp
;
1349 // Just to make sure that disabled indexes are all at the end of the array
1351 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1352 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1356 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1357 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1358 tmp
= NewCDPtr
[Index
];
1359 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1360 NewCDPtr
[Index2
] = tmp
;
1369 // Just to make sure that disabled indexes are all at the end of the array
1371 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1372 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1376 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1377 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1378 tmp
= NewNETPtr
[Index
];
1379 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1380 NewNETPtr
[Index2
] = tmp
;
1389 // Just to make sure that disabled indexes are all at the end of the array
1391 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1392 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1396 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1397 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1398 tmp
= NewBEVPtr
[Index
];
1399 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1400 NewBEVPtr
[Index2
] = tmp
;
1407 SafeFreePool (DevOrder
);
1409 Status
= gRT
->SetVariable (
1411 &EfiLegacyDevOrderGuid
,
1416 SafeFreePool (NewDevOrder
);
1422 BdsSetBootPriority4SameTypeDev (
1423 IN UINT16 DeviceType
,
1424 IN OUT BBS_TABLE
*LocalBbsTable
,
1425 IN OUT UINT16
*Priority
1428 DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
1429 LocalBbsTable - BBS table instance
1430 Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
1431 priority can be used next time.
1442 DevOrder
= BdsLibGetVariableAndSize (
1444 &EfiLegacyDevOrderGuid
,
1447 if (NULL
== DevOrder
) {
1448 return EFI_OUT_OF_RESOURCES
;
1451 OrigBuffer
= DevOrder
;
1452 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1453 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1457 DevOrder
+= sizeof (BBS_TYPE
);
1458 DevOrder
+= *(UINT16
*) DevOrder
;
1461 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1462 SafeFreePool (OrigBuffer
);
1463 return EFI_NOT_FOUND
;
1466 DevOrder
+= sizeof (BBS_TYPE
);
1467 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1468 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1470 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1472 for (Index
= 0; Index
< DevCount
; Index
++) {
1473 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1475 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1478 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1483 SafeFreePool (OrigBuffer
);
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"));
1528 BdsRefreshBbsTableForBoot (
1529 IN BDS_COMMON_OPTION
*Entry
1535 HDD_INFO
*LocalHddInfo
;
1536 BBS_TABLE
*LocalBbsTable
;
1538 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1542 UINTN BootOrderSize
;
1543 UINT8
*BootOptionVar
;
1544 UINTN BootOptionSize
;
1545 UINT16 BootOption
[100];
1548 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1552 LocalHddInfo
= NULL
;
1553 LocalBbsTable
= NULL
;
1554 DevType
= BBS_UNKNOWN
;
1556 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1557 if (EFI_ERROR (Status
)) {
1561 LegacyBios
->GetBbsInfo (
1569 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1570 // We will set them according to the settings setup by user
1572 for (Index
= 0; Index
< BbsCount
; Index
++) {
1573 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1574 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1575 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1576 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1580 // boot priority always starts at 0
1583 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1585 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1587 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1588 Status
= BdsSetBootPriority4SameTypeDev (
1593 if (EFI_ERROR (Status
)) {
1598 // we have to set the boot priority for other BBS entries with different device types
1600 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1602 &gEfiGlobalVariableGuid
,
1605 for (Index
= 0; BootOrder
&& Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
1606 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1607 BootOptionVar
= BdsLibGetVariableAndSize (
1609 &gEfiGlobalVariableGuid
,
1612 if (NULL
== BootOptionVar
) {
1616 Ptr
= BootOptionVar
;
1618 Ptr
+= sizeof (UINT32
);
1619 DevPathLen
= *(UINT16
*) Ptr
;
1620 Ptr
+= sizeof (UINT16
);
1621 Ptr
+= StrSize ((UINT16
*) Ptr
);
1622 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1623 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1624 SafeFreePool (BootOptionVar
);
1629 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1631 // We don't want to process twice for a device type
1633 SafeFreePool (BootOptionVar
);
1637 Status
= BdsSetBootPriority4SameTypeDev (
1638 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1642 SafeFreePool (BootOptionVar
);
1643 if (EFI_ERROR (Status
)) {
1649 SafeFreePool (BootOrder
);
1654 PrintBbsTable (LocalBbsTable
);