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
PerformUpdate(IN VOID * SystemFirmwareImage,IN UINTN SystemFirmwareImageSize,IN UPDATE_CONFIG_DATA * ConfigData,OUT UINT32 * LastAttemptVersion,OUT UINT32 * LastAttemptStatus)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
UpdateImage(IN VOID * SystemFirmwareImage,IN UINTN SystemFirmwareImageSize,IN VOID * ConfigImage,IN UINTN ConfigImageSize,OUT UINT32 * LastAttemptVersion,OUT UINT32 * LastAttemptStatus)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
SystemFirmwareAuthenticatedUpdate(IN VOID * Image,IN UINTN ImageSize,OUT UINT32 * LastAttemptVersion,OUT UINT32 * LastAttemptStatus)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
GetVariableHook(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,OUT UINT32 * Attributes OPTIONAL,IN OUT UINTN * DataSize,OUT VOID * Data)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
GetNextVariableNameHook(IN OUT UINTN * VariableNameSize,IN OUT CHAR16 * VariableName,IN OUT EFI_GUID * VendorGuid)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
SetVariableHook(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)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
QueryVariableInfoHook(IN UINT32 Attributes,OUT UINT64 * MaximumVariableStorageSize,OUT UINT64 * RemainingVariableStorageSize,OUT UINT64 * MaximumVariableSize)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
FmpSetImage(IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This,IN UINT8 ImageIndex,IN CONST VOID * Image,IN UINTN ImageSize,IN CONST VOID * VendorCode,IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,OUT CHAR16 ** AbortReason)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
SystemFirmwareUpdateMainDxe(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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