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