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