Adjust directory structures.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / CapsuleRuntimeDxe / CapsuleService.c
1 /*++\r
2 \r
3 Copyright (c) 2006 - 2007, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   CapsuleService.c\r
15 \r
16 Abstract:\r
17 \r
18   Capsule Runtime Service.\r
19 \r
20 --*/\r
21 \r
22 #include "CapsuleService.h"\r
23 \r
24 EFI_STATUS\r
25 EFIAPI\r
26 UpdateCapsule (\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
33 Routine Description:\r
34 \r
35   This code finds whether the capsules need reset to update, if not, update immediately.\r
36 \r
37 Arguments:\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
43 Returns:\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
146 EFI_STATUS\r
147 EFIAPI\r
148 QueryCapsuleCapabilities (\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
156 Routine Description:\r
157 \r
158   This code is to query about capsule capability.\r
159 \r
160 Arguments:\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
168 Returns:\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
221 EFI_STATUS\r
222 EFIAPI\r
223 CapsuleServiceInitialize (\r
224   IN EFI_HANDLE         ImageHandle,\r
225   IN EFI_SYSTEM_TABLE   *SystemTable\r
226   )\r
227 /*++\r
228 \r
229 Routine Description:\r
230 \r
231   This code is capsule runtime service initialization.\r
232 \r
233 Arguments:\r
234 \r
235   ImageHandle          The image handle\r
236   SystemTable          The system table.\r
237 \r
238 Returns:\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