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