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