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