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