]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenVtf/GenVtf.c
Sync basetools' source and binary files with r1707 of the basetools project.
[mirror_edk2.git] / BaseTools / Source / C / GenVtf / GenVtf.c
CommitLineData
30fdf114
LG
1/**\r
2\r
3Copyright (c) 1999 - 2008, Intel Corporation. All rights reserved\r
4This software and associated documentation (if any) is furnished\r
5under a license and may only be used or copied in accordance\r
6with the terms of the license. Except as permitted by such\r
7license, no part of this software or documentation may be\r
8reproduced, stored in a retrieval system, or transmitted in any\r
9form or by any means without the express written consent of\r
10Intel Corporation.\r
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
1270 Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName);\r
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
1409 Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName);\r
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
1691 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, TotalVtfSize);\r
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
2156 IN CHAR8 *SourceFileName\r
2157 )\r
2158/*++\r
2159\r
2160Routine Description:\r
2161\r
2162 This function adds the SYM tokens in the source file to the destination file.\r
2163 The SYM tokens are updated to reflect the base address.\r
2164\r
2165Arguments:\r
2166\r
2167 BaseAddress - The base address for the new SYM tokens.\r
2168 DestFileName - The destination file.\r
2169 SourceFileName - The source file.\r
2170\r
2171Returns:\r
2172\r
2173 EFI_SUCCESS - The function completed successfully.\r
2174 EFI_INVALID_PARAMETER - One of the input parameters was invalid.\r
2175 EFI_ABORTED - An error occurred.\r
2176\r
2177--*/\r
2178{\r
2179 FILE *SourceFile;\r
2180 FILE *DestFile;\r
2181 CHAR8 Buffer[_MAX_PATH];\r
2182 CHAR8 Type[_MAX_PATH];\r
2183 CHAR8 Address[_MAX_PATH];\r
2184 CHAR8 Section[_MAX_PATH];\r
2185 CHAR8 Token[_MAX_PATH];\r
2186 CHAR8 BaseToken[_MAX_PATH];\r
2187 UINT64 TokenAddress;\r
2188 long StartLocation;\r
2189\r
2190 //\r
2191 // Verify input parameters.\r
2192 //\r
2193 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {\r
2194 return EFI_INVALID_PARAMETER;\r
2195 }\r
2196\r
2197 //\r
2198 // Open the source file\r
2199 //\r
2200 SourceFile = fopen (SourceFileName, "r");\r
2201 if (SourceFile == NULL) {\r
2202\r
2203 //\r
2204 // SYM files are not required.\r
2205 //\r
2206 return EFI_SUCCESS;\r
2207 }\r
2208\r
2209 //\r
2210 // Use the file name minus extension as the base for tokens\r
2211 //\r
2212 strcpy (BaseToken, SourceFileName);\r
2213 strtok (BaseToken, ". \t\n");\r
2214 strcat (BaseToken, "__");\r
2215\r
2216 //\r
2217 // Open the destination file\r
2218 //\r
2219 DestFile = fopen (DestFileName, "a+");\r
2220 if (DestFile == NULL) {\r
2221 fclose (SourceFile);\r
2222 Error (NULL, 0, 0001, "Error opening file", DestFileName);\r
2223 return EFI_ABORTED;\r
2224 }\r
2225\r
2226 //\r
2227 // If this is the beginning of the output file, write the symbol format info.\r
2228 //\r
2229 if (fseek (DestFile, 0, SEEK_END) != 0) {\r
2230 fclose (SourceFile);\r
2231 fclose (DestFile);\r
2232 Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");\r
2233 return EFI_ABORTED;\r
2234 }\r
2235\r
2236 StartLocation = ftell (DestFile);\r
2237\r
2238 if (StartLocation == 0) {\r
2239 fprintf (DestFile, "TEXTSYM format | V1.0\n");\r
2240 } else if (StartLocation == -1) {\r
2241 fclose (SourceFile);\r
2242 fclose (DestFile);\r
2243 Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");\r
2244 return EFI_ABORTED;\r
2245 }\r
2246\r
2247 //\r
2248 // Read the first line\r
2249 //\r
2250 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {\r
2251 Buffer[0] = 0;\r
2252 }\r
2253\r
2254 //\r
2255 // Make sure it matches the expected sym format\r
2256 //\r
2257 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
2258 fclose (SourceFile);\r
2259 fclose (DestFile);\r
2260 Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");\r
2261 return EFI_ABORTED;\r
2262 }\r
2263\r
2264 //\r
2265 // Read in the file\r
2266 //\r
2267 while (feof (SourceFile) == 0) {\r
2268\r
2269 //\r
2270 // Read a line\r
2271 //\r
2272 if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {\r
2273\r
2274 //\r
2275 // Get the token address\r
2276 //\r
2277 AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
2278\r
2279 //\r
2280 // Add the base address, the size of the FFS file header and the size of the peim header.\r
2281 //\r
2282 TokenAddress += BaseAddress &~IPF_CACHE_BIT;\r
2283\r
fd171542 2284 fprintf (DestFile, "%s | %016llX | %s | %s%s\n", Type, (unsigned long long) TokenAddress, Section, BaseToken, Token);\r
30fdf114
LG
2285 }\r
2286 }\r
2287\r
2288 fclose (SourceFile);\r
2289 fclose (DestFile);\r
2290 return EFI_SUCCESS;\r
2291}\r
2292\r
2293EFI_STATUS\r
2294CalculateFitTableChecksum (\r
2295 VOID\r
2296 )\r
2297/*++\r
2298\r
2299Routine Description:\r
2300\r
2301 This function will perform byte checksum on the FIT table, if the the checksum required\r
2302 field is set to CheckSum required. If the checksum is not required then checksum byte\r
2303 will have value as 0;.\r
2304\r
2305Arguments:\r
2306\r
2307 NONE\r
2308\r
2309Returns:\r
2310\r
2311 Status - Value returned by call to CalculateChecksum8 ()\r
2312 EFI_SUCCESS - The function completed successfully\r
2313\r
2314--*/\r
2315{\r
2316 FIT_TABLE *TmpFitPtr;\r
2317 UINT64 FitTableAdd;\r
2318 UINT64 FitTableAddOffset;\r
2319 UINTN RelativeAddress;\r
2320 UINTN Size;\r
2321\r
2322 //\r
2323 // Read the Fit Table address from Itanium-based address map.\r
2324 //\r
2325 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
2326\r
2327 //\r
2328 // Translate this Itanium-based address in terms of local buffer address which\r
2329 // contains the image for Boot Strapped File\r
2330 //\r
2331 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);\r
2332 FitTableAdd = *(UINTN *) RelativeAddress;\r
2333\r
2334 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
2335\r
2336 TmpFitPtr = (FIT_TABLE *) RelativeAddress;\r
2337\r
2338 Size = TmpFitPtr->CompSize * 16;\r
2339\r
2340 if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
2341 TmpFitPtr->CheckSum = 0;\r
2342 TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);\r
2343 } else {\r
2344 TmpFitPtr->CheckSum = 0;\r
2345 }\r
2346\r
2347 return EFI_SUCCESS;\r
2348}\r
2349\r
2350VOID\r
2351Version (\r
2352 VOID\r
2353 )\r
2354/*++\r
2355\r
2356Routine Description:\r
2357\r
2358 Displays the standard utility information to SDTOUT\r
2359\r
2360Arguments:\r
2361\r
2362 None\r
2363\r
2364Returns:\r
2365\r
2366 None\r
2367\r
2368--*/\r
2369{\r
2370 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
2371}\r
2372\r
2373VOID\r
2374Usage (\r
2375 VOID\r
2376 )\r
2377/*++\r
2378\r
2379Routine Description:\r
2380\r
2381 Displays the utility usage syntax to STDOUT\r
2382\r
2383Arguments:\r
2384\r
2385 None\r
2386\r
2387Returns:\r
2388\r
2389 None\r
2390\r
2391--*/\r
2392{\r
2393 //\r
2394 // Summary usage\r
2395 //\r
2396 fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);\r
2397\r
2398 //\r
2399 // Copyright declaration\r
2400 //\r
2401 fprintf (stdout, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n");\r
2402 //\r
2403 // Details Option\r
2404 //\r
2405 fprintf (stdout, "Options:\n");\r
2406 fprintf (stdout, " -f Input_file, --filename Input_file\n\\r
2407 Input_file is name of the BS Image INF file\n");\r
2408 fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\\r
2409 BaseAddress is the starting address of Firmware Volume\n\\r
2410 where Boot Strapped Image will reside.\n");\r
2411 fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\\r
2412 FwVolumeSize is the size of Firmware Volume.\n");\r
2413 fprintf (stdout, " -o FileName, --output FileName\n\\r
2414 File will be created to store the ouput content.\n");\r
2415 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
2416 fprintf (stdout, " --version Show program's version number and exit.\n");\r
2417 fprintf (stdout, " -h, --help Show this help message and exit.\n");\r
2418 fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n");\r
2419 fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");\r
2420}\r
2421\r
2422int\r
2423main (\r
2424 IN int argc,\r
2425 IN char **argv\r
2426 )\r
2427/*++\r
2428\r
2429Routine Description:\r
2430\r
2431 This utility uses GenVtf.dll to build a Boot Strap File Image which will be\r
2432 part of firmware volume image.\r
2433\r
2434Arguments:\r
2435\r
2436 argc - The count of the parameters\r
2437 argv - The parameters\r
2438\r
2439\r
2440Returns:\r
2441\r
2442 0 - No error conditions detected.\r
2443 1 - One or more of the input parameters is invalid.\r
2444 2 - A resource required by the utility was unavailable.\r
2445 - Most commonly this will be memory allocation or file creation.\r
2446 3 - GenFvImage.dll could not be loaded.\r
2447 4 - Error executing the GenFvImage dll.\r
2448 5 - Now this tool does not support the IA32 platform\r
2449\r
2450--*/\r
2451{\r
2452 UINT8 Index;\r
2453 UINT64 StartAddress1;\r
2454 UINT64 StartAddress2;\r
2455 UINT64 FwVolSize1;\r
2456 UINT64 FwVolSize2;\r
2457 BOOLEAN FirstRoundO;\r
2458 BOOLEAN FirstRoundB;\r
2459 BOOLEAN FirstRoundS;\r
2460 EFI_STATUS Status;\r
2461 FILE *VtfFP;\r
2462 CHAR8 *VtfFileName;\r
2463\r
2464 SetUtilityName (UTILITY_NAME);\r
2465\r
2466 //\r
2467 // Initialize variables\r
2468 //\r
2469 StartAddress1 = 0;\r
2470 StartAddress2 = 0;\r
2471 FwVolSize1 = 0;\r
2472 FwVolSize2 = 0;\r
2473 FirstRoundB = TRUE;\r
2474 FirstRoundS = TRUE;\r
2475 FirstRoundO = TRUE;\r
2476 DebugMode = FALSE;\r
2477 OutFileName1 = NULL;\r
2478 OutFileName2 = NULL;\r
2479 VtfFP = NULL;\r
2480 DebugLevel = 0;\r
2481\r
2482 //\r
2483 // Verify the correct number of arguments\r
2484 //\r
2485 if (argc == 1) {\r
2486 Usage();\r
2487 return 0;\r
2488 }\r
2489\r
2490 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {\r
2491 Usage();\r
2492 return 0;\r
2493 }\r
2494\r
2495 if ((strcmp(argv[1], "--version") == 0)) {\r
2496 Version();\r
2497 return 0;\r
2498 }\r
2499\r
2500 //\r
2501 // Parse the command line arguments\r
2502 //\r
2503 for (Index = 1; Index < argc; Index += 2) {\r
2504 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {\r
2505 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {\r
2506 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");\r
2507 goto ERROR;\r
2508 }\r
2509 //\r
2510 // Get the output file name\r
2511 //\r
2512 VTF_OUTPUT = TRUE;\r
2513 if (FirstRoundO) {\r
2514 //\r
2515 // It's the first output file name\r
2516 //\r
2517 OutFileName1 = (CHAR8 *)argv[Index+1];\r
2518 FirstRoundO = FALSE;\r
2519 } else {\r
2520 //\r
2521 //It's the second output file name\r
2522 //\r
2523 OutFileName2 = (CHAR8 *)argv[Index+1];\r
2524 }\r
2525 continue;\r
2526 }\r
2527\r
2528 if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) {\r
2529 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {\r
2530 Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");\r
2531 goto ERROR;\r
2532 }\r
2533 //\r
2534 // Get the input VTF file name\r
2535 //\r
2536 VtfFileName = argv[Index+1];\r
2537 VtfFP = fopen(VtfFileName, "rb");\r
2538 if (VtfFP == NULL) {\r
2539 Error (NULL, 0, 0001, "Error opening file", VtfFileName);\r
2540 goto ERROR;\r
2541 }\r
2542 continue;\r
2543 }\r
2544 \r
2545 if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {\r
2546 if (FirstRoundB) {\r
2547 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);\r
2548 FirstRoundB = FALSE;\r
2549 } else {\r
2550 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);\r
2551 }\r
2552 if (Status != EFI_SUCCESS) {\r
2553 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);\r
2554 goto ERROR;\r
2555 } \r
2556 continue;\r
2557 }\r
2558\r
2559 if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {\r
2560 if (FirstRoundS) {\r
2561 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);\r
2562 FirstRoundS = FALSE;\r
2563 } else {\r
2564 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);\r
2565 SecondVTF = TRUE;\r
2566 }\r
2567\r
2568 if (Status != EFI_SUCCESS) {\r
2569 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);\r
2570 goto ERROR;\r
2571 }\r
2572 continue;\r
2573 }\r
2574\r
2575 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {\r
2576 VerboseMode = TRUE;\r
2577 Index--;\r
2578 continue;\r
2579 }\r
2580\r
2581 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {\r
2582 QuietMode = TRUE;\r
2583 Index--;\r
2584 continue;\r
2585 }\r
2586\r
2587 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {\r
2588 //\r
2589 // debug level specified\r
2590 //\r
2591 Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel);\r
2592 if (EFI_ERROR (Status)) {\r
2593 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);\r
2594 goto ERROR;\r
2595 }\r
2596 if (DebugLevel > 9) {\r
2597 Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);\r
2598 goto ERROR;\r
2599 }\r
2600 if((DebugLevel <= 9) &&(DebugLevel >= 5)) {\r
2601 DebugMode = TRUE;\r
2602 } else {\r
2603 DebugMode = FALSE;\r
2604 }\r
2605 continue;\r
2606 }\r
2607\r
2608 Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);\r
2609 goto ERROR;\r
2610 }\r
2611\r
2612 if (VtfFP == NULL) {\r
2613 Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");\r
2614 goto ERROR;\r
2615 }\r
2616\r
2617 if (FirstRoundB) {\r
2618 Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");\r
2619 goto ERROR;\r
2620 }\r
2621\r
2622 if (FirstRoundS) {\r
2623 Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");\r
2624 goto ERROR;\r
2625 }\r
2626 //\r
2627 // All Parameters has been parsed, now set the message print level\r
2628 //\r
2629 if (QuietMode) {\r
2630 SetPrintLevel(40);\r
2631 } else if (VerboseMode) {\r
2632 SetPrintLevel(15);\r
2633 } else if (DebugMode) {\r
2634 SetPrintLevel(DebugLevel);\r
2635 }\r
2636\r
2637 if (VerboseMode) {\r
2638 VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
2639 }\r
2640\r
2641 if (VTF_OUTPUT == FALSE) {\r
2642 if (SecondVTF == TRUE) {\r
2643 OutFileName1 = VTF_OUTPUT_FILE1;\r
2644 OutFileName2 = VTF_OUTPUT_FILE2;\r
2645 } else {\r
2646 OutFileName1 = VTF_OUTPUT_FILE1;\r
2647 }\r
2648 SymFileName = VTF_SYM_FILE;\r
2649 } else {\r
2650 INTN OutFileNameLen = strlen(OutFileName1);\r
2651 INTN Index;\r
2652\r
2653 for (Index = OutFileNameLen; Index > 0; --Index) {\r
2654 if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') {\r
2655 break;\r
2656 }\r
2657 }\r
2658 if (Index == 0) {\r
2659 SymFileName = VTF_SYM_FILE;\r
2660 } else {\r
2661 INTN SymFileNameLen = Index + 1 + strlen(VTF_SYM_FILE);\r
2662 SymFileName = malloc(SymFileNameLen + 1);\r
2663 memcpy(SymFileName, OutFileName1, Index + 1);\r
2664 memcpy(SymFileName + Index + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));\r
2665 SymFileName[SymFileNameLen] = '\0';\r
2666 }\r
2667 if (DebugMode) {\r
2668 DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);\r
2669 }\r
2670 }\r
2671\r
2672 //\r
2673 // Call the GenVtfImage\r
2674 //\r
2675 if (DebugMode) {\r
2676 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);\r
2677 }\r
2678 Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);\r
2679\r
2680 if (EFI_ERROR (Status)) {\r
2681 switch (Status) {\r
2682\r
2683 case EFI_INVALID_PARAMETER:\r
2684 Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");\r
2685 break;\r
2686\r
2687 case EFI_ABORTED:\r
fd171542 2688 Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image.");\r
30fdf114
LG
2689 break;\r
2690\r
2691 case EFI_OUT_OF_RESOURCES:\r
2692 Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");\r
2693 break;\r
2694\r
2695 case EFI_VOLUME_CORRUPTED:\r
fd171542 2696 Error (NULL, 0, 3000, "Invalid", "No base address was specified.");\r
30fdf114
LG
2697 break;\r
2698\r
2699 default:\r
fd171542 2700 Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status );\r
30fdf114
LG
2701 break;\r
2702 }\r
2703 }\r
2704ERROR:\r
2705 if (VtfFP != NULL) {\r
2706 fclose (VtfFP);\r
2707 }\r
2708\r
2709 if (DebugMode) {\r
2710 DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);\r
2711 }\r
2712\r
2713 if (VerboseMode) {\r
2714 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
2715 }\r
2716 return GetUtilityStatus();\r
2717}\r