]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/SecApResetVectorFixup/SecApResetVectorFixup.c
Renaming files/directories
[mirror_edk2.git] / Tools / CCode / Source / SecApResetVectorFixup / SecApResetVectorFixup.c
1 /*++
2
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
8
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.
11
12
13 Module Name:
14
15 SecApResetVectorFixup.c
16
17 Abstract:
18
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.
22
23 PEI FV after using the tool
24
25 -------------------------
26 |zzz |
27 | |
28 | |
29 | FFS |
30 | |
31 | |
32 | |
33 |---------------------- |
34 | PAD |
35 | |
36 |.......................| ---
37 | | |
38 |xxx | | 128K
39 |---------------------- | |
40 | VTF (SEC) | |
41 ------------------------- ---
42
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
45 file area.
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
48 UpdatePadFileGuid
49
50
51
52 --*/
53
54 #include "SecApResetVectorFixup.h"
55
56
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 };
59
60 //
61 // jmp 0xf000:0xffd0 (0xFFFFFFD0)
62 //
63 UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};
64
65 VOID
66 Version (
67 VOID
68 )
69 /*++
70
71 Routine Description:
72
73 Displays the standard utility information to SDTOUT
74
75 Arguments:
76
77 None
78
79 Returns:
80
81 None
82
83 --*/
84 {
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");
87 }
88
89 VOID
90 Usage (
91 VOID
92 )
93 /*++
94
95 Routine Description:
96
97 Displays the utility usage syntax to STDOUT
98
99 Arguments:
100
101 None
102
103 Returns:
104
105 None
106
107 --*/
108 {
109 Version();
110
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");
115 }
116
117
118 VOID
119 UpdatePadFileGuid (
120 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
121 IN EFI_FFS_FILE_HEADER *FileHeader,
122 IN UINT32 FileLength,
123 IN OUT EFI_GUID *Guid
124 )
125 /*++
126
127 Routine Description:
128
129 Update the Pad File Guid to change it to other guid and update
130 the checksum
131
132 Arguments:
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
137 Returns:
138 VOID
139 --*/
140
141 {
142 if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {
143 //
144 // Set new Pad file guid
145 //
146 memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));
147
148
149
150 FileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
151 FileHeader->Attributes = 0;
152 //
153 // Fill in checksums and state, must be zero during checksum calculation.
154 //
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);
161 } else {
162 FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
163 }
164
165 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
166
167 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
168 FileHeader->State = (UINT8)~(FileHeader->State);
169 }
170 }
171
172 }
173
174 VOID
175 SetHeaderChecksum (
176 IN EFI_FFS_FILE_HEADER *FfsHeader
177 )
178 /*++
179
180 Routine Description:
181 Caculate the checksum for the FFS header.
182
183 Parameters:
184 FfsHeader - FFS File Header which needs to caculate the checksum
185
186 Return:
187 N/A
188
189 --*/
190 {
191 EFI_FFS_FILE_STATE State;
192 UINT8 HeaderChecksum;
193 UINT8 FileChecksum;
194
195 //
196 // The state and the File checksum are not included
197 //
198 State = FfsHeader->State;
199 FfsHeader->State = 0;
200
201 FileChecksum = FfsHeader->IntegrityCheck.Checksum.File;
202 FfsHeader->IntegrityCheck.Checksum.File = 0;
203
204 FfsHeader->IntegrityCheck.Checksum.Header = 0;
205
206 HeaderChecksum = CalculateChecksum8 ((UINT8 *)FfsHeader,sizeof (EFI_FFS_FILE_HEADER));
207
208 FfsHeader->IntegrityCheck.Checksum.Header = (UINT8) (~(0x100-HeaderChecksum) + 1);
209
210 FfsHeader->State = State;
211 FfsHeader->IntegrityCheck.Checksum.File = FileChecksum;
212
213 return ;
214 }
215
216 VOID
217 SetFileChecksum (
218 IN EFI_FFS_FILE_HEADER *FfsHeader,
219 IN UINTN ActualFileSize
220 )
221 /*++
222
223 Routine Description:
224 Caculate the checksum for the FFS File, usually it is caculated before
225 the file tail is set.
226
227 Parameters:
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.
231 Return:
232 N/A
233
234 --*/
235 {
236 EFI_FFS_FILE_STATE State;
237 UINT8 FileChecksum;
238 UINTN ActualSize;
239
240 if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
241 //
242 // The file state is not included
243 //
244 State = FfsHeader->State;
245 FfsHeader->State = 0;
246
247 FfsHeader->IntegrityCheck.Checksum.File = 0;
248
249 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
250 ActualSize = ActualFileSize - 2;
251 } else {
252 ActualSize = ActualFileSize;
253 }
254 //
255 // File checksum does not including the file tail
256 //
257 FileChecksum = CalculateChecksum8 ((UINT8 *)FfsHeader,sizeof (EFI_FFS_FILE_HEADER));
258
259 FfsHeader->IntegrityCheck.Checksum.File = (UINT8) (~(0x100-FileChecksum) + 1);
260
261 FfsHeader->State = State;
262
263 } else {
264
265 FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
266
267 }
268
269 return ;
270 }
271
272 VOID
273 SetFileTail (
274 IN EFI_FFS_FILE_HEADER *FfsHeader,
275 IN UINTN ActualFileSize
276 )
277 /*++
278
279 Routine Description:
280 Set the file tail if needed
281
282 Parameters:
283 FfsHeader - FFS File Header which needs to caculate the checksum
284 ActualFileSize - The whole Ffs File Length, including the FFS Tail
285 if exists.
286 Return:
287 N/A
288
289 --*/
290 {
291 UINT8 TailLow;
292 UINT8 TailHigh;
293 UINT16 Tail;
294
295 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
296 //
297 // Insert tail here, since tail may not aligned on an even
298 // address, we need to do byte operation here.
299 //
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;
305 }
306
307 return ;
308 }
309
310 STATUS
311 main (
312 IN INTN argc,
313 IN CHAR8 **argv
314 )
315 /*++
316
317 Routine Description:
318
319 Main function.
320
321 Arguments:
322
323 argc - Number of command line parameters.
324 argv - Array of pointers to parameter strings.
325
326 Returns:
327 STATUS_SUCCESS - Utility exits successfully.
328 STATUS_ERROR - Some error occurred during execution.
329
330 --*/
331 {
332 FILE *FpIn;
333 FILE *FpOut;
334 UINT32 FvrecoveryFileSize;
335 UINT8 *FileBuffer;
336 UINT8 *FileBufferRaw;
337 UINT64 FvLength;
338 UINT32 Offset;
339 UINT32 FileLength;
340 UINT32 FileOccupiedSize;
341 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
342 EFI_FFS_FILE_HEADER *FileHeader;
343 EFI_GUID *TempGuid;
344 UINT8 *FixPoint;
345 UINT32 TempResult;
346 UINT32 Index;
347 UINT32 IpiVector;
348 STATUS Status;
349
350 TempGuid = NULL;
351 SetUtilityName (UTILITY_NAME);
352
353 if (argc == 1) {
354 Usage();
355 return STATUS_ERROR;
356 }
357
358 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
359 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
360 Usage();
361 return STATUS_ERROR;
362 }
363
364 if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
365 Version();
366 return STATUS_ERROR;
367 }
368
369 //
370 // Verify the correct number of arguments
371 //
372 if (argc != MAX_ARGS) {
373 Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
374 Usage ();
375 return STATUS_ERROR;
376 }
377 //
378 // Open the Input Fvrecovery.fv file
379 //
380 if ((FpIn = fopen (argv[1], "rb")) == NULL) {
381 Error (NULL, 0, 0, "Unable to open file", argv[1]);
382 return STATUS_ERROR;
383 }
384 //
385 // Get the Input Fvrecovery.fv file size
386 //
387 fseek (FpIn, 0, SEEK_END);
388 FvrecoveryFileSize = ftell (FpIn);
389 //
390 // Read the contents of input file to memory buffer
391 //
392 FileBuffer = NULL;
393 FileBufferRaw = NULL;
394 FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);
395 if (NULL == FileBufferRaw) {
396 Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
397 fclose (FpIn);
398 return STATUS_ERROR;
399 }
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);
407 fclose (FpIn);
408 return STATUS_ERROR;
409 }
410
411 //
412 // Prepare to walk the FV image
413 //
414 InitializeFvLib (FileBuffer, FvrecoveryFileSize);
415
416 //
417 // Close the input Fvrecovery.fv file
418 //
419 fclose (FpIn);
420
421 //
422 // Find the pad FFS file
423 //
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;
430
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) {
436 break;
437 }
438 FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);
439 Offset = (UINT32)FileHeader - (UINT32)FileBuffer;
440 }
441
442 if (Offset >= FvLength) {
443 Error (NULL, 0, 0, "No pad file found!", NULL);
444 free ((VOID *)FileBufferRaw);
445 return STATUS_ERROR;
446 }
447 //
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
452 //
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);
459 return STATUS_ERROR;
460 }
461 while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {
462 FixPoint += 0x1000;
463 }
464 FixPoint -= 0x1000;
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);
468 return STATUS_ERROR;
469 }
470
471 //
472 // Fix up Ap reset vector and calculate the IPI vector
473 //
474 for (Index = 0; Index < 5; Index++) {
475 FixPoint[Index] = ApResetVector[Index];
476 }
477 TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);
478 TempResult >>= 12;
479 IpiVector = TempResult & 0x0FF;
480
481 //
482 // Update Pad file and checksum
483 //
484 UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);
485
486 //
487 // Get FileHeader of SEC Ffs
488 //
489 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &FileHeader);
490
491 //
492 // Write IPI Vector at Offset FvrecoveryFileSize - 8
493 //
494 *(UINT32 *)((UINTN)(FileBuffer + FvrecoveryFileSize - 8)) = IpiVector;
495
496 if (Status == STATUS_SUCCESS) {
497 FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
498 //
499 // Update the Checksum of SEC ffs
500 //
501 SetHeaderChecksum (FileHeader);
502 SetFileChecksum (FileHeader, FileLength);
503 SetFileTail (FileHeader, FileLength);
504 } else {
505 Error (NULL, 0, 0, "Do not get SEC FFS File Header!", NULL);
506 }
507 //
508 // Open the output Fvrecovery.fv file
509 //
510 if ((FpOut = fopen (argv[2], "w+b")) == NULL) {
511 Error (NULL, 0, 0, "Unable to open file", argv[2]);
512 free ((VOID *)FileBufferRaw);
513 return STATUS_ERROR;
514 }
515 //
516 // Write the output Fvrecovery.fv file
517 //
518 if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {
519 Error (NULL, 0, 0, "Write output file error!", NULL);
520 free ((VOID *)FileBufferRaw);
521 return STATUS_ERROR;
522 }
523
524 //
525 // Close the output Fvrecovery.fv file
526 //
527 fclose (FpOut);
528 free ((VOID *)FileBufferRaw);
529 return STATUS_SUCCESS;
530 }
531