]> git.proxmox.com Git - mirror_edk2.git/blob - Nt32Pkg/Sec/FwVol.c
UefiCpuPkg: Remove double \r
[mirror_edk2.git] / Nt32Pkg / Sec / FwVol.c
1 /**@file
2
3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 Module Name:
7 FwVol.c
8
9 Abstract:
10 A simple FV stack so the SEC can extract the SEC Core from an
11 FV.
12
13 **/
14
15 #include "SecMain.h"
16
17 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
18 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
19
20 EFI_FFS_FILE_STATE
21 GetFileState (
22 IN UINT8 ErasePolarity,
23 IN EFI_FFS_FILE_HEADER *FfsHeader
24 )
25 /*++
26
27 Routine Description:
28 Returns the highest bit set of the State field
29
30 Arguments:
31 ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY
32 in the Attributes field.
33 FfsHeader - Pointer to FFS File Header.
34
35 Returns:
36 Returns the highest bit in the State field
37
38 --*/
39 {
40 EFI_FFS_FILE_STATE FileState;
41 EFI_FFS_FILE_STATE HighestBit;
42
43 FileState = FfsHeader->State;
44
45 if (ErasePolarity != 0) {
46 FileState = (EFI_FFS_FILE_STATE)~FileState;
47 }
48
49 HighestBit = 0x80;
50 while (HighestBit != 0 && (HighestBit & FileState) == 0) {
51 HighestBit >>= 1;
52 }
53
54 return HighestBit;
55 }
56
57 UINT8
58 CalculateHeaderChecksum (
59 IN EFI_FFS_FILE_HEADER *FileHeader
60 )
61 /*++
62
63 Routine Description:
64 Calculates the checksum of the header of a file.
65
66 Arguments:
67 FileHeader - Pointer to FFS File Header.
68
69 Returns:
70 Checksum of the header.
71
72 --*/
73 {
74 UINT8 *ptr;
75 UINTN Index;
76 UINT8 Sum;
77
78 Sum = 0;
79 ptr = (UINT8 *) FileHeader;
80
81 for (Index = 0; Index < sizeof (EFI_FFS_FILE_HEADER) - 3; Index += 4) {
82 Sum = (UINT8) (Sum + ptr[Index]);
83 Sum = (UINT8) (Sum + ptr[Index + 1]);
84 Sum = (UINT8) (Sum + ptr[Index + 2]);
85 Sum = (UINT8) (Sum + ptr[Index + 3]);
86 }
87
88 for (; Index < sizeof (EFI_FFS_FILE_HEADER); Index++) {
89 Sum = (UINT8) (Sum + ptr[Index]);
90 }
91 //
92 // State field (since this indicates the different state of file).
93 //
94 Sum = (UINT8) (Sum - FileHeader->State);
95 //
96 // Checksum field of the file is not part of the header checksum.
97 //
98 Sum = (UINT8) (Sum - FileHeader->IntegrityCheck.Checksum.File);
99
100 return Sum;
101 }
102
103 EFI_STATUS
104 SecFfsFindNextFile (
105 IN EFI_FV_FILETYPE SearchType,
106 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
107 IN OUT EFI_FFS_FILE_HEADER **FileHeader
108 )
109 /*++
110
111 Routine Description:
112 Given the input file pointer, search for the next matching file in the
113 FFS volume as defined by SearchType. The search starts from FileHeader inside
114 the Firmware Volume defined by FwVolHeader.
115
116 Arguments:
117 SearchType - Filter to find only files of this type.
118 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
119 FwVolHeader - Pointer to the FV header of the volume to search.
120 This parameter must point to a valid FFS volume.
121 FileHeader - Pointer to the current file from which to begin searching.
122 This pointer will be updated upon return to reflect the file
123 found.
124
125 Returns:
126 EFI_NOT_FOUND - No files matching the search criteria were found
127 EFI_SUCCESS
128
129 --*/
130 {
131 EFI_FFS_FILE_HEADER *FfsFileHeader;
132 UINT32 FileLength;
133 UINT32 FileOccupiedSize;
134 UINT32 FileOffset;
135 UINT64 FvLength;
136 UINT8 ErasePolarity;
137 UINT8 FileState;
138
139 FvLength = FwVolHeader->FvLength;
140 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
141 ErasePolarity = 1;
142 } else {
143 ErasePolarity = 0;
144 }
145 //
146 // If FileHeader is not specified (NULL) start with the first file in the
147 // firmware volume. Otherwise, start from the FileHeader.
148 //
149 if (*FileHeader == NULL) {
150 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolHeader + FwVolHeader->HeaderLength);
151 } else {
152 //
153 // Length is 24 bits wide so mask upper 8 bits
154 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
155 //
156 FileLength = *(UINT32 *) (*FileHeader)->Size & 0x00FFFFFF;
157 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
158 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) *FileHeader + FileOccupiedSize);
159 }
160
161 FileOffset = (UINT32) ((UINT8 *) FfsFileHeader - (UINT8 *) FwVolHeader);
162
163 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
164 //
165 // Get FileState which is the highest bit of the State
166 //
167 FileState = GetFileState (ErasePolarity, FfsFileHeader);
168
169 switch (FileState) {
170
171 case EFI_FILE_HEADER_INVALID:
172 FileOffset += sizeof (EFI_FFS_FILE_HEADER);
173 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
174 break;
175
176 case EFI_FILE_DATA_VALID:
177 case EFI_FILE_MARKED_FOR_UPDATE:
178 if (CalculateHeaderChecksum (FfsFileHeader) == 0) {
179 FileLength = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
180 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
181
182 if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) {
183
184 *FileHeader = FfsFileHeader;
185
186 return EFI_SUCCESS;
187 }
188
189 FileOffset += FileOccupiedSize;
190 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
191 } else {
192 return EFI_NOT_FOUND;
193 }
194 break;
195
196 case EFI_FILE_DELETED:
197 FileLength = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
198 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
199 FileOffset += FileOccupiedSize;
200 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
201 break;
202
203 default:
204 return EFI_NOT_FOUND;
205
206 }
207 }
208
209 return EFI_NOT_FOUND;
210 }
211
212 EFI_STATUS
213 SecFfsFindSectionData (
214 IN EFI_SECTION_TYPE SectionType,
215 IN EFI_FFS_FILE_HEADER *FfsFileHeader,
216 IN OUT VOID **SectionData
217 )
218 /*++
219
220 Routine Description:
221 Given the input file pointer, search for the next matching section in the
222 FFS volume.
223
224 Arguments:
225 SearchType - Filter to find only sections of this type.
226 FfsFileHeader - Pointer to the current file to search.
227 SectionData - Pointer to the Section matching SectionType in FfsFileHeader.
228 NULL if section not found
229
230 Returns:
231 EFI_NOT_FOUND - No files matching the search criteria were found
232 EFI_SUCCESS
233
234 --*/
235 {
236 UINT32 FileSize;
237 EFI_COMMON_SECTION_HEADER *Section;
238 UINT32 SectionLength;
239 UINT32 ParsedLength;
240
241 //
242 // Size is 24 bits wide so mask upper 8 bits.
243 // Does not include FfsFileHeader header size
244 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
245 //
246 Section = (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1);
247 FileSize = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
248 FileSize -= sizeof (EFI_FFS_FILE_HEADER);
249
250 *SectionData = NULL;
251 ParsedLength = 0;
252 while (ParsedLength < FileSize) {
253 if (Section->Type == SectionType) {
254 *SectionData = (VOID *) (Section + 1);
255 return EFI_SUCCESS;
256 }
257 //
258 // Size is 24 bits wide so mask upper 8 bits.
259 // SectionLength is adjusted it is 4 byte aligned.
260 // Go to the next section
261 //
262 SectionLength = *(UINT32 *) Section->Size & 0x00FFFFFF;
263 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
264
265 ParsedLength += SectionLength;
266 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
267 }
268
269 return EFI_NOT_FOUND;
270 }
271
272 EFI_STATUS
273 SecFfsFindPeiCore (
274 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
275 OUT VOID **Pe32Data
276 )
277 /*++
278
279 Routine Description:
280 Given the pointer to the Firmware Volume Header find the SEC
281 core and return it's PE32 image.
282
283 Arguments:
284 FwVolHeader - Pointer to memory mapped FV
285 Pe32Data - Pointer to SEC PE32 iamge.
286
287 Returns:
288 EFI_SUCCESS - Pe32Data is valid
289 other - Failure
290
291 --*/
292 {
293 EFI_STATUS Status;
294 EFI_FFS_FILE_HEADER *FileHeader;
295 EFI_FV_FILETYPE SearchType;
296
297 SearchType = EFI_FV_FILETYPE_PEI_CORE;
298 FileHeader = NULL;
299 do {
300 Status = SecFfsFindNextFile (SearchType, FwVolHeader, &FileHeader);
301 if (!EFI_ERROR (Status)) {
302 Status = SecFfsFindSectionData (EFI_SECTION_PE32, FileHeader, Pe32Data);
303 return Status;
304 }
305 } while (!EFI_ERROR (Status));
306
307 return Status;
308 }