Home | History | Annotate | Download | only in SystemFirmwareUpdate
      1 /** @file
      2   SetImage instance to update system firmware.
      3 
      4   Caution: This module requires additional review when modified.
      5   This module will have external input - capsule image.
      6   This external input must be validated carefully to avoid security issue like
      7   buffer overflow, integer overflow.
      8 
      9   FmpSetImage() will receive untrusted input and do basic validation.
     10 
     11   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
     12   This program and the accompanying materials
     13   are licensed and made available under the terms and conditions of the BSD License
     14   which accompanies this distribution.  The full text of the license may be found at
     15   http://opensource.org/licenses/bsd-license.php
     16 
     17   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     19 
     20 **/
     21 
     22 #include "SystemFirmwareDxe.h"
     23 
     24 //
     25 // SystemFmp driver private data
     26 //
     27 SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate = NULL;
     28 
     29 EFI_GUID mCurrentImageTypeId;
     30 
     31 BOOLEAN  mNvRamUpdated = FALSE;
     32 
     33 /**
     34   Parse Config data file to get the updated data array.
     35 
     36   @param[in]      DataBuffer      Config raw file buffer.
     37   @param[in]      BufferSize      Size of raw buffer.
     38   @param[in, out] ConfigHeader    Pointer to the config header.
     39   @param[in, out] UpdateArray     Pointer to the config of update data.
     40 
     41   @retval EFI_NOT_FOUND         No config data is found.
     42   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
     43   @retval EFI_SUCCESS           Parse the config file successfully.
     44 
     45 **/
     46 EFI_STATUS
     47 ParseUpdateDataFile (
     48   IN      UINT8                         *DataBuffer,
     49   IN      UINTN                         BufferSize,
     50   IN OUT  CONFIG_HEADER                 *ConfigHeader,
     51   IN OUT  UPDATE_CONFIG_DATA            **UpdateArray
     52   );
     53 
     54 /**
     55   Update System Firmware image component.
     56 
     57   @param[in]  SystemFirmwareImage     Points to the System Firmware image.
     58   @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
     59   @param[in]  ConfigData              Points to the component configuration structure.
     60   @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
     61   @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
     62 
     63   @retval EFI_SUCCESS             The System Firmware image is updated.
     64   @retval EFI_WRITE_PROTECTED     The flash device is read only.
     65 **/
     66 EFI_STATUS
     67 PerformUpdate (
     68   IN VOID                         *SystemFirmwareImage,
     69   IN UINTN                        SystemFirmwareImageSize,
     70   IN UPDATE_CONFIG_DATA           *ConfigData,
     71   OUT UINT32                      *LastAttemptVersion,
     72   OUT UINT32                      *LastAttemptStatus
     73   )
     74 {
     75   EFI_STATUS                   Status;
     76 
     77   DEBUG((DEBUG_INFO, "PlatformUpdate:"));
     78   DEBUG((DEBUG_INFO, "  BaseAddress - 0x%lx,", ConfigData->BaseAddress));
     79   DEBUG((DEBUG_INFO, "  ImageOffset - 0x%x,", ConfigData->ImageOffset));
     80   DEBUG((DEBUG_INFO, "  Legnth - 0x%x\n", ConfigData->Length));
     81   Status = PerformFlashWrite (
     82              ConfigData->FirmwareType,
     83              ConfigData->BaseAddress,
     84              ConfigData->AddressType,
     85              (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->ImageOffset),
     86              ConfigData->Length
     87              );
     88   if (!EFI_ERROR(Status)) {
     89     *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
     90     if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {
     91       mNvRamUpdated = TRUE;
     92     }
     93   } else {
     94     *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
     95   }
     96   return Status;
     97 }
     98 
     99 /**
    100   Update System Firmware image.
    101 
    102   @param[in]  SystemFirmwareImage     Points to the System Firmware image.
    103   @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
    104   @param[in]  ConfigImage             Points to the config file image.
    105   @param[in]  ConfigImageSize         The length of the config file image in bytes.
    106   @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    107   @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    108 
    109   @retval EFI_SUCCESS             The System Firmware image is updated.
    110   @retval EFI_WRITE_PROTECTED     The flash device is read only.
    111 **/
    112 EFI_STATUS
    113 UpdateImage (
    114   IN VOID                         *SystemFirmwareImage,
    115   IN UINTN                        SystemFirmwareImageSize,
    116   IN VOID                         *ConfigImage,
    117   IN UINTN                        ConfigImageSize,
    118   OUT UINT32                      *LastAttemptVersion,
    119   OUT UINT32                      *LastAttemptStatus
    120   )
    121 {
    122   EFI_STATUS                            Status;
    123   UPDATE_CONFIG_DATA                    *ConfigData;
    124   UPDATE_CONFIG_DATA                    *UpdateConfigData;
    125   CONFIG_HEADER                         ConfigHeader;
    126   UINTN                                 Index;
    127 
    128   if (ConfigImage == NULL) {
    129     DEBUG((DEBUG_INFO, "PlatformUpdate (NoConfig):"));
    130     DEBUG((DEBUG_INFO, "  BaseAddress - 0x%x,", 0));
    131     DEBUG((DEBUG_INFO, "  Length - 0x%x\n", SystemFirmwareImageSize));
    132     // ASSUME the whole System Firmware include NVRAM region.
    133     Status = PerformFlashWrite (
    134                PlatformFirmwareTypeNvRam,
    135                0,
    136                FlashAddressTypeRelativeAddress,
    137                SystemFirmwareImage,
    138                SystemFirmwareImageSize
    139                );
    140     if (!EFI_ERROR(Status)) {
    141       *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
    142       mNvRamUpdated = TRUE;
    143     } else {
    144       *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
    145     }
    146     return Status;
    147   }
    148 
    149   DEBUG((DEBUG_INFO, "PlatformUpdate (With Config):\n"));
    150   ConfigData        = NULL;
    151   ZeroMem (&ConfigHeader, sizeof(ConfigHeader));
    152   Status            = ParseUpdateDataFile (
    153                         ConfigImage,
    154                         ConfigImageSize,
    155                         &ConfigHeader,
    156                         &ConfigData
    157                         );
    158   DEBUG((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status));
    159   if (EFI_ERROR(Status)) {
    160     *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
    161     return EFI_INVALID_PARAMETER;
    162   }
    163   DEBUG((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates));
    164   DEBUG((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid)));
    165 
    166   Index = 0;
    167   UpdateConfigData = ConfigData;
    168   while (Index < ConfigHeader.NumOfUpdates) {
    169     if (CompareGuid(&UpdateConfigData->FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) {
    170       DEBUG((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid));
    171       Status = PerformUpdate (
    172                  SystemFirmwareImage,
    173                  SystemFirmwareImageSize,
    174                  UpdateConfigData,
    175                  LastAttemptVersion,
    176                  LastAttemptStatus
    177                  );
    178       //
    179       // Shall updates be serialized so that if an update is not successfully completed,
    180       // the remaining updates won't be performed.
    181       //
    182       if (EFI_ERROR (Status)) {
    183         break;
    184       }
    185     } else {
    186       DEBUG((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid));
    187     }
    188 
    189     Index++;
    190     UpdateConfigData++;
    191   }
    192 
    193   return Status;
    194 }
    195 
    196 /**
    197   Authenticate and update System Firmware image.
    198 
    199   Caution: This function may receive untrusted input.
    200 
    201   @param[in]  Image              The EDKII system FMP capsule image.
    202   @param[in]  ImageSize          The size of the EDKII system FMP capsule image in bytes.
    203   @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    204   @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
    205 
    206   @retval EFI_SUCCESS             EDKII system FMP capsule passes authentication and the System Firmware image is updated.
    207   @retval EFI_SECURITY_VIOLATION  EDKII system FMP capsule fails authentication and the System Firmware image is not updated.
    208   @retval EFI_WRITE_PROTECTED     The flash device is read only.
    209 **/
    210 EFI_STATUS
    211 SystemFirmwareAuthenticatedUpdate (
    212   IN VOID                         *Image,
    213   IN UINTN                        ImageSize,
    214   OUT UINT32                      *LastAttemptVersion,
    215   OUT UINT32                      *LastAttemptStatus
    216   )
    217 {
    218   EFI_STATUS                  Status;
    219   VOID                        *SystemFirmwareImage;
    220   UINTN                       SystemFirmwareImageSize;
    221   VOID                        *ConfigImage;
    222   UINTN                       ConfigImageSize;
    223   VOID                        *AuthenticatedImage;
    224   UINTN                       AuthenticatedImageSize;
    225 
    226   AuthenticatedImage     = NULL;
    227   AuthenticatedImageSize = 0;
    228 
    229   DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n"));
    230 
    231   Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
    232   if (EFI_ERROR(Status)) {
    233     DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status));
    234     return Status;
    235   }
    236 
    237   DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n"));
    238   ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
    239   DEBUG((DEBUG_INFO, "ExtractConfigImage ...\n"));
    240   ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
    241 
    242   DEBUG((DEBUG_INFO, "UpdateImage ...\n"));
    243   Status = UpdateImage(SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus);
    244   if (EFI_ERROR(Status)) {
    245     DEBUG((DEBUG_INFO, "UpdateImage - %r\n", Status));
    246     return Status;
    247   }
    248 
    249   DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n"));
    250 
    251   return EFI_SUCCESS;
    252 }
    253 
    254 /**
    255 
    256   This code finds variable in storage blocks (Volatile or Non-Volatile).
    257 
    258   @param[in]      VariableName               Name of Variable to be found.
    259   @param[in]      VendorGuid                 Variable vendor GUID.
    260   @param[out]     Attributes                 Attribute value of the variable found.
    261   @param[in, out] DataSize                   Size of Data found. If size is less than the
    262                                              data, this value contains the required size.
    263   @param[out]     Data                       Data pointer.
    264 
    265   @return EFI_INVALID_PARAMETER     Invalid parameter.
    266   @return EFI_SUCCESS               Find the specified variable.
    267   @return EFI_NOT_FOUND             Not found.
    268   @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
    269 
    270 **/
    271 EFI_STATUS
    272 EFIAPI
    273 GetVariableHook (
    274   IN      CHAR16            *VariableName,
    275   IN      EFI_GUID          *VendorGuid,
    276   OUT     UINT32            *Attributes OPTIONAL,
    277   IN OUT  UINTN             *DataSize,
    278   OUT     VOID              *Data
    279   )
    280 {
    281   DEBUG((DEBUG_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGuid));
    282   return EFI_NOT_AVAILABLE_YET;
    283 }
    284 
    285 /**
    286 
    287   This code Finds the Next available variable.
    288 
    289   @param[in, out] VariableNameSize           Size of the variable name.
    290   @param[in, out] VariableName               Pointer to variable name.
    291   @param[in, out] VendorGuid                 Variable Vendor Guid.
    292 
    293   @return EFI_INVALID_PARAMETER     Invalid parameter.
    294   @return EFI_SUCCESS               Find the specified variable.
    295   @return EFI_NOT_FOUND             Not found.
    296   @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
    297 
    298 **/
    299 EFI_STATUS
    300 EFIAPI
    301 GetNextVariableNameHook (
    302   IN OUT  UINTN             *VariableNameSize,
    303   IN OUT  CHAR16            *VariableName,
    304   IN OUT  EFI_GUID          *VendorGuid
    305   )
    306 {
    307   DEBUG((DEBUG_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, VendorGuid));
    308   return EFI_NOT_AVAILABLE_YET;
    309 }
    310 
    311 /**
    312 
    313   This code sets variable in storage blocks (Volatile or Non-Volatile).
    314 
    315   @param[in] VariableName                     Name of Variable to be found.
    316   @param[in] VendorGuid                       Variable vendor GUID.
    317   @param[in] Attributes                       Attribute value of the variable found
    318   @param[in] DataSize                         Size of Data found. If size is less than the
    319                                               data, this value contains the required size.
    320   @param[in] Data                             Data pointer.
    321 
    322   @return EFI_INVALID_PARAMETER           Invalid parameter.
    323   @return EFI_SUCCESS                     Set successfully.
    324   @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
    325   @return EFI_NOT_FOUND                   Not found.
    326   @return EFI_WRITE_PROTECTED             Variable is read-only.
    327 
    328 **/
    329 EFI_STATUS
    330 EFIAPI
    331 SetVariableHook (
    332   IN CHAR16                  *VariableName,
    333   IN EFI_GUID                *VendorGuid,
    334   IN UINT32                  Attributes,
    335   IN UINTN                   DataSize,
    336   IN VOID                    *Data
    337   )
    338 {
    339   DEBUG((DEBUG_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableName, VendorGuid, Attributes, DataSize));
    340   return EFI_NOT_AVAILABLE_YET;
    341 }
    342 
    343 /**
    344 
    345   This code returns information about the EFI variables.
    346 
    347   @param[in]  Attributes                     Attributes bitmask to specify the type of variables
    348                                              on which to return information.
    349   @param[out] MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
    350                                              for the EFI variables associated with the attributes specified.
    351   @param[out] RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
    352                                              for EFI variables associated with the attributes specified.
    353   @param[out] MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
    354                                              associated with the attributes specified.
    355 
    356   @return EFI_SUCCESS                   Query successfully.
    357 
    358 **/
    359 EFI_STATUS
    360 EFIAPI
    361 QueryVariableInfoHook (
    362   IN  UINT32                 Attributes,
    363   OUT UINT64                 *MaximumVariableStorageSize,
    364   OUT UINT64                 *RemainingVariableStorageSize,
    365   OUT UINT64                 *MaximumVariableSize
    366   )
    367 {
    368   DEBUG((DEBUG_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes));
    369   return EFI_NOT_AVAILABLE_YET;
    370 }
    371 
    372 /**
    373   Updates the firmware image of the device.
    374 
    375   This function updates the hardware with the new firmware image.
    376   This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
    377   If the firmware image is updatable, the function should perform the following minimal validations
    378   before proceeding to do the firmware image update.
    379   - Validate the image authentication if image has attribute
    380     IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
    381     EFI_SECURITY_VIOLATION if the validation fails.
    382   - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
    383     the image is unsupported. The function can optionally provide more detailed information on
    384     why the image is not a supported image.
    385   - Validate the data from VendorCode if not null. Image validation must be performed before
    386     VendorCode data validation. VendorCode data is ignored or considered invalid if image
    387     validation failed. The function returns EFI_ABORTED if the data is invalid.
    388 
    389   VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
    390   the caller did not specify the policy or use the default policy. As an example, vendor can implement
    391   a policy to allow an option to force a firmware image update when the abort reason is due to the new
    392   firmware image version is older than the current firmware image version or bad image checksum.
    393   Sensitive operations such as those wiping the entire firmware image and render the device to be
    394   non-functional should be encoded in the image itself rather than passed with the VendorCode.
    395   AbortReason enables vendor to have the option to provide a more detailed description of the abort
    396   reason to the caller.
    397 
    398   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
    399   @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
    400                                  The number is between 1 and DescriptorCount.
    401   @param[in]  Image              Points to the new image.
    402   @param[in]  ImageSize          Size of the new image in bytes.
    403   @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
    404                                  Null indicates the caller did not specify the policy or use the default policy.
    405   @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
    406   @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
    407                                  details for the aborted operation. The buffer is allocated by this function
    408                                  with AllocatePool(), and it is the caller's responsibility to free it with a
    409                                  call to FreePool().
    410 
    411   @retval EFI_SUCCESS            The device was successfully updated with the new image.
    412   @retval EFI_ABORTED            The operation is aborted.
    413   @retval EFI_INVALID_PARAMETER  The Image was NULL.
    414   @retval EFI_UNSUPPORTED        The operation is not supported.
    415   @retval EFI_SECURITY_VIOLATIO  The operation could not be performed due to an authentication failure.
    416 
    417 **/
    418 EFI_STATUS
    419 EFIAPI
    420 FmpSetImage (
    421   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL                 *This,
    422   IN  UINT8                                            ImageIndex,
    423   IN  CONST VOID                                       *Image,
    424   IN  UINTN                                            ImageSize,
    425   IN  CONST VOID                                       *VendorCode,
    426   IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS    Progress,
    427   OUT CHAR16                                           **AbortReason
    428   )
    429 {
    430   EFI_STATUS              Status;
    431   EFI_STATUS              VarStatus;
    432   SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate;
    433 
    434   if (Image == NULL || ImageSize == 0 || AbortReason == NULL) {
    435     return EFI_INVALID_PARAMETER;
    436   }
    437 
    438   SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This);
    439   *AbortReason     = NULL;
    440 
    441   if (ImageIndex == 0 || ImageIndex > SystemFmpPrivate->DescriptorCount) {
    442     return EFI_INVALID_PARAMETER;
    443   }
    444 
    445   Status = SystemFirmwareAuthenticatedUpdate((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus);
    446   DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));
    447 
    448   //
    449   // If NVRAM is updated, we should no longer touch variable services, because
    450   // the current variable driver may not manage the new NVRAM region.
    451   //
    452   if (mNvRamUpdated) {
    453     DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Serivces\n"));
    454     gRT->GetVariable         = GetVariableHook;
    455     gRT->GetNextVariableName = GetNextVariableNameHook;
    456     gRT->SetVariable         = SetVariableHook;
    457     gRT->QueryVariableInfo   = QueryVariableInfoHook;
    458 
    459     gRT->Hdr.CRC32 = 0;
    460     gBS->CalculateCrc32 (
    461           (UINT8 *) &gRT->Hdr,
    462           gRT->Hdr.HeaderSize,
    463           &gRT->Hdr.CRC32
    464           );
    465   }
    466 
    467   VarStatus = gRT->SetVariable(
    468                      SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
    469                      &gSystemFmpLastAttemptVariableGuid,
    470                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    471                      sizeof(SystemFmpPrivate->LastAttempt),
    472                      &SystemFmpPrivate->LastAttempt
    473                      );
    474   DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));
    475 
    476   return Status;
    477 }
    478 
    479 /**
    480   System FMP module entrypoint
    481 
    482   @param  ImageHandle       The firmware allocated handle for the EFI image.
    483   @param  SystemTable       A pointer to the EFI System Table.
    484 
    485   @return EFI_SUCCESS System FMP module is initialized.
    486 **/
    487 EFI_STATUS
    488 EFIAPI
    489 SystemFirmwareUpdateMainDxe (
    490   IN EFI_HANDLE                         ImageHandle,
    491   IN EFI_SYSTEM_TABLE                   *SystemTable
    492   )
    493 {
    494   EFI_STATUS                                      Status;
    495 
    496   //
    497   // Initialize SystemFmpPrivateData
    498   //
    499   mSystemFmpPrivate = AllocateZeroPool (sizeof(SYSTEM_FMP_PRIVATE_DATA));
    500   if (mSystemFmpPrivate == NULL) {
    501     return EFI_OUT_OF_RESOURCES;
    502   }
    503 
    504   Status = InitializePrivateData(mSystemFmpPrivate);
    505   if (EFI_ERROR(Status)) {
    506     FreePool(mSystemFmpPrivate);
    507     mSystemFmpPrivate = NULL;
    508     return Status;
    509   }
    510 
    511   //
    512   // Install FMP protocol.
    513   //
    514   Status = gBS->InstallMultipleProtocolInterfaces (
    515                   &mSystemFmpPrivate->Handle,
    516                   &gEfiFirmwareManagementProtocolGuid,
    517                   &mSystemFmpPrivate->Fmp,
    518                   &gSystemFmpProtocolGuid,
    519                   &mSystemFmpPrivate->Fmp,
    520                   NULL
    521                   );
    522   if (EFI_ERROR (Status)) {
    523     FreePool(mSystemFmpPrivate);
    524     mSystemFmpPrivate = NULL;
    525     return Status;
    526   }
    527 
    528   return Status;
    529 }
    530