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