]> git.proxmox.com Git - mirror_edk2.git/blame - SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareReportDxe.c
SignedCapsulePkg/SystemFirmwareReportDxe: Pass thru on same handle
[mirror_edk2.git] / SignedCapsulePkg / Universal / SystemFirmwareUpdate / SystemFirmwareReportDxe.c
CommitLineData
f6f91d38
JY
1/** @file\r
2 SetImage instance to report system firmware and act as agent to system update.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This module will have external input - capsule image.\r
6 This external input must be validated carefully to avoid security issue like\r
7 buffer overflow, integer overflow.\r
8\r
9 FmpSetImage() will receive untrusted input and do basic validation.\r
10\r
153f5c7a 11 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
f6f91d38
JY
12 This program and the accompanying materials\r
13 are licensed and made available under the terms and conditions of the BSD License\r
14 which accompanies this distribution. The full text of the license may be found at\r
15 http://opensource.org/licenses/bsd-license.php\r
16\r
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
19\r
20**/\r
21\r
22#include "SystemFirmwareDxe.h"\r
23\r
24//\r
25// SystemFmp driver private data\r
26//\r
27SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate = NULL;\r
28\r
29/**\r
30 Dispatch system FMP images.\r
31\r
32 Caution: This function may receive untrusted input.\r
33\r
34 @param[in] Image The EDKII system FMP capsule image.\r
35 @param[in] ImageSize The size of the EDKII system FMP capsule image in bytes.\r
36 @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
37 @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
38\r
39 @retval EFI_SUCESS Process Capsule Image successfully.\r
40 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
41 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
42 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
43**/\r
44EFI_STATUS\r
45DispatchSystemFmpImages (\r
46 IN VOID *Image,\r
47 IN UINTN ImageSize,\r
48 OUT UINT32 *LastAttemptVersion,\r
49 OUT UINT32 *LastAttemptStatus\r
50 )\r
51{\r
52 EFI_STATUS Status;\r
53 VOID *AuthenticatedImage;\r
54 UINTN AuthenticatedImageSize;\r
55 VOID *DispatchFvImage;\r
56 UINTN DispatchFvImageSize;\r
57 EFI_HANDLE FvProtocolHandle;\r
58 EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
59 BOOLEAN Result;\r
60\r
8b66342c
HW
61 AuthenticatedImage = NULL;\r
62 AuthenticatedImageSize = 0;\r
63\r
f6f91d38
JY
64 DEBUG((DEBUG_INFO, "DispatchSystemFmpImages\n"));\r
65\r
66 //\r
67 // Verify\r
68 //\r
69 Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);\r
70 if (EFI_ERROR(Status)) {\r
71 DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status));\r
72 return Status;\r
73 }\r
74\r
75 //\r
76 // Get FV\r
77 //\r
78 Result = ExtractDriverFvImage(AuthenticatedImage, AuthenticatedImageSize, &DispatchFvImage, &DispatchFvImageSize);\r
79 if (Result) {\r
80 DEBUG((DEBUG_INFO, "ExtractDriverFvImage\n"));\r
81 //\r
82 // Dispatch\r
83 //\r
84 if (((EFI_FIRMWARE_VOLUME_HEADER *)DispatchFvImage)->FvLength == DispatchFvImageSize) {\r
85 FvImage = AllocatePages(EFI_SIZE_TO_PAGES(DispatchFvImageSize));\r
86 if (FvImage != NULL) {\r
87 CopyMem(FvImage, DispatchFvImage, DispatchFvImageSize);\r
88 Status = gDS->ProcessFirmwareVolume(\r
89 (VOID *)FvImage,\r
90 (UINTN)FvImage->FvLength,\r
91 &FvProtocolHandle\r
92 );\r
93 DEBUG((DEBUG_INFO, "ProcessFirmwareVolume - %r\n", Status));\r
94 if (!EFI_ERROR(Status)) {\r
95 gDS->Dispatch();\r
96 DEBUG((DEBUG_INFO, "Dispatch Done\n"));\r
97 }\r
98 }\r
99 }\r
100 }\r
101\r
102 return EFI_SUCCESS;\r
103}\r
104\r
105/**\r
106 Updates the firmware image of the device.\r
107\r
108 This function updates the hardware with the new firmware image.\r
109 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.\r
110 If the firmware image is updatable, the function should perform the following minimal validations\r
111 before proceeding to do the firmware image update.\r
112 - Validate the image authentication if image has attribute\r
113 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns\r
114 EFI_SECURITY_VIOLATION if the validation fails.\r
115 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if\r
116 the image is unsupported. The function can optionally provide more detailed information on\r
117 why the image is not a supported image.\r
118 - Validate the data from VendorCode if not null. Image validation must be performed before\r
119 VendorCode data validation. VendorCode data is ignored or considered invalid if image\r
120 validation failed. The function returns EFI_ABORTED if the data is invalid.\r
121\r
122 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if\r
123 the caller did not specify the policy or use the default policy. As an example, vendor can implement\r
124 a policy to allow an option to force a firmware image update when the abort reason is due to the new\r
125 firmware image version is older than the current firmware image version or bad image checksum.\r
126 Sensitive operations such as those wiping the entire firmware image and render the device to be\r
127 non-functional should be encoded in the image itself rather than passed with the VendorCode.\r
128 AbortReason enables vendor to have the option to provide a more detailed description of the abort\r
129 reason to the caller.\r
130\r
131 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
132 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
133 The number is between 1 and DescriptorCount.\r
134 @param[in] Image Points to the new image.\r
135 @param[in] ImageSize Size of the new image in bytes.\r
136 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.\r
137 Null indicates the caller did not specify the policy or use the default policy.\r
138 @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
139 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
140 details for the aborted operation. The buffer is allocated by this function\r
141 with AllocatePool(), and it is the caller's responsibility to free it with a\r
142 call to FreePool().\r
143\r
144 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
145 @retval EFI_ABORTED The operation is aborted.\r
146 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
147 @retval EFI_UNSUPPORTED The operation is not supported.\r
148 @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.\r
149\r
150**/\r
151EFI_STATUS\r
152EFIAPI\r
153FmpSetImage (\r
154 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
155 IN UINT8 ImageIndex,\r
156 IN CONST VOID *Image,\r
157 IN UINTN ImageSize,\r
158 IN CONST VOID *VendorCode,\r
159 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,\r
160 OUT CHAR16 **AbortReason\r
161 )\r
162{\r
163 SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate;\r
164 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *SystemFmp;\r
165 EFI_STATUS Status;\r
166 EFI_STATUS VarStatus;\r
167\r
168 if (Image == NULL || ImageSize == 0 || AbortReason == NULL) {\r
169 return EFI_INVALID_PARAMETER;\r
170 }\r
171\r
172 SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(This);\r
173 *AbortReason = NULL;\r
174\r
175 if (ImageIndex == 0 || ImageIndex > SystemFmpPrivate->DescriptorCount) {\r
176 return EFI_INVALID_PARAMETER;\r
177 }\r
178\r
179 //\r
180 // Process FV\r
181 //\r
182 Status = DispatchSystemFmpImages((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus);\r
183 DEBUG((DEBUG_INFO, "(Agent)SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));\r
184 if (EFI_ERROR(Status)) {\r
185 VarStatus = gRT->SetVariable(\r
186 SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,\r
187 &gSystemFmpLastAttemptVariableGuid,\r
188 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
189 sizeof(SystemFmpPrivate->LastAttempt),\r
190 &SystemFmpPrivate->LastAttempt\r
191 );\r
192 DEBUG((DEBUG_INFO, "(Agent)SetLastAttemp - %r\n", VarStatus));\r
193 return Status;\r
194 }\r
195\r
196 //\r
153f5c7a 197 // Pass Thru to System FMP Protocol on same handle as FMP Protocol\r
f6f91d38 198 //\r
153f5c7a
KM
199 Status = gBS->HandleProtocol(\r
200 SystemFmpPrivate->Handle,\r
201 &gSystemFmpProtocolGuid,\r
202 (VOID **)&SystemFmp\r
203 );\r
f6f91d38
JY
204 if (EFI_ERROR(Status)) {\r
205 DEBUG((DEBUG_INFO, "(Agent)SetImage - SystemFmpProtocol - %r\n", Status));\r
206 SystemFmpPrivate->LastAttempt.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;\r
207 VarStatus = gRT->SetVariable(\r
208 SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,\r
209 &gSystemFmpLastAttemptVariableGuid,\r
210 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
211 sizeof(SystemFmpPrivate->LastAttempt),\r
212 &SystemFmpPrivate->LastAttempt\r
213 );\r
214 DEBUG((DEBUG_INFO, "(Agent)SetLastAttemp - %r\n", VarStatus));\r
215 return Status;\r
216 }\r
217\r
218 return SystemFmp->SetImage(SystemFmp, ImageIndex, Image, ImageSize, VendorCode, Progress, AbortReason);\r
219}\r
220\r
221/**\r
222 System FMP module entrypoint\r
223\r
224 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
225 @param[in] SystemTable A pointer to the EFI System Table.\r
226\r
227 @return EFI_SUCCESS System FMP module is initialized.\r
228**/\r
229EFI_STATUS\r
230EFIAPI\r
231SystemFirmwareReportMainDxe (\r
232 IN EFI_HANDLE ImageHandle,\r
233 IN EFI_SYSTEM_TABLE *SystemTable\r
234 )\r
235{\r
236 EFI_STATUS Status;\r
237\r
238 //\r
239 // Initialize SystemFmpPrivateData\r
240 //\r
241 mSystemFmpPrivate = AllocateZeroPool (sizeof(SYSTEM_FMP_PRIVATE_DATA));\r
242 if (mSystemFmpPrivate == NULL) {\r
243 return EFI_OUT_OF_RESOURCES;\r
244 }\r
245\r
246 Status = InitializePrivateData(mSystemFmpPrivate);\r
247 if (EFI_ERROR(Status)) {\r
248 FreePool(mSystemFmpPrivate);\r
249 mSystemFmpPrivate = NULL;\r
250 return Status;\r
251 }\r
252\r
253 //\r
254 // Install FMP protocol.\r
255 //\r
256 Status = gBS->InstallProtocolInterface (\r
257 &mSystemFmpPrivate->Handle,\r
258 &gEfiFirmwareManagementProtocolGuid,\r
259 EFI_NATIVE_INTERFACE,\r
260 &mSystemFmpPrivate->Fmp\r
261 );\r
262 if (EFI_ERROR (Status)) {\r
263 FreePool(mSystemFmpPrivate);\r
264 mSystemFmpPrivate = NULL;\r
265 return Status;\r
266 }\r
267\r
268 return Status;\r
269}\r