3 Copyright (c) 2004-2007 Intel Corporation. All rights reserved
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
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.
15 SecApResetVectorFixup.c
19 This utility is part of build process for IA32 Fvrecovery.fv whose total size
20 is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset
21 vector at the zero vector of Fv header.
23 PEI FV after using the tool
25 -------------------------
33 |---------------------- |
36 |.......................| ---
39 |---------------------- | |
41 ------------------------- ---
43 1. zzz --> Zero vector, which is beyond the 128K limited address space
44 2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD
46 3. After the build process ,the PAD guid is changed to a new GUID to avoid
47 the PAD definition confusing. If there is some problem, try to disable
54 #include "SecApResetVectorFixup.h"
57 EFI_GUID DefaultFvPadFileNameGuid
= { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
58 EFI_GUID NewFvPadFileNameGuid
= { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };
61 // jmp 0xf000:0xffd0 (0xFFFFFFD0)
63 UINT8 ApResetVector
[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};
73 Displays the standard utility information to SDTOUT
85 printf ("%s v%d.%d -Tiano IA32 SEC Ap Reset Vector Fixup Utility.\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
86 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
97 Displays the utility usage syntax to STDOUT
111 printf ("\nUsage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME
);
112 printf (" Where:\n");
113 printf (" InputFvrecoveryFile - Name of the IA32 input Fvrecovery.fv file.\n");
114 printf (" OutputFvrecoveryFile - Name of the IA32 output Fvrecovery.fv file.\n");
120 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
,
121 IN EFI_FFS_FILE_HEADER
*FileHeader
,
122 IN UINT32 FileLength
,
123 IN OUT EFI_GUID
*Guid
129 Update the Pad File Guid to change it to other guid and update
133 FvHeader - EFI_FIRMWARE_VOLUME_HEADER
134 FileHeader - The FFS PAD file header.
135 FileLength - The FFS PAD file length.
136 Guid - The Guid to compare and if it is PAD Guid, update it to new Guid
142 if ((CompareGuid (Guid
, (EFI_GUID
*)&DefaultFvPadFileNameGuid
)) == 0) {
144 // Set new Pad file guid
146 memcpy (Guid
, &NewFvPadFileNameGuid
, sizeof (EFI_GUID
));
150 FileHeader
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
151 FileHeader
->Attributes
= 0;
153 // Fill in checksums and state, must be zero during checksum calculation.
155 FileHeader
->IntegrityCheck
.Checksum
.Header
= 0;
156 FileHeader
->IntegrityCheck
.Checksum
.File
= 0;
157 FileHeader
->State
= 0;
158 FileHeader
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
159 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
160 FileHeader
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) FileHeader
, FileLength
);
162 FileHeader
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
165 FileHeader
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
167 if (FvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
168 FileHeader
->State
= (UINT8
)~(FileHeader
->State
);
176 IN EFI_FFS_FILE_HEADER
*FfsHeader
181 Caculate the checksum for the FFS header.
184 FfsHeader - FFS File Header which needs to caculate the checksum
191 EFI_FFS_FILE_STATE State
;
192 UINT8 HeaderChecksum
;
196 // The state and the File checksum are not included
198 State
= FfsHeader
->State
;
199 FfsHeader
->State
= 0;
201 FileChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
202 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
204 FfsHeader
->IntegrityCheck
.Checksum
.Header
= 0;
206 HeaderChecksum
= CalculateChecksum8 ((UINT8
*)FfsHeader
,sizeof (EFI_FFS_FILE_HEADER
));
208 FfsHeader
->IntegrityCheck
.Checksum
.Header
= (UINT8
) (~(0x100-HeaderChecksum
) + 1);
210 FfsHeader
->State
= State
;
211 FfsHeader
->IntegrityCheck
.Checksum
.File
= FileChecksum
;
218 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
219 IN UINTN ActualFileSize
224 Caculate the checksum for the FFS File, usually it is caculated before
225 the file tail is set.
228 FfsHeader - FFS File Header which needs to caculate the checksum
229 ActualFileSize - The whole Ffs File Length, including the FFS Tail
230 if exists, but at this time, it is 0.
236 EFI_FFS_FILE_STATE State
;
240 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
242 // The file state is not included
244 State
= FfsHeader
->State
;
245 FfsHeader
->State
= 0;
247 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
249 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
250 ActualSize
= ActualFileSize
- 2;
252 ActualSize
= ActualFileSize
;
255 // File checksum does not including the file tail
257 FileChecksum
= CalculateChecksum8 ((UINT8
*)FfsHeader
,sizeof (EFI_FFS_FILE_HEADER
));
259 FfsHeader
->IntegrityCheck
.Checksum
.File
= (UINT8
) (~(0x100-FileChecksum
) + 1);
261 FfsHeader
->State
= State
;
265 FfsHeader
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
274 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
275 IN UINTN ActualFileSize
280 Set the file tail if needed
283 FfsHeader - FFS File Header which needs to caculate the checksum
284 ActualFileSize - The whole Ffs File Length, including the FFS Tail
295 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
297 // Insert tail here, since tail may not aligned on an even
298 // address, we need to do byte operation here.
300 Tail
= (UINT16
)~FfsHeader
->IntegrityCheck
.TailReference
;
301 TailLow
= (UINT8
) Tail
;
302 TailHigh
= (UINT8
) (Tail
>> 8);
303 *((UINT8
*) FfsHeader
+ ActualFileSize
- 2) = TailLow
;
304 *((UINT8
*) FfsHeader
+ ActualFileSize
- 1) = TailHigh
;
323 argc - Number of command line parameters.
324 argv - Array of pointers to parameter strings.
327 STATUS_SUCCESS - Utility exits successfully.
328 STATUS_ERROR - Some error occurred during execution.
334 UINT32 FvrecoveryFileSize
;
336 UINT8
*FileBufferRaw
;
340 UINT32 FileOccupiedSize
;
341 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
342 EFI_FFS_FILE_HEADER
*FileHeader
;
351 SetUtilityName (UTILITY_NAME
);
358 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0) ||
359 (strcmp(argv
[1], "-?") == 0) || (strcmp(argv
[1], "/?") == 0)) {
364 if ((strcmp(argv
[1], "-V") == 0) || (strcmp(argv
[1], "--version") == 0)) {
370 // Verify the correct number of arguments
372 if (argc
!= MAX_ARGS
) {
373 Error (NULL
, 0, 0, "invalid number of input parameters specified", NULL
);
378 // Open the Input Fvrecovery.fv file
380 if ((FpIn
= fopen (argv
[1], "rb")) == NULL
) {
381 Error (NULL
, 0, 0, "Unable to open file", argv
[1]);
385 // Get the Input Fvrecovery.fv file size
387 fseek (FpIn
, 0, SEEK_END
);
388 FvrecoveryFileSize
= ftell (FpIn
);
390 // Read the contents of input file to memory buffer
393 FileBufferRaw
= NULL
;
394 FileBufferRaw
= (UINT8
*) malloc (FvrecoveryFileSize
+ 0x10000);
395 if (NULL
== FileBufferRaw
) {
396 Error (NULL
, 0, 0, "No sufficient memory to allocate!", NULL
);
400 TempResult
= 0x10000 - ((UINT32
)FileBufferRaw
& 0x0FFFF);
401 FileBuffer
= (UINT8
*)((UINT32
)FileBufferRaw
+ TempResult
);
402 fseek (FpIn
, 0, SEEK_SET
);
403 TempResult
= fread (FileBuffer
, 1, FvrecoveryFileSize
, FpIn
);
404 if (TempResult
!= FvrecoveryFileSize
) {
405 Error (NULL
, 0, 0, "Read input file error!", NULL
);
406 free ((VOID
*)FileBufferRaw
);
412 // Prepare to walk the FV image
414 InitializeFvLib (FileBuffer
, FvrecoveryFileSize
);
417 // Close the input Fvrecovery.fv file
422 // Find the pad FFS file
424 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)FileBuffer
;
425 FvLength
= FvHeader
->FvLength
;
426 FileHeader
= (EFI_FFS_FILE_HEADER
*)(FileBuffer
+ FvHeader
->HeaderLength
);
427 FileLength
= (*(UINT32
*)(FileHeader
->Size
)) & 0x00FFFFFF;
428 FileOccupiedSize
= GETOCCUPIEDSIZE(FileLength
, 8);
429 Offset
= (UINT32
)FileHeader
- (UINT32
)FileBuffer
;
431 while (Offset
< FvLength
) {
432 TempGuid
= (EFI_GUID
*)&(FileHeader
->Name
);
433 FileLength
= (*(UINT32
*)(FileHeader
->Size
)) & 0x00FFFFFF;
434 FileOccupiedSize
= GETOCCUPIEDSIZE(FileLength
, 8);
435 if ((CompareGuid (TempGuid
, (EFI_GUID
*)&DefaultFvPadFileNameGuid
)) == 0) {
438 FileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT32
)FileHeader
+ FileOccupiedSize
);
439 Offset
= (UINT32
)FileHeader
- (UINT32
)FileBuffer
;
442 if (Offset
>= FvLength
) {
443 Error (NULL
, 0, 0, "No pad file found!", NULL
);
444 free ((VOID
*)FileBufferRaw
);
448 // Find the position to place Ap reset vector, the offset
449 // between the position and the end of Fvrecovery.fv file
450 // should not exceed 128kB to prevent Ap reset vector from
451 // outside legacy E and F segment
453 FixPoint
= (UINT8
*)(FileHeader
+ sizeof(EFI_FFS_FILE_HEADER
));
454 TempResult
= 0x1000 - ((UINT32
)FixPoint
& 0x0FFF);
455 FixPoint
+=TempResult
;
456 if (((UINT32
)FixPoint
- (UINT32
)FileHeader
+ 5) > FileOccupiedSize
) {
457 Error (NULL
, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL
);
458 free ((VOID
*)FileBufferRaw
);
461 while (((UINT32
)FixPoint
- (UINT32
)FileHeader
+ 5) <= FileOccupiedSize
) {
465 if ((UINT32
)FvHeader
+ FvLength
- (UINT32
)FixPoint
> 0x20000) {
466 Error (NULL
, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL
);
467 free ((VOID
*)FileBufferRaw
);
472 // Fix up Ap reset vector and calculate the IPI vector
474 for (Index
= 0; Index
< 5; Index
++) {
475 FixPoint
[Index
] = ApResetVector
[Index
];
477 TempResult
= 0x0FFFFFFFF - ((UINT32
)FvHeader
+ (UINT32
)FvLength
- 1 - (UINT32
)FixPoint
);
479 IpiVector
= TempResult
& 0x0FF;
482 // Update Pad file and checksum
484 UpdatePadFileGuid (FvHeader
, FileHeader
, FileLength
, TempGuid
);
487 // Get FileHeader of SEC Ffs
489 Status
= GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE
, 1, &FileHeader
);
492 // Write IPI Vector at Offset FvrecoveryFileSize - 8
494 *(UINT32
*)((UINTN
)(FileBuffer
+ FvrecoveryFileSize
- 8)) = IpiVector
;
496 if (Status
== STATUS_SUCCESS
) {
497 FileLength
= (*(UINT32
*)(FileHeader
->Size
)) & 0x00FFFFFF;
499 // Update the Checksum of SEC ffs
501 SetHeaderChecksum (FileHeader
);
502 SetFileChecksum (FileHeader
, FileLength
);
503 SetFileTail (FileHeader
, FileLength
);
505 Error (NULL
, 0, 0, "Do not get SEC FFS File Header!", NULL
);
508 // Open the output Fvrecovery.fv file
510 if ((FpOut
= fopen (argv
[2], "w+b")) == NULL
) {
511 Error (NULL
, 0, 0, "Unable to open file", argv
[2]);
512 free ((VOID
*)FileBufferRaw
);
516 // Write the output Fvrecovery.fv file
518 if ((fwrite (FileBuffer
, 1, FvrecoveryFileSize
, FpOut
)) != FvrecoveryFileSize
) {
519 Error (NULL
, 0, 0, "Write output file error!", NULL
);
520 free ((VOID
*)FileBufferRaw
);
525 // Close the output Fvrecovery.fv file
528 free ((VOID
*)FileBufferRaw
);
529 return STATUS_SUCCESS
;