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