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
,
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.
75 BdsBuildLegacyDevNameString (
76 IN BBS_TABLE
*CurBBSEntry
,
79 OUT CHAR16
*BootString
92 Fmt
= L
"Primary Master %s";
99 Fmt
= L
"Primary Slave %s";
106 Fmt
= L
"Secondary Master %s";
113 Fmt
= L
"Secondary Slave %s";
121 switch (CurBBSEntry
->DeviceType
) {
142 case BBS_EMBED_NETWORK
:
156 // If current BBS entry has its description then use it.
158 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
159 if (NULL
!= StringDesc
) {
161 // Only get fisrt 32 characters, this is suggested by BBS spec
163 AsciiToUnicodeSize (StringDesc
, 32, temp
);
168 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
172 BdsCreateLegacyBootOption (
173 IN BBS_TABLE
*CurrentBbsEntry
,
174 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
176 IN OUT UINT16
**BootOrderList
,
177 IN OUT UINTN
*BootOrderListSize
183 Create a legacy boot option for the specified entry of
184 BBS table, save it as variable, and append it to the boot
189 CurrentBbsEntry - Pointer to current BBS table.
190 CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
191 Index - Index of the specified entry in BBS table.
192 BootOrderList - On input, the original boot order list.
193 On output, the new boot order list attached with the
195 BootOrderListSize - On input, the original size of boot order list.
196 - On output, the size of new boot order list.
200 EFI_SUCCESS - Boot Option successfully created.
201 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
202 Other - Error occurs while setting variable.
207 UINT16 CurrentBootOptionNo
;
208 UINT16 BootString
[10];
209 UINT16 BootDesc
[100];
210 UINT16
*NewBootOrderList
;
214 UINT16 CurrentBbsDevPathSize
;
215 UINTN BootOrderIndex
;
216 UINTN BootOrderLastIndex
;
218 BOOLEAN IndexNotFound
;
220 if (NULL
== (*BootOrderList
)) {
221 CurrentBootOptionNo
= 0;
223 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
224 IndexNotFound
= TRUE
;
225 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
226 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
227 IndexNotFound
= FALSE
;
232 if (!IndexNotFound
) {
239 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
249 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
251 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
253 BufferSize
= sizeof (UINT32
) +
256 CurrentBbsDevPathSize
+
260 Buffer
= AllocateZeroPool (BufferSize
);
261 if (Buffer
== NULL
) {
262 return EFI_OUT_OF_RESOURCES
;
265 Ptr
= (UINT8
*) Buffer
;
267 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
268 Ptr
+= sizeof (UINT32
);
270 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
271 Ptr
+= sizeof (UINT16
);
278 Ptr
+= StrSize (BootDesc
);
283 CurrentBbsDevPathSize
285 Ptr
+= CurrentBbsDevPathSize
;
293 Ptr
+= sizeof (BBS_TABLE
);
294 *((UINT16
*) Ptr
) = (UINT16
) Index
;
296 Status
= gRT
->SetVariable (
298 &gEfiGlobalVariableGuid
,
304 SafeFreePool (Buffer
);
307 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
308 if (NULL
== NewBootOrderList
) {
309 return EFI_OUT_OF_RESOURCES
;
312 if (NULL
!= *BootOrderList
) {
313 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
316 SafeFreePool (*BootOrderList
);
318 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
319 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
320 *BootOrderListSize
+= sizeof (UINT16
);
321 *BootOrderList
= NewBootOrderList
;
327 BdsIsLegacyBootOption (
328 IN UINT8
*BootOptionVar
,
329 OUT BBS_TABLE
**BbsEntry
,
334 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
339 Ptr
+= sizeof (UINT32
);
340 DevPathLen
= *(UINT16
*) Ptr
;
341 Ptr
+= sizeof (UINT16
);
342 Ptr
+= StrSize ((UINT16
*) Ptr
);
343 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
344 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
346 *BbsEntry
= (BBS_TABLE
*) Ptr
;
347 Ptr
+= sizeof (BBS_TABLE
);
348 *BbsIndex
= *(UINT16
*) Ptr
;
359 BdsDeleteBootOption (
360 IN UINTN OptionNumber
,
361 IN OUT UINT16
*BootOrder
,
362 IN OUT UINTN
*BootOrderSize
365 UINT16 BootOption
[100];
370 Status
= EFI_SUCCESS
;
373 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
374 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
376 // adjust boot order array
378 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
379 if (BootOrder
[Index
] == OptionNumber
) {
385 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
386 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
387 if (Index
>= Index2Del
) {
388 BootOrder
[Index
] = BootOrder
[Index
+ 1];
392 *BootOrderSize
-= sizeof (UINT16
);
400 BdsDeleteAllInvalidLegacyBootOptions (
407 Delete all the invalid legacy boot options.
415 EFI_SUCCESS - All invalide legacy boot options are deleted.
416 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
417 EFI_NOT_FOUND - Fail to retrive variable of boot order.
418 Other - Error occurs while setting variable or locating
424 UINT8
*BootOptionVar
;
426 UINTN BootOptionSize
;
430 HDD_INFO
*LocalHddInfo
;
431 BBS_TABLE
*LocalBbsTable
;
434 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
436 UINT16 BootOption
[10];
437 UINT16 BootDesc
[100];
438 BOOLEAN DescStringMatch
;
440 Status
= EFI_SUCCESS
;
446 LocalBbsTable
= NULL
;
449 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
450 if (EFI_ERROR (Status
)) {
454 LegacyBios
->GetBbsInfo (
462 BootOrder
= BdsLibGetVariableAndSize (
464 &gEfiGlobalVariableGuid
,
467 if (NULL
== BootOrder
) {
468 return EFI_NOT_FOUND
;
472 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
473 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
474 BootOptionVar
= BdsLibGetVariableAndSize (
476 &gEfiGlobalVariableGuid
,
479 if (NULL
== BootOptionVar
) {
480 SafeFreePool (BootOrder
);
481 return EFI_OUT_OF_RESOURCES
;
484 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
485 SafeFreePool (BootOptionVar
);
491 // Check if BBS Description String is changed
493 DescStringMatch
= FALSE
;
495 BdsBuildLegacyDevNameString (
496 &LocalBbsTable
[BbsIndex
],
502 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
503 DescStringMatch
= TRUE
;
506 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
507 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
508 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_LOWEST_PRIORITY
)) &&
509 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
515 SafeFreePool (BootOptionVar
);
519 BdsDeleteBootOption (
527 Status
= gRT
->SetVariable (
529 &gEfiGlobalVariableGuid
,
535 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
538 SafeFreePool (BootOrder
);
544 BdsFindLegacyBootOptionByDevType (
545 IN UINT16
*BootOrder
,
546 IN UINTN BootOptionNum
,
548 OUT UINT32
*Attribute
,
549 OUT UINT16
*BbsIndex
,
550 OUT UINTN
*OptionNumber
554 UINTN BootOrderIndex
;
555 UINT16 BootOption
[100];
556 UINTN BootOptionSize
;
557 UINT8
*BootOptionVar
;
564 if (NULL
== BootOrder
) {
568 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
569 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
570 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
571 BootOptionVar
= BdsLibGetVariableAndSize (
573 &gEfiGlobalVariableGuid
,
576 if (NULL
== BootOptionVar
) {
580 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
581 SafeFreePool (BootOptionVar
);
585 if (BbsEntry
->DeviceType
!= DevType
) {
586 SafeFreePool (BootOptionVar
);
590 *Attribute
= *(UINT32
*) BootOptionVar
;
591 *OptionNumber
= Index
;
593 SafeFreePool (BootOptionVar
);
601 BdsCreateOneLegacyBootOption (
602 IN BBS_TABLE
*BbsItem
,
604 IN OUT UINT16
**BootOrderList
,
605 IN OUT UINTN
*BootOrderListSize
608 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
610 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
614 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
615 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
616 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
617 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
618 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
620 DevPath
= AppendDevicePathNode (
622 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
624 if (NULL
== DevPath
) {
625 return EFI_OUT_OF_RESOURCES
;
628 Status
= BdsCreateLegacyBootOption (
635 BbsItem
->BootPriority
= 0x00;
637 gBS
->FreePool (DevPath
);
643 BdsAddNonExistingLegacyBootOptions (
650 Add the legacy boot options from BBS table if they do not exist.
658 EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
659 others - An error occurred when creating legacy boot options.
668 HDD_INFO
*LocalHddInfo
;
669 BBS_TABLE
*LocalBbsTable
;
671 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
681 LocalBbsTable
= NULL
;
683 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
684 if (EFI_ERROR (Status
)) {
688 LegacyBios
->GetBbsInfo (
696 BootOrder
= BdsLibGetVariableAndSize (
698 &gEfiGlobalVariableGuid
,
701 if (NULL
== BootOrder
) {
705 for (Index
= 0; Index
< BbsCount
; Index
++) {
706 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
707 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
712 Ret
= BdsFindLegacyBootOptionByDevType (
714 BootOrderSize
/ sizeof (UINT16
),
715 LocalBbsTable
[Index
].DeviceType
,
720 if (Ret
&& (Attribute
& LOAD_OPTION_ACTIVE
) != 0) {
725 if (Index
!= BbsIndex
) {
726 BdsDeleteBootOption (
736 // Not found such type of legacy device in boot options or we found but it's disabled
737 // so we have to create one and put it to the tail of boot order list
739 Status
= BdsCreateOneLegacyBootOption (
740 &LocalBbsTable
[Index
],
745 if (EFI_ERROR (Status
)) {
750 if (BootOrderSize
> 0) {
751 Status
= gRT
->SetVariable (
753 &gEfiGlobalVariableGuid
,
759 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
762 if (BootOrder
!= NULL
) {
763 SafeFreePool (BootOrder
);
771 IN BBS_TABLE
*BbsTable
,
779 for (Index
= 0; Index
< BbsCount
; Index
++) {
780 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
784 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
788 *Buf
= (UINT16
) (Index
& 0xFF);
797 IN BBS_TABLE
*BbsTable
,
819 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
822 Status
= EFI_SUCCESS
;
824 for (Index
= 0; Index
< BbsCount
; Index
++) {
825 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
829 switch (BbsTable
[Index
].DeviceType
) {
842 case BBS_EMBED_NETWORK
:
855 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
856 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
857 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
858 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
859 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
861 DevOrder
= AllocateZeroPool (TotalSize
);
862 if (NULL
== DevOrder
) {
863 return EFI_OUT_OF_RESOURCES
;
868 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
869 Ptr
+= sizeof (BBS_TYPE
);
870 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
871 Ptr
+= sizeof (UINT16
);
873 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
876 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
877 Ptr
+= sizeof (BBS_TYPE
);
878 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
879 Ptr
+= sizeof (UINT16
);
881 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
884 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
885 Ptr
+= sizeof (BBS_TYPE
);
886 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
887 Ptr
+= sizeof (UINT16
);
889 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
892 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
893 Ptr
+= sizeof (BBS_TYPE
);
894 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
895 Ptr
+= sizeof (UINT16
);
897 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
900 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
901 Ptr
+= sizeof (BBS_TYPE
);
902 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
903 Ptr
+= sizeof (UINT16
);
905 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
908 Status
= gRT
->SetVariable (
910 &EfiLegacyDevOrderGuid
,
915 SafeFreePool (DevOrder
);
921 BdsUpdateLegacyDevOrder (
925 Format of LegacyDevOrder variable:
926 |-----------------------------------------------------------------------------------------------------------------
927 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
928 |-----------------------------------------------------------------------------------------------------------------
930 Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
931 Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
932 the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
939 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
943 HDD_INFO
*LocalHddInfo
;
944 BBS_TABLE
*LocalBbsTable
;
972 LocalBbsTable
= NULL
;
980 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
988 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
989 if (EFI_ERROR (Status
)) {
993 LegacyBios
->GetBbsInfo (
1001 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1003 &EfiLegacyDevOrderGuid
,
1006 if (NULL
== DevOrder
) {
1007 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1010 // First we figure out how many boot devices with same device type respectively
1012 for (Index
= 0; Index
< BbsCount
; Index
++) {
1013 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1014 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1015 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1020 switch (LocalBbsTable
[Index
].DeviceType
) {
1033 case BBS_EMBED_NETWORK
:
1037 case BBS_BEV_DEVICE
:
1046 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1047 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1048 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1049 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1050 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1052 NewDevOrder
= AllocateZeroPool (TotalSize
);
1053 if (NULL
== NewDevOrder
) {
1054 return EFI_OUT_OF_RESOURCES
;
1057 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1058 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1059 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1060 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1061 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1067 NewPtr
= NewDevOrder
;
1068 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1069 Ptr
+= sizeof (BBS_TYPE
);
1070 NewPtr
+= sizeof (BBS_TYPE
);
1071 Length
= *((UINT16
*) Ptr
);
1072 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1073 Ptr
+= sizeof (UINT16
);
1075 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1076 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1077 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1078 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1079 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1081 Ptr
+= sizeof (UINT16
);
1085 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1087 Ptr
+= sizeof (UINT16
);
1092 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1093 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1094 Ptr
+= sizeof (BBS_TYPE
);
1095 NewPtr
+= sizeof (BBS_TYPE
);
1096 Length
= *((UINT16
*) Ptr
);
1097 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1098 Ptr
+= sizeof (UINT16
);
1100 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1101 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1102 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1103 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1104 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1106 Ptr
+= sizeof (UINT16
);
1110 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1112 Ptr
+= sizeof (UINT16
);
1117 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1118 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1119 Ptr
+= sizeof (BBS_TYPE
);
1120 NewPtr
+= sizeof (BBS_TYPE
);
1121 Length
= *((UINT16
*) Ptr
);
1122 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1123 Ptr
+= sizeof (UINT16
);
1125 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1126 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1127 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1128 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1129 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1131 Ptr
+= sizeof (UINT16
);
1135 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1137 Ptr
+= sizeof (UINT16
);
1142 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1143 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1144 Ptr
+= sizeof (BBS_TYPE
);
1145 NewPtr
+= sizeof (BBS_TYPE
);
1146 Length
= *((UINT16
*) Ptr
);
1147 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1148 Ptr
+= sizeof (UINT16
);
1150 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1151 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1152 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1153 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1154 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1156 Ptr
+= sizeof (UINT16
);
1160 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1162 Ptr
+= sizeof (UINT16
);
1167 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1168 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1169 Ptr
+= sizeof (BBS_TYPE
);
1170 NewPtr
+= sizeof (BBS_TYPE
);
1171 Length
= *((UINT16
*) Ptr
);
1172 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1173 Ptr
+= sizeof (UINT16
);
1175 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1176 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1177 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1178 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1179 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1181 Ptr
+= sizeof (UINT16
);
1185 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1187 Ptr
+= sizeof (UINT16
);
1190 for (Index
= 0; Index
< BbsCount
; Index
++) {
1191 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1192 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1193 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1198 switch (LocalBbsTable
[Index
].DeviceType
) {
1201 NewDevPtr
= NewFDPtr
;
1206 NewDevPtr
= NewHDPtr
;
1211 NewDevPtr
= NewCDPtr
;
1214 case BBS_EMBED_NETWORK
:
1216 NewDevPtr
= NewNETPtr
;
1219 case BBS_BEV_DEVICE
:
1221 NewDevPtr
= NewBEVPtr
;
1229 // at this point we have copied those valid indexes to new buffer
1230 // and we should check if there is any new appeared boot device
1233 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1234 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1239 if (Index2
== *Idx
) {
1241 // Index2 == *Idx means we didn't find Index
1242 // so Index is a new appeared device's index in BBS table
1245 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1253 // Just to make sure that disabled indexes are all at the end of the array
1255 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1256 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1260 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1261 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1262 tmp
= NewFDPtr
[Index
];
1263 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1264 NewFDPtr
[Index2
] = tmp
;
1273 // Just to make sure that disabled indexes are all at the end of the array
1275 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1276 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1280 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1281 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1282 tmp
= NewHDPtr
[Index
];
1283 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1284 NewHDPtr
[Index2
] = tmp
;
1293 // Just to make sure that disabled indexes are all at the end of the array
1295 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1296 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1300 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1301 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1302 tmp
= NewCDPtr
[Index
];
1303 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1304 NewCDPtr
[Index2
] = tmp
;
1313 // Just to make sure that disabled indexes are all at the end of the array
1315 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1316 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1320 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1321 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1322 tmp
= NewNETPtr
[Index
];
1323 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1324 NewNETPtr
[Index2
] = tmp
;
1333 // Just to make sure that disabled indexes are all at the end of the array
1335 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1336 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1340 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1341 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1342 tmp
= NewBEVPtr
[Index
];
1343 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1344 NewBEVPtr
[Index2
] = tmp
;
1351 SafeFreePool (DevOrder
);
1353 Status
= gRT
->SetVariable (
1355 &EfiLegacyDevOrderGuid
,
1360 SafeFreePool (NewDevOrder
);
1366 BdsSetBootPriority4SameTypeDev (
1367 IN UINT16 DeviceType
,
1368 IN OUT BBS_TABLE
*LocalBbsTable
,
1369 IN OUT UINT16
*Priority
1372 DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
1373 LocalBbsTable - BBS table instance
1374 Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
1375 priority can be used next time.
1386 DevOrder
= BdsLibGetVariableAndSize (
1388 &EfiLegacyDevOrderGuid
,
1391 if (NULL
== DevOrder
) {
1392 return EFI_OUT_OF_RESOURCES
;
1395 OrigBuffer
= DevOrder
;
1396 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1397 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1401 DevOrder
+= sizeof (BBS_TYPE
);
1402 DevOrder
+= *(UINT16
*) DevOrder
;
1405 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1406 SafeFreePool (OrigBuffer
);
1407 return EFI_NOT_FOUND
;
1410 DevOrder
+= sizeof (BBS_TYPE
);
1411 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1412 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1414 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1416 for (Index
= 0; Index
< DevCount
; Index
++) {
1417 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1419 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1422 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1427 SafeFreePool (OrigBuffer
);
1433 IN BBS_TABLE
*LocalBbsTable
1438 DEBUG ((EFI_D_ERROR
, "\n"));
1439 DEBUG ((EFI_D_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1440 DEBUG ((EFI_D_ERROR
, "=============================================\n"));
1441 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1442 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1443 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1444 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1451 " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
1453 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1454 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1455 (UINTN
) LocalBbsTable
[Idx
].Device
,
1456 (UINTN
) LocalBbsTable
[Idx
].Function
,
1457 (UINTN
) LocalBbsTable
[Idx
].Class
,
1458 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1459 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1460 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1461 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1462 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1463 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1464 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1468 DEBUG ((EFI_D_ERROR
, "\n"));
1472 BdsRefreshBbsTableForBoot (
1473 IN BDS_COMMON_OPTION
*Entry
1479 HDD_INFO
*LocalHddInfo
;
1480 BBS_TABLE
*LocalBbsTable
;
1482 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1486 UINTN BootOrderSize
;
1487 UINT8
*BootOptionVar
;
1488 UINTN BootOptionSize
;
1489 UINT16 BootOption
[100];
1492 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1496 LocalHddInfo
= NULL
;
1497 LocalBbsTable
= NULL
;
1498 DevType
= BBS_UNKNOWN
;
1500 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
1501 if (EFI_ERROR (Status
)) {
1505 LegacyBios
->GetBbsInfo (
1513 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1514 // We will set them according to the settings setup by user
1516 for (Index
= 0; Index
< BbsCount
; Index
++) {
1517 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1518 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1519 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1520 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1524 // boot priority always starts at 0
1527 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1529 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1531 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1532 Status
= BdsSetBootPriority4SameTypeDev (
1537 if (EFI_ERROR (Status
)) {
1542 // we have to set the boot priority for other BBS entries with different device types
1544 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1546 &gEfiGlobalVariableGuid
,
1549 for (Index
= 0; BootOrder
&& Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
1550 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1551 BootOptionVar
= BdsLibGetVariableAndSize (
1553 &gEfiGlobalVariableGuid
,
1556 if (NULL
== BootOptionVar
) {
1560 Ptr
= BootOptionVar
;
1562 Ptr
+= sizeof (UINT32
);
1563 DevPathLen
= *(UINT16
*) Ptr
;
1564 Ptr
+= sizeof (UINT16
);
1565 Ptr
+= StrSize ((UINT16
*) Ptr
);
1566 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1567 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1568 SafeFreePool (BootOptionVar
);
1573 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1575 // We don't want to process twice for a device type
1577 SafeFreePool (BootOptionVar
);
1581 Status
= BdsSetBootPriority4SameTypeDev (
1582 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1586 SafeFreePool (BootOptionVar
);
1587 if (EFI_ERROR (Status
)) {
1593 SafeFreePool (BootOrder
);
1598 PrintBbsTable (LocalBbsTable
);