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