1 /** @file
2   Produce FMP instance for system firmware.
3 
4   Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "SystemFirmwareDxe.h"
10 
11 EFI_GUID gSystemFmpLastAttemptVariableGuid = SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID;
12 EFI_GUID gSystemFmpProtocolGuid = SYSTEM_FMP_PROTOCOL_GUID;
13 
14 EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
15   FmpGetImageInfo,
16   FmpGetImage,
17   FmpSetImage,
18   FmpCheckImage,
19   FmpGetPackageInfo,
20   FmpSetPackageInfo
21 };
22 
23 /**
24   Returns information about the current firmware image(s) of the device.
25 
26   This function allows a copy of the current firmware image to be created and saved.
27   The saved copy could later been used, for example, in firmware image recovery or rollback.
28 
29   @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
30   @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
31                                      On input, this is the size of the buffer allocated by the caller.
32                                      On output, it is the size of the buffer returned by the firmware
33                                      if the buffer was large enough, or the size of the buffer needed
34                                      to contain the image(s) information if the buffer was too small.
35   @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
36                                      information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
37   @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
38                                      associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
39   @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
40                                      descriptors or firmware images within this device.
41   @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
42                                      of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
43   @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
44                                      The format is vendor specific and new version must have a greater value
45                                      than the old version. If PackageVersion is not supported, the value is
46                                      0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
47                                      is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
48                                      that package version update is in progress.
49   @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
50                                      package version name. The buffer is allocated by this function with
51                                      AllocatePool(), and it is the caller's responsibility to free it with a call
52                                      to FreePool().
53 
54   @retval EFI_SUCCESS                The device was successfully updated with the new image.
55   @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
56                                      needed to hold the image(s) information is returned in ImageInfoSize.
57   @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
58   @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
59 
60 **/
61 EFI_STATUS
62 EFIAPI
FmpGetImageInfo(IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This,IN OUT UINTN * ImageInfoSize,IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR * ImageInfo,OUT UINT32 * DescriptorVersion,OUT UINT8 * DescriptorCount,OUT UINTN * DescriptorSize,OUT UINT32 * PackageVersion,OUT CHAR16 ** PackageVersionName)63 FmpGetImageInfo (
64   IN        EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
65   IN OUT    UINTN                            *ImageInfoSize,
66   IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR    *ImageInfo,
67   OUT       UINT32                           *DescriptorVersion,
68   OUT       UINT8                            *DescriptorCount,
69   OUT       UINTN                            *DescriptorSize,
70   OUT       UINT32                           *PackageVersion,
71   OUT       CHAR16                           **PackageVersionName
72   )
73 {
74   SYSTEM_FMP_PRIVATE_DATA                *SystemFmpPrivate;
75   EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
76 
77   SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This);
78 
79   if(ImageInfoSize == NULL) {
80     return EFI_INVALID_PARAMETER;
81   }
82 
83   if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount) {
84     *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount;
85     return EFI_BUFFER_TOO_SMALL;
86   }
87 
88   if (ImageInfo == NULL ||
89       DescriptorVersion == NULL ||
90       DescriptorCount == NULL ||
91       DescriptorSize == NULL ||
92       PackageVersion == NULL ||
93       PackageVersionName == NULL) {
94     return EFI_INVALID_PARAMETER;
95   }
96 
97   *ImageInfoSize      = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount;
98   *DescriptorSize     = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
99   *DescriptorCount    = SystemFmpPrivate->DescriptorCount;
100   *DescriptorVersion  = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
101 
102   //
103   // supports 1 ImageInfo descriptor
104   //
105   ImageDescriptor = SystemFmpPrivate->ImageDescriptor;
106   ImageInfo->ImageIndex = ImageDescriptor->ImageIndex;
107   CopyGuid (&ImageInfo->ImageTypeId, &ImageDescriptor->ImageTypeId);
108   ImageInfo->ImageId = ImageDescriptor->ImageId;
109   if (ImageDescriptor->ImageIdNameStringOffset != 0) {
110     ImageInfo->ImageIdName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->ImageIdNameStringOffset);
111   } else {
112     ImageInfo->ImageIdName = NULL;
113   }
114   ImageInfo->Version = ImageDescriptor->Version;
115   if (ImageDescriptor->VersionNameStringOffset != 0) {
116     ImageInfo->VersionName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->VersionNameStringOffset);
117   } else {
118     ImageInfo->VersionName = NULL;
119   }
120   ImageInfo->Size = (UINTN)ImageDescriptor->Size;
121   ImageInfo->AttributesSupported = ImageDescriptor->AttributesSupported;
122   ImageInfo->AttributesSetting = ImageDescriptor->AttributesSetting;
123   ImageInfo->Compatibilities = ImageDescriptor->Compatibilities;
124   ImageInfo->LowestSupportedImageVersion = ImageDescriptor->LowestSupportedImageVersion;
125   ImageInfo->LastAttemptVersion = SystemFmpPrivate->LastAttempt.LastAttemptVersion;
126   ImageInfo->LastAttemptStatus = SystemFmpPrivate->LastAttempt.LastAttemptStatus;
127   ImageInfo->HardwareInstance = ImageDescriptor->HardwareInstance;
128 
129   //
130   // package version
131   //
132   *PackageVersion = ImageDescriptor->PackageVersion;
133   if (ImageDescriptor->PackageVersionNameStringOffset != 0) {
134     *PackageVersionName = (VOID *)((UINTN)ImageDescriptor + ImageDescriptor->PackageVersionNameStringOffset);
135     *PackageVersionName = AllocateCopyPool(StrSize(*PackageVersionName), *PackageVersionName);
136   } else {
137     *PackageVersionName = NULL;
138   }
139 
140   return EFI_SUCCESS;
141 }
142 
143 /**
144   Retrieves a copy of the current firmware image of the device.
145 
146   This function allows a copy of the current firmware image to be created and saved.
147   The saved copy could later been used, for example, in firmware image recovery or rollback.
148 
149   @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
150   @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
151                                  The number is between 1 and DescriptorCount.
152   @param[in,out] Image           Points to the buffer where the current image is copied to.
153   @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
154                                  On return, points to the length of the image, in bytes.
155 
156   @retval EFI_SUCCESS            The device was successfully updated with the new image.
157   @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
158                                  image. The current buffer size needed to hold the image is returned
159                                  in ImageSize.
160   @retval EFI_INVALID_PARAMETER  The Image was NULL.
161   @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
162   @retval EFI_UNSUPPORTED        The operation is not supported.
163   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
164 
165 **/
166 EFI_STATUS
167 EFIAPI
FmpGetImage(IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This,IN UINT8 ImageIndex,IN OUT VOID * Image,IN OUT UINTN * ImageSize)168 FmpGetImage (
169   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
170   IN  UINT8                             ImageIndex,
171   IN  OUT  VOID                         *Image,
172   IN  OUT  UINTN                        *ImageSize
173   )
174 {
175   return EFI_UNSUPPORTED;
176 }
177 
178 /**
179   Checks if the firmware image is valid for the device.
180 
181   This function allows firmware update application to validate the firmware image without
182   invoking the SetImage() first.
183 
184   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
185   @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
186                                  The number is between 1 and DescriptorCount.
187   @param[in]  Image              Points to the new image.
188   @param[in]  ImageSize          Size of the new image in bytes.
189   @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
190                                  if available, additional information if the image is invalid.
191 
192   @retval EFI_SUCCESS            The image was successfully checked.
193   @retval EFI_INVALID_PARAMETER  The Image was NULL.
194   @retval EFI_UNSUPPORTED        The operation is not supported.
195   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
196 
197 **/
198 EFI_STATUS
199 EFIAPI
FmpCheckImage(IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This,IN UINT8 ImageIndex,IN CONST VOID * Image,IN UINTN ImageSize,OUT UINT32 * ImageUpdatable)200 FmpCheckImage (
201   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
202   IN  UINT8                             ImageIndex,
203   IN  CONST VOID                        *Image,
204   IN  UINTN                             ImageSize,
205   OUT UINT32                            *ImageUpdatable
206   )
207 {
208   return EFI_UNSUPPORTED;
209 }
210 
211 /**
212   Returns information about the firmware package.
213 
214   This function returns package information.
215 
216   @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
217   @param[out] PackageVersion           A version number that represents all the firmware images in the device.
218                                        The format is vendor specific and new version must have a greater value
219                                        than the old version. If PackageVersion is not supported, the value is
220                                        0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
221                                        comparison is to be performed using PackageVersionName. A value of
222                                        0xFFFFFFFD indicates that package version update is in progress.
223   @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
224                                        the package version name. The buffer is allocated by this function with
225                                        AllocatePool(), and it is the caller's responsibility to free it with a
226                                        call to FreePool().
227   @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
228                                        package version name. A value of 0 indicates the device does not support
229                                        update of package version name. Length is the number of Unicode characters,
230                                        including the terminating null character.
231   @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
232                                        Definitions' for possible returned values of this parameter. A value of 1
233                                        indicates the attribute is supported and the current setting value is
234                                        indicated in AttributesSetting. A value of 0 indicates the attribute is not
235                                        supported and the current setting value in AttributesSetting is meaningless.
236   @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
237                                        values of this parameter
238 
239   @retval EFI_SUCCESS                  The package information was successfully returned.
240   @retval EFI_UNSUPPORTED              The operation is not supported.
241 
242 **/
243 EFI_STATUS
244 EFIAPI
FmpGetPackageInfo(IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This,OUT UINT32 * PackageVersion,OUT CHAR16 ** PackageVersionName,OUT UINT32 * PackageVersionNameMaxLen,OUT UINT64 * AttributesSupported,OUT UINT64 * AttributesSetting)245 FmpGetPackageInfo (
246   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
247   OUT UINT32                           *PackageVersion,
248   OUT CHAR16                           **PackageVersionName,
249   OUT UINT32                           *PackageVersionNameMaxLen,
250   OUT UINT64                           *AttributesSupported,
251   OUT UINT64                           *AttributesSetting
252   )
253 {
254   return EFI_UNSUPPORTED;
255 }
256 
257 /**
258   Updates information about the firmware package.
259 
260   This function updates package information.
261   This function returns EFI_UNSUPPORTED if the package information is not updatable.
262   VendorCode enables vendor to implement vendor-specific package information update policy.
263   Null if the caller did not specify this policy or use the default policy.
264 
265   @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
266   @param[in]  Image              Points to the authentication image.
267                                  Null if authentication is not required.
268   @param[in]  ImageSize          Size of the authentication image in bytes.
269                                  0 if authentication is not required.
270   @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
271                                  image update policy.
272                                  Null indicates the caller did not specify this policy or use
273                                  the default policy.
274   @param[in]  PackageVersion     The new package version.
275   @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
276                                  the package version name.
277                                  The string length is equal to or less than the value returned in
278                                  PackageVersionNameMaxLen.
279 
280   @retval EFI_SUCCESS            The device was successfully updated with the new package
281                                  information.
282   @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
283                                  returned in PackageVersionNameMaxLen.
284   @retval EFI_UNSUPPORTED        The operation is not supported.
285   @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
286 
287 **/
288 EFI_STATUS
289 EFIAPI
FmpSetPackageInfo(IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This,IN CONST VOID * Image,IN UINTN ImageSize,IN CONST VOID * VendorCode,IN UINT32 PackageVersion,IN CONST CHAR16 * PackageVersionName)290 FmpSetPackageInfo (
291   IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL   *This,
292   IN  CONST VOID                         *Image,
293   IN  UINTN                              ImageSize,
294   IN  CONST VOID                         *VendorCode,
295   IN  UINT32                             PackageVersion,
296   IN  CONST CHAR16                       *PackageVersionName
297   )
298 {
299   return EFI_UNSUPPORTED;
300 }
301 
302 /**
303   Initialize SystemFmpDriver private data structure.
304 
305   @param[in] SystemFmpPrivate  private data structure to be initialized.
306 
307   @return EFI_SUCCESS private data is initialized.
308 **/
309 EFI_STATUS
InitializePrivateData(IN SYSTEM_FMP_PRIVATE_DATA * SystemFmpPrivate)310 InitializePrivateData (
311   IN SYSTEM_FMP_PRIVATE_DATA  *SystemFmpPrivate
312   )
313 {
314   EFI_STATUS       VarStatus;
315   UINTN            VarSize;
316 
317   SystemFmpPrivate->Signature       = SYSTEM_FMP_PRIVATE_DATA_SIGNATURE;
318   SystemFmpPrivate->Handle          = NULL;
319   SystemFmpPrivate->DescriptorCount = 1;
320   CopyMem(&SystemFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
321 
322   SystemFmpPrivate->ImageDescriptor = PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor);
323 
324   SystemFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
325   SystemFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
326   VarSize = sizeof(SystemFmpPrivate->LastAttempt);
327   VarStatus = gRT->GetVariable(
328                      SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
329                      &gSystemFmpLastAttemptVariableGuid,
330                      NULL,
331                      &VarSize,
332                      &SystemFmpPrivate->LastAttempt
333                      );
334   DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));
335   DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));
336 
337   return EFI_SUCCESS;
338 }
339 
340 
341