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