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