]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
Remove SafeFreePool from MemoryAllocationLib as this API's name is misleading. Its...
[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
30394aa1 28 @param Size The number of characters to translate.\r
744fc758 29 @param UStr Pointer to output Unicode string buffer.\r
b30312ba 30\r
b30312ba 31**/\r
93e3992d 32VOID\r
33AsciiToUnicodeSize (\r
744fc758 34 IN UINT8 *AStr,\r
93e3992d 35 IN UINTN Size,\r
744fc758 36 OUT UINT16 *UStr\r
93e3992d 37 )\r
93e3992d 38{\r
744fc758 39 UINTN Idx;\r
93e3992d 40\r
744fc758 41 Idx = 0;\r
42 while (AStr[Idx] != 0) {\r
43 UStr[Idx] = (CHAR16) AStr[Idx];\r
44 if (Idx == Size) {\r
93e3992d 45 break;\r
46 }\r
47\r
744fc758 48 Idx++;\r
93e3992d 49 }\r
744fc758 50 UStr[Idx] = 0;\r
93e3992d 51}\r
52\r
b30312ba 53/**\r
744fc758 54 Build Legacy Device Name String according.\r
b30312ba 55\r
744fc758 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
b30312ba 60\r
b30312ba 61**/\r
93e3992d 62VOID\r
63BdsBuildLegacyDevNameString (\r
30394aa1 64 IN BBS_TABLE *CurBBSEntry,\r
65 IN UINTN Index,\r
66 IN UINTN BufSize,\r
67 OUT CHAR16 *BootString\r
93e3992d 68 )\r
69{\r
70 CHAR16 *Fmt;\r
71 CHAR16 *Type;\r
72 UINT8 *StringDesc;\r
744fc758 73 CHAR16 Temp[80];\r
93e3992d 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
744fc758 151 AsciiToUnicodeSize (StringDesc, 32, Temp);\r
93e3992d 152 Fmt = L"%s";\r
744fc758 153 Type = Temp;\r
93e3992d 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
b30312ba 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
93e3992d 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
93e3992d 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
30394aa1 215 if ((*BootOrderList) == NULL) {\r
93e3992d 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
30394aa1 249 UnicodeStrToAsciiStr ((CONST CHAR16*)&BootDesc, (CHAR8*)&HelpString);\r
250\r
93e3992d 251 StringLen = AsciiStrLen (HelpString);\r
dce655e8 252 NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
93e3992d 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
dce655e8 281 Buffer = AllocateZeroPool (BufferSize);\r
93e3992d 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
676df92c 327 FreePool (Buffer);\r
328 \r
93e3992d 329 Buffer = NULL;\r
330\r
dce655e8 331 NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
93e3992d 332 if (NULL == NewBootOrderList) {\r
333 FreePool (NewBbsDevPathNode);\r
334 FreePool (CurrentBbsDevPath);\r
335 return EFI_OUT_OF_RESOURCES;\r
336 }\r
337\r
676df92c 338 if (*BootOrderList != NULL) {\r
93e3992d 339 CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
676df92c 340 FreePool (*BootOrderList);\r
93e3992d 341 }\r
342\r
93e3992d 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
b30312ba 353/**\r
744fc758 354 Check if the boot option is a legacy one.\r
b30312ba 355\r
744fc758 356 @param BootOptionVar The boot option data payload.\r
357 @param BbsEntry The BBS Table.\r
358 @param BbsIndex The table index.\r
b30312ba 359\r
744fc758 360 @retval TRUE It is a legacy boot option.\r
361 @retval FALSE It is not a legacy boot option.\r
b30312ba 362\r
363**/\r
93e3992d 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
b30312ba 396/**\r
744fc758 397 Delete all the invalid legacy boot options.\r
b30312ba 398\r
78f64f28
LG
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
b30312ba 402**/\r
403EFI_STATUS\r
404BdsDeleteAllInvalidLegacyBootOptions (\r
405 VOID\r
406 )\r
93e3992d 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
676df92c 465 if (BootOrder != NULL) {\r
466 FreePool (BootOrder);\r
467 }\r
93e3992d 468 return EFI_OUT_OF_RESOURCES;\r
469 }\r
30394aa1 470 \r
471 //\r
472 // Skip Non-Legacy boot options\r
473 // \r
93e3992d 474 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
676df92c 475 if (BootOptionVar!= NULL) {\r
476 FreePool (BootOptionVar);\r
477 }\r
93e3992d 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
676df92c 506 if (BootOptionVar != NULL) {\r
507 FreePool (BootOptionVar);\r
508 }\r
93e3992d 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
30394aa1 519 //\r
520 // Adjust the number of boot options.\r
521 //\r
a78b08d1 522 if (BootOrderSize != 0) {\r
93e3992d 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
676df92c 534 if (BootOrder != NULL) {\r
535 FreePool (BootOrder);\r
536 }\r
93e3992d 537\r
538 return Status;\r
539}\r
540\r
b30312ba 541/**\r
744fc758 542 Find all legacy boot option by device type.\r
b30312ba 543\r
744fc758 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
b30312ba 550\r
744fc758 551 @retval TRUE The Legacy boot option is found.\r
552 @retval FALSE The legacy boot option is not found.\r
b30312ba 553\r
554**/\r
93e3992d 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
30394aa1 580 //\r
581 // Loop all boot option from variable\r
582 //\r
93e3992d 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
30394aa1 595 //\r
596 // Skip Non-legacy boot option\r
597 //\r
93e3992d 598 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
676df92c 599 FreePool (BootOptionVar);\r
93e3992d 600 continue;\r
601 }\r
602\r
603 if (BbsEntry->DeviceType != DevType) {\r
676df92c 604 FreePool (BootOptionVar);\r
93e3992d 605 continue;\r
606 }\r
607\r
608 *Attribute = *(UINT32 *) BootOptionVar;\r
609 *OptionNumber = Index;\r
610 Found = TRUE;\r
676df92c 611 FreePool (BootOptionVar);\r
93e3992d 612 break;\r
613 }\r
614\r
615 return Found;\r
616}\r
617\r
b30312ba 618/**\r
744fc758 619 Create a legacy boot option.\r
b30312ba 620\r
744fc758 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
b30312ba 625\r
744fc758 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
b30312ba 629\r
630**/\r
93e3992d 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
30394aa1 645 //\r
646 // Create device path node.\r
647 //\r
93e3992d 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
b30312ba 676/**\r
93e3992d 677\r
678 Add the legacy boot options from BBS table if they do not exist.\r
679\r
78f64f28
LG
680 @retval EFI_SUCCESS The boot options are added successfully \r
681 or they are already in boot options.\r
93e3992d 682\r
b30312ba 683**/\r
684EFI_STATUS\r
685BdsAddNonExistingLegacyBootOptions (\r
686 VOID\r
687 )\r
93e3992d 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
676df92c 778 FreePool (BootOrder);\r
93e3992d 779 }\r
780\r
781 return Status;\r
782}\r
783\r
b30312ba 784/**\r
744fc758 785 Fill the device order buffer.\r
b30312ba 786\r
744fc758 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
b30312ba 791\r
744fc758 792 @return The device order buffer.\r
b30312ba 793\r
794**/\r
93e3992d 795UINT16 *\r
796BdsFillDevOrderBuf (\r
797 IN BBS_TABLE *BbsTable,\r
798 IN BBS_TYPE BbsType,\r
799 IN UINTN BbsCount,\r
744fc758 800 OUT UINT16 *Buf\r
93e3992d 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
b30312ba 821/**\r
744fc758 822 Create the device order buffer.\r
b30312ba 823\r
744fc758 824 @param BbsTable The BBS table.\r
825 @param BbsCount The BBS Count.\r
b30312ba 826\r
744fc758 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
b30312ba 832\r
833**/\r
93e3992d 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
30394aa1 863 //\r
864 // Count all boot devices\r
865 //\r
93e3992d 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
30394aa1 903 //\r
904 // Create buffer to hold all boot device order\r
905 //\r
dce655e8 906 DevOrder = AllocateZeroPool (TotalSize);\r
93e3992d 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
a78b08d1 917 if (FDCount != 0) {\r
93e3992d 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
a78b08d1 925 if (HDCount != 0) {\r
93e3992d 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
a78b08d1 933 if (CDCount != 0) {\r
93e3992d 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
a78b08d1 941 if (NETCount != 0) {\r
93e3992d 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
a78b08d1 949 if (BEVCount != 0) {\r
93e3992d 950 Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
951 }\r
952\r
30394aa1 953 //\r
954 // Save device order for legacy boot device to variable.\r
955 //\r
93e3992d 956 Status = gRT->SetVariable (\r
5f597758 957 VAR_LEGACY_DEV_ORDER,\r
93e3992d 958 &EfiLegacyDevOrderGuid,\r
959 VAR_FLAG,\r
960 TotalSize,\r
961 DevOrder\r
962 );\r
676df92c 963 FreePool (DevOrder);\r
93e3992d 964\r
965 return Status;\r
966}\r
967\r
b30312ba 968/**\r
b30312ba 969\r
78f64f28
LG
970 Add the legacy boot devices from BBS table into \r
971 the legacy device boot order.\r
b30312ba 972\r
78f64f28 973 @retval EFI_SUCCESS The boot devices are added successfully.\r
b30312ba 974\r
975**/\r
93e3992d 976EFI_STATUS\r
977BdsUpdateLegacyDevOrder (\r
978 VOID\r
979 )\r
93e3992d 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
744fc758 1009 UINT16 Tmp;\r
93e3992d 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
5f597758 1047 VAR_LEGACY_DEV_ORDER,\r
93e3992d 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
dce655e8 1096 NewDevOrder = AllocateZeroPool (TotalSize);\r
93e3992d 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
a78b08d1 1274 if (Idx != 0) {\r
93e3992d 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
a78b08d1 1293 if (FDCount != 0) {\r
93e3992d 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
744fc758 1304 Tmp = NewFDPtr[Index];\r
93e3992d 1305 NewFDPtr[Index] = NewFDPtr[Index2];\r
744fc758 1306 NewFDPtr[Index2] = Tmp;\r
93e3992d 1307 break;\r
1308 }\r
1309 }\r
1310 }\r
1311 }\r
1312\r
a78b08d1 1313 if (HDCount != 0) {\r
93e3992d 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
744fc758 1324 Tmp = NewHDPtr[Index];\r
93e3992d 1325 NewHDPtr[Index] = NewHDPtr[Index2];\r
744fc758 1326 NewHDPtr[Index2] = Tmp;\r
93e3992d 1327 break;\r
1328 }\r
1329 }\r
1330 }\r
1331 }\r
1332\r
a78b08d1 1333 if (CDCount != 0) {\r
93e3992d 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
744fc758 1344 Tmp = NewCDPtr[Index];\r
93e3992d 1345 NewCDPtr[Index] = NewCDPtr[Index2];\r
744fc758 1346 NewCDPtr[Index2] = Tmp;\r
93e3992d 1347 break;\r
1348 }\r
1349 }\r
1350 }\r
1351 }\r
1352\r
a78b08d1 1353 if (NETCount != 0) {\r
93e3992d 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
744fc758 1364 Tmp = NewNETPtr[Index];\r
93e3992d 1365 NewNETPtr[Index] = NewNETPtr[Index2];\r
744fc758 1366 NewNETPtr[Index2] = Tmp;\r
93e3992d 1367 break;\r
1368 }\r
1369 }\r
1370 }\r
1371 }\r
1372\r
a78b08d1 1373 if (BEVCount!= 0) {\r
93e3992d 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
744fc758 1384 Tmp = NewBEVPtr[Index];\r
93e3992d 1385 NewBEVPtr[Index] = NewBEVPtr[Index2];\r
744fc758 1386 NewBEVPtr[Index2] = Tmp;\r
93e3992d 1387 break;\r
1388 }\r
1389 }\r
1390 }\r
1391 }\r
1392\r
676df92c 1393 FreePool (DevOrder);\r
93e3992d 1394\r
1395 Status = gRT->SetVariable (\r
5f597758 1396 VAR_LEGACY_DEV_ORDER,\r
93e3992d 1397 &EfiLegacyDevOrderGuid,\r
1398 VAR_FLAG,\r
1399 TotalSize,\r
1400 NewDevOrder\r
1401 );\r
676df92c 1402 FreePool (NewDevOrder);\r
93e3992d 1403\r
1404 return Status;\r
1405}\r
1406\r
b30312ba 1407/**\r
744fc758 1408 Set Boot Priority for specified device type.\r
b30312ba 1409\r
744fc758 1410 @param DeviceType The device type.\r
1411 @param LocalBbsTable The BBS table.\r
1412 @param Priority The prority table.\r
b30312ba 1413\r
744fc758 1414 @retval EFI_SUCCESS The function completes successfully.\r
1415 @retval EFI_NOT_FOUND Failed to find device.\r
b30312ba 1416\r
1417**/\r
93e3992d 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
93e3992d 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
5f597758 1434 VAR_LEGACY_DEV_ORDER,\r
93e3992d 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
676df92c 1453 FreePool (OrigBuffer);\r
93e3992d 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
676df92c 1474 FreePool (OrigBuffer);\r
93e3992d 1475 return EFI_SUCCESS;\r
1476}\r
1477\r
b30312ba 1478/**\r
744fc758 1479 Print the BBS Table.\r
b30312ba 1480\r
744fc758 1481 @param LocalBbsTable The BBS table.\r
b30312ba 1482\r
1483**/\r
93e3992d 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
f26b92e4 1504 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
93e3992d 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
b30312ba 1524/**\r
b30312ba 1525\r
78f64f28 1526 Set the boot priority for BBS entries based on boot option entry and boot order.\r
b30312ba 1527\r
78f64f28
LG
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
30394aa1 1531 @return status of BdsSetBootPriority4SameTypeDev()\r
b30312ba 1532**/\r
93e3992d 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
a78b08d1 1611 for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {\r
93e3992d 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
676df92c 1630 FreePool (BootOptionVar);\r
93e3992d 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
676df92c 1639 FreePool (BootOptionVar);\r
93e3992d 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
676df92c 1648 FreePool (BootOptionVar);\r
93e3992d 1649 if (EFI_ERROR (Status)) {\r
1650 break;\r
1651 }\r
1652 }\r
1653\r
a78b08d1 1654 if (BootOrder != NULL) {\r
676df92c 1655 FreePool (BootOrder);\r
93e3992d 1656 }\r
1657 //\r
1658 // For debug\r
1659 //\r
1660 PrintBbsTable (LocalBbsTable);\r
1661\r
1662 return Status;\r
1663}\r