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
);
188 argc - Number of command line parameters.
189 argv - Array of pointers to parameter strings.
192 STATUS_SUCCESS - Utility exits successfully.
193 STATUS_ERROR - Some error occurred during execution.
199 UINT32 FvrecoveryFileSize
;
201 UINT8
*FileBufferRaw
;
205 UINT32 FileOccupiedSize
;
206 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
207 EFI_FFS_FILE_HEADER
*FileHeader
;
215 SetUtilityName (UTILITY_NAME
);
222 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0) ||
223 (strcmp(argv
[1], "-?") == 0) || (strcmp(argv
[1], "/?") == 0)) {
228 if ((strcmp(argv
[1], "-V") == 0) || (strcmp(argv
[1], "--version") == 0)) {
234 // Verify the correct number of arguments
236 if (argc
!= MAX_ARGS
) {
237 Error (NULL
, 0, 0, "invalid number of input parameters specified", NULL
);
242 // Open the Input Fvrecovery.fv file
244 if ((FpIn
= fopen (argv
[1], "rb")) == NULL
) {
245 Error (NULL
, 0, 0, "Unable to open file", argv
[1]);
249 // Get the Input Fvrecovery.fv file size
251 fseek (FpIn
, 0, SEEK_END
);
252 FvrecoveryFileSize
= ftell (FpIn
);
254 // Read the contents of input file to memory buffer
257 FileBufferRaw
= NULL
;
258 FileBufferRaw
= (UINT8
*) malloc (FvrecoveryFileSize
+ 0x10000);
259 if (NULL
== FileBufferRaw
) {
260 Error (NULL
, 0, 0, "No sufficient memory to allocate!", NULL
);
264 TempResult
= 0x10000 - ((UINT32
)FileBufferRaw
& 0x0FFFF);
265 FileBuffer
= (UINT8
*)((UINT32
)FileBufferRaw
+ TempResult
);
266 fseek (FpIn
, 0, SEEK_SET
);
267 TempResult
= fread (FileBuffer
, 1, FvrecoveryFileSize
, FpIn
);
268 if (TempResult
!= FvrecoveryFileSize
) {
269 Error (NULL
, 0, 0, "Read input file error!", NULL
);
270 free ((VOID
*)FileBufferRaw
);
275 // Close the input Fvrecovery.fv file
279 // Find the pad FFS file
281 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)FileBuffer
;
282 FvLength
= FvHeader
->FvLength
;
283 FileHeader
= (EFI_FFS_FILE_HEADER
*)(FileBuffer
+ FvHeader
->HeaderLength
);
284 FileLength
= (*(UINT32
*)(FileHeader
->Size
)) & 0x00FFFFFF;
285 FileOccupiedSize
= GETOCCUPIEDSIZE(FileLength
, 8);
286 Offset
= (UINT32
)FileHeader
- (UINT32
)FileBuffer
;
288 while (Offset
< FvLength
) {
289 TempGuid
= (EFI_GUID
*)&(FileHeader
->Name
);
290 FileLength
= (*(UINT32
*)(FileHeader
->Size
)) & 0x00FFFFFF;
291 FileOccupiedSize
= GETOCCUPIEDSIZE(FileLength
, 8);
292 if ((CompareGuid (TempGuid
, (EFI_GUID
*)&DefaultFvPadFileNameGuid
)) == 0) {
295 FileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT32
)FileHeader
+ FileOccupiedSize
);
296 Offset
= (UINT32
)FileHeader
- (UINT32
)FileBuffer
;
299 if (Offset
>= FvLength
) {
300 Error (NULL
, 0, 0, "No pad file found!", NULL
);
301 free ((VOID
*)FileBufferRaw
);
305 // Find the position to place Ap reset vector, the offset
306 // between the position and the end of Fvrecovery.fv file
307 // should not exceed 128kB to prevent Ap reset vector from
308 // outside legacy E and F segment
310 FixPoint
= (UINT8
*)(FileHeader
+ sizeof(EFI_FFS_FILE_HEADER
));
311 TempResult
= 0x1000 - ((UINT32
)FixPoint
& 0x0FFF);
312 FixPoint
+=TempResult
;
313 if (((UINT32
)FixPoint
- (UINT32
)FileHeader
+ 5) > FileOccupiedSize
) {
314 Error (NULL
, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL
);
315 free ((VOID
*)FileBufferRaw
);
318 while (((UINT32
)FixPoint
- (UINT32
)FileHeader
+ 5) <= FileOccupiedSize
) {
322 if ((UINT32
)FvHeader
+ FvLength
- (UINT32
)FixPoint
> 0x20000) {
323 Error (NULL
, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL
);
324 free ((VOID
*)FileBufferRaw
);
328 // Fix up Ap reset vector and calculate the IPI vector
330 for (Index
= 0; Index
< 5; Index
++) {
331 FixPoint
[Index
] = ApResetVector
[Index
];
333 TempResult
= 0x0FFFFFFFF - ((UINT32
)FvHeader
+ (UINT32
)FvLength
- 1 - (UINT32
)FixPoint
);
335 IpiVector
= TempResult
& 0x0FF;
338 UpdatePadFileGuid (FvHeader
, FileHeader
, FileLength
, TempGuid
);
341 // Open the output Fvrecovery.fv file
343 if ((FpOut
= fopen (argv
[2], "w+b")) == NULL
) {
344 Error (NULL
, 0, 0, "Unable to open file", argv
[2]);
345 free ((VOID
*)FileBufferRaw
);
349 // Write the output Fvrecovery.fv file
351 if ((fwrite (FileBuffer
, 1, FvrecoveryFileSize
, FpOut
)) != FvrecoveryFileSize
) {
352 Error (NULL
, 0, 0, "Write output file error!", NULL
);
353 free ((VOID
*)FileBufferRaw
);
359 fseek (FpOut
, -8, SEEK_END
);
360 if ((fwrite (&IpiVector
, 1, sizeof(UINT32
), FpOut
)) != sizeof(UINT32
)) {
361 Error (NULL
, 0, 0, "Write output file error!", NULL
);
362 free ((VOID
*)FileBufferRaw
);
366 // Close the output Fvrecovery.fv file
369 free ((VOID
*)FileBufferRaw
);
370 return STATUS_SUCCESS
;