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