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