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