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