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