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