]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
4d5a4580c68448beba770fad4dc19dfd34d6ff20
[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 AStr Pointer to input Ascii string.
28 @param Size The number of characters to translate.
29 @param UStr Pointer to output Unicode string buffer.
30
31 @return None
32
33 **/
34 VOID
35 AsciiToUnicodeSize (
36 IN UINT8 *AStr,
37 IN UINTN Size,
38 OUT UINT16 *UStr
39 )
40 {
41 UINTN Idx;
42
43 Idx = 0;
44 while (AStr[Idx] != 0) {
45 UStr[Idx] = (CHAR16) AStr[Idx];
46 if (Idx == Size) {
47 break;
48 }
49
50 Idx++;
51 }
52 UStr[Idx] = 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 Build Legacy Device Name String according.
89
90 @param CurBBSEntry BBS Table.
91 @param Index Index.
92 @param BufSize The buffer size.
93 @param BootString The output string.
94
95 @return VOID No output.
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 Check if the boot option is a legacy one.
390
391 @param BootOptionVar The boot option data payload.
392 @param BbsEntry The BBS Table.
393 @param BbsIndex The table index.
394
395 @retval TRUE It is a legacy boot option.
396 @retval FALSE It is not a legacy boot option.
397
398 **/
399 BOOLEAN
400 BdsIsLegacyBootOption (
401 IN UINT8 *BootOptionVar,
402 OUT BBS_TABLE **BbsEntry,
403 OUT UINT16 *BbsIndex
404 )
405 {
406 UINT8 *Ptr;
407 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
408 BOOLEAN Ret;
409 UINT16 DevPathLen;
410
411 Ptr = BootOptionVar;
412 Ptr += sizeof (UINT32);
413 DevPathLen = *(UINT16 *) Ptr;
414 Ptr += sizeof (UINT16);
415 Ptr += StrSize ((UINT16 *) Ptr);
416 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
417 if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
418 Ptr += DevPathLen;
419 *BbsEntry = (BBS_TABLE *) Ptr;
420 Ptr += sizeof (BBS_TABLE);
421 *BbsIndex = *(UINT16 *) Ptr;
422 Ret = TRUE;
423 } else {
424 *BbsEntry = NULL;
425 Ret = FALSE;
426 }
427
428 return Ret;
429 }
430
431 /**
432 Delete all the invalid legacy boot options.
433
434
435
436 @retval EFI_SUCCESS All invalide legacy boot options are deleted.
437 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.
438 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.
439 **/
440 EFI_STATUS
441 BdsDeleteAllInvalidLegacyBootOptions (
442 VOID
443 )
444 {
445 UINT16 *BootOrder;
446 UINT8 *BootOptionVar;
447 UINTN BootOrderSize;
448 UINTN BootOptionSize;
449 EFI_STATUS Status;
450 UINT16 HddCount;
451 UINT16 BbsCount;
452 HDD_INFO *LocalHddInfo;
453 BBS_TABLE *LocalBbsTable;
454 BBS_TABLE *BbsEntry;
455 UINT16 BbsIndex;
456 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
457 UINTN Index;
458 UINT16 BootOption[10];
459 UINT16 BootDesc[100];
460 BOOLEAN DescStringMatch;
461
462 Status = EFI_SUCCESS;
463 BootOrder = NULL;
464 BootOrderSize = 0;
465 HddCount = 0;
466 BbsCount = 0;
467 LocalHddInfo = NULL;
468 LocalBbsTable = NULL;
469 BbsEntry = NULL;
470
471 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
472 if (EFI_ERROR (Status)) {
473 return Status;
474 }
475
476 LegacyBios->GetBbsInfo (
477 LegacyBios,
478 &HddCount,
479 &LocalHddInfo,
480 &BbsCount,
481 &LocalBbsTable
482 );
483
484 BootOrder = BdsLibGetVariableAndSize (
485 L"BootOrder",
486 &gEfiGlobalVariableGuid,
487 &BootOrderSize
488 );
489 if (NULL == BootOrder) {
490 return EFI_NOT_FOUND;
491 }
492
493 Index = 0;
494 while (Index < BootOrderSize / sizeof (UINT16)) {
495 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
496 BootOptionVar = BdsLibGetVariableAndSize (
497 BootOption,
498 &gEfiGlobalVariableGuid,
499 &BootOptionSize
500 );
501 if (NULL == BootOptionVar) {
502 SafeFreePool (BootOrder);
503 return EFI_OUT_OF_RESOURCES;
504 }
505
506 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {
507 SafeFreePool (BootOptionVar);
508 Index++;
509 continue;
510 }
511
512 //
513 // Check if BBS Description String is changed
514 //
515 DescStringMatch = FALSE;
516
517 BdsBuildLegacyDevNameString (
518 &LocalBbsTable[BbsIndex],
519 BbsIndex,
520 sizeof(BootDesc),
521 BootDesc
522 );
523
524 if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {
525 DescStringMatch = TRUE;
526 }
527
528 if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||
529 (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&
530 (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&
531 DescStringMatch) {
532 Index++;
533 continue;
534 }
535
536 SafeFreePool (BootOptionVar);
537 //
538 // should delete
539 //
540 BdsDeleteBootOption (
541 BootOrder[Index],
542 BootOrder,
543 &BootOrderSize
544 );
545 }
546
547 if (BootOrderSize != 0) {
548 Status = gRT->SetVariable (
549 L"BootOrder",
550 &gEfiGlobalVariableGuid,
551 VAR_FLAG,
552 BootOrderSize,
553 BootOrder
554 );
555 } else {
556 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
557 }
558
559 SafeFreePool (BootOrder);
560
561 return Status;
562 }
563
564 /**
565 Find all legacy boot option by device type.
566
567 @param BootOrder The boot order array.
568 @param BootOptionNum The number of boot option.
569 @param DevType Device type.
570 @param Attribute The boot option attribute.
571 @param BbsIndex The BBS table index.
572 @param OptionNumber The boot option index.
573
574 @retval TRUE The Legacy boot option is found.
575 @retval FALSE The legacy boot option is not found.
576
577 **/
578 BOOLEAN
579 BdsFindLegacyBootOptionByDevType (
580 IN UINT16 *BootOrder,
581 IN UINTN BootOptionNum,
582 IN UINT16 DevType,
583 OUT UINT32 *Attribute,
584 OUT UINT16 *BbsIndex,
585 OUT UINTN *OptionNumber
586 )
587 {
588 UINTN Index;
589 UINTN BootOrderIndex;
590 UINT16 BootOption[100];
591 UINTN BootOptionSize;
592 UINT8 *BootOptionVar;
593 BBS_TABLE *BbsEntry;
594 BOOLEAN Found;
595
596 BbsEntry = NULL;
597 Found = FALSE;
598
599 if (NULL == BootOrder) {
600 return Found;
601 }
602
603 for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {
604 Index = (UINTN) BootOrder[BootOrderIndex];
605 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);
606 BootOptionVar = BdsLibGetVariableAndSize (
607 BootOption,
608 &gEfiGlobalVariableGuid,
609 &BootOptionSize
610 );
611 if (NULL == BootOptionVar) {
612 continue;
613 }
614
615 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {
616 SafeFreePool (BootOptionVar);
617 continue;
618 }
619
620 if (BbsEntry->DeviceType != DevType) {
621 SafeFreePool (BootOptionVar);
622 continue;
623 }
624
625 *Attribute = *(UINT32 *) BootOptionVar;
626 *OptionNumber = Index;
627 Found = TRUE;
628 SafeFreePool (BootOptionVar);
629 break;
630 }
631
632 return Found;
633 }
634
635 /**
636 Create a legacy boot option.
637
638 @param BbsItem The BBS Table entry.
639 @param Index Index of the specified entry in BBS table.
640 @param BootOrderList The boot order list.
641 @param BootOrderListSize The size of boot order list.
642
643 @retval EFI_OUT_OF_RESOURCE No enough memory.
644 @retval EFI_SUCCESS The function complete successfully.
645 @return Other value if the legacy boot option is not created.
646
647 **/
648 EFI_STATUS
649 BdsCreateOneLegacyBootOption (
650 IN BBS_TABLE *BbsItem,
651 IN UINTN Index,
652 IN OUT UINT16 **BootOrderList,
653 IN OUT UINTN *BootOrderListSize
654 )
655 {
656 BBS_BBS_DEVICE_PATH BbsDevPathNode;
657 EFI_STATUS Status;
658 EFI_DEVICE_PATH_PROTOCOL *DevPath;
659
660 DevPath = NULL;
661
662 BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;
663 BbsDevPathNode.Header.SubType = BBS_BBS_DP;
664 SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));
665 BbsDevPathNode.DeviceType = BbsItem->DeviceType;
666 CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));
667
668 DevPath = AppendDevicePathNode (
669 EndDevicePath,
670 (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode
671 );
672 if (NULL == DevPath) {
673 return EFI_OUT_OF_RESOURCES;
674 }
675
676 Status = BdsCreateLegacyBootOption (
677 BbsItem,
678 DevPath,
679 Index,
680 BootOrderList,
681 BootOrderListSize
682 );
683 BbsItem->BootPriority = 0x00;
684
685 FreePool (DevPath);
686
687 return Status;
688 }
689
690 /**
691
692 Add the legacy boot options from BBS table if they do not exist.
693
694
695
696 @retval EFI_SUCCESS The boot options are added successfully
697 or they are already in boot options.
698
699 **/
700 EFI_STATUS
701 BdsAddNonExistingLegacyBootOptions (
702 VOID
703 )
704 {
705 UINT16 *BootOrder;
706 UINTN BootOrderSize;
707 EFI_STATUS Status;
708 UINT16 HddCount;
709 UINT16 BbsCount;
710 HDD_INFO *LocalHddInfo;
711 BBS_TABLE *LocalBbsTable;
712 UINT16 BbsIndex;
713 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
714 UINTN Index;
715 UINT32 Attribute;
716 UINTN OptionNumber;
717 BOOLEAN Ret;
718
719 BootOrder = NULL;
720 HddCount = 0;
721 BbsCount = 0;
722 LocalHddInfo = NULL;
723 LocalBbsTable = NULL;
724
725 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
726 if (EFI_ERROR (Status)) {
727 return Status;
728 }
729
730 LegacyBios->GetBbsInfo (
731 LegacyBios,
732 &HddCount,
733 &LocalHddInfo,
734 &BbsCount,
735 &LocalBbsTable
736 );
737
738 BootOrder = BdsLibGetVariableAndSize (
739 L"BootOrder",
740 &gEfiGlobalVariableGuid,
741 &BootOrderSize
742 );
743 if (NULL == BootOrder) {
744 BootOrderSize = 0;
745 }
746
747 for (Index = 0; Index < BbsCount; Index++) {
748 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
749 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
750 ) {
751 continue;
752 }
753
754 Ret = BdsFindLegacyBootOptionByDevType (
755 BootOrder,
756 BootOrderSize / sizeof (UINT16),
757 LocalBbsTable[Index].DeviceType,
758 &Attribute,
759 &BbsIndex,
760 &OptionNumber
761 );
762 if (Ret) {
763 continue;
764 }
765
766 //
767 // Not found such type of legacy device in boot options or we found but it's disabled
768 // so we have to create one and put it to the tail of boot order list
769 //
770 Status = BdsCreateOneLegacyBootOption (
771 &LocalBbsTable[Index],
772 Index,
773 &BootOrder,
774 &BootOrderSize
775 );
776 if (EFI_ERROR (Status)) {
777 break;
778 }
779 }
780
781 if (BootOrderSize > 0) {
782 Status = gRT->SetVariable (
783 L"BootOrder",
784 &gEfiGlobalVariableGuid,
785 VAR_FLAG,
786 BootOrderSize,
787 BootOrder
788 );
789 } else {
790 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
791 }
792
793 if (BootOrder != NULL) {
794 SafeFreePool (BootOrder);
795 }
796
797 return Status;
798 }
799
800 /**
801 Fill the device order buffer.
802
803 @param BbsTable The BBS table.
804 @param BbsType The BBS Type.
805 @param BbsCount The BBS Count.
806 @param Buf device order buffer.
807
808 @return The device order buffer.
809
810 **/
811 UINT16 *
812 BdsFillDevOrderBuf (
813 IN BBS_TABLE *BbsTable,
814 IN BBS_TYPE BbsType,
815 IN UINTN BbsCount,
816 OUT UINT16 *Buf
817 )
818 {
819 UINTN Index;
820
821 for (Index = 0; Index < BbsCount; Index++) {
822 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
823 continue;
824 }
825
826 if (BbsTable[Index].DeviceType != BbsType) {
827 continue;
828 }
829
830 *Buf = (UINT16) (Index & 0xFF);
831 Buf++;
832 }
833
834 return Buf;
835 }
836
837 /**
838 Create the device order buffer.
839
840 @param BbsTable The BBS table.
841 @param BbsCount The BBS Count.
842
843 @retval EFI_SUCCES The buffer is created and the EFI variable named
844 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
845 set correctly.
846 @return Other value if the set of EFI variable fails. Check gRT->SetVariable
847 for detailed information.
848
849 **/
850 EFI_STATUS
851 BdsCreateDevOrder (
852 IN BBS_TABLE *BbsTable,
853 IN UINT16 BbsCount
854 )
855 {
856 UINTN Index;
857 UINTN FDCount;
858 UINTN HDCount;
859 UINTN CDCount;
860 UINTN NETCount;
861 UINTN BEVCount;
862 UINTN TotalSize;
863 UINTN HeaderSize;
864 UINT8 *DevOrder;
865 UINT8 *Ptr;
866 EFI_STATUS Status;
867
868 FDCount = 0;
869 HDCount = 0;
870 CDCount = 0;
871 NETCount = 0;
872 BEVCount = 0;
873 TotalSize = 0;
874 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
875 DevOrder = NULL;
876 Ptr = NULL;
877 Status = EFI_SUCCESS;
878
879 for (Index = 0; Index < BbsCount; Index++) {
880 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
881 continue;
882 }
883
884 switch (BbsTable[Index].DeviceType) {
885 case BBS_FLOPPY:
886 FDCount++;
887 break;
888
889 case BBS_HARDDISK:
890 HDCount++;
891 break;
892
893 case BBS_CDROM:
894 CDCount++;
895 break;
896
897 case BBS_EMBED_NETWORK:
898 NETCount++;
899 break;
900
901 case BBS_BEV_DEVICE:
902 BEVCount++;
903 break;
904
905 default:
906 break;
907 }
908 }
909
910 TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
911 TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
912 TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
913 TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
914 TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
915
916 DevOrder = AllocateZeroPool (TotalSize);
917 if (NULL == DevOrder) {
918 return EFI_OUT_OF_RESOURCES;
919 }
920
921 Ptr = DevOrder;
922
923 *((BBS_TYPE *) Ptr) = BBS_FLOPPY;
924 Ptr += sizeof (BBS_TYPE);
925 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
926 Ptr += sizeof (UINT16);
927 if (FDCount != 0) {
928 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);
929 }
930
931 *((BBS_TYPE *) Ptr) = BBS_HARDDISK;
932 Ptr += sizeof (BBS_TYPE);
933 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
934 Ptr += sizeof (UINT16);
935 if (HDCount != 0) {
936 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);
937 }
938
939 *((BBS_TYPE *) Ptr) = BBS_CDROM;
940 Ptr += sizeof (BBS_TYPE);
941 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
942 Ptr += sizeof (UINT16);
943 if (CDCount != 0) {
944 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);
945 }
946
947 *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;
948 Ptr += sizeof (BBS_TYPE);
949 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
950 Ptr += sizeof (UINT16);
951 if (NETCount != 0) {
952 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);
953 }
954
955 *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;
956 Ptr += sizeof (BBS_TYPE);
957 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
958 Ptr += sizeof (UINT16);
959 if (BEVCount != 0) {
960 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);
961 }
962
963 Status = gRT->SetVariable (
964 VAR_LEGACY_DEV_ORDER,
965 &EfiLegacyDevOrderGuid,
966 VAR_FLAG,
967 TotalSize,
968 DevOrder
969 );
970 SafeFreePool (DevOrder);
971
972 return Status;
973 }
974
975 /**
976
977 Add the legacy boot devices from BBS table into
978 the legacy device boot order.
979
980 @retval EFI_SUCCESS The boot devices are added successfully.
981
982 **/
983 EFI_STATUS
984 BdsUpdateLegacyDevOrder (
985 VOID
986 )
987 {
988 UINT8 *DevOrder;
989 UINT8 *NewDevOrder;
990 UINTN DevOrderSize;
991 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
992 EFI_STATUS Status;
993 UINT16 HddCount;
994 UINT16 BbsCount;
995 HDD_INFO *LocalHddInfo;
996 BBS_TABLE *LocalBbsTable;
997 UINTN Index;
998 UINTN Index2;
999 UINTN *Idx;
1000 UINTN FDCount;
1001 UINTN HDCount;
1002 UINTN CDCount;
1003 UINTN NETCount;
1004 UINTN BEVCount;
1005 UINTN TotalSize;
1006 UINTN HeaderSize;
1007 UINT8 *Ptr;
1008 UINT8 *NewPtr;
1009 UINT16 *NewFDPtr;
1010 UINT16 *NewHDPtr;
1011 UINT16 *NewCDPtr;
1012 UINT16 *NewNETPtr;
1013 UINT16 *NewBEVPtr;
1014 UINT16 *NewDevPtr;
1015 UINT16 Length;
1016 UINT16 Tmp;
1017 UINTN FDIndex;
1018 UINTN HDIndex;
1019 UINTN CDIndex;
1020 UINTN NETIndex;
1021 UINTN BEVIndex;
1022
1023 LocalHddInfo = NULL;
1024 LocalBbsTable = NULL;
1025 Idx = NULL;
1026 FDCount = 0;
1027 HDCount = 0;
1028 CDCount = 0;
1029 NETCount = 0;
1030 BEVCount = 0;
1031 TotalSize = 0;
1032 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
1033 FDIndex = 0;
1034 HDIndex = 0;
1035 CDIndex = 0;
1036 NETIndex = 0;
1037 BEVIndex = 0;
1038 NewDevPtr = NULL;
1039
1040 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
1041 if (EFI_ERROR (Status)) {
1042 return Status;
1043 }
1044
1045 LegacyBios->GetBbsInfo (
1046 LegacyBios,
1047 &HddCount,
1048 &LocalHddInfo,
1049 &BbsCount,
1050 &LocalBbsTable
1051 );
1052
1053 DevOrder = (UINT8 *) BdsLibGetVariableAndSize (
1054 VAR_LEGACY_DEV_ORDER,
1055 &EfiLegacyDevOrderGuid,
1056 &DevOrderSize
1057 );
1058 if (NULL == DevOrder) {
1059 return BdsCreateDevOrder (LocalBbsTable, BbsCount);
1060 }
1061 //
1062 // First we figure out how many boot devices with same device type respectively
1063 //
1064 for (Index = 0; Index < BbsCount; Index++) {
1065 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
1066 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
1067 ) {
1068 continue;
1069 }
1070
1071 switch (LocalBbsTable[Index].DeviceType) {
1072 case BBS_FLOPPY:
1073 FDCount++;
1074 break;
1075
1076 case BBS_HARDDISK:
1077 HDCount++;
1078 break;
1079
1080 case BBS_CDROM:
1081 CDCount++;
1082 break;
1083
1084 case BBS_EMBED_NETWORK:
1085 NETCount++;
1086 break;
1087
1088 case BBS_BEV_DEVICE:
1089 BEVCount++;
1090 break;
1091
1092 default:
1093 break;
1094 }
1095 }
1096
1097 TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
1098 TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
1099 TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
1100 TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
1101 TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
1102
1103 NewDevOrder = AllocateZeroPool (TotalSize);
1104 if (NULL == NewDevOrder) {
1105 return EFI_OUT_OF_RESOURCES;
1106 }
1107
1108 NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);
1109 NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);
1110 NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);
1111 NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);
1112 NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);
1113
1114 //
1115 // copy FD
1116 //
1117 Ptr = DevOrder;
1118 NewPtr = NewDevOrder;
1119 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1120 Ptr += sizeof (BBS_TYPE);
1121 NewPtr += sizeof (BBS_TYPE);
1122 Length = *((UINT16 *) Ptr);
1123 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
1124 Ptr += sizeof (UINT16);
1125
1126 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1127 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1128 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1129 LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY
1130 ) {
1131 Ptr += sizeof (UINT16);
1132 continue;
1133 }
1134
1135 NewFDPtr[FDIndex] = *(UINT16 *) Ptr;
1136 FDIndex++;
1137 Ptr += sizeof (UINT16);
1138 }
1139 //
1140 // copy HD
1141 //
1142 NewPtr = (UINT8 *) NewHDPtr - 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) + HDCount * 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_HARDDISK
1155 ) {
1156 Ptr += sizeof (UINT16);
1157 continue;
1158 }
1159
1160 NewHDPtr[HDIndex] = *(UINT16 *) Ptr;
1161 HDIndex++;
1162 Ptr += sizeof (UINT16);
1163 }
1164 //
1165 // copy CD
1166 //
1167 NewPtr = (UINT8 *) NewCDPtr - 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) + CDCount * 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_CDROM
1180 ) {
1181 Ptr += sizeof (UINT16);
1182 continue;
1183 }
1184
1185 NewCDPtr[CDIndex] = *(UINT16 *) Ptr;
1186 CDIndex++;
1187 Ptr += sizeof (UINT16);
1188 }
1189 //
1190 // copy NET
1191 //
1192 NewPtr = (UINT8 *) NewNETPtr - HeaderSize;
1193 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1194 Ptr += sizeof (BBS_TYPE);
1195 NewPtr += sizeof (BBS_TYPE);
1196 Length = *((UINT16 *) Ptr);
1197 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
1198 Ptr += sizeof (UINT16);
1199
1200 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1201 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1202 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1203 LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
1204 LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK
1205 ) {
1206 Ptr += sizeof (UINT16);
1207 continue;
1208 }
1209
1210 NewNETPtr[NETIndex] = *(UINT16 *) Ptr;
1211 NETIndex++;
1212 Ptr += sizeof (UINT16);
1213 }
1214 //
1215 // copy BEV
1216 //
1217 NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;
1218 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1219 Ptr += sizeof (BBS_TYPE);
1220 NewPtr += sizeof (BBS_TYPE);
1221 Length = *((UINT16 *) Ptr);
1222 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
1223 Ptr += sizeof (UINT16);
1224
1225 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1226 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1227 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1228 LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
1229 LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE
1230 ) {
1231 Ptr += sizeof (UINT16);
1232 continue;
1233 }
1234
1235 NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;
1236 BEVIndex++;
1237 Ptr += sizeof (UINT16);
1238 }
1239
1240 for (Index = 0; Index < BbsCount; Index++) {
1241 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
1242 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
1243 ) {
1244 continue;
1245 }
1246
1247 switch (LocalBbsTable[Index].DeviceType) {
1248 case BBS_FLOPPY:
1249 Idx = &FDIndex;
1250 NewDevPtr = NewFDPtr;
1251 break;
1252
1253 case BBS_HARDDISK:
1254 Idx = &HDIndex;
1255 NewDevPtr = NewHDPtr;
1256 break;
1257
1258 case BBS_CDROM:
1259 Idx = &CDIndex;
1260 NewDevPtr = NewCDPtr;
1261 break;
1262
1263 case BBS_EMBED_NETWORK:
1264 Idx = &NETIndex;
1265 NewDevPtr = NewNETPtr;
1266 break;
1267
1268 case BBS_BEV_DEVICE:
1269 Idx = &BEVIndex;
1270 NewDevPtr = NewBEVPtr;
1271 break;
1272
1273 default:
1274 Idx = NULL;
1275 break;
1276 }
1277 //
1278 // at this point we have copied those valid indexes to new buffer
1279 // and we should check if there is any new appeared boot device
1280 //
1281 if (Idx != 0) {
1282 for (Index2 = 0; Index2 < *Idx; Index2++) {
1283 if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
1284 break;
1285 }
1286 }
1287
1288 if (Index2 == *Idx) {
1289 //
1290 // Index2 == *Idx means we didn't find Index
1291 // so Index is a new appeared device's index in BBS table
1292 // save it.
1293 //
1294 NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);
1295 (*Idx)++;
1296 }
1297 }
1298 }
1299
1300 if (FDCount != 0) {
1301 //
1302 // Just to make sure that disabled indexes are all at the end of the array
1303 //
1304 for (Index = 0; Index < FDIndex - 1; Index++) {
1305 if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {
1306 continue;
1307 }
1308
1309 for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {
1310 if (0 == (NewFDPtr[Index2] & 0xFF00)) {
1311 Tmp = NewFDPtr[Index];
1312 NewFDPtr[Index] = NewFDPtr[Index2];
1313 NewFDPtr[Index2] = Tmp;
1314 break;
1315 }
1316 }
1317 }
1318 }
1319
1320 if (HDCount != 0) {
1321 //
1322 // Just to make sure that disabled indexes are all at the end of the array
1323 //
1324 for (Index = 0; Index < HDIndex - 1; Index++) {
1325 if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {
1326 continue;
1327 }
1328
1329 for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {
1330 if (0 == (NewHDPtr[Index2] & 0xFF00)) {
1331 Tmp = NewHDPtr[Index];
1332 NewHDPtr[Index] = NewHDPtr[Index2];
1333 NewHDPtr[Index2] = Tmp;
1334 break;
1335 }
1336 }
1337 }
1338 }
1339
1340 if (CDCount != 0) {
1341 //
1342 // Just to make sure that disabled indexes are all at the end of the array
1343 //
1344 for (Index = 0; Index < CDIndex - 1; Index++) {
1345 if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {
1346 continue;
1347 }
1348
1349 for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {
1350 if (0 == (NewCDPtr[Index2] & 0xFF00)) {
1351 Tmp = NewCDPtr[Index];
1352 NewCDPtr[Index] = NewCDPtr[Index2];
1353 NewCDPtr[Index2] = Tmp;
1354 break;
1355 }
1356 }
1357 }
1358 }
1359
1360 if (NETCount != 0) {
1361 //
1362 // Just to make sure that disabled indexes are all at the end of the array
1363 //
1364 for (Index = 0; Index < NETIndex - 1; Index++) {
1365 if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {
1366 continue;
1367 }
1368
1369 for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {
1370 if (0 == (NewNETPtr[Index2] & 0xFF00)) {
1371 Tmp = NewNETPtr[Index];
1372 NewNETPtr[Index] = NewNETPtr[Index2];
1373 NewNETPtr[Index2] = Tmp;
1374 break;
1375 }
1376 }
1377 }
1378 }
1379
1380 if (BEVCount!= 0) {
1381 //
1382 // Just to make sure that disabled indexes are all at the end of the array
1383 //
1384 for (Index = 0; Index < BEVIndex - 1; Index++) {
1385 if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {
1386 continue;
1387 }
1388
1389 for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {
1390 if (0 == (NewBEVPtr[Index2] & 0xFF00)) {
1391 Tmp = NewBEVPtr[Index];
1392 NewBEVPtr[Index] = NewBEVPtr[Index2];
1393 NewBEVPtr[Index2] = Tmp;
1394 break;
1395 }
1396 }
1397 }
1398 }
1399
1400 SafeFreePool (DevOrder);
1401
1402 Status = gRT->SetVariable (
1403 VAR_LEGACY_DEV_ORDER,
1404 &EfiLegacyDevOrderGuid,
1405 VAR_FLAG,
1406 TotalSize,
1407 NewDevOrder
1408 );
1409 SafeFreePool (NewDevOrder);
1410
1411 return Status;
1412 }
1413
1414 /**
1415 Set Boot Priority for specified device type.
1416
1417 @param DeviceType The device type.
1418 @param LocalBbsTable The BBS table.
1419 @param Priority The prority table.
1420
1421 @retval EFI_SUCCESS The function completes successfully.
1422 @retval EFI_NOT_FOUND Failed to find device.
1423
1424 **/
1425 EFI_STATUS
1426 BdsSetBootPriority4SameTypeDev (
1427 IN UINT16 DeviceType,
1428 IN OUT BBS_TABLE *LocalBbsTable,
1429 IN OUT UINT16 *Priority
1430 )
1431 {
1432 UINT8 *DevOrder;
1433
1434 UINT8 *OrigBuffer;
1435 UINT16 *DevIndex;
1436 UINTN DevOrderSize;
1437 UINTN DevCount;
1438 UINTN Index;
1439
1440 DevOrder = BdsLibGetVariableAndSize (
1441 VAR_LEGACY_DEV_ORDER,
1442 &EfiLegacyDevOrderGuid,
1443 &DevOrderSize
1444 );
1445 if (NULL == DevOrder) {
1446 return EFI_OUT_OF_RESOURCES;
1447 }
1448
1449 OrigBuffer = DevOrder;
1450 while (DevOrder < OrigBuffer + DevOrderSize) {
1451 if (DeviceType == * (BBS_TYPE *) DevOrder) {
1452 break;
1453 }
1454
1455 DevOrder += sizeof (BBS_TYPE);
1456 DevOrder += *(UINT16 *) DevOrder;
1457 }
1458
1459 if (DevOrder >= OrigBuffer + DevOrderSize) {
1460 SafeFreePool (OrigBuffer);
1461 return EFI_NOT_FOUND;
1462 }
1463
1464 DevOrder += sizeof (BBS_TYPE);
1465 DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);
1466 DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));
1467 //
1468 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1469 //
1470 for (Index = 0; Index < DevCount; Index++) {
1471 if ((DevIndex[Index] & 0xFF00) == 0xFF00) {
1472 //
1473 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1474 //
1475 } else {
1476 LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;
1477 (*Priority)++;
1478 }
1479 }
1480
1481 SafeFreePool (OrigBuffer);
1482 return EFI_SUCCESS;
1483 }
1484
1485 /**
1486 Print the BBS Table.
1487
1488 @param LocalBbsTable The BBS table.
1489
1490 **/
1491 VOID
1492 PrintBbsTable (
1493 IN BBS_TABLE *LocalBbsTable
1494 )
1495 {
1496 UINT16 Idx;
1497
1498 DEBUG ((DEBUG_ERROR, "\n"));
1499 DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1500 DEBUG ((DEBUG_ERROR, "=============================================\n"));
1501 for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {
1502 if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||
1503 (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
1504 (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)
1505 ) {
1506 continue;
1507 }
1508
1509 DEBUG (
1510 (DEBUG_ERROR,
1511 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1512 (UINTN) Idx,
1513 (UINTN) LocalBbsTable[Idx].BootPriority,
1514 (UINTN) LocalBbsTable[Idx].Bus,
1515 (UINTN) LocalBbsTable[Idx].Device,
1516 (UINTN) LocalBbsTable[Idx].Function,
1517 (UINTN) LocalBbsTable[Idx].Class,
1518 (UINTN) LocalBbsTable[Idx].SubClass,
1519 (UINTN) LocalBbsTable[Idx].DeviceType,
1520 (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
1521 (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
1522 (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
1523 (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
1524 (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))
1525 );
1526 }
1527
1528 DEBUG ((DEBUG_ERROR, "\n"));
1529 }
1530
1531 /**
1532
1533 Set the boot priority for BBS entries based on boot option entry and boot order.
1534
1535 @param Entry The boot option is to be checked for refresh BBS table.
1536
1537 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1538
1539 **/
1540 EFI_STATUS
1541 BdsRefreshBbsTableForBoot (
1542 IN BDS_COMMON_OPTION *Entry
1543 )
1544 {
1545 EFI_STATUS Status;
1546 UINT16 HddCount;
1547 UINT16 BbsCount;
1548 HDD_INFO *LocalHddInfo;
1549 BBS_TABLE *LocalBbsTable;
1550 UINT16 DevType;
1551 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
1552 UINTN Index;
1553 UINT16 Priority;
1554 UINT16 *BootOrder;
1555 UINTN BootOrderSize;
1556 UINT8 *BootOptionVar;
1557 UINTN BootOptionSize;
1558 UINT16 BootOption[100];
1559 UINT8 *Ptr;
1560 UINT16 DevPathLen;
1561 EFI_DEVICE_PATH_PROTOCOL *DevPath;
1562
1563 HddCount = 0;
1564 BbsCount = 0;
1565 LocalHddInfo = NULL;
1566 LocalBbsTable = NULL;
1567 DevType = BBS_UNKNOWN;
1568
1569 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
1570 if (EFI_ERROR (Status)) {
1571 return Status;
1572 }
1573
1574 LegacyBios->GetBbsInfo (
1575 LegacyBios,
1576 &HddCount,
1577 &LocalHddInfo,
1578 &BbsCount,
1579 &LocalBbsTable
1580 );
1581 //
1582 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1583 // We will set them according to the settings setup by user
1584 //
1585 for (Index = 0; Index < BbsCount; Index++) {
1586 if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||
1587 (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||
1588 (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {
1589 LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
1590 }
1591 }
1592 //
1593 // boot priority always starts at 0
1594 //
1595 Priority = 0;
1596 if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
1597 //
1598 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1599 //
1600 DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
1601 Status = BdsSetBootPriority4SameTypeDev (
1602 DevType,
1603 LocalBbsTable,
1604 &Priority
1605 );
1606 if (EFI_ERROR (Status)) {
1607 return Status;
1608 }
1609 }
1610 //
1611 // we have to set the boot priority for other BBS entries with different device types
1612 //
1613 BootOrder = (UINT16 *) BdsLibGetVariableAndSize (
1614 L"BootOrder",
1615 &gEfiGlobalVariableGuid,
1616 &BootOrderSize
1617 );
1618 for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {
1619 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
1620 BootOptionVar = BdsLibGetVariableAndSize (
1621 BootOption,
1622 &gEfiGlobalVariableGuid,
1623 &BootOptionSize
1624 );
1625 if (NULL == BootOptionVar) {
1626 continue;
1627 }
1628
1629 Ptr = BootOptionVar;
1630
1631 Ptr += sizeof (UINT32);
1632 DevPathLen = *(UINT16 *) Ptr;
1633 Ptr += sizeof (UINT16);
1634 Ptr += StrSize ((UINT16 *) Ptr);
1635 DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
1636 if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {
1637 SafeFreePool (BootOptionVar);
1638 continue;
1639 }
1640
1641 Ptr += DevPathLen;
1642 if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {
1643 //
1644 // We don't want to process twice for a device type
1645 //
1646 SafeFreePool (BootOptionVar);
1647 continue;
1648 }
1649
1650 Status = BdsSetBootPriority4SameTypeDev (
1651 ((BBS_TABLE *) Ptr)->DeviceType,
1652 LocalBbsTable,
1653 &Priority
1654 );
1655 SafeFreePool (BootOptionVar);
1656 if (EFI_ERROR (Status)) {
1657 break;
1658 }
1659 }
1660
1661 if (BootOrder != NULL) {
1662 SafeFreePool (BootOrder);
1663 }
1664 //
1665 // For debug
1666 //
1667 PrintBbsTable (LocalBbsTable);
1668
1669 return Status;
1670 }