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