]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
BDS enhancement: enumerate & show all legacy boot options in Boot Manager so that...
[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
441 while (DevOrderCount-- != 0) {\r
442 for (Index = 0; Index < mBootOptionBbsMappingCount; Index++) {\r
443 if (mBootOptionBbsMapping[Index].BbsIndex == (DevOrder[DevOrderCount] & 0xFF)) {\r
444 BbsType = mBootOptionBbsMapping[Index].BbsType;\r
445 NewBootOption[DevOrderCount] = mBootOptionBbsMapping[Index].BootOptionNumber;\r
446 \r
447 if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) {\r
448 DisBootOption[*DisBootOptionCount] = NewBootOption[DevOrderCount];\r
449 (*DisBootOptionCount)++;\r
450 } else {\r
451 EnBootOption[*EnBootOptionCount] = NewBootOption[DevOrderCount];\r
452 (*EnBootOptionCount)++;\r
453 }\r
454 break;\r
455 }\r
456 }\r
457 }\r
458\r
459 for (Index = 0; Index < BootOptionCount; Index++) {\r
460 //\r
461 // Find the start position for the BbsType in BootOption\r
462 //\r
463 for (MappingIndex = 0; MappingIndex < mBootOptionBbsMappingCount; MappingIndex++) {\r
464 if (mBootOptionBbsMapping[MappingIndex].BbsType == BbsType && mBootOptionBbsMapping[MappingIndex].BootOptionNumber == BootOption[Index]) {\r
465 break;\r
466 }\r
467 }\r
468\r
469 //\r
470 // Overwrite the old BootOption\r
471 //\r
472 if (MappingIndex < mBootOptionBbsMappingCount) {\r
473 CopyMem (&BootOption[Index], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16));\r
474 break;\r
475 }\r
476 }\r
477}\r
478\r
479/**\r
480 Group the legacy boot options in the BootOption.\r
481\r
482 The routine assumes the boot options in the beginning that covers all the device \r
483 types are ordered properly and re-position the following boot options just after\r
484 the corresponding boot options with the same device type.\r
485 For example:\r
486 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]\r
487 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly\r
488 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]\r
489\r
490 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]\r
491 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly\r
492 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]\r
493\r
494 @param BootOption Pointer to buffer containing Boot Option Numbers\r
495 @param BootOptionCount Count of the Boot Option Numbers\r
496**/\r
497VOID\r
498GroupMultipleLegacyBootOption4SameType (\r
499 UINT16 *BootOption,\r
500 UINTN BootOptionCount\r
501 )\r
502{\r
503 UINTN DeviceTypeIndex[7];\r
504 UINTN Index;\r
505 UINTN MappingIndex;\r
506 UINTN *NextIndex;\r
507 UINT16 OptionNumber;\r
508 UINTN DeviceIndex;\r
509\r
510 SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xFF);\r
511\r
512 for (Index = 0; Index < BootOptionCount; Index++) {\r
513\r
514 //\r
515 // Find the DeviceType\r
516 //\r
517 for (MappingIndex = 0; MappingIndex < mBootOptionBbsMappingCount; MappingIndex++) {\r
518 if (mBootOptionBbsMapping[MappingIndex].BootOptionNumber == BootOption[Index]) {\r
519 break;\r
520 }\r
521 }\r
522 if (MappingIndex == mBootOptionBbsMappingCount) {\r
523 //\r
524 // Is not a legacy boot option\r
525 //\r
526 continue;\r
527 }\r
528\r
529 ASSERT ((mBootOptionBbsMapping[MappingIndex].BbsType & 0xF) < \r
530 sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]));\r
531 NextIndex = &DeviceTypeIndex[mBootOptionBbsMapping[MappingIndex].BbsType & 0xF];\r
532 if (*NextIndex == (UINTN) -1) {\r
533 //\r
534 // *NextIndex is the index in BootOption to put the next Option Number for the same type\r
535 //\r
536 *NextIndex = Index + 1;\r
537 } else {\r
538 //\r
539 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position\r
540 //\r
541 OptionNumber = BootOption[Index];\r
542 CopyMem (&BootOption[*NextIndex + 1], &BootOption[*NextIndex], (Index - *NextIndex) * sizeof (UINT16));\r
543 BootOption[*NextIndex] = OptionNumber;\r
544\r
545 //\r
546 // Update the DeviceTypeIndex array to reflect the right shift operation\r
547 //\r
548 for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) {\r
549 if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) {\r
550 DeviceTypeIndex[DeviceIndex]++;\r
551 }\r
552 }\r
553 }\r
554 }\r
555}\r
556\r
5c08e117 557/**\r
558 Delete all the invalid legacy boot options.\r
559\r
560 @retval EFI_SUCCESS All invalide legacy boot options are deleted.\r
561 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
562 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.\r
563**/\r
564EFI_STATUS\r
6ba0bc7c 565EFIAPI\r
5c08e117 566BdsDeleteAllInvalidLegacyBootOptions (\r
567 VOID\r
568 )\r
569{\r
570 UINT16 *BootOrder;\r
571 UINT8 *BootOptionVar;\r
572 UINTN BootOrderSize;\r
573 UINTN BootOptionSize;\r
574 EFI_STATUS Status;\r
575 UINT16 HddCount;\r
576 UINT16 BbsCount;\r
577 HDD_INFO *LocalHddInfo;\r
578 BBS_TABLE *LocalBbsTable;\r
579 BBS_TABLE *BbsEntry;\r
580 UINT16 BbsIndex;\r
581 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
582 UINTN Index;\r
583 UINT16 BootOption[10];\r
584 UINT16 BootDesc[100];\r
585 BOOLEAN DescStringMatch;\r
586\r
587 Status = EFI_SUCCESS;\r
588 BootOrder = NULL;\r
589 BootOrderSize = 0;\r
590 HddCount = 0;\r
591 BbsCount = 0;\r
592 LocalHddInfo = NULL;\r
593 LocalBbsTable = NULL;\r
594 BbsEntry = NULL;\r
595\r
596 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
597 if (EFI_ERROR (Status)) {\r
598 return Status;\r
599 }\r
600\r
601 LegacyBios->GetBbsInfo (\r
602 LegacyBios,\r
603 &HddCount,\r
604 &LocalHddInfo,\r
605 &BbsCount,\r
606 &LocalBbsTable\r
607 );\r
608\r
609 BootOrder = BdsLibGetVariableAndSize (\r
610 L"BootOrder",\r
611 &gEfiGlobalVariableGuid,\r
612 &BootOrderSize\r
613 );\r
22d1f978
RN
614 if (BootOrder == NULL) {\r
615 BootOrderSize = 0;\r
5c08e117 616 }\r
617\r
618 Index = 0;\r
619 while (Index < BootOrderSize / sizeof (UINT16)) {\r
620 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
621 BootOptionVar = BdsLibGetVariableAndSize (\r
622 BootOption,\r
623 &gEfiGlobalVariableGuid,\r
624 &BootOptionSize\r
625 );\r
626 if (NULL == BootOptionVar) {\r
22d1f978
RN
627 BootOptionSize = 0;\r
628 Status = gRT->GetVariable (\r
629 BootOption,\r
630 &gEfiGlobalVariableGuid,\r
631 NULL,\r
632 &BootOptionSize,\r
633 BootOptionVar\r
634 );\r
635 if (Status == EFI_NOT_FOUND) {\r
636 //\r
637 // Update BootOrder\r
638 //\r
639 BdsDeleteBootOption (\r
640 BootOrder[Index],\r
641 BootOrder,\r
642 &BootOrderSize\r
643 );\r
644 continue;\r
645 } else {\r
5c08e117 646 FreePool (BootOrder);\r
22d1f978 647 return EFI_OUT_OF_RESOURCES;\r
5c08e117 648 }\r
5c08e117 649 }\r
650 \r
651 //\r
22d1f978 652 // Skip Non-Legacy boot option\r
5c08e117 653 // \r
654 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
655 if (BootOptionVar!= NULL) {\r
656 FreePool (BootOptionVar);\r
657 }\r
658 Index++;\r
659 continue;\r
660 }\r
661\r
22d1f978
RN
662 if (BbsIndex < BbsCount) {\r
663 //\r
664 // Check if BBS Description String is changed\r
665 //\r
666 DescStringMatch = FALSE;\r
667 BdsBuildLegacyDevNameString (\r
668 &LocalBbsTable[BbsIndex],\r
669 BbsIndex,\r
670 sizeof (BootDesc),\r
671 BootDesc\r
672 );\r
673\r
674 if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
675 DescStringMatch = TRUE;\r
676 }\r
5c08e117 677\r
22d1f978
RN
678 if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
679 (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&\r
680 (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
681 DescStringMatch) {\r
682 Index++;\r
683 continue;\r
684 }\r
5c08e117 685 }\r
686\r
687 if (BootOptionVar != NULL) {\r
688 FreePool (BootOptionVar);\r
689 }\r
690 //\r
691 // should delete\r
692 //\r
693 BdsDeleteBootOption (\r
694 BootOrder[Index],\r
695 BootOrder,\r
696 &BootOrderSize\r
697 );\r
698 }\r
699\r
700 //\r
701 // Adjust the number of boot options.\r
702 //\r
703 if (BootOrderSize != 0) {\r
704 Status = gRT->SetVariable (\r
705 L"BootOrder",\r
706 &gEfiGlobalVariableGuid,\r
707 VAR_FLAG,\r
708 BootOrderSize,\r
709 BootOrder\r
710 );\r
711 } else {\r
712 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
713 }\r
714\r
715 if (BootOrder != NULL) {\r
716 FreePool (BootOrder);\r
717 }\r
718\r
719 return Status;\r
720}\r
721\r
722/**\r
723 Find all legacy boot option by device type.\r
724\r
725 @param BootOrder The boot order array.\r
726 @param BootOptionNum The number of boot option.\r
727 @param DevType Device type.\r
22d1f978 728 @param DevName Device name.\r
5c08e117 729 @param Attribute The boot option attribute.\r
730 @param BbsIndex The BBS table index.\r
731 @param OptionNumber The boot option index.\r
732\r
733 @retval TRUE The Legacy boot option is found.\r
734 @retval FALSE The legacy boot option is not found.\r
735\r
736**/\r
737BOOLEAN\r
22d1f978 738BdsFindLegacyBootOptionByDevTypeAndName (\r
5c08e117 739 IN UINT16 *BootOrder,\r
740 IN UINTN BootOptionNum,\r
741 IN UINT16 DevType,\r
22d1f978 742 IN CHAR16 *DevName,\r
5c08e117 743 OUT UINT32 *Attribute,\r
744 OUT UINT16 *BbsIndex,\r
22d1f978 745 OUT UINT16 *OptionNumber\r
5c08e117 746 )\r
747{\r
748 UINTN Index;\r
22d1f978 749 CHAR16 BootOption[9];\r
5c08e117 750 UINTN BootOptionSize;\r
751 UINT8 *BootOptionVar;\r
752 BBS_TABLE *BbsEntry;\r
753 BOOLEAN Found;\r
754\r
755 BbsEntry = NULL;\r
756 Found = FALSE;\r
757\r
758 if (NULL == BootOrder) {\r
759 return Found;\r
760 }\r
761\r
762 //\r
763 // Loop all boot option from variable\r
764 //\r
22d1f978
RN
765 for (Index = 0; Index < BootOptionNum; Index++) {\r
766 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", (UINTN) BootOrder[Index]);\r
5c08e117 767 BootOptionVar = BdsLibGetVariableAndSize (\r
768 BootOption,\r
769 &gEfiGlobalVariableGuid,\r
770 &BootOptionSize\r
771 );\r
772 if (NULL == BootOptionVar) {\r
773 continue;\r
774 }\r
775\r
776 //\r
777 // Skip Non-legacy boot option\r
778 //\r
779 if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
780 FreePool (BootOptionVar);\r
781 continue;\r
782 }\r
783\r
22d1f978
RN
784 if (\r
785 (BbsEntry->DeviceType != DevType) ||\r
786 (StrCmp (DevName, (CHAR16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) != 0)\r
787 ) {\r
5c08e117 788 FreePool (BootOptionVar);\r
789 continue;\r
790 }\r
791\r
792 *Attribute = *(UINT32 *) BootOptionVar;\r
22d1f978 793 *OptionNumber = BootOrder[Index];\r
5c08e117 794 Found = TRUE;\r
795 FreePool (BootOptionVar);\r
796 break;\r
797 }\r
798\r
799 return Found;\r
800}\r
801\r
802/**\r
803 Create a legacy boot option.\r
804\r
805 @param BbsItem The BBS Table entry.\r
806 @param Index Index of the specified entry in BBS table.\r
807 @param BootOrderList The boot order list.\r
808 @param BootOrderListSize The size of boot order list.\r
809\r
810 @retval EFI_OUT_OF_RESOURCE No enough memory.\r
811 @retval EFI_SUCCESS The function complete successfully.\r
812 @return Other value if the legacy boot option is not created.\r
813\r
814**/\r
815EFI_STATUS\r
816BdsCreateOneLegacyBootOption (\r
817 IN BBS_TABLE *BbsItem,\r
818 IN UINTN Index,\r
819 IN OUT UINT16 **BootOrderList,\r
820 IN OUT UINTN *BootOrderListSize\r
821 )\r
822{\r
823 BBS_BBS_DEVICE_PATH BbsDevPathNode;\r
824 EFI_STATUS Status;\r
825 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
826\r
827 DevPath = NULL;\r
828\r
829 //\r
830 // Create device path node.\r
831 //\r
832 BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;\r
833 BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
834 SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
835 BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
836 CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
837\r
838 DevPath = AppendDevicePathNode (\r
839 EndDevicePath,\r
840 (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
841 );\r
842 if (NULL == DevPath) {\r
843 return EFI_OUT_OF_RESOURCES;\r
844 }\r
845\r
846 Status = BdsCreateLegacyBootOption (\r
847 BbsItem,\r
848 DevPath,\r
849 Index,\r
850 BootOrderList,\r
851 BootOrderListSize\r
852 );\r
853 BbsItem->BootPriority = 0x00;\r
854\r
855 FreePool (DevPath);\r
856\r
857 return Status;\r
858}\r
859\r
860/**\r
5c08e117 861 Add the legacy boot options from BBS table if they do not exist.\r
862\r
e83c9064
LG
863 @retval EFI_SUCCESS The boot options are added successfully \r
864 or they are already in boot options.\r
865 @retval EFI_NOT_FOUND No legacy boot options is found.\r
866 @retval EFI_OUT_OF_RESOURCE No enough memory.\r
867 @return Other value LegacyBoot options are not added.\r
5c08e117 868**/\r
869EFI_STATUS\r
6ba0bc7c 870EFIAPI\r
5c08e117 871BdsAddNonExistingLegacyBootOptions (\r
872 VOID\r
873 )\r
874{\r
875 UINT16 *BootOrder;\r
876 UINTN BootOrderSize;\r
877 EFI_STATUS Status;\r
22d1f978 878 CHAR16 Desc[100];\r
5c08e117 879 UINT16 HddCount;\r
880 UINT16 BbsCount;\r
881 HDD_INFO *LocalHddInfo;\r
882 BBS_TABLE *LocalBbsTable;\r
883 UINT16 BbsIndex;\r
884 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
22d1f978 885 UINT16 Index;\r
5c08e117 886 UINT32 Attribute;\r
22d1f978
RN
887 UINT16 OptionNumber;\r
888 BOOLEAN Exist;\r
5c08e117 889\r
5c08e117 890 HddCount = 0;\r
891 BbsCount = 0;\r
892 LocalHddInfo = NULL;\r
893 LocalBbsTable = NULL;\r
894\r
895 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
896 if (EFI_ERROR (Status)) {\r
897 return Status;\r
898 }\r
899\r
22d1f978
RN
900 if (mBootOptionBbsMapping != NULL) {\r
901 FreePool (mBootOptionBbsMapping);\r
902\r
903 mBootOptionBbsMapping = NULL;\r
904 mBootOptionBbsMappingCount = 0;\r
905 }\r
906\r
5c08e117 907 LegacyBios->GetBbsInfo (\r
908 LegacyBios,\r
909 &HddCount,\r
910 &LocalHddInfo,\r
911 &BbsCount,\r
912 &LocalBbsTable\r
913 );\r
914\r
915 BootOrder = BdsLibGetVariableAndSize (\r
916 L"BootOrder",\r
917 &gEfiGlobalVariableGuid,\r
918 &BootOrderSize\r
919 );\r
22d1f978 920 if (BootOrder == NULL) {\r
5c08e117 921 BootOrderSize = 0;\r
922 }\r
923\r
924 for (Index = 0; Index < BbsCount; Index++) {\r
925 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
926 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
927 ) {\r
928 continue;\r
929 }\r
930\r
22d1f978
RN
931 BdsBuildLegacyDevNameString (&LocalBbsTable[Index], Index, sizeof (Desc), Desc);\r
932\r
933 Exist = BdsFindLegacyBootOptionByDevTypeAndName (\r
934 BootOrder,\r
935 BootOrderSize / sizeof (UINT16),\r
936 LocalBbsTable[Index].DeviceType,\r
937 Desc,\r
938 &Attribute,\r
939 &BbsIndex,\r
940 &OptionNumber\r
941 );\r
942 if (!Exist) {\r
943 //\r
944 // Not found such type of legacy device in boot options or we found but it's disabled\r
945 // so we have to create one and put it to the tail of boot order list\r
946 //\r
947 Status = BdsCreateOneLegacyBootOption (\r
948 &LocalBbsTable[Index],\r
949 Index,\r
950 &BootOrder,\r
951 &BootOrderSize\r
952 );\r
953 if (EFI_ERROR (Status)) {\r
954 break;\r
955 }\r
956 BbsIndex = Index;\r
957 OptionNumber = BootOrder[BootOrderSize / sizeof (UINT16) - 1];\r
5c08e117 958 }\r
959\r
22d1f978 960 ASSERT (BbsIndex == Index);\r
5c08e117 961 //\r
22d1f978 962 // Save the BbsIndex\r
5c08e117 963 //\r
22d1f978
RN
964 mBootOptionBbsMapping = ReallocatePool (\r
965 mBootOptionBbsMappingCount * sizeof (BOOT_OPTION_BBS_MAPPING),\r
966 (mBootOptionBbsMappingCount + 1) * sizeof (BOOT_OPTION_BBS_MAPPING),\r
967 mBootOptionBbsMapping\r
968 );\r
969 ASSERT (mBootOptionBbsMapping != NULL);\r
970 mBootOptionBbsMapping[mBootOptionBbsMappingCount].BootOptionNumber = OptionNumber;\r
971 mBootOptionBbsMapping[mBootOptionBbsMappingCount].BbsIndex = Index;\r
972 mBootOptionBbsMapping[mBootOptionBbsMappingCount].BbsType = LocalBbsTable[Index].DeviceType;\r
973 mBootOptionBbsMappingCount ++;\r
5c08e117 974 }\r
975\r
22d1f978
RN
976 //\r
977 // Group the Boot Option Number in BootOrder for the same type devices\r
978 //\r
979 GroupMultipleLegacyBootOption4SameType (\r
980 BootOrder,\r
981 BootOrderSize / sizeof (UINT16)\r
982 );\r
983\r
5c08e117 984 if (BootOrderSize > 0) {\r
985 Status = gRT->SetVariable (\r
986 L"BootOrder",\r
987 &gEfiGlobalVariableGuid,\r
988 VAR_FLAG,\r
989 BootOrderSize,\r
990 BootOrder\r
991 );\r
992 } else {\r
993 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
994 }\r
995\r
996 if (BootOrder != NULL) {\r
997 FreePool (BootOrder);\r
998 }\r
999\r
1000 return Status;\r
1001}\r
1002\r
1003/**\r
1004 Fill the device order buffer.\r
1005\r
1006 @param BbsTable The BBS table.\r
1007 @param BbsType The BBS Type.\r
1008 @param BbsCount The BBS Count.\r
1009 @param Buf device order buffer.\r
1010\r
1011 @return The device order buffer.\r
1012\r
1013**/\r
1014UINT16 *\r
1015BdsFillDevOrderBuf (\r
1016 IN BBS_TABLE *BbsTable,\r
1017 IN BBS_TYPE BbsType,\r
1018 IN UINTN BbsCount,\r
22d1f978 1019 OUT UINT16 *Buf\r
5c08e117 1020 )\r
1021{\r
1022 UINTN Index;\r
1023\r
1024 for (Index = 0; Index < BbsCount; Index++) {\r
1025 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
1026 continue;\r
1027 }\r
1028\r
1029 if (BbsTable[Index].DeviceType != BbsType) {\r
1030 continue;\r
1031 }\r
1032\r
1033 *Buf = (UINT16) (Index & 0xFF);\r
1034 Buf++;\r
1035 }\r
1036\r
1037 return Buf;\r
1038}\r
1039\r
1040/**\r
1041 Create the device order buffer.\r
1042\r
1043 @param BbsTable The BBS table.\r
1044 @param BbsCount The BBS Count.\r
1045\r
e83c9064
LG
1046 @retval EFI_SUCCES The buffer is created and the EFI variable named \r
1047 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is\r
1048 set correctly.\r
1049 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.\r
1050 @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail\r
1051 because of hardware error.\r
5c08e117 1052**/\r
1053EFI_STATUS\r
1054BdsCreateDevOrder (\r
1055 IN BBS_TABLE *BbsTable,\r
1056 IN UINT16 BbsCount\r
1057 )\r
1058{\r
22d1f978
RN
1059 UINTN Index;\r
1060 UINTN FDCount;\r
1061 UINTN HDCount;\r
1062 UINTN CDCount;\r
1063 UINTN NETCount;\r
1064 UINTN BEVCount;\r
1065 UINTN TotalSize;\r
1066 UINTN HeaderSize;\r
1067 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
1068 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrderPtr;\r
1069 EFI_STATUS Status;\r
5c08e117 1070\r
1071 FDCount = 0;\r
1072 HDCount = 0;\r
1073 CDCount = 0;\r
1074 NETCount = 0;\r
1075 BEVCount = 0;\r
1076 TotalSize = 0;\r
1077 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
1078 DevOrder = NULL;\r
5c08e117 1079 Status = EFI_SUCCESS;\r
1080\r
1081 //\r
1082 // Count all boot devices\r
1083 //\r
1084 for (Index = 0; Index < BbsCount; Index++) {\r
1085 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
1086 continue;\r
1087 }\r
1088\r
1089 switch (BbsTable[Index].DeviceType) {\r
1090 case BBS_FLOPPY:\r
1091 FDCount++;\r
1092 break;\r
1093\r
1094 case BBS_HARDDISK:\r
1095 HDCount++;\r
1096 break;\r
1097\r
1098 case BBS_CDROM:\r
1099 CDCount++;\r
1100 break;\r
1101\r
1102 case BBS_EMBED_NETWORK:\r
1103 NETCount++;\r
1104 break;\r
1105\r
1106 case BBS_BEV_DEVICE:\r
1107 BEVCount++;\r
1108 break;\r
1109\r
1110 default:\r
1111 break;\r
1112 }\r
1113 }\r
1114\r
1115 TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
1116 TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
1117 TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
1118 TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
1119 TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
1120\r
1121 //\r
1122 // Create buffer to hold all boot device order\r
1123 //\r
1124 DevOrder = AllocateZeroPool (TotalSize);\r
1125 if (NULL == DevOrder) {\r
1126 return EFI_OUT_OF_RESOURCES;\r
1127 }\r
22d1f978 1128 DevOrderPtr = DevOrder;\r
5c08e117 1129\r
22d1f978
RN
1130 DevOrderPtr->BbsType = BBS_FLOPPY;\r
1131 DevOrderPtr->Length = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));\r
1132 DevOrderPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);\r
5c08e117 1133\r
22d1f978
RN
1134 DevOrderPtr->BbsType = BBS_HARDDISK;\r
1135 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
1136 DevOrderPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);\r
1137 \r
1138 DevOrderPtr->BbsType = BBS_CDROM;\r
1139 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
1140 DevOrderPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);\r
1141 \r
1142 DevOrderPtr->BbsType = BBS_EMBED_NETWORK;\r
1143 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
1144 DevOrderPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);\r
5c08e117 1145\r
22d1f978
RN
1146 DevOrderPtr->BbsType = BBS_BEV_DEVICE;\r
1147 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
1148 DevOrderPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);\r
5c08e117 1149\r
22d1f978 1150 ASSERT (TotalSize == (UINTN) ((UINT8 *) DevOrderPtr - (UINT8 *) DevOrder));\r
5c08e117 1151\r
1152 //\r
1153 // Save device order for legacy boot device to variable.\r
1154 //\r
1155 Status = gRT->SetVariable (\r
1156 VAR_LEGACY_DEV_ORDER,\r
1157 &EfiLegacyDevOrderGuid,\r
1158 VAR_FLAG,\r
1159 TotalSize,\r
1160 DevOrder\r
1161 );\r
1162 FreePool (DevOrder);\r
1163\r
1164 return Status;\r
1165}\r
1166\r
1167/**\r
5c08e117 1168 Add the legacy boot devices from BBS table into \r
1169 the legacy device boot order.\r
1170\r
e83c9064
LG
1171 @retval EFI_SUCCESS The boot devices are added successfully.\r
1172 @retval EFI_NOT_FOUND The legacy boot devices are not found.\r
1173 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.\r
1174 @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable\r
1175 because of hardware error.\r
5c08e117 1176**/\r
1177EFI_STATUS\r
6ba0bc7c 1178EFIAPI\r
5c08e117 1179BdsUpdateLegacyDevOrder (\r
1180 VOID\r
1181 )\r
1182{\r
22d1f978
RN
1183 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
1184 BM_LEGACY_DEV_ORDER_CONTEXT *NewDevOrder;\r
1185 BM_LEGACY_DEV_ORDER_CONTEXT *Ptr;\r
1186 BM_LEGACY_DEV_ORDER_CONTEXT *NewPtr;\r
1187 UINTN DevOrderSize;\r
1188 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1189 EFI_STATUS Status;\r
1190 UINT16 HddCount;\r
1191 UINT16 BbsCount;\r
1192 HDD_INFO *LocalHddInfo;\r
1193 BBS_TABLE *LocalBbsTable;\r
1194 UINTN Index;\r
1195 UINTN Index2;\r
1196 UINTN *Idx;\r
1197 UINTN FDCount;\r
1198 UINTN HDCount;\r
1199 UINTN CDCount;\r
1200 UINTN NETCount;\r
1201 UINTN BEVCount;\r
1202 UINTN TotalSize;\r
1203 UINTN HeaderSize;\r
1204 UINT16 *NewFDPtr;\r
1205 UINT16 *NewHDPtr;\r
1206 UINT16 *NewCDPtr;\r
1207 UINT16 *NewNETPtr;\r
1208 UINT16 *NewBEVPtr;\r
1209 UINT16 *NewDevPtr;\r
1210 UINTN FDIndex;\r
1211 UINTN HDIndex;\r
1212 UINTN CDIndex;\r
1213 UINTN NETIndex;\r
1214 UINTN BEVIndex;\r
5c08e117 1215\r
5c08e117 1216 Idx = NULL;\r
1217 FDCount = 0;\r
1218 HDCount = 0;\r
1219 CDCount = 0;\r
1220 NETCount = 0;\r
1221 BEVCount = 0;\r
1222 TotalSize = 0;\r
1223 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
1224 FDIndex = 0;\r
1225 HDIndex = 0;\r
1226 CDIndex = 0;\r
1227 NETIndex = 0;\r
1228 BEVIndex = 0;\r
1229 NewDevPtr = NULL;\r
1230\r
1231 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
1232 if (EFI_ERROR (Status)) {\r
1233 return Status;\r
1234 }\r
1235\r
22d1f978
RN
1236 Status = LegacyBios->GetBbsInfo (\r
1237 LegacyBios,\r
1238 &HddCount,\r
1239 &LocalHddInfo,\r
1240 &BbsCount,\r
1241 &LocalBbsTable\r
1242 );\r
1243 if (EFI_ERROR (Status)) {\r
1244 return Status;\r
1245 }\r
5c08e117 1246\r
22d1f978
RN
1247 DevOrder = BdsLibGetVariableAndSize (\r
1248 VAR_LEGACY_DEV_ORDER,\r
1249 &EfiLegacyDevOrderGuid,\r
1250 &DevOrderSize\r
1251 );\r
5c08e117 1252 if (NULL == DevOrder) {\r
1253 return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
1254 }\r
1255 //\r
1256 // First we figure out how many boot devices with same device type respectively\r
1257 //\r
1258 for (Index = 0; Index < BbsCount; Index++) {\r
1259 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
1260 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
1261 ) {\r
1262 continue;\r
1263 }\r
1264\r
1265 switch (LocalBbsTable[Index].DeviceType) {\r
1266 case BBS_FLOPPY:\r
1267 FDCount++;\r
1268 break;\r
1269\r
1270 case BBS_HARDDISK:\r
1271 HDCount++;\r
1272 break;\r
1273\r
1274 case BBS_CDROM:\r
1275 CDCount++;\r
1276 break;\r
1277\r
1278 case BBS_EMBED_NETWORK:\r
1279 NETCount++;\r
1280 break;\r
1281\r
1282 case BBS_BEV_DEVICE:\r
1283 BEVCount++;\r
1284 break;\r
1285\r
1286 default:\r
1287 break;\r
1288 }\r
1289 }\r
1290\r
1291 TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
1292 TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
1293 TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
1294 TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
1295 TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
1296\r
1297 NewDevOrder = AllocateZeroPool (TotalSize);\r
1298 if (NULL == NewDevOrder) {\r
1299 return EFI_OUT_OF_RESOURCES;\r
1300 }\r
1301\r
22d1f978 1302\r
5c08e117 1303\r
1304 //\r
1305 // copy FD\r
1306 //\r
22d1f978
RN
1307 Ptr = DevOrder;\r
1308 NewPtr = NewDevOrder;\r
1309 NewPtr->BbsType = Ptr->BbsType;\r
1310 NewPtr->Length = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
1311 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
1312 if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
1313 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
1314 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY\r
5c08e117 1315 ) {\r
5c08e117 1316 continue;\r
1317 }\r
1318\r
22d1f978 1319 NewPtr->Data[FDIndex] = Ptr->Data[Index];\r
5c08e117 1320 FDIndex++;\r
5c08e117 1321 }\r
22d1f978
RN
1322 NewFDPtr = NewPtr->Data;\r
1323\r
5c08e117 1324 //\r
1325 // copy HD\r
1326 //\r
22d1f978
RN
1327 Ptr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
1328 NewPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
1329 NewPtr->BbsType = Ptr->BbsType;\r
1330 NewPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
1331 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
1332 if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
1333 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
1334 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
1335 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK\r
5c08e117 1336 ) {\r
5c08e117 1337 continue;\r
1338 }\r
1339\r
22d1f978 1340 NewPtr->Data[HDIndex] = Ptr->Data[Index];\r
5c08e117 1341 HDIndex++;\r
5c08e117 1342 }\r
22d1f978
RN
1343 NewHDPtr = NewPtr->Data;\r
1344\r
5c08e117 1345 //\r
1346 // copy CD\r
1347 //\r
22d1f978
RN
1348 Ptr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
1349 NewPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
1350 NewPtr->BbsType = Ptr->BbsType;\r
1351 NewPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
1352 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
1353 if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
1354 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
1355 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
1356 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM\r
5c08e117 1357 ) {\r
5c08e117 1358 continue;\r
1359 }\r
1360\r
22d1f978 1361 NewPtr->Data[CDIndex] = Ptr->Data[Index];\r
5c08e117 1362 CDIndex++;\r
5c08e117 1363 }\r
22d1f978
RN
1364 NewCDPtr = NewPtr->Data;\r
1365\r
5c08e117 1366 //\r
1367 // copy NET\r
1368 //\r
22d1f978
RN
1369 Ptr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
1370 NewPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
1371 NewPtr->BbsType = Ptr->BbsType;\r
1372 NewPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
1373 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
1374 if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
1375 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
1376 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
1377 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK\r
5c08e117 1378 ) {\r
5c08e117 1379 continue;\r
1380 }\r
1381\r
22d1f978 1382 NewPtr->Data[NETIndex] = Ptr->Data[Index];\r
5c08e117 1383 NETIndex++;\r
5c08e117 1384 }\r
22d1f978
RN
1385 NewNETPtr = NewPtr->Data;\r
1386 \r
5c08e117 1387 //\r
1388 // copy BEV\r
1389 //\r
22d1f978
RN
1390 Ptr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
1391 NewPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
1392 NewPtr->BbsType = Ptr->BbsType;\r
1393 NewPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
1394 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
1395 if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
1396 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
1397 LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
1398 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE\r
5c08e117 1399 ) {\r
5c08e117 1400 continue;\r
1401 }\r
1402\r
22d1f978 1403 NewPtr->Data[BEVIndex] = Ptr->Data[Index];\r
5c08e117 1404 BEVIndex++;\r
5c08e117 1405 }\r
22d1f978 1406 NewBEVPtr = NewPtr->Data;\r
5c08e117 1407\r
1408 for (Index = 0; Index < BbsCount; Index++) {\r
1409 if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
1410 (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
1411 ) {\r
1412 continue;\r
1413 }\r
1414\r
1415 switch (LocalBbsTable[Index].DeviceType) {\r
1416 case BBS_FLOPPY:\r
1417 Idx = &FDIndex;\r
1418 NewDevPtr = NewFDPtr;\r
1419 break;\r
1420\r
1421 case BBS_HARDDISK:\r
1422 Idx = &HDIndex;\r
1423 NewDevPtr = NewHDPtr;\r
1424 break;\r
1425\r
1426 case BBS_CDROM:\r
1427 Idx = &CDIndex;\r
1428 NewDevPtr = NewCDPtr;\r
1429 break;\r
1430\r
1431 case BBS_EMBED_NETWORK:\r
1432 Idx = &NETIndex;\r
1433 NewDevPtr = NewNETPtr;\r
1434 break;\r
1435\r
1436 case BBS_BEV_DEVICE:\r
1437 Idx = &BEVIndex;\r
1438 NewDevPtr = NewBEVPtr;\r
1439 break;\r
1440\r
1441 default:\r
1442 Idx = NULL;\r
1443 break;\r
1444 }\r
1445 //\r
1446 // at this point we have copied those valid indexes to new buffer\r
1447 // and we should check if there is any new appeared boot device\r
1448 //\r
22d1f978 1449 if (Idx != NULL) {\r
5c08e117 1450 for (Index2 = 0; Index2 < *Idx; Index2++) {\r
1451 if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
1452 break;\r
1453 }\r
1454 }\r
1455\r
1456 if (Index2 == *Idx) {\r
1457 //\r
1458 // Index2 == *Idx means we didn't find Index\r
1459 // so Index is a new appeared device's index in BBS table\r
22d1f978 1460 // insert it before disabled indexes.\r
5c08e117 1461 //\r
22d1f978
RN
1462 for (Index2 = 0; Index2 < *Idx; Index2++) {\r
1463 if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {\r
1464 break;\r
1465 }\r
5c08e117 1466 }\r
22d1f978
RN
1467 CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));\r
1468 NewDevPtr[Index2] = (UINT16) (Index & 0xFF);\r
1469 (*Idx)++;\r
5c08e117 1470 }\r
1471 }\r
1472 }\r
1473\r
1474 FreePool (DevOrder);\r
1475\r
1476 Status = gRT->SetVariable (\r
1477 VAR_LEGACY_DEV_ORDER,\r
1478 &EfiLegacyDevOrderGuid,\r
1479 VAR_FLAG,\r
1480 TotalSize,\r
1481 NewDevOrder\r
1482 );\r
1483 FreePool (NewDevOrder);\r
1484\r
1485 return Status;\r
1486}\r
1487\r
1488/**\r
1489 Set Boot Priority for specified device type.\r
1490\r
1491 @param DeviceType The device type.\r
22d1f978 1492 @param BbsIndex The BBS index to set the highest priority. Ignore when -1.\r
5c08e117 1493 @param LocalBbsTable The BBS table.\r
1494 @param Priority The prority table.\r
1495\r
e83c9064
LG
1496 @retval EFI_SUCCESS The function completes successfully.\r
1497 @retval EFI_NOT_FOUND Failed to find device.\r
1498 @retval EFI_OUT_OF_RESOURCES Failed to get the efi variable of device order.\r
5c08e117 1499\r
1500**/\r
1501EFI_STATUS\r
1502BdsSetBootPriority4SameTypeDev (\r
1503 IN UINT16 DeviceType,\r
22d1f978 1504 IN UINTN BbsIndex,\r
5c08e117 1505 IN OUT BBS_TABLE *LocalBbsTable,\r
1506 IN OUT UINT16 *Priority\r
1507 )\r
1508{\r
22d1f978
RN
1509 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
1510 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrderPtr;\r
1511 UINTN DevOrderSize;\r
1512 UINTN Index;\r
5c08e117 1513\r
1514 DevOrder = BdsLibGetVariableAndSize (\r
22d1f978
RN
1515 VAR_LEGACY_DEV_ORDER,\r
1516 &EfiLegacyDevOrderGuid,\r
1517 &DevOrderSize\r
1518 );\r
5c08e117 1519 if (NULL == DevOrder) {\r
1520 return EFI_OUT_OF_RESOURCES;\r
1521 }\r
1522\r
22d1f978
RN
1523 DevOrderPtr = DevOrder;\r
1524 while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) {\r
1525 if (DevOrderPtr->BbsType == DeviceType) {\r
5c08e117 1526 break;\r
1527 }\r
1528\r
22d1f978 1529 DevOrderPtr = (BM_LEGACY_DEV_ORDER_CONTEXT *) ((UINT8 *) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length);\r
5c08e117 1530 }\r
1531\r
22d1f978
RN
1532 if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) {\r
1533 FreePool (DevOrder);\r
5c08e117 1534 return EFI_NOT_FOUND;\r
1535 }\r
1536\r
22d1f978
RN
1537 if (BbsIndex != (UINTN) -1) {\r
1538 LocalBbsTable[BbsIndex].BootPriority = *Priority;\r
1539 (*Priority)++;\r
1540 }\r
5c08e117 1541 //\r
1542 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
1543 //\r
22d1f978
RN
1544 for (Index = 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) {\r
1545 if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) {\r
5c08e117 1546 //\r
1547 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
1548 //\r
22d1f978
RN
1549 } else if (DevOrderPtr->Data[Index] != BbsIndex) {\r
1550 LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority;\r
5c08e117 1551 (*Priority)++;\r
1552 }\r
1553 }\r
1554\r
22d1f978 1555 FreePool (DevOrder);\r
5c08e117 1556 return EFI_SUCCESS;\r
1557}\r
1558\r
1559/**\r
1560 Print the BBS Table.\r
1561\r
1562 @param LocalBbsTable The BBS table.\r
13078b3f 1563 @param BbsCount The count of entry in BBS table.\r
5c08e117 1564**/\r
1565VOID\r
1566PrintBbsTable (\r
d7d5db96 1567 IN BBS_TABLE *LocalBbsTable,\r
1568 IN UINT16 BbsCount\r
5c08e117 1569 )\r
1570{\r
1571 UINT16 Idx;\r
1572\r
1573 DEBUG ((DEBUG_ERROR, "\n"));\r
1574 DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
1575 DEBUG ((DEBUG_ERROR, "=============================================\n"));\r
d7d5db96 1576 for (Idx = 0; Idx < BbsCount; Idx++) {\r
5c08e117 1577 if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
1578 (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
1579 (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
1580 ) {\r
1581 continue;\r
1582 }\r
1583\r
1584 DEBUG (\r
1585 (DEBUG_ERROR,\r
1586 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
1587 (UINTN) Idx,\r
1588 (UINTN) LocalBbsTable[Idx].BootPriority,\r
1589 (UINTN) LocalBbsTable[Idx].Bus,\r
1590 (UINTN) LocalBbsTable[Idx].Device,\r
1591 (UINTN) LocalBbsTable[Idx].Function,\r
1592 (UINTN) LocalBbsTable[Idx].Class,\r
1593 (UINTN) LocalBbsTable[Idx].SubClass,\r
1594 (UINTN) LocalBbsTable[Idx].DeviceType,\r
1595 (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
1596 (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
1597 (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
1598 (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
1599 (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
1600 );\r
1601 }\r
1602\r
1603 DEBUG ((DEBUG_ERROR, "\n"));\r
1604}\r
1605\r
1606/**\r
5c08e117 1607 Set the boot priority for BBS entries based on boot option entry and boot order.\r
1608\r
1609 @param Entry The boot option is to be checked for refresh BBS table.\r
1610 \r
e83c9064
LG
1611 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.\r
1612 @retval EFI_NOT_FOUND BBS entries can't be found.\r
1613 @retval EFI_OUT_OF_RESOURCES Failed to get the legacy device boot order.\r
5c08e117 1614**/\r
1615EFI_STATUS\r
6ba0bc7c 1616EFIAPI\r
5c08e117 1617BdsRefreshBbsTableForBoot (\r
1618 IN BDS_COMMON_OPTION *Entry\r
1619 )\r
1620{\r
1621 EFI_STATUS Status;\r
22d1f978 1622 UINT16 BbsIndex;\r
5c08e117 1623 UINT16 HddCount;\r
1624 UINT16 BbsCount;\r
1625 HDD_INFO *LocalHddInfo;\r
1626 BBS_TABLE *LocalBbsTable;\r
1627 UINT16 DevType;\r
1628 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1629 UINTN Index;\r
1630 UINT16 Priority;\r
1631 UINT16 *BootOrder;\r
1632 UINTN BootOrderSize;\r
1633 UINT8 *BootOptionVar;\r
1634 UINTN BootOptionSize;\r
22d1f978 1635 CHAR16 BootOption[9];\r
5c08e117 1636 UINT8 *Ptr;\r
1637 UINT16 DevPathLen;\r
1638 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
22d1f978
RN
1639 UINT16 *DeviceType;\r
1640 UINTN DeviceTypeCount;\r
1641 UINTN DeviceTypeIndex;\r
5c08e117 1642\r
1643 HddCount = 0;\r
1644 BbsCount = 0;\r
1645 LocalHddInfo = NULL;\r
1646 LocalBbsTable = NULL;\r
1647 DevType = BBS_UNKNOWN;\r
1648\r
1649 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
1650 if (EFI_ERROR (Status)) {\r
1651 return Status;\r
1652 }\r
1653\r
1654 LegacyBios->GetBbsInfo (\r
1655 LegacyBios,\r
1656 &HddCount,\r
1657 &LocalHddInfo,\r
1658 &BbsCount,\r
1659 &LocalBbsTable\r
1660 );\r
1661 //\r
1662 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
1663 // We will set them according to the settings setup by user\r
1664 //\r
1665 for (Index = 0; Index < BbsCount; Index++) {\r
1666 if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
1667 (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
1668 (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
1669 LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
1670 }\r
1671 }\r
1672 //\r
1673 // boot priority always starts at 0\r
1674 //\r
1675 Priority = 0;\r
1676 if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
1677 //\r
1678 // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
1679 //\r
22d1f978
RN
1680 DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
1681 BbsIndex = *(UINT16 *) ((BBS_TABLE *) Entry->LoadOptions + 1);\r
5c08e117 1682 Status = BdsSetBootPriority4SameTypeDev (\r
1683 DevType,\r
22d1f978 1684 BbsIndex,\r
5c08e117 1685 LocalBbsTable,\r
1686 &Priority\r
1687 );\r
1688 if (EFI_ERROR (Status)) {\r
1689 return Status;\r
1690 }\r
1691 }\r
1692 //\r
1693 // we have to set the boot priority for other BBS entries with different device types\r
1694 //\r
22d1f978
RN
1695 BootOrder = BdsLibGetVariableAndSize (\r
1696 L"BootOrder",\r
1697 &gEfiGlobalVariableGuid,\r
1698 &BootOrderSize\r
1699 );\r
1700 DeviceType = AllocatePool (BootOrderSize + sizeof (UINT16));\r
1701 ASSERT (DeviceType != NULL);\r
1702\r
1703 DeviceType[0] = DevType;\r
1704 DeviceTypeCount = 1;\r
5c08e117 1705 for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {\r
1706 UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
1707 BootOptionVar = BdsLibGetVariableAndSize (\r
1708 BootOption,\r
1709 &gEfiGlobalVariableGuid,\r
1710 &BootOptionSize\r
1711 );\r
1712 if (NULL == BootOptionVar) {\r
1713 continue;\r
1714 }\r
1715\r
1716 Ptr = BootOptionVar;\r
1717\r
1718 Ptr += sizeof (UINT32);\r
1719 DevPathLen = *(UINT16 *) Ptr;\r
1720 Ptr += sizeof (UINT16);\r
1721 Ptr += StrSize ((UINT16 *) Ptr);\r
1722 DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
1723 if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
1724 FreePool (BootOptionVar);\r
1725 continue;\r
1726 }\r
1727\r
1728 Ptr += DevPathLen;\r
22d1f978
RN
1729 DevType = ((BBS_TABLE *) Ptr)->DeviceType;\r
1730 for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {\r
1731 if (DeviceType[DeviceTypeIndex] == DevType) {\r
1732 break;\r
1733 }\r
1734 }\r
1735 if (DeviceTypeIndex < DeviceTypeCount) {\r
5c08e117 1736 //\r
1737 // We don't want to process twice for a device type\r
1738 //\r
1739 FreePool (BootOptionVar);\r
1740 continue;\r
1741 }\r
1742\r
22d1f978
RN
1743 DeviceType[DeviceTypeCount] = DevType;\r
1744 DeviceTypeCount++;\r
1745\r
5c08e117 1746 Status = BdsSetBootPriority4SameTypeDev (\r
22d1f978
RN
1747 DevType,\r
1748 (UINTN) -1,\r
5c08e117 1749 LocalBbsTable,\r
1750 &Priority\r
1751 );\r
1752 FreePool (BootOptionVar);\r
1753 if (EFI_ERROR (Status)) {\r
1754 break;\r
1755 }\r
1756 }\r
1757\r
1758 if (BootOrder != NULL) {\r
1759 FreePool (BootOrder);\r
1760 }\r
1761\r
1762 DEBUG_CODE_BEGIN();\r
d7d5db96 1763 PrintBbsTable (LocalBbsTable, BbsCount);\r
5c08e117 1764 DEBUG_CODE_END();\r
1765 \r
1766 return Status;\r
1767}\r