]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenFv/GenFvInternalLib.c
Sync basetools' source and binary files with r1707 of the basetools project.
[mirror_edk2.git] / BaseTools / Source / C / GenFv / GenFvInternalLib.c
1 /** @file
2
3 Copyright (c) 2004 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this 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 Module Name:
13
14 GenFvInternalLib.c
15
16 Abstract:
17
18 This file contains the internal functions required to generate a Firmware Volume.
19
20 **/
21
22 //
23 // Include files
24 //
25 #ifdef __GNUC__
26 #include <uuid/uuid.h>
27 #include <sys/stat.h>
28 #endif
29 #include <string.h>
30 #ifndef __GNUC__
31 #include <io.h>
32 #endif
33 #include <assert.h>
34
35 #include "GenFvInternalLib.h"
36 #include "FvLib.h"
37 #include "PeCoffLib.h"
38 #include "WinNtInclude.h"
39
40 BOOLEAN mArm = FALSE;
41 STATIC UINT32 MaxFfsAlignment = 0;
42
43 EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
44 EFI_GUID mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV];
45 EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
46 EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};
47
48 CHAR8 *mFvbAttributeName[] = {
49 EFI_FVB2_READ_DISABLED_CAP_STRING,
50 EFI_FVB2_READ_ENABLED_CAP_STRING,
51 EFI_FVB2_READ_STATUS_STRING,
52 EFI_FVB2_WRITE_DISABLED_CAP_STRING,
53 EFI_FVB2_WRITE_ENABLED_CAP_STRING,
54 EFI_FVB2_WRITE_STATUS_STRING,
55 EFI_FVB2_LOCK_CAP_STRING,
56 EFI_FVB2_LOCK_STATUS_STRING,
57 NULL,
58 EFI_FVB2_STICKY_WRITE_STRING,
59 EFI_FVB2_MEMORY_MAPPED_STRING,
60 EFI_FVB2_ERASE_POLARITY_STRING,
61 EFI_FVB2_READ_LOCK_CAP_STRING,
62 EFI_FVB2_READ_LOCK_STATUS_STRING,
63 EFI_FVB2_WRITE_LOCK_CAP_STRING,
64 EFI_FVB2_WRITE_LOCK_STATUS_STRING
65 };
66
67 CHAR8 *mFvbAlignmentName[] = {
68 EFI_FVB2_ALIGNMENT_1_STRING,
69 EFI_FVB2_ALIGNMENT_2_STRING,
70 EFI_FVB2_ALIGNMENT_4_STRING,
71 EFI_FVB2_ALIGNMENT_8_STRING,
72 EFI_FVB2_ALIGNMENT_16_STRING,
73 EFI_FVB2_ALIGNMENT_32_STRING,
74 EFI_FVB2_ALIGNMENT_64_STRING,
75 EFI_FVB2_ALIGNMENT_128_STRING,
76 EFI_FVB2_ALIGNMENT_256_STRING,
77 EFI_FVB2_ALIGNMENT_512_STRING,
78 EFI_FVB2_ALIGNMENT_1K_STRING,
79 EFI_FVB2_ALIGNMENT_2K_STRING,
80 EFI_FVB2_ALIGNMENT_4K_STRING,
81 EFI_FVB2_ALIGNMENT_8K_STRING,
82 EFI_FVB2_ALIGNMENT_16K_STRING,
83 EFI_FVB2_ALIGNMENT_32K_STRING,
84 EFI_FVB2_ALIGNMENT_64K_STRING,
85 EFI_FVB2_ALIGNMENT_128K_STRING,
86 EFI_FVB2_ALIGNMENT_256K_STRING,
87 EFI_FVB2_ALIGNMNET_512K_STRING,
88 EFI_FVB2_ALIGNMENT_1M_STRING,
89 EFI_FVB2_ALIGNMENT_2M_STRING,
90 EFI_FVB2_ALIGNMENT_4M_STRING,
91 EFI_FVB2_ALIGNMENT_8M_STRING,
92 EFI_FVB2_ALIGNMENT_16M_STRING,
93 EFI_FVB2_ALIGNMENT_32M_STRING,
94 EFI_FVB2_ALIGNMENT_64M_STRING,
95 EFI_FVB2_ALIGNMENT_128M_STRING,
96 EFI_FVB2_ALIGNMENT_256M_STRING,
97 EFI_FVB2_ALIGNMENT_512M_STRING,
98 EFI_FVB2_ALIGNMENT_1G_STRING,
99 EFI_FVB2_ALIGNMENT_2G_STRING
100 };
101
102 //
103 // This data array will be located at the base of the Firmware Volume Header (FVH)
104 // in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
105 // will be used to keep the FVH checksum consistent.
106 // This code will be run in response to a starutp IPI for HT-enabled systems.
107 //
108 #define SIZEOF_STARTUP_DATA_ARRAY 0x10
109
110 UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
111 //
112 // EA D0 FF 00 F0 ; far jmp F000:FFD0
113 // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
114 // 0, 0 ; Checksum Padding
115 //
116 0xEA,
117 0xD0,
118 0xFF,
119 0x0,
120 0xF0,
121 0x00,
122 0x00,
123 0x00,
124 0x00,
125 0x00,
126 0x00,
127 0x00,
128 0x00,
129 0x00,
130 0x00,
131 0x00
132 };
133
134 UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
135 //
136 // EB CE ; jmp short ($-0x30)
137 // ; (from offset 0x0 to offset 0xFFD0)
138 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
139 // 0, 0 ; Checksum Padding
140 //
141 0xEB,
142 0xCE,
143 0x00,
144 0x00,
145 0x00,
146 0x00,
147 0x00,
148 0x00,
149 0x00,
150 0x00,
151 0x00,
152 0x00,
153 0x00,
154 0x00,
155 0x00,
156 0x00
157 };
158
159 FV_INFO mFvDataInfo;
160 CAP_INFO mCapDataInfo;
161
162 EFI_STATUS
163 ParseFvInf (
164 IN MEMORY_FILE *InfFile,
165 OUT FV_INFO *FvInfo
166 )
167 /*++
168
169 Routine Description:
170
171 This function parses a FV.INF file and copies info into a FV_INFO structure.
172
173 Arguments:
174
175 InfFile Memory file image.
176 FvInfo Information read from INF file.
177
178 Returns:
179
180 EFI_SUCCESS INF file information successfully retrieved.
181 EFI_ABORTED INF file has an invalid format.
182 EFI_NOT_FOUND A required string was not found in the INF file.
183 --*/
184 {
185 CHAR8 Value[_MAX_PATH];
186 UINT64 Value64;
187 UINTN Index;
188 UINTN Number;
189 EFI_STATUS Status;
190 EFI_GUID GuidValue;
191
192 //
193 // Read the FV base address
194 //
195 if (!mFvDataInfo.BaseAddressSet) {
196 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
197 if (Status == EFI_SUCCESS) {
198 //
199 // Get the base address
200 //
201 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
202 if (EFI_ERROR (Status)) {
203 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);
204 return EFI_ABORTED;
205 }
206 DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);
207
208 FvInfo->BaseAddress = Value64;
209 }
210 }
211
212 //
213 // Read the FV File System Guid
214 //
215 if (!FvInfo->FvFileSystemGuidSet) {
216 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILESYSTEMGUID_STRING, 0, Value);
217 if (Status == EFI_SUCCESS) {
218 //
219 // Get the guid value
220 //
221 Status = StringToGuid (Value, &GuidValue);
222 if (EFI_ERROR (Status)) {
223 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, Value);
224 return EFI_ABORTED;
225 }
226 memcpy (&FvInfo->FvFileSystemGuid, &GuidValue, sizeof (EFI_GUID));
227 FvInfo->FvFileSystemGuidSet = TRUE;
228 }
229 }
230
231 //
232 // Read the FV Name Guid
233 //
234 if (!FvInfo->FvNameGuidSet) {
235 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_NAMEGUID_STRING, 0, Value);
236 if (Status == EFI_SUCCESS) {
237 //
238 // Get the guid value
239 //
240 Status = StringToGuid (Value, &GuidValue);
241 if (EFI_ERROR (Status)) {
242 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_NAMEGUID_STRING, Value);
243 return EFI_ABORTED;
244 }
245 memcpy (&FvInfo->FvNameGuid, &GuidValue, sizeof (EFI_GUID));
246 FvInfo->FvNameGuidSet = TRUE;
247 }
248 }
249
250 //
251 // Read the FV file name
252 //
253 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
254 if (Status == EFI_SUCCESS) {
255 //
256 // copy the file name
257 //
258 strcpy (FvInfo->FvName, Value);
259 }
260
261 //
262 // Read Fv Attribute
263 //
264 for (Index = 0; Index < sizeof (mFvbAttributeName)/sizeof (CHAR8 *); Index ++) {
265 if ((mFvbAttributeName [Index] != NULL) && \
266 (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAttributeName [Index], 0, Value) == EFI_SUCCESS)) {
267 if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) {
268 FvInfo->FvAttributes |= 1 << Index;
269 } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) {
270 Error (NULL, 0, 2000, "Invalid parameter", "%s expected %s | %s", mFvbAttributeName [Index], TRUE_STRING, FALSE_STRING);
271 return EFI_ABORTED;
272 }
273 }
274 }
275
276 //
277 // Read Fv Alignment
278 //
279 for (Index = 0; Index < sizeof (mFvbAlignmentName)/sizeof (CHAR8 *); Index ++) {
280 if (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAlignmentName [Index], 0, Value) == EFI_SUCCESS) {
281 if (strcmp (Value, TRUE_STRING) == 0) {
282 FvInfo->FvAttributes |= Index << 16;
283 DebugMsg (NULL, 0, 9, "FV file alignment", "Align = %s", mFvbAlignmentName [Index]);
284 break;
285 }
286 }
287 }
288
289 //
290 // Read block maps
291 //
292 for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
293 if (FvInfo->FvBlocks[Index].Length == 0) {
294 //
295 // Read block size
296 //
297 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
298
299 if (Status == EFI_SUCCESS) {
300 //
301 // Update the size of block
302 //
303 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
304 if (EFI_ERROR (Status)) {
305 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_BLOCK_SIZE_STRING, Value);
306 return EFI_ABORTED;
307 }
308
309 FvInfo->FvBlocks[Index].Length = (UINT32) Value64;
310 DebugMsg (NULL, 0, 9, "FV Block Size", "%s = %s", EFI_BLOCK_SIZE_STRING, Value);
311 } else {
312 //
313 // If there is no blocks size, but there is the number of block, then we have a mismatched pair
314 // and should return an error.
315 //
316 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
317 if (!EFI_ERROR (Status)) {
318 Error (NULL, 0, 2000, "Invalid parameter", "both %s and %s must be specified.", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
319 return EFI_ABORTED;
320 } else {
321 //
322 // We are done
323 //
324 break;
325 }
326 }
327
328 //
329 // Read blocks number
330 //
331 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
332
333 if (Status == EFI_SUCCESS) {
334 //
335 // Update the number of blocks
336 //
337 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
338 if (EFI_ERROR (Status)) {
339 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_NUM_BLOCKS_STRING, Value);
340 return EFI_ABORTED;
341 }
342
343 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
344 DebugMsg (NULL, 0, 9, "FV Block Number", "%s = %s", EFI_NUM_BLOCKS_STRING, Value);
345 }
346 }
347 }
348
349 if (Index == 0) {
350 Error (NULL, 0, 2001, "Missing required argument", "block size.");
351 return EFI_ABORTED;
352 }
353
354 //
355 // Read files
356 //
357 Number = 0;
358 for (Number = 0; Number < MAX_NUMBER_OF_FILES_IN_FV; Number ++) {
359 if (FvInfo->FvFiles[Number][0] == '\0') {
360 break;
361 }
362 }
363
364 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
365 //
366 // Read the FFS file list
367 //
368 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
369
370 if (Status == EFI_SUCCESS) {
371 //
372 // Add the file
373 //
374 strcpy (FvInfo->FvFiles[Number + Index], Value);
375 DebugMsg (NULL, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index, Value);
376 } else {
377 break;
378 }
379 }
380
381 if ((Index + Number) == 0) {
382 Warning (NULL, 0, 0, "FV components are not specified.", NULL);
383 }
384
385 return EFI_SUCCESS;
386 }
387
388 VOID
389 UpdateFfsFileState (
390 IN EFI_FFS_FILE_HEADER *FfsFile,
391 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
392 )
393 /*++
394
395 Routine Description:
396
397 This function changes the FFS file attributes based on the erase polarity
398 of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY.
399
400 Arguments:
401
402 FfsFile File header.
403 FvHeader FV header.
404
405 Returns:
406
407 None
408
409 --*/
410 {
411 if (FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
412 FfsFile->State = (UINT8)~(FfsFile->State);
413 // FfsFile->State |= ~(UINT8) EFI_FILE_ALL_STATE_BITS;
414 }
415 }
416
417 EFI_STATUS
418 ReadFfsAlignment (
419 IN EFI_FFS_FILE_HEADER *FfsFile,
420 IN OUT UINT32 *Alignment
421 )
422 /*++
423
424 Routine Description:
425
426 This function determines the alignment of the FFS input file from the file
427 attributes.
428
429 Arguments:
430
431 FfsFile FFS file to parse
432 Alignment The minimum required alignment offset of the FFS file
433
434 Returns:
435
436 EFI_SUCCESS The function completed successfully.
437 EFI_INVALID_PARAMETER One of the input parameters was invalid.
438 EFI_ABORTED An error occurred.
439
440 --*/
441 {
442 //
443 // Verify input parameters.
444 //
445 if (FfsFile == NULL || Alignment == NULL) {
446 return EFI_INVALID_PARAMETER;
447 }
448
449 switch ((FfsFile->Attributes >> 3) & 0x07) {
450
451 case 0:
452 //
453 // 8 byte alignment, mini alignment requirement for FFS file.
454 //
455 *Alignment = 3;
456 break;
457
458 case 1:
459 //
460 // 16 byte alignment
461 //
462 *Alignment = 4;
463 break;
464
465 case 2:
466 //
467 // 128 byte alignment
468 //
469 *Alignment = 7;
470 break;
471
472 case 3:
473 //
474 // 512 byte alignment
475 //
476 *Alignment = 9;
477 break;
478
479 case 4:
480 //
481 // 1K byte alignment
482 //
483 *Alignment = 10;
484 break;
485
486 case 5:
487 //
488 // 4K byte alignment
489 //
490 *Alignment = 12;
491 break;
492
493 case 6:
494 //
495 // 32K byte alignment
496 //
497 *Alignment = 15;
498 break;
499
500 case 7:
501 //
502 // 64K byte alignment
503 //
504 *Alignment = 16;
505 break;
506
507 default:
508 break;
509 }
510
511 return EFI_SUCCESS;
512 }
513
514 EFI_STATUS
515 AddPadFile (
516 IN OUT MEMORY_FILE *FvImage,
517 IN UINT32 DataAlignment,
518 IN VOID *FvEnd,
519 IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader
520 )
521 /*++
522
523 Routine Description:
524
525 This function adds a pad file to the FV image if it required to align the
526 data of the next file.
527
528 Arguments:
529
530 FvImage The memory image of the FV to add it to.
531 The current offset must be valid.
532 DataAlignment The data alignment of the next FFS file.
533 FvEnd End of the empty data in FvImage.
534 ExtHeader PI FvExtHeader Optional
535
536 Returns:
537
538 EFI_SUCCESS The function completed successfully.
539 EFI_INVALID_PARAMETER One of the input parameters was invalid.
540 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
541 the pad file add.
542
543 --*/
544 {
545 EFI_FFS_FILE_HEADER *PadFile;
546 UINTN PadFileSize;
547
548 //
549 // Verify input parameters.
550 //
551 if (FvImage == NULL) {
552 return EFI_INVALID_PARAMETER;
553 }
554
555 //
556 // Check if a pad file is necessary
557 //
558 if ((ExtHeader == NULL) && (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0)) {
559 return EFI_SUCCESS;
560 }
561
562 //
563 // Calculate the pad file size
564 //
565 //
566 // This is the earliest possible valid offset (current plus pad file header
567 // plus the next file header)
568 //
569 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
570
571 //
572 // Add whatever it takes to get to the next aligned address
573 //
574 while ((PadFileSize % DataAlignment) != 0) {
575 PadFileSize++;
576 }
577 //
578 // Subtract the next file header size
579 //
580 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
581
582 //
583 // Subtract the starting offset to get size
584 //
585 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
586
587 //
588 // Append extension header size
589 //
590 if (ExtHeader != NULL) {
591 PadFileSize = PadFileSize + ExtHeader->ExtHeaderSize;
592 }
593
594 //
595 // Verify that we have enough space for the file header
596 //
597 if (((UINTN) FvImage->CurrentFilePointer + PadFileSize) > (UINTN) FvEnd) {
598 return EFI_OUT_OF_RESOURCES;
599 }
600
601 //
602 // Write pad file header
603 //
604 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
605
606 //
607 // Write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
608 //
609 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
610 PadFile->Attributes = 0;
611
612 //
613 // Write pad file size (calculated size minus next file header size)
614 //
615 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);
616 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);
617 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);
618
619 //
620 // Fill in checksums and state, they must be 0 for checksumming.
621 //
622 PadFile->IntegrityCheck.Checksum.Header = 0;
623 PadFile->IntegrityCheck.Checksum.File = 0;
624 PadFile->State = 0;
625 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
626 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
627
628 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
629 UpdateFfsFileState (
630 (EFI_FFS_FILE_HEADER *) PadFile,
631 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
632 );
633
634 //
635 // Update the current FV pointer
636 //
637 FvImage->CurrentFilePointer += PadFileSize;
638
639 if (ExtHeader != NULL) {
640 //
641 // Copy Fv Extension Header and Set Fv Extension header offset
642 //
643 memcpy (PadFile + 1, ExtHeader, ExtHeader->ExtHeaderSize);
644 ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) (PadFile + 1) - (UINTN) FvImage->FileImage);
645 //
646 // Make next file start at QWord Boundry
647 //
648 while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {
649 FvImage->CurrentFilePointer++;
650 }
651 }
652
653 return EFI_SUCCESS;
654 }
655
656 BOOLEAN
657 IsVtfFile (
658 IN EFI_FFS_FILE_HEADER *FileBuffer
659 )
660 /*++
661
662 Routine Description:
663
664 This function checks the header to validate if it is a VTF file
665
666 Arguments:
667
668 FileBuffer Buffer in which content of a file has been read.
669
670 Returns:
671
672 TRUE If this is a VTF file
673 FALSE If this is not a VTF file
674
675 --*/
676 {
677 if (!memcmp (&FileBuffer->Name, &mEfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID))) {
678 return TRUE;
679 } else {
680 return FALSE;
681 }
682 }
683
684 EFI_STATUS
685 WriteMapFile (
686 IN OUT FILE *FvMapFile,
687 IN CHAR8 *FileName,
688 IN EFI_GUID *FileGuidPtr,
689 IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
690 IN PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext
691 )
692 /*++
693
694 Routine Description:
695
696 This function gets the basic debug information (entrypoint, baseaddress, .text, .data section base address)
697 from PE/COFF image and abstracts Pe Map file information and add them into FvMap file for Debug.
698
699 Arguments:
700
701 FvMapFile A pointer to FvMap File
702 FileName Ffs File PathName
703 FileGuidPtr Guid Value of Ffs file
704 ImageBaseAddress PeImage Base Address.
705 pImageContext Image Context Information.
706
707 Returns:
708
709 EFI_SUCCESS Added required map information.
710
711 --*/
712 {
713 CHAR8 PeMapFileName [_MAX_PATH];
714 CHAR8 *Cptr, *Cptr2;
715 CHAR8 FileGuidName [MAX_LINE_LEN];
716 FILE *PeMapFile;
717 CHAR8 Line [MAX_LINE_LEN];
718 CHAR8 KeyWord [MAX_LINE_LEN];
719 CHAR8 FunctionName [MAX_LINE_LEN];
720 EFI_PHYSICAL_ADDRESS FunctionAddress;
721 UINT32 FunctionType;
722 CHAR8 FunctionTypeName [MAX_LINE_LEN];
723 UINT32 Index;
724 UINT32 AddressOfEntryPoint;
725 UINT32 Offset;
726 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
727 EFI_TE_IMAGE_HEADER *TEImageHeader;
728 EFI_IMAGE_SECTION_HEADER *SectionHeader;
729 unsigned long long TempLongAddress;
730 //
731 // Init local variable
732 //
733 FunctionType = 0;
734 //
735 // Print FileGuid to string buffer.
736 //
737 PrintGuidToBuffer (FileGuidPtr, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);
738
739 //
740 // Construct Map file Name
741 //
742 strcpy (PeMapFileName, FileName);
743
744 //
745 // Change '\\' to '/', unified path format.
746 //
747 Cptr = PeMapFileName;
748 while (*Cptr != '\0') {
749 if (*Cptr == '\\') {
750 *Cptr = FILE_SEP_CHAR;
751 }
752 Cptr ++;
753 }
754
755 //
756 // Get Map file
757 //
758 Cptr = PeMapFileName + strlen (PeMapFileName);
759 while ((*Cptr != '.') && (Cptr >= PeMapFileName)) {
760 Cptr --;
761 }
762 if (Cptr < PeMapFileName) {
763 return EFI_NOT_FOUND;
764 } else {
765 *(Cptr + 1) = 'm';
766 *(Cptr + 2) = 'a';
767 *(Cptr + 3) = 'p';
768 *(Cptr + 4) = '\0';
769 }
770
771 //
772 // Get module Name
773 //
774 Cptr2 = Cptr;
775 while ((*Cptr != FILE_SEP_CHAR) && (Cptr >= PeMapFileName)) {
776 Cptr --;
777 }
778 *Cptr2 = '\0';
779 strcpy (KeyWord, Cptr + 1);
780 *Cptr2 = '.';
781
782 //
783 // AddressOfEntryPoint and Offset in Image
784 //
785 if (!pImageContext->IsTeImage) {
786 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);
787 AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
788 Offset = 0;
789 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
790 (UINT8 *) ImgHdr +
791 sizeof (UINT32) +
792 sizeof (EFI_IMAGE_FILE_HEADER) +
793 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
794 );
795 Index = ImgHdr->Pe32.FileHeader.NumberOfSections;
796 } else {
797 TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle;
798 AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;
799 Offset = TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
800 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
801 Index = TEImageHeader->NumberOfSections;
802 }
803
804 //
805 // module information output
806 //
807 if (ImageBaseAddress == 0) {
808 fprintf (FvMapFile, "%s (dummy) (", KeyWord);
809 fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) ImageBaseAddress);
810 } else {
811 fprintf (FvMapFile, "%s (", KeyWord);
812 fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) (ImageBaseAddress + Offset));
813 }
814 fprintf (FvMapFile, "EntryPoint=%08llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
815 fprintf (FvMapFile, "GUID=%s", FileGuidName);
816 fprintf (FvMapFile, ")\n");
817
818 for (; Index > 0; Index --, SectionHeader ++) {
819 if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {
820 fprintf (FvMapFile, ".textbaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));
821 } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {
822 fprintf (FvMapFile, ".databaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));
823 }
824 }
825 fprintf (FvMapFile, "\n\n");
826
827 //
828 // Open PeMapFile
829 //
830 PeMapFile = fopen (PeMapFileName, "r");
831 if (PeMapFile == NULL) {
832 // fprintf (stdout, "can't open %s file to reading\n", PeMapFileName);
833 return EFI_ABORTED;
834 }
835 VerboseMsg ("The map file is %s", PeMapFileName);
836
837 //
838 // Output Functions information into Fv Map file
839 //
840 while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) {
841 //
842 // Skip blank line
843 //
844 if (Line[0] == 0x0a) {
845 FunctionType = 0;
846 continue;
847 }
848 //
849 // By Address and Static keyword
850 //
851 if (FunctionType == 0) {
852 sscanf (Line, "%s", KeyWord);
853 if (stricmp (KeyWord, "Address") == 0) {
854 //
855 // function list
856 //
857 FunctionType = 1;
858 fgets (Line, MAX_LINE_LEN, PeMapFile);
859 } else if (stricmp (KeyWord, "Static") == 0) {
860 //
861 // static function list
862 //
863 FunctionType = 2;
864 fgets (Line, MAX_LINE_LEN, PeMapFile);
865 }
866 continue;
867 }
868 //
869 // Printf Function Information
870 //
871 if (FunctionType == 1) {
872 sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);
873 FunctionAddress = (UINT64) TempLongAddress;
874 if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {
875 fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
876 fprintf (FvMapFile, "(%08llx) F ", (unsigned long long) (FunctionAddress - Offset));
877 fprintf (FvMapFile, "%s\n", FunctionName);
878 } else {
879 fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
880 fprintf (FvMapFile, "(%08llx) ", (unsigned long long) (FunctionAddress - Offset));
881 fprintf (FvMapFile, "%s\n", FunctionName);
882 }
883 } else if (FunctionType == 2) {
884 sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);
885 FunctionAddress = (UINT64) TempLongAddress;
886 if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {
887 fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
888 fprintf (FvMapFile, "(%08llx) FS ", (unsigned long long) (FunctionAddress - Offset));
889 fprintf (FvMapFile, "%s\n", FunctionName);
890 } else {
891 fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
892 fprintf (FvMapFile, "(%08llx) ", (unsigned long long) (FunctionAddress - Offset));
893 fprintf (FvMapFile, "%s\n", FunctionName);
894 }
895 }
896 }
897 //
898 // Close PeMap file
899 //
900 fprintf (FvMapFile, "\n\n");
901 fclose (PeMapFile);
902
903 return EFI_SUCCESS;
904 }
905
906 EFI_STATUS
907 AddFile (
908 IN OUT MEMORY_FILE *FvImage,
909 IN FV_INFO *FvInfo,
910 IN UINTN Index,
911 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
912 IN FILE *FvMapFile
913 )
914 /*++
915
916 Routine Description:
917
918 This function adds a file to the FV image. The file will pad to the
919 appropriate alignment if required.
920
921 Arguments:
922
923 FvImage The memory image of the FV to add it to. The current offset
924 must be valid.
925 FvInfo Pointer to information about the FV.
926 Index The file in the FvInfo file list to add.
927 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
928 to the end of the FvImage then no VTF previously found.
929 FvMapFile Pointer to FvMap File
930
931 Returns:
932
933 EFI_SUCCESS The function completed successfully.
934 EFI_INVALID_PARAMETER One of the input parameters was invalid.
935 EFI_ABORTED An error occurred.
936 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
937
938 --*/
939 {
940 FILE *NewFile;
941 UINTN FileSize;
942 UINT8 *FileBuffer;
943 UINTN NumBytesRead;
944 UINT32 CurrentFileAlignment;
945 EFI_STATUS Status;
946 UINTN Index1;
947
948 Index1 = 0;
949 //
950 // Verify input parameters.
951 //
952 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL) {
953 return EFI_INVALID_PARAMETER;
954 }
955
956 //
957 // Read the file to add
958 //
959 NewFile = fopen (FvInfo->FvFiles[Index], "rb");
960
961 if (NewFile == NULL) {
962 Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]);
963 return EFI_ABORTED;
964 }
965
966 //
967 // Get the file size
968 //
969 FileSize = _filelength (fileno (NewFile));
970
971 //
972 // Read the file into a buffer
973 //
974 FileBuffer = malloc (FileSize);
975 if (FileBuffer == NULL) {
976 Error (NULL, 0, 4001, "Resouce", "memory cannot be allocated!");
977 return EFI_OUT_OF_RESOURCES;
978 }
979
980 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
981
982 //
983 // Done with the file, from this point on we will just use the buffer read.
984 //
985 fclose (NewFile);
986
987 //
988 // Verify read successful
989 //
990 if (NumBytesRead != sizeof (UINT8) * FileSize) {
991 free (FileBuffer);
992 Error (NULL, 0, 0004, "Error reading file", FvInfo->FvFiles[Index]);
993 return EFI_ABORTED;
994 }
995
996 //
997 // For None PI Ffs file, directly add them into FvImage.
998 //
999 if (!FvInfo->IsPiFvImage) {
1000 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
1001 if (FvInfo->SizeofFvFiles[Index] > FileSize) {
1002 FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index];
1003 } else {
1004 FvImage->CurrentFilePointer += FileSize;
1005 }
1006 goto Done;
1007 }
1008
1009 //
1010 // Verify Ffs file
1011 //
1012 Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer);
1013 if (EFI_ERROR (Status)) {
1014 free (FileBuffer);
1015 Error (NULL, 0, 3000, "Invalid", "%s is a FFS file.", FvInfo->FvFiles[Index]);
1016 return EFI_INVALID_PARAMETER;
1017 }
1018
1019 //
1020 // Verify space exists to add the file
1021 //
1022 if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
1023 free (FileBuffer);
1024 Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s.", FvInfo->FvFiles[Index]);
1025 return EFI_OUT_OF_RESOURCES;
1026 }
1027
1028 //
1029 // Verify the input file is the duplicated file in this Fv image
1030 //
1031 for (Index1 = 0; Index1 < Index; Index1 ++) {
1032 if (CompareGuid ((EFI_GUID *) FileBuffer, &mFileGuidArray [Index1]) == 0) {
1033 Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %uth file have the same file GUID.", (unsigned) Index1 + 1, (unsigned) Index + 1);
1034 PrintGuid ((EFI_GUID *) FileBuffer);
1035 return EFI_INVALID_PARAMETER;
1036 }
1037 }
1038 CopyMem (&mFileGuidArray [Index], FileBuffer, sizeof (EFI_GUID));
1039
1040 //
1041 // Update the file state based on polarity of the FV.
1042 //
1043 UpdateFfsFileState (
1044 (EFI_FFS_FILE_HEADER *) FileBuffer,
1045 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
1046 );
1047
1048 //
1049 // Check if alignment is required
1050 //
1051 ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
1052
1053 //
1054 // Find the largest alignment of all the FFS files in the FV
1055 //
1056 if (CurrentFileAlignment > MaxFfsAlignment) {
1057 MaxFfsAlignment = CurrentFileAlignment;
1058 }
1059 //
1060 // If we have a VTF file, add it at the top.
1061 //
1062 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
1063 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
1064 //
1065 // No previous VTF, add this one.
1066 //
1067 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
1068 //
1069 // Sanity check. The file MUST align appropriately
1070 //
1071 if (((UINTN) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {
1072 Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %u-byte boundary.", (unsigned) (1 << CurrentFileAlignment));
1073 free (FileBuffer);
1074 return EFI_ABORTED;
1075 }
1076 //
1077 // Rebase the PE or TE image in FileBuffer of FFS file for XIP
1078 // Rebase for the debug genfvmap tool
1079 //
1080 FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
1081 //
1082 // copy VTF File
1083 //
1084 memcpy (*VtfFileImage, FileBuffer, FileSize);
1085 free (FileBuffer);
1086 DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL);
1087 return EFI_SUCCESS;
1088 } else {
1089 //
1090 // Already found a VTF file.
1091 //
1092 Error (NULL, 0, 3000, "Invalid", "multiple VTF files are not permitted within a single FV.");
1093 free (FileBuffer);
1094 return EFI_ABORTED;
1095 }
1096 }
1097
1098 //
1099 // Add pad file if necessary
1100 //
1101 Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL);
1102 if (EFI_ERROR (Status)) {
1103 Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");
1104 free (FileBuffer);
1105 return EFI_ABORTED;
1106 }
1107 //
1108 // Add file
1109 //
1110 if ((UINTN) (FvImage->CurrentFilePointer + FileSize) <= (UINTN) (*VtfFileImage)) {
1111 //
1112 // Rebase the PE or TE image in FileBuffer of FFS file for XIP.
1113 // Rebase Bs and Rt drivers for the debug genfvmap tool.
1114 //
1115 FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
1116 //
1117 // Copy the file
1118 //
1119 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
1120 FvImage->CurrentFilePointer += FileSize;
1121 } else {
1122 Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]);
1123 free (FileBuffer);
1124 return EFI_ABORTED;
1125 }
1126 //
1127 // Make next file start at QWord Boundry
1128 //
1129 while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {
1130 FvImage->CurrentFilePointer++;
1131 }
1132
1133 Done:
1134 //
1135 // Free allocated memory.
1136 //
1137 free (FileBuffer);
1138
1139 return EFI_SUCCESS;
1140 }
1141
1142 EFI_STATUS
1143 PadFvImage (
1144 IN MEMORY_FILE *FvImage,
1145 IN EFI_FFS_FILE_HEADER *VtfFileImage
1146 )
1147 /*++
1148
1149 Routine Description:
1150
1151 This function places a pad file between the last file in the FV and the VTF
1152 file if the VTF file exists.
1153
1154 Arguments:
1155
1156 FvImage Memory file for the FV memory image
1157 VtfFileImage The address of the VTF file. If this is the end of the FV
1158 image, no VTF exists and no pad file is needed.
1159
1160 Returns:
1161
1162 EFI_SUCCESS Completed successfully.
1163 EFI_INVALID_PARAMETER One of the input parameters was NULL.
1164
1165 --*/
1166 {
1167 EFI_FFS_FILE_HEADER *PadFile;
1168 UINTN FileSize;
1169
1170 //
1171 // If there is no VTF or the VTF naturally follows the previous file without a
1172 // pad file, then there's nothing to do
1173 //
1174 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || \
1175 ((UINTN) VtfFileImage == (UINTN) FvImage->CurrentFilePointer)) {
1176 return EFI_SUCCESS;
1177 }
1178
1179 if ((UINTN) VtfFileImage < (UINTN) FvImage->CurrentFilePointer) {
1180 return EFI_INVALID_PARAMETER;
1181 }
1182
1183 //
1184 // Pad file starts at beginning of free space
1185 //
1186 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
1187
1188 //
1189 // write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
1190 //
1191 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
1192 PadFile->Attributes = 0;
1193
1194 //
1195 // FileSize includes the EFI_FFS_FILE_HEADER
1196 //
1197 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
1198 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
1199 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
1200 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
1201
1202 //
1203 // Fill in checksums and state, must be zero during checksum calculation.
1204 //
1205 PadFile->IntegrityCheck.Checksum.Header = 0;
1206 PadFile->IntegrityCheck.Checksum.File = 0;
1207 PadFile->State = 0;
1208 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
1209 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1210
1211 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
1212
1213 UpdateFfsFileState (
1214 (EFI_FFS_FILE_HEADER *) PadFile,
1215 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
1216 );
1217 //
1218 // Update the current FV pointer
1219 //
1220 FvImage->CurrentFilePointer = FvImage->Eof;
1221
1222 return EFI_SUCCESS;
1223 }
1224
1225 EFI_STATUS
1226 UpdateResetVector (
1227 IN MEMORY_FILE *FvImage,
1228 IN FV_INFO *FvInfo,
1229 IN EFI_FFS_FILE_HEADER *VtfFile
1230 )
1231 /*++
1232
1233 Routine Description:
1234
1235 This parses the FV looking for the PEI core and then plugs the address into
1236 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
1237 complete an IA32 Bootstrap FV.
1238
1239 Arguments:
1240
1241 FvImage Memory file for the FV memory image
1242 FvInfo Information read from INF file.
1243 VtfFile Pointer to the VTF file in the FV image.
1244
1245 Returns:
1246
1247 EFI_SUCCESS Function Completed successfully.
1248 EFI_ABORTED Error encountered.
1249 EFI_INVALID_PARAMETER A required parameter was NULL.
1250 EFI_NOT_FOUND PEI Core file not found.
1251
1252 --*/
1253 {
1254 EFI_FFS_FILE_HEADER *PeiCoreFile;
1255 EFI_FFS_FILE_HEADER *SecCoreFile;
1256 EFI_STATUS Status;
1257 EFI_FILE_SECTION_POINTER Pe32Section;
1258 UINT32 EntryPoint;
1259 UINT32 BaseOfCode;
1260 UINT16 MachineType;
1261 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
1262 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
1263 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;
1264 INT32 Ia32SecEntryOffset;
1265 UINT32 *Ia32ResetAddressPtr;
1266 UINT8 *BytePointer;
1267 UINT8 *BytePointer2;
1268 UINT16 *WordPointer;
1269 UINT16 CheckSum;
1270 UINT32 IpiVector;
1271 UINTN Index;
1272 EFI_FFS_FILE_STATE SavedState;
1273 UINT64 FitAddress;
1274 FIT_TABLE *FitTablePtr;
1275
1276 //
1277 // Verify input parameters
1278 //
1279 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
1280 return EFI_INVALID_PARAMETER;
1281 }
1282 //
1283 // Initialize FV library
1284 //
1285 InitializeFvLib (FvImage->FileImage, FvInfo->Size);
1286
1287 //
1288 // Verify VTF file
1289 //
1290 Status = VerifyFfsFile (VtfFile);
1291 if (EFI_ERROR (Status)) {
1292 return EFI_INVALID_PARAMETER;
1293 }
1294
1295 //
1296 // Find the Sec Core
1297 //
1298 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
1299 if (EFI_ERROR (Status) || SecCoreFile == NULL) {
1300 Error (NULL, 0, 3000, "Invalid", "could not find the SEC core file in the FV.");
1301 return EFI_ABORTED;
1302 }
1303 //
1304 // Sec Core found, now find PE32 section
1305 //
1306 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
1307 if (Status == EFI_NOT_FOUND) {
1308 Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
1309 }
1310
1311 if (EFI_ERROR (Status)) {
1312 Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file.");
1313 return EFI_ABORTED;
1314 }
1315
1316 Status = GetPe32Info (
1317 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1318 &EntryPoint,
1319 &BaseOfCode,
1320 &MachineType
1321 );
1322
1323 if (EFI_ERROR (Status)) {
1324 Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");
1325 return EFI_ABORTED;
1326 }
1327
1328 //
1329 // Physical address is FV base + offset of PE32 + offset of the entry point
1330 //
1331 SecCorePhysicalAddress = FvInfo->BaseAddress;
1332 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
1333 SecCorePhysicalAddress += EntryPoint;
1334 DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
1335
1336 //
1337 // Find the PEI Core
1338 //
1339 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
1340 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
1341 Error (NULL, 0, 3000, "Invalid", "could not find the PEI core in the FV.");
1342 return EFI_ABORTED;
1343 }
1344 //
1345 // PEI Core found, now find PE32 or TE section
1346 //
1347 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
1348 if (Status == EFI_NOT_FOUND) {
1349 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
1350 }
1351
1352 if (EFI_ERROR (Status)) {
1353 Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file.");
1354 return EFI_ABORTED;
1355 }
1356
1357 Status = GetPe32Info (
1358 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1359 &EntryPoint,
1360 &BaseOfCode,
1361 &MachineType
1362 );
1363
1364 if (EFI_ERROR (Status)) {
1365 Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core.");
1366 return EFI_ABORTED;
1367 }
1368 //
1369 // Physical address is FV base + offset of PE32 + offset of the entry point
1370 //
1371 PeiCorePhysicalAddress = FvInfo->BaseAddress;
1372 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
1373 PeiCorePhysicalAddress += EntryPoint;
1374 DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
1375
1376 if (MachineType == EFI_IMAGE_MACHINE_IA64) {
1377 //
1378 // Update PEI_CORE address
1379 //
1380 //
1381 // Set the uncached attribute bit in the physical address
1382 //
1383 PeiCorePhysicalAddress |= 0x8000000000000000ULL;
1384
1385 //
1386 // Check if address is aligned on a 16 byte boundary
1387 //
1388 if (PeiCorePhysicalAddress & 0xF) {
1389 Error (NULL, 0, 3000, "Invalid",
1390 "PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %llXh.",
1391 (unsigned long long) PeiCorePhysicalAddress
1392 );
1393 return EFI_ABORTED;
1394 }
1395 //
1396 // First Get the FIT table address
1397 //
1398 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
1399
1400 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
1401
1402 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
1403
1404 if (!EFI_ERROR (Status)) {
1405 UpdateFitCheckSum (FitTablePtr);
1406 }
1407
1408 //
1409 // Update SEC_CORE address
1410 //
1411 //
1412 // Set the uncached attribute bit in the physical address
1413 //
1414 SecCorePhysicalAddress |= 0x8000000000000000ULL;
1415 //
1416 // Check if address is aligned on a 16 byte boundary
1417 //
1418 if (SecCorePhysicalAddress & 0xF) {
1419 Error (NULL, 0, 3000, "Invalid",
1420 "SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %llXh.",
1421 (unsigned long long) SecCorePhysicalAddress
1422 );
1423 return EFI_ABORTED;
1424 }
1425 //
1426 // Update the address
1427 //
1428 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
1429 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
1430
1431 } else if (
1432 (MachineType == EFI_IMAGE_MACHINE_IA32 ||
1433 MachineType == EFI_IMAGE_MACHINE_X64) &&
1434 (((UINTN)FvImage->Eof - (UINTN)FvImage->FileImage) >= IA32_X64_VTF_SIGNATURE_OFFSET) &&
1435 (*(UINT32 *)(VOID*)((UINTN) FvImage->Eof - IA32_X64_VTF_SIGNATURE_OFFSET) ==
1436 IA32_X64_VTF0_SIGNATURE)
1437 ) {
1438 //
1439 // If VTF-0 signature is found, then no modifications are needed.
1440 //
1441 } else if (MachineType == EFI_IMAGE_MACHINE_IA32 || MachineType == EFI_IMAGE_MACHINE_X64) {
1442 //
1443 // Get the location to update
1444 //
1445 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
1446
1447 //
1448 // Write lower 32 bits of physical address for Pei Core entry
1449 //
1450 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
1451
1452 //
1453 // Write SecCore Entry point relative address into the jmp instruction in reset vector.
1454 //
1455 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET);
1456
1457 Ia32SecEntryOffset = (INT32) (SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2));
1458 if (Ia32SecEntryOffset <= -65536) {
1459 Error (NULL, 0, 3000, "Invalid", "The SEC EXE file size is too large, it must be less than 64K.");
1460 return STATUS_ERROR;
1461 }
1462
1463 *(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset;
1464
1465 //
1466 // Update the BFV base address
1467 //
1468 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
1469 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
1470 DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%llX.", (unsigned long long) FvInfo->BaseAddress);
1471
1472 //
1473 // Update the Startup AP in the FVH header block ZeroVector region.
1474 //
1475 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
1476 if (FvInfo->Size <= 0x10000) {
1477 BytePointer2 = m64kRecoveryStartupApDataArray;
1478 } else if (FvInfo->Size <= 0x20000) {
1479 BytePointer2 = m128kRecoveryStartupApDataArray;
1480 } else {
1481 BytePointer2 = m128kRecoveryStartupApDataArray;
1482 //
1483 // Find the position to place Ap reset vector, the offset
1484 // between the position and the end of Fvrecovery.fv file
1485 // should not exceed 128kB to prevent Ap reset vector from
1486 // outside legacy E and F segment
1487 //
1488 Status = FindApResetVectorPosition (FvImage, &BytePointer);
1489 if (EFI_ERROR (Status)) {
1490 Error (NULL, 0, 3000, "Invalid", "Cannot find the appropriate location in FvImage to add Ap reset vector!");
1491 return EFI_ABORTED;
1492 }
1493 }
1494
1495 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
1496 BytePointer[Index] = BytePointer2[Index];
1497 }
1498 //
1499 // Calculate the checksum
1500 //
1501 CheckSum = 0x0000;
1502 WordPointer = (UINT16 *) (BytePointer);
1503 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
1504 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
1505 WordPointer++;
1506 }
1507 //
1508 // Update the checksum field
1509 //
1510 WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2);
1511 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
1512
1513 //
1514 // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.
1515 //
1516 IpiVector = (UINT32) (FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer));
1517 DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", (unsigned) IpiVector);
1518 if ((IpiVector & 0xFFF) != 0) {
1519 Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned");
1520 return EFI_ABORTED;
1521 }
1522 IpiVector = IpiVector >> 12;
1523 IpiVector = IpiVector & 0xFF;
1524
1525 //
1526 // Write IPI Vector at Offset FvrecoveryFileSize - 8
1527 //
1528 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 8);
1529 *Ia32ResetAddressPtr = IpiVector;
1530 } else if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
1531 //
1532 // Since the ARM reset vector is in the FV Header you really don't need a
1533 // Volume Top File, but if you have one for some reason don't crash...
1534 //
1535 } else {
1536 Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType);
1537 return EFI_ABORTED;
1538 }
1539
1540 //
1541 // Now update file checksum
1542 //
1543 SavedState = VtfFile->State;
1544 VtfFile->IntegrityCheck.Checksum.File = 0;
1545 VtfFile->State = 0;
1546 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
1547 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
1548 (UINT8 *) VtfFile,
1549 GetLength (VtfFile->Size)
1550 );
1551 } else {
1552 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1553 }
1554
1555 VtfFile->State = SavedState;
1556
1557 return EFI_SUCCESS;
1558 }
1559
1560
1561 EFI_STATUS
1562 UpdateArmResetVectorIfNeeded (
1563 IN MEMORY_FILE *FvImage,
1564 IN FV_INFO *FvInfo
1565 )
1566 /*++
1567
1568 Routine Description:
1569 This parses the FV looking for SEC and patches that address into the
1570 beginning of the FV header.
1571
1572 For ARM the reset vector is at 0x00000000 or 0xFFFF0000.
1573 This would commonly map to the first entry in the ROM.
1574 ARM Exceptions:
1575 Reset +0
1576 Undefined +4
1577 SWI +8
1578 Prefetch Abort +12
1579 Data Abort +16
1580 IRQ +20
1581 FIQ +24
1582
1583 We support two schemes on ARM.
1584 1) Beginning of the FV is the reset vector
1585 2) Reset vector is data bytes FDF file and that code branches to reset vector
1586 in the beginning of the FV (fixed size offset).
1587
1588
1589 Need to have the jump for the reset vector at location zero.
1590 We also need to store the address or PEI (if it exists).
1591 We stub out a return from interrupt in case the debugger
1592 is using SWI.
1593 The optional entry to the common exception handler is
1594 to support full featured exception handling from ROM and is currently
1595 not support by this tool.
1596
1597 Arguments:
1598 FvImage Memory file for the FV memory image
1599 FvInfo Information read from INF file.
1600
1601 Returns:
1602
1603 EFI_SUCCESS Function Completed successfully.
1604 EFI_ABORTED Error encountered.
1605 EFI_INVALID_PARAMETER A required parameter was NULL.
1606 EFI_NOT_FOUND PEI Core file not found.
1607
1608 --*/
1609 {
1610 EFI_FFS_FILE_HEADER *PeiCoreFile;
1611 EFI_FFS_FILE_HEADER *SecCoreFile;
1612 EFI_STATUS Status;
1613 EFI_FILE_SECTION_POINTER Pe32Section;
1614 UINT32 EntryPoint;
1615 UINT32 BaseOfCode;
1616 UINT16 MachineType;
1617 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
1618 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
1619 INT32 ResetVector[4]; // 0 - is branch relative to SEC entry point
1620 // 1 - PEI Entry Point
1621 // 2 - movs pc,lr for a SWI handler
1622 // 3 - Place holder for Common Exception Handler
1623
1624 //
1625 // Verify input parameters
1626 //
1627 if (FvImage == NULL || FvInfo == NULL) {
1628 return EFI_INVALID_PARAMETER;
1629 }
1630 //
1631 // Initialize FV library
1632 //
1633 InitializeFvLib (FvImage->FileImage, FvInfo->Size);
1634
1635 //
1636 // Find the Sec Core
1637 //
1638 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
1639 if (EFI_ERROR (Status) || SecCoreFile == NULL) {
1640 //
1641 // Maybe hardware does SEC job and we only have PEI Core?
1642 //
1643
1644 //
1645 // Find the PEI Core. It may not exist if SEC loads DXE core directly
1646 //
1647 PeiCorePhysicalAddress = 0;
1648 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
1649 if (!EFI_ERROR (Status) && PeiCoreFile != NULL) {
1650 //
1651 // PEI Core found, now find PE32 or TE section
1652 //
1653 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
1654 if (Status == EFI_NOT_FOUND) {
1655 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
1656 }
1657
1658 if (EFI_ERROR (Status)) {
1659 Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!");
1660 return EFI_ABORTED;
1661 }
1662
1663 Status = GetPe32Info (
1664 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1665 &EntryPoint,
1666 &BaseOfCode,
1667 &MachineType
1668 );
1669
1670 if (EFI_ERROR (Status)) {
1671 Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!");
1672 return EFI_ABORTED;
1673 }
1674 //
1675 // Physical address is FV base + offset of PE32 + offset of the entry point
1676 //
1677 PeiCorePhysicalAddress = FvInfo->BaseAddress;
1678 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
1679 PeiCorePhysicalAddress += EntryPoint;
1680 DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
1681
1682 if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
1683 memset (ResetVector, 0, sizeof (ResetVector));
1684 // Address of PEI Core, if we have one
1685 ResetVector[1] = (UINT32)PeiCorePhysicalAddress;
1686 }
1687
1688 //
1689 // Copy to the beginning of the FV
1690 //
1691 memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector));
1692
1693 }
1694
1695 return EFI_SUCCESS;
1696 }
1697
1698 //
1699 // Sec Core found, now find PE32 section
1700 //
1701 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
1702 if (Status == EFI_NOT_FOUND) {
1703 Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
1704 }
1705
1706 if (EFI_ERROR (Status)) {
1707 Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file.");
1708 return EFI_ABORTED;
1709 }
1710
1711 Status = GetPe32Info (
1712 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1713 &EntryPoint,
1714 &BaseOfCode,
1715 &MachineType
1716 );
1717 if (EFI_ERROR (Status)) {
1718 Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");
1719 return EFI_ABORTED;
1720 }
1721
1722 if (MachineType != EFI_IMAGE_MACHINE_ARMT) {
1723 //
1724 // If SEC is not ARM we have nothing to do
1725 //
1726 return EFI_SUCCESS;
1727 }
1728
1729 //
1730 // Physical address is FV base + offset of PE32 + offset of the entry point
1731 //
1732 SecCorePhysicalAddress = FvInfo->BaseAddress;
1733 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
1734 SecCorePhysicalAddress += EntryPoint;
1735 DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
1736
1737 //
1738 // Find the PEI Core. It may not exist if SEC loads DXE core directly
1739 //
1740 PeiCorePhysicalAddress = 0;
1741 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
1742 if (!EFI_ERROR (Status) && PeiCoreFile != NULL) {
1743 //
1744 // PEI Core found, now find PE32 or TE section
1745 //
1746 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
1747 if (Status == EFI_NOT_FOUND) {
1748 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
1749 }
1750
1751 if (EFI_ERROR (Status)) {
1752 Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!");
1753 return EFI_ABORTED;
1754 }
1755
1756 Status = GetPe32Info (
1757 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1758 &EntryPoint,
1759 &BaseOfCode,
1760 &MachineType
1761 );
1762
1763 if (EFI_ERROR (Status)) {
1764 Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!");
1765 return EFI_ABORTED;
1766 }
1767 //
1768 // Physical address is FV base + offset of PE32 + offset of the entry point
1769 //
1770 PeiCorePhysicalAddress = FvInfo->BaseAddress;
1771 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
1772 PeiCorePhysicalAddress += EntryPoint;
1773 DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
1774 }
1775
1776
1777 // B SecEntryPoint - signed_immed_24 part +/-32MB offset
1778 // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8
1779 ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;
1780
1781 if (ResetVector[0] > 0x00FFFFFF) {
1782 Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");
1783 return EFI_ABORTED;
1784 }
1785
1786 // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint
1787 ResetVector[0] |= 0xEA000000;
1788
1789
1790 // Address of PEI Core, if we have one
1791 ResetVector[1] = (UINT32)PeiCorePhysicalAddress;
1792
1793 // SWI handler movs pc,lr. Just in case a debugger uses SWI
1794 ResetVector[2] = 0xE1B0F07E;
1795
1796 // Place holder to support a common interrupt handler from ROM.
1797 // Currently not suppprted. For this to be used the reset vector would not be in this FV
1798 // and the exception vectors would be hard coded in the ROM and just through this address
1799 // to find a common handler in the a module in the FV.
1800 ResetVector[3] = 0;
1801
1802 //
1803 // Copy to the beginning of the FV
1804 //
1805 memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector));
1806
1807 DebugMsg (NULL, 0, 9, "Update Reset vector in FV Header", NULL);
1808
1809 return EFI_SUCCESS;
1810 }
1811
1812 EFI_STATUS
1813 GetPe32Info (
1814 IN UINT8 *Pe32,
1815 OUT UINT32 *EntryPoint,
1816 OUT UINT32 *BaseOfCode,
1817 OUT UINT16 *MachineType
1818 )
1819 /*++
1820
1821 Routine Description:
1822
1823 Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
1824 See EfiImage.h for machine types. The entry point offset is from the beginning
1825 of the PE32 buffer passed in.
1826
1827 Arguments:
1828
1829 Pe32 Beginning of the PE32.
1830 EntryPoint Offset from the beginning of the PE32 to the image entry point.
1831 BaseOfCode Base address of code.
1832 MachineType Magic number for the machine type.
1833
1834 Returns:
1835
1836 EFI_SUCCESS Function completed successfully.
1837 EFI_ABORTED Error encountered.
1838 EFI_INVALID_PARAMETER A required parameter was NULL.
1839 EFI_UNSUPPORTED The operation is unsupported.
1840
1841 --*/
1842 {
1843 EFI_IMAGE_DOS_HEADER *DosHeader;
1844 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
1845 EFI_TE_IMAGE_HEADER *TeHeader;
1846
1847 //
1848 // Verify input parameters
1849 //
1850 if (Pe32 == NULL) {
1851 return EFI_INVALID_PARAMETER;
1852 }
1853
1854 //
1855 // First check whether it is one TE Image.
1856 //
1857 TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
1858 if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
1859 //
1860 // By TeImage Header to get output
1861 //
1862 *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
1863 *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
1864 *MachineType = TeHeader->Machine;
1865 } else {
1866
1867 //
1868 // Then check whether
1869 // First is the DOS header
1870 //
1871 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
1872
1873 //
1874 // Verify DOS header is expected
1875 //
1876 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
1877 Error (NULL, 0, 3000, "Invalid", "Unknown magic number in the DOS header, 0x%04X.", DosHeader->e_magic);
1878 return EFI_UNSUPPORTED;
1879 }
1880 //
1881 // Immediately following is the NT header.
1882 //
1883 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN) Pe32 + DosHeader->e_lfanew);
1884
1885 //
1886 // Verify NT header is expected
1887 //
1888 if (ImgHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
1889 Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", (unsigned) ImgHdr->Pe32.Signature);
1890 return EFI_UNSUPPORTED;
1891 }
1892 //
1893 // Get output
1894 //
1895 *EntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
1896 *BaseOfCode = ImgHdr->Pe32.OptionalHeader.BaseOfCode;
1897 *MachineType = ImgHdr->Pe32.FileHeader.Machine;
1898 }
1899
1900 //
1901 // Verify machine type is supported
1902 //
1903 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC &&
1904 *MachineType != EFI_IMAGE_MACHINE_ARMT) {
1905 Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");
1906 return EFI_UNSUPPORTED;
1907 }
1908
1909 return EFI_SUCCESS;
1910 }
1911
1912 EFI_STATUS
1913 GenerateFvImage (
1914 IN CHAR8 *InfFileImage,
1915 IN UINTN InfFileSize,
1916 IN CHAR8 *FvFileName,
1917 IN CHAR8 *MapFileName
1918 )
1919 /*++
1920
1921 Routine Description:
1922
1923 This is the main function which will be called from application.
1924
1925 Arguments:
1926
1927 InfFileImage Buffer containing the INF file contents.
1928 InfFileSize Size of the contents of the InfFileImage buffer.
1929 FvFileName Requested name for the FV file.
1930 MapFileName Fv map file to log fv driver information.
1931
1932 Returns:
1933
1934 EFI_SUCCESS Function completed successfully.
1935 EFI_OUT_OF_RESOURCES Could not allocate required resources.
1936 EFI_ABORTED Error encountered.
1937 EFI_INVALID_PARAMETER A required parameter was NULL.
1938
1939 --*/
1940 {
1941 EFI_STATUS Status;
1942 MEMORY_FILE InfMemoryFile;
1943 MEMORY_FILE FvImageMemoryFile;
1944 UINTN Index;
1945 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1946 EFI_FFS_FILE_HEADER *VtfFileImage;
1947 UINT8 *FvBufferHeader; // to make sure fvimage header 8 type alignment.
1948 UINT8 *FvImage;
1949 UINTN FvImageSize;
1950 FILE *FvFile;
1951 CHAR8 FvMapName [_MAX_PATH];
1952 FILE *FvMapFile;
1953 EFI_FIRMWARE_VOLUME_EXT_HEADER FvExtHeader;
1954
1955 FvBufferHeader = NULL;
1956 FvFile = NULL;
1957 FvMapFile = NULL;
1958
1959 if (InfFileImage != NULL) {
1960 //
1961 // Initialize file structures
1962 //
1963 InfMemoryFile.FileImage = InfFileImage;
1964 InfMemoryFile.CurrentFilePointer = InfFileImage;
1965 InfMemoryFile.Eof = InfFileImage + InfFileSize;
1966
1967 //
1968 // Parse the FV inf file for header information
1969 //
1970 Status = ParseFvInf (&InfMemoryFile, &mFvDataInfo);
1971 if (EFI_ERROR (Status)) {
1972 Error (NULL, 0, 0003, "Error parsing file", "the input FV INF file.");
1973 return Status;
1974 }
1975 }
1976
1977 //
1978 // Update the file name return values
1979 //
1980 if (FvFileName == NULL && mFvDataInfo.FvName[0] != '\0') {
1981 FvFileName = mFvDataInfo.FvName;
1982 }
1983
1984 if (FvFileName == NULL) {
1985 Error (NULL, 0, 1001, "Missing option", "Output file name");
1986 return EFI_ABORTED;
1987 }
1988
1989 if (mFvDataInfo.FvBlocks[0].Length == 0) {
1990 Error (NULL, 0, 1001, "Missing required argument", "Block Size");
1991 return EFI_ABORTED;
1992 }
1993
1994 //
1995 // Debug message Fv File System Guid
1996 //
1997 if (mFvDataInfo.FvFileSystemGuidSet) {
1998 DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1999 (unsigned) mFvDataInfo.FvFileSystemGuid.Data1,
2000 mFvDataInfo.FvFileSystemGuid.Data2,
2001 mFvDataInfo.FvFileSystemGuid.Data3,
2002 mFvDataInfo.FvFileSystemGuid.Data4[0],
2003 mFvDataInfo.FvFileSystemGuid.Data4[1],
2004 mFvDataInfo.FvFileSystemGuid.Data4[2],
2005 mFvDataInfo.FvFileSystemGuid.Data4[3],
2006 mFvDataInfo.FvFileSystemGuid.Data4[4],
2007 mFvDataInfo.FvFileSystemGuid.Data4[5],
2008 mFvDataInfo.FvFileSystemGuid.Data4[6],
2009 mFvDataInfo.FvFileSystemGuid.Data4[7]);
2010 }
2011 //
2012 // Debug message Fv Name Guid
2013 //
2014 if (mFvDataInfo.FvNameGuidSet) {
2015 DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
2016 (unsigned) mFvDataInfo.FvNameGuid.Data1,
2017 mFvDataInfo.FvNameGuid.Data2,
2018 mFvDataInfo.FvNameGuid.Data3,
2019 mFvDataInfo.FvNameGuid.Data4[0],
2020 mFvDataInfo.FvNameGuid.Data4[1],
2021 mFvDataInfo.FvNameGuid.Data4[2],
2022 mFvDataInfo.FvNameGuid.Data4[3],
2023 mFvDataInfo.FvNameGuid.Data4[4],
2024 mFvDataInfo.FvNameGuid.Data4[5],
2025 mFvDataInfo.FvNameGuid.Data4[6],
2026 mFvDataInfo.FvNameGuid.Data4[7]);
2027 }
2028
2029 if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {
2030 mFvDataInfo.IsPiFvImage = TRUE;
2031 }
2032
2033 //
2034 // FvMap file to log the function address of all modules in one Fvimage
2035 //
2036 if (MapFileName != NULL) {
2037 strcpy (FvMapName, MapFileName);
2038 } else {
2039 strcpy (FvMapName, FvFileName);
2040 strcat (FvMapName, ".map");
2041 }
2042 VerboseMsg ("FV Map file name is %s", FvMapName);
2043
2044 //
2045 // Calculate the FV size and Update Fv Size based on the actual FFS files.
2046 // And Update mFvDataInfo data.
2047 //
2048 Status = CalculateFvSize (&mFvDataInfo);
2049 if (EFI_ERROR (Status)) {
2050 return Status;
2051 }
2052 VerboseMsg ("the generated FV image size is %u bytes", (unsigned) mFvDataInfo.Size);
2053
2054 //
2055 // support fv image and empty fv image
2056 //
2057 FvImageSize = mFvDataInfo.Size;
2058
2059 //
2060 // Allocate the FV, assure FvImage Header 8 byte alignment
2061 //
2062 FvBufferHeader = malloc (FvImageSize + sizeof (UINT64));
2063 if (FvBufferHeader == NULL) {
2064 return EFI_OUT_OF_RESOURCES;
2065 }
2066 FvImage = (UINT8 *) (((UINTN) FvBufferHeader + 7) & ~7);
2067
2068 //
2069 // Initialize the FV to the erase polarity
2070 //
2071 if (mFvDataInfo.FvAttributes == 0) {
2072 //
2073 // Set Default Fv Attribute
2074 //
2075 mFvDataInfo.FvAttributes = FV_DEFAULT_ATTRIBUTE;
2076 }
2077 if (mFvDataInfo.FvAttributes & EFI_FVB2_ERASE_POLARITY) {
2078 memset (FvImage, -1, FvImageSize);
2079 } else {
2080 memset (FvImage, 0, FvImageSize);
2081 }
2082
2083 //
2084 // Initialize FV header
2085 //
2086 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
2087
2088 //
2089 // Initialize the zero vector to all zeros.
2090 //
2091 memset (FvHeader->ZeroVector, 0, 16);
2092
2093 //
2094 // Copy the Fv file system GUID
2095 //
2096 memcpy (&FvHeader->FileSystemGuid, &mFvDataInfo.FvFileSystemGuid, sizeof (EFI_GUID));
2097
2098 FvHeader->FvLength = FvImageSize;
2099 FvHeader->Signature = EFI_FVH_SIGNATURE;
2100 FvHeader->Attributes = mFvDataInfo.FvAttributes;
2101 FvHeader->Revision = EFI_FVH_REVISION;
2102 FvHeader->ExtHeaderOffset = 0;
2103 FvHeader->Reserved[0] = 0;
2104
2105 //
2106 // Copy firmware block map
2107 //
2108 for (Index = 0; mFvDataInfo.FvBlocks[Index].Length != 0; Index++) {
2109 FvHeader->BlockMap[Index].NumBlocks = mFvDataInfo.FvBlocks[Index].NumBlocks;
2110 FvHeader->BlockMap[Index].Length = mFvDataInfo.FvBlocks[Index].Length;
2111 }
2112
2113 //
2114 // Add block map terminator
2115 //
2116 FvHeader->BlockMap[Index].NumBlocks = 0;
2117 FvHeader->BlockMap[Index].Length = 0;
2118
2119 //
2120 // Complete the header
2121 //
2122 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->BlockMap[Index + 1])) - (UINTN) FvImage);
2123 FvHeader->Checksum = 0;
2124 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2125
2126 //
2127 // If there is no FFS file, generate one empty FV
2128 //
2129 if (mFvDataInfo.FvFiles[0][0] == 0 && !mFvDataInfo.FvNameGuidSet) {
2130 goto WriteFile;
2131 }
2132
2133 //
2134 // Initialize our "file" view of the buffer
2135 //
2136 FvImageMemoryFile.FileImage = (CHAR8 *)FvImage;
2137 FvImageMemoryFile.CurrentFilePointer = (CHAR8 *)FvImage + FvHeader->HeaderLength;
2138 FvImageMemoryFile.Eof = (CHAR8 *)FvImage + FvImageSize;
2139
2140 //
2141 // Initialize the FV library.
2142 //
2143 InitializeFvLib (FvImageMemoryFile.FileImage, FvImageSize);
2144
2145 //
2146 // Initialize the VTF file address.
2147 //
2148 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
2149
2150 //
2151 // Open FvMap file
2152 //
2153 FvMapFile = fopen (FvMapName, "w");
2154 if (FvMapFile == NULL) {
2155 Error (NULL, 0, 0001, "Error opening file", FvMapName);
2156 return EFI_ABORTED;
2157 }
2158
2159 //
2160 // record FV size information into FvMap file.
2161 //
2162 if (mFvTotalSize != 0) {
2163 fprintf (FvMapFile, EFI_FV_TOTAL_SIZE_STRING);
2164 fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTotalSize);
2165 }
2166 if (mFvTakenSize != 0) {
2167 fprintf (FvMapFile, EFI_FV_TAKEN_SIZE_STRING);
2168 fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTakenSize);
2169 }
2170 if (mFvTotalSize != 0 && mFvTakenSize != 0) {
2171 fprintf (FvMapFile, EFI_FV_SPACE_SIZE_STRING);
2172 fprintf (FvMapFile, " = 0x%x\n\n", (unsigned) (mFvTotalSize - mFvTakenSize));
2173 }
2174
2175 //
2176 // Set PI FV extension header
2177 //
2178 if (mFvDataInfo.FvNameGuidSet) {
2179 memcpy (&FvExtHeader.FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID));
2180 FvExtHeader.ExtHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);
2181 AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, &FvExtHeader);
2182 //
2183 // Fv Extension header change update Fv Header Check sum
2184 //
2185 FvHeader->Checksum = 0;
2186 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2187 }
2188
2189 //
2190 // Add files to FV
2191 //
2192 for (Index = 0; mFvDataInfo.FvFiles[Index][0] != 0; Index++) {
2193 //
2194 // Add the file
2195 //
2196 Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile);
2197
2198 //
2199 // Exit if error detected while adding the file
2200 //
2201 if (EFI_ERROR (Status)) {
2202 goto Finish;
2203 }
2204 }
2205
2206 //
2207 // If there is a VTF file, some special actions need to occur.
2208 //
2209 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
2210 //
2211 // Pad from the end of the last file to the beginning of the VTF file.
2212 // If the left space is less than sizeof (EFI_FFS_FILE_HEADER)?
2213 //
2214 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
2215 if (EFI_ERROR (Status)) {
2216 Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file.");
2217 goto Finish;
2218 }
2219 if (!mArm) {
2220 //
2221 // Update reset vector (SALE_ENTRY for IPF)
2222 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
2223 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
2224 // reset vector. If the PEI Core is found, the VTF file will probably get
2225 // corrupted by updating the entry point.
2226 //
2227 if ((mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
2228 Status = UpdateResetVector (&FvImageMemoryFile, &mFvDataInfo, VtfFileImage);
2229 if (EFI_ERROR(Status)) {
2230 Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
2231 goto Finish;
2232 }
2233 DebugMsg (NULL, 0, 9, "Update Reset vector in VTF file", NULL);
2234 }
2235 }
2236 }
2237
2238 if (mArm) {
2239 Status = UpdateArmResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);
2240 if (EFI_ERROR (Status)) {
2241 Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
2242 goto Finish;
2243 }
2244
2245 //
2246 // Update Checksum for FvHeader
2247 //
2248 FvHeader->Checksum = 0;
2249 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2250 }
2251
2252 //
2253 // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV
2254 //
2255 if ((((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {
2256 FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF));
2257 //
2258 // Update Checksum for FvHeader
2259 //
2260 FvHeader->Checksum = 0;
2261 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2262 }
2263
2264 WriteFile:
2265 //
2266 // Write fv file
2267 //
2268 FvFile = fopen (FvFileName, "wb");
2269 if (FvFile == NULL) {
2270 Error (NULL, 0, 0001, "Error opening file", FvFileName);
2271 Status = EFI_ABORTED;
2272 goto Finish;
2273 }
2274
2275 if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) {
2276 Error (NULL, 0, 0002, "Error writing file", FvFileName);
2277 Status = EFI_ABORTED;
2278 goto Finish;
2279 }
2280
2281 Finish:
2282 if (FvBufferHeader != NULL) {
2283 free (FvBufferHeader);
2284 }
2285
2286 if (FvFile != NULL) {
2287 fclose (FvFile);
2288 }
2289
2290 if (FvMapFile != NULL) {
2291 fclose (FvMapFile);
2292 }
2293
2294 return Status;
2295 }
2296
2297 EFI_STATUS
2298 UpdatePeiCoreEntryInFit (
2299 IN FIT_TABLE *FitTablePtr,
2300 IN UINT64 PeiCorePhysicalAddress
2301 )
2302 /*++
2303
2304 Routine Description:
2305
2306 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
2307 Sec to Pei Core
2308
2309 Arguments:
2310
2311 FitTablePtr - The pointer of FIT_TABLE.
2312 PeiCorePhysicalAddress - The address of Pei Core entry.
2313
2314 Returns:
2315
2316 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
2317 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
2318
2319 --*/
2320 {
2321 FIT_TABLE *TmpFitPtr;
2322 UINTN Index;
2323 UINTN NumFitComponents;
2324
2325 TmpFitPtr = FitTablePtr;
2326 NumFitComponents = TmpFitPtr->CompSize;
2327
2328 for (Index = 0; Index < NumFitComponents; Index++) {
2329 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
2330 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
2331 return EFI_SUCCESS;
2332 }
2333
2334 TmpFitPtr++;
2335 }
2336
2337 return EFI_NOT_FOUND;
2338 }
2339
2340 VOID
2341 UpdateFitCheckSum (
2342 IN FIT_TABLE *FitTablePtr
2343 )
2344 /*++
2345
2346 Routine Description:
2347
2348 This function is used to update the checksum for FIT.
2349
2350
2351 Arguments:
2352
2353 FitTablePtr - The pointer of FIT_TABLE.
2354
2355 Returns:
2356
2357 None.
2358
2359 --*/
2360 {
2361 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
2362 FitTablePtr->CheckSum = 0;
2363 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
2364 }
2365 }
2366
2367 EFI_STATUS
2368 CalculateFvSize (
2369 FV_INFO *FvInfoPtr
2370 )
2371 /*++
2372 Routine Description:
2373 Calculate the FV size and Update Fv Size based on the actual FFS files.
2374 And Update FvInfo data.
2375
2376 Arguments:
2377 FvInfoPtr - The pointer to FV_INFO structure.
2378
2379 Returns:
2380 EFI_ABORTED - Ffs Image Error
2381 EFI_SUCCESS - Successfully update FvSize
2382 --*/
2383 {
2384 UINTN CurrentOffset;
2385 UINTN Index;
2386 FILE *fpin;
2387 UINTN FfsFileSize;
2388 UINT32 FfsAlignment;
2389 EFI_FFS_FILE_HEADER FfsHeader;
2390 BOOLEAN VtfFileFlag;
2391 UINTN VtfFileSize;
2392
2393 VtfFileSize = 0;
2394 VtfFileFlag = FALSE;
2395 fpin = NULL;
2396 Index = 0;
2397
2398 //
2399 // Compute size for easy access later
2400 //
2401 FvInfoPtr->Size = 0;
2402 for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) {
2403 FvInfoPtr->Size += FvInfoPtr->FvBlocks[Index].NumBlocks * FvInfoPtr->FvBlocks[Index].Length;
2404 }
2405
2406 //
2407 // Caculate the required sizes for all FFS files.
2408 //
2409 CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
2410
2411 for (Index = 1;; Index ++) {
2412 CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
2413 if (FvInfoPtr->FvBlocks[Index].NumBlocks == 0 || FvInfoPtr->FvBlocks[Index].Length == 0) {
2414 break;
2415 }
2416 }
2417
2418 //
2419 // Calculate PI extension header
2420 //
2421 if (CompareGuid (&mFvDataInfo.FvNameGuid, &mZeroGuid) != 0) {
2422 CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);
2423 CurrentOffset = (CurrentOffset + 7) & (~7);
2424 }
2425
2426 //
2427 // Accumlate every FFS file size.
2428 //
2429 for (Index = 0; FvInfoPtr->FvFiles[Index][0] != 0; Index++) {
2430 //
2431 // Open FFS file
2432 //
2433 fpin = NULL;
2434 fpin = fopen (FvInfoPtr->FvFiles[Index], "rb");
2435 if (fpin == NULL) {
2436 Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]);
2437 return EFI_ABORTED;
2438 }
2439 //
2440 // Get the file size
2441 //
2442 FfsFileSize = _filelength (fileno (fpin));
2443 //
2444 // Read Ffs File header
2445 //
2446 fread (&FfsHeader, sizeof (UINT8), sizeof (EFI_FFS_FILE_HEADER), fpin);
2447 //
2448 // close file
2449 //
2450 fclose (fpin);
2451
2452 if (FvInfoPtr->IsPiFvImage) {
2453 //
2454 // Check whether this ffs file is vtf file
2455 //
2456 if (IsVtfFile (&FfsHeader)) {
2457 if (VtfFileFlag) {
2458 //
2459 // One Fv image can't have two vtf files.
2460 //
2461 return EFI_ABORTED;
2462 }
2463 VtfFileFlag = TRUE;
2464 VtfFileSize = FfsFileSize;
2465 continue;
2466 }
2467
2468 //
2469 // Get the alignment of FFS file
2470 //
2471 ReadFfsAlignment (&FfsHeader, &FfsAlignment);
2472 FfsAlignment = 1 << FfsAlignment;
2473 //
2474 // Add Pad file
2475 //
2476 if (((CurrentOffset + sizeof (EFI_FFS_FILE_HEADER)) % FfsAlignment) != 0) {
2477 CurrentOffset = (CurrentOffset + sizeof (EFI_FFS_FILE_HEADER) * 2 + FfsAlignment - 1) & ~(FfsAlignment - 1);
2478 CurrentOffset -= sizeof (EFI_FFS_FILE_HEADER);
2479 }
2480 }
2481
2482 //
2483 // Add ffs file size
2484 //
2485 if (FvInfoPtr->SizeofFvFiles[Index] > FfsFileSize) {
2486 CurrentOffset += FvInfoPtr->SizeofFvFiles[Index];
2487 } else {
2488 CurrentOffset += FfsFileSize;
2489 }
2490
2491 //
2492 // Make next ffs file start at QWord Boundry
2493 //
2494 if (FvInfoPtr->IsPiFvImage) {
2495 CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
2496 }
2497 }
2498 CurrentOffset += VtfFileSize;
2499 DebugMsg (NULL, 0, 9, "FvImage size", "The caculated fv image size is 0x%x and the current set fv image size is 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
2500
2501 if (FvInfoPtr->Size == 0) {
2502 //
2503 // Update FvInfo data
2504 //
2505 FvInfoPtr->FvBlocks[0].NumBlocks = CurrentOffset / FvInfoPtr->FvBlocks[0].Length + ((CurrentOffset % FvInfoPtr->FvBlocks[0].Length)?1:0);
2506 FvInfoPtr->Size = FvInfoPtr->FvBlocks[0].NumBlocks * FvInfoPtr->FvBlocks[0].Length;
2507 FvInfoPtr->FvBlocks[1].NumBlocks = 0;
2508 FvInfoPtr->FvBlocks[1].Length = 0;
2509 } else if (FvInfoPtr->Size < CurrentOffset) {
2510 //
2511 // Not invalid
2512 //
2513 Error (NULL, 0, 3000, "Invalid", "the required fv image size 0x%x exceeds the set fv image size 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
2514 return EFI_INVALID_PARAMETER;
2515 }
2516
2517 //
2518 // Set Fv Size Information
2519 //
2520 mFvTotalSize = FvInfoPtr->Size;
2521 mFvTakenSize = CurrentOffset;
2522
2523 return EFI_SUCCESS;
2524 }
2525
2526 EFI_STATUS
2527 FfsRebaseImageRead (
2528 IN VOID *FileHandle,
2529 IN UINTN FileOffset,
2530 IN OUT UINT32 *ReadSize,
2531 OUT VOID *Buffer
2532 )
2533 /*++
2534
2535 Routine Description:
2536
2537 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
2538
2539 Arguments:
2540
2541 FileHandle - The handle to the PE/COFF file
2542
2543 FileOffset - The offset, in bytes, into the file to read
2544
2545 ReadSize - The number of bytes to read from the file starting at FileOffset
2546
2547 Buffer - A pointer to the buffer to read the data into.
2548
2549 Returns:
2550
2551 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
2552
2553 --*/
2554 {
2555 CHAR8 *Destination8;
2556 CHAR8 *Source8;
2557 UINT32 Length;
2558
2559 Destination8 = Buffer;
2560 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
2561 Length = *ReadSize;
2562 while (Length--) {
2563 *(Destination8++) = *(Source8++);
2564 }
2565
2566 return EFI_SUCCESS;
2567 }
2568
2569 EFI_STATUS
2570 FfsRebase (
2571 IN OUT FV_INFO *FvInfo,
2572 IN CHAR8 *FileName,
2573 IN OUT EFI_FFS_FILE_HEADER *FfsFile,
2574 IN UINTN XipOffset,
2575 IN FILE *FvMapFile
2576 )
2577 /*++
2578
2579 Routine Description:
2580
2581 This function determines if a file is XIP and should be rebased. It will
2582 rebase any PE32 sections found in the file using the base address.
2583
2584 Arguments:
2585
2586 FvInfo A pointer to FV_INFO struture.
2587 FileName Ffs File PathName
2588 FfsFile A pointer to Ffs file image.
2589 XipOffset The offset address to use for rebasing the XIP file image.
2590 FvMapFile FvMapFile to record the function address in one Fvimage
2591
2592 Returns:
2593
2594 EFI_SUCCESS The image was properly rebased.
2595 EFI_INVALID_PARAMETER An input parameter is invalid.
2596 EFI_ABORTED An error occurred while rebasing the input file image.
2597 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
2598 EFI_NOT_FOUND No compressed sections could be found.
2599
2600 --*/
2601 {
2602 EFI_STATUS Status;
2603 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
2604 PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext;
2605 EFI_PHYSICAL_ADDRESS XipBase;
2606 EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
2607 EFI_PHYSICAL_ADDRESS *BaseToUpdate;
2608 UINTN Index;
2609 EFI_FILE_SECTION_POINTER CurrentPe32Section;
2610 EFI_FFS_FILE_STATE SavedState;
2611 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
2612 EFI_TE_IMAGE_HEADER *TEImageHeader;
2613 UINT8 Flags;
2614 UINT8 *MemoryImagePointer;
2615 EFI_IMAGE_SECTION_HEADER *SectionHeader;
2616 CHAR8 PeFileName [_MAX_PATH];
2617 CHAR8 *Cptr;
2618 FILE *PeFile;
2619 UINT8 *PeFileBuffer;
2620 UINT32 PeFileSize;
2621 CHAR8 *PdbPointer;
2622
2623 Index = 0;
2624 MemoryImagePointer = NULL;
2625 BaseToUpdate = NULL;
2626 TEImageHeader = NULL;
2627 ImgHdr = NULL;
2628 SectionHeader = NULL;
2629 Cptr = NULL;
2630 PeFile = NULL;
2631 PeFileBuffer = NULL;
2632
2633 //
2634 // Check XipAddress, BootAddress and RuntimeAddress
2635 //
2636 Flags = 0;
2637 XipBase = 0;
2638 if (FvInfo->BaseAddress != 0) {
2639 Flags |= REBASE_XIP_FILE;
2640 XipBase = FvInfo->BaseAddress + XipOffset;
2641 }
2642 if (FvInfo->BootBaseAddress != 0) {
2643 Flags |= REBASE_BOOTTIME_FILE;
2644 }
2645 if (FvInfo->RuntimeBaseAddress != 0) {
2646 Flags |= REBASE_RUNTIME_FILE;
2647 }
2648
2649 //
2650 // Don't Rebase this FFS.
2651 // Only copy the original map file into the FvMap file
2652 // for the image that is not required to be relocated.
2653 //
2654
2655 //
2656 // We only process files potentially containing PE32 sections.
2657 //
2658 switch (FfsFile->Type) {
2659 case EFI_FV_FILETYPE_SECURITY_CORE:
2660 case EFI_FV_FILETYPE_PEI_CORE:
2661 case EFI_FV_FILETYPE_PEIM:
2662 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
2663 case EFI_FV_FILETYPE_DRIVER:
2664 case EFI_FV_FILETYPE_DXE_CORE:
2665 break;
2666 default:
2667 return EFI_SUCCESS;
2668 }
2669 //
2670 // Rebase each PE32 section
2671 //
2672 Status = EFI_SUCCESS;
2673 for (Index = 1;; Index++) {
2674 //
2675 // Init Value
2676 //
2677 NewPe32BaseAddress = 0;
2678
2679 //
2680 // Find Pe Image
2681 //
2682 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
2683 if (EFI_ERROR (Status)) {
2684 break;
2685 }
2686
2687 //
2688 // Initialize context
2689 //
2690 memset (&ImageContext, 0, sizeof (ImageContext));
2691 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
2692 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
2693 Status = PeCoffLoaderGetImageInfo (&ImageContext);
2694 if (EFI_ERROR (Status)) {
2695 Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
2696 return Status;
2697 }
2698
2699 if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {
2700 mArm = TRUE;
2701 }
2702
2703 //
2704 // Keep Image Context for PE image in FV
2705 //
2706 memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext));
2707
2708 //
2709 // Get File PdbPointer
2710 //
2711 PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);
2712
2713 //
2714 // Get PeHeader pointer
2715 //
2716 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + ImageContext.PeCoffHeaderOffset);
2717
2718 //
2719 // Calculate the PE32 base address, based on file type
2720 //
2721 switch (FfsFile->Type) {
2722 case EFI_FV_FILETYPE_SECURITY_CORE:
2723 case EFI_FV_FILETYPE_PEI_CORE:
2724 case EFI_FV_FILETYPE_PEIM:
2725 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
2726 if ((Flags & REBASE_XIP_FILE) == 0) {
2727 //
2728 // We aren't relocating XIP code, so skip it.
2729 //
2730 goto WritePeMap;
2731 }
2732
2733 //
2734 // Check if section-alignment and file-alignment match or not
2735 //
2736 if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
2737 //
2738 // Xip module has the same section alignment and file alignment.
2739 //
2740 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);
2741 return EFI_ABORTED;
2742 }
2743 //
2744 // PeImage has no reloc section. It will try to get reloc data from the original EFI image.
2745 //
2746 if (ImageContext.RelocationsStripped) {
2747 //
2748 // Construct the original efi file Name
2749 //
2750 strcpy (PeFileName, FileName);
2751 Cptr = PeFileName + strlen (PeFileName);
2752 while (*Cptr != '.') {
2753 Cptr --;
2754 }
2755 if (*Cptr != '.') {
2756 Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
2757 return EFI_ABORTED;
2758 } else {
2759 *(Cptr + 1) = 'e';
2760 *(Cptr + 2) = 'f';
2761 *(Cptr + 3) = 'i';
2762 *(Cptr + 4) = '\0';
2763 }
2764 PeFile = fopen (PeFileName, "rb");
2765 if (PeFile == NULL) {
2766 Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
2767 //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
2768 //return EFI_ABORTED;
2769 break;
2770 }
2771 //
2772 // Get the file size
2773 //
2774 PeFileSize = _filelength (fileno (PeFile));
2775 PeFileBuffer = (UINT8 *) malloc (PeFileSize);
2776 if (PeFileBuffer == NULL) {
2777 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
2778 return EFI_OUT_OF_RESOURCES;
2779 }
2780 //
2781 // Read Pe File
2782 //
2783 fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile);
2784 //
2785 // close file
2786 //
2787 fclose (PeFile);
2788 //
2789 // Handle pointer to the original efi image.
2790 //
2791 ImageContext.Handle = PeFileBuffer;
2792 Status = PeCoffLoaderGetImageInfo (&ImageContext);
2793 if (EFI_ERROR (Status)) {
2794 Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
2795 return Status;
2796 }
2797 ImageContext.RelocationsStripped = FALSE;
2798 }
2799
2800 NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;
2801 BaseToUpdate = &XipBase;
2802 break;
2803
2804 case EFI_FV_FILETYPE_DRIVER:
2805 case EFI_FV_FILETYPE_DXE_CORE:
2806 switch (ImgHdr->Pe32.OptionalHeader.Subsystem) {
2807 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
2808 if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {
2809 //
2810 // Check if section-alignment and file-alignment match or not
2811 //
2812 if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
2813 //
2814 // Xip module has the same section alignment and file alignment.
2815 //
2816 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);
2817 return EFI_ABORTED;
2818 }
2819 NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;
2820 BaseToUpdate = &XipBase;
2821 } else if ((Flags & REBASE_RUNTIME_FILE) == REBASE_RUNTIME_FILE) {
2822 //
2823 // make sure image base address at the section alignment
2824 //
2825 FvInfo->RuntimeBaseAddress = (FvInfo->RuntimeBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));
2826 FvInfo->RuntimeBaseAddress = FvInfo->RuntimeBaseAddress & (~(EFI_PAGE_SIZE - 1));
2827 NewPe32BaseAddress = FvInfo->RuntimeBaseAddress;
2828 BaseToUpdate = &(FvInfo->RuntimeBaseAddress);
2829 } else {
2830 //
2831 // RT drivers aren't supposed to be relocated
2832 //
2833 goto WritePeMap;
2834 }
2835 break;
2836
2837 default:
2838 //
2839 // We treat all other subsystems the same as BS_DRIVER
2840 //
2841 if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {
2842 //
2843 // Check if section-alignment and file-alignment match or not
2844 //
2845 if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
2846 //
2847 // Xip module has the same section alignment and file alignment.
2848 //
2849 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);
2850 return EFI_ABORTED;
2851 }
2852 NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;
2853 BaseToUpdate = &XipBase;
2854 } else if ((Flags & REBASE_BOOTTIME_FILE) == REBASE_BOOTTIME_FILE) {
2855 //
2856 // make sure image base address at the Section and Page alignment
2857 //
2858 FvInfo->BootBaseAddress = (FvInfo->BootBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));
2859 FvInfo->BootBaseAddress = FvInfo->BootBaseAddress & (~(EFI_PAGE_SIZE - 1));
2860 NewPe32BaseAddress = FvInfo->BootBaseAddress;
2861 BaseToUpdate = &(FvInfo->BootBaseAddress);
2862 } else {
2863 //
2864 // Skip all BS_DRIVER's
2865 //
2866 goto WritePeMap;
2867 }
2868 break;
2869 }
2870 break;
2871
2872 default:
2873 //
2874 // Not supported file type
2875 //
2876 return EFI_SUCCESS;
2877 }
2878
2879 //
2880 // Relocation exist and rebase
2881 //
2882 if (!ImageContext.RelocationsStripped) {
2883 //
2884 // Load and Relocate Image Data
2885 //
2886 MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
2887 if (MemoryImagePointer == NULL) {
2888 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
2889 return EFI_OUT_OF_RESOURCES;
2890 }
2891 memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
2892 ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));
2893
2894 Status = PeCoffLoaderLoadImage (&ImageContext);
2895 if (EFI_ERROR (Status)) {
2896 Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
2897 free ((VOID *) MemoryImagePointer);
2898 return Status;
2899 }
2900
2901 ImageContext.DestinationAddress = NewPe32BaseAddress;
2902 Status = PeCoffLoaderRelocateImage (&ImageContext);
2903 if (EFI_ERROR (Status)) {
2904 Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
2905 free ((VOID *) MemoryImagePointer);
2906 return Status;
2907 }
2908
2909 //
2910 // Copy Relocated data to raw image file.
2911 //
2912 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
2913 (UINTN) ImgHdr +
2914 sizeof (UINT32) +
2915 sizeof (EFI_IMAGE_FILE_HEADER) +
2916 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
2917 );
2918
2919 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
2920 CopyMem (
2921 (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + SectionHeader->PointerToRawData,
2922 (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
2923 SectionHeader->SizeOfRawData
2924 );
2925 }
2926
2927 free ((VOID *) MemoryImagePointer);
2928 MemoryImagePointer = NULL;
2929 if (PeFileBuffer != NULL) {
2930 free (PeFileBuffer);
2931 PeFileBuffer = NULL;
2932 }
2933 }
2934
2935 //
2936 // Update Image Base Address
2937 //
2938 if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2939 ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
2940 } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2941 ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
2942 } else {
2943 Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
2944 ImgHdr->Pe32.OptionalHeader.Magic,
2945 FileName
2946 );
2947 return EFI_ABORTED;
2948 }
2949
2950 //
2951 // Update BASE address by add one page size.
2952 //
2953 *BaseToUpdate -= EFI_PAGE_SIZE;
2954
2955 //
2956 // Now update file checksum
2957 //
2958 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2959 SavedState = FfsFile->State;
2960 FfsFile->IntegrityCheck.Checksum.File = 0;
2961 FfsFile->State = 0;
2962 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2963 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
2964 (UINT8 *) FfsFile,
2965 GetLength (FfsFile->Size)
2966 );
2967 } else {
2968 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2969 }
2970
2971 FfsFile->State = SavedState;
2972 }
2973
2974 //
2975 // Get this module function address from ModulePeMapFile and add them into FvMap file
2976 //
2977 WritePeMap:
2978 //
2979 // Default use FileName as map file path
2980 //
2981 if (PdbPointer == NULL) {
2982 PdbPointer = FileName;
2983 }
2984
2985 WriteMapFile (FvMapFile, PdbPointer, (EFI_GUID *) FfsFile, NewPe32BaseAddress, &OrigImageContext);
2986 }
2987
2988 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
2989 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
2990 FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
2991 FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
2992 ) {
2993 //
2994 // Only Peim code may have a TE section
2995 //
2996 return EFI_SUCCESS;
2997 }
2998
2999 //
3000 // Now process TE sections
3001 //
3002 for (Index = 1;; Index++) {
3003 NewPe32BaseAddress = 0;
3004
3005 //
3006 // Find Te Image
3007 //
3008 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
3009 if (EFI_ERROR (Status)) {
3010 break;
3011 }
3012
3013 //
3014 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
3015 // by GenTEImage
3016 //
3017 TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
3018
3019 //
3020 // Initialize context, load image info.
3021 //
3022 memset (&ImageContext, 0, sizeof (ImageContext));
3023 ImageContext.Handle = (VOID *) TEImageHeader;
3024 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
3025 Status = PeCoffLoaderGetImageInfo (&ImageContext);
3026 if (EFI_ERROR (Status)) {
3027 Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
3028 return Status;
3029 }
3030
3031 if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {
3032 mArm = TRUE;
3033 }
3034
3035 //
3036 // Keep Image Context for TE image in FV
3037 //
3038 memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext));
3039
3040 //
3041 // Get File PdbPointer
3042 //
3043 PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);
3044
3045 if ((Flags & REBASE_XIP_FILE) == 0) {
3046 //
3047 // For none XIP PEIM module, their map info also are collected.
3048 //
3049 goto WriteTeMap;
3050 }
3051
3052 //
3053 // Set new rebased address.
3054 //
3055 NewPe32BaseAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \
3056 - TEImageHeader->StrippedSize - (UINTN) FfsFile;
3057
3058 //
3059 // if reloc is stripped, try to get the original efi image to get reloc info.
3060 //
3061 if (ImageContext.RelocationsStripped == TRUE) {
3062 //
3063 // Construct the original efi file name
3064 //
3065 strcpy (PeFileName, FileName);
3066 Cptr = PeFileName + strlen (PeFileName);
3067 while (*Cptr != '.') {
3068 Cptr --;
3069 }
3070
3071 if (*Cptr != '.') {
3072 Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
3073 return EFI_ABORTED;
3074 } else {
3075 *(Cptr + 1) = 'e';
3076 *(Cptr + 2) = 'f';
3077 *(Cptr + 3) = 'i';
3078 *(Cptr + 4) = '\0';
3079 }
3080
3081 PeFile = fopen (PeFileName, "rb");
3082 if (PeFile == NULL) {
3083 Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
3084 //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
3085 //return EFI_ABORTED;
3086 } else {
3087 //
3088 // Get the file size
3089 //
3090 PeFileSize = _filelength (fileno (PeFile));
3091 PeFileBuffer = (UINT8 *) malloc (PeFileSize);
3092 if (PeFileBuffer == NULL) {
3093 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
3094 return EFI_OUT_OF_RESOURCES;
3095 }
3096 //
3097 // Read Pe File
3098 //
3099 fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile);
3100 //
3101 // close file
3102 //
3103 fclose (PeFile);
3104 //
3105 // Append reloc section into TeImage
3106 //
3107 ImageContext.Handle = PeFileBuffer;
3108 Status = PeCoffLoaderGetImageInfo (&ImageContext);
3109 if (EFI_ERROR (Status)) {
3110 Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
3111 return Status;
3112 }
3113 ImageContext.RelocationsStripped = FALSE;
3114 }
3115 }
3116
3117 //
3118 // Relocation exist and rebase
3119 //
3120 if (!ImageContext.RelocationsStripped) {
3121 //
3122 // Load and Relocate Image Data
3123 //
3124 MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
3125 if (MemoryImagePointer == NULL) {
3126 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
3127 return EFI_OUT_OF_RESOURCES;
3128 }
3129 memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
3130 ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));
3131
3132 Status = PeCoffLoaderLoadImage (&ImageContext);
3133 if (EFI_ERROR (Status)) {
3134 Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
3135 free ((VOID *) MemoryImagePointer);
3136 return Status;
3137 }
3138 //
3139 // Reloacate TeImage
3140 //
3141 ImageContext.DestinationAddress = NewPe32BaseAddress;
3142 Status = PeCoffLoaderRelocateImage (&ImageContext);
3143 if (EFI_ERROR (Status)) {
3144 Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);
3145 free ((VOID *) MemoryImagePointer);
3146 return Status;
3147 }
3148
3149 //
3150 // Copy the relocated image into raw image file.
3151 //
3152 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
3153 for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {
3154 if (!ImageContext.IsTeImage) {
3155 CopyMem (
3156 (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
3157 (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
3158 SectionHeader->SizeOfRawData
3159 );
3160 } else {
3161 CopyMem (
3162 (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
3163 (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress),
3164 SectionHeader->SizeOfRawData
3165 );
3166 }
3167 }
3168
3169 //
3170 // Free the allocated memory resource
3171 //
3172 free ((VOID *) MemoryImagePointer);
3173 MemoryImagePointer = NULL;
3174 if (PeFileBuffer != NULL) {
3175 free (PeFileBuffer);
3176 PeFileBuffer = NULL;
3177 }
3178 }
3179
3180 //
3181 // Update Image Base Address
3182 //
3183 TEImageHeader->ImageBase = NewPe32BaseAddress;
3184
3185 //
3186 // Now update file checksum
3187 //
3188 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
3189 SavedState = FfsFile->State;
3190 FfsFile->IntegrityCheck.Checksum.File = 0;
3191 FfsFile->State = 0;
3192 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
3193 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
3194 (UINT8 *) FfsFile,
3195 GetLength (FfsFile->Size)
3196 );
3197 } else {
3198 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
3199 }
3200
3201 FfsFile->State = SavedState;
3202 }
3203 //
3204 // Get this module function address from ModulePeMapFile and add them into FvMap file
3205 //
3206 WriteTeMap:
3207 //
3208 // Default use FileName as map file path
3209 //
3210 if (PdbPointer == NULL) {
3211 PdbPointer = FileName;
3212 }
3213
3214 WriteMapFile (
3215 FvMapFile,
3216 PdbPointer,
3217 (EFI_GUID *) FfsFile,
3218 NewPe32BaseAddress,
3219 &OrigImageContext
3220 );
3221 }
3222
3223 return EFI_SUCCESS;
3224 }
3225
3226 EFI_STATUS
3227 FindApResetVectorPosition (
3228 IN MEMORY_FILE *FvImage,
3229 OUT UINT8 **Pointer
3230 )
3231 /*++
3232
3233 Routine Description:
3234
3235 Find the position in this FvImage to place Ap reset vector.
3236
3237 Arguments:
3238
3239 FvImage Memory file for the FV memory image.
3240 Pointer Pointer to pointer to position.
3241
3242 Returns:
3243
3244 EFI_NOT_FOUND - No satisfied position is found.
3245 EFI_SUCCESS - The suitable position is return.
3246
3247 --*/
3248 {
3249 EFI_FFS_FILE_HEADER *PadFile;
3250 UINT32 Index;
3251 EFI_STATUS Status;
3252 UINT8 *FixPoint;
3253 UINT32 FileLength;
3254
3255 for (Index = 1; ;Index ++) {
3256 //
3257 // Find Pad File to add ApResetVector info
3258 //
3259 Status = GetFileByType (EFI_FV_FILETYPE_FFS_PAD, Index, &PadFile);
3260 if (EFI_ERROR (Status) || (PadFile == NULL)) {
3261 //
3262 // No Pad file to be found.
3263 //
3264 break;
3265 }
3266 //
3267 // Get Pad file size.
3268 //
3269 FileLength = (*(UINT32 *)(PadFile->Size)) & 0x00FFFFFF;
3270 FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
3271 //
3272 // FixPoint must be align on 0x1000 relative to FvImage Header
3273 //
3274 FixPoint = (UINT8*) PadFile + sizeof (EFI_FFS_FILE_HEADER);
3275 FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);
3276 //
3277 // FixPoint be larger at the last place of one fv image.
3278 //
3279 while (((UINTN) FixPoint + SIZEOF_STARTUP_DATA_ARRAY - (UINTN) PadFile) <= FileLength) {
3280 FixPoint += 0x1000;
3281 }
3282 FixPoint -= 0x1000;
3283
3284 if ((UINTN) FixPoint < ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER))) {
3285 //
3286 // No alignment FixPoint in this Pad File.
3287 //
3288 continue;
3289 }
3290
3291 if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {
3292 //
3293 // Find the position to place ApResetVector
3294 //
3295 *Pointer = FixPoint;
3296 return EFI_SUCCESS;
3297 }
3298 }
3299
3300 return EFI_NOT_FOUND;
3301 }
3302
3303 EFI_STATUS
3304 ParseCapInf (
3305 IN MEMORY_FILE *InfFile,
3306 OUT CAP_INFO *CapInfo
3307 )
3308 /*++
3309
3310 Routine Description:
3311
3312 This function parses a Cap.INF file and copies info into a CAP_INFO structure.
3313
3314 Arguments:
3315
3316 InfFile Memory file image.
3317 CapInfo Information read from INF file.
3318
3319 Returns:
3320
3321 EFI_SUCCESS INF file information successfully retrieved.
3322 EFI_ABORTED INF file has an invalid format.
3323 EFI_NOT_FOUND A required string was not found in the INF file.
3324 --*/
3325 {
3326 CHAR8 Value[_MAX_PATH];
3327 UINT64 Value64;
3328 UINTN Index, Number;
3329 EFI_STATUS Status;
3330
3331 //
3332 // Initialize Cap info
3333 //
3334 // memset (CapInfo, 0, sizeof (CAP_INFO));
3335 //
3336
3337 //
3338 // Read the Capsule Guid
3339 //
3340 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_GUID_STRING, 0, Value);
3341 if (Status == EFI_SUCCESS) {
3342 //
3343 // Get the Capsule Guid
3344 //
3345 Status = StringToGuid (Value, &CapInfo->CapGuid);
3346 if (EFI_ERROR (Status)) {
3347 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_GUID_STRING, Value);
3348 return EFI_ABORTED;
3349 }
3350 DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, Value);
3351 }
3352
3353 //
3354 // Read the Capsule Header Size
3355 //
3356 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_HEADER_SIZE_STRING, 0, Value);
3357 if (Status == EFI_SUCCESS) {
3358 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
3359 if (EFI_ERROR (Status)) {
3360 Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value);
3361 return EFI_ABORTED;
3362 }
3363 CapInfo->HeaderSize = (UINT32) Value64;
3364 DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value);
3365 }
3366
3367 //
3368 // Read the Capsule Flag
3369 //
3370 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_FLAGS_STRING, 0, Value);
3371 if (Status == EFI_SUCCESS) {
3372 if (strstr (Value, "PopulateSystemTable") != NULL) {
3373 CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;
3374 if (strstr (Value, "InitiateReset") != NULL) {
3375 CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;
3376 }
3377 } else if (strstr (Value, "PersistAcrossReset") != NULL) {
3378 CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
3379 if (strstr (Value, "InitiateReset") != NULL) {
3380 CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;
3381 }
3382 } else {
3383 Error (NULL, 0, 2000, "Invalid parameter", "invalid Flag setting for %s.", EFI_CAPSULE_FLAGS_STRING);
3384 return EFI_ABORTED;
3385 }
3386 DebugMsg (NULL, 0, 9, "Capsule Flag", Value);
3387 }
3388
3389 //
3390 // Read Capsule File name
3391 //
3392 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FILE_NAME_STRING, 0, Value);
3393 if (Status == EFI_SUCCESS) {
3394 //
3395 // Get output file name
3396 //
3397 strcpy (CapInfo->CapName, Value);
3398 }
3399
3400 //
3401 // Read the Capsule FileImage
3402 //
3403 Number = 0;
3404 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_CAP; Index++) {
3405 if (CapInfo->CapFiles[Index][0] != '\0') {
3406 continue;
3407 }
3408 //
3409 // Read the capsule file name
3410 //
3411 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Number++, Value);
3412
3413 if (Status == EFI_SUCCESS) {
3414 //
3415 // Add the file
3416 //
3417 strcpy (CapInfo->CapFiles[Index], Value);
3418 DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]);
3419 } else {
3420 break;
3421 }
3422 }
3423
3424 if (Index == 0) {
3425 Warning (NULL, 0, 0, "Capsule components are not specified.", NULL);
3426 }
3427
3428 return EFI_SUCCESS;
3429 }
3430
3431 EFI_STATUS
3432 GenerateCapImage (
3433 IN CHAR8 *InfFileImage,
3434 IN UINTN InfFileSize,
3435 IN CHAR8 *CapFileName
3436 )
3437 /*++
3438
3439 Routine Description:
3440
3441 This is the main function which will be called from application to create UEFI Capsule image.
3442
3443 Arguments:
3444
3445 InfFileImage Buffer containing the INF file contents.
3446 InfFileSize Size of the contents of the InfFileImage buffer.
3447 CapFileName Requested name for the Cap file.
3448
3449 Returns:
3450
3451 EFI_SUCCESS Function completed successfully.
3452 EFI_OUT_OF_RESOURCES Could not allocate required resources.
3453 EFI_ABORTED Error encountered.
3454 EFI_INVALID_PARAMETER A required parameter was NULL.
3455
3456 --*/
3457 {
3458 UINT32 CapSize;
3459 UINT8 *CapBuffer;
3460 EFI_CAPSULE_HEADER *CapsuleHeader;
3461 MEMORY_FILE InfMemoryFile;
3462 UINT32 FileSize;
3463 UINT32 Index;
3464 FILE *fpin, *fpout;
3465 EFI_STATUS Status;
3466
3467 if (InfFileImage != NULL) {
3468 //
3469 // Initialize file structures
3470 //
3471 InfMemoryFile.FileImage = InfFileImage;
3472 InfMemoryFile.CurrentFilePointer = InfFileImage;
3473 InfMemoryFile.Eof = InfFileImage + InfFileSize;
3474
3475 //
3476 // Parse the Cap inf file for header information
3477 //
3478 Status = ParseCapInf (&InfMemoryFile, &mCapDataInfo);
3479 if (Status != EFI_SUCCESS) {
3480 return Status;
3481 }
3482 }
3483
3484 if (mCapDataInfo.HeaderSize == 0) {
3485 //
3486 // make header size align 16 bytes.
3487 //
3488 mCapDataInfo.HeaderSize = sizeof (EFI_CAPSULE_HEADER);
3489 mCapDataInfo.HeaderSize = (mCapDataInfo.HeaderSize + 0xF) & ~0xF;
3490 }
3491
3492 if (mCapDataInfo.HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {
3493 Error (NULL, 0, 2000, "Invalid parameter", "The specified HeaderSize cannot be less than the size of EFI_CAPSULE_HEADER.");
3494 return EFI_INVALID_PARAMETER;
3495 }
3496
3497 if (CapFileName == NULL && mCapDataInfo.CapName[0] != '\0') {
3498 CapFileName = mCapDataInfo.CapName;
3499 }
3500
3501 if (CapFileName == NULL) {
3502 Error (NULL, 0, 2001, "Missing required argument", "Output Capsule file name");
3503 return EFI_INVALID_PARAMETER;
3504 }
3505
3506 //
3507 // Set Default Capsule Guid value
3508 //
3509 if (CompareGuid (&mCapDataInfo.CapGuid, &mZeroGuid) == 0) {
3510 memcpy (&mCapDataInfo.CapGuid, &mDefaultCapsuleGuid, sizeof (EFI_GUID));
3511 }
3512 //
3513 // Calculate the size of capsule image.
3514 //
3515 Index = 0;
3516 FileSize = 0;
3517 CapSize = mCapDataInfo.HeaderSize;
3518 while (mCapDataInfo.CapFiles [Index][0] != '\0') {
3519 fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");
3520 if (fpin == NULL) {
3521 Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);
3522 return EFI_ABORTED;
3523 }
3524 FileSize = _filelength (fileno (fpin));
3525 CapSize += FileSize;
3526 fclose (fpin);
3527 Index ++;
3528 }
3529
3530 //
3531 // Allocate buffer for capsule image.
3532 //
3533 CapBuffer = (UINT8 *) malloc (CapSize);
3534 if (CapBuffer == NULL) {
3535 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated for creating the capsule.");
3536 return EFI_OUT_OF_RESOURCES;
3537 }
3538
3539 //
3540 // Initialize the capsule header to zero
3541 //
3542 memset (CapBuffer, 0, mCapDataInfo.HeaderSize);
3543
3544 //
3545 // create capsule header and get capsule body
3546 //
3547 CapsuleHeader = (EFI_CAPSULE_HEADER *) CapBuffer;
3548 memcpy (&CapsuleHeader->CapsuleGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID));
3549 CapsuleHeader->HeaderSize = mCapDataInfo.HeaderSize;
3550 CapsuleHeader->Flags = mCapDataInfo.Flags;
3551 CapsuleHeader->CapsuleImageSize = CapSize;
3552
3553 Index = 0;
3554 FileSize = 0;
3555 CapSize = CapsuleHeader->HeaderSize;
3556 while (mCapDataInfo.CapFiles [Index][0] != '\0') {
3557 fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");
3558 if (fpin == NULL) {
3559 Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);
3560 free (CapBuffer);
3561 return EFI_ABORTED;
3562 }
3563 FileSize = _filelength (fileno (fpin));
3564 fread (CapBuffer + CapSize, 1, FileSize, fpin);
3565 fclose (fpin);
3566 Index ++;
3567 CapSize += FileSize;
3568 }
3569
3570 //
3571 // write capsule data into the output file
3572 //
3573 fpout = fopen (CapFileName, "wb");
3574 if (fpout == NULL) {
3575 Error (NULL, 0, 0001, "Error opening file", CapFileName);
3576 free (CapBuffer);
3577 return EFI_ABORTED;
3578 }
3579
3580 fwrite (CapBuffer, 1, CapSize, fpout);
3581 fclose (fpout);
3582
3583 VerboseMsg ("The size of the generated capsule image is %u bytes", (unsigned) CapSize);
3584
3585 return EFI_SUCCESS;
3586 }