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