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