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