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