]> git.proxmox.com Git - mirror_edk2.git/blob - Nt32Pkg/PlatformBdsDxe/Generic/BootMaint/BBSsupport.c
add in PlatformBds.inf
[mirror_edk2.git] / Nt32Pkg / PlatformBdsDxe / Generic / BootMaint / BBSsupport.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 BBSsupport.c
15
16 Abstract:
17
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
20 the legacy BBS table.
21
22 --*/
23
24 //
25 // Include common header file for this module.
26 //
27 #include "CommonHeader.h"
28
29 #include "BBSsupport.h"
30
31 EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {
32 END_DEVICE_PATH_TYPE,
33 END_ENTIRE_DEVICE_PATH_SUBTYPE,
34 END_DEVICE_PATH_LENGTH,
35 0
36 };
37
38 VOID
39 AsciiToUnicodeSize (
40 IN UINT8 *a,
41 IN UINTN Size,
42 OUT UINT16 *u
43 )
44 /*++
45
46 Routine Description:
47
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.
52
53 Arguments:
54
55 a - Pointer to input Ascii string.
56 Size - The number of characters to translate.
57 u - Pointer to output Unicode string buffer.
58
59 Returns:
60
61 None
62
63 --*/
64 {
65 UINTN i;
66
67 i = 0;
68 while (a[i] != 0) {
69 u[i] = (CHAR16) a[i];
70 if (i == Size) {
71 break;
72 }
73
74 i++;
75 }
76 u[i] = 0;
77 }
78
79 VOID
80 BdsBuildLegacyDevNameString (
81 IN BBS_TABLE *CurBBSEntry,
82 IN UINTN Index,
83 IN UINTN BufSize,
84 OUT CHAR16 *BootString
85 )
86 {
87 CHAR16 *Fmt;
88 CHAR16 *Type;
89 UINT8 *StringDesc;
90 CHAR16 temp[80];
91
92 switch (Index) {
93 //
94 // Primary Master
95 //
96 case 1:
97 Fmt = L"Primary Master %s";
98 break;
99
100 //
101 // Primary Slave
102 //
103 case 2:
104 Fmt = L"Primary Slave %s";
105 break;
106
107 //
108 // Secondary Master
109 //
110 case 3:
111 Fmt = L"Secondary Master %s";
112 break;
113
114 //
115 // Secondary Slave
116 //
117 case 4:
118 Fmt = L"Secondary Slave %s";
119 break;
120
121 default:
122 Fmt = L"%s";
123 break;
124 }
125
126 switch (CurBBSEntry->DeviceType) {
127 case BBS_FLOPPY:
128 Type = L"Floppy";
129 break;
130
131 case BBS_HARDDISK:
132 Type = L"Harddisk";
133 break;
134
135 case BBS_CDROM:
136 Type = L"CDROM";
137 break;
138
139 case BBS_PCMCIA:
140 Type = L"PCMCIAe";
141 break;
142
143 case BBS_USB:
144 Type = L"USB";
145 break;
146
147 case BBS_EMBED_NETWORK:
148 Type = L"Network";
149 break;
150
151 case BBS_BEV_DEVICE:
152 Type = L"BEVe";
153 break;
154
155 case BBS_UNKNOWN:
156 default:
157 Type = L"Unknown";
158 break;
159 }
160 //
161 // If current BBS entry has its description then use it.
162 //
163 StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);
164 if (NULL != StringDesc) {
165 //
166 // Only get fisrt 32 characters, this is suggested by BBS spec
167 //
168 AsciiToUnicodeSize (StringDesc, 32, temp);
169 Fmt = L"%s";
170 Type = temp;
171 }
172
173 UnicodeSPrint (BootString, BufSize, Fmt, Type);
174 }
175
176 EFI_STATUS
177 BdsCreateLegacyBootOption (
178 IN BBS_TABLE *CurrentBbsEntry,
179 IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,
180 IN UINTN Index,
181 IN OUT UINT16 **BootOrderList,
182 IN OUT UINTN *BootOrderListSize
183 )
184 /*++
185
186 Routine Description:
187
188 Create a legacy boot option for the specified entry of
189 BBS table, save it as variable, and append it to the boot
190 order list.
191
192 Arguments:
193
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
199 created node.
200 BootOrderListSize - On input, the original size of boot order list.
201 - On output, the size of new boot order list.
202
203 Returns:
204
205 EFI_SUCCESS - Boot Option successfully created.
206 EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
207 Other - Error occurs while setting variable.
208
209 --*/
210 {
211 EFI_STATUS Status;
212 UINT16 CurrentBootOptionNo;
213 UINT16 BootString[10];
214 UINT16 BootDesc[100];
215 UINT16 *NewBootOrderList;
216 UINTN BufferSize;
217 VOID *Buffer;
218 UINT8 *Ptr;
219 UINT16 CurrentBbsDevPathSize;
220 UINTN BootOrderIndex;
221 UINTN BootOrderLastIndex;
222 UINTN ArrayIndex;
223 BOOLEAN IndexNotFound;
224
225 if (NULL == (*BootOrderList)) {
226 CurrentBootOptionNo = 0;
227 } else {
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;
233 break;
234 }
235 }
236
237 if (!IndexNotFound) {
238 continue;
239 } else {
240 break;
241 }
242 }
243
244 CurrentBootOptionNo = (UINT16) ArrayIndex;
245 }
246
247 UnicodeSPrint (
248 BootString,
249 sizeof (BootString),
250 L"Boot%04x",
251 CurrentBootOptionNo
252 );
253
254 BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);
255
256 CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));
257
258 BufferSize = sizeof (UINT32) +
259 sizeof (UINT16) +
260 StrSize (BootDesc) +
261 CurrentBbsDevPathSize +
262 sizeof (BBS_TABLE) +
263 sizeof (UINT16);
264
265 Buffer = AllocateZeroPool (BufferSize);
266 if (Buffer == NULL) {
267 return EFI_OUT_OF_RESOURCES;
268 }
269
270 Ptr = (UINT8 *) Buffer;
271
272 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
273 Ptr += sizeof (UINT32);
274
275 *((UINT16 *) Ptr) = CurrentBbsDevPathSize;
276 Ptr += sizeof (UINT16);
277
278 CopyMem (
279 Ptr,
280 BootDesc,
281 StrSize (BootDesc)
282 );
283 Ptr += StrSize (BootDesc);
284
285 CopyMem (
286 Ptr,
287 CurrentBbsDevPath,
288 CurrentBbsDevPathSize
289 );
290 Ptr += CurrentBbsDevPathSize;
291
292 CopyMem (
293 Ptr,
294 CurrentBbsEntry,
295 sizeof (BBS_TABLE)
296 );
297
298 Ptr += sizeof (BBS_TABLE);
299 *((UINT16 *) Ptr) = (UINT16) Index;
300
301 Status = gRT->SetVariable (
302 BootString,
303 &gEfiGlobalVariableGuid,
304 VAR_FLAG,
305 BufferSize,
306 Buffer
307 );
308
309 SafeFreePool (Buffer);
310 Buffer = NULL;
311
312 NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));
313 if (NULL == NewBootOrderList) {
314 return EFI_OUT_OF_RESOURCES;
315 }
316
317 if (NULL != *BootOrderList) {
318 CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);
319 }
320
321 SafeFreePool (*BootOrderList);
322
323 BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));
324 NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;
325 *BootOrderListSize += sizeof (UINT16);
326 *BootOrderList = NewBootOrderList;
327
328 return Status;
329 }
330
331 BOOLEAN
332 BdsIsLegacyBootOption (
333 IN UINT8 *BootOptionVar,
334 OUT BBS_TABLE **BbsEntry,
335 OUT UINT16 *BbsIndex
336 )
337 {
338 UINT8 *Ptr;
339 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
340 BOOLEAN Ret;
341 UINT16 DevPathLen;
342
343 Ptr = BootOptionVar;
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)) {
350 Ptr += DevPathLen;
351 *BbsEntry = (BBS_TABLE *) Ptr;
352 Ptr += sizeof (BBS_TABLE);
353 *BbsIndex = *(UINT16 *) Ptr;
354 Ret = TRUE;
355 } else {
356 *BbsEntry = NULL;
357 Ret = FALSE;
358 }
359
360 return Ret;
361 }
362
363 EFI_STATUS
364 BdsDeleteBootOption (
365 IN UINTN OptionNumber,
366 IN OUT UINT16 *BootOrder,
367 IN OUT UINTN *BootOrderSize
368 )
369 {
370 UINT16 BootOption[100];
371 UINTN Index;
372 EFI_STATUS Status;
373 UINTN Index2Del;
374
375 Status = EFI_SUCCESS;
376 Index2Del = 0;
377
378 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);
379 Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);
380 //
381 // adjust boot order array
382 //
383 for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {
384 if (BootOrder[Index] == OptionNumber) {
385 Index2Del = Index;
386 break;
387 }
388 }
389
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];
394 }
395 }
396
397 *BootOrderSize -= sizeof (UINT16);
398 }
399
400 return Status;
401
402 }
403
404 EFI_STATUS
405 BdsDeleteAllInvalidLegacyBootOptions (
406 VOID
407 )
408 /*++
409
410 Routine Description:
411
412 Delete all the invalid legacy boot options.
413
414 Arguments:
415
416 None.
417
418 Returns:
419
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
424 protocol.
425
426 --*/
427 {
428 UINT16 *BootOrder;
429 UINT8 *BootOptionVar;
430 UINTN BootOrderSize;
431 UINTN BootOptionSize;
432 EFI_STATUS Status;
433 UINT16 HddCount;
434 UINT16 BbsCount;
435 HDD_INFO *LocalHddInfo;
436 BBS_TABLE *LocalBbsTable;
437 BBS_TABLE *BbsEntry;
438 UINT16 BbsIndex;
439 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
440 UINTN Index;
441 UINT16 BootOption[10];
442 UINT16 BootDesc[100];
443 BOOLEAN DescStringMatch;
444
445 Status = EFI_SUCCESS;
446 BootOrder = NULL;
447 BootOrderSize = 0;
448 HddCount = 0;
449 BbsCount = 0;
450 LocalHddInfo = NULL;
451 LocalBbsTable = NULL;
452 BbsEntry = NULL;
453
454 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
455 if (EFI_ERROR (Status)) {
456 return Status;
457 }
458
459 LegacyBios->GetBbsInfo (
460 LegacyBios,
461 &HddCount,
462 &LocalHddInfo,
463 &BbsCount,
464 &LocalBbsTable
465 );
466
467 BootOrder = BdsLibGetVariableAndSize (
468 L"BootOrder",
469 &gEfiGlobalVariableGuid,
470 &BootOrderSize
471 );
472 if (NULL == BootOrder) {
473 return EFI_NOT_FOUND;
474 }
475
476 Index = 0;
477 while (Index < BootOrderSize / sizeof (UINT16)) {
478 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
479 BootOptionVar = BdsLibGetVariableAndSize (
480 BootOption,
481 &gEfiGlobalVariableGuid,
482 &BootOptionSize
483 );
484 if (NULL == BootOptionVar) {
485 SafeFreePool (BootOrder);
486 return EFI_OUT_OF_RESOURCES;
487 }
488
489 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {
490 SafeFreePool (BootOptionVar);
491 Index++;
492 continue;
493 }
494
495 //
496 // Check if BBS Description String is changed
497 //
498 DescStringMatch = FALSE;
499
500 BdsBuildLegacyDevNameString (
501 &LocalBbsTable[BbsIndex],
502 BbsIndex,
503 sizeof(BootDesc),
504 BootDesc
505 );
506
507 if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {
508 DescStringMatch = TRUE;
509 }
510
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) &&
515 DescStringMatch) {
516 Index++;
517 continue;
518 }
519
520 SafeFreePool (BootOptionVar);
521 //
522 // should delete
523 //
524 BdsDeleteBootOption (
525 BootOrder[Index],
526 BootOrder,
527 &BootOrderSize
528 );
529 }
530
531 if (BootOrderSize) {
532 Status = gRT->SetVariable (
533 L"BootOrder",
534 &gEfiGlobalVariableGuid,
535 VAR_FLAG,
536 BootOrderSize,
537 BootOrder
538 );
539 } else {
540 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
541 }
542
543 SafeFreePool (BootOrder);
544
545 return Status;
546 }
547
548 BOOLEAN
549 BdsFindLegacyBootOptionByDevType (
550 IN UINT16 *BootOrder,
551 IN UINTN BootOptionNum,
552 IN UINT16 DevType,
553 OUT UINT32 *Attribute,
554 OUT UINT16 *BbsIndex,
555 OUT UINTN *OptionNumber
556 )
557 {
558 UINTN Index;
559 UINTN BootOrderIndex;
560 UINT16 BootOption[100];
561 UINTN BootOptionSize;
562 UINT8 *BootOptionVar;
563 BBS_TABLE *BbsEntry;
564 BOOLEAN Found;
565
566 BbsEntry = NULL;
567 Found = FALSE;
568
569 if (NULL == BootOrder) {
570 return Found;
571 }
572
573 for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {
574 Index = (UINTN) BootOrder[BootOrderIndex];
575 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);
576 BootOptionVar = BdsLibGetVariableAndSize (
577 BootOption,
578 &gEfiGlobalVariableGuid,
579 &BootOptionSize
580 );
581 if (NULL == BootOptionVar) {
582 continue;
583 }
584
585 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {
586 SafeFreePool (BootOptionVar);
587 continue;
588 }
589
590 if (BbsEntry->DeviceType != DevType) {
591 SafeFreePool (BootOptionVar);
592 continue;
593 }
594
595 *Attribute = *(UINT32 *) BootOptionVar;
596 *OptionNumber = Index;
597 Found = TRUE;
598 SafeFreePool (BootOptionVar);
599 break;
600 }
601
602 return Found;
603 }
604
605 EFI_STATUS
606 BdsCreateOneLegacyBootOption (
607 IN BBS_TABLE *BbsItem,
608 IN UINTN Index,
609 IN OUT UINT16 **BootOrderList,
610 IN OUT UINTN *BootOrderListSize
611 )
612 {
613 BBS_BBS_DEVICE_PATH BbsDevPathNode;
614 EFI_STATUS Status;
615 EFI_DEVICE_PATH_PROTOCOL *DevPath;
616
617 DevPath = NULL;
618
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));
624
625 DevPath = AppendDevicePathNode (
626 EndDevicePath,
627 (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode
628 );
629 if (NULL == DevPath) {
630 return EFI_OUT_OF_RESOURCES;
631 }
632
633 Status = BdsCreateLegacyBootOption (
634 BbsItem,
635 DevPath,
636 Index,
637 BootOrderList,
638 BootOrderListSize
639 );
640 BbsItem->BootPriority = 0x00;
641
642 FreePool (DevPath);
643
644 return Status;
645 }
646
647 EFI_STATUS
648 BdsAddNonExistingLegacyBootOptions (
649 VOID
650 )
651 /*++
652
653 Routine Description:
654
655 Add the legacy boot options from BBS table if they do not exist.
656
657 Arguments:
658
659 None.
660
661 Returns:
662
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.
665
666 --*/
667 {
668 UINT16 *BootOrder;
669 UINTN BootOrderSize;
670 EFI_STATUS Status;
671 UINT16 HddCount;
672 UINT16 BbsCount;
673 HDD_INFO *LocalHddInfo;
674 BBS_TABLE *LocalBbsTable;
675 UINT16 BbsIndex;
676 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
677 UINTN Index;
678 UINT32 Attribute;
679 UINTN OptionNumber;
680 BOOLEAN Ret;
681
682 BootOrder = NULL;
683 HddCount = 0;
684 BbsCount = 0;
685 LocalHddInfo = NULL;
686 LocalBbsTable = NULL;
687
688 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
689 if (EFI_ERROR (Status)) {
690 return Status;
691 }
692
693 LegacyBios->GetBbsInfo (
694 LegacyBios,
695 &HddCount,
696 &LocalHddInfo,
697 &BbsCount,
698 &LocalBbsTable
699 );
700
701 BootOrder = BdsLibGetVariableAndSize (
702 L"BootOrder",
703 &gEfiGlobalVariableGuid,
704 &BootOrderSize
705 );
706 if (NULL == BootOrder) {
707 BootOrderSize = 0;
708 }
709
710 for (Index = 0; Index < BbsCount; Index++) {
711 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
712 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
713 ) {
714 continue;
715 }
716
717 Ret = BdsFindLegacyBootOptionByDevType (
718 BootOrder,
719 BootOrderSize / sizeof (UINT16),
720 LocalBbsTable[Index].DeviceType,
721 &Attribute,
722 &BbsIndex,
723 &OptionNumber
724 );
725 if (Ret && (Attribute & LOAD_OPTION_ACTIVE) != 0) {
726 continue;
727 }
728
729 if (Ret) {
730 if (Index != BbsIndex) {
731 BdsDeleteBootOption (
732 OptionNumber,
733 BootOrder,
734 &BootOrderSize
735 );
736 } else {
737 continue;
738 }
739 }
740 //
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
743 //
744 Status = BdsCreateOneLegacyBootOption (
745 &LocalBbsTable[Index],
746 Index,
747 &BootOrder,
748 &BootOrderSize
749 );
750 if (EFI_ERROR (Status)) {
751 break;
752 }
753 }
754
755 if (BootOrderSize > 0) {
756 Status = gRT->SetVariable (
757 L"BootOrder",
758 &gEfiGlobalVariableGuid,
759 VAR_FLAG,
760 BootOrderSize,
761 BootOrder
762 );
763 } else {
764 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
765 }
766
767 if (BootOrder != NULL) {
768 SafeFreePool (BootOrder);
769 }
770
771 return Status;
772 }
773
774 UINT16 *
775 BdsFillDevOrderBuf (
776 IN BBS_TABLE *BbsTable,
777 IN BBS_TYPE BbsType,
778 IN UINTN BbsCount,
779 IN UINT16 *Buf
780 )
781 {
782 UINTN Index;
783
784 for (Index = 0; Index < BbsCount; Index++) {
785 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
786 continue;
787 }
788
789 if (BbsTable[Index].DeviceType != BbsType) {
790 continue;
791 }
792
793 *Buf = (UINT16) (Index & 0xFF);
794 Buf++;
795 }
796
797 return Buf;
798 }
799
800 EFI_STATUS
801 BdsCreateDevOrder (
802 IN BBS_TABLE *BbsTable,
803 IN UINT16 BbsCount
804 )
805 {
806 UINTN Index;
807 UINTN FDCount;
808 UINTN HDCount;
809 UINTN CDCount;
810 UINTN NETCount;
811 UINTN BEVCount;
812 UINTN TotalSize;
813 UINTN HeaderSize;
814 UINT8 *DevOrder;
815 UINT8 *Ptr;
816 EFI_STATUS Status;
817
818 FDCount = 0;
819 HDCount = 0;
820 CDCount = 0;
821 NETCount = 0;
822 BEVCount = 0;
823 TotalSize = 0;
824 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
825 DevOrder = NULL;
826 Ptr = NULL;
827 Status = EFI_SUCCESS;
828
829 for (Index = 0; Index < BbsCount; Index++) {
830 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
831 continue;
832 }
833
834 switch (BbsTable[Index].DeviceType) {
835 case BBS_FLOPPY:
836 FDCount++;
837 break;
838
839 case BBS_HARDDISK:
840 HDCount++;
841 break;
842
843 case BBS_CDROM:
844 CDCount++;
845 break;
846
847 case BBS_EMBED_NETWORK:
848 NETCount++;
849 break;
850
851 case BBS_BEV_DEVICE:
852 BEVCount++;
853 break;
854
855 default:
856 break;
857 }
858 }
859
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);
865
866 DevOrder = AllocateZeroPool (TotalSize);
867 if (NULL == DevOrder) {
868 return EFI_OUT_OF_RESOURCES;
869 }
870
871 Ptr = DevOrder;
872
873 *((BBS_TYPE *) Ptr) = BBS_FLOPPY;
874 Ptr += sizeof (BBS_TYPE);
875 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
876 Ptr += sizeof (UINT16);
877 if (FDCount) {
878 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);
879 }
880
881 *((BBS_TYPE *) Ptr) = BBS_HARDDISK;
882 Ptr += sizeof (BBS_TYPE);
883 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
884 Ptr += sizeof (UINT16);
885 if (HDCount) {
886 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);
887 }
888
889 *((BBS_TYPE *) Ptr) = BBS_CDROM;
890 Ptr += sizeof (BBS_TYPE);
891 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
892 Ptr += sizeof (UINT16);
893 if (CDCount) {
894 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);
895 }
896
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);
901 if (NETCount) {
902 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);
903 }
904
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);
909 if (BEVCount) {
910 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);
911 }
912
913 Status = gRT->SetVariable (
914 VarLegacyDevOrder,
915 &EfiLegacyDevOrderGuid,
916 VAR_FLAG,
917 TotalSize,
918 DevOrder
919 );
920 SafeFreePool (DevOrder);
921
922 return Status;
923 }
924
925 EFI_STATUS
926 BdsUpdateLegacyDevOrder (
927 VOID
928 )
929 /*++
930 Format of LegacyDevOrder variable:
931 |-----------------------------------------------------------------------------------------------------------------
932 | BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
933 |-----------------------------------------------------------------------------------------------------------------
934
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
938 disabled by user.
939 --*/
940 {
941 UINT8 *DevOrder;
942 UINT8 *NewDevOrder;
943 UINTN DevOrderSize;
944 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
945 EFI_STATUS Status;
946 UINT16 HddCount;
947 UINT16 BbsCount;
948 HDD_INFO *LocalHddInfo;
949 BBS_TABLE *LocalBbsTable;
950 UINTN Index;
951 UINTN Index2;
952 UINTN *Idx;
953 UINTN FDCount;
954 UINTN HDCount;
955 UINTN CDCount;
956 UINTN NETCount;
957 UINTN BEVCount;
958 UINTN TotalSize;
959 UINTN HeaderSize;
960 UINT8 *Ptr;
961 UINT8 *NewPtr;
962 UINT16 *NewFDPtr;
963 UINT16 *NewHDPtr;
964 UINT16 *NewCDPtr;
965 UINT16 *NewNETPtr;
966 UINT16 *NewBEVPtr;
967 UINT16 *NewDevPtr;
968 UINT16 Length;
969 UINT16 tmp;
970 UINTN FDIndex;
971 UINTN HDIndex;
972 UINTN CDIndex;
973 UINTN NETIndex;
974 UINTN BEVIndex;
975
976 LocalHddInfo = NULL;
977 LocalBbsTable = NULL;
978 Idx = NULL;
979 FDCount = 0;
980 HDCount = 0;
981 CDCount = 0;
982 NETCount = 0;
983 BEVCount = 0;
984 TotalSize = 0;
985 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
986 FDIndex = 0;
987 HDIndex = 0;
988 CDIndex = 0;
989 NETIndex = 0;
990 BEVIndex = 0;
991 NewDevPtr = NULL;
992
993 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
994 if (EFI_ERROR (Status)) {
995 return Status;
996 }
997
998 LegacyBios->GetBbsInfo (
999 LegacyBios,
1000 &HddCount,
1001 &LocalHddInfo,
1002 &BbsCount,
1003 &LocalBbsTable
1004 );
1005
1006 DevOrder = (UINT8 *) BdsLibGetVariableAndSize (
1007 VarLegacyDevOrder,
1008 &EfiLegacyDevOrderGuid,
1009 &DevOrderSize
1010 );
1011 if (NULL == DevOrder) {
1012 return BdsCreateDevOrder (LocalBbsTable, BbsCount);
1013 }
1014 //
1015 // First we figure out how many boot devices with same device type respectively
1016 //
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)
1021 ) {
1022 continue;
1023 }
1024
1025 switch (LocalBbsTable[Index].DeviceType) {
1026 case BBS_FLOPPY:
1027 FDCount++;
1028 break;
1029
1030 case BBS_HARDDISK:
1031 HDCount++;
1032 break;
1033
1034 case BBS_CDROM:
1035 CDCount++;
1036 break;
1037
1038 case BBS_EMBED_NETWORK:
1039 NETCount++;
1040 break;
1041
1042 case BBS_BEV_DEVICE:
1043 BEVCount++;
1044 break;
1045
1046 default:
1047 break;
1048 }
1049 }
1050
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));
1056
1057 NewDevOrder = AllocateZeroPool (TotalSize);
1058 if (NULL == NewDevOrder) {
1059 return EFI_OUT_OF_RESOURCES;
1060 }
1061
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);
1067
1068 //
1069 // copy FD
1070 //
1071 Ptr = DevOrder;
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);
1079
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
1085 ) {
1086 Ptr += sizeof (UINT16);
1087 continue;
1088 }
1089
1090 NewFDPtr[FDIndex] = *(UINT16 *) Ptr;
1091 FDIndex++;
1092 Ptr += sizeof (UINT16);
1093 }
1094 //
1095 // copy HD
1096 //
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);
1104
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
1110 ) {
1111 Ptr += sizeof (UINT16);
1112 continue;
1113 }
1114
1115 NewHDPtr[HDIndex] = *(UINT16 *) Ptr;
1116 HDIndex++;
1117 Ptr += sizeof (UINT16);
1118 }
1119 //
1120 // copy CD
1121 //
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);
1129
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
1135 ) {
1136 Ptr += sizeof (UINT16);
1137 continue;
1138 }
1139
1140 NewCDPtr[CDIndex] = *(UINT16 *) Ptr;
1141 CDIndex++;
1142 Ptr += sizeof (UINT16);
1143 }
1144 //
1145 // copy NET
1146 //
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);
1154
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
1160 ) {
1161 Ptr += sizeof (UINT16);
1162 continue;
1163 }
1164
1165 NewNETPtr[NETIndex] = *(UINT16 *) Ptr;
1166 NETIndex++;
1167 Ptr += sizeof (UINT16);
1168 }
1169 //
1170 // copy BEV
1171 //
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);
1179
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
1185 ) {
1186 Ptr += sizeof (UINT16);
1187 continue;
1188 }
1189
1190 NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;
1191 BEVIndex++;
1192 Ptr += sizeof (UINT16);
1193 }
1194
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)
1199 ) {
1200 continue;
1201 }
1202
1203 switch (LocalBbsTable[Index].DeviceType) {
1204 case BBS_FLOPPY:
1205 Idx = &FDIndex;
1206 NewDevPtr = NewFDPtr;
1207 break;
1208
1209 case BBS_HARDDISK:
1210 Idx = &HDIndex;
1211 NewDevPtr = NewHDPtr;
1212 break;
1213
1214 case BBS_CDROM:
1215 Idx = &CDIndex;
1216 NewDevPtr = NewCDPtr;
1217 break;
1218
1219 case BBS_EMBED_NETWORK:
1220 Idx = &NETIndex;
1221 NewDevPtr = NewNETPtr;
1222 break;
1223
1224 case BBS_BEV_DEVICE:
1225 Idx = &BEVIndex;
1226 NewDevPtr = NewBEVPtr;
1227 break;
1228
1229 default:
1230 Idx = NULL;
1231 break;
1232 }
1233 //
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
1236 //
1237 if (Idx) {
1238 for (Index2 = 0; Index2 < *Idx; Index2++) {
1239 if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
1240 break;
1241 }
1242 }
1243
1244 if (Index2 == *Idx) {
1245 //
1246 // Index2 == *Idx means we didn't find Index
1247 // so Index is a new appeared device's index in BBS table
1248 // save it.
1249 //
1250 NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);
1251 (*Idx)++;
1252 }
1253 }
1254 }
1255
1256 if (FDCount) {
1257 //
1258 // Just to make sure that disabled indexes are all at the end of the array
1259 //
1260 for (Index = 0; Index < FDIndex - 1; Index++) {
1261 if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {
1262 continue;
1263 }
1264
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;
1270 break;
1271 }
1272 }
1273 }
1274 }
1275
1276 if (HDCount) {
1277 //
1278 // Just to make sure that disabled indexes are all at the end of the array
1279 //
1280 for (Index = 0; Index < HDIndex - 1; Index++) {
1281 if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {
1282 continue;
1283 }
1284
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;
1290 break;
1291 }
1292 }
1293 }
1294 }
1295
1296 if (CDCount) {
1297 //
1298 // Just to make sure that disabled indexes are all at the end of the array
1299 //
1300 for (Index = 0; Index < CDIndex - 1; Index++) {
1301 if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {
1302 continue;
1303 }
1304
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;
1310 break;
1311 }
1312 }
1313 }
1314 }
1315
1316 if (NETCount) {
1317 //
1318 // Just to make sure that disabled indexes are all at the end of the array
1319 //
1320 for (Index = 0; Index < NETIndex - 1; Index++) {
1321 if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {
1322 continue;
1323 }
1324
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;
1330 break;
1331 }
1332 }
1333 }
1334 }
1335
1336 if (BEVCount) {
1337 //
1338 // Just to make sure that disabled indexes are all at the end of the array
1339 //
1340 for (Index = 0; Index < BEVIndex - 1; Index++) {
1341 if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {
1342 continue;
1343 }
1344
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;
1350 break;
1351 }
1352 }
1353 }
1354 }
1355
1356 SafeFreePool (DevOrder);
1357
1358 Status = gRT->SetVariable (
1359 VarLegacyDevOrder,
1360 &EfiLegacyDevOrderGuid,
1361 VAR_FLAG,
1362 TotalSize,
1363 NewDevOrder
1364 );
1365 SafeFreePool (NewDevOrder);
1366
1367 return Status;
1368 }
1369
1370 EFI_STATUS
1371 BdsSetBootPriority4SameTypeDev (
1372 IN UINT16 DeviceType,
1373 IN OUT BBS_TABLE *LocalBbsTable,
1374 IN OUT UINT16 *Priority
1375 )
1376 /*++
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.
1381 --*/
1382 {
1383 UINT8 *DevOrder;
1384
1385 UINT8 *OrigBuffer;
1386 UINT16 *DevIndex;
1387 UINTN DevOrderSize;
1388 UINTN DevCount;
1389 UINTN Index;
1390
1391 DevOrder = BdsLibGetVariableAndSize (
1392 VarLegacyDevOrder,
1393 &EfiLegacyDevOrderGuid,
1394 &DevOrderSize
1395 );
1396 if (NULL == DevOrder) {
1397 return EFI_OUT_OF_RESOURCES;
1398 }
1399
1400 OrigBuffer = DevOrder;
1401 while (DevOrder < OrigBuffer + DevOrderSize) {
1402 if (DeviceType == * (BBS_TYPE *) DevOrder) {
1403 break;
1404 }
1405
1406 DevOrder += sizeof (BBS_TYPE);
1407 DevOrder += *(UINT16 *) DevOrder;
1408 }
1409
1410 if (DevOrder >= OrigBuffer + DevOrderSize) {
1411 SafeFreePool (OrigBuffer);
1412 return EFI_NOT_FOUND;
1413 }
1414
1415 DevOrder += sizeof (BBS_TYPE);
1416 DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);
1417 DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));
1418 //
1419 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1420 //
1421 for (Index = 0; Index < DevCount; Index++) {
1422 if ((DevIndex[Index] & 0xFF00) == 0xFF00) {
1423 //
1424 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1425 //
1426 } else {
1427 LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;
1428 (*Priority)++;
1429 }
1430 }
1431
1432 SafeFreePool (OrigBuffer);
1433 return EFI_SUCCESS;
1434 }
1435
1436 VOID
1437 PrintBbsTable (
1438 IN BBS_TABLE *LocalBbsTable
1439 )
1440 {
1441 UINT16 Idx;
1442
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)
1450 ) {
1451 continue;
1452 }
1453
1454 DEBUG (
1455 (EFI_D_ERROR,
1456 " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
1457 (UINTN) Idx,
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))
1470 );
1471 }
1472
1473 DEBUG ((EFI_D_ERROR, "\n"));
1474 }
1475
1476 EFI_STATUS
1477 BdsRefreshBbsTableForBoot (
1478 IN BDS_COMMON_OPTION *Entry
1479 )
1480 {
1481 EFI_STATUS Status;
1482 UINT16 HddCount;
1483 UINT16 BbsCount;
1484 HDD_INFO *LocalHddInfo;
1485 BBS_TABLE *LocalBbsTable;
1486 UINT16 DevType;
1487 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
1488 UINTN Index;
1489 UINT16 Priority;
1490 UINT16 *BootOrder;
1491 UINTN BootOrderSize;
1492 UINT8 *BootOptionVar;
1493 UINTN BootOptionSize;
1494 UINT16 BootOption[100];
1495 UINT8 *Ptr;
1496 UINT16 DevPathLen;
1497 EFI_DEVICE_PATH_PROTOCOL *DevPath;
1498
1499 HddCount = 0;
1500 BbsCount = 0;
1501 LocalHddInfo = NULL;
1502 LocalBbsTable = NULL;
1503 DevType = BBS_UNKNOWN;
1504
1505 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
1506 if (EFI_ERROR (Status)) {
1507 return Status;
1508 }
1509
1510 LegacyBios->GetBbsInfo (
1511 LegacyBios,
1512 &HddCount,
1513 &LocalHddInfo,
1514 &BbsCount,
1515 &LocalBbsTable
1516 );
1517 //
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
1520 //
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;
1526 }
1527 }
1528 //
1529 // boot priority always starts at 0
1530 //
1531 Priority = 0;
1532 if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
1533 //
1534 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1535 //
1536 DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
1537 Status = BdsSetBootPriority4SameTypeDev (
1538 DevType,
1539 LocalBbsTable,
1540 &Priority
1541 );
1542 if (EFI_ERROR (Status)) {
1543 return Status;
1544 }
1545 }
1546 //
1547 // we have to set the boot priority for other BBS entries with different device types
1548 //
1549 BootOrder = (UINT16 *) BdsLibGetVariableAndSize (
1550 L"BootOrder",
1551 &gEfiGlobalVariableGuid,
1552 &BootOrderSize
1553 );
1554 for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) {
1555 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
1556 BootOptionVar = BdsLibGetVariableAndSize (
1557 BootOption,
1558 &gEfiGlobalVariableGuid,
1559 &BootOptionSize
1560 );
1561 if (NULL == BootOptionVar) {
1562 continue;
1563 }
1564
1565 Ptr = BootOptionVar;
1566
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);
1574 continue;
1575 }
1576
1577 Ptr += DevPathLen;
1578 if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {
1579 //
1580 // We don't want to process twice for a device type
1581 //
1582 SafeFreePool (BootOptionVar);
1583 continue;
1584 }
1585
1586 Status = BdsSetBootPriority4SameTypeDev (
1587 ((BBS_TABLE *) Ptr)->DeviceType,
1588 LocalBbsTable,
1589 &Priority
1590 );
1591 SafeFreePool (BootOptionVar);
1592 if (EFI_ERROR (Status)) {
1593 break;
1594 }
1595 }
1596
1597 if (BootOrder) {
1598 SafeFreePool (BootOrder);
1599 }
1600 //
1601 // For debug
1602 //
1603 PrintBbsTable (LocalBbsTable);
1604
1605 return Status;
1606 }