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