]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CCode/Source/SecApResetVectorFixup/SecApResetVectorFixup.c
ReCaculate the checksum after fixing up AP section for Sec module.
[mirror_edk2.git] / Tools / CCode / Source / SecApResetVectorFixup / SecApResetVectorFixup.c
CommitLineData
d25c4bf0 1/*++\r
2\r
60db81c1 3Copyright (c) 2004-2007 Intel Corporation. All rights reserved\r
ad1f8df0 4This program and the accompanying materials are licensed and made available \r
5under the terms and conditions of the BSD License which accompanies this \r
6distribution. 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
d25c4bf0 11\r
12\r
13Module Name:\r
14\r
15 SecApResetVectorFixup.c\r
16\r
17Abstract:\r
18\r
19 This utility is part of build process for IA32 Fvrecovery.fv whose total size\r
20 is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset \r
21 vector at the zero vector of Fv header.\r
22 \r
23 PEI FV after using the tool\r
24 \r
25 -------------------------\r
26 |zzz |\r
27 | |\r
28 | |\r
29 | FFS |\r
30 | |\r
31 | |\r
32 | |\r
33 |---------------------- |\r
34 | PAD |\r
35 | |\r
36 |.......................| --- \r
37 | | |\r
38 |xxx | | 128K \r
39 |---------------------- | | \r
40 | VTF (SEC) | |\r
41 ------------------------- ---\r
42 \r
43 1. zzz --> Zero vector, which is beyond the 128K limited address space\r
44 2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD\r
45 file area.\r
46 3. After the build process ,the PAD guid is changed to a new GUID to avoid \r
47 the PAD definition confusing. If there is some problem, try to disable\r
48 UpdatePadFileGuid\r
49 \r
50 \r
51 \r
52--*/\r
53\r
54#include "SecApResetVectorFixup.h"\r
55\r
56\r
57EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };\r
58EFI_GUID NewFvPadFileNameGuid = { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };\r
59\r
60//\r
61// jmp 0xf000:0xffd0 (0xFFFFFFD0)\r
62//\r
63UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};\r
64\r
65VOID\r
60db81c1 66Version (\r
d25c4bf0 67 VOID\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73 Displays the standard utility information to SDTOUT\r
74\r
75Arguments:\r
76\r
77 None\r
78\r
79Returns:\r
80\r
81 None\r
82\r
83--*/\r
84{\r
60db81c1 85 printf ("%s v%d.%d -Tiano IA32 SEC Ap Reset Vector Fixup Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
86 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");\r
d25c4bf0 87}\r
88\r
89VOID\r
60db81c1 90Usage (\r
d25c4bf0 91 VOID\r
92 )\r
93/*++\r
94\r
95Routine Description:\r
96\r
97 Displays the utility usage syntax to STDOUT\r
98\r
99Arguments:\r
100\r
101 None\r
102\r
103Returns:\r
104\r
105 None\r
106\r
107--*/\r
108{\r
60db81c1 109 Version();\r
110 \r
111 printf ("\nUsage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME);\r
d25c4bf0 112 printf (" Where:\n");\r
60db81c1 113 printf (" InputFvrecoveryFile - Name of the IA32 input Fvrecovery.fv file.\n");\r
114 printf (" OutputFvrecoveryFile - Name of the IA32 output Fvrecovery.fv file.\n");\r
d25c4bf0 115}\r
116\r
117\r
118VOID \r
119UpdatePadFileGuid (\r
120 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
121 IN EFI_FFS_FILE_HEADER *FileHeader,\r
122 IN UINT32 FileLength,\r
123 IN OUT EFI_GUID *Guid\r
124 )\r
125/*++\r
126\r
127Routine Description:\r
128\r
129 Update the Pad File Guid to change it to other guid and update\r
130 the checksum\r
131\r
132Arguments:\r
133 FvHeader - EFI_FIRMWARE_VOLUME_HEADER \r
134 FileHeader - The FFS PAD file header.\r
135 FileLength - The FFS PAD file length.\r
136 Guid - The Guid to compare and if it is PAD Guid, update it to new Guid\r
137Returns:\r
138 VOID\r
139--*/\r
140\r
141{\r
142 if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {\r
143 //\r
144 // Set new Pad file guid\r
145 // \r
146 memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));\r
147\r
148\r
149\r
150 FileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;\r
151 FileHeader->Attributes = 0;\r
152 //\r
153 // Fill in checksums and state, must be zero during checksum calculation.\r
154 //\r
155 FileHeader->IntegrityCheck.Checksum.Header = 0;\r
156 FileHeader->IntegrityCheck.Checksum.File = 0;\r
157 FileHeader->State = 0;\r
158 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
159 if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
160 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, FileLength);\r
161 } else {\r
162 FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
163 }\r
164\r
165 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
166\r
167 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
168 FileHeader->State = (UINT8)~(FileHeader->State);\r
169 } \r
170 }\r
171 \r
172}\r
173\r
9fc9e7e0 174VOID\r
175SetHeaderChecksum (\r
176 IN EFI_FFS_FILE_HEADER *FfsHeader\r
177 )\r
178/*++\r
179\r
180 Routine Description:\r
181 Caculate the checksum for the FFS header.\r
182\r
183 Parameters:\r
184 FfsHeader - FFS File Header which needs to caculate the checksum\r
185\r
186 Return:\r
187 N/A\r
188\r
189--*/\r
190{\r
191 EFI_FFS_FILE_STATE State;\r
192 UINT8 HeaderChecksum;\r
193 UINT8 FileChecksum;\r
194\r
195 //\r
196 // The state and the File checksum are not included\r
197 //\r
198 State = FfsHeader->State;\r
199 FfsHeader->State = 0;\r
200\r
201 FileChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r
202 FfsHeader->IntegrityCheck.Checksum.File = 0;\r
203\r
204 FfsHeader->IntegrityCheck.Checksum.Header = 0;\r
205\r
206 HeaderChecksum = CalculateChecksum8 ((UINT8 *)FfsHeader,sizeof (EFI_FFS_FILE_HEADER));\r
207\r
208 FfsHeader->IntegrityCheck.Checksum.Header = (UINT8) (~(0x100-HeaderChecksum) + 1);\r
209\r
210 FfsHeader->State = State;\r
211 FfsHeader->IntegrityCheck.Checksum.File = FileChecksum;\r
212\r
213 return ;\r
214}\r
215\r
216VOID\r
217SetFileChecksum (\r
218 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
219 IN UINTN ActualFileSize\r
220 )\r
221/*++\r
222\r
223 Routine Description:\r
224 Caculate the checksum for the FFS File, usually it is caculated before\r
225 the file tail is set.\r
226\r
227 Parameters:\r
228 FfsHeader - FFS File Header which needs to caculate the checksum\r
229 ActualFileSize - The whole Ffs File Length, including the FFS Tail\r
230 if exists, but at this time, it is 0.\r
231 Return:\r
232 N/A\r
233\r
234--*/\r
235{\r
236 EFI_FFS_FILE_STATE State;\r
237 UINT8 FileChecksum;\r
238 UINTN ActualSize;\r
239\r
240 if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
241 //\r
242 // The file state is not included\r
243 //\r
244 State = FfsHeader->State;\r
245 FfsHeader->State = 0;\r
246\r
247 FfsHeader->IntegrityCheck.Checksum.File = 0;\r
248\r
249 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
250 ActualSize = ActualFileSize - 2;\r
251 } else {\r
252 ActualSize = ActualFileSize;\r
253 }\r
254 //\r
255 // File checksum does not including the file tail\r
256 //\r
257 FileChecksum = CalculateChecksum8 ((UINT8 *)FfsHeader,sizeof (EFI_FFS_FILE_HEADER));\r
258\r
259 FfsHeader->IntegrityCheck.Checksum.File = (UINT8) (~(0x100-FileChecksum) + 1);\r
260\r
261 FfsHeader->State = State;\r
262\r
263 } else {\r
264\r
265 FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
266\r
267 }\r
268\r
269 return ;\r
270}\r
271\r
272VOID\r
273SetFileTail (\r
274 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
275 IN UINTN ActualFileSize\r
276 )\r
277/*++\r
278\r
279 Routine Description:\r
280 Set the file tail if needed\r
281\r
282 Parameters:\r
283 FfsHeader - FFS File Header which needs to caculate the checksum\r
284 ActualFileSize - The whole Ffs File Length, including the FFS Tail\r
285 if exists.\r
286 Return:\r
287 N/A\r
288\r
289--*/\r
290{\r
291 UINT8 TailLow;\r
292 UINT8 TailHigh;\r
293 UINT16 Tail;\r
294\r
295 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
296 //\r
297 // Insert tail here, since tail may not aligned on an even\r
298 // address, we need to do byte operation here.\r
299 //\r
300 Tail = (UINT16)~FfsHeader->IntegrityCheck.TailReference;\r
301 TailLow = (UINT8) Tail;\r
302 TailHigh = (UINT8) (Tail >> 8);\r
303 *((UINT8 *) FfsHeader + ActualFileSize - 2) = TailLow;\r
304 *((UINT8 *) FfsHeader + ActualFileSize - 1) = TailHigh;\r
305 }\r
306\r
307 return ;\r
308}\r
d25c4bf0 309\r
310STATUS\r
311main (\r
312 IN INTN argc,\r
313 IN CHAR8 **argv\r
314 )\r
315/*++\r
316\r
317Routine Description:\r
318\r
319 Main function.\r
320\r
321Arguments:\r
322\r
323 argc - Number of command line parameters.\r
324 argv - Array of pointers to parameter strings.\r
325\r
326Returns:\r
327 STATUS_SUCCESS - Utility exits successfully.\r
328 STATUS_ERROR - Some error occurred during execution.\r
329\r
330--*/\r
331{\r
332 FILE *FpIn;\r
333 FILE *FpOut;\r
334 UINT32 FvrecoveryFileSize;\r
335 UINT8 *FileBuffer;\r
336 UINT8 *FileBufferRaw;\r
337 UINT64 FvLength;\r
338 UINT32 Offset;\r
339 UINT32 FileLength;\r
340 UINT32 FileOccupiedSize;\r
341 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
342 EFI_FFS_FILE_HEADER *FileHeader;\r
343 EFI_GUID *TempGuid;\r
344 UINT8 *FixPoint;\r
345 UINT32 TempResult;\r
346 UINT32 Index;\r
347 UINT32 IpiVector;\r
9fc9e7e0 348 STATUS Status;\r
d25c4bf0 349\r
350 TempGuid = NULL;\r
351 SetUtilityName (UTILITY_NAME);\r
352\r
60db81c1 353 if (argc == 1) {\r
354 Usage();\r
355 return STATUS_ERROR;\r
356 }\r
357 \r
358 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||\r
359 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {\r
360 Usage();\r
361 return STATUS_ERROR;\r
362 }\r
363 \r
364 if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {\r
365 Version();\r
366 return STATUS_ERROR;\r
367 }\r
368 \r
d25c4bf0 369 //\r
370 // Verify the correct number of arguments\r
371 //\r
372 if (argc != MAX_ARGS) {\r
373 Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);\r
60db81c1 374 Usage ();\r
d25c4bf0 375 return STATUS_ERROR;\r
376 }\r
377 //\r
378 // Open the Input Fvrecovery.fv file\r
379 //\r
380 if ((FpIn = fopen (argv[1], "rb")) == NULL) {\r
381 Error (NULL, 0, 0, "Unable to open file", argv[1]);\r
382 return STATUS_ERROR;\r
383 }\r
384 //\r
385 // Get the Input Fvrecovery.fv file size\r
386 //\r
387 fseek (FpIn, 0, SEEK_END);\r
388 FvrecoveryFileSize = ftell (FpIn);\r
389 //\r
390 // Read the contents of input file to memory buffer\r
391 //\r
392 FileBuffer = NULL;\r
393 FileBufferRaw = NULL;\r
394 FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);\r
395 if (NULL == FileBufferRaw) {\r
396 Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);\r
397 fclose (FpIn);\r
398 return STATUS_ERROR;\r
399 }\r
400 TempResult = 0x10000 - ((UINT32)FileBufferRaw & 0x0FFFF);\r
401 FileBuffer = (UINT8 *)((UINT32)FileBufferRaw + TempResult);\r
402 fseek (FpIn, 0, SEEK_SET);\r
403 TempResult = fread (FileBuffer, 1, FvrecoveryFileSize, FpIn);\r
404 if (TempResult != FvrecoveryFileSize) {\r
405 Error (NULL, 0, 0, "Read input file error!", NULL);\r
406 free ((VOID *)FileBufferRaw);\r
407 fclose (FpIn);\r
408 return STATUS_ERROR;\r
409 }\r
9fc9e7e0 410 \r
411 //\r
412 // Prepare to walk the FV image\r
413 //\r
414 InitializeFvLib (FileBuffer, FvrecoveryFileSize);\r
415 \r
d25c4bf0 416 //\r
417 // Close the input Fvrecovery.fv file\r
418 //\r
419 fclose (FpIn);\r
9fc9e7e0 420 \r
d25c4bf0 421 //\r
422 // Find the pad FFS file\r
423 //\r
424 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;\r
425 FvLength = FvHeader->FvLength;\r
426 FileHeader = (EFI_FFS_FILE_HEADER *)(FileBuffer + FvHeader->HeaderLength);\r
427 FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
428 FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);\r
429 Offset = (UINT32)FileHeader - (UINT32)FileBuffer;\r
430 \r
431 while (Offset < FvLength) {\r
432 TempGuid = (EFI_GUID *)&(FileHeader->Name);\r
433 FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
434 FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);\r
435 if ((CompareGuid (TempGuid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {\r
436 break;\r
437 }\r
438 FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);\r
439 Offset = (UINT32)FileHeader - (UINT32)FileBuffer;\r
440 }\r
441\r
442 if (Offset >= FvLength) {\r
443 Error (NULL, 0, 0, "No pad file found!", NULL);\r
444 free ((VOID *)FileBufferRaw);\r
445 return STATUS_ERROR;\r
446 }\r
447 //\r
448 // Find the position to place Ap reset vector, the offset\r
449 // between the position and the end of Fvrecovery.fv file\r
450 // should not exceed 128kB to prevent Ap reset vector from\r
451 // outside legacy E and F segment\r
452 //\r
453 FixPoint = (UINT8 *)(FileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
454 TempResult = 0x1000 - ((UINT32)FixPoint & 0x0FFF);\r
455 FixPoint +=TempResult;\r
456 if (((UINT32)FixPoint - (UINT32)FileHeader + 5) > FileOccupiedSize) {\r
457 Error (NULL, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL);\r
458 free ((VOID *)FileBufferRaw);\r
459 return STATUS_ERROR; \r
460 }\r
461 while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {\r
462 FixPoint += 0x1000;\r
463 }\r
464 FixPoint -= 0x1000;\r
465 if ((UINT32)FvHeader + FvLength - (UINT32)FixPoint > 0x20000) {\r
466 Error (NULL, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL);\r
467 free ((VOID *)FileBufferRaw);\r
468 return STATUS_ERROR; \r
9fc9e7e0 469 }\r
470\r
d25c4bf0 471 //\r
472 // Fix up Ap reset vector and calculate the IPI vector\r
473 //\r
474 for (Index = 0; Index < 5; Index++) {\r
475 FixPoint[Index] = ApResetVector[Index];\r
476 } \r
477 TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);\r
478 TempResult >>= 12;\r
479 IpiVector = TempResult & 0x0FF;\r
9fc9e7e0 480 \r
481 //\r
482 // Update Pad file and checksum\r
483 //\r
484 UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);\r
d25c4bf0 485 \r
9fc9e7e0 486 //\r
487 // Get FileHeader of SEC Ffs\r
488 //\r
489 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &FileHeader);\r
d25c4bf0 490 \r
9fc9e7e0 491 //\r
492 // Write IPI Vector at Offset FvrecoveryFileSize - 8\r
493 //\r
494 *(UINT32 *)((UINTN)(FileBuffer + FvrecoveryFileSize - 8)) = IpiVector;\r
d25c4bf0 495\r
9fc9e7e0 496 if (Status == STATUS_SUCCESS) {\r
497 FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
498 //\r
499 // Update the Checksum of SEC ffs\r
500 //\r
501 SetHeaderChecksum (FileHeader);\r
502 SetFileChecksum (FileHeader, FileLength);\r
503 SetFileTail (FileHeader, FileLength);\r
504 } else {\r
505 Error (NULL, 0, 0, "Do not get SEC FFS File Header!", NULL);\r
506 }\r
d25c4bf0 507 //\r
508 // Open the output Fvrecovery.fv file\r
509 //\r
510 if ((FpOut = fopen (argv[2], "w+b")) == NULL) {\r
511 Error (NULL, 0, 0, "Unable to open file", argv[2]);\r
512 free ((VOID *)FileBufferRaw);\r
513 return STATUS_ERROR;\r
514 }\r
515 //\r
516 // Write the output Fvrecovery.fv file\r
517 //\r
518 if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {\r
519 Error (NULL, 0, 0, "Write output file error!", NULL);\r
520 free ((VOID *)FileBufferRaw);\r
521 return STATUS_ERROR; \r
522 }\r
9fc9e7e0 523\r
d25c4bf0 524 //\r
525 // Close the output Fvrecovery.fv file\r
526 //\r
527 fclose (FpOut);\r
528 free ((VOID *)FileBufferRaw);\r
529 return STATUS_SUCCESS;\r
530}\r
531\r