]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
Code scrub for the Capsule, SecurityStub, and Crc32 library instance.
[mirror_edk2.git] / MdeModulePkg / Universal / CapsuleRuntimeDxe / CapsuleService.c
CommitLineData
13d40edd 1/** @file\r
5d69642d
LG
2 Capsule Runtime Drivers produces two UEFI capsule runtime services.\r
3 (UpdateCapsule, QueryCapsuleCapabilities)\r
74fea867 4\r
13d40edd 5Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
74fea867 6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
13d40edd 14**/\r
74fea867 15\r
16#include "CapsuleService.h"\r
17\r
5d69642d
LG
18/**\r
19 Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended\r
20 consumption, the firmware may process the capsule immediately. If the payload should persist\r
21 across a system reset, the reset value returned from EFI_QueryCapsuleCapabilities must\r
22 be passed into ResetSystem() and will cause the capsule to be processed by the firmware as\r
23 part of the reset process.\r
24\r
25 @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules\r
26 being passed into update capsule.\r
27 @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in\r
28 CaspuleHeaderArray.\r
29 @param ScatterGatherList Physical pointer to a set of\r
30 EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the\r
31 location in physical memory of a set of capsules.\r
32\r
33 @retval EFI_SUCCESS Valid capsule was passed. If\r
34 CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the\r
35 capsule has been successfully processed by the firmware.\r
36 @retval EFI_DEVICE_ERROR The capsule update was started, but failed due to a device error.\r
37 @retval EFI_INVALID_PARAMETER CapsuleCount is Zero, or CapsuleImage is not valid.\r
38 For across reset capsule image, ScatterGatherList is NULL.\r
39 @retval EFI_UNSUPPORTED CapsuleImage is not recognized by the firmware.\r
40\r
41**/\r
74fea867 42EFI_STATUS\r
43EFIAPI\r
44UpdateCapsule (\r
45 IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
46 IN UINTN CapsuleCount,\r
47 IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL\r
48 )\r
74fea867 49{\r
74fea867 50 UINTN ArrayNumber;\r
74fea867 51 EFI_STATUS Status;\r
74fea867 52 EFI_CAPSULE_HEADER *CapsuleHeader;\r
5d69642d
LG
53 \r
54 //\r
55 // Capsule Count can't be less than one.\r
56 //\r
74fea867 57 if (CapsuleCount < 1) {\r
58 return EFI_INVALID_PARAMETER;\r
59 }\r
60\r
74fea867 61 CapsuleHeader = NULL;\r
62\r
63 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
d12f75fe
LG
64 //\r
65 // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have\r
66 // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.\r
67 //\r
74fea867 68 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
69 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
70 return EFI_INVALID_PARAMETER;\r
71 }\r
d12f75fe 72 //\r
6ee65722
LG
73 // Check Capsule image without populate flag by firmware support capsule function \r
74 //\r
75 if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && \r
76 (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {\r
77 return EFI_UNSUPPORTED;\r
78 }\r
74fea867 79 }\r
80\r
d12f75fe 81 //\r
6ee65722 82 // Assume that capsules have the same flags on reseting or not.\r
74fea867 83 //\r
84 CapsuleHeader = CapsuleHeaderArray[0];\r
5d69642d
LG
85 \r
86 //\r
87 // Process across reset capsule image.\r
88 //\r
74fea867 89 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
90 //\r
6ee65722 91 // Check if the platform supports update capsule across a system reset\r
74fea867 92 //\r
93 if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {\r
94 return EFI_UNSUPPORTED;\r
95 }\r
d12f75fe
LG
96 //\r
97 // ScatterGatherList is only referenced if the capsules are defined to persist across\r
98 // system reset. \r
99 //\r
1be0dda6 100 if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {\r
74fea867 101 return EFI_INVALID_PARAMETER;\r
102 } else {\r
d12f75fe
LG
103 //\r
104 // ScatterGatherList is only referenced if the capsules are defined to persist across\r
105 // system reset. Set its value into NV storage to let pre-boot driver to pick it up \r
106 // after coming through a system reset.\r
107 //\r
74fea867 108 Status = EfiSetVariable (\r
109 EFI_CAPSULE_VARIABLE_NAME,\r
110 &gEfiCapsuleVendorGuid,\r
111 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
112 sizeof (UINTN),\r
113 (VOID *) &ScatterGatherList\r
114 );\r
115 if (Status != EFI_SUCCESS) {\r
d12f75fe 116 return Status;\r
74fea867 117 }\r
6ee65722 118 //\r
5d69642d 119 // Successfully set the capsule image address into EFI variable.\r
6ee65722
LG
120 //\r
121 return EFI_SUCCESS;\r
74fea867 122 }\r
74fea867 123 }\r
124\r
125 //\r
5d69642d 126 // Process the non-reset capsule image.\r
74fea867 127 //\r
128 if (EfiAtRuntime ()) {\r
5d69642d
LG
129 //\r
130 // Runtime mode doesn't support the non-reset capsule image.\r
131 //\r
17b87537 132 return EFI_UNSUPPORTED;\r
74fea867 133 }\r
134\r
135 //\r
d12f75fe 136 // Here should be in the boot-time for non-reset capsule image\r
5d69642d 137 // Platform specific update for the non-reset capsule image.\r
74fea867 138 //\r
5d69642d 139 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
6ee65722
LG
140 Status = ProcessCapsuleImage (CapsuleHeaderArray[ArrayNumber]);\r
141 if (EFI_ERROR (Status)) {\r
d12f75fe 142 return Status;\r
74fea867 143 }\r
74fea867 144 }\r
145\r
146 return EFI_SUCCESS;\r
147}\r
148\r
5d69642d
LG
149/**\r
150 Returns if the capsule can be supported via UpdateCapsule().\r
151\r
152 @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules\r
153 being passed into update capsule.\r
154 @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in\r
155 CaspuleHeaderArray.\r
156 @param MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can\r
157 support as an argument to UpdateCapsule() via\r
158 CapsuleHeaderArray and ScatterGatherList.\r
159 @param ResetType Returns the type of reset required for the capsule update.\r
74fea867 160\r
5d69642d
LG
161 @retval EFI_SUCCESS Valid answer returned.\r
162 @retval EFI_UNSUPPORTED The capsule image is not supported on this platform, and\r
163 MaximumCapsuleSize and ResetType are undefined.\r
164 @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL, or ResetTyep is NULL,\r
165 Or CapsuleCount is Zero, or CapsuleImage is not valid.\r
74fea867 166\r
5d69642d 167**/\r
74fea867 168EFI_STATUS\r
169EFIAPI\r
170QueryCapsuleCapabilities (\r
171 IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
172 IN UINTN CapsuleCount,\r
173 OUT UINT64 *MaxiumCapsuleSize,\r
174 OUT EFI_RESET_TYPE *ResetType\r
175 )\r
74fea867 176{\r
177 UINTN ArrayNumber;\r
178 EFI_CAPSULE_HEADER *CapsuleHeader;\r
179\r
5d69642d
LG
180 //\r
181 // Capsule Count can't be less than one.\r
182 //\r
74fea867 183 if (CapsuleCount < 1) {\r
184 return EFI_INVALID_PARAMETER;\r
185 }\r
5d69642d
LG
186 \r
187 //\r
188 // Check whether input paramter is valid\r
189 //\r
74fea867 190 if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {\r
191 return EFI_INVALID_PARAMETER;\r
192 }\r
193\r
194 CapsuleHeader = NULL;\r
195\r
196 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
197 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
d12f75fe
LG
198 //\r
199 // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have\r
200 // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.\r
201 //\r
74fea867 202 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
203 return EFI_INVALID_PARAMETER;\r
204 }\r
d12f75fe 205 //\r
5d69642d 206 // Check Capsule image without populate flag is supported by firmware\r
6ee65722
LG
207 //\r
208 if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && \r
209 (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {\r
210 return EFI_UNSUPPORTED;\r
211 }\r
74fea867 212 }\r
213\r
214 //\r
5d69642d 215 // Assume that capsules have the same flags on reseting or not.\r
74fea867 216 //\r
217 CapsuleHeader = CapsuleHeaderArray[0];\r
218 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
219 //\r
220 //Check if the platform supports update capsule across a system reset\r
221 //\r
222 if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {\r
223 return EFI_UNSUPPORTED;\r
224 }\r
225 *ResetType = EfiResetWarm;\r
226 *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule);\r
227 } else {\r
5d69642d
LG
228 //\r
229 // For non-reset capsule image.\r
230 //\r
74fea867 231 *ResetType = EfiResetCold;\r
232 *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule);\r
233 }\r
234 return EFI_SUCCESS;\r
235}\r
236\r
237\r
5d69642d
LG
238/**\r
239\r
240 This code is to install UEFI capsule runtime service.\r
241\r
242 @param ImageHandle The firmware allocated handle for the EFI image. \r
243 @param SystemTable A pointer to the EFI System Table.\r
244\r
245 @retval EFI_SUCCESS UEFI Capsule Runtime Services are installed successfully. \r
246\r
247**/\r
74fea867 248EFI_STATUS\r
249EFIAPI\r
250CapsuleServiceInitialize (\r
251 IN EFI_HANDLE ImageHandle,\r
252 IN EFI_SYSTEM_TABLE *SystemTable\r
253 )\r
74fea867 254{\r
255 EFI_STATUS Status;\r
256 EFI_HANDLE NewHandle;\r
5d69642d
LG
257 \r
258 //\r
259 // Install capsule runtime services into UEFI runtime service tables.\r
260 //\r
74fea867 261 SystemTable->RuntimeServices->UpdateCapsule = UpdateCapsule;\r
262 SystemTable->RuntimeServices->QueryCapsuleCapabilities = QueryCapsuleCapabilities;\r
263\r
264 //\r
5d69642d
LG
265 // Install the Capsule Architectural Protocol on a new handle\r
266 // to signify the capsule runtime services are ready.\r
74fea867 267 //\r
268 NewHandle = NULL;\r
269\r
270 Status = gBS->InstallMultipleProtocolInterfaces (\r
271 &NewHandle,\r
272 &gEfiCapsuleArchProtocolGuid,\r
273 NULL,\r
274 NULL\r
275 );\r
276 ASSERT_EFI_ERROR (Status);\r
277\r
278 return EFI_SUCCESS;\r
279}\r