]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
Fix some inconsistencies in EFIAPI usage.
[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 - 2008, Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "BBSsupport.h"
18
19 /**
20
21 Translate the first n characters of an Ascii string to
22 Unicode characters. The count n is indicated by parameter
23 Size. If Size is greater than the length of string, then
24 the entire string is translated.
25
26
27 @param AStr Pointer to input Ascii string.
28 @param Size The number of characters to translate.
29 @param UStr Pointer to output Unicode string buffer.
30
31 **/
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
679 Add the legacy boot options from BBS table if they do not exist.
680
681 @retval EFI_SUCCESS The boot options are added successfully
682 or they are already in boot options.
683
684 **/
685 EFI_STATUS
686 EFIAPI
687 BdsAddNonExistingLegacyBootOptions (
688 VOID
689 )
690 {
691 UINT16 *BootOrder;
692 UINTN BootOrderSize;
693 EFI_STATUS Status;
694 UINT16 HddCount;
695 UINT16 BbsCount;
696 HDD_INFO *LocalHddInfo;
697 BBS_TABLE *LocalBbsTable;
698 UINT16 BbsIndex;
699 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
700 UINTN Index;
701 UINT32 Attribute;
702 UINTN OptionNumber;
703 BOOLEAN Ret;
704
705 BootOrder = NULL;
706 HddCount = 0;
707 BbsCount = 0;
708 LocalHddInfo = NULL;
709 LocalBbsTable = NULL;
710
711 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
712 if (EFI_ERROR (Status)) {
713 return Status;
714 }
715
716 LegacyBios->GetBbsInfo (
717 LegacyBios,
718 &HddCount,
719 &LocalHddInfo,
720 &BbsCount,
721 &LocalBbsTable
722 );
723
724 BootOrder = BdsLibGetVariableAndSize (
725 L"BootOrder",
726 &gEfiGlobalVariableGuid,
727 &BootOrderSize
728 );
729 if (NULL == BootOrder) {
730 BootOrderSize = 0;
731 }
732
733 for (Index = 0; Index < BbsCount; Index++) {
734 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
735 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
736 ) {
737 continue;
738 }
739
740 Ret = BdsFindLegacyBootOptionByDevType (
741 BootOrder,
742 BootOrderSize / sizeof (UINT16),
743 LocalBbsTable[Index].DeviceType,
744 &Attribute,
745 &BbsIndex,
746 &OptionNumber
747 );
748 if (Ret) {
749 continue;
750 }
751
752 //
753 // Not found such type of legacy device in boot options or we found but it's disabled
754 // so we have to create one and put it to the tail of boot order list
755 //
756 Status = BdsCreateOneLegacyBootOption (
757 &LocalBbsTable[Index],
758 Index,
759 &BootOrder,
760 &BootOrderSize
761 );
762 if (EFI_ERROR (Status)) {
763 break;
764 }
765 }
766
767 if (BootOrderSize > 0) {
768 Status = gRT->SetVariable (
769 L"BootOrder",
770 &gEfiGlobalVariableGuid,
771 VAR_FLAG,
772 BootOrderSize,
773 BootOrder
774 );
775 } else {
776 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
777 }
778
779 if (BootOrder != NULL) {
780 FreePool (BootOrder);
781 }
782
783 return Status;
784 }
785
786 /**
787 Fill the device order buffer.
788
789 @param BbsTable The BBS table.
790 @param BbsType The BBS Type.
791 @param BbsCount The BBS Count.
792 @param Buf device order buffer.
793
794 @return The device order buffer.
795
796 **/
797 UINT16 *
798 BdsFillDevOrderBuf (
799 IN BBS_TABLE *BbsTable,
800 IN BBS_TYPE BbsType,
801 IN UINTN BbsCount,
802 OUT UINT16 *Buf
803 )
804 {
805 UINTN Index;
806
807 for (Index = 0; Index < BbsCount; Index++) {
808 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
809 continue;
810 }
811
812 if (BbsTable[Index].DeviceType != BbsType) {
813 continue;
814 }
815
816 *Buf = (UINT16) (Index & 0xFF);
817 Buf++;
818 }
819
820 return Buf;
821 }
822
823 /**
824 Create the device order buffer.
825
826 @param BbsTable The BBS table.
827 @param BbsCount The BBS Count.
828
829 @retval EFI_SUCCES The buffer is created and the EFI variable named
830 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
831 set correctly.
832 @return Other value if the set of EFI variable fails. Check gRT->SetVariable
833 for detailed information.
834
835 **/
836 EFI_STATUS
837 BdsCreateDevOrder (
838 IN BBS_TABLE *BbsTable,
839 IN UINT16 BbsCount
840 )
841 {
842 UINTN Index;
843 UINTN FDCount;
844 UINTN HDCount;
845 UINTN CDCount;
846 UINTN NETCount;
847 UINTN BEVCount;
848 UINTN TotalSize;
849 UINTN HeaderSize;
850 UINT8 *DevOrder;
851 UINT8 *Ptr;
852 EFI_STATUS Status;
853
854 FDCount = 0;
855 HDCount = 0;
856 CDCount = 0;
857 NETCount = 0;
858 BEVCount = 0;
859 TotalSize = 0;
860 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
861 DevOrder = NULL;
862 Ptr = NULL;
863 Status = EFI_SUCCESS;
864
865 //
866 // Count all boot devices
867 //
868 for (Index = 0; Index < BbsCount; Index++) {
869 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
870 continue;
871 }
872
873 switch (BbsTable[Index].DeviceType) {
874 case BBS_FLOPPY:
875 FDCount++;
876 break;
877
878 case BBS_HARDDISK:
879 HDCount++;
880 break;
881
882 case BBS_CDROM:
883 CDCount++;
884 break;
885
886 case BBS_EMBED_NETWORK:
887 NETCount++;
888 break;
889
890 case BBS_BEV_DEVICE:
891 BEVCount++;
892 break;
893
894 default:
895 break;
896 }
897 }
898
899 TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
900 TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
901 TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
902 TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
903 TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
904
905 //
906 // Create buffer to hold all boot device order
907 //
908 DevOrder = AllocateZeroPool (TotalSize);
909 if (NULL == DevOrder) {
910 return EFI_OUT_OF_RESOURCES;
911 }
912
913 Ptr = DevOrder;
914
915 *((BBS_TYPE *) Ptr) = BBS_FLOPPY;
916 Ptr += sizeof (BBS_TYPE);
917 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
918 Ptr += sizeof (UINT16);
919 if (FDCount != 0) {
920 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);
921 }
922
923 *((BBS_TYPE *) Ptr) = BBS_HARDDISK;
924 Ptr += sizeof (BBS_TYPE);
925 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
926 Ptr += sizeof (UINT16);
927 if (HDCount != 0) {
928 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);
929 }
930
931 *((BBS_TYPE *) Ptr) = BBS_CDROM;
932 Ptr += sizeof (BBS_TYPE);
933 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
934 Ptr += sizeof (UINT16);
935 if (CDCount != 0) {
936 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);
937 }
938
939 *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;
940 Ptr += sizeof (BBS_TYPE);
941 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
942 Ptr += sizeof (UINT16);
943 if (NETCount != 0) {
944 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);
945 }
946
947 *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;
948 Ptr += sizeof (BBS_TYPE);
949 *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
950 Ptr += sizeof (UINT16);
951 if (BEVCount != 0) {
952 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);
953 }
954
955 //
956 // Save device order for legacy boot device to variable.
957 //
958 Status = gRT->SetVariable (
959 VAR_LEGACY_DEV_ORDER,
960 &EfiLegacyDevOrderGuid,
961 VAR_FLAG,
962 TotalSize,
963 DevOrder
964 );
965 FreePool (DevOrder);
966
967 return Status;
968 }
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
977 **/
978 EFI_STATUS
979 EFIAPI
980 BdsUpdateLegacyDevOrder (
981 VOID
982 )
983 {
984 UINT8 *DevOrder;
985 UINT8 *NewDevOrder;
986 UINTN DevOrderSize;
987 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
988 EFI_STATUS Status;
989 UINT16 HddCount;
990 UINT16 BbsCount;
991 HDD_INFO *LocalHddInfo;
992 BBS_TABLE *LocalBbsTable;
993 UINTN Index;
994 UINTN Index2;
995 UINTN *Idx;
996 UINTN FDCount;
997 UINTN HDCount;
998 UINTN CDCount;
999 UINTN NETCount;
1000 UINTN BEVCount;
1001 UINTN TotalSize;
1002 UINTN HeaderSize;
1003 UINT8 *Ptr;
1004 UINT8 *NewPtr;
1005 UINT16 *NewFDPtr;
1006 UINT16 *NewHDPtr;
1007 UINT16 *NewCDPtr;
1008 UINT16 *NewNETPtr;
1009 UINT16 *NewBEVPtr;
1010 UINT16 *NewDevPtr;
1011 UINT16 Length;
1012 UINT16 Tmp;
1013 UINTN FDIndex;
1014 UINTN HDIndex;
1015 UINTN CDIndex;
1016 UINTN NETIndex;
1017 UINTN BEVIndex;
1018
1019 LocalHddInfo = NULL;
1020 LocalBbsTable = NULL;
1021 Idx = NULL;
1022 FDCount = 0;
1023 HDCount = 0;
1024 CDCount = 0;
1025 NETCount = 0;
1026 BEVCount = 0;
1027 TotalSize = 0;
1028 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
1029 FDIndex = 0;
1030 HDIndex = 0;
1031 CDIndex = 0;
1032 NETIndex = 0;
1033 BEVIndex = 0;
1034 NewDevPtr = NULL;
1035
1036 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
1037 if (EFI_ERROR (Status)) {
1038 return Status;
1039 }
1040
1041 LegacyBios->GetBbsInfo (
1042 LegacyBios,
1043 &HddCount,
1044 &LocalHddInfo,
1045 &BbsCount,
1046 &LocalBbsTable
1047 );
1048
1049 DevOrder = (UINT8 *) BdsLibGetVariableAndSize (
1050 VAR_LEGACY_DEV_ORDER,
1051 &EfiLegacyDevOrderGuid,
1052 &DevOrderSize
1053 );
1054 if (NULL == DevOrder) {
1055 return BdsCreateDevOrder (LocalBbsTable, BbsCount);
1056 }
1057 //
1058 // First we figure out how many boot devices with same device type respectively
1059 //
1060 for (Index = 0; Index < BbsCount; Index++) {
1061 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
1062 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
1063 ) {
1064 continue;
1065 }
1066
1067 switch (LocalBbsTable[Index].DeviceType) {
1068 case BBS_FLOPPY:
1069 FDCount++;
1070 break;
1071
1072 case BBS_HARDDISK:
1073 HDCount++;
1074 break;
1075
1076 case BBS_CDROM:
1077 CDCount++;
1078 break;
1079
1080 case BBS_EMBED_NETWORK:
1081 NETCount++;
1082 break;
1083
1084 case BBS_BEV_DEVICE:
1085 BEVCount++;
1086 break;
1087
1088 default:
1089 break;
1090 }
1091 }
1092
1093 TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
1094 TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
1095 TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
1096 TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
1097 TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
1098
1099 NewDevOrder = AllocateZeroPool (TotalSize);
1100 if (NULL == NewDevOrder) {
1101 return EFI_OUT_OF_RESOURCES;
1102 }
1103
1104 NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);
1105 NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);
1106 NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);
1107 NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);
1108 NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);
1109
1110 //
1111 // copy FD
1112 //
1113 Ptr = DevOrder;
1114 NewPtr = NewDevOrder;
1115 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1116 Ptr += sizeof (BBS_TYPE);
1117 NewPtr += sizeof (BBS_TYPE);
1118 Length = *((UINT16 *) Ptr);
1119 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
1120 Ptr += sizeof (UINT16);
1121
1122 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1123 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1124 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1125 LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY
1126 ) {
1127 Ptr += sizeof (UINT16);
1128 continue;
1129 }
1130
1131 NewFDPtr[FDIndex] = *(UINT16 *) Ptr;
1132 FDIndex++;
1133 Ptr += sizeof (UINT16);
1134 }
1135 //
1136 // copy HD
1137 //
1138 NewPtr = (UINT8 *) NewHDPtr - HeaderSize;
1139 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1140 Ptr += sizeof (BBS_TYPE);
1141 NewPtr += sizeof (BBS_TYPE);
1142 Length = *((UINT16 *) Ptr);
1143 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
1144 Ptr += sizeof (UINT16);
1145
1146 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1147 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1148 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1149 LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
1150 LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK
1151 ) {
1152 Ptr += sizeof (UINT16);
1153 continue;
1154 }
1155
1156 NewHDPtr[HDIndex] = *(UINT16 *) Ptr;
1157 HDIndex++;
1158 Ptr += sizeof (UINT16);
1159 }
1160 //
1161 // copy CD
1162 //
1163 NewPtr = (UINT8 *) NewCDPtr - HeaderSize;
1164 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1165 Ptr += sizeof (BBS_TYPE);
1166 NewPtr += sizeof (BBS_TYPE);
1167 Length = *((UINT16 *) Ptr);
1168 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
1169 Ptr += sizeof (UINT16);
1170
1171 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1172 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1173 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1174 LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
1175 LocalBbsTable[*Ptr].DeviceType != BBS_CDROM
1176 ) {
1177 Ptr += sizeof (UINT16);
1178 continue;
1179 }
1180
1181 NewCDPtr[CDIndex] = *(UINT16 *) Ptr;
1182 CDIndex++;
1183 Ptr += sizeof (UINT16);
1184 }
1185 //
1186 // copy NET
1187 //
1188 NewPtr = (UINT8 *) NewNETPtr - HeaderSize;
1189 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1190 Ptr += sizeof (BBS_TYPE);
1191 NewPtr += sizeof (BBS_TYPE);
1192 Length = *((UINT16 *) Ptr);
1193 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
1194 Ptr += sizeof (UINT16);
1195
1196 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1197 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1198 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1199 LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
1200 LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK
1201 ) {
1202 Ptr += sizeof (UINT16);
1203 continue;
1204 }
1205
1206 NewNETPtr[NETIndex] = *(UINT16 *) Ptr;
1207 NETIndex++;
1208 Ptr += sizeof (UINT16);
1209 }
1210 //
1211 // copy BEV
1212 //
1213 NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;
1214 *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
1215 Ptr += sizeof (BBS_TYPE);
1216 NewPtr += sizeof (BBS_TYPE);
1217 Length = *((UINT16 *) Ptr);
1218 *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
1219 Ptr += sizeof (UINT16);
1220
1221 for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
1222 if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
1223 LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
1224 LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
1225 LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE
1226 ) {
1227 Ptr += sizeof (UINT16);
1228 continue;
1229 }
1230
1231 NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;
1232 BEVIndex++;
1233 Ptr += sizeof (UINT16);
1234 }
1235
1236 for (Index = 0; Index < BbsCount; Index++) {
1237 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
1238 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
1239 ) {
1240 continue;
1241 }
1242
1243 switch (LocalBbsTable[Index].DeviceType) {
1244 case BBS_FLOPPY:
1245 Idx = &FDIndex;
1246 NewDevPtr = NewFDPtr;
1247 break;
1248
1249 case BBS_HARDDISK:
1250 Idx = &HDIndex;
1251 NewDevPtr = NewHDPtr;
1252 break;
1253
1254 case BBS_CDROM:
1255 Idx = &CDIndex;
1256 NewDevPtr = NewCDPtr;
1257 break;
1258
1259 case BBS_EMBED_NETWORK:
1260 Idx = &NETIndex;
1261 NewDevPtr = NewNETPtr;
1262 break;
1263
1264 case BBS_BEV_DEVICE:
1265 Idx = &BEVIndex;
1266 NewDevPtr = NewBEVPtr;
1267 break;
1268
1269 default:
1270 Idx = NULL;
1271 break;
1272 }
1273 //
1274 // at this point we have copied those valid indexes to new buffer
1275 // and we should check if there is any new appeared boot device
1276 //
1277 if (Idx != 0) {
1278 for (Index2 = 0; Index2 < *Idx; Index2++) {
1279 if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
1280 break;
1281 }
1282 }
1283
1284 if (Index2 == *Idx) {
1285 //
1286 // Index2 == *Idx means we didn't find Index
1287 // so Index is a new appeared device's index in BBS table
1288 // save it.
1289 //
1290 NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);
1291 (*Idx)++;
1292 }
1293 }
1294 }
1295
1296 if (FDCount != 0) {
1297 //
1298 // Just to make sure that disabled indexes are all at the end of the array
1299 //
1300 for (Index = 0; Index < FDIndex - 1; Index++) {
1301 if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {
1302 continue;
1303 }
1304
1305 for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {
1306 if (0 == (NewFDPtr[Index2] & 0xFF00)) {
1307 Tmp = NewFDPtr[Index];
1308 NewFDPtr[Index] = NewFDPtr[Index2];
1309 NewFDPtr[Index2] = Tmp;
1310 break;
1311 }
1312 }
1313 }
1314 }
1315
1316 if (HDCount != 0) {
1317 //
1318 // Just to make sure that disabled indexes are all at the end of the array
1319 //
1320 for (Index = 0; Index < HDIndex - 1; Index++) {
1321 if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {
1322 continue;
1323 }
1324
1325 for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {
1326 if (0 == (NewHDPtr[Index2] & 0xFF00)) {
1327 Tmp = NewHDPtr[Index];
1328 NewHDPtr[Index] = NewHDPtr[Index2];
1329 NewHDPtr[Index2] = Tmp;
1330 break;
1331 }
1332 }
1333 }
1334 }
1335
1336 if (CDCount != 0) {
1337 //
1338 // Just to make sure that disabled indexes are all at the end of the array
1339 //
1340 for (Index = 0; Index < CDIndex - 1; Index++) {
1341 if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {
1342 continue;
1343 }
1344
1345 for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {
1346 if (0 == (NewCDPtr[Index2] & 0xFF00)) {
1347 Tmp = NewCDPtr[Index];
1348 NewCDPtr[Index] = NewCDPtr[Index2];
1349 NewCDPtr[Index2] = Tmp;
1350 break;
1351 }
1352 }
1353 }
1354 }
1355
1356 if (NETCount != 0) {
1357 //
1358 // Just to make sure that disabled indexes are all at the end of the array
1359 //
1360 for (Index = 0; Index < NETIndex - 1; Index++) {
1361 if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {
1362 continue;
1363 }
1364
1365 for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {
1366 if (0 == (NewNETPtr[Index2] & 0xFF00)) {
1367 Tmp = NewNETPtr[Index];
1368 NewNETPtr[Index] = NewNETPtr[Index2];
1369 NewNETPtr[Index2] = Tmp;
1370 break;
1371 }
1372 }
1373 }
1374 }
1375
1376 if (BEVCount!= 0) {
1377 //
1378 // Just to make sure that disabled indexes are all at the end of the array
1379 //
1380 for (Index = 0; Index < BEVIndex - 1; Index++) {
1381 if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {
1382 continue;
1383 }
1384
1385 for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {
1386 if (0 == (NewBEVPtr[Index2] & 0xFF00)) {
1387 Tmp = NewBEVPtr[Index];
1388 NewBEVPtr[Index] = NewBEVPtr[Index2];
1389 NewBEVPtr[Index2] = Tmp;
1390 break;
1391 }
1392 }
1393 }
1394 }
1395
1396 FreePool (DevOrder);
1397
1398 Status = gRT->SetVariable (
1399 VAR_LEGACY_DEV_ORDER,
1400 &EfiLegacyDevOrderGuid,
1401 VAR_FLAG,
1402 TotalSize,
1403 NewDevOrder
1404 );
1405 FreePool (NewDevOrder);
1406
1407 return Status;
1408 }
1409
1410 /**
1411 Set Boot Priority for specified device type.
1412
1413 @param DeviceType The device type.
1414 @param LocalBbsTable The BBS table.
1415 @param Priority The prority table.
1416
1417 @retval EFI_SUCCESS The function completes successfully.
1418 @retval EFI_NOT_FOUND Failed to find device.
1419
1420 **/
1421 EFI_STATUS
1422 BdsSetBootPriority4SameTypeDev (
1423 IN UINT16 DeviceType,
1424 IN OUT BBS_TABLE *LocalBbsTable,
1425 IN OUT UINT16 *Priority
1426 )
1427 {
1428 UINT8 *DevOrder;
1429
1430 UINT8 *OrigBuffer;
1431 UINT16 *DevIndex;
1432 UINTN DevOrderSize;
1433 UINTN DevCount;
1434 UINTN Index;
1435
1436 DevOrder = BdsLibGetVariableAndSize (
1437 VAR_LEGACY_DEV_ORDER,
1438 &EfiLegacyDevOrderGuid,
1439 &DevOrderSize
1440 );
1441 if (NULL == DevOrder) {
1442 return EFI_OUT_OF_RESOURCES;
1443 }
1444
1445 OrigBuffer = DevOrder;
1446 while (DevOrder < OrigBuffer + DevOrderSize) {
1447 if (DeviceType == * (BBS_TYPE *) DevOrder) {
1448 break;
1449 }
1450
1451 DevOrder += sizeof (BBS_TYPE);
1452 DevOrder += *(UINT16 *) DevOrder;
1453 }
1454
1455 if (DevOrder >= OrigBuffer + DevOrderSize) {
1456 FreePool (OrigBuffer);
1457 return EFI_NOT_FOUND;
1458 }
1459
1460 DevOrder += sizeof (BBS_TYPE);
1461 DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);
1462 DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));
1463 //
1464 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
1465 //
1466 for (Index = 0; Index < DevCount; Index++) {
1467 if ((DevIndex[Index] & 0xFF00) == 0xFF00) {
1468 //
1469 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
1470 //
1471 } else {
1472 LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;
1473 (*Priority)++;
1474 }
1475 }
1476
1477 FreePool (OrigBuffer);
1478 return EFI_SUCCESS;
1479 }
1480
1481 /**
1482 Print the BBS Table.
1483
1484 @param LocalBbsTable The BBS table.
1485
1486 **/
1487 VOID
1488 PrintBbsTable (
1489 IN BBS_TABLE *LocalBbsTable
1490 )
1491 {
1492 UINT16 Idx;
1493
1494 DEBUG ((DEBUG_ERROR, "\n"));
1495 DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
1496 DEBUG ((DEBUG_ERROR, "=============================================\n"));
1497 for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {
1498 if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||
1499 (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
1500 (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)
1501 ) {
1502 continue;
1503 }
1504
1505 DEBUG (
1506 (DEBUG_ERROR,
1507 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
1508 (UINTN) Idx,
1509 (UINTN) LocalBbsTable[Idx].BootPriority,
1510 (UINTN) LocalBbsTable[Idx].Bus,
1511 (UINTN) LocalBbsTable[Idx].Device,
1512 (UINTN) LocalBbsTable[Idx].Function,
1513 (UINTN) LocalBbsTable[Idx].Class,
1514 (UINTN) LocalBbsTable[Idx].SubClass,
1515 (UINTN) LocalBbsTable[Idx].DeviceType,
1516 (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
1517 (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
1518 (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
1519 (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
1520 (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))
1521 );
1522 }
1523
1524 DEBUG ((DEBUG_ERROR, "\n"));
1525 }
1526
1527 /**
1528
1529 Set the boot priority for BBS entries based on boot option entry and boot order.
1530
1531 @param Entry The boot option is to be checked for refresh BBS table.
1532
1533 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.
1534 @return status of BdsSetBootPriority4SameTypeDev()
1535 **/
1536 EFI_STATUS
1537 EFIAPI
1538 BdsRefreshBbsTableForBoot (
1539 IN BDS_COMMON_OPTION *Entry
1540 )
1541 {
1542 EFI_STATUS Status;
1543 UINT16 HddCount;
1544 UINT16 BbsCount;
1545 HDD_INFO *LocalHddInfo;
1546 BBS_TABLE *LocalBbsTable;
1547 UINT16 DevType;
1548 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
1549 UINTN Index;
1550 UINT16 Priority;
1551 UINT16 *BootOrder;
1552 UINTN BootOrderSize;
1553 UINT8 *BootOptionVar;
1554 UINTN BootOptionSize;
1555 UINT16 BootOption[100];
1556 UINT8 *Ptr;
1557 UINT16 DevPathLen;
1558 EFI_DEVICE_PATH_PROTOCOL *DevPath;
1559
1560 HddCount = 0;
1561 BbsCount = 0;
1562 LocalHddInfo = NULL;
1563 LocalBbsTable = NULL;
1564 DevType = BBS_UNKNOWN;
1565
1566 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
1567 if (EFI_ERROR (Status)) {
1568 return Status;
1569 }
1570
1571 LegacyBios->GetBbsInfo (
1572 LegacyBios,
1573 &HddCount,
1574 &LocalHddInfo,
1575 &BbsCount,
1576 &LocalBbsTable
1577 );
1578 //
1579 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
1580 // We will set them according to the settings setup by user
1581 //
1582 for (Index = 0; Index < BbsCount; Index++) {
1583 if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||
1584 (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||
1585 (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {
1586 LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
1587 }
1588 }
1589 //
1590 // boot priority always starts at 0
1591 //
1592 Priority = 0;
1593 if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
1594 //
1595 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
1596 //
1597 DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
1598 Status = BdsSetBootPriority4SameTypeDev (
1599 DevType,
1600 LocalBbsTable,
1601 &Priority
1602 );
1603 if (EFI_ERROR (Status)) {
1604 return Status;
1605 }
1606 }
1607 //
1608 // we have to set the boot priority for other BBS entries with different device types
1609 //
1610 BootOrder = (UINT16 *) BdsLibGetVariableAndSize (
1611 L"BootOrder",
1612 &gEfiGlobalVariableGuid,
1613 &BootOrderSize
1614 );
1615 for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {
1616 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
1617 BootOptionVar = BdsLibGetVariableAndSize (
1618 BootOption,
1619 &gEfiGlobalVariableGuid,
1620 &BootOptionSize
1621 );
1622 if (NULL == BootOptionVar) {
1623 continue;
1624 }
1625
1626 Ptr = BootOptionVar;
1627
1628 Ptr += sizeof (UINT32);
1629 DevPathLen = *(UINT16 *) Ptr;
1630 Ptr += sizeof (UINT16);
1631 Ptr += StrSize ((UINT16 *) Ptr);
1632 DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
1633 if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {
1634 FreePool (BootOptionVar);
1635 continue;
1636 }
1637
1638 Ptr += DevPathLen;
1639 if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {
1640 //
1641 // We don't want to process twice for a device type
1642 //
1643 FreePool (BootOptionVar);
1644 continue;
1645 }
1646
1647 Status = BdsSetBootPriority4SameTypeDev (
1648 ((BBS_TABLE *) Ptr)->DeviceType,
1649 LocalBbsTable,
1650 &Priority
1651 );
1652 FreePool (BootOptionVar);
1653 if (EFI_ERROR (Status)) {
1654 break;
1655 }
1656 }
1657
1658 if (BootOrder != NULL) {
1659 FreePool (BootOrder);
1660 }
1661
1662 DEBUG_CODE_BEGIN();
1663 PrintBbsTable (LocalBbsTable);
1664 DEBUG_CODE_END();
1665
1666 return Status;
1667 }