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