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