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

MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c

Go to the documentation of this file.
00001 
00018 #include <Uefi.h>
00019 
00020 #include <Protocol/Capsule.h>
00021 #include <Guid/CapsuleVendor.h>
00022 
00023 #include <Library/DebugLib.h>
00024 #include <Library/PcdLib.h>
00025 #include <Library/CapsuleLib.h>
00026 #include <Library/UefiDriverEntryPoint.h>
00027 #include <Library/UefiBootServicesTableLib.h>
00028 #include <Library/UefiRuntimeServicesTableLib.h>
00029 #include <Library/UefiRuntimeLib.h>
00030 #include <Library/BaseLib.h>
00031 #include <Library/PrintLib.h>
00032 
00033 //
00034 // Handle for the installation of Capsule Architecture Protocol.
00035 //
00036 EFI_HANDLE  mNewHandle = NULL;
00037 
00038 //
00039 // The times of calling UpdateCapsule ()
00040 //
00041 UINTN       mTimes      = 0;
00042 
00047 VOID
00048 SaveLongModeContext (
00049   VOID
00050   );
00051 
00078 EFI_STATUS
00079 EFIAPI
00080 UpdateCapsule (
00081   IN EFI_CAPSULE_HEADER      **CapsuleHeaderArray,
00082   IN UINTN                   CapsuleCount,
00083   IN EFI_PHYSICAL_ADDRESS    ScatterGatherList OPTIONAL
00084   )
00085 {
00086   UINTN                     ArrayNumber;
00087   EFI_STATUS                Status;
00088   EFI_CAPSULE_HEADER        *CapsuleHeader;
00089   BOOLEAN                   NeedReset;
00090   BOOLEAN                   InitiateReset;
00091   CHAR16                    CapsuleVarName[30];
00092   CHAR16                    *TempVarName;  
00093   
00094   //
00095   // Capsule Count can't be less than one.
00096   //
00097   if (CapsuleCount < 1) {
00098     return EFI_INVALID_PARAMETER;
00099   }
00100 
00101   NeedReset         = FALSE;
00102   InitiateReset     = FALSE;
00103   CapsuleHeader     = NULL;
00104   CapsuleVarName[0] = 0;
00105 
00106   for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
00107     //
00108     // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
00109     // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
00110     //
00111     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
00112     if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
00113       return EFI_INVALID_PARAMETER;
00114     }
00115     //
00116     // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have
00117     // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
00118     //
00119     if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
00120       return EFI_INVALID_PARAMETER;
00121     }
00122     //
00123     // Check Capsule image without populate flag by firmware support capsule function  
00124     //
00125     if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && 
00126         (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {
00127       return EFI_UNSUPPORTED;
00128     }
00129   }
00130 
00131   //
00132   // Walk through all capsules, record whether there is a capsule needs reset
00133   // or initiate reset. And then process capsules which has no reset flag directly.
00134   //
00135   for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {
00136     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
00137     //
00138     // Here should be in the boot-time for non-reset capsule image
00139     // Platform specific update for the non-reset capsule image.
00140     //
00141     if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
00142       if (EfiAtRuntime ()) { 
00143         Status = EFI_UNSUPPORTED;
00144       } else {
00145         Status = ProcessCapsuleImage(CapsuleHeader);
00146       }
00147       if (EFI_ERROR(Status)) {
00148         return Status;
00149       }
00150     } else {
00151       NeedReset = TRUE;
00152       if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) != 0) {
00153         InitiateReset = TRUE;
00154       }
00155     }
00156   }
00157   
00158   //
00159   // After launching all capsules who has no reset flag, if no more capsules claims
00160   // for a system reset just return.
00161   //
00162   if (!NeedReset) {
00163     return EFI_SUCCESS;
00164   }
00165 
00166   //
00167   // ScatterGatherList is only referenced if the capsules are defined to persist across
00168   // system reset. 
00169   //
00170   if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
00171     return EFI_INVALID_PARAMETER;
00172   }
00173 
00174   //
00175   // Check if the platform supports update capsule across a system reset
00176   //
00177   if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
00178     return EFI_UNSUPPORTED;
00179   }
00180 
00181   //
00182   // Construct variable name CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
00183   // if user calls UpdateCapsule multiple times.
00184   //
00185   StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
00186   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
00187   if (mTimes > 0) {
00188     UnicodeValueToString (TempVarName, 0, mTimes, 0);
00189   }
00190 
00191   //
00192   // ScatterGatherList is only referenced if the capsules are defined to persist across
00193   // system reset. Set its value into NV storage to let pre-boot driver to pick it up 
00194   // after coming through a system reset.
00195   //
00196   Status = EfiSetVariable (
00197              CapsuleVarName,
00198              &gEfiCapsuleVendorGuid,
00199              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
00200              sizeof (UINTN),
00201              (VOID *) &ScatterGatherList
00202              );
00203   if (!EFI_ERROR (Status)) {
00204      //
00205      // Variable has been set successfully, increase variable index.
00206      //
00207      mTimes++;
00208      if(InitiateReset) {
00209        //
00210        // Firmware that encounters a capsule which has the CAPSULE_FLAGS_INITIATE_RESET Flag set in its header
00211        // will initiate a reset of the platform which is compatible with the passed-in capsule request and will 
00212        // not return back to the caller.
00213        //
00214        EfiResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
00215      }
00216   }
00217   return Status;
00218 }
00219 
00239 EFI_STATUS
00240 EFIAPI
00241 QueryCapsuleCapabilities (
00242   IN  EFI_CAPSULE_HEADER   **CapsuleHeaderArray,
00243   IN  UINTN                CapsuleCount,
00244   OUT UINT64               *MaxiumCapsuleSize,
00245   OUT EFI_RESET_TYPE       *ResetType
00246   )
00247 {
00248   UINTN                     ArrayNumber;
00249   EFI_CAPSULE_HEADER        *CapsuleHeader;
00250   BOOLEAN                   NeedReset;
00251 
00252   //
00253   // Capsule Count can't be less than one.
00254   //
00255   if (CapsuleCount < 1) {
00256     return EFI_INVALID_PARAMETER;
00257   }
00258   
00259   //
00260   // Check whether input parameter is valid
00261   //
00262   if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {
00263     return EFI_INVALID_PARAMETER;
00264   }
00265 
00266   CapsuleHeader = NULL;
00267   NeedReset     = FALSE;
00268 
00269   for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
00270     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
00271     //
00272     // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
00273     // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
00274     //
00275     if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
00276       return EFI_INVALID_PARAMETER;
00277     }
00278     //
00279     // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have
00280     // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
00281     //
00282     if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
00283       return EFI_INVALID_PARAMETER;
00284     }
00285     //
00286     // Check Capsule image without populate flag is supported by firmware
00287     //
00288     if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && 
00289         (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {
00290       return EFI_UNSUPPORTED;
00291     }
00292   }
00293 
00294   //
00295   // Find out whether there is any capsule defined to persist across system reset. 
00296   //
00297   for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {
00298     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
00299     if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
00300       NeedReset = TRUE;
00301       break;
00302     }
00303   }
00304   
00305   if (NeedReset) {
00306     //
00307     //Check if the platform supports update capsule across a system reset
00308     //
00309     if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
00310       return EFI_UNSUPPORTED;
00311     }
00312     *ResetType = EfiResetWarm;
00313     *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule);
00314   } else {
00315     //
00316     // For non-reset capsule image.
00317     //
00318     *ResetType = EfiResetCold;
00319     *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule);
00320   }
00321 
00322   return EFI_SUCCESS;
00323 }
00324 
00325 
00336 EFI_STATUS
00337 EFIAPI
00338 CapsuleServiceInitialize (
00339   IN EFI_HANDLE         ImageHandle,
00340   IN EFI_SYSTEM_TABLE   *SystemTable
00341   )
00342 {
00343   EFI_STATUS  Status;
00344   
00345   //
00346   // When PEI phase is IA32, DXE phase is X64, it is possible that capsule data are 
00347   // put above 4GB, so capsule PEI will transfer to long mode to get capsule data.
00348   // The page table and stack is used to transfer processor mode from IA32 to long mode.
00349   // Create the base address of page table and stack, and save them into variable.
00350   // This is not needed when capsule with reset type is not supported.
00351   //
00352   SaveLongModeContext ();
00353     
00354   //
00355   // Install capsule runtime services into UEFI runtime service tables.
00356   //
00357   gRT->UpdateCapsule                    = UpdateCapsule;
00358   gRT->QueryCapsuleCapabilities         = QueryCapsuleCapabilities;
00359 
00360   //
00361   // Install the Capsule Architectural Protocol on a new handle
00362   // to signify the capsule runtime services are ready.
00363   //
00364   Status = gBS->InstallMultipleProtocolInterfaces (
00365                   &mNewHandle,
00366                   &gEfiCapsuleArchProtocolGuid,
00367                   NULL,
00368                   NULL
00369                   );
00370   ASSERT_EFI_ERROR (Status);
00371 
00372   return Status;
00373 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines