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