]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/Capsules.c
Add pragma(1) to the structure of BM_LEGACY_DEV_ORDER_CONTEXT:
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / Capsules.c
CommitLineData
93e3992d 1/*++\r
2\r
3Copyright (c) 2004 - 2008, 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 Capsules.c\r
15\r
16Abstract:\r
17\r
18 BDS routines to handle capsules.\r
19\r
20--*/\r
21#include "Bds.h"\r
22\r
23VOID\r
24BdsLockFv (\r
25 IN EFI_CPU_IO_PROTOCOL *CpuIo,\r
26 IN EFI_PHYSICAL_ADDRESS Base\r
27 )\r
28{\r
29 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
30 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
31 EFI_PHYSICAL_ADDRESS BaseAddress;\r
32 UINT8 Data;\r
33 UINT32 BlockLength;\r
34 UINTN Index;\r
35\r
36 BaseAddress = Base - 0x400000 + 2;\r
37 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));\r
38 BlockMap = &(FvHeader->BlockMap[0]);\r
39\r
40 while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {\r
41 BlockLength = BlockMap->Length;\r
42 for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
43 CpuIo->Mem.Read (\r
44 CpuIo,\r
45 EfiCpuIoWidthUint8,\r
46 BaseAddress,\r
47 1,\r
48 &Data\r
49 );\r
50 Data = (UINT8) (Data | 0x3);\r
51 CpuIo->Mem.Write (\r
52 CpuIo,\r
53 EfiCpuIoWidthUint8,\r
54 BaseAddress,\r
55 1,\r
56 &Data\r
57 );\r
58 BaseAddress += BlockLength;\r
59 }\r
60\r
61 BlockMap++;\r
62 }\r
63}\r
64\r
65EFI_STATUS\r
66ProcessCapsules (\r
67 EFI_BOOT_MODE BootMode\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73 This routine is called to see if there are any capsules we need to process.\r
74 If the boot mode is not UPDATE, then we do nothing. Otherwise find the\r
75 capsule HOBS and produce firmware volumes for them via the DXE service.\r
76 Then call the dispatcher to dispatch drivers from them. Finally, check\r
77 the status of the updates.\r
78\r
79Arguments:\r
80\r
81 BootMode - the current boot mode\r
82\r
83Returns:\r
84\r
85 EFI_INVALID_PARAMETER - boot mode is not correct for an update\r
86\r
87Note:\r
88\r
89 This function should be called by BDS in case we need to do some\r
90 sort of processing even if there is no capsule to process. We\r
91 need to do this if an earlier update went awry and we need to\r
92 clear the capsule variable so on the next reset PEI does not see it and\r
93 think there is a capsule available.\r
94\r
95--*/\r
96{\r
97 EFI_STATUS Status;\r
98 EFI_PEI_HOB_POINTERS HobPointer;\r
99 EFI_CAPSULE_HEADER *CapsuleHeader;\r
100 UINT32 Size;\r
101 UINT32 CapsuleNumber;\r
102 UINT32 CapsuleTotalNumber;\r
103 EFI_CAPSULE_TABLE *CapsuleTable;\r
104 UINT32 Index;\r
105 UINT32 CacheIndex;\r
106 UINT32 CacheNumber;\r
107 VOID **CapsulePtr;\r
108 VOID **CapsulePtrCache;\r
109 EFI_GUID *CapsuleGuidCache; \r
110 CAPSULE_HOB_INFO *CapsuleHobInfo;\r
111\r
112 CapsuleNumber = 0;\r
113 CapsuleTotalNumber = 0;\r
114 CacheIndex = 0;\r
115 CacheNumber = 0;\r
116 CapsulePtr = NULL;\r
117 CapsulePtrCache = NULL;\r
118 CapsuleGuidCache = NULL;\r
119\r
120 //\r
121 // We don't do anything else if the boot mode is not flash-update\r
122 //\r
123 if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
124 return EFI_INVALID_PARAMETER;\r
125 }\r
126 \r
127 Status = EFI_SUCCESS;\r
128 //\r
129 // Find all capsule images from hob\r
130 //\r
131 HobPointer.Raw = GetHobList ();\r
132 while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
133 CapsuleTotalNumber ++;\r
134\r
135 HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
136 }\r
137 \r
138 if (CapsuleTotalNumber == 0) {\r
139 //\r
140 // We didn't find a hob, so had no errors.\r
141 //\r
142 PlatformBdsLockNonUpdatableFlash ();\r
143 return EFI_SUCCESS;\r
144 }\r
145 \r
146 //\r
147 // Init temp Capsule Data table.\r
148 //\r
149 CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
150 ASSERT (CapsulePtr != NULL);\r
151 CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
152 ASSERT (CapsulePtrCache != NULL);\r
153 CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);\r
154 ASSERT (CapsuleGuidCache != NULL);\r
155 \r
156 //\r
157 // Find all capsule images from hob\r
158 //\r
159 HobPointer.Raw = GetHobList ();\r
160 while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
161 CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);\r
162 CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);\r
163\r
164 HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
165 }\r
166\r
167 //\r
168 //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
169 //capsuleTable to configure table with EFI_CAPSULE_GUID\r
170 //\r
171\r
172 //\r
173 // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
174 // System to have information persist across a system reset. EFI System Table must \r
175 // point to an array of capsules that contains the same CapsuleGuid value. And agents\r
176 // searching for this type capsule will look in EFI System Table and search for the \r
177 // capsule's Guid and associated pointer to retrieve the data. Two steps below describes\r
178 // how to sorting the capsules by the unique guid and install the array to EFI System Table. \r
179 // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an \r
180 // array for later sorting capsules by CapsuleGuid.\r
181 //\r
182 for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
183 CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
184 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
185 //\r
186 // For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
187 // If already has the Guid, skip it. Whereas, record it in the CacheArray as \r
188 // an additional one.\r
189 //\r
190 CacheIndex = 0;\r
191 while (CacheIndex < CacheNumber) {\r
192 if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {\r
193 break;\r
194 }\r
195 CacheIndex++;\r
196 }\r
197 if (CacheIndex == CacheNumber) {\r
198 CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));\r
199 }\r
200 }\r
201 }\r
202\r
203 //\r
204 // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules\r
205 // whose guid is the same as it, and malloc memory for an array which preceding\r
206 // with UINT32. The array fills with entry point of capsules that have the same\r
207 // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install\r
208 // this array into EFI System Table, so that agents searching for this type capsule\r
209 // will look in EFI System Table and search for the capsule's Guid and associated\r
210 // pointer to retrieve the data.\r
211 //\r
212 CacheIndex = 0;\r
213 while (CacheIndex < CacheNumber) {\r
214 CapsuleNumber = 0; \r
215 for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
216 CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
217 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
218 if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
219 //\r
220 // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
221 //\r
222 CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
223 }\r
224 }\r
225 }\r
226 if (CapsuleNumber != 0) {\r
227 Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*); \r
228 CapsuleTable = AllocateRuntimePool (Size);\r
229 ASSERT (CapsuleTable != NULL);\r
230 CapsuleTable->CapsuleArrayNumber = CapsuleNumber;\r
231 CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
232 Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
233 ASSERT_EFI_ERROR (Status);\r
234 }\r
235 CacheIndex++;\r
236 }\r
237\r
238 //\r
239 // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are\r
240 // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash \r
241 // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional\r
242 // type capsule transaction could be extended. It depends on platform policy.\r
243 //\r
244 for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
245 CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
246 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
247 //\r
248 // Call capsule library to process capsule image.\r
249 //\r
250 ProcessCapsuleImage (CapsuleHeader);\r
251 }\r
252 }\r
253\r
254 PlatformBdsLockNonUpdatableFlash ();\r
255 \r
256 //\r
257 // Free the allocated temp memory space.\r
258 //\r
259 FreePool (CapsuleGuidCache);\r
260 FreePool (CapsulePtrCache);\r
261 FreePool (CapsulePtr);\r
262\r
263 return Status;\r
264}\r