3 Copyright (c) 2006 - 2007, 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
25 // Include common header file for this module.
27 #include "CommonHeader.h"
29 #include "BBSsupport.h"
31 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
[] = {
33 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
34 END_DEVICE_PATH_LENGTH
,
48 Translate the first n characters of an Ascii string to
49 Unicode characters. The count n is indicated by parameter
50 Size. If Size is greater than the length of string, then
51 the entire string is translated.
55 a - Pointer to input Ascii string.
56 Size - The number of characters to translate.
57 u - Pointer to output Unicode string buffer.
80 BdsBuildLegacyDevNameString (
81 IN BBS_TABLE
*CurBBSEntry
,
84 OUT CHAR16
*BootString
97 Fmt
= L
"Primary Master %s";
104 Fmt
= L
"Primary Slave %s";
111 Fmt
= L
"Secondary Master %s";
118 Fmt
= L
"Secondary Slave %s";
126 switch (CurBBSEntry
->DeviceType
) {
147 case BBS_EMBED_NETWORK
:
161 // If current BBS entry has its description then use it.
163 StringDesc
= (UINT8
*) (UINTN
) ((CurBBSEntry
->DescStringSegment
<< 4) + CurBBSEntry
->DescStringOffset
);
164 if (NULL
!= StringDesc
) {
166 // Only get fisrt 32 characters, this is suggested by BBS spec
168 AsciiToUnicodeSize (StringDesc
, 32, temp
);
173 UnicodeSPrint (BootString
, BufSize
, Fmt
, Type
);
177 BdsCreateLegacyBootOption (
178 IN BBS_TABLE
*CurrentBbsEntry
,
179 IN EFI_DEVICE_PATH_PROTOCOL
*CurrentBbsDevPath
,
181 IN OUT UINT16
**BootOrderList
,
182 IN OUT UINTN
*BootOrderListSize
188 Create a legacy boot option for the specified entry of
189 BBS table, save it as variable, and append it to the boot
194 CurrentBbsEntry - Pointer to current BBS table.
195 CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
196 Index - Index of the specified entry in BBS table.
197 BootOrderList - On input, the original boot order list.
198 On output, the new boot order list attached with the
200 BootOrderListSize - On input, the original size of boot order list.
201 - On output, the size of new boot order list.
205 EFI_SUCCESS - Boot Option successfully created.
206 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
207 Other - Error occurs while setting variable.
212 UINT16 CurrentBootOptionNo
;
213 UINT16 BootString
[10];
214 UINT16 BootDesc
[100];
215 UINT16
*NewBootOrderList
;
219 UINT16 CurrentBbsDevPathSize
;
220 UINTN BootOrderIndex
;
221 UINTN BootOrderLastIndex
;
223 BOOLEAN IndexNotFound
;
225 if (NULL
== (*BootOrderList
)) {
226 CurrentBootOptionNo
= 0;
228 for (ArrayIndex
= 0; ArrayIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); ArrayIndex
++) {
229 IndexNotFound
= TRUE
;
230 for (BootOrderIndex
= 0; BootOrderIndex
< (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
)); BootOrderIndex
++) {
231 if ((*BootOrderList
)[BootOrderIndex
] == ArrayIndex
) {
232 IndexNotFound
= FALSE
;
237 if (!IndexNotFound
) {
244 CurrentBootOptionNo
= (UINT16
) ArrayIndex
;
254 BdsBuildLegacyDevNameString (CurrentBbsEntry
, Index
, sizeof (BootDesc
), BootDesc
);
256 CurrentBbsDevPathSize
= (UINT16
) (GetDevicePathSize (CurrentBbsDevPath
));
258 BufferSize
= sizeof (UINT32
) +
261 CurrentBbsDevPathSize
+
265 Buffer
= AllocateZeroPool (BufferSize
);
266 if (Buffer
== NULL
) {
267 return EFI_OUT_OF_RESOURCES
;
270 Ptr
= (UINT8
*) Buffer
;
272 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
273 Ptr
+= sizeof (UINT32
);
275 *((UINT16
*) Ptr
) = CurrentBbsDevPathSize
;
276 Ptr
+= sizeof (UINT16
);
283 Ptr
+= StrSize (BootDesc
);
288 CurrentBbsDevPathSize
290 Ptr
+= CurrentBbsDevPathSize
;
298 Ptr
+= sizeof (BBS_TABLE
);
299 *((UINT16
*) Ptr
) = (UINT16
) Index
;
301 Status
= gRT
->SetVariable (
303 &gEfiGlobalVariableGuid
,
309 SafeFreePool (Buffer
);
312 NewBootOrderList
= AllocateZeroPool (*BootOrderListSize
+ sizeof (UINT16
));
313 if (NULL
== NewBootOrderList
) {
314 return EFI_OUT_OF_RESOURCES
;
317 if (NULL
!= *BootOrderList
) {
318 CopyMem (NewBootOrderList
, *BootOrderList
, *BootOrderListSize
);
321 SafeFreePool (*BootOrderList
);
323 BootOrderLastIndex
= (UINTN
) (*BootOrderListSize
/ sizeof (UINT16
));
324 NewBootOrderList
[BootOrderLastIndex
] = CurrentBootOptionNo
;
325 *BootOrderListSize
+= sizeof (UINT16
);
326 *BootOrderList
= NewBootOrderList
;
332 BdsIsLegacyBootOption (
333 IN UINT8
*BootOptionVar
,
334 OUT BBS_TABLE
**BbsEntry
,
339 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
344 Ptr
+= sizeof (UINT32
);
345 DevPathLen
= *(UINT16
*) Ptr
;
346 Ptr
+= sizeof (UINT16
);
347 Ptr
+= StrSize ((UINT16
*) Ptr
);
348 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
349 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
351 *BbsEntry
= (BBS_TABLE
*) Ptr
;
352 Ptr
+= sizeof (BBS_TABLE
);
353 *BbsIndex
= *(UINT16
*) Ptr
;
364 BdsDeleteBootOption (
365 IN UINTN OptionNumber
,
366 IN OUT UINT16
*BootOrder
,
367 IN OUT UINTN
*BootOrderSize
370 UINT16 BootOption
[100];
375 Status
= EFI_SUCCESS
;
378 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", OptionNumber
);
379 Status
= EfiLibDeleteVariable (BootOption
, &gEfiGlobalVariableGuid
);
381 // adjust boot order array
383 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
); Index
++) {
384 if (BootOrder
[Index
] == OptionNumber
) {
390 if (Index
!= *BootOrderSize
/ sizeof (UINT16
)) {
391 for (Index
= 0; Index
< *BootOrderSize
/ sizeof (UINT16
) - 1; Index
++) {
392 if (Index
>= Index2Del
) {
393 BootOrder
[Index
] = BootOrder
[Index
+ 1];
397 *BootOrderSize
-= sizeof (UINT16
);
405 BdsDeleteAllInvalidLegacyBootOptions (
412 Delete all the invalid legacy boot options.
420 EFI_SUCCESS - All invalide legacy boot options are deleted.
421 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
422 EFI_NOT_FOUND - Fail to retrive variable of boot order.
423 Other - Error occurs while setting variable or locating
429 UINT8
*BootOptionVar
;
431 UINTN BootOptionSize
;
435 HDD_INFO
*LocalHddInfo
;
436 BBS_TABLE
*LocalBbsTable
;
439 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
441 UINT16 BootOption
[10];
442 UINT16 BootDesc
[100];
443 BOOLEAN DescStringMatch
;
445 Status
= EFI_SUCCESS
;
451 LocalBbsTable
= NULL
;
454 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
455 if (EFI_ERROR (Status
)) {
459 LegacyBios
->GetBbsInfo (
467 BootOrder
= BdsLibGetVariableAndSize (
469 &gEfiGlobalVariableGuid
,
472 if (NULL
== BootOrder
) {
473 return EFI_NOT_FOUND
;
477 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
478 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
479 BootOptionVar
= BdsLibGetVariableAndSize (
481 &gEfiGlobalVariableGuid
,
484 if (NULL
== BootOptionVar
) {
485 SafeFreePool (BootOrder
);
486 return EFI_OUT_OF_RESOURCES
;
489 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, &BbsIndex
)) {
490 SafeFreePool (BootOptionVar
);
496 // Check if BBS Description String is changed
498 DescStringMatch
= FALSE
;
500 BdsBuildLegacyDevNameString (
501 &LocalBbsTable
[BbsIndex
],
507 if (StrCmp (BootDesc
, (UINT16
*)(BootOptionVar
+ sizeof (UINT32
) + sizeof (UINT16
))) == 0) {
508 DescStringMatch
= TRUE
;
511 if (!((LocalBbsTable
[BbsIndex
].BootPriority
== BBS_IGNORE_ENTRY
) ||
512 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
513 (LocalBbsTable
[BbsIndex
].BootPriority
== BBS_LOWEST_PRIORITY
)) &&
514 (LocalBbsTable
[BbsIndex
].DeviceType
== BbsEntry
->DeviceType
) &&
520 SafeFreePool (BootOptionVar
);
524 BdsDeleteBootOption (
532 Status
= gRT
->SetVariable (
534 &gEfiGlobalVariableGuid
,
540 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
543 SafeFreePool (BootOrder
);
549 BdsFindLegacyBootOptionByDevType (
550 IN UINT16
*BootOrder
,
551 IN UINTN BootOptionNum
,
553 OUT UINT32
*Attribute
,
554 OUT UINT16
*BbsIndex
,
555 OUT UINTN
*OptionNumber
559 UINTN BootOrderIndex
;
560 UINT16 BootOption
[100];
561 UINTN BootOptionSize
;
562 UINT8
*BootOptionVar
;
569 if (NULL
== BootOrder
) {
573 for (BootOrderIndex
= 0; BootOrderIndex
< BootOptionNum
; BootOrderIndex
++) {
574 Index
= (UINTN
) BootOrder
[BootOrderIndex
];
575 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", Index
);
576 BootOptionVar
= BdsLibGetVariableAndSize (
578 &gEfiGlobalVariableGuid
,
581 if (NULL
== BootOptionVar
) {
585 if (!BdsIsLegacyBootOption (BootOptionVar
, &BbsEntry
, BbsIndex
)) {
586 SafeFreePool (BootOptionVar
);
590 if (BbsEntry
->DeviceType
!= DevType
) {
591 SafeFreePool (BootOptionVar
);
595 *Attribute
= *(UINT32
*) BootOptionVar
;
596 *OptionNumber
= Index
;
598 SafeFreePool (BootOptionVar
);
606 BdsCreateOneLegacyBootOption (
607 IN BBS_TABLE
*BbsItem
,
609 IN OUT UINT16
**BootOrderList
,
610 IN OUT UINTN
*BootOrderListSize
613 BBS_BBS_DEVICE_PATH BbsDevPathNode
;
615 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
619 BbsDevPathNode
.Header
.Type
= BBS_DEVICE_PATH
;
620 BbsDevPathNode
.Header
.SubType
= BBS_BBS_DP
;
621 SetDevicePathNodeLength (&BbsDevPathNode
.Header
, sizeof (BBS_BBS_DEVICE_PATH
));
622 BbsDevPathNode
.DeviceType
= BbsItem
->DeviceType
;
623 CopyMem (&BbsDevPathNode
.StatusFlag
, &BbsItem
->StatusFlags
, sizeof (UINT16
));
625 DevPath
= AppendDevicePathNode (
627 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevPathNode
629 if (NULL
== DevPath
) {
630 return EFI_OUT_OF_RESOURCES
;
633 Status
= BdsCreateLegacyBootOption (
640 BbsItem
->BootPriority
= 0x00;
648 BdsAddNonExistingLegacyBootOptions (
655 Add the legacy boot options from BBS table if they do not exist.
663 EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
664 others - An error occurred when creating legacy boot options.
673 HDD_INFO
*LocalHddInfo
;
674 BBS_TABLE
*LocalBbsTable
;
676 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
686 LocalBbsTable
= NULL
;
688 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
689 if (EFI_ERROR (Status
)) {
693 LegacyBios
->GetBbsInfo (
701 BootOrder
= BdsLibGetVariableAndSize (
703 &gEfiGlobalVariableGuid
,
706 if (NULL
== BootOrder
) {
710 for (Index
= 0; Index
< BbsCount
; Index
++) {
711 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
712 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
)
717 Ret
= BdsFindLegacyBootOptionByDevType (
719 BootOrderSize
/ sizeof (UINT16
),
720 LocalBbsTable
[Index
].DeviceType
,
725 if (Ret
&& (Attribute
& LOAD_OPTION_ACTIVE
) != 0) {
730 if (Index
!= BbsIndex
) {
731 BdsDeleteBootOption (
741 // Not found such type of legacy device in boot options or we found but it's disabled
742 // so we have to create one and put it to the tail of boot order list
744 Status
= BdsCreateOneLegacyBootOption (
745 &LocalBbsTable
[Index
],
750 if (EFI_ERROR (Status
)) {
755 if (BootOrderSize
> 0) {
756 Status
= gRT
->SetVariable (
758 &gEfiGlobalVariableGuid
,
764 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
767 if (BootOrder
!= NULL
) {
768 SafeFreePool (BootOrder
);
776 IN BBS_TABLE
*BbsTable
,
784 for (Index
= 0; Index
< BbsCount
; Index
++) {
785 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
789 if (BbsTable
[Index
].DeviceType
!= BbsType
) {
793 *Buf
= (UINT16
) (Index
& 0xFF);
802 IN BBS_TABLE
*BbsTable
,
824 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
827 Status
= EFI_SUCCESS
;
829 for (Index
= 0; Index
< BbsCount
; Index
++) {
830 if (BbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) {
834 switch (BbsTable
[Index
].DeviceType
) {
847 case BBS_EMBED_NETWORK
:
860 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * FDCount
);
861 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * HDCount
);
862 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * CDCount
);
863 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * NETCount
);
864 TotalSize
+= (HeaderSize
+ sizeof (UINT16
) * BEVCount
);
866 DevOrder
= AllocateZeroPool (TotalSize
);
867 if (NULL
== DevOrder
) {
868 return EFI_OUT_OF_RESOURCES
;
873 *((BBS_TYPE
*) Ptr
) = BBS_FLOPPY
;
874 Ptr
+= sizeof (BBS_TYPE
);
875 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
876 Ptr
+= sizeof (UINT16
);
878 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_FLOPPY
, BbsCount
, (UINT16
*) Ptr
);
881 *((BBS_TYPE
*) Ptr
) = BBS_HARDDISK
;
882 Ptr
+= sizeof (BBS_TYPE
);
883 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
884 Ptr
+= sizeof (UINT16
);
886 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_HARDDISK
, BbsCount
, (UINT16
*) Ptr
);
889 *((BBS_TYPE
*) Ptr
) = BBS_CDROM
;
890 Ptr
+= sizeof (BBS_TYPE
);
891 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
892 Ptr
+= sizeof (UINT16
);
894 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_CDROM
, BbsCount
, (UINT16
*) Ptr
);
897 *((BBS_TYPE
*) Ptr
) = BBS_EMBED_NETWORK
;
898 Ptr
+= sizeof (BBS_TYPE
);
899 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
900 Ptr
+= sizeof (UINT16
);
902 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_EMBED_NETWORK
, BbsCount
, (UINT16
*) Ptr
);
905 *((BBS_TYPE
*) Ptr
) = BBS_BEV_DEVICE
;
906 Ptr
+= sizeof (BBS_TYPE
);
907 *((UINT16
*) Ptr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
908 Ptr
+= sizeof (UINT16
);
910 Ptr
= (UINT8
*) BdsFillDevOrderBuf (BbsTable
, BBS_BEV_DEVICE
, BbsCount
, (UINT16
*) Ptr
);
913 Status
= gRT
->SetVariable (
915 &EfiLegacyDevOrderGuid
,
920 SafeFreePool (DevOrder
);
926 BdsUpdateLegacyDevOrder (
930 Format of LegacyDevOrder variable:
931 |-----------------------------------------------------------------------------------------------------------------
932 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
933 |-----------------------------------------------------------------------------------------------------------------
935 Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
936 Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
937 the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
944 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
948 HDD_INFO
*LocalHddInfo
;
949 BBS_TABLE
*LocalBbsTable
;
977 LocalBbsTable
= NULL
;
985 HeaderSize
= sizeof (BBS_TYPE
) + sizeof (UINT16
);
993 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
994 if (EFI_ERROR (Status
)) {
998 LegacyBios
->GetBbsInfo (
1006 DevOrder
= (UINT8
*) BdsLibGetVariableAndSize (
1008 &EfiLegacyDevOrderGuid
,
1011 if (NULL
== DevOrder
) {
1012 return BdsCreateDevOrder (LocalBbsTable
, BbsCount
);
1015 // First we figure out how many boot devices with same device type respectively
1017 for (Index
= 0; Index
< BbsCount
; Index
++) {
1018 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1019 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1020 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1025 switch (LocalBbsTable
[Index
].DeviceType
) {
1038 case BBS_EMBED_NETWORK
:
1042 case BBS_BEV_DEVICE
:
1051 TotalSize
+= (HeaderSize
+ FDCount
* sizeof (UINT16
));
1052 TotalSize
+= (HeaderSize
+ HDCount
* sizeof (UINT16
));
1053 TotalSize
+= (HeaderSize
+ CDCount
* sizeof (UINT16
));
1054 TotalSize
+= (HeaderSize
+ NETCount
* sizeof (UINT16
));
1055 TotalSize
+= (HeaderSize
+ BEVCount
* sizeof (UINT16
));
1057 NewDevOrder
= AllocateZeroPool (TotalSize
);
1058 if (NULL
== NewDevOrder
) {
1059 return EFI_OUT_OF_RESOURCES
;
1062 NewFDPtr
= (UINT16
*) (NewDevOrder
+ HeaderSize
);
1063 NewHDPtr
= (UINT16
*) ((UINT8
*) NewFDPtr
+ FDCount
* sizeof (UINT16
) + HeaderSize
);
1064 NewCDPtr
= (UINT16
*) ((UINT8
*) NewHDPtr
+ HDCount
* sizeof (UINT16
) + HeaderSize
);
1065 NewNETPtr
= (UINT16
*) ((UINT8
*) NewCDPtr
+ CDCount
* sizeof (UINT16
) + HeaderSize
);
1066 NewBEVPtr
= (UINT16
*) ((UINT8
*) NewNETPtr
+ NETCount
* sizeof (UINT16
) + HeaderSize
);
1072 NewPtr
= NewDevOrder
;
1073 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1074 Ptr
+= sizeof (BBS_TYPE
);
1075 NewPtr
+= sizeof (BBS_TYPE
);
1076 Length
= *((UINT16
*) Ptr
);
1077 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + FDCount
* sizeof (UINT16
));
1078 Ptr
+= sizeof (UINT16
);
1080 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1081 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1082 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1083 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1084 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_FLOPPY
1086 Ptr
+= sizeof (UINT16
);
1090 NewFDPtr
[FDIndex
] = *(UINT16
*) Ptr
;
1092 Ptr
+= sizeof (UINT16
);
1097 NewPtr
= (UINT8
*) NewHDPtr
- HeaderSize
;
1098 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1099 Ptr
+= sizeof (BBS_TYPE
);
1100 NewPtr
+= sizeof (BBS_TYPE
);
1101 Length
= *((UINT16
*) Ptr
);
1102 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + HDCount
* sizeof (UINT16
));
1103 Ptr
+= sizeof (UINT16
);
1105 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1106 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1107 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1108 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1109 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_HARDDISK
1111 Ptr
+= sizeof (UINT16
);
1115 NewHDPtr
[HDIndex
] = *(UINT16
*) Ptr
;
1117 Ptr
+= sizeof (UINT16
);
1122 NewPtr
= (UINT8
*) NewCDPtr
- HeaderSize
;
1123 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1124 Ptr
+= sizeof (BBS_TYPE
);
1125 NewPtr
+= sizeof (BBS_TYPE
);
1126 Length
= *((UINT16
*) Ptr
);
1127 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + CDCount
* sizeof (UINT16
));
1128 Ptr
+= sizeof (UINT16
);
1130 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1131 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1132 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1133 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1134 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_CDROM
1136 Ptr
+= sizeof (UINT16
);
1140 NewCDPtr
[CDIndex
] = *(UINT16
*) Ptr
;
1142 Ptr
+= sizeof (UINT16
);
1147 NewPtr
= (UINT8
*) NewNETPtr
- HeaderSize
;
1148 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1149 Ptr
+= sizeof (BBS_TYPE
);
1150 NewPtr
+= sizeof (BBS_TYPE
);
1151 Length
= *((UINT16
*) Ptr
);
1152 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + NETCount
* sizeof (UINT16
));
1153 Ptr
+= sizeof (UINT16
);
1155 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1156 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1157 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1158 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1159 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_EMBED_NETWORK
1161 Ptr
+= sizeof (UINT16
);
1165 NewNETPtr
[NETIndex
] = *(UINT16
*) Ptr
;
1167 Ptr
+= sizeof (UINT16
);
1172 NewPtr
= (UINT8
*) NewBEVPtr
- HeaderSize
;
1173 *((BBS_TYPE
*) NewPtr
) = *((BBS_TYPE
*) Ptr
);
1174 Ptr
+= sizeof (BBS_TYPE
);
1175 NewPtr
+= sizeof (BBS_TYPE
);
1176 Length
= *((UINT16
*) Ptr
);
1177 *((UINT16
*) NewPtr
) = (UINT16
) (sizeof (UINT16
) + BEVCount
* sizeof (UINT16
));
1178 Ptr
+= sizeof (UINT16
);
1180 for (Index
= 0; Index
< Length
/ sizeof (UINT16
) - 1; Index
++) {
1181 if (LocalBbsTable
[*Ptr
].BootPriority
== BBS_IGNORE_ENTRY
||
1182 LocalBbsTable
[*Ptr
].BootPriority
== BBS_DO_NOT_BOOT_FROM
||
1183 LocalBbsTable
[*Ptr
].BootPriority
== BBS_LOWEST_PRIORITY
||
1184 LocalBbsTable
[*Ptr
].DeviceType
!= BBS_BEV_DEVICE
1186 Ptr
+= sizeof (UINT16
);
1190 NewBEVPtr
[BEVIndex
] = *(UINT16
*) Ptr
;
1192 Ptr
+= sizeof (UINT16
);
1195 for (Index
= 0; Index
< BbsCount
; Index
++) {
1196 if ((LocalBbsTable
[Index
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1197 (LocalBbsTable
[Index
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1198 (LocalBbsTable
[Index
].BootPriority
== BBS_LOWEST_PRIORITY
)
1203 switch (LocalBbsTable
[Index
].DeviceType
) {
1206 NewDevPtr
= NewFDPtr
;
1211 NewDevPtr
= NewHDPtr
;
1216 NewDevPtr
= NewCDPtr
;
1219 case BBS_EMBED_NETWORK
:
1221 NewDevPtr
= NewNETPtr
;
1224 case BBS_BEV_DEVICE
:
1226 NewDevPtr
= NewBEVPtr
;
1234 // at this point we have copied those valid indexes to new buffer
1235 // and we should check if there is any new appeared boot device
1238 for (Index2
= 0; Index2
< *Idx
; Index2
++) {
1239 if ((NewDevPtr
[Index2
] & 0xFF) == (UINT16
) Index
) {
1244 if (Index2
== *Idx
) {
1246 // Index2 == *Idx means we didn't find Index
1247 // so Index is a new appeared device's index in BBS table
1250 NewDevPtr
[*Idx
] = (UINT16
) (Index
& 0xFF);
1258 // Just to make sure that disabled indexes are all at the end of the array
1260 for (Index
= 0; Index
< FDIndex
- 1; Index
++) {
1261 if (0xFF00 != (NewFDPtr
[Index
] & 0xFF00)) {
1265 for (Index2
= Index
+ 1; Index2
< FDIndex
; Index2
++) {
1266 if (0 == (NewFDPtr
[Index2
] & 0xFF00)) {
1267 tmp
= NewFDPtr
[Index
];
1268 NewFDPtr
[Index
] = NewFDPtr
[Index2
];
1269 NewFDPtr
[Index2
] = tmp
;
1278 // Just to make sure that disabled indexes are all at the end of the array
1280 for (Index
= 0; Index
< HDIndex
- 1; Index
++) {
1281 if (0xFF00 != (NewHDPtr
[Index
] & 0xFF00)) {
1285 for (Index2
= Index
+ 1; Index2
< HDIndex
; Index2
++) {
1286 if (0 == (NewHDPtr
[Index2
] & 0xFF00)) {
1287 tmp
= NewHDPtr
[Index
];
1288 NewHDPtr
[Index
] = NewHDPtr
[Index2
];
1289 NewHDPtr
[Index2
] = tmp
;
1298 // Just to make sure that disabled indexes are all at the end of the array
1300 for (Index
= 0; Index
< CDIndex
- 1; Index
++) {
1301 if (0xFF00 != (NewCDPtr
[Index
] & 0xFF00)) {
1305 for (Index2
= Index
+ 1; Index2
< CDIndex
; Index2
++) {
1306 if (0 == (NewCDPtr
[Index2
] & 0xFF00)) {
1307 tmp
= NewCDPtr
[Index
];
1308 NewCDPtr
[Index
] = NewCDPtr
[Index2
];
1309 NewCDPtr
[Index2
] = tmp
;
1318 // Just to make sure that disabled indexes are all at the end of the array
1320 for (Index
= 0; Index
< NETIndex
- 1; Index
++) {
1321 if (0xFF00 != (NewNETPtr
[Index
] & 0xFF00)) {
1325 for (Index2
= Index
+ 1; Index2
< NETIndex
; Index2
++) {
1326 if (0 == (NewNETPtr
[Index2
] & 0xFF00)) {
1327 tmp
= NewNETPtr
[Index
];
1328 NewNETPtr
[Index
] = NewNETPtr
[Index2
];
1329 NewNETPtr
[Index2
] = tmp
;
1338 // Just to make sure that disabled indexes are all at the end of the array
1340 for (Index
= 0; Index
< BEVIndex
- 1; Index
++) {
1341 if (0xFF00 != (NewBEVPtr
[Index
] & 0xFF00)) {
1345 for (Index2
= Index
+ 1; Index2
< BEVIndex
; Index2
++) {
1346 if (0 == (NewBEVPtr
[Index2
] & 0xFF00)) {
1347 tmp
= NewBEVPtr
[Index
];
1348 NewBEVPtr
[Index
] = NewBEVPtr
[Index2
];
1349 NewBEVPtr
[Index2
] = tmp
;
1356 SafeFreePool (DevOrder
);
1358 Status
= gRT
->SetVariable (
1360 &EfiLegacyDevOrderGuid
,
1365 SafeFreePool (NewDevOrder
);
1371 BdsSetBootPriority4SameTypeDev (
1372 IN UINT16 DeviceType
,
1373 IN OUT BBS_TABLE
*LocalBbsTable
,
1374 IN OUT UINT16
*Priority
1377 DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
1378 LocalBbsTable - BBS table instance
1379 Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
1380 priority can be used next time.
1391 DevOrder
= BdsLibGetVariableAndSize (
1393 &EfiLegacyDevOrderGuid
,
1396 if (NULL
== DevOrder
) {
1397 return EFI_OUT_OF_RESOURCES
;
1400 OrigBuffer
= DevOrder
;
1401 while (DevOrder
< OrigBuffer
+ DevOrderSize
) {
1402 if (DeviceType
== * (BBS_TYPE
*) DevOrder
) {
1406 DevOrder
+= sizeof (BBS_TYPE
);
1407 DevOrder
+= *(UINT16
*) DevOrder
;
1410 if (DevOrder
>= OrigBuffer
+ DevOrderSize
) {
1411 SafeFreePool (OrigBuffer
);
1412 return EFI_NOT_FOUND
;
1415 DevOrder
+= sizeof (BBS_TYPE
);
1416 DevCount
= (*((UINT16
*) DevOrder
) - sizeof (UINT16
)) / sizeof (UINT16
);
1417 DevIndex
= (UINT16
*) (DevOrder
+ sizeof (UINT16
));
1419 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1421 for (Index
= 0; Index
< DevCount
; Index
++) {
1422 if ((DevIndex
[Index
] & 0xFF00) == 0xFF00) {
1424 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1427 LocalBbsTable
[DevIndex
[Index
] & 0xFF].BootPriority
= *Priority
;
1432 SafeFreePool (OrigBuffer
);
1438 IN BBS_TABLE
*LocalBbsTable
1443 DEBUG ((EFI_D_ERROR
, "\n"));
1444 DEBUG ((EFI_D_ERROR
, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1445 DEBUG ((EFI_D_ERROR
, "=============================================\n"));
1446 for (Idx
= 0; Idx
< MAX_BBS_ENTRIES
; Idx
++) {
1447 if ((LocalBbsTable
[Idx
].BootPriority
== BBS_IGNORE_ENTRY
) ||
1448 (LocalBbsTable
[Idx
].BootPriority
== BBS_DO_NOT_BOOT_FROM
) ||
1449 (LocalBbsTable
[Idx
].BootPriority
== BBS_LOWEST_PRIORITY
)
1456 " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
1458 (UINTN
) LocalBbsTable
[Idx
].BootPriority
,
1459 (UINTN
) LocalBbsTable
[Idx
].Bus
,
1460 (UINTN
) LocalBbsTable
[Idx
].Device
,
1461 (UINTN
) LocalBbsTable
[Idx
].Function
,
1462 (UINTN
) LocalBbsTable
[Idx
].Class
,
1463 (UINTN
) LocalBbsTable
[Idx
].SubClass
,
1464 (UINTN
) LocalBbsTable
[Idx
].DeviceType
,
1465 (UINTN
) * (UINT16
*) &LocalBbsTable
[Idx
].StatusFlags
,
1466 (UINTN
) LocalBbsTable
[Idx
].BootHandlerSegment
,
1467 (UINTN
) LocalBbsTable
[Idx
].BootHandlerOffset
,
1468 (UINTN
) ((LocalBbsTable
[Idx
].MfgStringSegment
<< 4) + LocalBbsTable
[Idx
].MfgStringOffset
),
1469 (UINTN
) ((LocalBbsTable
[Idx
].DescStringSegment
<< 4) + LocalBbsTable
[Idx
].DescStringOffset
))
1473 DEBUG ((EFI_D_ERROR
, "\n"));
1477 BdsRefreshBbsTableForBoot (
1478 IN BDS_COMMON_OPTION
*Entry
1484 HDD_INFO
*LocalHddInfo
;
1485 BBS_TABLE
*LocalBbsTable
;
1487 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
1491 UINTN BootOrderSize
;
1492 UINT8
*BootOptionVar
;
1493 UINTN BootOptionSize
;
1494 UINT16 BootOption
[100];
1497 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1501 LocalHddInfo
= NULL
;
1502 LocalBbsTable
= NULL
;
1503 DevType
= BBS_UNKNOWN
;
1505 Status
= EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid
, &LegacyBios
);
1506 if (EFI_ERROR (Status
)) {
1510 LegacyBios
->GetBbsInfo (
1518 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1519 // We will set them according to the settings setup by user
1521 for (Index
= 0; Index
< BbsCount
; Index
++) {
1522 if (!((BBS_IGNORE_ENTRY
== LocalBbsTable
[Index
].BootPriority
) ||
1523 (BBS_DO_NOT_BOOT_FROM
== LocalBbsTable
[Index
].BootPriority
) ||
1524 (BBS_LOWEST_PRIORITY
== LocalBbsTable
[Index
].BootPriority
))) {
1525 LocalBbsTable
[Index
].BootPriority
= BBS_UNPRIORITIZED_ENTRY
;
1529 // boot priority always starts at 0
1532 if (Entry
->LoadOptionsSize
== sizeof (BBS_TABLE
) + sizeof (UINT16
)) {
1534 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1536 DevType
= ((BBS_TABLE
*) Entry
->LoadOptions
)->DeviceType
;
1537 Status
= BdsSetBootPriority4SameTypeDev (
1542 if (EFI_ERROR (Status
)) {
1547 // we have to set the boot priority for other BBS entries with different device types
1549 BootOrder
= (UINT16
*) BdsLibGetVariableAndSize (
1551 &gEfiGlobalVariableGuid
,
1554 for (Index
= 0; BootOrder
&& Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
1555 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
1556 BootOptionVar
= BdsLibGetVariableAndSize (
1558 &gEfiGlobalVariableGuid
,
1561 if (NULL
== BootOptionVar
) {
1565 Ptr
= BootOptionVar
;
1567 Ptr
+= sizeof (UINT32
);
1568 DevPathLen
= *(UINT16
*) Ptr
;
1569 Ptr
+= sizeof (UINT16
);
1570 Ptr
+= StrSize ((UINT16
*) Ptr
);
1571 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1572 if (BBS_DEVICE_PATH
!= DevPath
->Type
|| BBS_BBS_DP
!= DevPath
->SubType
) {
1573 SafeFreePool (BootOptionVar
);
1578 if (DevType
== ((BBS_TABLE
*) Ptr
)->DeviceType
) {
1580 // We don't want to process twice for a device type
1582 SafeFreePool (BootOptionVar
);
1586 Status
= BdsSetBootPriority4SameTypeDev (
1587 ((BBS_TABLE
*) Ptr
)->DeviceType
,
1591 SafeFreePool (BootOptionVar
);
1592 if (EFI_ERROR (Status
)) {
1598 SafeFreePool (BootOrder
);
1603 PrintBbsTable (LocalBbsTable
);