]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c
IntelFrameworkModulePkg: Clean up source files
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / LegacyBootManagerLib / LegacyBm.c
CommitLineData
9e3f171d
RN
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
0a6f4824 6Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
9e3f171d
RN
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "InternalLegacyBm.h"\r
18\r
19#define LEGACY_BM_BOOT_DESCRIPTION_LENGTH 32\r
20\r
21/**\r
22 Initialize legacy boot manager library by call EfiBootManagerRegisterLegacyBootSupport\r
23 function to export two function pointer.\r
24\r
25 @param ImageHandle The image handle.\r
26 @param SystemTable The system table.\r
27\r
28 @retval EFI_SUCCESS The legacy boot manager library is initialized correctly.\r
29 @return Other value if failed to initialize the legacy boot manager library.\r
30**/\r
31EFI_STATUS\r
32EFIAPI\r
33LegacyBootManagerLibConstructor (\r
34 IN EFI_HANDLE ImageHandle,\r
35 IN EFI_SYSTEM_TABLE *SystemTable\r
36)\r
37{\r
38 EfiBootManagerRegisterLegacyBootSupport (\r
39 LegacyBmRefreshAllBootOption,\r
40 LegacyBmBoot\r
41 );\r
42 return EFI_SUCCESS;\r
43}\r
44\r
45/**\r
46 Get the device type from the input legacy device path.\r
47\r
48 @param DevicePath The legacy device path.\r
49\r
50 @retval The legacy device type.\r
51**/\r
52UINT16\r
53LegacyBmDeviceType (\r
54 EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
55 )\r
56{\r
57 ASSERT ((DevicePathType (DevicePath) == BBS_DEVICE_PATH) &&\r
58 (DevicePathSubType (DevicePath) == BBS_BBS_DP));\r
59 return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType;\r
60}\r
61\r
62/**\r
63 Validate the BbsEntry base on the Boot Priority info in the BbsEntry.\r
64\r
65 @param BbsEntry The input bbs entry info.\r
66\r
67 @retval TRUE The BbsEntry is valid.\r
68 @retval FALSE The BbsEntry is invalid.\r
69**/\r
70BOOLEAN\r
71LegacyBmValidBbsEntry (\r
72 IN BBS_TABLE *BbsEntry\r
73 )\r
74{\r
75 switch (BbsEntry->BootPriority) {\r
76 case BBS_IGNORE_ENTRY:\r
77 case BBS_DO_NOT_BOOT_FROM:\r
78 case BBS_LOWEST_PRIORITY:\r
79 return FALSE;\r
80 default:\r
81 return TRUE;\r
82 }\r
83}\r
84\r
85/**\r
86 Build Legacy Device Name String according.\r
87\r
88 @param CurBBSEntry BBS Table.\r
89 @param Index Index.\r
90 @param BufSize The buffer size.\r
91 @param BootString The output string.\r
92\r
93**/\r
94VOID\r
95LegacyBmBuildLegacyDevNameString (\r
96 IN BBS_TABLE *CurBBSEntry,\r
97 IN UINTN Index,\r
98 IN UINTN BufSize,\r
99 OUT CHAR16 *BootString\r
100 )\r
101{\r
102 CHAR16 *Fmt;\r
103 CHAR16 *Type;\r
104 CHAR8 *StringDesc;\r
105 CHAR8 StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
106 CHAR16 StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
107\r
108 switch (Index) {\r
109 //\r
110 // Primary Master\r
111 //\r
112 case 1:\r
113 Fmt = L"Primary Master %s";\r
114 break;\r
115\r
116 //\r
117 // Primary Slave\r
118 //\r
119 case 2:\r
120 Fmt = L"Primary Slave %s";\r
121 break;\r
122\r
123 //\r
124 // Secondary Master\r
125 //\r
126 case 3:\r
127 Fmt = L"Secondary Master %s";\r
128 break;\r
129\r
130 //\r
131 // Secondary Slave\r
132 //\r
133 case 4:\r
134 Fmt = L"Secondary Slave %s";\r
135 break;\r
136\r
137 default:\r
138 Fmt = L"%s";\r
139 break;\r
140 }\r
141\r
142 switch (CurBBSEntry->DeviceType) {\r
143 case BBS_FLOPPY:\r
144 Type = L"Floppy";\r
145 break;\r
146\r
147 case BBS_HARDDISK:\r
148 Type = L"Harddisk";\r
149 break;\r
150\r
151 case BBS_CDROM:\r
152 Type = L"CDROM";\r
153 break;\r
154\r
155 case BBS_PCMCIA:\r
156 Type = L"PCMCIAe";\r
157 break;\r
158\r
159 case BBS_USB:\r
160 Type = L"USB";\r
161 break;\r
162\r
163 case BBS_EMBED_NETWORK:\r
164 Type = L"Network";\r
165 break;\r
166\r
167 case BBS_BEV_DEVICE:\r
168 Type = L"BEVe";\r
169 break;\r
170\r
171 case BBS_UNKNOWN:\r
172 default:\r
173 Type = L"Unknown";\r
174 break;\r
175 }\r
176 //\r
177 // If current BBS entry has its description then use it.\r
178 //\r
aa5f60ae 179 StringDesc = (CHAR8 *) (((UINTN) CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
9e3f171d
RN
180 if (NULL != StringDesc) {\r
181 //\r
182 // Only get fisrt 32 characters, this is suggested by BBS spec\r
183 //\r
184 CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH);\r
185 StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] = 0;\r
80901a24 186 AsciiStrToUnicodeStrS (StringBufferA, StringBufferU, ARRAY_SIZE (StringBufferU));\r
9e3f171d
RN
187 Fmt = L"%s";\r
188 Type = StringBufferU;\r
189 }\r
190\r
191 //\r
192 // BbsTable 16 entries are for onboard IDE.\r
193 // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11\r
194 //\r
195 if (Index >= 5 && Index <= 16 && (CurBBSEntry->DeviceType == BBS_HARDDISK || CurBBSEntry->DeviceType == BBS_CDROM)) {\r
196 Fmt = L"%s %d";\r
197 UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);\r
198 } else {\r
199 UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
200 }\r
201}\r
202\r
203/**\r
204 Get the Bbs index for the input boot option.\r
205\r
206 @param BootOption The input boot option info.\r
207 @param BbsTable The input Bbs table.\r
208 @param BbsCount The input total bbs entry number.\r
209 @param BbsIndexUsed The array shows how many BBS table indexs have been used.\r
210\r
211 @retval The index for the input boot option.\r
212**/\r
213UINT16\r
214LegacyBmFuzzyMatch (\r
215 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,\r
216 BBS_TABLE *BbsTable,\r
217 UINT16 BbsCount,\r
218 BOOLEAN *BbsIndexUsed\r
219 )\r
220{\r
221 UINT16 Index;\r
222 LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData;\r
223 CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
224\r
225 BbsData = (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData;\r
226\r
227 //\r
228 // Directly check the BBS index stored in BootOption\r
229 //\r
230 if ((BbsData->BbsIndex < BbsCount) &&\r
231 (LegacyBmDeviceType (BootOption->FilePath) == BbsTable[BbsData->BbsIndex].DeviceType)) {\r
232 LegacyBmBuildLegacyDevNameString (\r
233 &BbsTable[BbsData->BbsIndex],\r
234 BbsData->BbsIndex,\r
235 sizeof (Description),\r
236 Description\r
237 );\r
238 if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[BbsData->BbsIndex]) {\r
239 //\r
0a6f4824 240 // If devices with the same description string are connected,\r
9e3f171d
RN
241 // the BbsIndex of the first device is returned for the other device also.\r
242 // So, check if the BbsIndex is already being used, before assigning the BbsIndex.\r
243 //\r
244 BbsIndexUsed[BbsData->BbsIndex] = TRUE;\r
245 return BbsData->BbsIndex;\r
246 }\r
247 }\r
248\r
249 //\r
250 // BBS table could be changed (entry removed/moved)\r
251 // find the correct BBS index\r
252 //\r
253 for (Index = 0; Index < BbsCount; Index++) {\r
254 if (!LegacyBmValidBbsEntry (&BbsTable[Index]) ||\r
255 (BbsTable[Index].DeviceType != LegacyBmDeviceType (BootOption->FilePath))) {\r
256 continue;\r
257 }\r
258\r
259 LegacyBmBuildLegacyDevNameString (\r
260 &BbsTable[Index],\r
261 Index,\r
262 sizeof (Description),\r
263 Description\r
264 );\r
265 if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[Index]) {\r
266 //\r
0a6f4824 267 // If devices with the same description string are connected,\r
9e3f171d
RN
268 // the BbsIndex of the first device is assigned for the other device also.\r
269 // So, check if the BbsIndex is already being used, before assigning the corrected BbsIndex.\r
270 //\r
271 break;\r
272 }\r
273 }\r
274\r
275 //\r
276 // Add the corrected BbsIndex in the UsedBbsIndex Buffer\r
277 //\r
278 if (Index != BbsCount) {\r
279 BbsIndexUsed[Index] = TRUE;\r
280 }\r
281\r
282 return Index;\r
283}\r
284\r
285/**\r
286\r
287 Update legacy device order base on the input info.\r
288\r
289 @param LegacyDevOrder Legacy device order data buffer.\r
290 @param LegacyDevOrderSize Legacy device order data buffer size.\r
291 @param DeviceType Device type which need to check.\r
292 @param OldBbsIndex Old Bds Index.\r
293 @param NewBbsIndex New Bds Index, if it is -1,means remove this option.\r
294\r
295**/\r
296VOID\r
297LegacyBmUpdateBbsIndex (\r
298 LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder,\r
299 UINTN *LegacyDevOrderSize,\r
300 UINT16 DeviceType,\r
301 UINT16 OldBbsIndex,\r
302 UINT16 NewBbsIndex // Delete entry if -1\r
303 )\r
304{\r
305 LEGACY_DEV_ORDER_ENTRY *Entry;\r
306 UINTN Index;\r
307\r
308 ASSERT (((LegacyDevOrder == NULL) && (*LegacyDevOrderSize == 0)) ||\r
309 ((LegacyDevOrder != NULL) && (*LegacyDevOrderSize != 0))\r
310 );\r
311\r
0a6f4824 312 for (Entry = LegacyDevOrder;\r
9e3f171d
RN
313 Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *LegacyDevOrderSize);\r
314 Entry = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_TYPE) + Entry->Length)\r
315 ) {\r
316 if (Entry->BbsType == DeviceType) {\r
317 for (Index = 0; Index < Entry->Length / sizeof (UINT16) - 1; Index++) {\r
318 if (Entry->Data[Index] == OldBbsIndex) {\r
319 if (NewBbsIndex == (UINT16) -1) {\r
320 //\r
321 // Delete the old entry\r
322 //\r
323 CopyMem (\r
0a6f4824
LG
324 &Entry->Data[Index],\r
325 &Entry->Data[Index + 1],\r
9e3f171d
RN
326 (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &Entry->Data[Index + 1]\r
327 );\r
328 Entry->Length -= sizeof (UINT16);\r
329 *LegacyDevOrderSize -= sizeof(UINT16);\r
330 } else {\r
331 Entry->Data[Index] = NewBbsIndex;\r
332 }\r
333 break;\r
334 }\r
335 }\r
336 break;\r
337 }\r
338 }\r
339}\r
340\r
341/**\r
342 Delete all the legacy boot options.\r
343\r
344 @retval EFI_SUCCESS All legacy boot options are deleted.\r
345**/\r
346EFI_STATUS\r
347LegacyBmDeleteAllBootOptions (\r
348 VOID\r
349 )\r
350{\r
351 EFI_STATUS Status;\r
352 UINTN Index;\r
353 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
354 UINTN BootOptionCount;\r
355\r
356 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
357 for (Index = 0; Index < BootOptionCount; Index++) {\r
358 if ((DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&\r
359 (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)) {\r
360 Status = EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);\r
361 //\r
362 // Deleting variable with current variable implementation shouldn't fail.\r
363 //\r
364 ASSERT_EFI_ERROR (Status);\r
365 }\r
366 }\r
367\r
368 Status = gRT->SetVariable (\r
369 VAR_LEGACY_DEV_ORDER,\r
370 &gEfiLegacyDevOrderVariableGuid,\r
371 0,\r
372 0,\r
373 NULL\r
374 );\r
375 //\r
376 // Deleting variable with current variable implementation shouldn't fail.\r
377 //\r
378 ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);\r
379\r
380 return EFI_SUCCESS;\r
381}\r
382\r
383\r
384/**\r
385 Delete all the invalid legacy boot options.\r
386\r
387 @retval EFI_SUCCESS All invalide legacy boot options are deleted.\r
388 @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
389 @retval EFI_NOT_FOUND Fail to retrive variable of boot order.\r
390**/\r
391EFI_STATUS\r
392LegacyBmDeleteAllInvalidBootOptions (\r
393 VOID\r
394 )\r
395{\r
396 EFI_STATUS Status;\r
397 UINT16 HddCount;\r
398 UINT16 BbsCount;\r
399 HDD_INFO *HddInfo;\r
400 BBS_TABLE *BbsTable;\r
401 UINT16 BbsIndex;\r
402 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
403 UINTN Index;\r
404 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
405 UINTN BootOptionCount;\r
406 LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder;\r
407 UINTN LegacyDevOrderSize;\r
408 BOOLEAN *BbsIndexUsed;\r
409\r
410 HddCount = 0;\r
411 BbsCount = 0;\r
412 HddInfo = NULL;\r
413 BbsTable = NULL;\r
414\r
415 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
416 if (EFI_ERROR (Status)) {\r
417 return Status;\r
418 }\r
419\r
420 Status = LegacyBios->GetBbsInfo (\r
421 LegacyBios,\r
422 &HddCount,\r
423 &HddInfo,\r
424 &BbsCount,\r
425 &BbsTable\r
426 );\r
427 if (EFI_ERROR (Status)) {\r
428 return Status;\r
429 }\r
430\r
431 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &LegacyDevOrder, &LegacyDevOrderSize);\r
432\r
433 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
434\r
435 BbsIndexUsed = AllocateZeroPool (BbsCount * sizeof (BOOLEAN));\r
436 ASSERT (BbsIndexUsed != NULL);\r
437\r
438 for (Index = 0; Index < BootOptionCount; Index++) {\r
439 //\r
440 // Skip non legacy boot option\r
441 //\r
442 if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) ||\r
443 (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)) {\r
444 continue;\r
445 }\r
446\r
447 BbsIndex = LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCount, BbsIndexUsed);\r
448 if (BbsIndex == BbsCount) {\r
449 DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description));\r
450 //\r
451 // Delete entry from LegacyDevOrder\r
452 //\r
453 LegacyBmUpdateBbsIndex (\r
454 LegacyDevOrder,\r
455 &LegacyDevOrderSize,\r
456 LegacyBmDeviceType (BootOption[Index].FilePath),\r
457 ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,\r
458 (UINT16) -1\r
459 );\r
460 EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);\r
461 } else {\r
462 if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex != BbsIndex) {\r
463 DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s Bbs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description,\r
464 (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, (UINTN) BbsIndex));\r
465 //\r
466 // Update the BBS index in LegacyDevOrder\r
467 //\r
468 LegacyBmUpdateBbsIndex (\r
469 LegacyDevOrder,\r
470 &LegacyDevOrderSize,\r
471 LegacyBmDeviceType (BootOption[Index].FilePath),\r
472 ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,\r
473 BbsIndex\r
474 );\r
475\r
476 //\r
477 // Update the OptionalData in the Boot#### variable\r
478 //\r
479 ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex = BbsIndex;\r
480 EfiBootManagerLoadOptionToVariable (&BootOption[Index]);\r
481 }\r
482 }\r
483 }\r
484 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
485\r
486 if (LegacyDevOrder != NULL) {\r
487 Status = gRT->SetVariable (\r
488 VAR_LEGACY_DEV_ORDER,\r
489 &gEfiLegacyDevOrderVariableGuid,\r
490 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
491 LegacyDevOrderSize,\r
492 LegacyDevOrder\r
493 );\r
494 //\r
495 // Shrink variable with current variable implementation shouldn't fail.\r
496 //\r
497 ASSERT_EFI_ERROR (Status);\r
498\r
499 FreePool (LegacyDevOrder);\r
500 }\r
501 FreePool(BbsIndexUsed);\r
502 return Status;\r
503}\r
504\r
505/**\r
506 Create legacy boot option.\r
507\r
508 @param BootOption Ponter to the boot option which will be crated.\r
509 @param BbsEntry The input bbs entry info.\r
510 @param BbsIndex The BBS index.\r
511\r
512 @retval EFI_SUCCESS Create legacy boot option successfully.\r
513 @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
514\r
515**/\r
516EFI_STATUS\r
517LegacyBmCreateLegacyBootOption (\r
518 IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,\r
519 IN BBS_TABLE *BbsEntry,\r
520 IN UINT16 BbsIndex\r
521 )\r
522{\r
523 EFI_STATUS Status;\r
524 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
525 CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
526 CHAR8 HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
527 UINTN StringLen;\r
528 LEGACY_BM_BOOT_OPTION_BBS_DATA *OptionalData;\r
529 BBS_BBS_DEVICE_PATH *BbsNode;\r
530\r
531 if ((BootOption == NULL) || (BbsEntry == NULL)) {\r
532 return EFI_INVALID_PARAMETER;\r
533 }\r
0a6f4824 534\r
9e3f171d
RN
535 LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Description), Description);\r
536\r
537 //\r
538 // Create the BBS device path with description string\r
539 //\r
9b82facd 540 UnicodeStrToAsciiStrS (Description, HelpString, sizeof (HelpString));\r
9e3f171d
RN
541 StringLen = AsciiStrLen (HelpString);\r
542 DevicePath = AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + END_DEVICE_PATH_LENGTH);\r
543 ASSERT (DevicePath != NULL);\r
544\r
545 BbsNode = (BBS_BBS_DEVICE_PATH *) DevicePath;\r
546 SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
547 BbsNode->Header.Type = BBS_DEVICE_PATH;\r
548 BbsNode->Header.SubType = BBS_BBS_DP;\r
549 BbsNode->DeviceType = BbsEntry->DeviceType;\r
550 CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATUS_FLAGS));\r
551 CopyMem (BbsNode->String, HelpString, StringLen + 1);\r
552\r
553 SetDevicePathEndNode (NextDevicePathNode (BbsNode));\r
554\r
555 //\r
556 // Create the OptionalData\r
557 //\r
558 OptionalData = AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA));\r
559 ASSERT (OptionalData != NULL);\r
560 OptionalData->BbsIndex = BbsIndex;\r
561\r
562 //\r
563 // Create the BootOption\r
564 //\r
565 Status = EfiBootManagerInitializeLoadOption (\r
566 BootOption,\r
567 LoadOptionNumberUnassigned,\r
568 LoadOptionTypeBoot,\r
569 LOAD_OPTION_ACTIVE,\r
570 Description,\r
571 DevicePath,\r
572 (UINT8 *) OptionalData,\r
573 sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)\r
574 );\r
575 FreePool (DevicePath);\r
576 FreePool (OptionalData);\r
0a6f4824 577\r
9e3f171d
RN
578 return Status;\r
579}\r
580\r
581/**\r
582 Fill the device order buffer.\r
583\r
584 @param BbsTable The BBS table.\r
585 @param BbsType The BBS Type.\r
586 @param BbsCount The BBS Count.\r
587 @param Buf device order buffer.\r
588\r
589 @return The device order buffer.\r
590\r
591**/\r
592UINT16 *\r
593LegacyBmFillDevOrderBuf (\r
594 IN BBS_TABLE *BbsTable,\r
595 IN BBS_TYPE BbsType,\r
596 IN UINTN BbsCount,\r
597 OUT UINT16 *Buf\r
598 )\r
599{\r
600 UINTN Index;\r
601\r
602 for (Index = 0; Index < BbsCount; Index++) {\r
603 if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\r
604 continue;\r
605 }\r
606\r
607 if (BbsTable[Index].DeviceType != BbsType) {\r
608 continue;\r
609 }\r
610\r
611 *Buf = (UINT16) (Index & 0xFF);\r
612 Buf++;\r
613 }\r
614\r
615 return Buf;\r
616}\r
617\r
618/**\r
619 Create the device order buffer.\r
620\r
621 @param BbsTable The BBS table.\r
622 @param BbsCount The BBS Count.\r
623\r
0a6f4824 624 @retval EFI_SUCCES The buffer is created and the EFI variable named\r
9e3f171d
RN
625 VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is\r
626 set correctly.\r
627 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.\r
628 @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail\r
629 because of hardware error.\r
630**/\r
631EFI_STATUS\r
632LegacyBmCreateDevOrder (\r
633 IN BBS_TABLE *BbsTable,\r
634 IN UINT16 BbsCount\r
635 )\r
636{\r
637 UINTN Index;\r
638 UINTN FDCount;\r
639 UINTN HDCount;\r
640 UINTN CDCount;\r
641 UINTN NETCount;\r
642 UINTN BEVCount;\r
643 UINTN TotalSize;\r
644 UINTN HeaderSize;\r
645 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
646 LEGACY_DEV_ORDER_ENTRY *DevOrderPtr;\r
647 EFI_STATUS Status;\r
648\r
649 FDCount = 0;\r
650 HDCount = 0;\r
651 CDCount = 0;\r
652 NETCount = 0;\r
653 BEVCount = 0;\r
654 TotalSize = 0;\r
655 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
656 DevOrder = NULL;\r
657 Status = EFI_SUCCESS;\r
658\r
659 //\r
660 // Count all boot devices\r
661 //\r
662 for (Index = 0; Index < BbsCount; Index++) {\r
663 if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\r
664 continue;\r
665 }\r
666\r
667 switch (BbsTable[Index].DeviceType) {\r
668 case BBS_FLOPPY:\r
669 FDCount++;\r
670 break;\r
671\r
672 case BBS_HARDDISK:\r
673 HDCount++;\r
674 break;\r
675\r
676 case BBS_CDROM:\r
677 CDCount++;\r
678 break;\r
679\r
680 case BBS_EMBED_NETWORK:\r
681 NETCount++;\r
682 break;\r
683\r
684 case BBS_BEV_DEVICE:\r
685 BEVCount++;\r
686 break;\r
687\r
688 default:\r
689 break;\r
690 }\r
691 }\r
692\r
693 TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
694 TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
695 TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
696 TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
697 TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
698\r
699 //\r
700 // Create buffer to hold all boot device order\r
701 //\r
702 DevOrder = AllocateZeroPool (TotalSize);\r
703 if (NULL == DevOrder) {\r
704 return EFI_OUT_OF_RESOURCES;\r
705 }\r
706 DevOrderPtr = DevOrder;\r
707\r
708 DevOrderPtr->BbsType = BBS_FLOPPY;\r
709 DevOrderPtr->Length = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));\r
710 DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);\r
711\r
712 DevOrderPtr->BbsType = BBS_HARDDISK;\r
713 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
714 DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);\r
0a6f4824 715\r
9e3f171d
RN
716 DevOrderPtr->BbsType = BBS_CDROM;\r
717 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
718 DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);\r
0a6f4824 719\r
9e3f171d
RN
720 DevOrderPtr->BbsType = BBS_EMBED_NETWORK;\r
721 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
722 DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);\r
723\r
724 DevOrderPtr->BbsType = BBS_BEV_DEVICE;\r
725 DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
726 DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);\r
727\r
4ff5fd20 728 ASSERT (TotalSize == ((UINTN) DevOrderPtr - (UINTN) DevOrder));\r
9e3f171d
RN
729\r
730 //\r
731 // Save device order for legacy boot device to variable.\r
732 //\r
733 Status = gRT->SetVariable (\r
734 VAR_LEGACY_DEV_ORDER,\r
735 &gEfiLegacyDevOrderVariableGuid,\r
736 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
737 TotalSize,\r
738 DevOrder\r
739 );\r
740 FreePool (DevOrder);\r
741\r
742 return Status;\r
743}\r
744\r
745/**\r
0a6f4824 746 Add the legacy boot devices from BBS table into\r
9e3f171d
RN
747 the legacy device boot order.\r
748\r
749 @retval EFI_SUCCESS The boot devices are added successfully.\r
750 @retval EFI_NOT_FOUND The legacy boot devices are not found.\r
751 @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.\r
752 @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable\r
753 because of hardware error.\r
754**/\r
755EFI_STATUS\r
756LegacyBmUpdateDevOrder (\r
757 VOID\r
758 )\r
759{\r
760 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
761 LEGACY_DEV_ORDER_ENTRY *NewDevOrder;\r
762 LEGACY_DEV_ORDER_ENTRY *Ptr;\r
763 LEGACY_DEV_ORDER_ENTRY *NewPtr;\r
764 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
765 EFI_STATUS Status;\r
766 UINT16 HddCount;\r
767 UINT16 BbsCount;\r
768 HDD_INFO *LocalHddInfo;\r
769 BBS_TABLE *LocalBbsTable;\r
770 UINTN Index;\r
771 UINTN Index2;\r
772 UINTN *Idx;\r
773 UINTN FDCount;\r
774 UINTN HDCount;\r
775 UINTN CDCount;\r
776 UINTN NETCount;\r
777 UINTN BEVCount;\r
778 UINTN TotalSize;\r
779 UINTN HeaderSize;\r
780 UINT16 *NewFDPtr;\r
781 UINT16 *NewHDPtr;\r
782 UINT16 *NewCDPtr;\r
783 UINT16 *NewNETPtr;\r
784 UINT16 *NewBEVPtr;\r
785 UINT16 *NewDevPtr;\r
786 UINTN FDIndex;\r
787 UINTN HDIndex;\r
788 UINTN CDIndex;\r
789 UINTN NETIndex;\r
790 UINTN BEVIndex;\r
791\r
792 Idx = NULL;\r
793 FDCount = 0;\r
794 HDCount = 0;\r
795 CDCount = 0;\r
796 NETCount = 0;\r
797 BEVCount = 0;\r
798 TotalSize = 0;\r
799 HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
800 FDIndex = 0;\r
801 HDIndex = 0;\r
802 CDIndex = 0;\r
803 NETIndex = 0;\r
804 BEVIndex = 0;\r
805 NewDevPtr = NULL;\r
806\r
807 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
808 if (EFI_ERROR (Status)) {\r
809 return Status;\r
810 }\r
811\r
812 Status = LegacyBios->GetBbsInfo (\r
813 LegacyBios,\r
814 &HddCount,\r
815 &LocalHddInfo,\r
816 &BbsCount,\r
817 &LocalBbsTable\r
818 );\r
819 if (EFI_ERROR (Status)) {\r
820 return Status;\r
821 }\r
822\r
823 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, NULL);\r
824 if (NULL == DevOrder) {\r
825 return LegacyBmCreateDevOrder (LocalBbsTable, BbsCount);\r
826 }\r
827 //\r
828 // First we figure out how many boot devices with same device type respectively\r
829 //\r
830 for (Index = 0; Index < BbsCount; Index++) {\r
831 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
832 continue;\r
833 }\r
834\r
835 switch (LocalBbsTable[Index].DeviceType) {\r
836 case BBS_FLOPPY:\r
837 FDCount++;\r
838 break;\r
839\r
840 case BBS_HARDDISK:\r
841 HDCount++;\r
842 break;\r
843\r
844 case BBS_CDROM:\r
845 CDCount++;\r
846 break;\r
847\r
848 case BBS_EMBED_NETWORK:\r
849 NETCount++;\r
850 break;\r
851\r
852 case BBS_BEV_DEVICE:\r
853 BEVCount++;\r
854 break;\r
855\r
856 default:\r
857 break;\r
858 }\r
859 }\r
860\r
861 TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
862 TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
863 TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
864 TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
865 TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
866\r
867 NewDevOrder = AllocateZeroPool (TotalSize);\r
868 if (NULL == NewDevOrder) {\r
869 return EFI_OUT_OF_RESOURCES;\r
870 }\r
871\r
872 //\r
873 // copy FD\r
874 //\r
875 Ptr = DevOrder;\r
876 NewPtr = NewDevOrder;\r
877 NewPtr->BbsType = Ptr->BbsType;\r
878 NewPtr->Length = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
879 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
880 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
881 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY\r
882 ) {\r
883 continue;\r
884 }\r
885\r
886 NewPtr->Data[FDIndex] = Ptr->Data[Index];\r
887 FDIndex++;\r
888 }\r
889 NewFDPtr = NewPtr->Data;\r
890\r
891 //\r
892 // copy HD\r
893 //\r
894 Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
895 NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
896 NewPtr->BbsType = Ptr->BbsType;\r
897 NewPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
898 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
899 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
900 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK\r
901 ) {\r
902 continue;\r
903 }\r
904\r
905 NewPtr->Data[HDIndex] = Ptr->Data[Index];\r
906 HDIndex++;\r
907 }\r
908 NewHDPtr = NewPtr->Data;\r
909\r
910 //\r
911 // copy CD\r
912 //\r
913 Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
914 NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
915 NewPtr->BbsType = Ptr->BbsType;\r
916 NewPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
917 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
918 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
919 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM\r
920 ) {\r
921 continue;\r
922 }\r
923\r
924 NewPtr->Data[CDIndex] = Ptr->Data[Index];\r
925 CDIndex++;\r
926 }\r
927 NewCDPtr = NewPtr->Data;\r
928\r
929 //\r
930 // copy NET\r
931 //\r
932 Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
933 NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
934 NewPtr->BbsType = Ptr->BbsType;\r
935 NewPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
936 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
937 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
938 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK\r
939 ) {\r
940 continue;\r
941 }\r
942\r
943 NewPtr->Data[NETIndex] = Ptr->Data[Index];\r
944 NETIndex++;\r
945 }\r
946 NewNETPtr = NewPtr->Data;\r
0a6f4824 947\r
9e3f171d
RN
948 //\r
949 // copy BEV\r
950 //\r
951 Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
952 NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
953 NewPtr->BbsType = Ptr->BbsType;\r
954 NewPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
955 for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
956 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
957 LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE\r
958 ) {\r
959 continue;\r
960 }\r
961\r
962 NewPtr->Data[BEVIndex] = Ptr->Data[Index];\r
963 BEVIndex++;\r
964 }\r
965 NewBEVPtr = NewPtr->Data;\r
966\r
967 for (Index = 0; Index < BbsCount; Index++) {\r
968 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
969 continue;\r
970 }\r
971\r
972 switch (LocalBbsTable[Index].DeviceType) {\r
973 case BBS_FLOPPY:\r
974 Idx = &FDIndex;\r
975 NewDevPtr = NewFDPtr;\r
976 break;\r
977\r
978 case BBS_HARDDISK:\r
979 Idx = &HDIndex;\r
980 NewDevPtr = NewHDPtr;\r
981 break;\r
982\r
983 case BBS_CDROM:\r
984 Idx = &CDIndex;\r
985 NewDevPtr = NewCDPtr;\r
986 break;\r
987\r
988 case BBS_EMBED_NETWORK:\r
989 Idx = &NETIndex;\r
990 NewDevPtr = NewNETPtr;\r
991 break;\r
992\r
993 case BBS_BEV_DEVICE:\r
994 Idx = &BEVIndex;\r
995 NewDevPtr = NewBEVPtr;\r
996 break;\r
997\r
998 default:\r
999 Idx = NULL;\r
1000 break;\r
1001 }\r
1002 //\r
1003 // at this point we have copied those valid indexes to new buffer\r
1004 // and we should check if there is any new appeared boot device\r
1005 //\r
1006 if (Idx != NULL) {\r
1007 for (Index2 = 0; Index2 < *Idx; Index2++) {\r
1008 if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
1009 break;\r
1010 }\r
1011 }\r
1012\r
1013 if (Index2 == *Idx) {\r
1014 //\r
1015 // Index2 == *Idx means we didn't find Index\r
1016 // so Index is a new appeared device's index in BBS table\r
1017 // insert it before disabled indexes.\r
1018 //\r
1019 for (Index2 = 0; Index2 < *Idx; Index2++) {\r
1020 if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {\r
1021 break;\r
1022 }\r
1023 }\r
1024 CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));\r
1025 NewDevPtr[Index2] = (UINT16) (Index & 0xFF);\r
1026 (*Idx)++;\r
1027 }\r
1028 }\r
1029 }\r
1030\r
1031 FreePool (DevOrder);\r
1032\r
1033 Status = gRT->SetVariable (\r
1034 VAR_LEGACY_DEV_ORDER,\r
1035 &gEfiLegacyDevOrderVariableGuid,\r
1036 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1037 TotalSize,\r
1038 NewDevOrder\r
1039 );\r
1040 FreePool (NewDevOrder);\r
1041\r
1042 return Status;\r
1043}\r
1044\r
1045/**\r
1046 Set Boot Priority for specified device type.\r
1047\r
1048 @param DeviceType The device type.\r
1049 @param BbsIndex The BBS index to set the highest priority. Ignore when -1.\r
1050 @param LocalBbsTable The BBS table.\r
1051 @param Priority The prority table.\r
1052\r
1053 @retval EFI_SUCCESS The function completes successfully.\r
1054 @retval EFI_NOT_FOUND Failed to find device.\r
1055 @retval EFI_OUT_OF_RESOURCES Failed to get the efi variable of device order.\r
1056\r
1057**/\r
1058EFI_STATUS\r
1059LegacyBmSetPriorityForSameTypeDev (\r
1060 IN UINT16 DeviceType,\r
1061 IN UINTN BbsIndex,\r
1062 IN OUT BBS_TABLE *LocalBbsTable,\r
1063 IN OUT UINT16 *Priority\r
1064 )\r
1065{\r
1066 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
1067 LEGACY_DEV_ORDER_ENTRY *DevOrderPtr;\r
1068 UINTN DevOrderSize;\r
1069 UINTN Index;\r
1070\r
1071 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, &DevOrderSize);\r
1072 if (NULL == DevOrder) {\r
1073 return EFI_OUT_OF_RESOURCES;\r
1074 }\r
1075\r
1076 DevOrderPtr = DevOrder;\r
1077 while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) {\r
1078 if (DevOrderPtr->BbsType == DeviceType) {\r
1079 break;\r
1080 }\r
1081\r
1082 DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length);\r
1083 }\r
1084\r
1085 if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) {\r
1086 FreePool (DevOrder);\r
1087 return EFI_NOT_FOUND;\r
1088 }\r
1089\r
1090 if (BbsIndex != (UINTN) -1) {\r
1091 //\r
1092 // In case the BBS entry isn't valid because devices were plugged or removed.\r
1093 //\r
1094 if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTable[BbsIndex].DeviceType != DeviceType)) {\r
1095 FreePool (DevOrder);\r
1096 return EFI_NOT_FOUND;\r
1097 }\r
1098 LocalBbsTable[BbsIndex].BootPriority = *Priority;\r
1099 (*Priority)++;\r
1100 }\r
1101 //\r
1102 // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
1103 //\r
1104 for (Index = 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) {\r
1105 if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) {\r
1106 //\r
1107 // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
1108 //\r
1109 } else if (DevOrderPtr->Data[Index] != BbsIndex) {\r
1110 LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority;\r
1111 (*Priority)++;\r
1112 }\r
1113 }\r
1114\r
1115 FreePool (DevOrder);\r
1116 return EFI_SUCCESS;\r
1117}\r
1118\r
1119/**\r
1120 Print the BBS Table.\r
1121\r
1122 @param LocalBbsTable The BBS table.\r
1123 @param BbsCount The count of entry in BBS table.\r
1124**/\r
1125VOID\r
1126LegacyBmPrintBbsTable (\r
1127 IN BBS_TABLE *LocalBbsTable,\r
1128 IN UINT16 BbsCount\r
1129 )\r
1130{\r
1131 UINT16 Index;\r
1132\r
1133 DEBUG ((DEBUG_INFO, "\n"));\r
1134 DEBUG ((DEBUG_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
1135 DEBUG ((DEBUG_INFO, "=============================================\n"));\r
1136 for (Index = 0; Index < BbsCount; Index++) {\r
1137 if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
1138 continue;\r
1139 }\r
1140\r
1141 DEBUG (\r
1142 (DEBUG_INFO,\r
1143 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
1144 (UINTN) Index,\r
1145 (UINTN) LocalBbsTable[Index].BootPriority,\r
1146 (UINTN) LocalBbsTable[Index].Bus,\r
1147 (UINTN) LocalBbsTable[Index].Device,\r
1148 (UINTN) LocalBbsTable[Index].Function,\r
1149 (UINTN) LocalBbsTable[Index].Class,\r
1150 (UINTN) LocalBbsTable[Index].SubClass,\r
1151 (UINTN) LocalBbsTable[Index].DeviceType,\r
1152 (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags,\r
1153 (UINTN) LocalBbsTable[Index].BootHandlerSegment,\r
1154 (UINTN) LocalBbsTable[Index].BootHandlerOffset,\r
1155 (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset),\r
1156 (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset))\r
1157 );\r
1158 }\r
1159\r
1160 DEBUG ((DEBUG_INFO, "\n"));\r
1161}\r
1162\r
1163/**\r
1164 Set the boot priority for BBS entries based on boot option entry and boot order.\r
1165\r
1166 @param BootOption The boot option is to be checked for refresh BBS table.\r
0a6f4824 1167\r
9e3f171d
RN
1168 @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.\r
1169 @retval EFI_NOT_FOUND BBS entries can't be found.\r
1170 @retval EFI_OUT_OF_RESOURCES Failed to get the legacy device boot order.\r
1171**/\r
1172EFI_STATUS\r
1173LegacyBmRefreshBbsTableForBoot (\r
1174 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\r
1175 )\r
1176{\r
1177 EFI_STATUS Status;\r
1178 UINT16 BbsIndex;\r
1179 UINT16 HddCount;\r
1180 UINT16 BbsCount;\r
1181 HDD_INFO *LocalHddInfo;\r
1182 BBS_TABLE *LocalBbsTable;\r
1183 UINT16 DevType;\r
1184 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1185 UINTN Index;\r
1186 UINT16 Priority;\r
1187 UINT16 *DeviceType;\r
1188 UINTN DeviceTypeCount;\r
1189 UINTN DeviceTypeIndex;\r
1190 EFI_BOOT_MANAGER_LOAD_OPTION *Option;\r
1191 UINTN OptionCount;\r
1192\r
1193 HddCount = 0;\r
1194 BbsCount = 0;\r
1195 LocalHddInfo = NULL;\r
1196 LocalBbsTable = NULL;\r
1197 DevType = BBS_UNKNOWN;\r
1198\r
1199 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
1200 if (EFI_ERROR (Status)) {\r
1201 return Status;\r
1202 }\r
1203\r
1204 Status = LegacyBios->GetBbsInfo (\r
1205 LegacyBios,\r
1206 &HddCount,\r
1207 &LocalHddInfo,\r
1208 &BbsCount,\r
1209 &LocalBbsTable\r
1210 );\r
1211 if (EFI_ERROR (Status)) {\r
1212 return Status;\r
1213 }\r
1214\r
1215 //\r
1216 // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
1217 // We will set them according to the settings setup by user\r
1218 //\r
1219 for (Index = 0; Index < BbsCount; Index++) {\r
1220 if (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
1221 LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
1222 }\r
1223 }\r
1224 //\r
1225 // boot priority always starts at 0\r
1226 //\r
0a6f4824 1227 Priority = 0;\r
9e3f171d
RN
1228 if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) &&\r
1229 (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {\r
1230 //\r
1231 // If BootOption stands for a legacy boot option, we prioritize the devices with the same type first.\r
1232 //\r
1233 DevType = LegacyBmDeviceType (BootOption->FilePath);\r
1234 BbsIndex = ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData)->BbsIndex;\r
1235 Status = LegacyBmSetPriorityForSameTypeDev (\r
1236 DevType,\r
1237 BbsIndex,\r
1238 LocalBbsTable,\r
1239 &Priority\r
1240 );\r
1241 if (EFI_ERROR (Status)) {\r
1242 return Status;\r
1243 }\r
1244 }\r
1245 //\r
1246 // we have to set the boot priority for other BBS entries with different device types\r
1247 //\r
1248 Option = EfiBootManagerGetLoadOptions (&OptionCount, LoadOptionTypeBoot);\r
1249 DeviceType = AllocatePool (sizeof (UINT16) * OptionCount);\r
1250 ASSERT (DeviceType != NULL);\r
1251 DeviceType[0] = DevType;\r
1252 DeviceTypeCount = 1;\r
1253 for (Index = 0; Index < OptionCount; Index++) {\r
1254 if ((DevicePathType (Option[Index].FilePath) != BBS_DEVICE_PATH) ||\r
1255 (DevicePathSubType (Option[Index].FilePath) != BBS_BBS_DP)) {\r
1256 continue;\r
1257 }\r
0a6f4824 1258\r
9e3f171d
RN
1259 DevType = LegacyBmDeviceType (Option[Index].FilePath);\r
1260 for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {\r
1261 if (DeviceType[DeviceTypeIndex] == DevType) {\r
1262 break;\r
1263 }\r
1264 }\r
1265 if (DeviceTypeIndex < DeviceTypeCount) {\r
1266 //\r
1267 // We don't want to process twice for a device type\r
1268 //\r
1269 continue;\r
1270 }\r
1271\r
1272 DeviceType[DeviceTypeCount] = DevType;\r
1273 DeviceTypeCount++;\r
1274\r
1275 Status = LegacyBmSetPriorityForSameTypeDev (\r
1276 DevType,\r
1277 (UINTN) -1,\r
1278 LocalBbsTable,\r
1279 &Priority\r
1280 );\r
1281 }\r
1282 EfiBootManagerFreeLoadOptions (Option, OptionCount);\r
1283\r
1284 DEBUG_CODE_BEGIN();\r
1285 LegacyBmPrintBbsTable (LocalBbsTable, BbsCount);\r
1286 DEBUG_CODE_END();\r
0a6f4824 1287\r
9e3f171d
RN
1288 return Status;\r
1289}\r
1290\r
1291\r
1292/**\r
1293 Boot the legacy system with the boot option.\r
1294\r
1295 @param BootOption The legacy boot option which have BBS device path\r
1296 On return, BootOption->Status contains the boot status.\r
1297 EFI_UNSUPPORTED There is no legacybios protocol, do not support\r
1298 legacy boot.\r
1299 EFI_STATUS The status of LegacyBios->LegacyBoot ().\r
1300**/\r
1301VOID\r
1302EFIAPI\r
1303LegacyBmBoot (\r
1304 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\r
1305 )\r
1306{\r
1307 EFI_STATUS Status;\r
1308 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1309\r
1310 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
1311 if (EFI_ERROR (Status)) {\r
1312 //\r
1313 // If no LegacyBios protocol we do not support legacy boot\r
1314 //\r
1315 BootOption->Status = EFI_UNSUPPORTED;\r
1316 return;\r
1317 }\r
1318 //\r
1319 // Notes: if we separate the int 19, then we don't need to refresh BBS\r
1320 //\r
1321 Status = LegacyBmRefreshBbsTableForBoot (BootOption);\r
1322 if (EFI_ERROR (Status)) {\r
1323 BootOption->Status = Status;\r
1324 return;\r
1325 }\r
1326\r
1327 BootOption->Status = LegacyBios->LegacyBoot (\r
1328 LegacyBios,\r
1329 (BBS_BBS_DEVICE_PATH *) BootOption->FilePath,\r
1330 BootOption->OptionalDataSize,\r
1331 BootOption->OptionalData\r
1332 );\r
1333}\r
1334\r
1335/**\r
1336 This function enumerates all the legacy boot options.\r
1337\r
1338 @param BootOptionCount Return the legacy boot option count.\r
1339\r
1340 @retval Pointer to the legacy boot option buffer.\r
1341**/\r
1342EFI_BOOT_MANAGER_LOAD_OPTION *\r
1343LegacyBmEnumerateAllBootOptions (\r
1344 UINTN *BootOptionCount\r
1345 )\r
1346{\r
1347 EFI_STATUS Status;\r
1348 UINT16 HddCount;\r
1349 UINT16 BbsCount;\r
1350 HDD_INFO *HddInfo;\r
1351 BBS_TABLE *BbsTable;\r
1352 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1353 UINT16 Index;\r
1354 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
1355\r
1356 ASSERT (BootOptionCount != NULL);\r
1357\r
1358 BootOptions = NULL;\r
1359 *BootOptionCount = 0;\r
1360 BbsCount = 0;\r
1361\r
1362 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
1363 if (EFI_ERROR (Status)) {\r
1364 return NULL;\r
1365 }\r
1366\r
1367 Status = LegacyBios->GetBbsInfo (\r
1368 LegacyBios,\r
1369 &HddCount,\r
1370 &HddInfo,\r
1371 &BbsCount,\r
1372 &BbsTable\r
1373 );\r
1374 if (EFI_ERROR (Status)) {\r
1375 return NULL;\r
1376 }\r
1377\r
1378 for (Index = 0; Index < BbsCount; Index++) {\r
1379 if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\r
1380 continue;\r
1381 }\r
1382\r
1383 BootOptions = ReallocatePool (\r
1384 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
1385 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
1386 BootOptions\r
1387 );\r
1388 ASSERT (BootOptions != NULL);\r
1389\r
1390 Status = LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCount)++], &BbsTable[Index], Index);\r
1391 ASSERT_EFI_ERROR (Status);\r
1392 }\r
1393\r
1394 return BootOptions;\r
1395}\r
1396\r
1397/**\r
1398 Return the index of the boot option in the boot option array.\r
1399\r
1400 The function compares the Description, FilePath, OptionalData.\r
1401\r
1402 @param Key The input boot option which is compared with.\r
1403 @param Array The input boot option array.\r
1404 @param Count The count of the input boot options.\r
1405\r
1406 @retval The index of the input boot option in the array.\r
1407\r
1408**/\r
1409INTN\r
1410LegacyBmFindBootOption (\r
1411 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,\r
1412 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,\r
1413 IN UINTN Count\r
1414 )\r
1415{\r
1416 UINTN Index;\r
1417\r
1418 for (Index = 0; Index < Count; Index++) {\r
1419 if ((StrCmp (Key->Description, Array[Index].Description) == 0) &&\r
1420 (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&\r
1421 (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&\r
1422 (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {\r
1423 return (INTN) Index;\r
1424 }\r
1425 }\r
1426\r
1427 return -1;\r
1428}\r
1429\r
1430/**\r
1431 Refresh all legacy boot options.\r
1432\r
1433**/\r
1434VOID\r
1435EFIAPI\r
1436LegacyBmRefreshAllBootOption (\r
1437 VOID\r
1438 )\r
1439{\r
1440 EFI_STATUS Status;\r
1441 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1442 UINTN RootBridgeHandleCount;\r
1443 EFI_HANDLE *RootBridgeHandleBuffer;\r
1444 UINTN HandleCount;\r
1445 EFI_HANDLE *HandleBuffer;\r
1446 UINTN RootBridgeIndex;\r
1447 UINTN Index;\r
1448 UINTN Flags;\r
1449 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
1450 UINTN BootOptionCount;\r
1451 EFI_BOOT_MANAGER_LOAD_OPTION *ExistingBootOptions;\r
1452 UINTN ExistingBootOptionCount;\r
1453\r
1454 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
1455 if (EFI_ERROR (Status)) {\r
1456 LegacyBmDeleteAllBootOptions ();\r
1457 return;\r
1458 }\r
1459 PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0);\r
1460\r
1461 //\r
0a6f4824 1462 // Before enumerating the legacy boot option, we need to dispatch all the legacy option roms\r
9e3f171d
RN
1463 // to ensure the GetBbsInfo() counts all the legacy devices.\r
1464 //\r
1465 gBS->LocateHandleBuffer (\r
1466 ByProtocol,\r
1467 &gEfiPciRootBridgeIoProtocolGuid,\r
1468 NULL,\r
1469 &RootBridgeHandleCount,\r
1470 &RootBridgeHandleBuffer\r
1471 );\r
1472 for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {\r
1473 gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);\r
1474 gBS->LocateHandleBuffer (\r
1475 ByProtocol,\r
1476 &gEfiPciIoProtocolGuid,\r
1477 NULL,\r
1478 &HandleCount,\r
1479 &HandleBuffer\r
1480 );\r
1481 for (Index = 0; Index < HandleCount; Index++) {\r
1482 //\r
1483 // Start the thunk driver so that the legacy option rom gets dispatched.\r
0a6f4824 1484 // Note: We don't directly call InstallPciRom because some thunk drivers\r
9e3f171d
RN
1485 // (e.g. BlockIo thunk driver) depend on the immediate result after dispatching\r
1486 //\r
1487 Status = LegacyBios->CheckPciRom (\r
1488 LegacyBios,\r
1489 HandleBuffer[Index],\r
1490 NULL,\r
1491 NULL,\r
1492 &Flags\r
1493 );\r
1494 if (!EFI_ERROR (Status)) {\r
1495 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);\r
1496 }\r
1497 }\r
1498 }\r
1499\r
1500 //\r
1501 // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption\r
1502 // Firstly delete the invalid legacy boot options,\r
1503 // then enumreate and save the newly appeared legacy boot options\r
1504 // the last step is legacy boot option special action to refresh the LegacyDevOrder variable\r
1505 //\r
1506 LegacyBmDeleteAllInvalidBootOptions ();\r
1507\r
1508 ExistingBootOptions = EfiBootManagerGetLoadOptions (&ExistingBootOptionCount, LoadOptionTypeBoot);\r
1509 BootOptions = LegacyBmEnumerateAllBootOptions (&BootOptionCount);\r
1510\r
1511 for (Index = 0; Index < BootOptionCount; Index++) {\r
1512 if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, ExistingBootOptionCount) == -1) {\r
1513 Status = EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
1514 DEBUG ((\r
1515 EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r\n",\r
1516 (UINTN) BootOptions[Index].OptionNumber,\r
1517 (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].OptionalData)->BbsIndex,\r
1518 BootOptions[Index].Description,\r
1519 Status\r
1520 ));\r
1521 //\r
1522 // Continue upon failure to add boot option.\r
1523 //\r
1524 }\r
1525 }\r
1526\r
1527 EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCount);\r
1528 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
1529\r
1530 //\r
1531 // Failure to create LegacyDevOrder variable only impacts the boot order.\r
1532 //\r
1533 LegacyBmUpdateDevOrder ();\r
1534\r
1535 PERF_END (NULL, "LegacyBootOptionEnum", "BDS", 0);\r
1536}\r