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