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