1. Sync the latest network stack. Add NetLibCreateIPv4DPathNode () in netlib library.
[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
69 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
70 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
71 return EFI_INVALID_PARAMETER;\r
72 }\r
73 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
74 return EFI_UNSUPPORTED;\r
75 }\r
76 }\r
77\r
78 //\r
79 //Assume that capsules have the same flags on reseting or not.\r
80 //\r
81 CapsuleHeader = CapsuleHeaderArray[0];\r
82\r
83 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
84 //\r
85 //Check if the platform supports update capsule across a system reset\r
86 //\r
87 if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {\r
88 return EFI_UNSUPPORTED;\r
89 }\r
90\r
91 if (ScatterGatherList == 0) {\r
92 return EFI_INVALID_PARAMETER;\r
93 } else {\r
94 Status = EfiSetVariable (\r
95 EFI_CAPSULE_VARIABLE_NAME,\r
96 &gEfiCapsuleVendorGuid,\r
97 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
98 sizeof (UINTN),\r
99 (VOID *) &ScatterGatherList\r
100 );\r
101 if (Status != EFI_SUCCESS) {\r
102 return EFI_DEVICE_ERROR;\r
103 }\r
104 }\r
105 return EFI_SUCCESS;\r
106 }\r
107\r
108 //\r
109 //The rest occurs in the condition of non-reset mode\r
110 //\r
111 if (EfiAtRuntime ()) {\r
112 return EFI_INVALID_PARAMETER;\r
113 }\r
114\r
115 //\r
116 //Here should be in the boot-time\r
117 //\r
118 for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {\r
119 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
120 CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;\r
121\r
122 BufferPtr = AllocatePool (CapsuleSize);\r
123 if (BufferPtr == NULL) {\r
124 return EFI_DEVICE_ERROR;\r
125 }\r
126\r
127 CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize);\r
128\r
129 //\r
130 //Call DXE service ProcessFirmwareVolume to process immediatelly\r
131 //\r
132 Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle);\r
133 if (Status != EFI_SUCCESS) {\r
134 FreePool (BufferPtr);\r
135 return EFI_DEVICE_ERROR;\r
136 }\r
137 gDS->Dispatch ();\r
138 FreePool (BufferPtr);\r
139 }\r
140\r
141 return EFI_SUCCESS;\r
142}\r
143\r
144\r
145\r
146EFI_STATUS\r
147EFIAPI\r
148QueryCapsuleCapabilities (\r
149 IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,\r
150 IN UINTN CapsuleCount,\r
151 OUT UINT64 *MaxiumCapsuleSize,\r
152 OUT EFI_RESET_TYPE *ResetType\r
153 )\r
154/*++\r
155\r
156Routine Description:\r
157\r
158 This code is to query about capsule capability.\r
159\r
160Arguments:\r
161\r
162 CapsuleHeaderArray A array of pointers to capsule headers passed in\r
163 CapsuleCount The number of capsule\r
164 MaxiumCapsuleSize Max capsule size is supported\r
165 ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold.\r
166 If reset is needed, return EfiResetWarm.\r
167\r
168Returns:\r
169\r
170 EFI STATUS\r
171 EFI_SUCCESS Valid answer returned\r
172 EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported.\r
173 EFI_UNSUPPORTED The capsule type is not supported.\r
174\r
175--*/\r
176{\r
177 UINTN ArrayNumber;\r
178 EFI_CAPSULE_HEADER *CapsuleHeader;\r
179\r
180 if (CapsuleCount < 1) {\r
181 return EFI_INVALID_PARAMETER;\r
182 }\r
183\r
184 if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {\r
185 return EFI_INVALID_PARAMETER;\r
186 }\r
187\r
188 CapsuleHeader = NULL;\r
189\r
190 for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {\r
191 CapsuleHeader = CapsuleHeaderArray[ArrayNumber];\r
192 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
195 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
196 return EFI_UNSUPPORTED;\r
197 }\r
198 }\r
199\r
200 //\r
201 //Assume that capsules have the same flags on reseting or not.\r
202 //\r
203 CapsuleHeader = CapsuleHeaderArray[0];\r
204 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
205 //\r
206 //Check if the platform supports update capsule across a system reset\r
207 //\r
208 if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) {\r
209 return EFI_UNSUPPORTED;\r
210 }\r
211 *ResetType = EfiResetWarm;\r
212 *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule);\r
213 } else {\r
214 *ResetType = EfiResetCold;\r
215 *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule);\r
216 }\r
217 return EFI_SUCCESS;\r
218}\r
219\r
220\r
221EFI_STATUS\r
222EFIAPI\r
223CapsuleServiceInitialize (\r
224 IN EFI_HANDLE ImageHandle,\r
225 IN EFI_SYSTEM_TABLE *SystemTable\r
226 )\r
227/*++\r
228\r
229Routine Description:\r
230\r
231 This code is capsule runtime service initialization.\r
232\r
233Arguments:\r
234\r
235 ImageHandle The image handle\r
236 SystemTable The system table.\r
237\r
238Returns:\r
239\r
240 EFI STATUS\r
241\r
242--*/\r
243{\r
244 EFI_STATUS Status;\r
245 EFI_HANDLE NewHandle;\r
246\r
247 SystemTable->RuntimeServices->UpdateCapsule = UpdateCapsule;\r
248 SystemTable->RuntimeServices->QueryCapsuleCapabilities = QueryCapsuleCapabilities;\r
249\r
250 //\r
251 // Now install the Capsule Architectural Protocol on a new handle\r
252 //\r
253 NewHandle = NULL;\r
254\r
255 Status = gBS->InstallMultipleProtocolInterfaces (\r
256 &NewHandle,\r
257 &gEfiCapsuleArchProtocolGuid,\r
258 NULL,\r
259 NULL\r
260 );\r
261 ASSERT_EFI_ERROR (Status);\r
262\r
263 return EFI_SUCCESS;\r
264}\r