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