]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
e74a59151aea97c23f2d7905fc182dce1585fb32
[mirror_edk2.git] / MdeModulePkg / Universal / CapsuleRuntimeDxe / CapsuleService.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 CapsuleService.c
15
16 Abstract:
17
18 Capsule Runtime Service.
19
20 --*/
21
22 #include "CapsuleService.h"
23
24 EFI_STATUS
25 EFIAPI
26 UpdateCapsule (
27 IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
28 IN UINTN CapsuleCount,
29 IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
30 )
31 /*++
32
33 Routine Description:
34
35 This code finds whether the capsules need reset to update, if not, update immediately.
36
37 Arguments:
38
39 CapsuleHeaderArray A array of pointers to capsule headers passed in
40 CapsuleCount The number of capsule
41 ScatterGatherList Physical address of datablock list points to capsule
42
43 Returns:
44
45 EFI STATUS
46 EFI_SUCCESS Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is
47 not set, the capsule has been successfully processed by the firmware.
48 If it set, the ScattlerGatherList is successfully to be set.
49 EFI_INVALID_PARAMETER CapsuleCount is less than 1,CapsuleGuid is not supported.
50 EFI_DEVICE_ERROR Failed to SetVariable or AllocatePool or ProcessFirmwareVolume.
51
52 --*/
53 {
54 UINTN CapsuleSize;
55 UINTN ArrayNumber;
56 VOID *BufferPtr;
57 EFI_STATUS Status;
58 EFI_HANDLE FvHandle;
59 EFI_CAPSULE_HEADER *CapsuleHeader;
60
61 if (CapsuleCount < 1) {
62 return EFI_INVALID_PARAMETER;
63 }
64
65 BufferPtr = NULL;
66 CapsuleHeader = NULL;
67
68 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
69 //
70 // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
71 // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
72 //
73 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
74 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
75 return EFI_INVALID_PARAMETER;
76 }
77 //
78 // To remove this check. Capsule update supports non reset image.
79 //
80 // if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
81 // return EFI_UNSUPPORTED;
82 // }
83 }
84
85 //
86 // Check capsule guid is suppored by this platform. To do
87 //
88
89 //
90 //Assume that capsules have the same flags on reseting or not.
91 //
92 CapsuleHeader = CapsuleHeaderArray[0];
93
94 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
95 //
96 //Check if the platform supports update capsule across a system reset
97 //
98 if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {
99 return EFI_UNSUPPORTED;
100 }
101 //
102 // ScatterGatherList is only referenced if the capsules are defined to persist across
103 // system reset.
104 //
105 if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS) NULL) {
106 return EFI_INVALID_PARAMETER;
107 } else {
108 //
109 // ScatterGatherList is only referenced if the capsules are defined to persist across
110 // system reset. Set its value into NV storage to let pre-boot driver to pick it up
111 // after coming through a system reset.
112 //
113 Status = EfiSetVariable (
114 EFI_CAPSULE_VARIABLE_NAME,
115 &gEfiCapsuleVendorGuid,
116 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
117 sizeof (UINTN),
118 (VOID *) &ScatterGatherList
119 );
120 if (Status != EFI_SUCCESS) {
121 return Status;
122 }
123 }
124 return EFI_SUCCESS;
125 }
126
127 //
128 // The rest occurs in the condition of non-reset mode
129 // Current Runtime mode doesn't support the non-reset capsule image.
130 //
131 if (EfiAtRuntime ()) {
132 return EFI_INVALID_PARAMETER;
133 }
134
135 //
136 // Here should be in the boot-time for non-reset capsule image
137 // Default process to Update Capsule image into Flash for any guid image.
138 //
139 for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {
140 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
141 CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
142
143 BufferPtr = AllocatePool (CapsuleSize);
144 if (BufferPtr == NULL) {
145 return EFI_OUT_OF_RESOURCES;
146 }
147
148 CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize);
149
150 //
151 //Call DXE service ProcessFirmwareVolume to process immediatelly
152 //
153 Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle);
154 if (Status != EFI_SUCCESS) {
155 FreePool (BufferPtr);
156 return Status;
157 }
158 gDS->Dispatch ();
159 FreePool (BufferPtr);
160 }
161
162 return EFI_SUCCESS;
163 }
164
165
166
167 EFI_STATUS
168 EFIAPI
169 QueryCapsuleCapabilities (
170 IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
171 IN UINTN CapsuleCount,
172 OUT UINT64 *MaxiumCapsuleSize,
173 OUT EFI_RESET_TYPE *ResetType
174 )
175 /*++
176
177 Routine Description:
178
179 This code is to query about capsule capability.
180
181 Arguments:
182
183 CapsuleHeaderArray A array of pointers to capsule headers passed in
184 CapsuleCount The number of capsule
185 MaxiumCapsuleSize Max capsule size is supported
186 ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold.
187 If reset is needed, return EfiResetWarm.
188
189 Returns:
190
191 EFI STATUS
192 EFI_SUCCESS Valid answer returned
193 EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported.
194 EFI_UNSUPPORTED The capsule type is not supported.
195
196 --*/
197 {
198 UINTN ArrayNumber;
199 EFI_CAPSULE_HEADER *CapsuleHeader;
200
201 if (CapsuleCount < 1) {
202 return EFI_INVALID_PARAMETER;
203 }
204
205 if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {
206 return EFI_INVALID_PARAMETER;
207 }
208
209 CapsuleHeader = NULL;
210
211 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
212 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
213 //
214 // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
215 // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
216 //
217 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
218 return EFI_INVALID_PARAMETER;
219 }
220 //
221 // To remove this check. Capsule update supports non reset image.
222 //
223 // if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
224 // return EFI_UNSUPPORTED;
225 // }
226 }
227
228 //
229 //Assume that capsules have the same flags on reseting or not.
230 //
231 CapsuleHeader = CapsuleHeaderArray[0];
232 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
233 //
234 //Check if the platform supports update capsule across a system reset
235 //
236 if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {
237 return EFI_UNSUPPORTED;
238 }
239 *ResetType = EfiResetWarm;
240 *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule);
241 } else {
242 *ResetType = EfiResetCold;
243 *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule);
244 }
245 return EFI_SUCCESS;
246 }
247
248
249 EFI_STATUS
250 EFIAPI
251 CapsuleServiceInitialize (
252 IN EFI_HANDLE ImageHandle,
253 IN EFI_SYSTEM_TABLE *SystemTable
254 )
255 /*++
256
257 Routine Description:
258
259 This code is capsule runtime service initialization.
260
261 Arguments:
262
263 ImageHandle The image handle
264 SystemTable The system table.
265
266 Returns:
267
268 EFI STATUS
269
270 --*/
271 {
272 EFI_STATUS Status;
273 EFI_HANDLE NewHandle;
274
275 SystemTable->RuntimeServices->UpdateCapsule = UpdateCapsule;
276 SystemTable->RuntimeServices->QueryCapsuleCapabilities = QueryCapsuleCapabilities;
277
278 //
279 // Now install the Capsule Architectural Protocol on a new handle
280 //
281 NewHandle = NULL;
282
283 Status = gBS->InstallMultipleProtocolInterfaces (
284 &NewHandle,
285 &gEfiCapsuleArchProtocolGuid,
286 NULL,
287 NULL
288 );
289 ASSERT_EFI_ERROR (Status);
290
291 return EFI_SUCCESS;
292 }