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