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