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