EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c

Go to the documentation of this file.
00001 
00017 #include "BBSsupport.h"
00018 
00019 BOOT_OPTION_BBS_MAPPING  *mBootOptionBbsMapping     = NULL;
00020 UINTN                    mBootOptionBbsMappingCount = 0;
00021 
00035 VOID
00036 AsciiToUnicodeSize (
00037   IN UINT8              *AStr,
00038   IN UINTN              Size,
00039   OUT UINT16            *UStr
00040   )
00041 {
00042   UINTN Idx;
00043 
00044   Idx = 0;
00045   while (AStr[Idx] != 0) {
00046     UStr[Idx] = (CHAR16) AStr[Idx];
00047     if (Idx == Size) {
00048       break;
00049     }
00050 
00051     Idx++;
00052   }
00053   UStr[Idx] = 0;
00054 }
00055 
00065 VOID
00066 BdsBuildLegacyDevNameString (
00067   IN  BBS_TABLE                 *CurBBSEntry,
00068   IN  UINTN                     Index,
00069   IN  UINTN                     BufSize,
00070   OUT CHAR16                    *BootString
00071   )
00072 {
00073   CHAR16  *Fmt;
00074   CHAR16  *Type;
00075   UINT8   *StringDesc;
00076   CHAR16  Temp[80];
00077 
00078   switch (Index) {
00079   //
00080   // Primary Master
00081   //
00082   case 1:
00083     Fmt = L"Primary Master %s";
00084     break;
00085 
00086  //
00087  // Primary Slave
00088  //
00089   case 2:
00090     Fmt = L"Primary Slave %s";
00091     break;
00092 
00093   //
00094   // Secondary Master
00095   //
00096   case 3:
00097     Fmt = L"Secondary Master %s";
00098     break;
00099 
00100   //
00101   // Secondary Slave
00102   //
00103   case 4:
00104     Fmt = L"Secondary Slave %s";
00105     break;
00106 
00107   default:
00108     Fmt = L"%s";
00109     break;
00110   }
00111 
00112   switch (CurBBSEntry->DeviceType) {
00113   case BBS_FLOPPY:
00114     Type = L"Floppy";
00115     break;
00116 
00117   case BBS_HARDDISK:
00118     Type = L"Harddisk";
00119     break;
00120 
00121   case BBS_CDROM:
00122     Type = L"CDROM";
00123     break;
00124 
00125   case BBS_PCMCIA:
00126     Type = L"PCMCIAe";
00127     break;
00128 
00129   case BBS_USB:
00130     Type = L"USB";
00131     break;
00132 
00133   case BBS_EMBED_NETWORK:
00134     Type = L"Network";
00135     break;
00136 
00137   case BBS_BEV_DEVICE:
00138     Type = L"BEVe";
00139     break;
00140 
00141   case BBS_UNKNOWN:
00142   default:
00143     Type = L"Unknown";
00144     break;
00145   }
00146   //
00147   // If current BBS entry has its description then use it.
00148   //
00149   StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);
00150   if (NULL != StringDesc) {
00151     //
00152     // Only get fisrt 32 characters, this is suggested by BBS spec
00153     //
00154     AsciiToUnicodeSize (StringDesc, 32, Temp);
00155     Fmt   = L"%s";
00156     Type  = Temp;
00157   }
00158 
00159   //
00160   // BbsTable 16 entries are for onboard IDE.
00161   // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
00162   //
00163   if (Index >= 5 && Index <= 16 && (CurBBSEntry->DeviceType == BBS_HARDDISK || CurBBSEntry->DeviceType == BBS_CDROM)) {
00164     Fmt = L"%s %d";
00165     UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);
00166   } else {
00167     UnicodeSPrint (BootString, BufSize, Fmt, Type);
00168   }
00169 }
00170 
00192 EFI_STATUS
00193 BdsCreateLegacyBootOption (
00194   IN BBS_TABLE                        *CurrentBbsEntry,
00195   IN EFI_DEVICE_PATH_PROTOCOL         *CurrentBbsDevPath,
00196   IN UINTN                            Index,
00197   IN OUT UINT16                       **BootOrderList,
00198   IN OUT UINTN                        *BootOrderListSize
00199   )
00200 {
00201   EFI_STATUS           Status;
00202   UINT16               CurrentBootOptionNo;
00203   UINT16               BootString[10];
00204   CHAR16               BootDesc[100];
00205   CHAR8                HelpString[100];
00206   UINT16               *NewBootOrderList;
00207   UINTN                BufferSize;
00208   UINTN                StringLen;
00209   VOID                 *Buffer;
00210   UINT8                *Ptr;
00211   UINT16               CurrentBbsDevPathSize;
00212   UINTN                BootOrderIndex;
00213   UINTN                BootOrderLastIndex;
00214   UINTN                ArrayIndex;
00215   BOOLEAN              IndexNotFound;
00216   BBS_BBS_DEVICE_PATH  *NewBbsDevPathNode;
00217 
00218   if ((*BootOrderList) == NULL) {
00219     CurrentBootOptionNo = 0;
00220   } else {
00221     for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {
00222       IndexNotFound = TRUE;
00223       for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {
00224         if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {
00225           IndexNotFound = FALSE;
00226           break;
00227         }
00228       }
00229 
00230       if (!IndexNotFound) {
00231         continue;
00232       } else {
00233         break;
00234       }
00235     }
00236 
00237     CurrentBootOptionNo = (UINT16) ArrayIndex;
00238   }
00239 
00240   UnicodeSPrint (
00241     BootString,
00242     sizeof (BootString),
00243     L"Boot%04x",
00244     CurrentBootOptionNo
00245     );
00246 
00247   BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);
00248 
00249   //
00250   // Create new BBS device path node with description string
00251   //
00252   UnicodeStrToAsciiStr (BootDesc, HelpString);
00253 
00254   StringLen = AsciiStrLen (HelpString);
00255   NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
00256   if (NewBbsDevPathNode == NULL) {
00257     return EFI_OUT_OF_RESOURCES;
00258   }
00259   CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));
00260   CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);
00261   SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
00262 
00263   //
00264   // Create entire new CurrentBbsDevPath with end node
00265   //
00266   CurrentBbsDevPath = AppendDevicePathNode (
00267                         EndDevicePath,
00268                         (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode
00269                         );
00270    if (CurrentBbsDevPath == NULL) {
00271     FreePool (NewBbsDevPathNode);
00272     return EFI_OUT_OF_RESOURCES;
00273   }
00274 
00275   CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));
00276 
00277   BufferSize = sizeof (UINT32) +
00278     sizeof (UINT16) +
00279     StrSize (BootDesc) +
00280     CurrentBbsDevPathSize +
00281     sizeof (BBS_TABLE) +
00282     sizeof (UINT16);
00283 
00284   Buffer = AllocateZeroPool (BufferSize);
00285   if (Buffer == NULL) {
00286     FreePool (NewBbsDevPathNode);
00287     FreePool (CurrentBbsDevPath);
00288     return EFI_OUT_OF_RESOURCES;
00289   }
00290 
00291   Ptr               = (UINT8 *) Buffer;
00292 
00293   *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
00294   Ptr += sizeof (UINT32);
00295 
00296   *((UINT16 *) Ptr) = CurrentBbsDevPathSize;
00297   Ptr += sizeof (UINT16);
00298 
00299   CopyMem (
00300     Ptr,
00301     BootDesc,
00302     StrSize (BootDesc)
00303     );
00304   Ptr += StrSize (BootDesc);
00305 
00306   CopyMem (
00307     Ptr,
00308     CurrentBbsDevPath,
00309     CurrentBbsDevPathSize
00310     );
00311   Ptr += CurrentBbsDevPathSize;
00312 
00313   CopyMem (
00314     Ptr,
00315     CurrentBbsEntry,
00316     sizeof (BBS_TABLE)
00317     );
00318 
00319   Ptr += sizeof (BBS_TABLE);
00320   *((UINT16 *) Ptr) = (UINT16) Index;
00321 
00322   Status = gRT->SetVariable (
00323                   BootString,
00324                   &gEfiGlobalVariableGuid,
00325                   VAR_FLAG,
00326                   BufferSize,
00327                   Buffer
00328                   );
00329 
00330   FreePool (Buffer);
00331   
00332   Buffer = NULL;
00333 
00334   NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));
00335   if (NULL == NewBootOrderList) {
00336     FreePool (NewBbsDevPathNode);
00337     FreePool (CurrentBbsDevPath);
00338     return EFI_OUT_OF_RESOURCES;
00339   }
00340 
00341   if (*BootOrderList != NULL) {
00342     CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);
00343     FreePool (*BootOrderList);
00344   }
00345 
00346   BootOrderLastIndex                    = (UINTN) (*BootOrderListSize / sizeof (UINT16));
00347   NewBootOrderList[BootOrderLastIndex]  = CurrentBootOptionNo;
00348   *BootOrderListSize += sizeof (UINT16);
00349   *BootOrderList = NewBootOrderList;
00350 
00351   FreePool (NewBbsDevPathNode);
00352   FreePool (CurrentBbsDevPath);
00353   return Status;
00354 }
00355 
00367 BOOLEAN
00368 BdsIsLegacyBootOption (
00369   IN UINT8                 *BootOptionVar,
00370   OUT BBS_TABLE            **BbsEntry,
00371   OUT UINT16               *BbsIndex
00372   )
00373 {
00374   UINT8                     *Ptr;
00375   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
00376   BOOLEAN                   Ret;
00377   UINT16                    DevPathLen;
00378 
00379   Ptr = BootOptionVar;
00380   Ptr += sizeof (UINT32);
00381   DevPathLen = *(UINT16 *) Ptr;
00382   Ptr += sizeof (UINT16);
00383   Ptr += StrSize ((UINT16 *) Ptr);
00384   DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
00385   if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
00386     Ptr += DevPathLen;
00387     *BbsEntry = (BBS_TABLE *) Ptr;
00388     Ptr += sizeof (BBS_TABLE);
00389     *BbsIndex = *(UINT16 *) Ptr;
00390     Ret       = TRUE;
00391   } else {
00392     *BbsEntry = NULL;
00393     Ret       = FALSE;
00394   }
00395 
00396   return Ret;
00397 }
00398 
00415 VOID
00416 OrderLegacyBootOption4SameType (
00417   UINT16                   *BootOption,
00418   UINTN                    BootOptionCount,
00419   UINT16                   *DevOrder,
00420   UINTN                    DevOrderCount,
00421   UINT16                   *EnBootOption,
00422   UINTN                    *EnBootOptionCount,
00423   UINT16                   *DisBootOption,
00424   UINTN                    *DisBootOptionCount
00425   )
00426 {
00427   UINTN                    Index;
00428   UINTN                    MappingIndex;
00429   UINT16                   *NewBootOption;
00430   UINT16                   BbsType;
00431   
00432   *DisBootOptionCount = 0;
00433   *EnBootOptionCount  = 0;
00434   BbsType             = 0;
00435 
00436   //
00437   // Record the corresponding Boot Option Numbers according to the DevOrder
00438   // Record the EnBootOption and DisBootOption according to the DevOrder
00439   //
00440   NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16));
00441   ASSERT (NewBootOption != NULL);
00442 
00443   while (DevOrderCount-- != 0) {
00444     for (Index = 0; Index < mBootOptionBbsMappingCount; Index++) {
00445       if (mBootOptionBbsMapping[Index].BbsIndex == (DevOrder[DevOrderCount] & 0xFF)) {
00446         BbsType = mBootOptionBbsMapping[Index].BbsType;
00447         NewBootOption[DevOrderCount] = mBootOptionBbsMapping[Index].BootOptionNumber;
00448         
00449         if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) {
00450           DisBootOption[*DisBootOptionCount] = NewBootOption[DevOrderCount];
00451           (*DisBootOptionCount)++;
00452         } else {
00453           EnBootOption[*EnBootOptionCount] = NewBootOption[DevOrderCount];
00454           (*EnBootOptionCount)++;
00455         }
00456         break;
00457       }
00458     }
00459   }
00460 
00461   for (Index = 0; Index < BootOptionCount; Index++) {
00462     //
00463     // Find the start position for the BbsType in BootOption
00464     //
00465     for (MappingIndex = 0; MappingIndex < mBootOptionBbsMappingCount; MappingIndex++) {
00466       if (mBootOptionBbsMapping[MappingIndex].BbsType == BbsType && mBootOptionBbsMapping[MappingIndex].BootOptionNumber == BootOption[Index]) {
00467         break;
00468       }
00469     }
00470 
00471     //
00472     // Overwrite the old BootOption
00473     //
00474     if (MappingIndex < mBootOptionBbsMappingCount) {
00475       CopyMem (&BootOption[Index], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16));
00476       break;
00477     }
00478   }
00479 }
00480 
00499 VOID
00500 GroupMultipleLegacyBootOption4SameType (
00501   UINT16                   *BootOption,
00502   UINTN                    BootOptionCount
00503   )
00504 {
00505   UINTN                    DeviceTypeIndex[7];
00506   UINTN                    Index;
00507   UINTN                    MappingIndex;
00508   UINTN                    *NextIndex;
00509   UINT16                   OptionNumber;
00510   UINTN                    DeviceIndex;
00511 
00512   SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xFF);
00513 
00514   for (Index = 0; Index < BootOptionCount; Index++) {
00515 
00516     //
00517     // Find the DeviceType
00518     //
00519     for (MappingIndex = 0; MappingIndex < mBootOptionBbsMappingCount; MappingIndex++) {
00520       if (mBootOptionBbsMapping[MappingIndex].BootOptionNumber == BootOption[Index]) {
00521         break;
00522       }
00523     }
00524     if (MappingIndex == mBootOptionBbsMappingCount) {
00525       //
00526       // Is not a legacy boot option
00527       //
00528       continue;
00529     }
00530 
00531     ASSERT ((mBootOptionBbsMapping[MappingIndex].BbsType & 0xF) < 
00532              sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]));
00533     NextIndex = &DeviceTypeIndex[mBootOptionBbsMapping[MappingIndex].BbsType & 0xF];
00534     if (*NextIndex == (UINTN) -1) {
00535       //
00536       // *NextIndex is the index in BootOption to put the next Option Number for the same type
00537       //
00538       *NextIndex = Index + 1;
00539     } else {
00540       //
00541       // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position
00542       //
00543       OptionNumber = BootOption[Index];
00544       CopyMem (&BootOption[*NextIndex + 1], &BootOption[*NextIndex], (Index - *NextIndex) * sizeof (UINT16));
00545       BootOption[*NextIndex] = OptionNumber;
00546 
00547       //
00548       // Update the DeviceTypeIndex array to reflect the right shift operation
00549       //
00550       for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) {
00551         if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) {
00552           DeviceTypeIndex[DeviceIndex]++;
00553         }
00554       }
00555     }
00556   }
00557 }
00558 
00566 EFI_STATUS
00567 EFIAPI
00568 BdsDeleteAllInvalidLegacyBootOptions (
00569   VOID
00570   )
00571 {
00572   UINT16                    *BootOrder;
00573   UINT8                     *BootOptionVar;
00574   UINTN                     BootOrderSize;
00575   UINTN                     BootOptionSize;
00576   EFI_STATUS                Status;
00577   UINT16                    HddCount;
00578   UINT16                    BbsCount;
00579   HDD_INFO                  *LocalHddInfo;
00580   BBS_TABLE                 *LocalBbsTable;
00581   BBS_TABLE                 *BbsEntry;
00582   UINT16                    BbsIndex;
00583   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
00584   UINTN                     Index;
00585   UINT16                    BootOption[10];
00586   UINT16                    BootDesc[100];
00587   BOOLEAN                   DescStringMatch;
00588 
00589   Status        = EFI_SUCCESS;
00590   BootOrder     = NULL;
00591   BootOrderSize = 0;
00592   HddCount      = 0;
00593   BbsCount      = 0;
00594   LocalHddInfo  = NULL;
00595   LocalBbsTable = NULL;
00596   BbsEntry      = NULL;
00597 
00598   Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
00599   if (EFI_ERROR (Status)) {
00600     return Status;
00601   }
00602 
00603   LegacyBios->GetBbsInfo (
00604                 LegacyBios,
00605                 &HddCount,
00606                 &LocalHddInfo,
00607                 &BbsCount,
00608                 &LocalBbsTable
00609                 );
00610 
00611   BootOrder = BdsLibGetVariableAndSize (
00612                 L"BootOrder",
00613                 &gEfiGlobalVariableGuid,
00614                 &BootOrderSize
00615                 );
00616   if (BootOrder == NULL) {
00617     BootOrderSize = 0;
00618   }
00619 
00620   Index = 0;
00621   while (Index < BootOrderSize / sizeof (UINT16)) {
00622     UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
00623     BootOptionVar = BdsLibGetVariableAndSize (
00624                       BootOption,
00625                       &gEfiGlobalVariableGuid,
00626                       &BootOptionSize
00627                       );
00628     if (NULL == BootOptionVar) {
00629       BootOptionSize = 0;
00630       Status = gRT->GetVariable (
00631                       BootOption,
00632                       &gEfiGlobalVariableGuid,
00633                       NULL,
00634                       &BootOptionSize,
00635                       BootOptionVar
00636                       );
00637       if (Status == EFI_NOT_FOUND) {
00638         //
00639         // Update BootOrder
00640         //
00641         BdsDeleteBootOption (
00642           BootOrder[Index],
00643           BootOrder,
00644           &BootOrderSize
00645           );
00646         continue;
00647       } else {
00648         FreePool (BootOrder);
00649         return EFI_OUT_OF_RESOURCES;
00650       }
00651     }
00652   
00653     //
00654     // Skip Non-Legacy boot option
00655     // 
00656     if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {
00657       if (BootOptionVar!= NULL) {
00658         FreePool (BootOptionVar);
00659       }
00660       Index++;
00661       continue;
00662     }
00663 
00664     if (BbsIndex < BbsCount) {
00665       //
00666       // Check if BBS Description String is changed
00667       //
00668       DescStringMatch = FALSE;
00669       BdsBuildLegacyDevNameString (
00670         &LocalBbsTable[BbsIndex],
00671         BbsIndex,
00672         sizeof (BootDesc),
00673         BootDesc
00674         );
00675 
00676       if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {
00677         DescStringMatch = TRUE;
00678       }
00679 
00680       if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||
00681             (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&
00682           (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&
00683           DescStringMatch) {
00684         Index++;
00685         continue;
00686       }
00687     }
00688 
00689     if (BootOptionVar != NULL) {
00690       FreePool (BootOptionVar);
00691     }
00692     //
00693     // should delete
00694     //
00695     BdsDeleteBootOption (
00696       BootOrder[Index],
00697       BootOrder,
00698       &BootOrderSize
00699       );
00700   }
00701 
00702   //
00703   // Adjust the number of boot options.
00704   //
00705   if (BootOrderSize != 0) {
00706     Status = gRT->SetVariable (
00707                     L"BootOrder",
00708                     &gEfiGlobalVariableGuid,
00709                     VAR_FLAG,
00710                     BootOrderSize,
00711                     BootOrder
00712                     );
00713   } else {
00714     EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
00715   }
00716 
00717   if (BootOrder != NULL) {
00718     FreePool (BootOrder);
00719   }
00720 
00721   return Status;
00722 }
00723 
00739 BOOLEAN
00740 BdsFindLegacyBootOptionByDevTypeAndName (
00741   IN UINT16                 *BootOrder,
00742   IN UINTN                  BootOptionNum,
00743   IN UINT16                 DevType,
00744   IN CHAR16                 *DevName,
00745   OUT UINT32                *Attribute,
00746   OUT UINT16                *BbsIndex,
00747   OUT UINT16                *OptionNumber
00748   )
00749 {
00750   UINTN     Index;
00751   CHAR16    BootOption[9];
00752   UINTN     BootOptionSize;
00753   UINT8     *BootOptionVar;
00754   BBS_TABLE *BbsEntry;
00755   BOOLEAN   Found;
00756 
00757   BbsEntry  = NULL;
00758   Found     = FALSE;
00759 
00760   if (NULL == BootOrder) {
00761     return Found;
00762   }
00763 
00764   //
00765   // Loop all boot option from variable
00766   //
00767   for (Index = 0; Index < BootOptionNum; Index++) {
00768     UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", (UINTN) BootOrder[Index]);
00769     BootOptionVar = BdsLibGetVariableAndSize (
00770                       BootOption,
00771                       &gEfiGlobalVariableGuid,
00772                       &BootOptionSize
00773                       );
00774     if (NULL == BootOptionVar) {
00775       continue;
00776     }
00777 
00778     //
00779     // Skip Non-legacy boot option
00780     //
00781     if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {
00782       FreePool (BootOptionVar);
00783       continue;
00784     }
00785 
00786     if (
00787         (BbsEntry->DeviceType != DevType) ||
00788         (StrCmp (DevName, (CHAR16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) != 0)
00789        ) {
00790       FreePool (BootOptionVar);
00791       continue;
00792     }
00793 
00794     *Attribute    = *(UINT32 *) BootOptionVar;
00795     *OptionNumber = BootOrder[Index];
00796     Found         = TRUE;
00797     FreePool (BootOptionVar);
00798     break;
00799   }
00800 
00801   return Found;
00802 }
00803 
00817 EFI_STATUS
00818 BdsCreateOneLegacyBootOption (
00819   IN BBS_TABLE              *BbsItem,
00820   IN UINTN                  Index,
00821   IN OUT UINT16             **BootOrderList,
00822   IN OUT UINTN              *BootOrderListSize
00823   )
00824 {
00825   BBS_BBS_DEVICE_PATH       BbsDevPathNode;
00826   EFI_STATUS                Status;
00827   EFI_DEVICE_PATH_PROTOCOL  *DevPath;
00828 
00829   DevPath                       = NULL;
00830 
00831   //
00832   // Create device path node.
00833   //
00834   BbsDevPathNode.Header.Type    = BBS_DEVICE_PATH;
00835   BbsDevPathNode.Header.SubType = BBS_BBS_DP;
00836   SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));
00837   BbsDevPathNode.DeviceType = BbsItem->DeviceType;
00838   CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));
00839 
00840   DevPath = AppendDevicePathNode (
00841               EndDevicePath,
00842               (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode
00843               );
00844   if (NULL == DevPath) {
00845     return EFI_OUT_OF_RESOURCES;
00846   }
00847 
00848   Status = BdsCreateLegacyBootOption (
00849             BbsItem,
00850             DevPath,
00851             Index,
00852             BootOrderList,
00853             BootOrderListSize
00854             );
00855   BbsItem->BootPriority = 0x00;
00856 
00857   FreePool (DevPath);
00858 
00859   return Status;
00860 }
00861 
00871 EFI_STATUS
00872 EFIAPI
00873 BdsAddNonExistingLegacyBootOptions (
00874   VOID
00875   )
00876 {
00877   UINT16                    *BootOrder;
00878   UINTN                     BootOrderSize;
00879   EFI_STATUS                Status;
00880   CHAR16                    Desc[100];
00881   UINT16                    HddCount;
00882   UINT16                    BbsCount;
00883   HDD_INFO                  *LocalHddInfo;
00884   BBS_TABLE                 *LocalBbsTable;
00885   UINT16                    BbsIndex;
00886   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
00887   UINT16                    Index;
00888   UINT32                    Attribute;
00889   UINT16                    OptionNumber;
00890   BOOLEAN                   Exist;
00891 
00892   HddCount      = 0;
00893   BbsCount      = 0;
00894   LocalHddInfo  = NULL;
00895   LocalBbsTable = NULL;
00896 
00897   Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
00898   if (EFI_ERROR (Status)) {
00899     return Status;
00900   }
00901 
00902   if (mBootOptionBbsMapping != NULL) {
00903     FreePool (mBootOptionBbsMapping);
00904 
00905     mBootOptionBbsMapping      = NULL;
00906     mBootOptionBbsMappingCount = 0;
00907   }
00908 
00909   LegacyBios->GetBbsInfo (
00910                 LegacyBios,
00911                 &HddCount,
00912                 &LocalHddInfo,
00913                 &BbsCount,
00914                 &LocalBbsTable
00915                 );
00916 
00917   BootOrder = BdsLibGetVariableAndSize (
00918                 L"BootOrder",
00919                 &gEfiGlobalVariableGuid,
00920                 &BootOrderSize
00921                 );
00922   if (BootOrder == NULL) {
00923     BootOrderSize = 0;
00924   }
00925 
00926   for (Index = 0; Index < BbsCount; Index++) {
00927     if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
00928         (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
00929         ) {
00930       continue;
00931     }
00932 
00933     BdsBuildLegacyDevNameString (&LocalBbsTable[Index], Index, sizeof (Desc), Desc);
00934 
00935     Exist = BdsFindLegacyBootOptionByDevTypeAndName (
00936               BootOrder,
00937               BootOrderSize / sizeof (UINT16),
00938               LocalBbsTable[Index].DeviceType,
00939               Desc,
00940               &Attribute,
00941               &BbsIndex,
00942               &OptionNumber
00943               );
00944     if (!Exist) {
00945       //
00946       // Not found such type of legacy device in boot options or we found but it's disabled
00947       // so we have to create one and put it to the tail of boot order list
00948       //
00949       Status = BdsCreateOneLegacyBootOption (
00950                 &LocalBbsTable[Index],
00951                 Index,
00952                 &BootOrder,
00953                 &BootOrderSize
00954                 );
00955       if (EFI_ERROR (Status)) {
00956         break;
00957       }
00958       BbsIndex     = Index;
00959       OptionNumber = BootOrder[BootOrderSize / sizeof (UINT16) - 1];
00960     }
00961 
00962     ASSERT (BbsIndex == Index);
00963     //
00964     // Save the BbsIndex
00965     //
00966     mBootOptionBbsMapping = ReallocatePool (
00967                               mBootOptionBbsMappingCount * sizeof (BOOT_OPTION_BBS_MAPPING),
00968                               (mBootOptionBbsMappingCount + 1) * sizeof (BOOT_OPTION_BBS_MAPPING),
00969                               mBootOptionBbsMapping
00970                               );
00971     ASSERT (mBootOptionBbsMapping != NULL);
00972     mBootOptionBbsMapping[mBootOptionBbsMappingCount].BootOptionNumber = OptionNumber;
00973     mBootOptionBbsMapping[mBootOptionBbsMappingCount].BbsIndex         = Index;
00974     mBootOptionBbsMapping[mBootOptionBbsMappingCount].BbsType          = LocalBbsTable[Index].DeviceType;
00975     mBootOptionBbsMappingCount ++;
00976   }
00977 
00978   //
00979   // Group the Boot Option Number in BootOrder for the same type devices
00980   //
00981   GroupMultipleLegacyBootOption4SameType (
00982     BootOrder,
00983     BootOrderSize / sizeof (UINT16)
00984     );
00985 
00986   if (BootOrderSize > 0) {
00987     Status = gRT->SetVariable (
00988                     L"BootOrder",
00989                     &gEfiGlobalVariableGuid,
00990                     VAR_FLAG,
00991                     BootOrderSize,
00992                     BootOrder
00993                     );
00994   } else {
00995     EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
00996   }
00997 
00998   if (BootOrder != NULL) {
00999     FreePool (BootOrder);
01000   }
01001 
01002   return Status;
01003 }
01004 
01016 UINT16 *
01017 BdsFillDevOrderBuf (
01018   IN BBS_TABLE                    *BbsTable,
01019   IN BBS_TYPE                     BbsType,
01020   IN UINTN                        BbsCount,
01021   OUT UINT16                      *Buf
01022   )
01023 {
01024   UINTN Index;
01025 
01026   for (Index = 0; Index < BbsCount; Index++) {
01027     if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
01028       continue;
01029     }
01030 
01031     if (BbsTable[Index].DeviceType != BbsType) {
01032       continue;
01033     }
01034 
01035     *Buf = (UINT16) (Index & 0xFF);
01036     Buf++;
01037   }
01038 
01039   return Buf;
01040 }
01041 
01055 EFI_STATUS
01056 BdsCreateDevOrder (
01057   IN BBS_TABLE                  *BbsTable,
01058   IN UINT16                     BbsCount
01059   )
01060 {
01061   UINTN                       Index;
01062   UINTN                       FDCount;
01063   UINTN                       HDCount;
01064   UINTN                       CDCount;
01065   UINTN                       NETCount;
01066   UINTN                       BEVCount;
01067   UINTN                       TotalSize;
01068   UINTN                       HeaderSize;
01069   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
01070   LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;
01071   EFI_STATUS                  Status;
01072 
01073   FDCount     = 0;
01074   HDCount     = 0;
01075   CDCount     = 0;
01076   NETCount    = 0;
01077   BEVCount    = 0;
01078   TotalSize   = 0;
01079   HeaderSize  = sizeof (BBS_TYPE) + sizeof (UINT16);
01080   DevOrder    = NULL;
01081   Status      = EFI_SUCCESS;
01082 
01083   //
01084   // Count all boot devices
01085   //
01086   for (Index = 0; Index < BbsCount; Index++) {
01087     if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
01088       continue;
01089     }
01090 
01091     switch (BbsTable[Index].DeviceType) {
01092     case BBS_FLOPPY:
01093       FDCount++;
01094       break;
01095 
01096     case BBS_HARDDISK:
01097       HDCount++;
01098       break;
01099 
01100     case BBS_CDROM:
01101       CDCount++;
01102       break;
01103 
01104     case BBS_EMBED_NETWORK:
01105       NETCount++;
01106       break;
01107 
01108     case BBS_BEV_DEVICE:
01109       BEVCount++;
01110       break;
01111 
01112     default:
01113       break;
01114     }
01115   }
01116 
01117   TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
01118   TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
01119   TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
01120   TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
01121   TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
01122 
01123   //
01124   // Create buffer to hold all boot device order
01125   //
01126   DevOrder = AllocateZeroPool (TotalSize);
01127   if (NULL == DevOrder) {
01128     return EFI_OUT_OF_RESOURCES;
01129   }
01130   DevOrderPtr          = DevOrder;
01131 
01132   DevOrderPtr->BbsType = BBS_FLOPPY;
01133   DevOrderPtr->Length  = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));
01134   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);
01135 
01136   DevOrderPtr->BbsType = BBS_HARDDISK;
01137   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
01138   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);
01139   
01140   DevOrderPtr->BbsType = BBS_CDROM;
01141   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
01142   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);
01143   
01144   DevOrderPtr->BbsType = BBS_EMBED_NETWORK;
01145   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
01146   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);
01147 
01148   DevOrderPtr->BbsType = BBS_BEV_DEVICE;
01149   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
01150   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);
01151 
01152   ASSERT (TotalSize == (UINTN) ((UINT8 *) DevOrderPtr - (UINT8 *) DevOrder));
01153 
01154   //
01155   // Save device order for legacy boot device to variable.
01156   //
01157   Status = gRT->SetVariable (
01158                   VAR_LEGACY_DEV_ORDER,
01159                   &gEfiLegacyDevOrderVariableGuid,
01160                   VAR_FLAG,
01161                   TotalSize,
01162                   DevOrder
01163                   );
01164   FreePool (DevOrder);
01165 
01166   return Status;
01167 }
01168 
01179 EFI_STATUS
01180 EFIAPI
01181 BdsUpdateLegacyDevOrder (
01182   VOID
01183   )
01184 {
01185   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
01186   LEGACY_DEV_ORDER_ENTRY      *NewDevOrder;
01187   LEGACY_DEV_ORDER_ENTRY      *Ptr;
01188   LEGACY_DEV_ORDER_ENTRY      *NewPtr;
01189   UINTN                       DevOrderSize;
01190   EFI_LEGACY_BIOS_PROTOCOL    *LegacyBios;
01191   EFI_STATUS                  Status;
01192   UINT16                      HddCount;
01193   UINT16                      BbsCount;
01194   HDD_INFO                    *LocalHddInfo;
01195   BBS_TABLE                   *LocalBbsTable;
01196   UINTN                       Index;
01197   UINTN                       Index2;
01198   UINTN                       *Idx;
01199   UINTN                       FDCount;
01200   UINTN                       HDCount;
01201   UINTN                       CDCount;
01202   UINTN                       NETCount;
01203   UINTN                       BEVCount;
01204   UINTN                       TotalSize;
01205   UINTN                       HeaderSize;
01206   UINT16                      *NewFDPtr;
01207   UINT16                      *NewHDPtr;
01208   UINT16                      *NewCDPtr;
01209   UINT16                      *NewNETPtr;
01210   UINT16                      *NewBEVPtr;
01211   UINT16                      *NewDevPtr;
01212   UINTN                       FDIndex;
01213   UINTN                       HDIndex;
01214   UINTN                       CDIndex;
01215   UINTN                       NETIndex;
01216   UINTN                       BEVIndex;
01217 
01218   Idx           = NULL;
01219   FDCount       = 0;
01220   HDCount       = 0;
01221   CDCount       = 0;
01222   NETCount      = 0;
01223   BEVCount      = 0;
01224   TotalSize     = 0;
01225   HeaderSize    = sizeof (BBS_TYPE) + sizeof (UINT16);
01226   FDIndex       = 0;
01227   HDIndex       = 0;
01228   CDIndex       = 0;
01229   NETIndex      = 0;
01230   BEVIndex      = 0;
01231   NewDevPtr     = NULL;
01232 
01233   Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
01234   if (EFI_ERROR (Status)) {
01235     return Status;
01236   }
01237 
01238   Status = LegacyBios->GetBbsInfo (
01239                          LegacyBios,
01240                          &HddCount,
01241                          &LocalHddInfo,
01242                          &BbsCount,
01243                          &LocalBbsTable
01244                          );
01245   if (EFI_ERROR (Status)) {
01246     return Status;
01247   }
01248 
01249   DevOrder = BdsLibGetVariableAndSize (
01250                VAR_LEGACY_DEV_ORDER,
01251                &gEfiLegacyDevOrderVariableGuid,
01252                &DevOrderSize
01253                );
01254   if (NULL == DevOrder) {
01255     return BdsCreateDevOrder (LocalBbsTable, BbsCount);
01256   }
01257   //
01258   // First we figure out how many boot devices with same device type respectively
01259   //
01260   for (Index = 0; Index < BbsCount; Index++) {
01261     if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
01262         (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
01263         ) {
01264       continue;
01265     }
01266 
01267     switch (LocalBbsTable[Index].DeviceType) {
01268     case BBS_FLOPPY:
01269       FDCount++;
01270       break;
01271 
01272     case BBS_HARDDISK:
01273       HDCount++;
01274       break;
01275 
01276     case BBS_CDROM:
01277       CDCount++;
01278       break;
01279 
01280     case BBS_EMBED_NETWORK:
01281       NETCount++;
01282       break;
01283 
01284     case BBS_BEV_DEVICE:
01285       BEVCount++;
01286       break;
01287 
01288     default:
01289       break;
01290     }
01291   }
01292 
01293   TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
01294   TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
01295   TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
01296   TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
01297   TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
01298 
01299   NewDevOrder = AllocateZeroPool (TotalSize);
01300   if (NULL == NewDevOrder) {
01301     return EFI_OUT_OF_RESOURCES;
01302   }
01303 
01304 
01305 
01306   //
01307   // copy FD
01308   //
01309   Ptr             = DevOrder;
01310   NewPtr          = NewDevOrder;
01311   NewPtr->BbsType = Ptr->BbsType;
01312   NewPtr->Length  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
01313   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
01314     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
01315         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
01316         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY
01317         ) {
01318       continue;
01319     }
01320 
01321     NewPtr->Data[FDIndex] = Ptr->Data[Index];
01322     FDIndex++;
01323   }
01324   NewFDPtr = NewPtr->Data;
01325 
01326   //
01327   // copy HD
01328   //
01329   Ptr             = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
01330   NewPtr          = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
01331   NewPtr->BbsType = Ptr->BbsType;
01332   NewPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
01333   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
01334     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
01335         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
01336         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
01337         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK
01338         ) {
01339       continue;
01340     }
01341 
01342     NewPtr->Data[HDIndex] = Ptr->Data[Index];
01343     HDIndex++;
01344   }
01345   NewHDPtr = NewPtr->Data;
01346 
01347   //
01348   // copy CD
01349   //
01350   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
01351   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
01352   NewPtr->BbsType = Ptr->BbsType;
01353   NewPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
01354   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
01355     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
01356         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
01357         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
01358         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM
01359         ) {
01360       continue;
01361     }
01362 
01363     NewPtr->Data[CDIndex] = Ptr->Data[Index];
01364     CDIndex++;
01365   }
01366   NewCDPtr = NewPtr->Data;
01367 
01368   //
01369   // copy NET
01370   //
01371   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
01372   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
01373   NewPtr->BbsType = Ptr->BbsType;
01374   NewPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
01375   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
01376     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
01377         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
01378         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
01379         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK
01380         ) {
01381       continue;
01382     }
01383 
01384     NewPtr->Data[NETIndex] = Ptr->Data[Index];
01385     NETIndex++;
01386   }
01387   NewNETPtr = NewPtr->Data;
01388   
01389   //
01390   // copy BEV
01391   //
01392   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
01393   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
01394   NewPtr->BbsType = Ptr->BbsType;
01395   NewPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
01396   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
01397     if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||
01398         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||
01399         LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||
01400         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE
01401         ) {
01402       continue;
01403     }
01404 
01405     NewPtr->Data[BEVIndex] = Ptr->Data[Index];
01406     BEVIndex++;
01407   }
01408   NewBEVPtr = NewPtr->Data;
01409 
01410   for (Index = 0; Index < BbsCount; Index++) {
01411     if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
01412         (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
01413         ) {
01414       continue;
01415     }
01416 
01417     switch (LocalBbsTable[Index].DeviceType) {
01418     case BBS_FLOPPY:
01419       Idx       = &FDIndex;
01420       NewDevPtr = NewFDPtr;
01421       break;
01422 
01423     case BBS_HARDDISK:
01424       Idx       = &HDIndex;
01425       NewDevPtr = NewHDPtr;
01426       break;
01427 
01428     case BBS_CDROM:
01429       Idx       = &CDIndex;
01430       NewDevPtr = NewCDPtr;
01431       break;
01432 
01433     case BBS_EMBED_NETWORK:
01434       Idx       = &NETIndex;
01435       NewDevPtr = NewNETPtr;
01436       break;
01437 
01438     case BBS_BEV_DEVICE:
01439       Idx       = &BEVIndex;
01440       NewDevPtr = NewBEVPtr;
01441       break;
01442 
01443     default:
01444       Idx = NULL;
01445       break;
01446     }
01447     //
01448     // at this point we have copied those valid indexes to new buffer
01449     // and we should check if there is any new appeared boot device
01450     //
01451     if (Idx != NULL) {
01452       for (Index2 = 0; Index2 < *Idx; Index2++) {
01453         if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
01454           break;
01455         }
01456       }
01457 
01458       if (Index2 == *Idx) {
01459         //
01460         // Index2 == *Idx means we didn't find Index
01461         // so Index is a new appeared device's index in BBS table
01462         // insert it before disabled indexes.
01463         //
01464         for (Index2 = 0; Index2 < *Idx; Index2++) {
01465           if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {
01466             break;
01467           }
01468         }
01469         CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));
01470         NewDevPtr[Index2] = (UINT16) (Index & 0xFF);
01471         (*Idx)++;
01472       }
01473     }
01474   }
01475 
01476   FreePool (DevOrder);
01477 
01478   Status = gRT->SetVariable (
01479                   VAR_LEGACY_DEV_ORDER,
01480                   &gEfiLegacyDevOrderVariableGuid,
01481                   VAR_FLAG,
01482                   TotalSize,
01483                   NewDevOrder
01484                   );
01485   FreePool (NewDevOrder);
01486 
01487   return Status;
01488 }
01489 
01503 EFI_STATUS
01504 BdsSetBootPriority4SameTypeDev (
01505   IN UINT16                                              DeviceType,
01506   IN UINTN                                               BbsIndex,
01507   IN OUT BBS_TABLE                                       *LocalBbsTable,
01508   IN OUT UINT16                                          *Priority
01509   )
01510 {
01511   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
01512   LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;
01513   UINTN                       DevOrderSize;
01514   UINTN                       Index;
01515 
01516   DevOrder = BdsLibGetVariableAndSize (
01517                VAR_LEGACY_DEV_ORDER,
01518                &gEfiLegacyDevOrderVariableGuid,
01519                &DevOrderSize
01520                );
01521   if (NULL == DevOrder) {
01522     return EFI_OUT_OF_RESOURCES;
01523   }
01524 
01525   DevOrderPtr = DevOrder;
01526   while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) {
01527     if (DevOrderPtr->BbsType == DeviceType) {
01528       break;
01529     }
01530 
01531     DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length);
01532   }
01533 
01534   if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) {
01535     FreePool (DevOrder);
01536     return EFI_NOT_FOUND;
01537   }
01538 
01539   if (BbsIndex != (UINTN) -1) {
01540     LocalBbsTable[BbsIndex].BootPriority = *Priority;
01541     (*Priority)++;
01542   }
01543   //
01544   // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
01545   //
01546   for (Index = 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) {
01547     if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) {
01548       //
01549       // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
01550       //
01551     } else if (DevOrderPtr->Data[Index] != BbsIndex) {
01552       LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority;
01553       (*Priority)++;
01554     }
01555   }
01556 
01557   FreePool (DevOrder);
01558   return EFI_SUCCESS;
01559 }
01560 
01567 VOID
01568 PrintBbsTable (
01569   IN BBS_TABLE  *LocalBbsTable,
01570   IN UINT16     BbsCount
01571   )
01572 {
01573   UINT16  Idx;
01574 
01575   DEBUG ((DEBUG_ERROR, "\n"));
01576   DEBUG ((DEBUG_ERROR, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
01577   DEBUG ((DEBUG_ERROR, "=============================================\n"));
01578   for (Idx = 0; Idx < BbsCount; Idx++) {
01579     if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||
01580         (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
01581         (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)
01582         ) {
01583       continue;
01584     }
01585 
01586     DEBUG (
01587       (DEBUG_ERROR,
01588       " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
01589       (UINTN) Idx,
01590       (UINTN) LocalBbsTable[Idx].BootPriority,
01591       (UINTN) LocalBbsTable[Idx].Bus,
01592       (UINTN) LocalBbsTable[Idx].Device,
01593       (UINTN) LocalBbsTable[Idx].Function,
01594       (UINTN) LocalBbsTable[Idx].Class,
01595       (UINTN) LocalBbsTable[Idx].SubClass,
01596       (UINTN) LocalBbsTable[Idx].DeviceType,
01597       (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
01598       (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
01599       (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
01600       (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
01601       (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))
01602       );
01603   }
01604 
01605   DEBUG ((DEBUG_ERROR, "\n"));
01606 }
01607 
01617 EFI_STATUS
01618 EFIAPI
01619 BdsRefreshBbsTableForBoot (
01620   IN BDS_COMMON_OPTION        *Entry
01621   )
01622 {
01623   EFI_STATUS                Status;
01624   UINT16                    BbsIndex;
01625   UINT16                    HddCount;
01626   UINT16                    BbsCount;
01627   HDD_INFO                  *LocalHddInfo;
01628   BBS_TABLE                 *LocalBbsTable;
01629   UINT16                    DevType;
01630   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
01631   UINTN                     Index;
01632   UINT16                    Priority;
01633   UINT16                    *BootOrder;
01634   UINTN                     BootOrderSize;
01635   UINT8                     *BootOptionVar;
01636   UINTN                     BootOptionSize;
01637   CHAR16                    BootOption[9];
01638   UINT8                     *Ptr;
01639   UINT16                    DevPathLen;
01640   EFI_DEVICE_PATH_PROTOCOL  *DevPath;
01641   UINT16                    *DeviceType;
01642   UINTN                     DeviceTypeCount;
01643   UINTN                     DeviceTypeIndex;
01644 
01645   HddCount      = 0;
01646   BbsCount      = 0;
01647   LocalHddInfo  = NULL;
01648   LocalBbsTable = NULL;
01649   DevType       = BBS_UNKNOWN;
01650 
01651   Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
01652   if (EFI_ERROR (Status)) {
01653     return Status;
01654   }
01655 
01656   LegacyBios->GetBbsInfo (
01657                 LegacyBios,
01658                 &HddCount,
01659                 &LocalHddInfo,
01660                 &BbsCount,
01661                 &LocalBbsTable
01662                 );
01663   //
01664   // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
01665   // We will set them according to the settings setup by user
01666   //
01667   for (Index = 0; Index < BbsCount; Index++) {
01668     if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||
01669         (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||
01670          (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {
01671       LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
01672     }
01673   }
01674   //
01675   // boot priority always starts at 0
01676   //
01677   Priority = 0;
01678   if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
01679     //
01680     // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
01681     //
01682     DevType  = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
01683     BbsIndex = *(UINT16 *) ((BBS_TABLE *) Entry->LoadOptions + 1);
01684     Status = BdsSetBootPriority4SameTypeDev (
01685               DevType,
01686               BbsIndex,
01687               LocalBbsTable,
01688               &Priority
01689               );
01690     if (EFI_ERROR (Status)) {
01691       return Status;
01692     }
01693   }
01694   //
01695   // we have to set the boot priority for other BBS entries with different device types
01696   //
01697   BootOrder = BdsLibGetVariableAndSize (
01698                 L"BootOrder",
01699                 &gEfiGlobalVariableGuid,
01700                 &BootOrderSize
01701                 );
01702   DeviceType = AllocatePool (BootOrderSize + sizeof (UINT16));
01703   ASSERT (DeviceType != NULL);
01704 
01705   DeviceType[0]   = DevType;
01706   DeviceTypeCount = 1;
01707   for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {
01708     UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
01709     BootOptionVar = BdsLibGetVariableAndSize (
01710                       BootOption,
01711                       &gEfiGlobalVariableGuid,
01712                       &BootOptionSize
01713                       );
01714     if (NULL == BootOptionVar) {
01715       continue;
01716     }
01717 
01718     Ptr = BootOptionVar;
01719 
01720     Ptr += sizeof (UINT32);
01721     DevPathLen = *(UINT16 *) Ptr;
01722     Ptr += sizeof (UINT16);
01723     Ptr += StrSize ((UINT16 *) Ptr);
01724     DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
01725     if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {
01726       FreePool (BootOptionVar);
01727       continue;
01728     }
01729 
01730     Ptr += DevPathLen;
01731     DevType = ((BBS_TABLE *) Ptr)->DeviceType;
01732     for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {
01733       if (DeviceType[DeviceTypeIndex] == DevType) {
01734         break;
01735       }
01736     }
01737     if (DeviceTypeIndex < DeviceTypeCount) {
01738       //
01739       // We don't want to process twice for a device type
01740       //
01741       FreePool (BootOptionVar);
01742       continue;
01743     }
01744 
01745     DeviceType[DeviceTypeCount] = DevType;
01746     DeviceTypeCount++;
01747 
01748     Status = BdsSetBootPriority4SameTypeDev (
01749               DevType,
01750               (UINTN) -1,
01751               LocalBbsTable,
01752               &Priority
01753               );
01754     FreePool (BootOptionVar);
01755     if (EFI_ERROR (Status)) {
01756       break;
01757     }
01758   }
01759 
01760   if (BootOrder != NULL) {
01761     FreePool (BootOrder);
01762   }
01763 
01764   DEBUG_CODE_BEGIN();
01765     PrintBbsTable (LocalBbsTable, BbsCount);
01766   DEBUG_CODE_END();
01767   
01768   return Status;
01769 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines