3 Copyright (c) 2004 - 2008, 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
,
43 Translate the first n characters of an Ascii string to
44 Unicode characters. The count n is indicated by parameter
45 Size. If Size is greater than the length of string, then
46 the entire string is translated.
50 a - Pointer to input Ascii string.
51 Size - The number of characters to translate.
52 u - Pointer to output Unicode string buffer.
83 change a Unicode string t ASCII string
88 Lenght - most possible length of AStr
89 AStr - ASCII string to pass out
100 // just buffer copy, not character copy
102 for (Index
= 0; Index
< Length
; Index
++) {
103 *AStr
++ = (CHAR8
) *UStr
++;
110 BdsBuildLegacyDevNameString (
111 IN BBS_TABLE
*CurBBSEntry
,
114 OUT CHAR16
*BootString
127 Fmt
= L
"Primary Master %s";
134 Fmt
= L
"Primary Slave %s";
141 Fmt
= L
"Secondary Master %s";
148 Fmt
= L
"Secondary Slave %s";
156 switch (CurBBSEntry
->DeviceType
) {
177 case BBS_EMBED_NETWORK
:
191 // If current BBS entry has its description then use it.
193 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
194 if (NULL
!= StringDesc
) {
196 // Only get fisrt 32 characters, this is suggested by BBS spec
198 AsciiToUnicodeSize (StringDesc
, 32, temp
);
204 // BbsTable 16 entries are for onboard IDE.
205 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
207 if (Index
>= 5 && Index
<= 16 && CurBBSEntry
->DeviceType
== BBS_HARDDISK
) {
209 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
, Index
- 5);
211 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
216 BdsCreateLegacyBootOption (
217 IN BBS_TABLE
*CurrentBbsEntry
,
218 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
220 IN OUT UINT16
**BootOrderList
,
221 IN OUT UINTN
*BootOrderListSize
227 Create a legacy boot option for the specified entry of
228 BBS table, save it as variable, and append it to the boot
233 CurrentBbsEntry - Pointer to current BBS table.
234 CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
235 Index - Index of the specified entry in BBS table.
236 BootOrderList - On input, the original boot order list.
237 On output, the new boot order list attached with the
239 BootOrderListSize - On input, the original size of boot order list.
240 - On output, the size of new boot order list.
244 EFI_SUCCESS - Boot Option successfully created.
245 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
246 Other - Error occurs while setting variable.
251 UINT16 CurrentBootOptionNo
;
252 UINT16 BootString
[10];
253 UINT16 BootDesc
[100];
254 CHAR8 HelpString
[100];
255 UINT16
*NewBootOrderList
;
260 UINT16 CurrentBbsDevPathSize
;
261 UINTN BootOrderIndex
;
262 UINTN BootOrderLastIndex
;
264 BOOLEAN IndexNotFound
;
265 BBS_BBS_DEVICE_PATH
*NewBbsDevPathNode
;
267 if (NULL
== (*BootOrderList
)) {
268 CurrentBootOptionNo
= 0;
270 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
271 IndexNotFound
= TRUE
;
272 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
273 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
274 IndexNotFound
= FALSE
;
279 if (!IndexNotFound
) {
286 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
296 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
299 // Create new BBS device path node with description string
301 UnicodeToAscii (BootDesc
, StrSize (BootDesc
), HelpString
);
302 StringLen
= AsciiStrLen (HelpString
);
303 NewBbsDevPathNode
= EfiAllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
304 if (NewBbsDevPathNode
== NULL
) {
305 return EFI_OUT_OF_RESOURCES
;
307 CopyMem (NewBbsDevPathNode
, CurrentBbsDevPath
, sizeof (BBS_BBS_DEVICE_PATH
));
308 CopyMem (NewBbsDevPathNode
->String
, HelpString
, StringLen
+ 1);
309 SetDevicePathNodeLength (&(NewBbsDevPathNode
->Header
), sizeof (BBS_BBS_DEVICE_PATH
) + StringLen
);
312 // Create entire new CurrentBbsDevPath with end node
314 CurrentBbsDevPath
= AppendDevicePathNode (
316 (EFI_DEVICE_PATH_PROTOCOL
*) NewBbsDevPathNode
318 if (CurrentBbsDevPath
== NULL
) {
319 FreePool (NewBbsDevPathNode
);
320 return EFI_OUT_OF_RESOURCES
;
323 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
325 BufferSize
= sizeof (UINT32
) +
328 CurrentBbsDevPathSize
+
332 Buffer
= EfiAllocateZeroPool (BufferSize
);
333 if (Buffer
== NULL
) {
334 FreePool (NewBbsDevPathNode
);
335 FreePool (CurrentBbsDevPath
);
336 return EFI_OUT_OF_RESOURCES
;
339 Ptr
= (UINT8
*) Buffer
;
341 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
342 Ptr
+= sizeof (UINT32
);
344 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
345 Ptr
+= sizeof (UINT16
);
352 Ptr
+= StrSize (BootDesc
);
357 CurrentBbsDevPathSize
359 Ptr
+= CurrentBbsDevPathSize
;
367 Ptr
+= sizeof (BBS_TABLE
);
368 *((UINT16
*) Ptr
) = (UINT16
) Index
;
370 Status
= gRT
->SetVariable (
372 &gEfiGlobalVariableGuid
,
378 SafeFreePool (Buffer
);
381 NewBootOrderList
= EfiAllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
382 if (NULL
== NewBootOrderList
) {
383 FreePool (NewBbsDevPathNode
);
384 FreePool (CurrentBbsDevPath
);
385 return EFI_OUT_OF_RESOURCES
;
388 if (NULL
!= *BootOrderList
) {
389 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
392 SafeFreePool (*BootOrderList
);
394 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
395 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
396 *BootOrderListSize
+= sizeof (UINT16
);
397 *BootOrderList
= NewBootOrderList
;
399 FreePool (NewBbsDevPathNode
);
400 FreePool (CurrentBbsDevPath
);
405 BdsIsLegacyBootOption (
406 IN UINT8
*BootOptionVar
,
407 OUT BBS_TABLE
**BbsEntry
,
412 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
417 Ptr
+= sizeof (UINT32
);
418 DevPathLen
= *(UINT16
*) Ptr
;
419 Ptr
+= sizeof (UINT16
);
420 Ptr
+= StrSize ((UINT16
*) Ptr
);
421 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
422 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
424 *BbsEntry
= (BBS_TABLE
*) Ptr
;
425 Ptr
+= sizeof (BBS_TABLE
);
426 *BbsIndex
= *(UINT16
*) Ptr
;
437 BdsDeleteBootOption (
438 IN UINTN OptionNumber
,
439 IN OUT UINT16
*BootOrder
,
440 IN OUT UINTN
*BootOrderSize
443 UINT16 BootOption
[100];
448 Status
= EFI_SUCCESS
;
451 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
452 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
454 // adjust boot order array
456 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
457 if (BootOrder
[Index
] == OptionNumber
) {
463 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
464 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
465 if (Index
>= Index2Del
) {
466 BootOrder
[Index
] = BootOrder
[Index
+ 1];
470 *BootOrderSize
-= sizeof (UINT16
);
478 BdsDeleteAllInvalidLegacyBootOptions (
485 Delete all the invalid legacy boot options.
493 EFI_SUCCESS - All invalide legacy boot options are deleted.
494 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
495 EFI_NOT_FOUND - Fail to retrive variable of boot order.
496 Other - Error occurs while setting variable or locating
502 UINT8
*BootOptionVar
;
504 UINTN BootOptionSize
;
508 HDD_INFO
*LocalHddInfo
;
509 BBS_TABLE
*LocalBbsTable
;
512 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
514 UINT16 BootOption
[10];
515 UINT16 BootDesc
[100];
516 BOOLEAN DescStringMatch
;
518 Status
= EFI_SUCCESS
;
524 LocalBbsTable
= NULL
;
527 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
528 if (EFI_ERROR (Status
)) {
532 LegacyBios
->GetBbsInfo (
540 BootOrder
= BdsLibGetVariableAndSize (
542 &gEfiGlobalVariableGuid
,
545 if (NULL
== BootOrder
) {
546 return EFI_NOT_FOUND
;
550 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
551 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
552 BootOptionVar
= BdsLibGetVariableAndSize (
554 &gEfiGlobalVariableGuid
,
557 if (NULL
== BootOptionVar
) {
558 SafeFreePool (BootOrder
);
559 return EFI_OUT_OF_RESOURCES
;
562 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
563 SafeFreePool (BootOptionVar
);
569 // Check if BBS Description String is changed
571 DescStringMatch
= FALSE
;
573 BdsBuildLegacyDevNameString (
574 &LocalBbsTable
[BbsIndex
],
580 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
581 DescStringMatch
= TRUE
;
584 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
585 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)) &&
586 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
592 SafeFreePool (BootOptionVar
);
596 BdsDeleteBootOption (
604 Status
= gRT
->SetVariable (
606 &gEfiGlobalVariableGuid
,
612 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
615 SafeFreePool (BootOrder
);
621 BdsFindLegacyBootOptionByDevType (
622 IN UINT16
*BootOrder
,
623 IN UINTN BootOptionNum
,
625 OUT UINT32
*Attribute
,
626 OUT UINT16
*BbsIndex
,
627 OUT UINTN
*OptionNumber
631 UINTN BootOrderIndex
;
632 UINT16 BootOption
[100];
633 UINTN BootOptionSize
;
634 UINT8
*BootOptionVar
;
641 if (NULL
== BootOrder
) {
645 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
646 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
647 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
648 BootOptionVar
= BdsLibGetVariableAndSize (
650 &gEfiGlobalVariableGuid
,
653 if (NULL
== BootOptionVar
) {
657 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
658 SafeFreePool (BootOptionVar
);
662 if (BbsEntry
->DeviceType
!= DevType
) {
663 SafeFreePool (BootOptionVar
);
667 *Attribute
= *(UINT32
*) BootOptionVar
;
668 *OptionNumber
= Index
;
670 SafeFreePool (BootOptionVar
);
678 BdsCreateOneLegacyBootOption (
679 IN BBS_TABLE
*BbsItem
,
681 IN OUT UINT16
**BootOrderList
,
682 IN OUT UINTN
*BootOrderListSize
685 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
687 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
691 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
692 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
693 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
694 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
695 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
697 DevPath
= AppendDevicePathNode (
699 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
701 if (NULL
== DevPath
) {
702 return EFI_OUT_OF_RESOURCES
;
705 Status
= BdsCreateLegacyBootOption (
712 BbsItem
->BootPriority
= 0x00;
720 BdsAddNonExistingLegacyBootOptions (
727 Add the legacy boot options from BBS table if they do not exist.
735 EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
736 others - An error occurred when creating legacy boot options.
745 HDD_INFO
*LocalHddInfo
;
746 BBS_TABLE
*LocalBbsTable
;
748 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
758 LocalBbsTable
= NULL
;
760 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
761 if (EFI_ERROR (Status
)) {
765 LegacyBios
->GetBbsInfo (
773 BootOrder
= BdsLibGetVariableAndSize (
775 &gEfiGlobalVariableGuid
,
778 if (NULL
== BootOrder
) {
782 for (Index
= 0; Index
< BbsCount
; Index
++) {
783 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
784 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
789 Ret
= BdsFindLegacyBootOptionByDevType (
791 BootOrderSize
/ sizeof (UINT16
),
792 LocalBbsTable
[Index
].DeviceType
,
802 // Not found such type of legacy device in boot options or we found but it's disabled
803 // so we have to create one and put it to the tail of boot order list
805 Status
= BdsCreateOneLegacyBootOption (
806 &LocalBbsTable
[Index
],
811 if (EFI_ERROR (Status
)) {
816 if (BootOrderSize
> 0) {
817 Status
= gRT
->SetVariable (
819 &gEfiGlobalVariableGuid
,
825 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
828 if (BootOrder
!= NULL
) {
829 SafeFreePool (BootOrder
);
837 IN BBS_TABLE
*BbsTable
,
845 for (Index
= 0; Index
< BbsCount
; Index
++) {
846 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
850 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
854 *Buf
= (UINT16
) (Index
& 0xFF);
863 IN BBS_TABLE
*BbsTable
,
885 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
888 Status
= EFI_SUCCESS
;
890 for (Index
= 0; Index
< BbsCount
; Index
++) {
891 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
895 switch (BbsTable
[Index
].DeviceType
) {
908 case BBS_EMBED_NETWORK
:
921 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
922 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
923 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
924 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
925 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
927 DevOrder
= EfiAllocateZeroPool (TotalSize
);
928 if (NULL
== DevOrder
) {
929 return EFI_OUT_OF_RESOURCES
;
934 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
935 Ptr
+= sizeof (BBS_TYPE
);
936 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
937 Ptr
+= sizeof (UINT16
);
939 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
942 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
943 Ptr
+= sizeof (BBS_TYPE
);
944 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
945 Ptr
+= sizeof (UINT16
);
947 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
950 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
951 Ptr
+= sizeof (BBS_TYPE
);
952 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
953 Ptr
+= sizeof (UINT16
);
955 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
958 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
959 Ptr
+= sizeof (BBS_TYPE
);
960 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
961 Ptr
+= sizeof (UINT16
);
963 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
966 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
967 Ptr
+= sizeof (BBS_TYPE
);
968 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
969 Ptr
+= sizeof (UINT16
);
971 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
974 Status
= gRT
->SetVariable (
976 &EfiLegacyDevOrderGuid
,
981 SafeFreePool (DevOrder
);
987 BdsUpdateLegacyDevOrder (
991 Format of LegacyDevOrder variable:
992 |-----------------------------------------------------------------------------------------------------------------
993 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
994 |-----------------------------------------------------------------------------------------------------------------
996 Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
997 Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
998 the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
1005 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1009 HDD_INFO
*LocalHddInfo
;
1010 BBS_TABLE
*LocalBbsTable
;
1037 LocalHddInfo
= NULL
;
1038 LocalBbsTable
= NULL
;
1046 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
1054 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1055 if (EFI_ERROR (Status
)) {
1059 LegacyBios
->GetBbsInfo (
1067 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1069 &EfiLegacyDevOrderGuid
,
1072 if (NULL
== DevOrder
) {
1073 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1076 // First we figure out how many boot devices with same device type respectively
1078 for (Index
= 0; Index
< BbsCount
; Index
++) {
1079 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1080 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1085 switch (LocalBbsTable
[Index
].DeviceType
) {
1098 case BBS_EMBED_NETWORK
:
1102 case BBS_BEV_DEVICE
:
1111 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1112 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1113 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1114 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1115 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1117 NewDevOrder
= EfiAllocateZeroPool (TotalSize
);
1118 if (NULL
== NewDevOrder
) {
1119 return EFI_OUT_OF_RESOURCES
;
1122 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1123 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1124 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1125 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1126 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1132 NewPtr
= NewDevOrder
;
1133 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1134 Ptr
+= sizeof (BBS_TYPE
);
1135 NewPtr
+= sizeof (BBS_TYPE
);
1136 Length
= *((UINT16
*) Ptr
);
1137 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1138 Ptr
+= sizeof (UINT16
);
1140 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1141 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1142 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1143 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1145 Ptr
+= sizeof (UINT16
);
1149 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1151 Ptr
+= sizeof (UINT16
);
1156 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1157 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1158 Ptr
+= sizeof (BBS_TYPE
);
1159 NewPtr
+= sizeof (BBS_TYPE
);
1160 Length
= *((UINT16
*) Ptr
);
1161 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1162 Ptr
+= sizeof (UINT16
);
1164 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1165 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1166 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1167 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1168 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1170 Ptr
+= sizeof (UINT16
);
1174 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1176 Ptr
+= sizeof (UINT16
);
1181 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1182 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1183 Ptr
+= sizeof (BBS_TYPE
);
1184 NewPtr
+= sizeof (BBS_TYPE
);
1185 Length
= *((UINT16
*) Ptr
);
1186 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1187 Ptr
+= sizeof (UINT16
);
1189 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1190 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1191 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1192 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1193 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1195 Ptr
+= sizeof (UINT16
);
1199 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1201 Ptr
+= sizeof (UINT16
);
1206 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1207 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1208 Ptr
+= sizeof (BBS_TYPE
);
1209 NewPtr
+= sizeof (BBS_TYPE
);
1210 Length
= *((UINT16
*) Ptr
);
1211 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1212 Ptr
+= sizeof (UINT16
);
1214 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1215 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1216 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1217 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1218 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1220 Ptr
+= sizeof (UINT16
);
1224 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1226 Ptr
+= sizeof (UINT16
);
1231 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1232 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1233 Ptr
+= sizeof (BBS_TYPE
);
1234 NewPtr
+= sizeof (BBS_TYPE
);
1235 Length
= *((UINT16
*) Ptr
);
1236 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1237 Ptr
+= sizeof (UINT16
);
1239 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1240 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1241 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1242 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1243 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1245 Ptr
+= sizeof (UINT16
);
1249 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1251 Ptr
+= sizeof (UINT16
);
1254 for (Index
= 0; Index
< BbsCount
; Index
++) {
1255 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1256 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
1261 switch (LocalBbsTable
[Index
].DeviceType
) {
1264 NewDevPtr
= NewFDPtr
;
1269 NewDevPtr
= NewHDPtr
;
1274 NewDevPtr
= NewCDPtr
;
1277 case BBS_EMBED_NETWORK
:
1279 NewDevPtr
= NewNETPtr
;
1282 case BBS_BEV_DEVICE
:
1284 NewDevPtr
= NewBEVPtr
;
1292 // at this point we have copied those valid indexes to new buffer
1293 // and we should check if there is any new appeared boot device
1296 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1297 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1302 if (Index2
== *Idx
) {
1304 // Index2 == *Idx means we didn't find Index
1305 // so Index is a new appeared device's index in BBS table
1308 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1316 // Just to make sure that disabled indexes are all at the end of the array
1318 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1319 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1323 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1324 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1325 tmp
= NewFDPtr
[Index
];
1326 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1327 NewFDPtr
[Index2
] = tmp
;
1336 // Just to make sure that disabled indexes are all at the end of the array
1338 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1339 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1343 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1344 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1345 tmp
= NewHDPtr
[Index
];
1346 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1347 NewHDPtr
[Index2
] = tmp
;
1356 // Just to make sure that disabled indexes are all at the end of the array
1358 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1359 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1363 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1364 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1365 tmp
= NewCDPtr
[Index
];
1366 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1367 NewCDPtr
[Index2
] = tmp
;
1376 // Just to make sure that disabled indexes are all at the end of the array
1378 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1379 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1383 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1384 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1385 tmp
= NewNETPtr
[Index
];
1386 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1387 NewNETPtr
[Index2
] = tmp
;
1396 // Just to make sure that disabled indexes are all at the end of the array
1398 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1399 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1403 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1404 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1405 tmp
= NewBEVPtr
[Index
];
1406 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1407 NewBEVPtr
[Index2
] = tmp
;
1414 SafeFreePool (DevOrder
);
1416 Status
= gRT
->SetVariable (
1418 &EfiLegacyDevOrderGuid
,
1423 SafeFreePool (NewDevOrder
);
1429 BdsSetBootPriority4SameTypeDev (
1430 IN UINT16 DeviceType
,
1431 IN OUT BBS_TABLE
*LocalBbsTable
,
1432 IN OUT UINT16
*Priority
1435 DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
1436 LocalBbsTable - BBS table instance
1437 Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
1438 priority can be used next time.
1449 DevOrder
= BdsLibGetVariableAndSize (
1451 &EfiLegacyDevOrderGuid
,
1454 if (NULL
== DevOrder
) {
1455 return EFI_OUT_OF_RESOURCES
;
1458 OrigBuffer
= DevOrder
;
1459 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1460 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1464 DevOrder
+= sizeof (BBS_TYPE
);
1465 DevOrder
+= *(UINT16
*) DevOrder
;
1468 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1469 SafeFreePool (OrigBuffer
);
1470 return EFI_NOT_FOUND
;
1473 DevOrder
+= sizeof (BBS_TYPE
);
1474 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1475 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1477 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1479 for (Index
= 0; Index
< DevCount
; Index
++) {
1480 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1482 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1485 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1490 SafeFreePool (OrigBuffer
);
1496 IN BBS_TABLE
*LocalBbsTable
1501 DEBUG ((DEBUG_ERROR
, "\n"));
1502 DEBUG ((DEBUG_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1503 DEBUG ((DEBUG_ERROR
, "=============================================\n"));
1504 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1505 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1506 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1507 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1514 " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
1516 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1517 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1518 (UINTN
) LocalBbsTable
[Idx
].Device
,
1519 (UINTN
) LocalBbsTable
[Idx
].Function
,
1520 (UINTN
) LocalBbsTable
[Idx
].Class
,
1521 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1522 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1523 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1524 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1525 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1526 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1527 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1531 DEBUG ((DEBUG_ERROR
, "\n"));
1535 BdsRefreshBbsTableForBoot (
1536 IN BDS_COMMON_OPTION
*Entry
1542 HDD_INFO
*LocalHddInfo
;
1543 BBS_TABLE
*LocalBbsTable
;
1545 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1549 UINTN BootOrderSize
;
1550 UINT8
*BootOptionVar
;
1551 UINTN BootOptionSize
;
1552 UINT16 BootOption
[100];
1555 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1559 LocalHddInfo
= NULL
;
1560 LocalBbsTable
= NULL
;
1561 DevType
= BBS_UNKNOWN
;
1563 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, (VOID
**) &LegacyBios
);
1564 if (EFI_ERROR (Status
)) {
1568 LegacyBios
->GetBbsInfo (
1576 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1577 // We will set them according to the settings setup by user
1579 for (Index
= 0; Index
< BbsCount
; Index
++) {
1580 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1581 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1582 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1583 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1587 // boot priority always starts at 0
1590 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1592 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1594 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1595 Status
= BdsSetBootPriority4SameTypeDev (
1600 if (EFI_ERROR (Status
)) {
1605 // we have to set the boot priority for other BBS entries with different device types
1607 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1609 &gEfiGlobalVariableGuid
,
1612 for (Index
= 0; BootOrder
&& Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
1613 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1614 BootOptionVar
= BdsLibGetVariableAndSize (
1616 &gEfiGlobalVariableGuid
,
1619 if (NULL
== BootOptionVar
) {
1623 Ptr
= BootOptionVar
;
1625 Ptr
+= sizeof (UINT32
);
1626 DevPathLen
= *(UINT16
*) Ptr
;
1627 Ptr
+= sizeof (UINT16
);
1628 Ptr
+= StrSize ((UINT16
*) Ptr
);
1629 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1630 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1631 SafeFreePool (BootOptionVar
);
1636 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1638 // We don't want to process twice for a device type
1640 SafeFreePool (BootOptionVar
);
1644 Status
= BdsSetBootPriority4SameTypeDev (
1645 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1649 SafeFreePool (BootOptionVar
);
1650 if (EFI_ERROR (Status
)) {
1656 SafeFreePool (BootOrder
);
1661 PrintBbsTable (LocalBbsTable
);