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