]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
1. updated PCI/AGP Devices to check RemainingDevicePath in Supported() and Start...
[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
409d47b4 66 BOOLEAN NeedReset;\r
5d69642d
LG
67 \r
68 //\r
69 // Capsule Count can't be less than one.\r
70 //\r
74fea867 71 if (CapsuleCount < 1) {\r
72 return EFI_INVALID_PARAMETER;\r
73 }\r
409d47b4
LG
74 NeedReset = FALSE;\r
75 CapsuleHeader = NULL;\r
74fea867 76\r
77 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
d12f75fe
LG
78 //\r
79 // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have\r
80 // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.\r
81 //\r
74fea867 82 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
83 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
84 return EFI_INVALID_PARAMETER;\r
85 }\r
d12f75fe 86 //\r
6ee65722
LG
87 // Check Capsule image without populate flag by firmware support capsule function \r
88 //\r
89 if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && \r
90 (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {\r
91 return EFI_UNSUPPORTED;\r
92 }\r
74fea867 93 }\r
94\r
d12f75fe 95 //\r
409d47b4
LG
96 // Walk through all capsules, record whether there is a capsule \r
97 // needs reset. And then process capsules which has no reset flag directly.\r
5d69642d 98 //\r
409d47b4
LG
99 for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {\r
100 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
d12f75fe 101 //\r
409d47b4
LG
102 // Here should be in the boot-time for non-reset capsule image\r
103 // Platform specific update for the non-reset capsule image.\r
d12f75fe 104 //\r
409d47b4
LG
105 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {\r
106 if (EfiAtRuntime ()) { \r
107 Status = EFI_UNSUPPORTED;\r
108 } else {\r
109 Status = ProcessCapsuleImage(CapsuleHeader);\r
110 }\r
111 if (EFI_ERROR(Status)) {\r
d12f75fe 112 return Status;\r
74fea867 113 }\r
409d47b4
LG
114 } else {\r
115 NeedReset = TRUE;\r
74fea867 116 }\r
74fea867 117 }\r
409d47b4
LG
118 \r
119 //\r
120 // After launching all capsules who has no reset flag, if no more capsules claims\r
121 // for a system reset just return.\r
122 //\r
123 if (!NeedReset) {\r
124 return EFI_SUCCESS;\r
125 }\r
74fea867 126\r
127 //\r
409d47b4
LG
128 // ScatterGatherList is only referenced if the capsules are defined to persist across\r
129 // system reset. \r
74fea867 130 //\r
409d47b4
LG
131 if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {\r
132 return EFI_INVALID_PARAMETER;\r
74fea867 133 }\r
134\r
135 //\r
409d47b4 136 // Check if the platform supports update capsule across a system reset\r
74fea867 137 //\r
409d47b4
LG
138 if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {\r
139 return EFI_UNSUPPORTED;\r
74fea867 140 }\r
141\r
409d47b4
LG
142 //\r
143 // ScatterGatherList is only referenced if the capsules are defined to persist across\r
144 // system reset. Set its value into NV storage to let pre-boot driver to pick it up \r
145 // after coming through a system reset.\r
146 //\r
147 Status = gRT->SetVariable (\r
148 EFI_CAPSULE_VARIABLE_NAME,\r
149 &gEfiCapsuleVendorGuid,\r
150 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
151 sizeof (UINTN),\r
152 (VOID *) &ScatterGatherList\r
153 );\r
154\r
155 return Status;\r
74fea867 156}\r
157\r
5d69642d
LG
158/**\r
159 Returns if the capsule can be supported via UpdateCapsule().\r
160\r
161 @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules\r
162 being passed into update capsule.\r
163 @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in\r
164 CaspuleHeaderArray.\r
165 @param MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can\r
166 support as an argument to UpdateCapsule() via\r
167 CapsuleHeaderArray and ScatterGatherList.\r
168 @param ResetType Returns the type of reset required for the capsule update.\r
74fea867 169\r
5d69642d
LG
170 @retval EFI_SUCCESS Valid answer returned.\r
171 @retval EFI_UNSUPPORTED The capsule image is not supported on this platform, and\r
172 MaximumCapsuleSize and ResetType are undefined.\r
173 @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL, or ResetTyep is NULL,\r
174 Or CapsuleCount is Zero, or CapsuleImage is not valid.\r
74fea867 175\r
5d69642d 176**/\r
74fea867 177EFI_STATUS\r
178EFIAPI\r
179QueryCapsuleCapabilities (\r
180 IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
181 IN UINTN CapsuleCount,\r
182 OUT UINT64 *MaxiumCapsuleSize,\r
183 OUT EFI_RESET_TYPE *ResetType\r
184 )\r
74fea867 185{\r
186 UINTN ArrayNumber;\r
187 EFI_CAPSULE_HEADER *CapsuleHeader;\r
188\r
5d69642d
LG
189 //\r
190 // Capsule Count can't be less than one.\r
191 //\r
74fea867 192 if (CapsuleCount < 1) {\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
5d69642d
LG
195 \r
196 //\r
197 // Check whether input paramter is valid\r
198 //\r
74fea867 199 if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {\r
200 return EFI_INVALID_PARAMETER;\r
201 }\r
202\r
203 CapsuleHeader = NULL;\r
204\r
205 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
206 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
d12f75fe
LG
207 //\r
208 // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have\r
209 // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.\r
210 //\r
74fea867 211 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
212 return EFI_INVALID_PARAMETER;\r
213 }\r
d12f75fe 214 //\r
5d69642d 215 // Check Capsule image without populate flag is supported by firmware\r
6ee65722
LG
216 //\r
217 if (((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) && \r
218 (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS)) {\r
219 return EFI_UNSUPPORTED;\r
220 }\r
74fea867 221 }\r
222\r
223 //\r
5d69642d 224 // Assume that capsules have the same flags on reseting or not.\r
74fea867 225 //\r
226 CapsuleHeader = CapsuleHeaderArray[0];\r
227 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
228 //\r
229 //Check if the platform supports update capsule across a system reset\r
230 //\r
109e9a61 231 if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {\r
74fea867 232 return EFI_UNSUPPORTED;\r
233 }\r
5c526736 234 *ResetType = EfiResetWarm; \r
74fea867 235 } else {\r
5d69642d
LG
236 //\r
237 // For non-reset capsule image.\r
238 //\r
74fea867 239 *ResetType = EfiResetCold;\r
5c526736
LG
240 }\r
241 \r
242 //\r
243 // The support max capsule image size\r
244 //\r
245 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
97b2c9b5 246 *MaxiumCapsuleSize = PcdGet32(PcdMaxSizePopulateCapsule);\r
5c526736 247 } else {\r
97b2c9b5 248 *MaxiumCapsuleSize = PcdGet32(PcdMaxSizeNonPopulateCapsule);\r
74fea867 249 }\r
5c526736 250\r
74fea867 251 return EFI_SUCCESS;\r
252}\r
253\r
254\r
5d69642d
LG
255/**\r
256\r
109e9a61 257 This code installs UEFI capsule runtime service.\r
5d69642d
LG
258\r
259 @param ImageHandle The firmware allocated handle for the EFI image. \r
260 @param SystemTable A pointer to the EFI System Table.\r
261\r
262 @retval EFI_SUCCESS UEFI Capsule Runtime Services are installed successfully. \r
263\r
264**/\r
74fea867 265EFI_STATUS\r
266EFIAPI\r
267CapsuleServiceInitialize (\r
268 IN EFI_HANDLE ImageHandle,\r
269 IN EFI_SYSTEM_TABLE *SystemTable\r
270 )\r
74fea867 271{\r
272 EFI_STATUS Status;\r
273 EFI_HANDLE NewHandle;\r
5d69642d
LG
274 \r
275 //\r
276 // Install capsule runtime services into UEFI runtime service tables.\r
277 //\r
109e9a61
LG
278 gRT->UpdateCapsule = UpdateCapsule;\r
279 gRT->QueryCapsuleCapabilities = QueryCapsuleCapabilities;\r
74fea867 280\r
281 //\r
5d69642d
LG
282 // Install the Capsule Architectural Protocol on a new handle\r
283 // to signify the capsule runtime services are ready.\r
74fea867 284 //\r
285 NewHandle = NULL;\r
286\r
287 Status = gBS->InstallMultipleProtocolInterfaces (\r
288 &NewHandle,\r
289 &gEfiCapsuleArchProtocolGuid,\r
290 NULL,\r
291 NULL\r
292 );\r
293 ASSERT_EFI_ERROR (Status);\r
294\r
295 return EFI_SUCCESS;\r
296}\r