]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenVtf/GenVtf.c
BaseTools/GenVtf: Avoid possible NULL pointer dereference
[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
fd171542 115 unsigned Major;\r
116 unsigned 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
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
90114c10
HW
1244 if (CompFitPtr == NULL) {\r
1245 free (Buffer);\r
1246 return EFI_ABORTED;\r
1247 }\r
30fdf114
LG
1248\r
1249 CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;\r
1250 if ((FileSize % 16) != 0) {\r
1251 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");\r
1252 return EFI_INVALID_PARAMETER;\r
1253 }\r
1254 //assert ((FileSize % 16) == 0);\r
1255 CompFitPtr->CompSize = (UINT32) (FileSize / 16);\r
1256 CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1257 CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1258 if (VtfInfo->CheckSumRequired) {\r
1259 CompFitPtr->CheckSum = 0;\r
1260 CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);\r
1261 }\r
1262\r
1263 //\r
1264 // Free the buffer\r
1265 //\r
1266 if (Buffer) {\r
1267 free (Buffer);\r
1268 }\r
1269\r
1270 //\r
1271 // Update the SYM file for this component based on it's start address.\r
1272 //\r
b303ea72 1273 Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);\r
30fdf114
LG
1274 if (EFI_ERROR (Status)) {\r
1275\r
1276 //\r
1277 // At this time, SYM files are not required, so continue on error.\r
1278 //\r
1279 }\r
1280\r
1281 // !!!!!!!!!!!!!!!!!!!!!\r
1282 // BUGBUG:\r
1283 // This part of the code is a temporary line since PEICORE is going to be inside\r
1284 // VTF till we work out how to determine the SALE_ENTRY through it. We will need\r
1285 // to clarify so many related questions\r
1286 // !!!!!!!!!!!!!!!!!!!!!!!\r
1287\r
1288 if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) {\r
1289 Status = UpdateEntryPoint (VtfInfo, &CompStartAddress);\r
1290 }\r
1291\r
1292 return Status;\r
1293}\r
1294\r
1295EFI_STATUS\r
1296CreateAndUpdatePAL_A (\r
1297 IN PARSED_VTF_INFO *VtfInfo\r
1298 )\r
1299/*++\r
1300\r
1301Routine Description:\r
1302\r
1303 This function reads the binary file for each components and update them\r
1304 in VTF Buffer as well as FIT table\r
1305\r
1306Arguments:\r
1307\r
1308 VtfInfo - Pointer to Parsed Info\r
1309\r
1310Returns:\r
1311\r
1312 EFI_ABORTED - Due to one of the following reasons:\r
1313 (a)Error Opening File\r
1314 (b)The PAL_A Size is more than specified size status\r
1315 One of the values mentioned below returned from\r
1316 call to UpdateSymFile\r
1317 EFI_SUCCESS - The function completed successfully.\r
1318 EFI_INVALID_PARAMETER - One of the input parameters was invalid.\r
1319 EFI_ABORTED - An error occurred.UpdateSymFile\r
1320 EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
1321\r
1322--*/\r
1323{\r
1324 EFI_STATUS Status;\r
1325 UINT64 PalStartAddress;\r
1326 UINT64 AbsAddress;\r
1327 UINTN RelativeAddress;\r
1328 UINT64 FileSize;\r
30fdf114
LG
1329 UINT8 *Buffer;\r
1330 FILE *Fp;\r
1331 FIT_TABLE *PalFitPtr;\r
1332\r
1be2ed90 1333 Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");\r
30fdf114
LG
1334\r
1335 if (Fp == NULL) {\r
1336 Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);\r
1337 return EFI_ABORTED;\r
1338 }\r
1339\r
1340 FileSize = _filelength (fileno (Fp));\r
1341 if (FileSize < 64) {\r
1342 Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");\r
1343 return EFI_INVALID_PARAMETER;\r
1344 }\r
1345 FileSize -= SIZE_OF_PAL_HEADER;\r
1346\r
1347\r
1348 if (VtfInfo->PreferredSize) {\r
1349 if (FileSize > VtfInfo->CompSize) {\r
1350 Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");\r
1351 return EFI_ABORTED;\r
1352 }\r
1353\r
1354 FileSize = VtfInfo->CompSize;\r
1355 }\r
1356\r
1357 Buffer = malloc ((UINTN) FileSize);\r
1358 if (Buffer == NULL) {\r
1359 return EFI_OUT_OF_RESOURCES;\r
1360 }\r
1361 memset (Buffer, 0, (UINTN) FileSize);\r
1362\r
1363 //\r
1364 // Read, Get version Info and discard the PAL header.\r
1365 //\r
0d2711a6 1366 fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);\r
30fdf114
LG
1367\r
1368 //\r
1369 // Extract the version info from header of PAL_A. Once done, discrad this buffer\r
1370 //\r
1371 if (!VtfInfo->VersionPresent) {\r
1372 GetComponentVersionInfo (VtfInfo, Buffer);\r
1373 }\r
1374\r
1375 //\r
1376 // Read PAL_A file in a buffer\r
1377 //\r
0d2711a6 1378 fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
30fdf114
LG
1379 fclose (Fp);\r
1380\r
1381 PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);\r
1382 Vtf1LastStartAddress = PalStartAddress;\r
1383 Vtf1TotalSize += (UINT32) FileSize;\r
1384 Status = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);\r
1385\r
1386 AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;\r
1387 GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);\r
1388 PalFitPtr = (FIT_TABLE *) RelativeAddress;\r
1389 PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;\r
1390 //assert ((FileSize % 16) == 0);\r
1391 if ((FileSize % 16) != 0) {\r
1392 Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");\r
1393 return EFI_INVALID_PARAMETER;\r
1394 }\r
1395\r
1396 PalFitPtr->CompSize = (UINT32) (FileSize / 16);\r
1397 PalFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1398 PalFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1399 if (VtfInfo->CheckSumRequired) {\r
1400 PalFitPtr->CheckSum = 0;\r
1401 PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);\r
1402 }\r
1403\r
1404 if (Buffer) {\r
1405 free (Buffer);\r
1406 }\r
1407\r
1408 //\r
1409 // Update the SYM file for this component based on it's start address.\r
1410 //\r
b303ea72 1411 Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);\r
30fdf114
LG
1412 if (EFI_ERROR (Status)) {\r
1413\r
1414 //\r
1415 // At this time, SYM files are not required, so continue on error.\r
1416 //\r
1417 }\r
1418\r
1419 return Status;\r
1420}\r
1421\r
1422EFI_STATUS\r
1423CreateFitTableAndInitialize (\r
1424 IN PARSED_VTF_INFO *VtfInfo\r
1425 )\r
1426/*++\r
1427\r
1428Routine Description:\r
1429\r
1430 This function creates and intializes FIT table which would be used to\r
1431 add component info inside this\r
1432\r
1433Arguments:\r
1434\r
1435 VtfInfo - Pointer to Parsed Info\r
1436\r
1437Returns:\r
1438\r
1439 EFI_ABORTED - Aborted due to no size information\r
1440 EFI_SUCCESS - The function completed successfully\r
1441\r
1442--*/\r
1443{\r
1444 UINT64 PalFitTableAdd;\r
1445 UINT64 FitTableAdd;\r
1446 UINT64 FitTableAddressOffset;\r
1447 FIT_TABLE *PalFitPtr;\r
1448 FIT_TABLE *FitStartPtr;\r
1449 UINTN NumFitComp;\r
1450 UINTN RelativeAddress;\r
1451 UINTN Index;\r
1452\r
1453 if (!VtfInfo->PreferredSize) {\r
1454 Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");\r
1455 return EFI_ABORTED;\r
1456 }\r
1457\r
1458 if ((VtfInfo->CompSize % 16) != 0) {\r
1459 Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");\r
1460 }\r
1461\r
1462 PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;\r
1463 GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);\r
1464 PalFitPtr = (FIT_TABLE *) RelativeAddress;\r
1465 PalFitTableAdd = (PalFitPtr->CompAddress - VtfInfo->CompSize);\r
1466\r
1467 FitTableAdd = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize;\r
1468 FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
1469 GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);\r
1470 *(UINT64 *) RelativeAddress = FitTableAdd;\r
1471\r
1472 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
1473\r
1474 //\r
1475 // Update Fit Table with FIT Signature and FIT info in first 16 bytes.\r
1476 //\r
1477 FitStartPtr = (FIT_TABLE *) RelativeAddress;\r
1478\r
1479 strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ "\r
1480 assert (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0);\r
1481 FitStartPtr->CompSize = (VtfInfo->CompSize & 0x00FFFFFF) / 16;\r
1482 FitStartPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);\r
1483\r
1484 //\r
1485 // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also\r
1486 // determine what to do for things like the FV component that aren't easily checksummed.\r
1487 // The checksum will be done once we are done with all the componet update in the FIT\r
1488 // table\r
1489 //\r
1490 FitStartPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);\r
1491\r
1492 NumFitComp = FitStartPtr->CompSize;\r
1493\r
1494 FitStartPtr++;\r
1495\r
1496 //\r
1497 // Intialize remaining FIT table space to UNUSED fit component type\r
1498 // so that when we need to create a FIT entry for a component, we can\r
1499 // locate a free one and use it.\r
1500 //\r
1501 for (Index = 0; Index < (NumFitComp - 1); Index++) {\r
1502 FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED\r
1503 FitStartPtr++;\r
1504 }\r
1505\r
1506 Vtf1TotalSize += VtfInfo->CompSize;\r
1507 Vtf1LastStartAddress -= VtfInfo->CompSize;\r
1508\r
1509 return EFI_SUCCESS;\r
1510}\r
1511\r
1512EFI_STATUS\r
1513WriteVtfBinary (\r
1514 IN CHAR8 *FileName,\r
1515 IN UINT32 VtfSize,\r
1516 IN LOC_TYPE LocType\r
1517 )\r
1518/*++\r
1519\r
1520Routine Description:\r
1521\r
1522 Write Firmware Volume from memory to a file.\r
1523\r
1524Arguments:\r
1525\r
1526 FileName - Output File Name which needed to be created/\r
1527 VtfSize - FileSize\r
1528 LocType - The type of the VTF\r
1529\r
1530Returns:\r
1531\r
1532 EFI_ABORTED - Returned due to one of the following resons:\r
1533 (a) Error Opening File\r
1534 (b) Failing to copy buffers\r
1535 EFI_SUCCESS - The fuction completes successfully\r
1536\r
1537--*/\r
1538{\r
1539 FILE *Fp;\r
1540 UINTN NumByte;\r
1541 VOID *VtfBuffer;\r
1542 UINTN RelativeAddress;\r
1543\r
1544 if (LocType == FIRST_VTF) {\r
1545 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);\r
1546 VtfBuffer = (VOID *) RelativeAddress;\r
1547 } else {\r
1548 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);\r
1549 VtfBuffer = (VOID *) RelativeAddress;\r
1550 }\r
1551\r
1be2ed90 1552 Fp = fopen (LongFilePath (FileName), "wb");\r
30fdf114
LG
1553 if (Fp == NULL) {\r
1554 Error (NULL, 0, 0001, "Error opening file", FileName);\r
1555 return EFI_ABORTED;\r
1556 }\r
1557\r
1558 NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp);\r
1559\r
1560 if (Fp) {\r
1561 fclose (Fp);\r
1562 }\r
1563\r
1564 if (NumByte != (sizeof (UINT8) * VtfSize)) {\r
1565 Error (NULL, 0, 0002, "Error writing file", FileName);\r
1566 return EFI_ABORTED;\r
1567 }\r
1568\r
1569 return EFI_SUCCESS;\r
1570}\r
1571\r
1572EFI_STATUS\r
1573UpdateVtfBuffer (\r
1574 IN UINT64 StartAddress,\r
1575 IN UINT8 *Buffer,\r
1576 IN UINT64 DataSize,\r
1577 IN LOC_TYPE LocType\r
1578 )\r
1579/*++\r
1580\r
1581Routine Description:\r
1582\r
1583 Update the Firmware Volume Buffer with requested buffer data\r
1584\r
1585Arguments:\r
1586\r
1587 StartAddress - StartAddress in buffer. This number will automatically\r
1588 point to right address in buffer where data needed\r
1589 to be updated.\r
1590 Buffer - Buffer pointer from data will be copied to memory mapped buffer.\r
1591 DataSize - Size of the data needed to be copied.\r
1592 LocType - The type of the VTF: First or Second\r
1593\r
1594Returns:\r
1595\r
1596 EFI_ABORTED - The input parameter is error\r
1597 EFI_SUCCESS - The function completed successfully\r
1598\r
1599--*/\r
1600{\r
1601 UINT8 *LocalBufferPtrToWrite;\r
1602\r
1603 if (LocType == FIRST_VTF) {\r
1604 if ((StartAddress | IPF_CACHE_BIT) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) {\r
1605 Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");\r
1606 return EFI_ABORTED;\r
1607 }\r
1608\r
1609 LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer;\r
1610\r
1611 LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);\r
1612\r
1613 } else {\r
1614\r
1615 if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) {\r
1616 Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress");\r
1617 return EFI_ABORTED;\r
1618 }\r
1619 LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer;\r
1620 LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);\r
1621 }\r
1622\r
1623 memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);\r
1624\r
1625 return EFI_SUCCESS;\r
1626}\r
1627\r
1628EFI_STATUS\r
1629UpdateFfsHeader (\r
1630 IN UINT32 TotalVtfSize,\r
1631 IN LOC_TYPE LocType\r
1632 )\r
1633/*++\r
1634\r
1635Routine Description:\r
1636\r
1637 Update the Firmware Volume Buffer with requested buffer data\r
1638\r
1639Arguments:\r
1640\r
1641 TotalVtfSize - Size of the VTF\r
1642 Fileoffset - The start of the file relative to the start of the FV.\r
1643 LocType - The type of the VTF\r
1644\r
1645Returns:\r
1646\r
1647 EFI_SUCCESS - The function completed successfully\r
1648 EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL\r
1649\r
1650--*/\r
1651{\r
1652 EFI_FFS_FILE_HEADER *FileHeader;\r
1653 UINTN RelativeAddress;\r
1654 EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
1655\r
1656 //\r
1657 // Find the VTF file header location\r
1658 //\r
1659 if (LocType == FIRST_VTF) {\r
1660 GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);\r
1661 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;\r
1662 } else {\r
1663 GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);\r
1664 FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;\r
1665 }\r
1666\r
1667 if (FileHeader == NULL) {\r
1668 return EFI_INVALID_PARAMETER;\r
1669 }\r
1670\r
1671 //\r
1672 // write header\r
1673 //\r
1674 memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
1675 memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));\r
1676 FileHeader->Type = EFI_FV_FILETYPE_RAW;\r
1677 FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;\r
1678\r
1679 //\r
1680 // Now FileSize includes the EFI_FFS_FILE_HEADER\r
1681 //\r
1682 FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF);\r
1683 FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8);\r
1684 FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16);\r
1685\r
1686 //\r
1687 // Fill in checksums and state, all three must be zero for the checksums.\r
1688 //\r
1689 FileHeader->IntegrityCheck.Checksum.Header = 0;\r
1690 FileHeader->IntegrityCheck.Checksum.File = 0;\r
1691 FileHeader->State = 0;\r
1692 FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
b303ea72 1693 FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) (FileHeader + 1), TotalVtfSize - sizeof (EFI_FFS_FILE_HEADER));\r
30fdf114
LG
1694 FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
1695\r
1696 return EFI_SUCCESS;\r
1697}\r
1698\r
1699EFI_STATUS\r
1700ValidateAddressAndSize (\r
1701 IN UINT64 BaseAddress,\r
1702 IN UINT64 FwVolSize\r
1703 )\r
1704/*++\r
1705\r
1706Routine Description:\r
1707\r
1708 Update the Firmware Volume Buffer with requested buffer data\r
1709\r
1710Arguments:\r
1711\r
1712 BaseAddress - Base address for the Fw Volume.\r
1713\r
1714 FwVolSize - Total Size of the FwVolume to which VTF will be attached..\r
1715\r
1716Returns:\r
1717\r
1718 EFI_SUCCESS - The function completed successfully\r
1719 EFI_UNSUPPORTED - The input parameter is error\r
1720\r
1721--*/\r
1722{\r
07355bd5 1723 if ((FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {\r
30fdf114
LG
1724 return EFI_SUCCESS;\r
1725 }\r
1726\r
1727 return EFI_UNSUPPORTED;\r
1728}\r
1729\r
1730EFI_STATUS\r
1731UpdateIA32ResetVector (\r
1732 IN CHAR8 *FileName,\r
1733 IN UINT64 FirstFwVSize\r
1734 )\r
1735/*++\r
1736\r
1737Routine Description:\r
1738\r
1739 Update the 16 byte IA32 Reset vector to maintain the compatibility\r
1740\r
1741Arguments:\r
1742\r
1743 FileName - Binary file name which contains the IA32 Reset vector info..\r
1744 FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..\r
1745\r
1746Returns:\r
1747\r
1748 EFI_SUCCESS - The function completed successfully\r
1749 EFI_ABORTED - Invalid File Size\r
1750 EFI_INVALID_PARAMETER - Bad File Name\r
1751 EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
1752\r
1753--*/\r
1754{\r
1755 UINT8 *Buffer;\r
1756 UINT8 *LocalVtfBuffer;\r
1757 UINTN FileSize;\r
30fdf114
LG
1758 FILE *Fp;\r
1759\r
1760 if (!strcmp (FileName, "")) {\r
1761 return EFI_INVALID_PARAMETER;\r
1762 }\r
1763\r
1be2ed90 1764 Fp = fopen (LongFilePath (FileName), "rb");\r
30fdf114
LG
1765\r
1766 if (Fp == NULL) {\r
1767 Error (NULL, 0, 0001, "Error opening file", FileName);\r
1768 return EFI_ABORTED;\r
1769 }\r
1770\r
1771 FileSize = _filelength (fileno (Fp));\r
1772\r
1773 if (FileSize > 16) {\r
1774 return EFI_ABORTED;\r
1775 }\r
1776\r
1777 Buffer = malloc (FileSize);\r
1778 if (Buffer == NULL) {\r
1779 return EFI_OUT_OF_RESOURCES;\r
1780 }\r
1781\r
0d2711a6 1782 fread (Buffer, sizeof (UINT8), FileSize, Fp);\r
30fdf114
LG
1783\r
1784 LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT;\r
1785 memcpy (LocalVtfBuffer, Buffer, FileSize);\r
1786\r
1787 if (Buffer) {\r
1788 free (Buffer);\r
1789 }\r
1790\r
1791 if (Fp != NULL) {\r
1792 fclose (Fp);\r
1793 }\r
1794 return EFI_SUCCESS;\r
1795}\r
1796\r
1797VOID\r
1798CleanUpMemory (\r
1799 VOID\r
1800 )\r
1801/*++\r
1802\r
1803Routine Description:\r
1804\r
1805 This function cleans up any allocated buffer\r
1806\r
1807Arguments:\r
1808\r
1809 NONE\r
1810\r
1811Returns:\r
1812\r
1813 NONE\r
1814\r
1815--*/\r
1816{\r
1817 PARSED_VTF_INFO *TempFileListPtr;\r
1818\r
1819 if (Vtf1Buffer) {\r
1820 free (Vtf1Buffer);\r
1821 }\r
1822\r
1823 if (Vtf2Buffer) {\r
1824 free (Vtf2Buffer);\r
1825 }\r
1826\r
1827 //\r
1828 // Cleanup the buffer which was allocated to read the file names from FV.INF\r
1829 //\r
1830 FileListPtr = FileListHeadPtr;\r
1831 while (FileListPtr != NULL) {\r
1832 TempFileListPtr = FileListPtr->NextVtfInfo;\r
1833 free (FileListPtr);\r
1834 FileListPtr = TempFileListPtr;\r
1835 }\r
1836}\r
1837\r
1838EFI_STATUS\r
1839ProcessAndCreateVtf (\r
1840 IN UINT64 Size\r
1841 )\r
1842/*++\r
1843\r
1844Routine Description:\r
1845\r
1846 This function process the link list created during INF file parsing\r
1847 and create component in VTF and updates its info in FIT table\r
1848\r
1849Arguments:\r
1850\r
1851 Size - Size of the Firmware Volume of which, this VTF belongs to.\r
1852\r
1853Returns:\r
1854\r
1855 EFI_UNSUPPORTED - Unknown FIT type\r
1856 EFI_SUCCESS - The function completed successfully\r
1857\r
1858--*/\r
1859{\r
1860 EFI_STATUS Status;\r
1861 PARSED_VTF_INFO *ParsedInfoPtr;\r
1862\r
1863 Status = EFI_SUCCESS;\r
1864\r
1865 ParsedInfoPtr = FileListHeadPtr;\r
1866\r
1867 while (ParsedInfoPtr != NULL) {\r
1868\r
1869 switch (ParsedInfoPtr->CompType) {\r
1870 //\r
1871 // COMP_TYPE_FIT_HEADER is a special case, hence handle it here\r
1872 //\r
1873 case COMP_TYPE_FIT_HEADER:\r
1874 //COMP_TYPE_FIT_HEADER 0x00\r
1875 Status = CreateFitTableAndInitialize (ParsedInfoPtr);\r
1876 break;\r
1877\r
1878 //\r
1879 // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here\r
1880 //\r
1881 case COMP_TYPE_FIT_PAL_A:\r
1882 //COMP_TYPE_FIT_PAL_A 0x0F\r
1883 Status = CreateAndUpdatePAL_A (ParsedInfoPtr);\r
1884\r
1885 //\r
1886 // Based on VTF specification, once the PAL_A component has been written,\r
1887 // update the Firmware Volume info as FIT table. This will be utilized\r
1888 // to extract the Firmware Volume Start address where this VTF will be\r
1889 // of part.\r
1890 //\r
1891 if (Status == EFI_SUCCESS) {\r
1892 UpdateFitEntryForFwVolume (Size);\r
1893 }\r
1894 break;\r
1895\r
1896 case COMP_TYPE_FIT_FV_BOOT:\r
1897 //COMP_TYPE_FIT_FV_BOOT 0x7E\r
1898 //\r
1899 // Since FIT entry for Firmware Volume has been created and it is\r
1900 // located at (PAL_A start - 16 byte). So we will not process any\r
1901 // Firmware Volume related entry from INF file\r
1902 //\r
1903 Status = EFI_SUCCESS;\r
1904 break;\r
1905\r
1906 default:\r
1907 //\r
1908 // Any other component type should be handled here. This will create the\r
1909 // image in specified VTF and create appropriate entry about this\r
1910 // component in FIT Entry.\r
1911 //\r
1912 Status = CreateAndUpdateComponent (ParsedInfoPtr);\r
1913 if (EFI_ERROR (Status)) {\r
1914 Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName);\r
1915 return EFI_ABORTED;\r
1916 } else {\r
1917 break;}\r
1918 }\r
1919\r
1920 ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo;\r
1921 }\r
1922 return Status;\r
1923}\r
1924\r
1925EFI_STATUS\r
1926GenerateVtfImage (\r
1927 IN UINT64 StartAddress1,\r
1928 IN UINT64 Size1,\r
1929 IN UINT64 StartAddress2,\r
1930 IN UINT64 Size2,\r
1931 IN FILE *fp\r
1932 )\r
1933/*++\r
1934\r
1935Routine Description:\r
1936\r
1937 This is the main function which will be called from application.\r
1938\r
1939Arguments:\r
1940\r
1941 StartAddress1 - The start address of the first VTF\r
1942 Size1 - The size of the first VTF\r
1943 StartAddress2 - The start address of the second VTF\r
1944 Size2 - The size of the second VTF\r
1945 fp - The pointer to BSF inf file\r
1946\r
1947Returns:\r
1948\r
1949 EFI_OUT_OF_RESOURCES - Can not allocate memory\r
1950 The return value can be any of the values\r
1951 returned by the calls to following functions:\r
1952 GetVtfRelatedInfoFromInfFile\r
1953 ProcessAndCreateVtf\r
1954 UpdateIA32ResetVector\r
1955 UpdateFfsHeader\r
1956 WriteVtfBinary\r
1957\r
1958--*/\r
1959{\r
1960 EFI_STATUS Status;\r
1961 FILE *VtfFP;\r
1962\r
1963 Status = EFI_UNSUPPORTED;\r
1964 VtfFP = fp;\r
1965\r
1966 if (StartAddress2 == 0) {\r
1967 SecondVTF = FALSE;\r
1968 } else {\r
1969 SecondVTF = TRUE;\r
1970 }\r
1971\r
1972 Fv1BaseAddress = StartAddress1;\r
1973 Fv1EndAddress = Fv1BaseAddress + Size1;\r
fd171542 1974 if (Fv1EndAddress != 0x100000000ULL || Size1 < 0x100000) {\r
30fdf114
LG
1975 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");\r
1976 if (Size1 < 0x100000) {\r
1977 Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");\r
1978 } else if (SecondVTF != TRUE) {\r
1979 Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");\r
1980 }\r
1981 Usage();\r
1982 return EFI_INVALID_PARAMETER;\r
1983 }\r
1984\r
1985 //\r
1986 // The image buffer for the First VTF\r
1987 //\r
1988 Vtf1Buffer = malloc ((UINTN) Size1);\r
1989 if (Vtf1Buffer == NULL) {\r
1990 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");\r
1991 return EFI_OUT_OF_RESOURCES;\r
1992 }\r
1993 memset (Vtf1Buffer, 0x00, (UINTN) Size1);\r
1994 Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1;\r
1995 Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;\r
1996\r
1997 if (SecondVTF) {\r
1998 Fv2BaseAddress = StartAddress2;\r
1999 Fv2EndAddress = Fv2BaseAddress + Size2;\r
2000 if (Fv2EndAddress != StartAddress1) {\r
2001 Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");\r
2002 if (SecondVTF == TRUE) {\r
2003 Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");\r
2004 Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");\r
2005 }\r
2006 Usage();\r
2007 return EFI_INVALID_PARAMETER;\r
2008 }\r
2009\r
2010 //\r
2011 // The image buffer for the second VTF\r
2012 //\r
2013 Vtf2Buffer = malloc ((UINTN) Size2);\r
2014 if (Vtf2Buffer == NULL) {\r
2015 Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");\r
2016 return EFI_OUT_OF_RESOURCES;\r
2017 }\r
2018 memset (Vtf2Buffer, 0x00, (UINTN) Size2);\r
2019 Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2;\r
2020 Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;\r
2021 }\r
2022\r
2023 Status = GetVtfRelatedInfoFromInfFile (VtfFP);\r
2024\r
2025 if (Status != EFI_SUCCESS) {\r
2026 Error (NULL, 0, 0003, "Error parsing file", "the input file.");\r
2027 CleanUpMemory ();\r
2028 return Status;\r
2029 }\r
2030\r
2031 Status = ProcessAndCreateVtf (Size1);\r
2032 if (Status != EFI_SUCCESS) {\r
2033 CleanUpMemory ();\r
2034 return Status;\r
2035 }\r
2036\r
2037 if (SectionOptionFlag) {\r
2038 Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize);\r
2039 if (Status != EFI_SUCCESS) {\r
2040 CleanUpMemory ();\r
2041 return Status;\r
2042 }\r
2043 }\r
2044\r
2045 //\r
2046 // Re arrange the FIT Table for Ascending order of their FIT Type..\r
2047 //\r
2048 SortFitTable ();\r
2049\r
2050 //\r
2051 // All components have been updated in FIT table. Now perform the FIT table\r
2052 // checksum. The following function will check if Checksum is required,\r
2053 // if yes, then it will perform the checksum otherwise not.\r
2054 //\r
2055 CalculateFitTableChecksum ();\r
2056\r
2057 //\r
2058 // Write the FFS header\r
2059 //\r
2060 Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);\r
2061 Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);\r
2062\r
2063 Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF);\r
2064 if (Status != EFI_SUCCESS) {\r
2065 CleanUpMemory ();\r
2066 return Status;\r
2067 }\r
2068 //\r
2069 // Update the VTF buffer into specified VTF binary file\r
2070 //\r
2071 Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF);\r
2072\r
2073 if (SecondVTF) {\r
2074 Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);\r
2075 Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);\r
2076 Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF);\r
2077 if (Status != EFI_SUCCESS) {\r
2078 CleanUpMemory ();\r
2079 return Status;\r
2080 }\r
2081\r
2082 //\r
2083 // Update the VTF buffer into specified VTF binary file\r
2084 //\r
2085 Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF);\r
2086 }\r
2087\r
2088 CleanUpMemory ();\r
2089\r
2090 return Status;\r
2091}\r
2092\r
2093EFI_STATUS\r
2094PeimFixupInFitTable (\r
2095 IN UINT64 StartAddress\r
2096 )\r
2097/*++\r
2098\r
2099Routine Description:\r
2100\r
2101 This function is an entry point to fixup SAL-E entry point.\r
2102\r
2103Arguments:\r
2104\r
2105 StartAddress - StartAddress for PEIM.....\r
2106\r
2107Returns:\r
2108\r
2109 EFI_SUCCESS - The function completed successfully\r
2110 EFI_ABORTED - Error Opening File\r
2111 EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.\r
2112\r
2113--*/\r
2114{\r
2115 EFI_STATUS Status;\r
2116 FILE *Fp;\r
2117 UINT64 *StartAddressPtr;\r
2118 UINTN FirstFwVSize;\r
30fdf114
LG
2119\r
2120 StartAddressPtr = malloc (sizeof (UINT64));\r
2121 if (StartAddressPtr == NULL) {\r
2122 return EFI_OUT_OF_RESOURCES;\r
2123 }\r
2124 *StartAddressPtr = StartAddress;\r
2125\r
1be2ed90 2126 Fp = fopen (LongFilePath (OutFileName1), "rb");\r
30fdf114
LG
2127\r
2128 if (Fp == NULL) {\r
2129 Error (NULL, 0, 0001, "Error opening file", OutFileName1);\r
2130 if (StartAddressPtr) {\r
2131 free (StartAddressPtr);\r
2132 }\r
2133 return EFI_ABORTED;\r
2134 }\r
2135\r
2136 FirstFwVSize = _filelength (fileno (Fp));\r
2137 fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);\r
0d2711a6 2138 fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);\r
30fdf114
LG
2139\r
2140 if (Fp) {\r
2141 fclose (Fp);\r
2142 }\r
2143\r
2144 if (StartAddressPtr) {\r
2145 free (StartAddressPtr);\r
2146 }\r
2147\r
2148 Status = EFI_SUCCESS;\r
2149 return Status;\r
2150}\r
2151\r
2152EFI_STATUS\r
2153UpdateSymFile (\r
2154 IN UINT64 BaseAddress,\r
2155 IN CHAR8 *DestFileName,\r
b303ea72
LG
2156 IN CHAR8 *SourceFileName,\r
2157 IN UINT64 FileSize\r
2158\r
30fdf114
LG
2159 )\r
2160/*++\r
2161\r
2162Routine Description:\r
2163\r
2164 This function adds the SYM tokens in the source file to the destination file.\r
2165 The SYM tokens are updated to reflect the base address.\r
2166\r
2167Arguments:\r
2168\r
2169 BaseAddress - The base address for the new SYM tokens.\r
2170 DestFileName - The destination file.\r
2171 SourceFileName - The source file.\r
b303ea72 2172 FileSize - Size of bin file.\r
30fdf114
LG
2173\r
2174Returns:\r
2175\r
2176 EFI_SUCCESS - The function completed successfully.\r
2177 EFI_INVALID_PARAMETER - One of the input parameters was invalid.\r
2178 EFI_ABORTED - An error occurred.\r
2179\r
2180--*/\r
2181{\r
2182 FILE *SourceFile;\r
2183 FILE *DestFile;\r
1be2ed90
HC
2184 CHAR8 Buffer[MAX_LONG_FILE_PATH];\r
2185 CHAR8 Type[MAX_LONG_FILE_PATH];\r
2186 CHAR8 Address[MAX_LONG_FILE_PATH];\r
2187 CHAR8 Section[MAX_LONG_FILE_PATH];\r
2188 CHAR8 Token[MAX_LONG_FILE_PATH];\r
2189 CHAR8 BaseToken[MAX_LONG_FILE_PATH];\r
30fdf114 2190 UINT64 TokenAddress;\r
b303ea72 2191 long StartLocation;\r
30fdf114
LG
2192\r
2193 //\r
2194 // Verify input parameters.\r
2195 //\r
2196 if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {\r
2197 return EFI_INVALID_PARAMETER;\r
2198 }\r
2199\r
2200 //\r
2201 // Open the source file\r
2202 //\r
1be2ed90 2203 SourceFile = fopen (LongFilePath (SourceFileName), "r");\r
30fdf114
LG
2204 if (SourceFile == NULL) {\r
2205\r
2206 //\r
2207 // SYM files are not required.\r
2208 //\r
2209 return EFI_SUCCESS;\r
2210 }\r
2211\r
2212 //\r
2213 // Use the file name minus extension as the base for tokens\r
2214 //\r
2215 strcpy (BaseToken, SourceFileName);\r
2216 strtok (BaseToken, ". \t\n");\r
2217 strcat (BaseToken, "__");\r
2218\r
2219 //\r
2220 // Open the destination file\r
2221 //\r
1be2ed90 2222 DestFile = fopen (LongFilePath (DestFileName), "a+");\r
30fdf114
LG
2223 if (DestFile == NULL) {\r
2224 fclose (SourceFile);\r
2225 Error (NULL, 0, 0001, "Error opening file", DestFileName);\r
2226 return EFI_ABORTED;\r
2227 }\r
2228\r
2229 //\r
2230 // If this is the beginning of the output file, write the symbol format info.\r
2231 //\r
2232 if (fseek (DestFile, 0, SEEK_END) != 0) {\r
2233 fclose (SourceFile);\r
2234 fclose (DestFile);\r
2235 Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");\r
2236 return EFI_ABORTED;\r
2237 }\r
2238\r
2239 StartLocation = ftell (DestFile);\r
2240\r
2241 if (StartLocation == 0) {\r
2242 fprintf (DestFile, "TEXTSYM format | V1.0\n");\r
2243 } else if (StartLocation == -1) {\r
2244 fclose (SourceFile);\r
2245 fclose (DestFile);\r
2246 Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");\r
2247 return EFI_ABORTED;\r
2248 }\r
2249\r
2250 //\r
2251 // Read the first line\r
2252 //\r
1be2ed90 2253 if (fgets (Buffer, MAX_LONG_FILE_PATH, SourceFile) == NULL) {\r
30fdf114
LG
2254 Buffer[0] = 0;\r
2255 }\r
2256\r
2257 //\r
2258 // Make sure it matches the expected sym format\r
2259 //\r
2260 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
2261 fclose (SourceFile);\r
2262 fclose (DestFile);\r
2263 Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");\r
2264 return EFI_ABORTED;\r
2265 }\r
2266\r
2267 //\r
2268 // Read in the file\r
2269 //\r
2270 while (feof (SourceFile) == 0) {\r
2271\r
2272 //\r
2273 // Read a line\r
2274 //\r
2275 if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {\r
2276\r
2277 //\r
2278 // Get the token address\r
2279 //\r
2280 AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
b303ea72
LG
2281 if (TokenAddress > FileSize) {\r
2282 //\r
2283 // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.\r
2284 //\r
2285 break;\r
2286 }\r
30fdf114
LG
2287\r
2288 //\r
2289 // Add the base address, the size of the FFS file header and the size of the peim header.\r
2290 //\r
2291 TokenAddress += BaseAddress &~IPF_CACHE_BIT;\r
2292\r
b303ea72
LG
2293 fprintf (DestFile, "%s | %016llX | ", Type, (unsigned long long) TokenAddress);\r
2294 fprintf (DestFile, "%s | %s\n %s\n", Section, Token, BaseToken); \r
30fdf114
LG
2295 }\r
2296 }\r
2297\r
2298 fclose (SourceFile);\r
2299 fclose (DestFile);\r
2300 return EFI_SUCCESS;\r
2301}\r
2302\r
2303EFI_STATUS\r
2304CalculateFitTableChecksum (\r
2305 VOID\r
2306 )\r
2307/*++\r
2308\r
2309Routine Description:\r
2310\r
2311 This function will perform byte checksum on the FIT table, if the the checksum required\r
2312 field is set to CheckSum required. If the checksum is not required then checksum byte\r
2313 will have value as 0;.\r
2314\r
2315Arguments:\r
2316\r
2317 NONE\r
2318\r
2319Returns:\r
2320\r
2321 Status - Value returned by call to CalculateChecksum8 ()\r
2322 EFI_SUCCESS - The function completed successfully\r
2323\r
2324--*/\r
2325{\r
2326 FIT_TABLE *TmpFitPtr;\r
2327 UINT64 FitTableAdd;\r
2328 UINT64 FitTableAddOffset;\r
2329 UINTN RelativeAddress;\r
2330 UINTN Size;\r
2331\r
2332 //\r
2333 // Read the Fit Table address from Itanium-based address map.\r
2334 //\r
2335 FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);\r
2336\r
2337 //\r
2338 // Translate this Itanium-based address in terms of local buffer address which\r
2339 // contains the image for Boot Strapped File\r
2340 //\r
2341 GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);\r
2342 FitTableAdd = *(UINTN *) RelativeAddress;\r
2343\r
2344 GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);\r
2345\r
2346 TmpFitPtr = (FIT_TABLE *) RelativeAddress;\r
2347\r
2348 Size = TmpFitPtr->CompSize * 16;\r
2349\r
2350 if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
2351 TmpFitPtr->CheckSum = 0;\r
2352 TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);\r
2353 } else {\r
2354 TmpFitPtr->CheckSum = 0;\r
2355 }\r
2356\r
2357 return EFI_SUCCESS;\r
2358}\r
2359\r
2360VOID\r
2361Version (\r
2362 VOID\r
2363 )\r
2364/*++\r
2365\r
2366Routine Description:\r
2367\r
2368 Displays the standard utility information to SDTOUT\r
2369\r
2370Arguments:\r
2371\r
2372 None\r
2373\r
2374Returns:\r
2375\r
2376 None\r
2377\r
2378--*/\r
2379{\r
b36d134f 2380 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
2381}\r
2382\r
2383VOID\r
2384Usage (\r
2385 VOID\r
2386 )\r
2387/*++\r
2388\r
2389Routine Description:\r
2390\r
2391 Displays the utility usage syntax to STDOUT\r
2392\r
2393Arguments:\r
2394\r
2395 None\r
2396\r
2397Returns:\r
2398\r
2399 None\r
2400\r
2401--*/\r
2402{\r
2403 //\r
2404 // Summary usage\r
2405 //\r
2406 fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);\r
2407\r
2408 //\r
2409 // Copyright declaration\r
2410 //\r
1be2ed90 2411 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");\r
30fdf114
LG
2412 //\r
2413 // Details Option\r
2414 //\r
2415 fprintf (stdout, "Options:\n");\r
2416 fprintf (stdout, " -f Input_file, --filename Input_file\n\\r
2417 Input_file is name of the BS Image INF file\n");\r
2418 fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\\r
2419 BaseAddress is the starting address of Firmware Volume\n\\r
2420 where Boot Strapped Image will reside.\n");\r
2421 fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\\r
2422 FwVolumeSize is the size of Firmware Volume.\n");\r
2423 fprintf (stdout, " -o FileName, --output FileName\n\\r
2424 File will be created to store the ouput content.\n");\r
2425 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
2426 fprintf (stdout, " --version Show program's version number and exit.\n");\r
2427 fprintf (stdout, " -h, --help Show this help message and exit.\n");\r
2428 fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n");\r
2429 fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");\r
2430}\r
2431\r
2432int\r
2433main (\r
2434 IN int argc,\r
2435 IN char **argv\r
2436 )\r
2437/*++\r
2438\r
2439Routine Description:\r
2440\r
2441 This utility uses GenVtf.dll to build a Boot Strap File Image which will be\r
2442 part of firmware volume image.\r
2443\r
2444Arguments:\r
2445\r
2446 argc - The count of the parameters\r
2447 argv - The parameters\r
2448\r
2449\r
2450Returns:\r
2451\r
2452 0 - No error conditions detected.\r
2453 1 - One or more of the input parameters is invalid.\r
2454 2 - A resource required by the utility was unavailable.\r
2455 - Most commonly this will be memory allocation or file creation.\r
2456 3 - GenFvImage.dll could not be loaded.\r
2457 4 - Error executing the GenFvImage dll.\r
2458 5 - Now this tool does not support the IA32 platform\r
2459\r
2460--*/\r
2461{\r
2462 UINT8 Index;\r
2463 UINT64 StartAddress1;\r
2464 UINT64 StartAddress2;\r
2465 UINT64 FwVolSize1;\r
2466 UINT64 FwVolSize2;\r
2467 BOOLEAN FirstRoundO;\r
2468 BOOLEAN FirstRoundB;\r
2469 BOOLEAN FirstRoundS;\r
2470 EFI_STATUS Status;\r
2471 FILE *VtfFP;\r
2472 CHAR8 *VtfFileName;\r
2473\r
2474 SetUtilityName (UTILITY_NAME);\r
2475\r
2476 //\r
2477 // Initialize variables\r
2478 //\r
2479 StartAddress1 = 0;\r
2480 StartAddress2 = 0;\r
2481 FwVolSize1 = 0;\r
2482 FwVolSize2 = 0;\r
2483 FirstRoundB = TRUE;\r
2484 FirstRoundS = TRUE;\r
2485 FirstRoundO = TRUE;\r
2486 DebugMode = FALSE;\r
2487 OutFileName1 = NULL;\r
2488 OutFileName2 = NULL;\r
2489 VtfFP = NULL;\r
2490 DebugLevel = 0;\r
2491\r
2492 //\r
2493 // Verify the correct number of arguments\r
2494 //\r
2495 if (argc == 1) {\r
2496 Usage();\r
2497 return 0;\r
2498 }\r
2499\r
2500 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {\r
2501 Usage();\r
2502 return 0;\r
2503 }\r
2504\r
2505 if ((strcmp(argv[1], "--version") == 0)) {\r
2506 Version();\r
2507 return 0;\r
2508 }\r
2509\r
2510 //\r
2511 // Parse the command line arguments\r
2512 //\r
2513 for (Index = 1; Index < argc; Index += 2) {\r
2514 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {\r
2515 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {\r
2516 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");\r
2517 goto ERROR;\r
2518 }\r
2519 //\r
2520 // Get the output file name\r
2521 //\r
2522 VTF_OUTPUT = TRUE;\r
2523 if (FirstRoundO) {\r
2524 //\r
2525 // It's the first output file name\r
2526 //\r
2527 OutFileName1 = (CHAR8 *)argv[Index+1];\r
2528 FirstRoundO = FALSE;\r
2529 } else {\r
2530 //\r
2531 //It's the second output file name\r
2532 //\r
2533 OutFileName2 = (CHAR8 *)argv[Index+1];\r
2534 }\r
2535 continue;\r
2536 }\r
2537\r
2538 if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) {\r
2539 if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {\r
2540 Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");\r
2541 goto ERROR;\r
2542 }\r
2543 //\r
2544 // Get the input VTF file name\r
2545 //\r
2546 VtfFileName = argv[Index+1];\r
1be2ed90 2547 VtfFP = fopen (LongFilePath (VtfFileName), "rb");\r
30fdf114
LG
2548 if (VtfFP == NULL) {\r
2549 Error (NULL, 0, 0001, "Error opening file", VtfFileName);\r
2550 goto ERROR;\r
2551 }\r
2552 continue;\r
2553 }\r
2554 \r
2555 if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {\r
2556 if (FirstRoundB) {\r
2557 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);\r
2558 FirstRoundB = FALSE;\r
2559 } else {\r
2560 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);\r
2561 }\r
2562 if (Status != EFI_SUCCESS) {\r
2563 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);\r
2564 goto ERROR;\r
2565 } \r
2566 continue;\r
2567 }\r
2568\r
2569 if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {\r
2570 if (FirstRoundS) {\r
2571 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);\r
2572 FirstRoundS = FALSE;\r
2573 } else {\r
2574 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);\r
2575 SecondVTF = TRUE;\r
2576 }\r
2577\r
2578 if (Status != EFI_SUCCESS) {\r
2579 Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);\r
2580 goto ERROR;\r
2581 }\r
2582 continue;\r
2583 }\r
2584\r
2585 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {\r
2586 VerboseMode = TRUE;\r
2587 Index--;\r
2588 continue;\r
2589 }\r
2590\r
2591 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {\r
2592 QuietMode = TRUE;\r
2593 Index--;\r
2594 continue;\r
2595 }\r
2596\r
2597 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {\r
2598 //\r
2599 // debug level specified\r
2600 //\r
2601 Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel);\r
2602 if (EFI_ERROR (Status)) {\r
2603 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);\r
2604 goto ERROR;\r
2605 }\r
2606 if (DebugLevel > 9) {\r
2607 Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);\r
2608 goto ERROR;\r
2609 }\r
2610 if((DebugLevel <= 9) &&(DebugLevel >= 5)) {\r
2611 DebugMode = TRUE;\r
2612 } else {\r
2613 DebugMode = FALSE;\r
2614 }\r
2615 continue;\r
2616 }\r
2617\r
2618 Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);\r
2619 goto ERROR;\r
2620 }\r
2621\r
2622 if (VtfFP == NULL) {\r
2623 Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");\r
2624 goto ERROR;\r
2625 }\r
2626\r
2627 if (FirstRoundB) {\r
2628 Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");\r
2629 goto ERROR;\r
2630 }\r
2631\r
2632 if (FirstRoundS) {\r
2633 Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");\r
2634 goto ERROR;\r
2635 }\r
2636 //\r
2637 // All Parameters has been parsed, now set the message print level\r
2638 //\r
2639 if (QuietMode) {\r
2640 SetPrintLevel(40);\r
2641 } else if (VerboseMode) {\r
2642 SetPrintLevel(15);\r
2643 } else if (DebugMode) {\r
2644 SetPrintLevel(DebugLevel);\r
2645 }\r
2646\r
2647 if (VerboseMode) {\r
2648 VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
2649 }\r
2650\r
2651 if (VTF_OUTPUT == FALSE) {\r
2652 if (SecondVTF == TRUE) {\r
2653 OutFileName1 = VTF_OUTPUT_FILE1;\r
2654 OutFileName2 = VTF_OUTPUT_FILE2;\r
2655 } else {\r
2656 OutFileName1 = VTF_OUTPUT_FILE1;\r
2657 }\r
2658 SymFileName = VTF_SYM_FILE;\r
2659 } else {\r
90114c10 2660 assert (OutFileName1);\r
30fdf114 2661 INTN OutFileNameLen = strlen(OutFileName1);\r
5aec6991 2662 INTN NewIndex;\r
30fdf114 2663\r
5aec6991
YZ
2664 for (NewIndex = OutFileNameLen; NewIndex > 0; --NewIndex) {\r
2665 if (OutFileName1[NewIndex] == '/' || OutFileName1[NewIndex] == '\\') {\r
30fdf114
LG
2666 break;\r
2667 }\r
2668 }\r
5aec6991 2669 if (NewIndex == 0) {\r
30fdf114
LG
2670 SymFileName = VTF_SYM_FILE;\r
2671 } else {\r
5aec6991 2672 INTN SymFileNameLen = NewIndex + 1 + strlen(VTF_SYM_FILE);\r
30fdf114 2673 SymFileName = malloc(SymFileNameLen + 1);\r
90114c10
HW
2674 if (SymFileName == NULL) {\r
2675 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2676 goto ERROR;\r
2677 }\r
5aec6991
YZ
2678 memcpy(SymFileName, OutFileName1, NewIndex + 1);\r
2679 memcpy(SymFileName + NewIndex + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));\r
30fdf114
LG
2680 SymFileName[SymFileNameLen] = '\0';\r
2681 }\r
2682 if (DebugMode) {\r
2683 DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);\r
2684 }\r
2685 }\r
2686\r
2687 //\r
2688 // Call the GenVtfImage\r
2689 //\r
2690 if (DebugMode) {\r
2691 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);\r
2692 }\r
2693 Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);\r
2694\r
2695 if (EFI_ERROR (Status)) {\r
2696 switch (Status) {\r
2697\r
2698 case EFI_INVALID_PARAMETER:\r
2699 Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");\r
2700 break;\r
2701\r
2702 case EFI_ABORTED:\r
fd171542 2703 Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image.");\r
30fdf114
LG
2704 break;\r
2705\r
2706 case EFI_OUT_OF_RESOURCES:\r
2707 Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");\r
2708 break;\r
2709\r
2710 case EFI_VOLUME_CORRUPTED:\r
fd171542 2711 Error (NULL, 0, 3000, "Invalid", "No base address was specified.");\r
30fdf114
LG
2712 break;\r
2713\r
2714 default:\r
fd171542 2715 Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status );\r
30fdf114
LG
2716 break;\r
2717 }\r
2718 }\r
2719ERROR:\r
2720 if (VtfFP != NULL) {\r
2721 fclose (VtfFP);\r
2722 }\r
2723\r
2724 if (DebugMode) {\r
2725 DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);\r
2726 }\r
2727\r
2728 if (VerboseMode) {\r
2729 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
2730 }\r
2731 return GetUtilityStatus();\r
2732}\r