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