]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenVtf/GenVtf.c
BaseTools/GenVtf: silence false "stringop-overflow" warning with memcpy()
[mirror_edk2.git] / BaseTools / Source / C / GenVtf / GenVtf.c
CommitLineData
97fa0ee9
YL
1/** @file\r
2This file contains functions required to generate a boot strap file (BSF) also \r
3known as the Volume Top File (VTF)\r
30fdf114 4\r
a9b4ee43 5Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>\r
a709adfa
LG
6This program and the accompanying materials are licensed and made available \r
7under the terms and conditions of the BSD License which accompanies this \r
8distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
30fdf114 13\r
30fdf114
LG
14**/\r
15\r
16//\r
17//\r
18//\r
19#include <FvLib.h>\r
20#include <Common/UefiBaseTypes.h>\r
21#include "GenVtf.h"\r
22#include <Guid/PiFirmwareFileSystem.h>\r
23#include "CommonLib.h"\r
24#include "EfiUtilityMsgs.h"\r
25\r
26//\r
27// Global variables\r
28//\r
29UINTN SectionOptionFlag = 0;\r
30UINTN SectionCompFlag = 0;\r
31\r
32UINT64 DebugLevel;\r
33BOOLEAN DebugMode;\r
34\r
35BOOLEAN QuietMode = FALSE;\r
36\r
37BOOLEAN VTF_OUTPUT = FALSE;\r
38CHAR8 *OutFileName1;\r
39CHAR8 *OutFileName2;\r
40CHAR8 *SymFileName;\r
41\r
42CHAR8 **TokenStr;\r
43CHAR8 **OrgStrTokPtr;\r
44\r
45PARSED_VTF_INFO *FileListPtr;\r
46PARSED_VTF_INFO *FileListHeadPtr;\r
47\r
48VOID *Vtf1Buffer;\r
49VOID *Vtf1EndBuffer;\r
50VOID *Vtf2Buffer;\r
51VOID *Vtf2EndBuffer;\r
52\r
53UINTN ValidLineNum = 0;\r
54UINTN ValidFFDFileListNum = 0;\r
55\r
56//\r
57// Section Description and their number of occurences in *.INF file\r
58//\r
59UINTN NumFvFiles = 0;\r
60UINTN SectionOptionNum = 0;\r
61\r
62//\r
63// Global flag which will check for VTF Present, if yes then will be used\r
64// to decide about adding FFS header to pad data\r
65//\r
66BOOLEAN VTFPresent = FALSE;\r
67BOOLEAN SecondVTF = FALSE;\r
68\r
69//\r
70// Address related information\r
71//\r
72UINT64 Fv1BaseAddress = 0;\r
73UINT64 Fv2BaseAddress = 0;\r
74UINT64 Fv1EndAddress = 0;\r
75UINT64 Fv2EndAddress = 0;\r
76UINT32 Vtf1TotalSize = SIZE_TO_OFFSET_PAL_A_END;\r
77UINT64 Vtf1LastStartAddress = 0;\r
78UINT32 Vtf2TotalSize = 0;\r
79UINT64 Vtf2LastStartAddress = 0;\r
80\r
81UINT32 BufferToTop = 0;\r
82\r
83//\r
84// IA32 Reset Vector Bin name\r
85//\r
86CHAR8 IA32BinFile[FILE_NAME_SIZE];\r
87\r
88//\r
89// Function Implementations\r
90//\r
91EFI_STATUS\r
92ConvertVersionInfo (\r
93 IN CHAR8 *Str,\r
94 IN OUT UINT8 *MajorVer,\r
95 IN OUT UINT8 *MinorVer\r
96 )\r
97/*++\r
98Routine Description:\r
99\r
6780eef1 100 This function split version to major version and minor version\r
30fdf114
LG
101\r
102Arguments:\r
103\r
104 Str - String representing in form XX.XX\r
6780eef1
LG
105 MajorVer - The major version\r
106 MinorVer - The minor version\r
30fdf114
LG
107\r
108Returns:\r
109\r
6780eef1 110 EFI_SUCCESS - The function completed successfully.\r
30fdf114
LG
111\r
112--*/\r
113{\r
9fd2164e 114 CHAR8 TemStr[5] = "0000";\r
f45b5a76
HW
115 int Major;\r
116 int Minor;\r
9fd2164e 117 UINTN Length;\r
30fdf114
LG
118\r
119 Major = 0;\r
120 Minor = 0;\r
30fdf114 121\r
9fd2164e
LG
122 if (strstr (Str, ".") != NULL) {\r
123 sscanf (\r
124 Str,\r
125 "%02x.%02x",\r
126 &Major,\r
127 &Minor\r
128 );\r
129 } else {\r
130 Length = strlen(Str);\r
131 if (Length < 4) {\r
9de30670 132 memcpy (TemStr + 4 - Length, Str, Length);\r
9fd2164e 133 } else {\r
9de30670 134 memcpy (TemStr, Str + Length - 4, 4);\r
9fd2164e
LG
135 }\r
136 \r
137 sscanf (\r
138 TemStr,\r
139 "%02x%02x",\r
140 &Major,\r
141 &Minor\r
142 );\r
30fdf114
LG
143 }\r
144\r
30fdf114
LG
145 *MajorVer = (UINT8) Major;\r
146 *MinorVer = (UINT8) Minor;\r
147 return EFI_SUCCESS;\r
148}\r
149\r
150VOID\r
151TrimLine (\r
152 IN CHAR8 *Line\r
153 )\r
154/*++\r
155Routine Description:\r
156\r
157 This function cleans up the line by removing all whitespace and\r
158 comments\r
159\r
160Arguments:\r
161\r
162 Line - The pointer of the string\r
163\r
164Returns:\r
165\r
166 None\r
167\r
168--*/\r
169{\r
170 CHAR8 TmpLine[FILE_NAME_SIZE];\r
171 CHAR8 Char;\r
172 CHAR8 *Ptr0;\r
173 UINTN Index;\r
174 UINTN Index2;\r
175\r
176 //\r
177 // Change '#' to '//' for Comment style\r
178 //\r
179 if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {\r
180 Line[Ptr0 - Line] = 0;\r
181 }\r
182\r
183 //\r
184 // Initialize counters\r
185 //\r
186 Index = 0;\r
187 Index2 = 0;\r
188\r
189 while ((Char = Line[Index]) != 0) {\r
190 if ((Char != ' ') && (Char != '\t') && (Char != '\n') && (Char != '\r')) {\r
191 TmpLine[Index2++] = Char;\r
192 }\r
193 Index++;\r
194 }\r
195\r
196 TmpLine[Index2] = 0;\r
197 strcpy (Line, TmpLine);\r
198}\r
199\r
200VOID\r
201ValidLineCount (\r
202 IN FILE *Fp\r
203 )\r
204/*++\r
205\r
206Routine Description:\r
207\r
208 This function calculated number of valid lines in a input file.\r
209\r
210Arguments:\r
211\r
212 Fp - Pointer to a file handle which has been opened.\r
213\r
214Returns:\r
215\r
216 None\r
217\r
218--*/\r
219{\r
220 CHAR8 Buff[FILE_NAME_SIZE];\r
221 while (fgets(Buff, sizeof (Buff), Fp)) {\r
222 TrimLine (Buff);\r
223 if (Buff[0] == 0) {\r
224 continue;\r
225 }\r
226 ValidLineNum++;\r
227 }\r
228}\r
229\r
230EFI_STATUS\r
231ParseInputFile (\r
232 IN FILE *Fp\r
233 )\r
234/*++\r
235\r
236Routine Description:\r
237\r
238 This function parses the input file and tokenize the string\r
239\r
240Arguments:\r
241\r
242 Fp - Pointer to a file handle which has been opened.\r
243\r
244Returns:\r
245\r
246 None\r
247\r
248--*/\r
249{\r
250 CHAR8 *Token;\r
251 CHAR8 Buff[FILE_NAME_SIZE + 1];\r
252 CHAR8 Delimit[] = "=";\r
253\r
254 Buff [FILE_NAME_SIZE] = '\0';\r
255 Token = NULL;\r
256\r
257 while (fgets (Buff, FILE_NAME_SIZE, Fp) != NULL) {\r
258 TrimLine (Buff);\r
259 if (Buff[0] == 0) {\r
260 continue;\r
261 }\r
262 Token = strtok (Buff, Delimit);\r
263 while (Token != NULL) {\r
264 strcpy (*TokenStr, Token);\r
265 TokenStr ++;\r
266 Token = strtok (NULL, Delimit);\r
267 }\r
268 }\r
269 return EFI_SUCCESS;\r
270}\r
271\r
272EFI_STATUS\r
273InitializeComps (\r
274 VOID\r
275 )\r
276/*++\r
277\r
278Routine Description:\r
279\r
fd171542 280 This function initializes the relevant global variable which is being\r
30fdf114
LG
281 used to store the information retrieved from INF file. This also initializes\r
282 the VTF symbol file.\r
283\r
284Arguments:\r
285\r
286 None\r
287\r
288Returns:\r
289\r
290 EFI_SUCCESS - The function completed successfully\r
291 EFI_OUT_OF_RESOURCES - Malloc failed.\r
292\r
293--*/\r
294{\r
295\r
296 FileListPtr = malloc (sizeof (PARSED_VTF_INFO));\r
297\r
298 if (FileListPtr == NULL) {\r
299 return EFI_OUT_OF_RESOURCES;\r
300 }\r
301\r
302 FileListHeadPtr = FileListPtr;\r
303 memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));\r
304 FileListPtr->NextVtfInfo = NULL;\r
305\r
306 remove (SymFileName);\r
307 return EFI_SUCCESS;\r
308}\r
309\r
310VOID\r
311ParseAndUpdateComponents (\r
312 IN PARSED_VTF_INFO *VtfInfo\r
313 )\r
314/*++\r
315\r
316Routine Description:\r
317\r
fd171542 318 This function initializes the relevant global variable which is being\r
30fdf114
LG
319 used to store the information retrieved from INF file.\r
320\r
321Arguments:\r
322\r
323 VtfInfo - A pointer to the VTF Info Structure\r
324\r
325\r
326Returns:\r
327\r
328 None\r
329\r
330--*/\r
331{\r
332 UINT64 StringValue;\r
333\r
334 while (*TokenStr != NULL && (strnicmp (*TokenStr, "COMP_NAME", 9) != 0)) {\r
335\r
336 if (strnicmp (*TokenStr, "COMP_LOC", 8) == 0) {\r
337 TokenStr++;\r
338 if (strnicmp (*TokenStr, "F", 1) == 0) {\r
339 VtfInfo->LocationType = FIRST_VTF;\r
340 } else if (strnicmp (*TokenStr, "S", 1) == 0) {\r
341 VtfInfo->LocationType = SECOND_VTF;\r
342 } else {\r
343 VtfInfo->LocationType = NONE;\r
30fdf114
LG
344 }\r
345 } else if (strnicmp (*TokenStr, "COMP_TYPE", 9) == 0) {\r
346 TokenStr++;\r
347 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {\r
fd171542 348 Error (NULL, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr);\r
30fdf114
LG
349 return ;\r
350 }\r
351\r
352 VtfInfo->CompType = (UINT8) StringValue;\r
353 } else if (strnicmp (*TokenStr, "COMP_VER", 8) == 0) {\r
354 TokenStr++;\r
355 if (strnicmp (*TokenStr, "-", 1) == 0) {\r
356 VtfInfo->VersionPresent = FALSE;\r
357 VtfInfo->MajorVer = 0;\r
358 VtfInfo->MinorVer = 0;\r
359 } else {\r
360 VtfInfo->VersionPresent = TRUE;\r
361 ConvertVersionInfo (*TokenStr, &VtfInfo->MajorVer, &VtfInfo->MinorVer);\r
362 }\r
363 } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) {\r
364 TokenStr++;\r
1c47ab04
HW
365 if (strlen (*TokenStr) >= FILE_NAME_SIZE) {\r
366 Error (NULL, 0, 3000, "Invalid", "The 'COMP_BIN' name is too long.");\r
367 return ;\r
368 }\r
369 strncpy (VtfInfo->CompBinName, *TokenStr, FILE_NAME_SIZE - 1);\r
370 VtfInfo->CompBinName[FILE_NAME_SIZE - 1] = 0;\r
30fdf114
LG
371 } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) {\r
372 TokenStr++;\r
1c47ab04
HW
373 if (strlen (*TokenStr) >= FILE_NAME_SIZE) {\r
374 Error (NULL, 0, 3000, "Invalid", "The 'COMP_SYM' name is too long.");\r
375 return ;\r
376 }\r
377 strncpy (VtfInfo->CompSymName, *TokenStr, FILE_NAME_SIZE - 1);\r
378 VtfInfo->CompSymName[FILE_NAME_SIZE - 1] = 0;\r
30fdf114
LG
379 } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) {\r
380 TokenStr++;\r
381 if (strnicmp (*TokenStr, "-", 1) == 0) {\r
382 VtfInfo->PreferredSize = FALSE;\r
383 VtfInfo->CompSize = 0;\r
384 } else {\r
385 VtfInfo->PreferredSize = TRUE;\r
386 if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {\r
387 Error (NULL, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr);\r
388 return ;\r
389 }\r
390\r
391 VtfInfo->CompSize = (UINTN) StringValue;\r
392 }\r
393\r
394 } else if (strnicmp (*TokenStr, "COMP_CS", 7) == 0) {\r
395 TokenStr++;\r
396 if (strnicmp (*TokenStr, "1", 1) == 0) {\r
397 VtfInfo->CheckSumRequired = 1;\r
398 } else if (strnicmp (*TokenStr, "0", 1) == 0) {\r
399 VtfInfo->CheckSumRequired = 0;\r
400 } else {\r
401 Error (NULL, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");\r
402 }\r
403 }\r
404\r
405 TokenStr++;\r
406 if (*TokenStr == NULL) {\r
407 break;\r
408 }\r
409 }\r
410}\r
411\r
412VOID\r
413InitializeInFileInfo (\r
414 VOID\r
415 )\r
416/*++\r
417\r
418Routine Description:\r
419\r
420 This function intializes the relevant global variable which is being\r
421 used to store the information retrieved from INF file.\r
422\r
423Arguments:\r
424\r
425 NONE\r
426\r
427Returns:\r
428\r
429 NONE\r
430\r
431--*/\r
432{\r
433\r
434 SectionOptionFlag = 0;\r
435 SectionCompFlag = 0;\r
436 TokenStr = OrgStrTokPtr;\r
437\r
438 while (*TokenStr != NULL) {\r
439 if (strnicmp (*TokenStr, "[OPTIONS]", 9) == 0) {\r
440 SectionOptionFlag = 1;\r
441 SectionCompFlag = 0;\r
442 }\r
443\r
444 if (strnicmp (*TokenStr, "[COMPONENTS]", 12) == 0) {\r
445 if (FileListPtr == NULL) {\r
446 FileListPtr = FileListHeadPtr;\r
447 }\r
448\r
449 SectionCompFlag = 1;\r
450 SectionOptionFlag = 0;\r
451 TokenStr++;\r
452 }\r
453\r
454 if (SectionOptionFlag) {\r
455 if (stricmp (*TokenStr, "IA32_RST_BIN") == 0) {\r
456 TokenStr++;\r
1c47ab04
HW
457 if (strlen (*TokenStr) >= FILE_NAME_SIZE) {\r
458 Error (NULL, 0, 3000, "Invalid", "The 'IA32_RST_BIN' name is too long.");\r
459 break;\r
460 }\r
461 strncpy (IA32BinFile, *TokenStr, FILE_NAME_SIZE - 1);\r
462 IA32BinFile[FILE_NAME_SIZE - 1] = 0;\r
30fdf114
LG
463 }\r
464 }\r
465\r
466 if (SectionCompFlag) {\r
467 if (stricmp (*TokenStr, "COMP_NAME") == 0) {\r
468 TokenStr++;\r
1c47ab04
HW
469 if (strlen (*TokenStr) >= COMPONENT_NAME_SIZE) {\r
470 Error (NULL, 0, 3000, "Invalid", "The 'COMP_NAME' name is too long.");\r
471 break;\r
472 }\r
473 strncpy (FileListPtr->CompName, *TokenStr, COMPONENT_NAME_SIZE - 1);\r
474 FileListPtr->CompName[COMPONENT_NAME_SIZE - 1] = 0;\r
30fdf114
LG
475 TokenStr++;\r
476 ParseAndUpdateComponents (FileListPtr);\r
477 }\r
478\r
479 if (*TokenStr != NULL) {\r
480 FileListPtr->NextVtfInfo = malloc (sizeof (PARSED_VTF_INFO));\r
481 if (FileListPtr->NextVtfInfo == NULL) {\r
482 Error (NULL, 0, 4003, "Resource", "Out of memory resources.", NULL);\r
483 break;\r
484 }\r
485 FileListPtr = FileListPtr->NextVtfInfo;\r
486 memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));\r
487 FileListPtr->NextVtfInfo = NULL;\r
488 continue;\r
489 } else {\r
490 break;\r
491 }\r
492 }\r
493\r
494 TokenStr++;\r
495 }\r
496}\r
497\r
498EFI_STATUS\r
499GetVtfRelatedInfoFromInfFile (\r
500 IN FILE *FilePointer\r
501 )\r
502/*++\r
503\r
504Routine Description:\r
505\r
506 This function reads the input file, parse it and create a list of tokens\r
507 which is parsed and used, to intialize the data related to VTF\r
508\r
509Arguments:\r
510\r
511 FileName - FileName which needed to be read to parse data\r
512\r
513Returns:\r
514\r
515 EFI_ABORTED - Error in opening file\r
516 EFI_INVALID_PARAMETER - File doesn't contain any valid information\r
517 EFI_OUT_OF_RESOURCES - Malloc Failed\r
518 EFI_SUCCESS - The function completed successfully\r
519\r
520--*/\r
521{\r
522 FILE *Fp;\r
523 UINTN Index;\r
524 UINTN Index1;\r
525 EFI_STATUS Status;\r
526\r
527 Status = EFI_SUCCESS;\r
528 Fp = FilePointer;\r
529 if (Fp == NULL) {\r
530 Error (NULL, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");\r
531 return EFI_ABORTED;\r
532 }\r
533\r
534 ValidLineCount (Fp);\r
535\r
536 if (ValidLineNum == 0) {\r
537 Error (NULL, 0, 2000, "Invalid parameter", "File does not contain any valid information!");\r
538 return EFI_INVALID_PARAMETER;\r
539 }\r
540\r
541 TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));\r
542\r
543 if (TokenStr == NULL) {\r
544 return EFI_OUT_OF_RESOURCES;\r
545 }\r
546\r
547 memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));\r
548 OrgStrTokPtr = TokenStr;\r
549\r
550 for (Index = 0; Index < (2 * ValidLineNum); Index++) {\r
551 *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);\r
552\r
553 if (*TokenStr == NULL) {\r
554 Status = EFI_OUT_OF_RESOURCES;\r
555 goto ParseFileError;\r
556 }\r
557\r
558 memset (*TokenStr, 0, FILE_NAME_SIZE);\r
559 TokenStr++;\r
560 }\r
561\r
562 TokenStr = OrgStrTokPtr;\r
563 fseek (Fp, 0L, SEEK_SET);\r
564\r
565 Status = InitializeComps ();\r
566\r
567 if (Status != EFI_SUCCESS) {\r
568 goto ParseFileError;\r
569 }\r
570\r
571 Status = ParseInputFile (Fp);\r
572 if (Status != EFI_SUCCESS) {\r
573 goto ParseFileError;\r
574 }\r
575\r
576 InitializeInFileInfo ();\r
577\r
578ParseFileError:\r
579\r
580 for (Index1 = 0; Index1 < Index; Index1 ++) {\r
581 free (OrgStrTokPtr[Index1]);\r
582 }\r
583\r
584 free (OrgStrTokPtr);\r
585\r
586 return Status;\r
587}\r
588\r
589VOID\r
590GetRelativeAddressInVtfBuffer (\r
591 IN UINT64 Address,\r
592 IN OUT UINTN *RelativeAddress,\r
593 IN LOC_TYPE LocType\r
594 )\r
595/*++\r
596\r
597Routine Description:\r
598\r
599 This function checks for the address alignmnet for specified data boundary. In\r
600 case the address is not aligned, it returns FALSE and the amount of data in\r
601 terms of byte needed to adjust to get the boundary alignmnet. If data is\r
602 aligned, TRUE will be returned.\r
603\r
604Arguments:\r
605\r
606 Address - The address of the flash map space\r
607 RelativeAddress - The relative address of the Buffer\r
608 LocType - The type of the VTF\r
609\r
610\r
611Returns:\r
612\r
613\r
614--*/\r
615{\r
616 UINT64 TempAddress;\r
617 UINT8 *LocalBuff;\r
618\r
619 if (LocType == FIRST_VTF) {\r
620 LocalBuff = (UINT8 *) Vtf1EndBuffer;\r
621 TempAddress = Fv1EndAddress - Address;\r
622 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;\r
623 } else {\r
624 LocalBuff = (UINT8 *) Vtf2EndBuffer;\r
625 TempAddress = Fv2EndAddress - Address;\r
626 *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;\r
627 }\r
628}\r
629\r
630EFI_STATUS\r
631GetComponentVersionInfo (\r
632 IN OUT PARSED_VTF_INFO *VtfInfo,\r
633 IN UINT8 *Buffer\r
634 )\r
635/*++\r
636Routine Description:\r
637\r
638 This function will extract the version information from File\r
639\r
640Arguments:\r
641\r
642 VtfInfo - A Pointer to the VTF Info Structure\r
643 Buffer - A Pointer to type UINT8\r
644\r
645Returns:\r
646\r
647 EFI_SUCCESS - The function completed successfully\r
648 EFI_INVALID_PARAMETER - The parameter is invalid\r
649\r
650--*/\r
651{\r
652 UINT16 VersionInfo;\r
653 EFI_STATUS Status;\r
654\r
655 switch (VtfInfo->CompType) {\r
656\r
657 case COMP_TYPE_FIT_PAL_A:\r
658 case COMP_TYPE_FIT_PAL_B:\r
659 memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));\r
660 VtfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);\r
661 VtfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF);\r
662 Status = EFI_SUCCESS;\r
663 break;\r
664\r
665 default:\r
666 Status = EFI_INVALID_PARAMETER;\r
667 break;\r
668 }\r
669\r
670 return Status;\r
671}\r
672\r
673BOOLEAN\r
674CheckAddressAlignment (\r
675 IN UINT64 Address,\r
676 IN UINT64 AlignmentData,\r
677 IN OUT UINT64 *AlignAdjustByte\r
678 )\r
679/*++\r
680\r
681Routine Description:\r
682\r
683 This function checks for the address alignmnet for specified data boundary. In\r
684 case the address is not aligned, it returns FALSE and the amount of data in\r
685 terms of byte needed to adjust to get the boundary alignmnet. If data is\r
686 aligned, TRUE will be returned.\r
687\r
688Arguments:\r
689\r
690 Address - Pointer to buffer containing byte data of component.\r
691 AlignmentData - DataSize for which address needed to be aligned\r
692 AlignAdjustByte - Number of bytes needed to adjust alignment.\r
693\r
694Returns:\r
695\r
696 TRUE - Address is aligned to specific data size boundary\r
697 FALSE - Address in not aligned to specified data size boundary\r
698 - Add/Subtract AlignAdjustByte to aling the address.\r
699\r
700--*/\r
701{\r
702 //\r
703 // Check if the assigned address is on address boundary. If not, it will\r
704 // return the remaining byte required to adjust the address for specified\r
705 // address boundary\r
706 //\r
707 *AlignAdjustByte = (Address % AlignmentData);\r
708\r
709 if (*AlignAdjustByte == 0) {\r
710 return TRUE;\r
711 } else {\r
712 return FALSE;\r
713 }\r
714}\r
715\r
716EFI_STATUS\r
717GetFitTableStartAddress (\r
718 IN OUT FIT_TABLE **FitTable\r
719 )\r
720/*++\r
721\r
722Routine Description:\r
723\r
724 Get the FIT table start address in VTF Buffer\r
725\r
726Arguments:\r
727\r
728 FitTable - Pointer to available fit table where new component can be added\r
729\r
730Returns:\r
731\r
732 EFI_SUCCESS - The function completed successfully\r
733\r
734--*/\r
735{\r
736 UINT64 FitTableAdd;\r
737 UINT64 FitTableAddOffset;\r
738 UINTN RelativeAddress;\r
739\r
740 //\r
741 // Read the Fit Table address from Itanium-based address map.\r
742 //\r
743 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
744\r
745 //\r
746 // Translate this Itanium-based address in terms of local buffer address which\r
747 // contains the image for Boot Strapped File. The relative address will be\r
748 // the address of fit table VTF buffer.\r
749 //\r
750 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);\r
751 FitTableAdd = *(UINTN *) RelativeAddress;\r
752\r
753 //\r
754 // The FitTableAdd is the extracted Itanium based address pointing to FIT\r
755 // table. The relative address will return its actual location in VTF\r
756 // Buffer.\r
757 //\r
758 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
759\r
760 *FitTable = (FIT_TABLE *) RelativeAddress;\r
761\r
762 return EFI_SUCCESS;\r
763}\r
764\r
765EFI_STATUS\r
766GetNextAvailableFitPtr (\r
767 IN FIT_TABLE **FitPtr\r
768 )\r
769/*++\r
770\r
771Routine Description:\r
772\r
773 Get the FIT table address and locate the free space in fit where we can add\r
774 new component. In this process, this function locates the fit table using\r
775 Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)\r
776 and locate the available location in FIT table to be used by new components.\r
777 If there are any Fit table which areg not being used contains ComponentType\r
778 field as 0x7F. If needed we can change this and spec this out.\r
779\r
780Arguments:\r
781\r
782 FitPtr - Pointer to available fit table where new component can be added\r
783\r
784Returns:\r
785\r
786 EFI_SUCCESS - The function completed successfully\r
787\r
788--*/\r
789{\r
790 FIT_TABLE *TmpFitPtr;\r
791 UINT64 FitTableAdd;\r
792 UINT64 FitTableAddOffset;\r
793 UINTN Index;\r
794 UINTN NumFitComponents;\r
795 UINTN RelativeAddress;\r
796\r
797 //\r
798 // Read the Fit Table address from Itanium-based address map.\r
799 //\r
800 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
801\r
802 //\r
803 // Translate this Itanium-based address in terms of local buffer address which\r
804 // contains the image for Boot Strapped File. The relative address will be\r
805 // the address of fit table VTF buffer.\r
806 //\r
807 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);\r
808 FitTableAdd = *(UINTN *) RelativeAddress;\r
809\r
810 //\r
811 // The FitTableAdd is the extracted Itanium based address pointing to FIT\r
812 // table. The relative address will return its actual location in VTF\r
813 // Buffer.\r
814 //\r
815 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
816\r
817 TmpFitPtr = (FIT_TABLE *) RelativeAddress;\r
818 NumFitComponents = TmpFitPtr->CompSize;\r
c52d9f71 819 *FitPtr = NULL;\r
30fdf114
LG
820\r
821 for (Index = 0; Index < NumFitComponents; Index++) {\r
822 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {\r
823 *FitPtr = TmpFitPtr;\r
824 break;\r
825 }\r
826\r
827 TmpFitPtr++;\r
828 }\r
829\r
830 return EFI_SUCCESS;\r
831}\r
832\r
833int\r
834CompareItems (\r
835 IN const VOID *Arg1,\r
836 IN const VOID *Arg2\r
837 )\r
838/*++\r
839\r
840Routine Description:\r
841\r
842 This function is used by qsort to sort the FIT table based upon Component\r
843 Type in their incresing order.\r
844\r
845Arguments:\r
846\r
847 Arg1 - Pointer to Arg1\r
848 Arg2 - Pointer to Arg2\r
849\r
850Returns:\r
851\r
852 None\r
853\r
854--*/\r
855{\r
856 if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {\r
857 return 1;\r
858 } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {\r
859 return -1;\r
860 } else {\r
861 return 0;\r
862 }\r
863}\r
864\r
865VOID\r
866SortFitTable (\r
867 IN VOID\r
868 )\r
869/*++\r
870\r
871Routine Description:\r
872\r
873 This function is used by qsort to sort the FIT table based upon Component\r
874 Type in their incresing order.\r
875\r
876Arguments:\r
877\r
878 VOID\r
879\r
880Returns:\r
881\r
882 None\r
883\r
884--*/\r
885{\r
886 FIT_TABLE *FitTable;\r
887 FIT_TABLE *TmpFitPtr;\r
888 UINTN NumFitComponents;\r
889 UINTN Index;\r
890\r
891 GetFitTableStartAddress (&FitTable);\r
892 TmpFitPtr = FitTable;\r
893 NumFitComponents = 0;\r
894 for (Index = 0; Index < FitTable->CompSize; Index++) {\r
895 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) {\r
896 NumFitComponents += 1;\r
897 }\r
898 TmpFitPtr++;\r
899 }\r
900 qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);\r
901}\r
902\r
903VOID\r
904UpdateFitEntryForFwVolume (\r
905 IN UINT64 Size\r
906 )\r
907/*++\r
908\r
909Routine Description:\r
910\r
911 This function updates the information about Firmware Volume in FIT TABLE.\r
912 This FIT table has to be immediately below the PAL_A Start and it contains\r
913 component type and address information. Other information can't be\r
914 created this time so we would need to fix it up..\r
915\r
916\r
917Arguments:\r
918\r
919 Size - Firmware Volume Size\r
920\r
921Returns:\r
922\r
923 VOID\r
924\r
925--*/\r
926{\r
927 FIT_TABLE *CompFitPtr;\r
928 UINTN RelativeAddress;\r
929\r
930 //\r
931 // FV Fit table will be located at PAL_A Startaddress - 16 byte location\r
932 //\r
933 Vtf1LastStartAddress -= 0x10;\r
934 Vtf1TotalSize += 0x10;\r
935\r
936 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);\r
937\r
938 CompFitPtr = (FIT_TABLE *) RelativeAddress;\r
939 CompFitPtr->CompAddress = Fv1BaseAddress;\r
940\r
941 //\r
942 // Since we don't have any information about its location in Firmware Volume,\r
943 // initialize address to 0. This will be updated once Firmware Volume is\r
944 // being build and its current address will be fixed in FIT table. Currently\r
945 // we haven't implemented it so far and working on architectural clarafication\r
946 //\r
947 //\r
948 // Firmware Volume Size in 16 byte block\r
949 //\r
950 CompFitPtr->CompSize = ((UINT32) Size) / 16;\r
951\r
952 //\r
953 // Since Firmware Volume does not exist by the time we create this FIT info\r
954 // this should be fixedup from Firmware Volume creation tool. We haven't\r
955 // worked out a method so far.\r
956 //\r
957 CompFitPtr->CompVersion = MAKE_VERSION (0, 0);\r
958\r
959 //\r
960 // Since we don't have any info about this file, we are making sure that\r
961 // checksum is not needed.\r
962 //\r
963 CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);\r
964\r
965 //\r
966 // Since non VTF component will reside outside the VTF, we will not have its\r
967 // binary image while creating VTF, hence we will not perform checksum at\r
968 // this time. Once Firmware Volume is being created which will contain this\r
969 // VTF, it will fix the FIT table for all the non VTF component and hence\r
970 // checksum\r
971 //\r
972 CompFitPtr->CheckSum = 0;\r
973}\r
974\r
975EFI_STATUS\r
976UpdateFitEntryForNonVTFComp (\r
977 IN PARSED_VTF_INFO *VtfInfo\r
978 )\r
979/*++\r
980\r
981Routine Description:\r
982\r
983 This function updates the information about non VTF component in FIT TABLE.\r
984 Since non VTF componets binaries are not part of VTF binary, we would still\r
985 be required to update its location information in Firmware Volume, inside\r
986 FIT table.\r
987\r
988Arguments:\r
989\r
990 VtfInfo - Pointer to VTF Info Structure\r
991\r
992Returns:\r
993\r
994 EFI_ABORTED - The function fails to update the component in FIT\r
995 EFI_SUCCESS - The function completed successfully\r
996\r
997--*/\r
998{\r
999 FIT_TABLE *CompFitPtr;\r
1000\r
1001 //\r
1002 // Scan the FIT table for available space\r
1003 //\r
1004 GetNextAvailableFitPtr (&CompFitPtr);\r
1005 if (CompFitPtr == NULL) {\r
1006 Error (NULL, 0, 5003, "Invalid", "Can't update this component in FIT");\r
1007 return EFI_ABORTED;\r
1008 }\r
1009\r
1010 //\r
1011 // Since we don't have any information about its location in Firmware Volume,\r
1012 // initialize address to 0. This will be updated once Firmware Volume is\r
1013 // being build and its current address will be fixed in FIT table\r
1014 //\r
1015 CompFitPtr->CompAddress = 0;\r
1016 CompFitPtr->CompSize = VtfInfo->CompSize;\r
1017 CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1018 CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1019\r
1020 //\r
1021 // Since non VTF component will reside outside the VTF, we will not have its\r
1022 // binary image while creating VTF, hence we will not perform checksum at\r
1023 // this time. Once Firmware Volume is being created which will contain this\r
1024 // VTF, it will fix the FIT table for all the non VTF component and hence\r
1025 // checksum\r
1026 //\r
1027 CompFitPtr->CheckSum = 0;\r
1028\r
1029 //\r
1030 // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base\r
1031 // address of Firmware Volume in which this VTF will be attached.\r
1032 //\r
1033 if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {\r
1034 CompFitPtr->CompAddress = Fv1BaseAddress;\r
1035 }\r
1036\r
1037 return EFI_SUCCESS;\r
1038}\r
1039\r
1040//\r
1041// !!!WARNING\r
1042// This function is updating the SALE_ENTRY in Itanium address space as per SAL\r
1043// spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI\r
1044// CORE moves in Firmware Volume, we would need to modify this function to be\r
1045// used with a API which will detect PEICORE component while building Firmware\r
1046// Volume and update its entry in FIT table as well as in Itanium address space\r
1047// as per Intel?Itanium(TM) SAL address space\r
1048//\r
1049EFI_STATUS\r
1050UpdateEntryPoint (\r
1051 IN PARSED_VTF_INFO *VtfInfo,\r
1052 IN UINT64 *CompStartAddress\r
1053 )\r
1054/*++\r
1055\r
1056Routine Description:\r
1057\r
1058 This function updated the architectural entry point in IPF, SALE_ENTRY.\r
1059\r
1060Arguments:\r
1061\r
1062 VtfInfo - Pointer to VTF Info Structure\r
1063 CompStartAddress - Pointer to Component Start Address\r
1064\r
1065Returns:\r
1066\r
1067 EFI_INVALID_PARAMETER - The parameter is invalid\r
1068 EFI_SUCCESS - The function completed successfully\r
1069\r
1070--*/\r
1071{\r
1072 UINTN RelativeAddress;\r
1073 UINT64 SalEntryAdd;\r
1074 FILE *Fp;\r
1075 UINTN Offset;\r
1076\r
1077 CHAR8 Buff[FILE_NAME_SIZE];\r
1078 CHAR8 Buff1[10];\r
1079 CHAR8 Buff2[10];\r
1080 CHAR8 OffsetStr[30];\r
1081 CHAR8 Buff3[10];\r
1082 CHAR8 Buff4[10];\r
1083 CHAR8 Buff5[10];\r
1084 CHAR8 Token[50];\r
a9b4ee43 1085 CHAR8 FormatString[MAX_LINE_LEN];\r
30fdf114 1086\r
1be2ed90 1087 Fp = fopen (LongFilePath (VtfInfo->CompSymName), "rb");\r
30fdf114
LG
1088\r
1089 if (Fp == NULL) {\r
1090 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName);\r
1091 return EFI_INVALID_PARAMETER;\r
1092 }\r
1093\r
5baa399e
HW
1094 //\r
1095 // Generate the format string for fscanf\r
1096 //\r
a9b4ee43 1097 sprintf (\r
5baa399e 1098 FormatString,\r
5baa399e
HW
1099 "%%%us %%%us %%%us %%%us %%%us %%%us %%%us",\r
1100 (unsigned) sizeof (Buff1) - 1,\r
1101 (unsigned) sizeof (Buff2) - 1,\r
1102 (unsigned) sizeof (OffsetStr) - 1,\r
1103 (unsigned) sizeof (Buff3) - 1,\r
1104 (unsigned) sizeof (Buff4) - 1,\r
1105 (unsigned) sizeof (Buff5) - 1,\r
1106 (unsigned) sizeof (Token) - 1\r
1107 );\r
1108\r
30fdf114
LG
1109 while (fgets (Buff, sizeof (Buff), Fp) != NULL) {\r
1110 fscanf (\r
1111 Fp,\r
5baa399e 1112 FormatString,\r
30fdf114
LG
1113 Buff1,\r
1114 Buff2,\r
1115 OffsetStr,\r
1116 Buff3,\r
1117 Buff4,\r
1118 Buff5,\r
1119 Token\r
1120 );\r
1121 if (strnicmp (Token, "SALE_ENTRY", 10) == 0) {\r
1122 break;\r
1123 }\r
1124 }\r
1125\r
1126 Offset = strtoul (OffsetStr, NULL, 16);\r
1127\r
1128 *CompStartAddress += Offset;\r
1129 SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);\r
1130\r
1131 GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);\r
1132\r
1133 memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));\r
1134\r
1135 if (Fp != NULL) {\r
1136 fclose (Fp);\r
1137 }\r
1138\r
1139 return EFI_SUCCESS;\r
1140}\r
1141\r
1142EFI_STATUS\r
1143CreateAndUpdateComponent (\r
1144 IN PARSED_VTF_INFO *VtfInfo\r
1145 )\r
1146/*++\r
1147\r
1148Routine Description:\r
1149\r
1150 This function reads the binary file for each components and update them\r
1151 in VTF Buffer as well as in FIT table. If the component is located in non\r
1152 VTF area, only the FIT table address will be updated\r
1153\r
1154Arguments:\r
1155\r
1156 VtfInfo - Pointer to Parsed Info\r
1157\r
1158Returns:\r
1159\r
1160 EFI_SUCCESS - The function completed successful\r
1161 EFI_ABORTED - Aborted due to one of the many reasons like:\r
1162 (a) Component Size greater than the specified size.\r
1163 (b) Error opening files.\r
90114c10 1164 (c) Fail to get the FIT table address.\r
30fdf114
LG
1165\r
1166 EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()\r
1167 EFI_OUT_OF_RESOURCES Memory allocation failure.\r
1168\r
1169--*/\r
1170{\r
1171 EFI_STATUS Status;\r
1172 UINT64 CompStartAddress;\r
1173 UINT64 FileSize;\r
30fdf114
LG
1174 UINT64 NumAdjustByte;\r
1175 UINT8 *Buffer;\r
1176 FILE *Fp;\r
1177 FIT_TABLE *CompFitPtr;\r
1178 BOOLEAN Aligncheck;\r
1179\r
1180 if (VtfInfo->LocationType == NONE) {\r
1181 UpdateFitEntryForNonVTFComp (VtfInfo);\r
1182 return EFI_SUCCESS;\r
1183 }\r
1184\r
1be2ed90 1185 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");\r
30fdf114
LG
1186\r
1187 if (Fp == NULL) {\r
1188 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);\r
1189 return EFI_ABORTED;\r
1190 }\r
1191\r
1192 FileSize = _filelength (fileno (Fp));\r
1193 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {\r
1194\r
1195 //\r
1196 // BUGBUG: Satish to correct\r
1197 //\r
1198 FileSize -= SIZE_OF_PAL_HEADER;\r
1199 }\r
1200\r
1201 if (VtfInfo->PreferredSize) {\r
1202 if (FileSize > VtfInfo->CompSize) {\r
181c9559 1203 fclose (Fp);\r
30fdf114
LG
1204 Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size.");\r
1205 return EFI_ABORTED;\r
1206 }\r
1207\r
1208 FileSize = VtfInfo->CompSize;\r
1209 }\r
1210\r
1211 Buffer = malloc ((UINTN) FileSize);\r
1212 if (Buffer == NULL) {\r
181c9559 1213 fclose (Fp);\r
30fdf114
LG
1214 return EFI_OUT_OF_RESOURCES;\r
1215 }\r
1216 memset (Buffer, 0, (UINTN) FileSize);\r
1217\r
1218 if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {\r
1219\r
1220 //\r
1221 // Read first 64 bytes of PAL header and use it to find version info\r
1222 //\r
0d2711a6 1223 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);\r
30fdf114
LG
1224\r
1225 //\r
1226 // PAL header contains the version info. Currently, we will use the header\r
1227 // to read version info and then discard.\r
1228 //\r
1229 if (!VtfInfo->VersionPresent) {\r
1230 GetComponentVersionInfo (VtfInfo, Buffer);\r
1231 }\r
1232 }\r
1233\r
0d2711a6 1234 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
30fdf114
LG
1235 fclose (Fp);\r
1236\r
1237 //\r
1238 // If it is non PAL_B component, pass the entire buffer to get the version\r
1239 // info and implement any specific case inside GetComponentVersionInfo.\r
1240 //\r
1241 if (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) {\r
1242 if (!VtfInfo->VersionPresent) {\r
1243 GetComponentVersionInfo (VtfInfo, Buffer);\r
1244 }\r
1245 }\r
1246\r
1247 if (VtfInfo->LocationType == SECOND_VTF) {\r
1248\r
1249 CompStartAddress = (Vtf2LastStartAddress - FileSize);\r
1250 } else {\r
1251 CompStartAddress = (Vtf1LastStartAddress - FileSize);\r
1252 }\r
1253\r
1254 if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) {\r
1255 Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);\r
1256 } else {\r
1257 Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);\r
1258 }\r
1259\r
1260 if (!Aligncheck) {\r
1261 CompStartAddress -= NumAdjustByte;\r
1262 }\r
1263\r
1264 if (VtfInfo->LocationType == SECOND_VTF && SecondVTF == TRUE) {\r
1265 Vtf2LastStartAddress = CompStartAddress;\r
1266 Vtf2TotalSize += (UINT32) (FileSize + NumAdjustByte);\r
1267 Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);\r
1268 } else if (VtfInfo->LocationType == FIRST_VTF) {\r
1269 Vtf1LastStartAddress = CompStartAddress;\r
1270 Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte);\r
1271 Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);\r
1272 } else {\r
399caf2d 1273 free (Buffer);\r
30fdf114
LG
1274 Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");\r
1275 return EFI_INVALID_PARAMETER;\r
1276 }\r
1277\r
1278 if (EFI_ERROR (Status)) {\r
399caf2d 1279 free (Buffer);\r
30fdf114
LG
1280 return EFI_ABORTED;\r
1281 }\r
1282\r
1283 GetNextAvailableFitPtr (&CompFitPtr);\r
90114c10
HW
1284 if (CompFitPtr == NULL) {\r
1285 free (Buffer);\r
1286 return EFI_ABORTED;\r
1287 }\r
30fdf114
LG
1288\r
1289 CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;\r
1290 if ((FileSize % 16) != 0) {\r
399caf2d 1291 free (Buffer);\r
30fdf114
LG
1292 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");\r
1293 return EFI_INVALID_PARAMETER;\r
1294 }\r
1295 //assert ((FileSize % 16) == 0);\r
1296 CompFitPtr->CompSize = (UINT32) (FileSize / 16);\r
1297 CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1298 CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1299 if (VtfInfo->CheckSumRequired) {\r
1300 CompFitPtr->CheckSum = 0;\r
1301 CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);\r
1302 }\r
1303\r
1304 //\r
1305 // Free the buffer\r
1306 //\r
1307 if (Buffer) {\r
1308 free (Buffer);\r
1309 }\r
1310\r
1311 //\r
1312 // Update the SYM file for this component based on it's start address.\r
1313 //\r
b303ea72 1314 Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);\r
30fdf114
LG
1315 if (EFI_ERROR (Status)) {\r
1316\r
1317 //\r
1318 // At this time, SYM files are not required, so continue on error.\r
1319 //\r
1320 }\r
1321\r
1322 // !!!!!!!!!!!!!!!!!!!!!\r
1323 // BUGBUG:\r
1324 // This part of the code is a temporary line since PEICORE is going to be inside\r
1325 // VTF till we work out how to determine the SALE_ENTRY through it. We will need\r
1326 // to clarify so many related questions\r
1327 // !!!!!!!!!!!!!!!!!!!!!!!\r
1328\r
1329 if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) {\r
1330 Status = UpdateEntryPoint (VtfInfo, &CompStartAddress);\r
1331 }\r
1332\r
1333 return Status;\r
1334}\r
1335\r
1336EFI_STATUS\r
1337CreateAndUpdatePAL_A (\r
1338 IN PARSED_VTF_INFO *VtfInfo\r
1339 )\r
1340/*++\r
1341\r
1342Routine Description:\r
1343\r
1344 This function reads the binary file for each components and update them\r
1345 in VTF Buffer as well as FIT table\r
1346\r
1347Arguments:\r
1348\r
1349 VtfInfo - Pointer to Parsed Info\r
1350\r
1351Returns:\r
1352\r
1353 EFI_ABORTED - Due to one of the following reasons:\r
1354 (a)Error Opening File\r
1355 (b)The PAL_A Size is more than specified size status\r
1356 One of the values mentioned below returned from\r
1357 call to UpdateSymFile\r
1358 EFI_SUCCESS - The function completed successfully.\r
1359 EFI_INVALID_PARAMETER - One of the input parameters was invalid.\r
1360 EFI_ABORTED - An error occurred.UpdateSymFile\r
1361 EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
1362\r
1363--*/\r
1364{\r
1365 EFI_STATUS Status;\r
1366 UINT64 PalStartAddress;\r
1367 UINT64 AbsAddress;\r
1368 UINTN RelativeAddress;\r
1369 UINT64 FileSize;\r
30fdf114
LG
1370 UINT8 *Buffer;\r
1371 FILE *Fp;\r
1372 FIT_TABLE *PalFitPtr;\r
1373\r
1be2ed90 1374 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");\r
30fdf114
LG
1375\r
1376 if (Fp == NULL) {\r
1377 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);\r
1378 return EFI_ABORTED;\r
1379 }\r
1380\r
1381 FileSize = _filelength (fileno (Fp));\r
1382 if (FileSize < 64) {\r
181c9559 1383 fclose (Fp);\r
30fdf114
LG
1384 Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");\r
1385 return EFI_INVALID_PARAMETER;\r
1386 }\r
1387 FileSize -= SIZE_OF_PAL_HEADER;\r
1388\r
1389\r
1390 if (VtfInfo->PreferredSize) {\r
1391 if (FileSize > VtfInfo->CompSize) {\r
181c9559 1392 fclose (Fp);\r
30fdf114
LG
1393 Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");\r
1394 return EFI_ABORTED;\r
1395 }\r
1396\r
1397 FileSize = VtfInfo->CompSize;\r
1398 }\r
1399\r
1400 Buffer = malloc ((UINTN) FileSize);\r
1401 if (Buffer == NULL) {\r
181c9559 1402 fclose (Fp);\r
30fdf114
LG
1403 return EFI_OUT_OF_RESOURCES;\r
1404 }\r
1405 memset (Buffer, 0, (UINTN) FileSize);\r
1406\r
1407 //\r
1408 // Read, Get version Info and discard the PAL header.\r
1409 //\r
0d2711a6 1410 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);\r
30fdf114
LG
1411\r
1412 //\r
1413 // Extract the version info from header of PAL_A. Once done, discrad this buffer\r
1414 //\r
1415 if (!VtfInfo->VersionPresent) {\r
1416 GetComponentVersionInfo (VtfInfo, Buffer);\r
1417 }\r
1418\r
1419 //\r
1420 // Read PAL_A file in a buffer\r
1421 //\r
0d2711a6 1422 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
30fdf114
LG
1423 fclose (Fp);\r
1424\r
1425 PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);\r
1426 Vtf1LastStartAddress = PalStartAddress;\r
1427 Vtf1TotalSize += (UINT32) FileSize;\r
1428 Status = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);\r
1429\r
1430 AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;\r
1431 GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);\r
1432 PalFitPtr = (FIT_TABLE *) RelativeAddress;\r
1433 PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;\r
1434 //assert ((FileSize % 16) == 0);\r
1435 if ((FileSize % 16) != 0) {\r
399caf2d 1436 free (Buffer);\r
30fdf114
LG
1437 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");\r
1438 return EFI_INVALID_PARAMETER;\r
1439 }\r
1440\r
1441 PalFitPtr->CompSize = (UINT32) (FileSize / 16);\r
1442 PalFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1443 PalFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1444 if (VtfInfo->CheckSumRequired) {\r
1445 PalFitPtr->CheckSum = 0;\r
1446 PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);\r
1447 }\r
1448\r
1449 if (Buffer) {\r
1450 free (Buffer);\r
1451 }\r
1452\r
1453 //\r
1454 // Update the SYM file for this component based on it's start address.\r
1455 //\r
b303ea72 1456 Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);\r
30fdf114
LG
1457 if (EFI_ERROR (Status)) {\r
1458\r
1459 //\r
1460 // At this time, SYM files are not required, so continue on error.\r
1461 //\r
1462 }\r
1463\r
1464 return Status;\r
1465}\r
1466\r
1467EFI_STATUS\r
1468CreateFitTableAndInitialize (\r
1469 IN PARSED_VTF_INFO *VtfInfo\r
1470 )\r
1471/*++\r
1472\r
1473Routine Description:\r
1474\r
1475 This function creates and intializes FIT table which would be used to\r
1476 add component info inside this\r
1477\r
1478Arguments:\r
1479\r
1480 VtfInfo - Pointer to Parsed Info\r
1481\r
1482Returns:\r
1483\r
1484 EFI_ABORTED - Aborted due to no size information\r
1485 EFI_SUCCESS - The function completed successfully\r
1486\r
1487--*/\r
1488{\r
1489 UINT64 PalFitTableAdd;\r
1490 UINT64 FitTableAdd;\r
1491 UINT64 FitTableAddressOffset;\r
1492 FIT_TABLE *PalFitPtr;\r
1493 FIT_TABLE *FitStartPtr;\r
1494 UINTN NumFitComp;\r
1495 UINTN RelativeAddress;\r
1496 UINTN Index;\r
1497\r
1498 if (!VtfInfo->PreferredSize) {\r
1499 Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");\r
1500 return EFI_ABORTED;\r
1501 }\r
1502\r
1503 if ((VtfInfo->CompSize % 16) != 0) {\r
1504 Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");\r
1505 }\r
1506\r
1507 PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;\r
1508 GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);\r
1509 PalFitPtr = (FIT_TABLE *) RelativeAddress;\r
1510 PalFitTableAdd = (PalFitPtr->CompAddress - VtfInfo->CompSize);\r
1511\r
1512 FitTableAdd = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize;\r
1513 FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
1514 GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);\r
1515 *(UINT64 *) RelativeAddress = FitTableAdd;\r
1516\r
1517 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
1518\r
1519 //\r
1520 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.\r
1521 //\r
1522 FitStartPtr = (FIT_TABLE *) RelativeAddress;\r
1523\r
1524 strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ "\r
1525 assert (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0);\r
1526 FitStartPtr->CompSize = (VtfInfo->CompSize & 0x00FFFFFF) / 16;\r
1527 FitStartPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1528\r
1529 //\r
1530 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also\r
1531 // determine what to do for things like the FV component that aren't easily checksummed.\r
1532 // The checksum will be done once we are done with all the componet update in the FIT\r
1533 // table\r
1534 //\r
1535 FitStartPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1536\r
1537 NumFitComp = FitStartPtr->CompSize;\r
1538\r
1539 FitStartPtr++;\r
1540\r
1541 //\r
1542 // Intialize remaining FIT table space to UNUSED fit component type\r
1543 // so that when we need to create a FIT entry for a component, we can\r
1544 // locate a free one and use it.\r
1545 //\r
1546 for (Index = 0; Index < (NumFitComp - 1); Index++) {\r
1547 FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED\r
1548 FitStartPtr++;\r
1549 }\r
1550\r
1551 Vtf1TotalSize += VtfInfo->CompSize;\r
1552 Vtf1LastStartAddress -= VtfInfo->CompSize;\r
1553\r
1554 return EFI_SUCCESS;\r
1555}\r
1556\r
1557EFI_STATUS\r
1558WriteVtfBinary (\r
1559 IN CHAR8 *FileName,\r
1560 IN UINT32 VtfSize,\r
1561 IN LOC_TYPE LocType\r
1562 )\r
1563/*++\r
1564\r
1565Routine Description:\r
1566\r
1567 Write Firmware Volume from memory to a file.\r
1568\r
1569Arguments:\r
1570\r
1571 FileName - Output File Name which needed to be created/\r
1572 VtfSize - FileSize\r
1573 LocType - The type of the VTF\r
1574\r
1575Returns:\r
1576\r
1577 EFI_ABORTED - Returned due to one of the following resons:\r
1578 (a) Error Opening File\r
1579 (b) Failing to copy buffers\r
1580 EFI_SUCCESS - The fuction completes successfully\r
1581\r
1582--*/\r
1583{\r
1584 FILE *Fp;\r
1585 UINTN NumByte;\r
1586 VOID *VtfBuffer;\r
1587 UINTN RelativeAddress;\r
1588\r
1589 if (LocType == FIRST_VTF) {\r
1590 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);\r
1591 VtfBuffer = (VOID *) RelativeAddress;\r
1592 } else {\r
1593 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);\r
1594 VtfBuffer = (VOID *) RelativeAddress;\r
1595 }\r
1596\r
1be2ed90 1597 Fp = fopen (LongFilePath (FileName), "wb");\r
30fdf114
LG
1598 if (Fp == NULL) {\r
1599 Error (NULL, 0, 0001, "Error opening file", FileName);\r
1600 return EFI_ABORTED;\r
1601 }\r
1602\r
1603 NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp);\r
1604\r
1605 if (Fp) {\r
1606 fclose (Fp);\r
1607 }\r
1608\r
1609 if (NumByte != (sizeof (UINT8) * VtfSize)) {\r
1610 Error (NULL, 0, 0002, "Error writing file", FileName);\r
1611 return EFI_ABORTED;\r
1612 }\r
1613\r
1614 return EFI_SUCCESS;\r
1615}\r
1616\r
1617EFI_STATUS\r
1618UpdateVtfBuffer (\r
1619 IN UINT64 StartAddress,\r
1620 IN UINT8 *Buffer,\r
1621 IN UINT64 DataSize,\r
1622 IN LOC_TYPE LocType\r
1623 )\r
1624/*++\r
1625\r
1626Routine Description:\r
1627\r
1628 Update the Firmware Volume Buffer with requested buffer data\r
1629\r
1630Arguments:\r
1631\r
1632 StartAddress - StartAddress in buffer. This number will automatically\r
1633 point to right address in buffer where data needed\r
1634 to be updated.\r
1635 Buffer - Buffer pointer from data will be copied to memory mapped buffer.\r
1636 DataSize - Size of the data needed to be copied.\r
1637 LocType - The type of the VTF: First or Second\r
1638\r
1639Returns:\r
1640\r
1641 EFI_ABORTED - The input parameter is error\r
1642 EFI_SUCCESS - The function completed successfully\r
1643\r
1644--*/\r
1645{\r
1646 UINT8 *LocalBufferPtrToWrite;\r
1647\r
1648 if (LocType == FIRST_VTF) {\r
1649 if ((StartAddress | IPF_CACHE_BIT) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) {\r
1650 Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");\r
1651 return EFI_ABORTED;\r
1652 }\r
1653\r
1654 LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer;\r
1655\r
1656 LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);\r
1657\r
1658 } else {\r
1659\r
1660 if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) {\r
1661 Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress");\r
1662 return EFI_ABORTED;\r
1663 }\r
1664 LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer;\r
1665 LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);\r
1666 }\r
1667\r
1668 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);\r
1669\r
1670 return EFI_SUCCESS;\r
1671}\r
1672\r
1673EFI_STATUS\r
1674UpdateFfsHeader (\r
1675 IN UINT32 TotalVtfSize,\r
1676 IN LOC_TYPE LocType\r
1677 )\r
1678/*++\r
1679\r
1680Routine Description:\r
1681\r
1682 Update the Firmware Volume Buffer with requested buffer data\r
1683\r
1684Arguments:\r
1685\r
1686 TotalVtfSize - Size of the VTF\r
1687 Fileoffset - The start of the file relative to the start of the FV.\r
1688 LocType - The type of the VTF\r
1689\r
1690Returns:\r
1691\r
1692 EFI_SUCCESS - The function completed successfully\r
1693 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL\r
1694\r
1695--*/\r
1696{\r
1697 EFI_FFS_FILE_HEADER *FileHeader;\r
1698 UINTN RelativeAddress;\r
1699 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
1700\r
1701 //\r
1702 // Find the VTF file header location\r
1703 //\r
1704 if (LocType == FIRST_VTF) {\r
1705 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);\r
1706 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;\r
1707 } else {\r
1708 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);\r
1709 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;\r
1710 }\r
1711\r
1712 if (FileHeader == NULL) {\r
1713 return EFI_INVALID_PARAMETER;\r
1714 }\r
1715\r
1716 //\r
1717 // write header\r
1718 //\r
1719 memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
1720 memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));\r
1721 FileHeader->Type = EFI_FV_FILETYPE_RAW;\r
1722 FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;\r
1723\r
1724 //\r
1725 // Now FileSize includes the EFI_FFS_FILE_HEADER\r
1726 //\r
1727 FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF);\r
1728 FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8);\r
1729 FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16);\r
1730\r
1731 //\r
1732 // Fill in checksums and state, all three must be zero for the checksums.\r
1733 //\r
1734 FileHeader->IntegrityCheck.Checksum.Header = 0;\r
1735 FileHeader->IntegrityCheck.Checksum.File = 0;\r
1736 FileHeader->State = 0;\r
1737 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
b303ea72 1738 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) (FileHeader + 1), TotalVtfSize - sizeof (EFI_FFS_FILE_HEADER));\r
30fdf114
LG
1739 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
1740\r
1741 return EFI_SUCCESS;\r
1742}\r
1743\r
1744EFI_STATUS\r
1745ValidateAddressAndSize (\r
1746 IN UINT64 BaseAddress,\r
1747 IN UINT64 FwVolSize\r
1748 )\r
1749/*++\r
1750\r
1751Routine Description:\r
1752\r
1753 Update the Firmware Volume Buffer with requested buffer data\r
1754\r
1755Arguments:\r
1756\r
1757 BaseAddress - Base address for the Fw Volume.\r
1758\r
1759 FwVolSize - Total Size of the FwVolume to which VTF will be attached..\r
1760\r
1761Returns:\r
1762\r
1763 EFI_SUCCESS - The function completed successfully\r
1764 EFI_UNSUPPORTED - The input parameter is error\r
1765\r
1766--*/\r
1767{\r
07355bd5 1768 if ((FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {\r
30fdf114
LG
1769 return EFI_SUCCESS;\r
1770 }\r
1771\r
1772 return EFI_UNSUPPORTED;\r
1773}\r
1774\r
1775EFI_STATUS\r
1776UpdateIA32ResetVector (\r
1777 IN CHAR8 *FileName,\r
1778 IN UINT64 FirstFwVSize\r
1779 )\r
1780/*++\r
1781\r
1782Routine Description:\r
1783\r
1784 Update the 16 byte IA32 Reset vector to maintain the compatibility\r
1785\r
1786Arguments:\r
1787\r
1788 FileName - Binary file name which contains the IA32 Reset vector info..\r
1789 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..\r
1790\r
1791Returns:\r
1792\r
1793 EFI_SUCCESS - The function completed successfully\r
1794 EFI_ABORTED - Invalid File Size\r
1795 EFI_INVALID_PARAMETER - Bad File Name\r
1796 EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
1797\r
1798--*/\r
1799{\r
1800 UINT8 *Buffer;\r
1801 UINT8 *LocalVtfBuffer;\r
1802 UINTN FileSize;\r
30fdf114
LG
1803 FILE *Fp;\r
1804\r
1805 if (!strcmp (FileName, "")) {\r
1806 return EFI_INVALID_PARAMETER;\r
1807 }\r
1808\r
1be2ed90 1809 Fp = fopen (LongFilePath (FileName), "rb");\r
30fdf114
LG
1810\r
1811 if (Fp == NULL) {\r
1812 Error (NULL, 0, 0001, "Error opening file", FileName);\r
1813 return EFI_ABORTED;\r
1814 }\r
1815\r
1816 FileSize = _filelength (fileno (Fp));\r
1817\r
1818 if (FileSize > 16) {\r
181c9559 1819 fclose (Fp);\r
30fdf114
LG
1820 return EFI_ABORTED;\r
1821 }\r
1822\r
1823 Buffer = malloc (FileSize);\r
1824 if (Buffer == NULL) {\r
181c9559 1825 fclose (Fp);\r
30fdf114
LG
1826 return EFI_OUT_OF_RESOURCES;\r
1827 }\r
1828\r
0d2711a6 1829 fread (Buffer, sizeof (UINT8), FileSize, Fp);\r
30fdf114
LG
1830\r
1831 LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT;\r
1832 memcpy (LocalVtfBuffer, Buffer, FileSize);\r
1833\r
1834 if (Buffer) {\r
1835 free (Buffer);\r
1836 }\r
1837\r
1838 if (Fp != NULL) {\r
1839 fclose (Fp);\r
1840 }\r
1841 return EFI_SUCCESS;\r
1842}\r
1843\r
1844VOID\r
1845CleanUpMemory (\r
1846 VOID\r
1847 )\r
1848/*++\r
1849\r
1850Routine Description:\r
1851\r
1852 This function cleans up any allocated buffer\r
1853\r
1854Arguments:\r
1855\r
1856 NONE\r
1857\r
1858Returns:\r
1859\r
1860 NONE\r
1861\r
1862--*/\r
1863{\r
1864 PARSED_VTF_INFO *TempFileListPtr;\r
1865\r
1866 if (Vtf1Buffer) {\r
1867 free (Vtf1Buffer);\r
1868 }\r
1869\r
1870 if (Vtf2Buffer) {\r
1871 free (Vtf2Buffer);\r
1872 }\r
1873\r
1874 //\r
1875 // Cleanup the buffer which was allocated to read the file names from FV.INF\r
1876 //\r
1877 FileListPtr = FileListHeadPtr;\r
1878 while (FileListPtr != NULL) {\r
1879 TempFileListPtr = FileListPtr->NextVtfInfo;\r
1880 free (FileListPtr);\r
1881 FileListPtr = TempFileListPtr;\r
1882 }\r
1883}\r
1884\r
1885EFI_STATUS\r
1886ProcessAndCreateVtf (\r
1887 IN UINT64 Size\r
1888 )\r
1889/*++\r
1890\r
1891Routine Description:\r
1892\r
1893 This function process the link list created during INF file parsing\r
1894 and create component in VTF and updates its info in FIT table\r
1895\r
1896Arguments:\r
1897\r
1898 Size - Size of the Firmware Volume of which, this VTF belongs to.\r
1899\r
1900Returns:\r
1901\r
1902 EFI_UNSUPPORTED - Unknown FIT type\r
1903 EFI_SUCCESS - The function completed successfully\r
1904\r
1905--*/\r
1906{\r
1907 EFI_STATUS Status;\r
1908 PARSED_VTF_INFO *ParsedInfoPtr;\r
1909\r
1910 Status = EFI_SUCCESS;\r
1911\r
1912 ParsedInfoPtr = FileListHeadPtr;\r
1913\r
1914 while (ParsedInfoPtr != NULL) {\r
1915\r
1916 switch (ParsedInfoPtr->CompType) {\r
1917 //\r
1918 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here\r
1919 //\r
1920 case COMP_TYPE_FIT_HEADER:\r
1921 //COMP_TYPE_FIT_HEADER 0x00\r
1922 Status = CreateFitTableAndInitialize (ParsedInfoPtr);\r
1923 break;\r
1924\r
1925 //\r
1926 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here\r
1927 //\r
1928 case COMP_TYPE_FIT_PAL_A:\r
1929 //COMP_TYPE_FIT_PAL_A 0x0F\r
1930 Status = CreateAndUpdatePAL_A (ParsedInfoPtr);\r
1931\r
1932 //\r
1933 // Based on VTF specification, once the PAL_A component has been written,\r
1934 // update the Firmware Volume info as FIT table. This will be utilized\r
1935 // to extract the Firmware Volume Start address where this VTF will be\r
1936 // of part.\r
1937 //\r
1938 if (Status == EFI_SUCCESS) {\r
1939 UpdateFitEntryForFwVolume (Size);\r
1940 }\r
1941 break;\r
1942\r
1943 case COMP_TYPE_FIT_FV_BOOT:\r
1944 //COMP_TYPE_FIT_FV_BOOT 0x7E\r
1945 //\r
1946 // Since FIT entry for Firmware Volume has been created and it is\r
1947 // located at (PAL_A start - 16 byte). So we will not process any\r
1948 // Firmware Volume related entry from INF file\r
1949 //\r
1950 Status = EFI_SUCCESS;\r
1951 break;\r
1952\r
1953 default:\r
1954 //\r
1955 // Any other component type should be handled here. This will create the\r
1956 // image in specified VTF and create appropriate entry about this\r
1957 // component in FIT Entry.\r
1958 //\r
1959 Status = CreateAndUpdateComponent (ParsedInfoPtr);\r
1960 if (EFI_ERROR (Status)) {\r
1961 Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName);\r
1962 return EFI_ABORTED;\r
1963 } else {\r
1964 break;}\r
1965 }\r
1966\r
1967 ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo;\r
1968 }\r
1969 return Status;\r
1970}\r
1971\r
1972EFI_STATUS\r
1973GenerateVtfImage (\r
1974 IN UINT64 StartAddress1,\r
1975 IN UINT64 Size1,\r
1976 IN UINT64 StartAddress2,\r
1977 IN UINT64 Size2,\r
1978 IN FILE *fp\r
1979 )\r
1980/*++\r
1981\r
1982Routine Description:\r
1983\r
1984 This is the main function which will be called from application.\r
1985\r
1986Arguments:\r
1987\r
1988 StartAddress1 - The start address of the first VTF\r
1989 Size1 - The size of the first VTF\r
1990 StartAddress2 - The start address of the second VTF\r
1991 Size2 - The size of the second VTF\r
1992 fp - The pointer to BSF inf file\r
1993\r
1994Returns:\r
1995\r
1996 EFI_OUT_OF_RESOURCES - Can not allocate memory\r
1997 The return value can be any of the values\r
1998 returned by the calls to following functions:\r
1999 GetVtfRelatedInfoFromInfFile\r
2000 ProcessAndCreateVtf\r
2001 UpdateIA32ResetVector\r
2002 UpdateFfsHeader\r
2003 WriteVtfBinary\r
2004\r
2005--*/\r
2006{\r
2007 EFI_STATUS Status;\r
2008 FILE *VtfFP;\r
2009\r
2010 Status = EFI_UNSUPPORTED;\r
2011 VtfFP = fp;\r
2012\r
2013 if (StartAddress2 == 0) {\r
2014 SecondVTF = FALSE;\r
2015 } else {\r
2016 SecondVTF = TRUE;\r
2017 }\r
2018\r
2019 Fv1BaseAddress = StartAddress1;\r
2020 Fv1EndAddress = Fv1BaseAddress + Size1;\r
fd171542 2021 if (Fv1EndAddress != 0x100000000ULL || Size1 < 0x100000) {\r
30fdf114
LG
2022 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");\r
2023 if (Size1 < 0x100000) {\r
2024 Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");\r
2025 } else if (SecondVTF != TRUE) {\r
2026 Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");\r
2027 }\r
2028 Usage();\r
2029 return EFI_INVALID_PARAMETER;\r
2030 }\r
2031\r
2032 //\r
2033 // The image buffer for the First VTF\r
2034 //\r
2035 Vtf1Buffer = malloc ((UINTN) Size1);\r
2036 if (Vtf1Buffer == NULL) {\r
2037 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");\r
2038 return EFI_OUT_OF_RESOURCES;\r
2039 }\r
2040 memset (Vtf1Buffer, 0x00, (UINTN) Size1);\r
2041 Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1;\r
2042 Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;\r
2043\r
2044 if (SecondVTF) {\r
2045 Fv2BaseAddress = StartAddress2;\r
2046 Fv2EndAddress = Fv2BaseAddress + Size2;\r
2047 if (Fv2EndAddress != StartAddress1) {\r
2048 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");\r
2049 if (SecondVTF == TRUE) {\r
2050 Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");\r
2051 Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");\r
2052 }\r
2053 Usage();\r
2054 return EFI_INVALID_PARAMETER;\r
2055 }\r
2056\r
2057 //\r
2058 // The image buffer for the second VTF\r
2059 //\r
2060 Vtf2Buffer = malloc ((UINTN) Size2);\r
2061 if (Vtf2Buffer == NULL) {\r
2062 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");\r
2063 return EFI_OUT_OF_RESOURCES;\r
2064 }\r
2065 memset (Vtf2Buffer, 0x00, (UINTN) Size2);\r
2066 Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2;\r
2067 Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;\r
2068 }\r
2069\r
2070 Status = GetVtfRelatedInfoFromInfFile (VtfFP);\r
2071\r
2072 if (Status != EFI_SUCCESS) {\r
2073 Error (NULL, 0, 0003, "Error parsing file", "the input file.");\r
2074 CleanUpMemory ();\r
2075 return Status;\r
2076 }\r
2077\r
2078 Status = ProcessAndCreateVtf (Size1);\r
2079 if (Status != EFI_SUCCESS) {\r
2080 CleanUpMemory ();\r
2081 return Status;\r
2082 }\r
2083\r
2084 if (SectionOptionFlag) {\r
2085 Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize);\r
2086 if (Status != EFI_SUCCESS) {\r
2087 CleanUpMemory ();\r
2088 return Status;\r
2089 }\r
2090 }\r
2091\r
2092 //\r
2093 // Re arrange the FIT Table for Ascending order of their FIT Type..\r
2094 //\r
2095 SortFitTable ();\r
2096\r
2097 //\r
2098 // All components have been updated in FIT table. Now perform the FIT table\r
2099 // checksum. The following function will check if Checksum is required,\r
2100 // if yes, then it will perform the checksum otherwise not.\r
2101 //\r
2102 CalculateFitTableChecksum ();\r
2103\r
2104 //\r
2105 // Write the FFS header\r
2106 //\r
2107 Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);\r
2108 Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);\r
2109\r
2110 Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF);\r
2111 if (Status != EFI_SUCCESS) {\r
2112 CleanUpMemory ();\r
2113 return Status;\r
2114 }\r
2115 //\r
2116 // Update the VTF buffer into specified VTF binary file\r
2117 //\r
2118 Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF);\r
2119\r
2120 if (SecondVTF) {\r
2121 Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);\r
2122 Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);\r
2123 Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF);\r
2124 if (Status != EFI_SUCCESS) {\r
2125 CleanUpMemory ();\r
2126 return Status;\r
2127 }\r
2128\r
2129 //\r
2130 // Update the VTF buffer into specified VTF binary file\r
2131 //\r
2132 Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF);\r
2133 }\r
2134\r
2135 CleanUpMemory ();\r
2136\r
2137 return Status;\r
2138}\r
2139\r
2140EFI_STATUS\r
2141PeimFixupInFitTable (\r
2142 IN UINT64 StartAddress\r
2143 )\r
2144/*++\r
2145\r
2146Routine Description:\r
2147\r
2148 This function is an entry point to fixup SAL-E entry point.\r
2149\r
2150Arguments:\r
2151\r
2152 StartAddress - StartAddress for PEIM.....\r
2153\r
2154Returns:\r
2155\r
2156 EFI_SUCCESS - The function completed successfully\r
2157 EFI_ABORTED - Error Opening File\r
2158 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.\r
2159\r
2160--*/\r
2161{\r
2162 EFI_STATUS Status;\r
2163 FILE *Fp;\r
2164 UINT64 *StartAddressPtr;\r
2165 UINTN FirstFwVSize;\r
30fdf114
LG
2166\r
2167 StartAddressPtr = malloc (sizeof (UINT64));\r
2168 if (StartAddressPtr == NULL) {\r
2169 return EFI_OUT_OF_RESOURCES;\r
2170 }\r
2171 *StartAddressPtr = StartAddress;\r
2172\r
1be2ed90 2173 Fp = fopen (LongFilePath (OutFileName1), "rb");\r
30fdf114
LG
2174\r
2175 if (Fp == NULL) {\r
2176 Error (NULL, 0, 0001, "Error opening file", OutFileName1);\r
2177 if (StartAddressPtr) {\r
2178 free (StartAddressPtr);\r
2179 }\r
2180 return EFI_ABORTED;\r
2181 }\r
2182\r
2183 FirstFwVSize = _filelength (fileno (Fp));\r
2184 fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);\r
0d2711a6 2185 fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);\r
30fdf114
LG
2186\r
2187 if (Fp) {\r
2188 fclose (Fp);\r
2189 }\r
2190\r
2191 if (StartAddressPtr) {\r
2192 free (StartAddressPtr);\r
2193 }\r
2194\r
2195 Status = EFI_SUCCESS;\r
2196 return Status;\r
2197}\r
2198\r
2199EFI_STATUS\r
2200UpdateSymFile (\r
2201 IN UINT64 BaseAddress,\r
2202 IN CHAR8 *DestFileName,\r
b303ea72
LG
2203 IN CHAR8 *SourceFileName,\r
2204 IN UINT64 FileSize\r
2205\r
30fdf114
LG
2206 )\r
2207/*++\r
2208\r
2209Routine Description:\r
2210\r
2211 This function adds the SYM tokens in the source file to the destination file.\r
2212 The SYM tokens are updated to reflect the base address.\r
2213\r
2214Arguments:\r
2215\r
2216 BaseAddress - The base address for the new SYM tokens.\r
2217 DestFileName - The destination file.\r
2218 SourceFileName - The source file.\r
b303ea72 2219 FileSize - Size of bin file.\r
30fdf114
LG
2220\r
2221Returns:\r
2222\r
2223 EFI_SUCCESS - The function completed successfully.\r
2224 EFI_INVALID_PARAMETER - One of the input parameters was invalid.\r
2225 EFI_ABORTED - An error occurred.\r
2226\r
2227--*/\r
2228{\r
2229 FILE *SourceFile;\r
2230 FILE *DestFile;\r
1be2ed90
HC
2231 CHAR8 Buffer[MAX_LONG_FILE_PATH];\r
2232 CHAR8 Type[MAX_LONG_FILE_PATH];\r
2233 CHAR8 Address[MAX_LONG_FILE_PATH];\r
2234 CHAR8 Section[MAX_LONG_FILE_PATH];\r
2235 CHAR8 Token[MAX_LONG_FILE_PATH];\r
2236 CHAR8 BaseToken[MAX_LONG_FILE_PATH];\r
a9b4ee43 2237 CHAR8 FormatString[MAX_LINE_LEN];\r
30fdf114 2238 UINT64 TokenAddress;\r
b303ea72 2239 long StartLocation;\r
30fdf114
LG
2240\r
2241 //\r
2242 // Verify input parameters.\r
2243 //\r
2244 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {\r
2245 return EFI_INVALID_PARAMETER;\r
2246 }\r
2247\r
2248 //\r
2249 // Open the source file\r
2250 //\r
1be2ed90 2251 SourceFile = fopen (LongFilePath (SourceFileName), "r");\r
30fdf114
LG
2252 if (SourceFile == NULL) {\r
2253\r
2254 //\r
2255 // SYM files are not required.\r
2256 //\r
2257 return EFI_SUCCESS;\r
2258 }\r
2259\r
2260 //\r
2261 // Use the file name minus extension as the base for tokens\r
2262 //\r
1c47ab04
HW
2263 if (strlen (SourceFileName) >= MAX_LONG_FILE_PATH) {\r
2264 fclose (SourceFile);\r
2265 Error (NULL, 0, 2000, "Invalid parameter", "The source file name is too long.");\r
2266 return EFI_ABORTED;\r
2267 }\r
2268 strncpy (BaseToken, SourceFileName, MAX_LONG_FILE_PATH - 1);\r
2269 BaseToken[MAX_LONG_FILE_PATH - 1] = 0;\r
30fdf114 2270 strtok (BaseToken, ". \t\n");\r
1c47ab04
HW
2271 if (strlen (BaseToken) + strlen ("__") >= MAX_LONG_FILE_PATH) {\r
2272 fclose (SourceFile);\r
2273 Error (NULL, 0, 2000, "Invalid parameter", "The source file name is too long.");\r
2274 return EFI_ABORTED;\r
2275 }\r
2276 strncat (BaseToken, "__", MAX_LONG_FILE_PATH - strlen (BaseToken) - 1);\r
30fdf114
LG
2277\r
2278 //\r
2279 // Open the destination file\r
2280 //\r
1be2ed90 2281 DestFile = fopen (LongFilePath (DestFileName), "a+");\r
30fdf114
LG
2282 if (DestFile == NULL) {\r
2283 fclose (SourceFile);\r
2284 Error (NULL, 0, 0001, "Error opening file", DestFileName);\r
2285 return EFI_ABORTED;\r
2286 }\r
2287\r
2288 //\r
2289 // If this is the beginning of the output file, write the symbol format info.\r
2290 //\r
2291 if (fseek (DestFile, 0, SEEK_END) != 0) {\r
2292 fclose (SourceFile);\r
2293 fclose (DestFile);\r
2294 Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");\r
2295 return EFI_ABORTED;\r
2296 }\r
2297\r
2298 StartLocation = ftell (DestFile);\r
2299\r
2300 if (StartLocation == 0) {\r
2301 fprintf (DestFile, "TEXTSYM format | V1.0\n");\r
2302 } else if (StartLocation == -1) {\r
2303 fclose (SourceFile);\r
2304 fclose (DestFile);\r
2305 Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");\r
2306 return EFI_ABORTED;\r
2307 }\r
2308\r
2309 //\r
2310 // Read the first line\r
2311 //\r
1be2ed90 2312 if (fgets (Buffer, MAX_LONG_FILE_PATH, SourceFile) == NULL) {\r
30fdf114
LG
2313 Buffer[0] = 0;\r
2314 }\r
2315\r
2316 //\r
2317 // Make sure it matches the expected sym format\r
2318 //\r
2319 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
2320 fclose (SourceFile);\r
2321 fclose (DestFile);\r
2322 Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");\r
2323 return EFI_ABORTED;\r
2324 }\r
2325\r
5baa399e
HW
2326 //\r
2327 // Generate the format string for fscanf\r
2328 //\r
a9b4ee43 2329 sprintf (\r
5baa399e 2330 FormatString,\r
5baa399e
HW
2331 "%%%us | %%%us | %%%us | %%%us\n",\r
2332 (unsigned) sizeof (Type) - 1,\r
2333 (unsigned) sizeof (Address) - 1,\r
2334 (unsigned) sizeof (Section) - 1,\r
2335 (unsigned) sizeof (Token) - 1\r
2336 );\r
2337\r
30fdf114
LG
2338 //\r
2339 // Read in the file\r
2340 //\r
2341 while (feof (SourceFile) == 0) {\r
2342\r
2343 //\r
2344 // Read a line\r
2345 //\r
5baa399e 2346 if (fscanf (SourceFile, FormatString, Type, Address, Section, Token) == 4) {\r
30fdf114
LG
2347\r
2348 //\r
2349 // Get the token address\r
2350 //\r
2351 AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
b303ea72
LG
2352 if (TokenAddress > FileSize) {\r
2353 //\r
2354 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.\r
2355 //\r
2356 break;\r
2357 }\r
30fdf114
LG
2358\r
2359 //\r
2360 // Add the base address, the size of the FFS file header and the size of the peim header.\r
2361 //\r
2362 TokenAddress += BaseAddress &~IPF_CACHE_BIT;\r
2363\r
b303ea72
LG
2364 fprintf (DestFile, "%s | %016llX | ", Type, (unsigned long long) TokenAddress);\r
2365 fprintf (DestFile, "%s | %s\n %s\n", Section, Token, BaseToken); \r
30fdf114
LG
2366 }\r
2367 }\r
2368\r
2369 fclose (SourceFile);\r
2370 fclose (DestFile);\r
2371 return EFI_SUCCESS;\r
2372}\r
2373\r
2374EFI_STATUS\r
2375CalculateFitTableChecksum (\r
2376 VOID\r
2377 )\r
2378/*++\r
2379\r
2380Routine Description:\r
2381\r
2382 This function will perform byte checksum on the FIT table, if the the checksum required\r
2383 field is set to CheckSum required. If the checksum is not required then checksum byte\r
2384 will have value as 0;.\r
2385\r
2386Arguments:\r
2387\r
2388 NONE\r
2389\r
2390Returns:\r
2391\r
2392 Status - Value returned by call to CalculateChecksum8 ()\r
2393 EFI_SUCCESS - The function completed successfully\r
2394\r
2395--*/\r
2396{\r
2397 FIT_TABLE *TmpFitPtr;\r
2398 UINT64 FitTableAdd;\r
2399 UINT64 FitTableAddOffset;\r
2400 UINTN RelativeAddress;\r
2401 UINTN Size;\r
2402\r
2403 //\r
2404 // Read the Fit Table address from Itanium-based address map.\r
2405 //\r
2406 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
2407\r
2408 //\r
2409 // Translate this Itanium-based address in terms of local buffer address which\r
2410 // contains the image for Boot Strapped File\r
2411 //\r
2412 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);\r
2413 FitTableAdd = *(UINTN *) RelativeAddress;\r
2414\r
2415 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
2416\r
2417 TmpFitPtr = (FIT_TABLE *) RelativeAddress;\r
2418\r
2419 Size = TmpFitPtr->CompSize * 16;\r
2420\r
2421 if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
2422 TmpFitPtr->CheckSum = 0;\r
2423 TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);\r
2424 } else {\r
2425 TmpFitPtr->CheckSum = 0;\r
2426 }\r
2427\r
2428 return EFI_SUCCESS;\r
2429}\r
2430\r
2431VOID\r
2432Version (\r
2433 VOID\r
2434 )\r
2435/*++\r
2436\r
2437Routine Description:\r
2438\r
2439 Displays the standard utility information to SDTOUT\r
2440\r
2441Arguments:\r
2442\r
2443 None\r
2444\r
2445Returns:\r
2446\r
2447 None\r
2448\r
2449--*/\r
2450{\r
b36d134f 2451 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
2452}\r
2453\r
2454VOID\r
2455Usage (\r
2456 VOID\r
2457 )\r
2458/*++\r
2459\r
2460Routine Description:\r
2461\r
2462 Displays the utility usage syntax to STDOUT\r
2463\r
2464Arguments:\r
2465\r
2466 None\r
2467\r
2468Returns:\r
2469\r
2470 None\r
2471\r
2472--*/\r
2473{\r
2474 //\r
2475 // Summary usage\r
2476 //\r
2477 fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);\r
2478\r
2479 //\r
2480 // Copyright declaration\r
2481 //\r
1be2ed90 2482 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");\r
30fdf114
LG
2483 //\r
2484 // Details Option\r
2485 //\r
2486 fprintf (stdout, "Options:\n");\r
2487 fprintf (stdout, " -f Input_file, --filename Input_file\n\\r
2488 Input_file is name of the BS Image INF file\n");\r
2489 fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\\r
2490 BaseAddress is the starting address of Firmware Volume\n\\r
2491 where Boot Strapped Image will reside.\n");\r
2492 fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\\r
2493 FwVolumeSize is the size of Firmware Volume.\n");\r
2494 fprintf (stdout, " -o FileName, --output FileName\n\\r
2495 File will be created to store the ouput content.\n");\r
2496 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
2497 fprintf (stdout, " --version Show program's version number and exit.\n");\r
2498 fprintf (stdout, " -h, --help Show this help message and exit.\n");\r
2499 fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n");\r
2500 fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");\r
2501}\r
2502\r
2503int\r
2504main (\r
2505 IN int argc,\r
2506 IN char **argv\r
2507 )\r
2508/*++\r
2509\r
2510Routine Description:\r
2511\r
2512 This utility uses GenVtf.dll to build a Boot Strap File Image which will be\r
2513 part of firmware volume image.\r
2514\r
2515Arguments:\r
2516\r
2517 argc - The count of the parameters\r
2518 argv - The parameters\r
2519\r
2520\r
2521Returns:\r
2522\r
2523 0 - No error conditions detected.\r
2524 1 - One or more of the input parameters is invalid.\r
2525 2 - A resource required by the utility was unavailable.\r
2526 - Most commonly this will be memory allocation or file creation.\r
2527 3 - GenFvImage.dll could not be loaded.\r
2528 4 - Error executing the GenFvImage dll.\r
2529 5 - Now this tool does not support the IA32 platform\r
2530\r
2531--*/\r
2532{\r
2533 UINT8 Index;\r
2534 UINT64 StartAddress1;\r
2535 UINT64 StartAddress2;\r
2536 UINT64 FwVolSize1;\r
2537 UINT64 FwVolSize2;\r
2538 BOOLEAN FirstRoundO;\r
2539 BOOLEAN FirstRoundB;\r
2540 BOOLEAN FirstRoundS;\r
2541 EFI_STATUS Status;\r
2542 FILE *VtfFP;\r
2543 CHAR8 *VtfFileName;\r
2544\r
2545 SetUtilityName (UTILITY_NAME);\r
2546\r
2547 //\r
2548 // Initialize variables\r
2549 //\r
2550 StartAddress1 = 0;\r
2551 StartAddress2 = 0;\r
2552 FwVolSize1 = 0;\r
2553 FwVolSize2 = 0;\r
2554 FirstRoundB = TRUE;\r
2555 FirstRoundS = TRUE;\r
2556 FirstRoundO = TRUE;\r
2557 DebugMode = FALSE;\r
2558 OutFileName1 = NULL;\r
2559 OutFileName2 = NULL;\r
2560 VtfFP = NULL;\r
2561 DebugLevel = 0;\r
2562\r
2563 //\r
2564 // Verify the correct number of arguments\r
2565 //\r
2566 if (argc == 1) {\r
2567 Usage();\r
2568 return 0;\r
2569 }\r
2570\r
2571 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {\r
2572 Usage();\r
2573 return 0;\r
2574 }\r
2575\r
2576 if ((strcmp(argv[1], "--version") == 0)) {\r
2577 Version();\r
2578 return 0;\r
2579 }\r
2580\r
2581 //\r
2582 // Parse the command line arguments\r
2583 //\r
2584 for (Index = 1; Index < argc; Index += 2) {\r
2585 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {\r
2586 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {\r
2587 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");\r
2588 goto ERROR;\r
2589 }\r
2590 //\r
2591 // Get the output file name\r
2592 //\r
2593 VTF_OUTPUT = TRUE;\r
2594 if (FirstRoundO) {\r
2595 //\r
2596 // It's the first output file name\r
2597 //\r
2598 OutFileName1 = (CHAR8 *)argv[Index+1];\r
2599 FirstRoundO = FALSE;\r
2600 } else {\r
2601 //\r
2602 //It's the second output file name\r
2603 //\r
2604 OutFileName2 = (CHAR8 *)argv[Index+1];\r
2605 }\r
2606 continue;\r
2607 }\r
2608\r
2609 if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) {\r
2610 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {\r
2611 Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");\r
2612 goto ERROR;\r
2613 }\r
2614 //\r
2615 // Get the input VTF file name\r
2616 //\r
2617 VtfFileName = argv[Index+1];\r
181c9559
HW
2618 if (VtfFP != NULL) {\r
2619 //\r
2620 // VTF file name has been given previously, override with the new value\r
2621 //\r
2622 fclose (VtfFP);\r
2623 }\r
1be2ed90 2624 VtfFP = fopen (LongFilePath (VtfFileName), "rb");\r
30fdf114
LG
2625 if (VtfFP == NULL) {\r
2626 Error (NULL, 0, 0001, "Error opening file", VtfFileName);\r
2627 goto ERROR;\r
2628 }\r
2629 continue;\r
2630 }\r
2631 \r
2632 if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {\r
2633 if (FirstRoundB) {\r
2634 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);\r
2635 FirstRoundB = FALSE;\r
2636 } else {\r
2637 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);\r
2638 }\r
2639 if (Status != EFI_SUCCESS) {\r
2640 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);\r
2641 goto ERROR;\r
2642 } \r
2643 continue;\r
2644 }\r
2645\r
2646 if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {\r
2647 if (FirstRoundS) {\r
2648 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);\r
2649 FirstRoundS = FALSE;\r
2650 } else {\r
2651 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);\r
2652 SecondVTF = TRUE;\r
2653 }\r
2654\r
2655 if (Status != EFI_SUCCESS) {\r
2656 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);\r
2657 goto ERROR;\r
2658 }\r
2659 continue;\r
2660 }\r
2661\r
2662 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {\r
2663 VerboseMode = TRUE;\r
2664 Index--;\r
2665 continue;\r
2666 }\r
2667\r
2668 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {\r
2669 QuietMode = TRUE;\r
2670 Index--;\r
2671 continue;\r
2672 }\r
2673\r
2674 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {\r
2675 //\r
2676 // debug level specified\r
2677 //\r
2678 Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel);\r
2679 if (EFI_ERROR (Status)) {\r
2680 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);\r
2681 goto ERROR;\r
2682 }\r
2683 if (DebugLevel > 9) {\r
2684 Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);\r
2685 goto ERROR;\r
2686 }\r
2687 if((DebugLevel <= 9) &&(DebugLevel >= 5)) {\r
2688 DebugMode = TRUE;\r
2689 } else {\r
2690 DebugMode = FALSE;\r
2691 }\r
2692 continue;\r
2693 }\r
2694\r
2695 Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);\r
2696 goto ERROR;\r
2697 }\r
2698\r
2699 if (VtfFP == NULL) {\r
2700 Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");\r
2701 goto ERROR;\r
2702 }\r
2703\r
2704 if (FirstRoundB) {\r
2705 Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");\r
2706 goto ERROR;\r
2707 }\r
2708\r
2709 if (FirstRoundS) {\r
2710 Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");\r
2711 goto ERROR;\r
2712 }\r
2713 //\r
2714 // All Parameters has been parsed, now set the message print level\r
2715 //\r
2716 if (QuietMode) {\r
2717 SetPrintLevel(40);\r
2718 } else if (VerboseMode) {\r
2719 SetPrintLevel(15);\r
2720 } else if (DebugMode) {\r
2721 SetPrintLevel(DebugLevel);\r
2722 }\r
2723\r
2724 if (VerboseMode) {\r
2725 VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
2726 }\r
2727\r
2728 if (VTF_OUTPUT == FALSE) {\r
2729 if (SecondVTF == TRUE) {\r
2730 OutFileName1 = VTF_OUTPUT_FILE1;\r
2731 OutFileName2 = VTF_OUTPUT_FILE2;\r
2732 } else {\r
2733 OutFileName1 = VTF_OUTPUT_FILE1;\r
2734 }\r
2735 SymFileName = VTF_SYM_FILE;\r
2736 } else {\r
52757f69 2737 INTN OutFileNameLen;\r
5aec6991 2738 INTN NewIndex;\r
30fdf114 2739\r
52757f69
HW
2740 assert (OutFileName1);\r
2741 OutFileNameLen = strlen(OutFileName1);\r
2742\r
5aec6991
YZ
2743 for (NewIndex = OutFileNameLen; NewIndex > 0; --NewIndex) {\r
2744 if (OutFileName1[NewIndex] == '/' || OutFileName1[NewIndex] == '\\') {\r
30fdf114
LG
2745 break;\r
2746 }\r
2747 }\r
5aec6991 2748 if (NewIndex == 0) {\r
30fdf114
LG
2749 SymFileName = VTF_SYM_FILE;\r
2750 } else {\r
5aec6991 2751 INTN SymFileNameLen = NewIndex + 1 + strlen(VTF_SYM_FILE);\r
30fdf114 2752 SymFileName = malloc(SymFileNameLen + 1);\r
90114c10
HW
2753 if (SymFileName == NULL) {\r
2754 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2755 goto ERROR;\r
2756 }\r
5aec6991
YZ
2757 memcpy(SymFileName, OutFileName1, NewIndex + 1);\r
2758 memcpy(SymFileName + NewIndex + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));\r
30fdf114
LG
2759 SymFileName[SymFileNameLen] = '\0';\r
2760 }\r
2761 if (DebugMode) {\r
2762 DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);\r
2763 }\r
2764 }\r
2765\r
2766 //\r
2767 // Call the GenVtfImage\r
2768 //\r
2769 if (DebugMode) {\r
2770 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);\r
2771 }\r
2772 Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);\r
2773\r
2774 if (EFI_ERROR (Status)) {\r
2775 switch (Status) {\r
2776\r
2777 case EFI_INVALID_PARAMETER:\r
2778 Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");\r
2779 break;\r
2780\r
2781 case EFI_ABORTED:\r
fd171542 2782 Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image.");\r
30fdf114
LG
2783 break;\r
2784\r
2785 case EFI_OUT_OF_RESOURCES:\r
2786 Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");\r
2787 break;\r
2788\r
2789 case EFI_VOLUME_CORRUPTED:\r
fd171542 2790 Error (NULL, 0, 3000, "Invalid", "No base address was specified.");\r
30fdf114
LG
2791 break;\r
2792\r
2793 default:\r
fd171542 2794 Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status );\r
30fdf114
LG
2795 break;\r
2796 }\r
2797 }\r
2798ERROR:\r
2799 if (VtfFP != NULL) {\r
2800 fclose (VtfFP);\r
2801 }\r
2802\r
2803 if (DebugMode) {\r
2804 DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);\r
2805 }\r
2806\r
2807 if (VerboseMode) {\r
2808 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
2809 }\r
2810 return GetUtilityStatus();\r
2811}\r