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