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