]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/GenFfsFile/GenFfsFile.c
Initial import.
[mirror_edk2.git] / Tools / Source / TianoTools / GenFfsFile / GenFfsFile.c
1 /*++
2
3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 GenFfsFile.c
15
16 Abstract:
17
18 This file contains functions required to generate a Firmware File System
19 file.
20
21 --*/
22
23 #include "Base.h"
24 #include "UefiBaseTypes.h"
25 #include "FirmwareVolumeImageFormat.h"
26 #include "FirmwareFileSystem.h"
27 #include "FirmwareVolumeHeader.h"
28 #include "FirmwareVolumeImageFormat.h"
29 #include "ParseInf.h"
30 #include "EfiCompress.h"
31 #include "EfiCustomizedCompress.h"
32 #include "Crc32.h"
33 #include "GenFfsFile.h"
34 #include <stdio.h>
35 #include <ctype.h> // for isalpha()
36 //
37 // include file for _spawnv
38 //
39 #ifndef __GNUC__
40 #include <process.h>
41 #endif
42 #include <stdlib.h>
43 #include <string.h>
44 #include "CommonLib.h"
45 #include "EfiUtilityMsgs.h"
46 #include "SimpleFileParsing.h"
47
48 #define UTILITY_NAME "GenFfsFile"
49 #define TOOLVERSION "0.32"
50 #define MAX_ARRAY_SIZE 100
51
52 static
53 INT32
54 GetNextLine (
55 OUT CHAR8 *Destination,
56 IN FILE *Package,
57 IN OUT UINT32 *LineNumber
58 );
59
60 static
61 void
62 CheckSlash (
63 IN OUT CHAR8 *String,
64 IN FILE *In,
65 IN OUT UINT32 *LineNumber
66 );
67
68 static
69 INT32
70 FindSectionInPackage (
71 IN CHAR8 *BuildDirectory,
72 IN FILE *OverridePackage,
73 IN OUT UINT32 *LineNumber
74 );
75
76 static
77 STATUS
78 ProcessCommandLineArgs (
79 int Argc,
80 char *Argv[]
81 );
82
83 static
84 void
85 PrintUsage (
86 void
87 );
88
89 //
90 // Keep globals in this structure
91 //
92 static struct {
93 UINT8 BuildDirectory[_MAX_PATH];
94 UINT8 PrimaryPackagePath[_MAX_PATH];
95 UINT8 OverridePackagePath[_MAX_PATH];
96 BOOLEAN Verbose;
97 } mGlobals;
98
99 static EFI_GUID mZeroGuid = { 0 };
100
101 static
102 void
103 StripQuotes (
104 IN OUT CHAR8 *String
105 )
106 /*++
107
108 Routine Description:
109
110 Removes quotes and/or whitespace from around a string
111
112 Arguments:
113
114 String - String to remove quotes from
115
116 Returns:
117
118 None
119
120 --*/
121 {
122 UINTN Index;
123 UINTN Index2;
124 UINTN StrLen;
125
126 Index2 = strspn (String, "\" \t\n");
127 StrLen = strlen (String);
128
129 for (Index = Index2; String[Index] != '\"', Index < StrLen; Index++) {
130 String[Index - Index2] = String[Index];
131 }
132
133 String[Index - Index2] = 0;
134 }
135
136 static
137 void
138 PrintUsage (
139 void
140 )
141 /*++
142
143 Routine Description:
144
145 Print Error / Help message.
146
147 Arguments:
148
149 void
150
151 Returns:
152
153 None
154
155 --*/
156 {
157 printf ("Usage:\n");
158 printf (UTILITY_NAME " -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");
159 printf (" -b \"build directory\":\n ");
160 printf (" specifies the full path to the component build directory.\n");
161 printf (" -p1 \"P1_path\":\n");
162 printf (" specifies fully qualified file name to the primary package file.\n");
163 printf (" This file will normally exist in the same directory as the makefile\n");
164 printf (" for the component. Required.\n");
165 printf (" -p2 \"P2_path\":\n");
166 printf (" specifies fully qualified file name to the override package file.\n");
167 printf (" This file will normally exist in the build tip. Optional.\n");
168 }
169
170 static
171 INT32
172 TestComment (
173 IN CHAR8 *String,
174 IN FILE *In
175 )
176 /*++
177
178 Routine Description:
179
180 Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment
181
182 Arguments:
183
184 String - String to test
185
186 In - Open file to move pointer within
187
188 Returns:
189
190 -1 - End of file reached
191 0 - Not a comment
192 1 - Comment bypassed
193
194 --*/
195 {
196 CHAR8 CharBuffer;
197
198 CharBuffer = 0;
199 if ((String[0] == '/') && (String[1] == '/')) {
200 while (CharBuffer != '\n') {
201 fscanf (In, "%c", &CharBuffer);
202 if (feof (In)) {
203 return -1;
204 }
205 }
206 } else {
207 return 0;
208 }
209
210 return 1;
211 }
212
213 static
214 void
215 BreakString (
216 IN CONST CHAR8 *Source,
217 OUT CHAR8 *Destination,
218 IN INTN Direction
219 )
220 /*++
221
222 Routine Description:
223
224 Takes an input string and returns either the part before the =, or the part after the =, depending on direction
225
226 Arguments:
227
228 Source - String to break
229
230 Destination - Buffer to place new string in
231
232 Direction - 0 to return all of source string before =
233 1 to return all of source string after =
234
235 Returns:
236
237 None
238
239 --*/
240 {
241 UINTN Index;
242 UINTN Index2;
243
244 Index = 0;
245 Index2 = 0;
246
247 if (strchr (Source, '=') == NULL) {
248 strcpy (Destination, Source);
249
250 return ;
251 }
252
253 if (Direction == 0) {
254 //
255 // return part of string before =
256 //
257 while (Source[Index] != '=') {
258 Destination[Index] = Source[Index++];
259 }
260
261 Destination[Index] = 0;
262 } else {
263 //
264 // return part of string after =
265 //
266 strcpy (Destination, strchr (Source, '=') + 1);
267 }
268 }
269
270 static
271 INT32
272 GetNextLine (
273 OUT CHAR8 *Destination,
274 IN FILE *Package,
275 IN OUT UINT32 *LineNumber
276 )
277 /*++
278
279 Routine Description:
280
281 Gets the next non-commented line from the file
282
283 Arguments:
284
285 Destination - Where to put string
286
287 Package - Package to get string from
288
289 LineNumber - The actual line number.
290
291 Returns:
292
293 -1 - End of file reached
294 0 - Success
295
296 --*/
297 {
298 CHAR8 String[_MAX_PATH];
299 fscanf (Package, "%s", &String);
300 if (feof (Package)) {
301 return -1;
302 }
303
304 while (TestComment (String, Package) == 1) {
305 fscanf (Package, "%s", &String);
306 if (feof (Package)) {
307 return -1;
308 }
309 }
310
311 strcpy (Destination, String);
312 return 0;
313 }
314
315 static
316 VOID
317 CheckSlash (
318 IN OUT CHAR8 *String,
319 IN FILE *In,
320 IN OUT UINT32 *LineNumber
321 )
322 /*++
323
324 Routine Description:
325
326 Checks to see if string is line continuation character, if so goes to next valid line
327
328 Arguments:
329
330 String - String to test
331
332 In - Open file to move pointer within
333
334 LineNumber - The line number.
335
336 Returns:
337
338 None
339
340 --*/
341 {
342 CHAR8 ByteBuffer;
343 ByteBuffer = 0;
344
345 switch (String[0]) {
346
347 case '\\':
348 while (String[0] == '\\') {
349 while (ByteBuffer != '\n') {
350 fscanf (In, "%c", &ByteBuffer);
351 }
352 (*LineNumber)++;
353 if (GetNextLine (String, In, LineNumber) == -1) {
354 return ;
355 }
356 }
357 break;
358
359 case '\n':
360 (*LineNumber)++;
361 while (String[0] == '\n') {
362 if (GetNextLine (String, In, LineNumber) == -1) {
363 return ;
364 }
365 }
366 break;
367
368 default:
369 break;
370
371 }
372
373 }
374
375 static
376 INT32
377 FindSectionInPackage (
378 IN CHAR8 *BuildDirectory,
379 IN FILE *OverridePackage,
380 IN OUT UINT32 *LineNumber
381 )
382 /*++
383
384 Routine Description:
385
386 Finds the matching section within the package
387
388 Arguments:
389
390 BuildDirectory - name of section to find
391
392 OverridePackage - Package file to search within
393
394 LineNumber - The line number.
395
396 Returns:
397
398 -1 - End of file reached
399 0 - Success
400
401 --*/
402 {
403 CHAR8 String[_MAX_PATH];
404 CHAR8 NewString[_MAX_PATH];
405 String[0] = 0;
406
407 while (strcmp (BuildDirectory, String) != 0) {
408 if (GetNextLine (NewString, OverridePackage, LineNumber) != 0) {
409 return -1;
410 }
411
412 if (NewString[0] == '[') {
413 if (NewString[strlen (NewString) - 1] != ']') {
414 //
415 // have to construct string.
416 //
417 strcpy (String, NewString + 1);
418
419 while (1) {
420 fscanf (OverridePackage, "%s", &NewString);
421 if (feof (OverridePackage)) {
422 return -1;
423 }
424
425 if (NewString[0] != ']') {
426 if (strlen (String) != 0) {
427 strcat (String, " ");
428 }
429
430 strcat (String, NewString);
431 if (String[strlen (String) - 1] == ']') {
432 String[strlen (String) - 1] = 0;
433 break;
434 }
435 } else {
436 break;
437 }
438 }
439 } else {
440 NewString[strlen (NewString) - 1] = 0;
441 strcpy (String, NewString + 1);
442 }
443 }
444 }
445
446 return 0;
447 }
448
449 static
450 EFI_STATUS
451 GenSimpleGuidSection (
452 IN OUT UINT8 *FileBuffer,
453 IN OUT UINT32 *BufferSize,
454 IN UINT32 DataSize,
455 IN EFI_GUID SignGuid,
456 IN UINT16 GuidedSectionAttributes
457 )
458 /*++
459
460 Routine Description:
461
462 add GUIDed section header for the data buffer.
463 data stays in same location (overwrites source data).
464
465 Arguments:
466
467 FileBuffer - Buffer containing data to sign
468
469 BufferSize - On input, the size of FileBuffer. On output, the size of
470 actual section data (including added section header).
471
472 DataSize - Length of data to Sign
473
474 SignGuid - Guid to be add.
475
476 GuidedSectionAttributes - The section attribute.
477
478 Returns:
479
480 EFI_SUCCESS - Successful
481 EFI_OUT_OF_RESOURCES - Not enough resource.
482
483 --*/
484 {
485 UINT32 TotalSize;
486
487 EFI_GUID_DEFINED_SECTION GuidSectionHeader;
488 UINT8 *SwapBuffer;
489
490 SwapBuffer = NULL;
491
492 if (DataSize == 0) {
493 *BufferSize = 0;
494
495 return EFI_SUCCESS;
496 }
497
498 TotalSize = DataSize + sizeof (EFI_GUID_DEFINED_SECTION);
499 GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
500 GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
501 GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
502 GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
503 memcpy (&(GuidSectionHeader.SectionDefinitionGuid), &SignGuid, sizeof (EFI_GUID));
504 GuidSectionHeader.Attributes = GuidedSectionAttributes;
505 GuidSectionHeader.DataOffset = sizeof (EFI_GUID_DEFINED_SECTION);
506
507 SwapBuffer = (UINT8 *) malloc (DataSize);
508 if (SwapBuffer == NULL) {
509 return EFI_OUT_OF_RESOURCES;
510 }
511
512 memcpy (SwapBuffer, FileBuffer, DataSize);
513 memcpy (FileBuffer, &GuidSectionHeader, sizeof (EFI_GUID_DEFINED_SECTION));
514 memcpy (FileBuffer + sizeof (EFI_GUID_DEFINED_SECTION), SwapBuffer, DataSize);
515
516 //
517 // Make sure section ends on a DWORD boundary
518 //
519 while ((TotalSize & 0x03) != 0) {
520 FileBuffer[TotalSize] = 0;
521 TotalSize++;
522 }
523
524 *BufferSize = TotalSize;
525
526 if (SwapBuffer != NULL) {
527 free (SwapBuffer);
528 }
529
530 return EFI_SUCCESS;
531 }
532
533 static
534 EFI_STATUS
535 CompressSection (
536 UINT8 *FileBuffer,
537 UINT32 *BufferSize,
538 UINT32 DataSize,
539 CHAR8 *Type
540 )
541 /*++
542
543 Routine Description:
544
545 Compress the data and add section header for the compressed data.
546 Compressed data (with section header) stays in same location as the source
547 (overwrites source data).
548
549 Arguments:
550
551 FileBuffer - Buffer containing data to Compress
552
553 BufferSize - On input, the size of FileBuffer. On output, the size of
554 actual compressed data (including added section header).
555 When buffer is too small, this value indicates the size needed.
556
557 DataSize - The size of data to compress
558
559 Type - The compression type (not used currently).
560 Assume EFI_HEAVY_COMPRESSION.
561
562 Returns:
563
564 EFI_BUFFER_TOO_SMALL - Buffer size is too small.
565 EFI_UNSUPPORTED - Compress type can not be supported.
566 EFI_SUCCESS - Successful
567 EFI_OUT_OF_RESOURCES - Not enough resource.
568
569 --*/
570 {
571 EFI_STATUS Status;
572 UINT8 *CompData;
573 UINT32 CompSize;
574 UINT32 TotalSize;
575 EFI_COMPRESSION_SECTION CompressionSet;
576 UINT8 CompressionType;
577 COMPRESS_FUNCTION CompressFunction;
578
579 Status = EFI_SUCCESS;
580 CompData = NULL;
581 CompSize = 0;
582 TotalSize = 0;
583 CompressFunction = NULL;
584
585 //
586 // Get the compress type
587 //
588 if (strcmpi (Type, "Dummy") == 0) {
589 //
590 // Added "Dummy" to keep backward compatibility.
591 //
592 CompressionType = EFI_STANDARD_COMPRESSION;
593 CompressFunction = (COMPRESS_FUNCTION) Compress;
594
595 } else if (strcmpi (Type, "LZH") == 0) {
596 //
597 // EFI stardard compression (LZH)
598 //
599 CompressionType = EFI_STANDARD_COMPRESSION;
600 CompressFunction = (COMPRESS_FUNCTION) Compress;
601
602 } else {
603 //
604 // Customized compression
605 //
606 Status = SetCustomizedCompressionType (Type);
607 if (EFI_ERROR (Status)) {
608 return Status;
609 }
610
611 CompressionType = EFI_CUSTOMIZED_COMPRESSION;
612 CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
613 }
614 //
615 // Compress the raw data
616 //
617 Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);
618 if (Status == EFI_BUFFER_TOO_SMALL) {
619 CompData = malloc (CompSize);
620 if (!CompData) {
621 return EFI_OUT_OF_RESOURCES;
622 }
623
624 Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);
625 }
626
627 if (EFI_ERROR (Status)) {
628 if (CompData != NULL) {
629 free (CompData);
630 }
631
632 return Status;
633 }
634
635 TotalSize = CompSize + sizeof (EFI_COMPRESSION_SECTION);
636
637 //
638 // Buffer too small?
639 //
640 if (TotalSize > *BufferSize) {
641 *BufferSize = TotalSize;
642 if (CompData != NULL) {
643 free (CompData);
644 }
645
646 return EFI_BUFFER_TOO_SMALL;
647 }
648 //
649 // Add the section header for the compressed data
650 //
651 CompressionSet.CommonHeader.Type = EFI_SECTION_COMPRESSION;
652 CompressionSet.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
653 CompressionSet.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
654 CompressionSet.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
655 CompressionSet.CompressionType = CompressionType;
656 CompressionSet.UncompressedLength = DataSize;
657
658 //
659 // Copy header and data to the buffer
660 //
661 memcpy (FileBuffer, &CompressionSet, sizeof (EFI_COMPRESSION_SECTION));
662 memcpy (FileBuffer + sizeof (CompressionSet), CompData, CompSize);
663
664 //
665 // Make sure section ends on a DWORD boundary
666 //
667 while ((TotalSize & 0x03) != 0) {
668 FileBuffer[TotalSize] = 0;
669 TotalSize++;
670 }
671
672 *BufferSize = TotalSize;
673
674 if (CompData != NULL) {
675 free (CompData);
676 }
677
678 return EFI_SUCCESS;
679 }
680
681 static
682 void
683 StripParens (
684 IN OUT CHAR8 *String
685 )
686 /*++
687
688 Routine Description:
689
690 Removes Parenthesis from around a string
691
692 Arguments:
693
694 String - String to remove parens from
695
696 Returns:
697
698 None
699
700 --*/
701 {
702 INT32 Index;
703
704 if (String[0] != '(') {
705 return ;
706 }
707
708 for (Index = 1; String[Index] != ')'; Index++) {
709 String[Index - 1] = String[Index];
710 if (String[Index] == 0) {
711 return ;
712 }
713 }
714
715 String[Index - 1] = 0;
716
717 return ;
718 }
719
720 static
721 void
722 StripEqualMark (
723 IN OUT CHAR8 *String
724 )
725 /*++
726
727 Routine Description:
728
729 Removes Equal Mark from around a string
730
731 Arguments:
732
733 String - String to remove equal mark from
734
735 Returns:
736
737 None
738
739 --*/
740 {
741 INT32 Index;
742
743 if (String[0] != '=' && String[strlen (String) - 1] != '=') {
744 return ;
745 }
746
747 if (String[0] == '=') {
748
749 for (Index = 1; String[Index] != 0; Index++) {
750 String[Index - 1] = String[Index];
751 }
752
753 String[Index - 1] = 0;
754 }
755
756 if (String[strlen (String) - 1] == '=') {
757 String[strlen (String) - 1] = 0;
758 }
759
760 return ;
761 }
762
763 static
764 INT32
765 ProcessEnvironmentVariable (
766 IN CHAR8 *Buffer,
767 OUT CHAR8 *NewBuffer
768 )
769 /*++
770
771 Routine Description:
772
773 Converts environment variables to values
774
775 Arguments:
776
777 Buffer - Buffer containing Environment Variable String
778
779 NewBuffer - Buffer containing value of environment variable
780
781
782 Returns:
783
784 Number of characters from Buffer used
785
786 --*/
787 {
788 INT32 Index;
789 INT32 Index2;
790 CHAR8 VariableBuffer[_MAX_PATH];
791
792 Index = 2;
793 Index2 = 0;
794
795 while (Buffer[Index] != ')') {
796 VariableBuffer[Index - 2] = Buffer[Index++];
797 }
798
799 VariableBuffer[Index - 2] = 0;
800 Index++;
801
802 if (getenv (VariableBuffer) != NULL) {
803 strcpy (NewBuffer, getenv (VariableBuffer));
804 } else {
805 printf ("Environment variable %s not found!\n", VariableBuffer);
806 }
807
808 return Index;
809 }
810
811 static
812 void
813 SplitAttributesField (
814 IN CHAR8 *Buffer,
815 IN CHAR8 *AttributesArray[],
816 IN OUT UINT32 *NumberOfAttributes
817 )
818 /*
819 NumberOfAttributes: on input, it specifies the current number of attributes
820 stored in AttributeArray.
821 on output, it is updated to the latest number of attributes
822 stored in AttributesArray.
823 */
824 {
825 UINT32 Index;
826 UINT32 Index2;
827 UINT32 z;
828 CHAR8 *CharBuffer;
829
830 CharBuffer = NULL;
831 CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
832 ZeroMem (CharBuffer, _MAX_PATH);
833
834 for (Index = 0, z = 0, Index2 = 0; Index < strlen (Buffer); Index++) {
835
836 if (Buffer[Index] != '|') {
837 CharBuffer[z] = Buffer[Index];
838 z++;
839 } else {
840
841 CharBuffer[z] = 0;
842 AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;
843 Index2++;
844
845 //
846 // allocate new char buffer for the next attributes string
847 //
848 CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
849 ZeroMem (CharBuffer, _MAX_PATH);
850 z = 0;
851 }
852 }
853
854 CharBuffer[z] = 0;
855 //
856 // record the last attributes string in the Buffer
857 //
858 AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;
859 Index2++;
860
861 *NumberOfAttributes += Index2;
862
863 return ;
864 }
865
866 static
867 INT32
868 GetToolArguments (
869 CHAR8 *ToolArgumentsArray[],
870 FILE *Package,
871 CHAR8 **PtrInputFileName,
872 CHAR8 **PtrOutputFileName,
873 EFI_GUID *Guid,
874 UINT16 *GuidedSectionAttributes
875 )
876 {
877 CHAR8 Buffer[_MAX_PATH];
878 BOOLEAN ArgumentsFlag;
879 BOOLEAN InputFlag;
880 BOOLEAN OutputFlag;
881 BOOLEAN GuidFlag;
882 BOOLEAN AttributesFlag;
883 UINT32 argc;
884 UINT32 Index2;
885 UINT32 z;
886 CHAR8 *CharBuffer;
887 INT32 Index;
888 INT32 ReturnValue;
889 EFI_STATUS Status;
890
891 CHAR8 *AttributesArray[MAX_ARRAY_SIZE];
892 UINT32 NumberOfAttributes;
893 CHAR8 *InputFileName;
894 CHAR8 *OutputFileName;
895 UINT32 LineNumber;
896 Buffer[_MAX_PATH];
897
898 ArgumentsFlag = FALSE;
899 InputFlag = FALSE;
900 OutputFlag = FALSE;
901 GuidFlag = FALSE;
902 AttributesFlag = FALSE;
903 //
904 // Start at 1, since ToolArgumentsArray[0]
905 // is the program name.
906 //
907 argc = 1;
908 Index2 = 0;
909
910 z = 0;
911 ReturnValue = 0;
912 NumberOfAttributes = 0;
913 InputFileName = NULL;
914 OutputFileName = NULL;
915
916 ZeroMem (Buffer, _MAX_PATH);
917 ZeroMem (AttributesArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);
918 LineNumber = 0;
919 while (Buffer[0] != ')') {
920
921 if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
922 CheckSlash (Buffer, Package, &LineNumber);
923 StripEqualMark (Buffer);
924 } else {
925 Error (NULL, 0, 0, "failed to get next line from package file", NULL);
926 return -1;
927 }
928
929 if (Buffer[0] == ')') {
930 break;
931 } else if (strcmpi (Buffer, "ARGS") == 0) {
932
933 ArgumentsFlag = TRUE;
934 AttributesFlag = FALSE;
935 continue;
936
937 } else if (strcmpi (Buffer, "INPUT") == 0) {
938
939 InputFlag = TRUE;
940 ArgumentsFlag = FALSE;
941 AttributesFlag = FALSE;
942 continue;
943
944 } else if (strcmpi (Buffer, "OUTPUT") == 0) {
945
946 OutputFlag = TRUE;
947 ArgumentsFlag = FALSE;
948 AttributesFlag = FALSE;
949 continue;
950
951 } else if (strcmpi (Buffer, "GUID") == 0) {
952
953 GuidFlag = TRUE;
954 ArgumentsFlag = FALSE;
955 AttributesFlag = FALSE;
956 //
957 // fetch the GUID for the section
958 //
959 continue;
960
961 } else if (strcmpi (Buffer, "ATTRIBUTES") == 0) {
962
963 AttributesFlag = TRUE;
964 ArgumentsFlag = FALSE;
965 //
966 // fetch the GUIDed Section's Attributes
967 //
968 continue;
969
970 } else if (strcmpi (Buffer, "") == 0) {
971 continue;
972 }
973 //
974 // get all command arguments into ToolArgumentsArray
975 //
976 if (ArgumentsFlag) {
977
978 StripEqualMark (Buffer);
979
980 CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
981 if (CharBuffer == NULL) {
982 goto ErrorExit;
983 }
984
985 ZeroMem (CharBuffer, sizeof (_MAX_PATH));
986
987 ToolArgumentsArray[argc] = CharBuffer;
988
989 if (Buffer[0] == '$') {
990 Index = ProcessEnvironmentVariable (&Buffer[0], ToolArgumentsArray[argc]);
991 //
992 // if there is string after the environment variable, cat it.
993 //
994 if ((UINT32) Index < strlen (Buffer)) {
995 strcat (ToolArgumentsArray[argc], &Buffer[Index]);
996 }
997 } else {
998 strcpy (ToolArgumentsArray[argc], Buffer);
999 }
1000
1001 argc += 1;
1002 ToolArgumentsArray[argc] = NULL;
1003 continue;
1004 }
1005
1006 if (InputFlag) {
1007
1008 StripEqualMark (Buffer);
1009
1010 InputFileName = (CHAR8 *) malloc (_MAX_PATH);
1011 if (InputFileName == NULL) {
1012 goto ErrorExit;
1013 }
1014
1015 ZeroMem (InputFileName, sizeof (_MAX_PATH));
1016
1017 if (Buffer[0] == '$') {
1018 Index = ProcessEnvironmentVariable (&Buffer[0], InputFileName);
1019 //
1020 // if there is string after the environment variable, cat it.
1021 //
1022 if ((UINT32) Index < strlen (Buffer)) {
1023 strcat (InputFileName, &Buffer[Index]);
1024 }
1025 } else {
1026 strcpy (InputFileName, Buffer);
1027 }
1028
1029 InputFlag = FALSE;
1030 continue;
1031 }
1032
1033 if (OutputFlag) {
1034
1035 StripEqualMark (Buffer);
1036
1037 OutputFileName = (CHAR8 *) malloc (_MAX_PATH);
1038 if (OutputFileName == NULL) {
1039 goto ErrorExit;
1040 }
1041
1042 ZeroMem (OutputFileName, sizeof (_MAX_PATH));
1043
1044 if (Buffer[0] == '$') {
1045 Index = ProcessEnvironmentVariable (&Buffer[0], OutputFileName);
1046 //
1047 // if there is string after the environment variable, cat it.
1048 //
1049 if ((UINT32) Index < strlen (Buffer)) {
1050 strcat (OutputFileName, &Buffer[Index]);
1051 }
1052 } else {
1053 strcpy (OutputFileName, Buffer);
1054 }
1055
1056 OutputFlag = FALSE;
1057 continue;
1058 }
1059
1060 if (GuidFlag) {
1061
1062 StripEqualMark (Buffer);
1063
1064 Status = StringToGuid (Buffer, Guid);
1065 if (EFI_ERROR (Status)) {
1066 ReturnValue = -1;
1067 goto ErrorExit;
1068 }
1069
1070 GuidFlag = FALSE;
1071 }
1072
1073 if (AttributesFlag) {
1074
1075 StripEqualMark (Buffer);
1076
1077 //
1078 // there might be no space between each attribute in the statement,
1079 // split them aside and return each attribute string
1080 // in the AttributesArray
1081 //
1082 SplitAttributesField (Buffer, AttributesArray, &NumberOfAttributes);
1083 }
1084 }
1085 //
1086 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
1087 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
1088 //
1089 for (z = 0; z < NumberOfAttributes; z++) {
1090 if (strcmpi (AttributesArray[z], "PROCESSING_REQUIRED") == 0) {
1091 *GuidedSectionAttributes |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
1092 } else if (strcmpi (AttributesArray[z], "AUTH_STATUS_VALID") == 0) {
1093 *GuidedSectionAttributes |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
1094 }
1095 }
1096
1097 ErrorExit:
1098
1099 for (Index2 = 0; Index2 < MAX_ARRAY_SIZE; Index2++) {
1100 if (AttributesArray[Index2] == NULL) {
1101 break;
1102 }
1103
1104 free (AttributesArray[Index2]);
1105 }
1106
1107 *PtrInputFileName = InputFileName;
1108 *PtrOutputFileName = OutputFileName;
1109
1110 return ReturnValue;
1111 }
1112
1113 static
1114 INT32
1115 ProcessScript (
1116 IN OUT UINT8 *FileBuffer,
1117 IN FILE *Package,
1118 IN CHAR8 *BuildDirectory,
1119 IN BOOLEAN ForceUncompress
1120 )
1121 /*++
1122
1123 Routine Description:
1124
1125 Signs the section, data stays in same location
1126
1127 Arguments:
1128
1129 FileBuffer - Data Buffer
1130
1131 Package - Points to curly brace in Image Script
1132
1133 BuildDirectory - Name of the source directory parameter
1134
1135 ForceUncompress - Whether to force uncompress.
1136
1137 Returns:
1138
1139 Number of bytes added to file buffer
1140 -1 on error
1141
1142 --*/
1143 {
1144 EFI_STATUS Status;
1145 UINT32 Size;
1146 CHAR8 Buffer[_MAX_PATH];
1147 CHAR8 Type[_MAX_PATH];
1148 CHAR8 FileName[_MAX_PATH];
1149 CHAR8 NewBuffer[_MAX_PATH];
1150 INT32 Index3;
1151 INT32 Index2;
1152 UINT32 ReturnValue;
1153 UINT8 ByteBuffer;
1154 FILE *InFile;
1155 UINT32 SourceDataSize;
1156 CHAR8 *ToolArgumentsArray[MAX_ARRAY_SIZE];
1157 CHAR8 *OutputFileName;
1158 CHAR8 *InputFileName;
1159 CHAR8 ToolName[_MAX_PATH];
1160 FILE *OutputFile;
1161 FILE *InputFile;
1162 UINT8 Temp;
1163 int returnint;
1164 INT32 Index;
1165 UINT32 LineNumber;
1166 BOOLEAN IsError;
1167 EFI_GUID SignGuid;
1168 UINT16 GuidedSectionAttributes;
1169 UINT8 *TargetFileBuffer;
1170
1171 OutputFileName = NULL;
1172 InputFileName = NULL;
1173 OutputFile = NULL;
1174 InputFile = NULL;
1175 IsError = FALSE;
1176 GuidedSectionAttributes = 0;
1177 TargetFileBuffer = NULL;
1178
1179 Size = 0;
1180 LineNumber = 0;
1181 Buffer[0] = 0;
1182 for (Index3 = 0; Index3 < MAX_ARRAY_SIZE; ++Index3) {
1183 ToolArgumentsArray[Index3] = NULL;
1184 }
1185
1186 while (Buffer[0] != '}') {
1187 if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
1188 CheckSlash (Buffer, Package, &LineNumber);
1189 } else {
1190 printf ("ERROR in IMAGE SCRIPT!\n");
1191 IsError = TRUE;
1192 goto Done;
1193 }
1194
1195 if (strcmpi (Buffer, "Compress") == 0) {
1196 //
1197 // Handle compress
1198 //
1199 //
1200 // read compression type
1201 //
1202 if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
1203 CheckSlash (Buffer, Package, &LineNumber);
1204 }
1205
1206 StripParens (Buffer);
1207 if (Buffer[0] == '$') {
1208 ProcessEnvironmentVariable (&Buffer[0], Type);
1209 } else {
1210 strcpy (Type, Buffer);
1211 }
1212 //
1213 // build buffer
1214 //
1215 while (Buffer[0] != '{') {
1216 if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
1217 CheckSlash (Buffer, Package, &LineNumber);
1218 }
1219 }
1220
1221 ReturnValue = ProcessScript (&FileBuffer[Size], Package, BuildDirectory, ForceUncompress);
1222 if (ReturnValue == -1) {
1223 IsError = TRUE;
1224 goto Done;
1225 }
1226 //
1227 // Call compress routine on buffer.
1228 // Occasionally, compressed data + section header would
1229 // be largere than the source and EFI_BUFFER_TOO_SMALL is
1230 // returned from CompressSection()
1231 //
1232 SourceDataSize = ReturnValue;
1233
1234 if (!ForceUncompress) {
1235
1236 Status = CompressSection (
1237 &FileBuffer[Size],
1238 &ReturnValue,
1239 SourceDataSize,
1240 Type
1241 );
1242
1243 if (Status == EFI_BUFFER_TOO_SMALL) {
1244 Status = CompressSection (
1245 &FileBuffer[Size],
1246 &ReturnValue,
1247 SourceDataSize,
1248 Type
1249 );
1250 }
1251
1252 if (EFI_ERROR (Status)) {
1253 IsError = TRUE;
1254 goto Done;
1255 }
1256 }
1257
1258 Size += ReturnValue;
1259
1260 } else if (strcmpi (Buffer, "Tool") == 0) {
1261
1262 ZeroMem (ToolName, _MAX_PATH);
1263 ZeroMem (ToolArgumentsArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);
1264 ZeroMem (&SignGuid, sizeof (EFI_GUID));
1265
1266 //
1267 // handle signing Tool
1268 //
1269 while (Buffer[0] != '(') {
1270 if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
1271 CheckSlash (Buffer, Package, &LineNumber);
1272 }
1273 }
1274
1275 if (strcmpi (Buffer, "(") == 0) {
1276 if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
1277 CheckSlash (Buffer, Package, &LineNumber);
1278 }
1279 }
1280
1281 StripParens (Buffer);
1282
1283 if (Buffer[0] == '$') {
1284 Index = ProcessEnvironmentVariable (&Buffer[0], ToolName);
1285 //
1286 // if there is string after the environment variable, cat it.
1287 //
1288 if ((UINT32) Index < strlen (Buffer)) {
1289 strcat (ToolName, &Buffer[Index]);
1290 }
1291 } else {
1292 strcpy (ToolName, Buffer);
1293 }
1294
1295 ToolArgumentsArray[0] = ToolName;
1296
1297 //
1298 // read ARGS
1299 //
1300 if (GetToolArguments (
1301 ToolArgumentsArray,
1302 Package,
1303 &InputFileName,
1304 &OutputFileName,
1305 &SignGuid,
1306 &GuidedSectionAttributes
1307 ) == -1) {
1308 IsError = TRUE;
1309 goto Done;
1310 }
1311 //
1312 // if the tool need input file,
1313 // dump the file buffer to the specified input file.
1314 //
1315 if (InputFileName != NULL) {
1316 InputFile = fopen (InputFileName, "wb");
1317 if (InputFile == NULL) {
1318 Error (NULL, 0, 0, InputFileName, "failed to open output file for writing");
1319 IsError = TRUE;
1320 goto Done;
1321 }
1322
1323 fwrite (FileBuffer, sizeof (UINT8), Size, InputFile);
1324 fclose (InputFile);
1325 InputFile = NULL;
1326 free (InputFileName);
1327 InputFileName = NULL;
1328 }
1329 //
1330 // dispatch signing tool
1331 //
1332 #ifdef __GNUC__
1333 {
1334 char CommandLine[1000];
1335 sprintf(CommandLine, "%s %s", ToolName, ToolArgumentsArray);
1336 returnint = system(CommandLine);
1337 }
1338 #else
1339 returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray);
1340 #endif
1341 if (returnint != 0) {
1342 Error (NULL, 0, 0, ToolName, "external tool failed");
1343 IsError = TRUE;
1344 goto Done;
1345 }
1346 //
1347 // if the tool has output file,
1348 // dump the output file to the file buffer
1349 //
1350 if (OutputFileName != NULL) {
1351
1352 OutputFile = fopen (OutputFileName, "rb");
1353 if (OutputFile == NULL) {
1354 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
1355 IsError = TRUE;
1356 goto Done;
1357 }
1358
1359 TargetFileBuffer = &FileBuffer[Size];
1360 SourceDataSize = Size;
1361
1362 fread (&Temp, sizeof (UINT8), 1, OutputFile);
1363 while (!feof (OutputFile)) {
1364 FileBuffer[Size++] = Temp;
1365 fread (&Temp, sizeof (UINT8), 1, OutputFile);
1366 }
1367
1368 while ((Size & 0x03) != 0) {
1369 FileBuffer[Size] = 0;
1370 Size++;
1371 }
1372
1373 SourceDataSize = Size - SourceDataSize;
1374
1375 fclose (OutputFile);
1376 OutputFile = NULL;
1377 free (OutputFileName);
1378 OutputFileName = NULL;
1379
1380 if (CompareGuid (&SignGuid, &mZeroGuid) != 0) {
1381 ReturnValue = SourceDataSize;
1382 Status = GenSimpleGuidSection (
1383 TargetFileBuffer,
1384 &ReturnValue,
1385 SourceDataSize,
1386 SignGuid,
1387 GuidedSectionAttributes
1388 );
1389 if (EFI_ERROR (Status)) {
1390 IsError = TRUE;
1391 goto Done;
1392 }
1393
1394 Size = ReturnValue;
1395 }
1396 }
1397
1398 } else if (Buffer[0] != '}') {
1399 //
1400 // if we are here, we should see either a file name,
1401 // or a }.
1402 //
1403 Index3 = 0;
1404 FileName[0] = 0;
1405 //
1406 // Prepend the build directory to the file name if the
1407 // file name does not already contain a full path.
1408 //
1409 if (!isalpha (Buffer[0]) || (Buffer[1] != ':')) {
1410 sprintf (FileName, "%s\\", BuildDirectory);
1411 }
1412
1413 while (Buffer[Index3] != '\n') {
1414 if (Buffer[Index3] == '$') {
1415 Index3 += ProcessEnvironmentVariable (&Buffer[Index3], NewBuffer);
1416 strcat (FileName, NewBuffer);
1417 }
1418
1419 if (Buffer[Index3] == 0) {
1420 break;
1421 } else {
1422 Index2 = strlen (FileName);
1423 FileName[Index2++] = Buffer[Index3++];
1424 FileName[Index2] = 0;
1425 }
1426 }
1427
1428 InFile = fopen (FileName, "rb");
1429 if (InFile == NULL) {
1430 Error (NULL, 0, 0, FileName, "failed to open file for reading");
1431 IsError = TRUE;
1432 goto Done;
1433 }
1434
1435 fread (&ByteBuffer, sizeof (UINT8), 1, InFile);
1436 while (!feof (InFile)) {
1437 FileBuffer[Size++] = ByteBuffer;
1438 fread (&ByteBuffer, sizeof (UINT8), 1, InFile);
1439 }
1440
1441 fclose (InFile);
1442 InFile = NULL;
1443
1444 //
1445 // Make sure section ends on a DWORD boundary
1446 //
1447 while ((Size & 0x03) != 0) {
1448 FileBuffer[Size] = 0;
1449 Size++;
1450 }
1451
1452 }
1453 }
1454
1455 Done:
1456 for (Index3 = 1; Index3 < MAX_ARRAY_SIZE; Index3++) {
1457 if (ToolArgumentsArray[Index3] == NULL) {
1458 break;
1459 }
1460
1461 free (ToolArgumentsArray[Index3]);
1462 }
1463
1464 if (IsError) {
1465 return -1;
1466 }
1467
1468 return Size;
1469
1470 }
1471
1472 static
1473 UINT8
1474 StringToType (
1475 IN CHAR8 *String
1476 )
1477 /*++
1478
1479 Routine Description:
1480
1481 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
1482 unrecognized file type was specified.
1483
1484 Arguments:
1485
1486 String - File type string
1487
1488 Returns:
1489
1490 File Type Value
1491
1492 --*/
1493 {
1494 if (strcmpi (String, "EFI_FV_FILETYPE_RAW") == 0) {
1495 return EFI_FV_FILETYPE_RAW;
1496 }
1497
1498 if (strcmpi (String, "EFI_FV_FILETYPE_FREEFORM") == 0) {
1499 return EFI_FV_FILETYPE_FREEFORM;
1500 }
1501
1502 if (strcmpi (String, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
1503 return EFI_FV_FILETYPE_SECURITY_CORE;
1504 }
1505
1506 if (strcmpi (String, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
1507 return EFI_FV_FILETYPE_PEI_CORE;
1508 }
1509
1510 if (strcmpi (String, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
1511 return EFI_FV_FILETYPE_DXE_CORE;
1512 }
1513
1514 if (strcmpi (String, "EFI_FV_FILETYPE_PEIM") == 0) {
1515 return EFI_FV_FILETYPE_PEIM;
1516 }
1517
1518 if (strcmpi (String, "EFI_FV_FILETYPE_DRIVER") == 0) {
1519 return EFI_FV_FILETYPE_DRIVER;
1520 }
1521
1522 if (strcmpi (String, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
1523 return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER;
1524 }
1525
1526 if (strcmpi (String, "EFI_FV_FILETYPE_APPLICATION") == 0) {
1527 return EFI_FV_FILETYPE_APPLICATION;
1528 }
1529
1530 if (strcmpi (String, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
1531 return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;
1532 }
1533
1534 return EFI_FV_FILETYPE_ALL;
1535 }
1536
1537 static
1538 UINT32
1539 AdjustFileSize (
1540 IN UINT8 *FileBuffer,
1541 IN UINT32 FileSize
1542 )
1543 /*++
1544
1545 Routine Description:
1546 Adjusts file size to insure sectioned file is exactly the right length such
1547 that it ends on exactly the last byte of the last section. ProcessScript()
1548 may have padded beyond the end of the last section out to a 4 byte boundary.
1549 This padding is stripped.
1550
1551 Arguments:
1552 FileBuffer - Data Buffer - contains a section stream
1553 FileSize - Size of FileBuffer as returned from ProcessScript()
1554
1555 Returns:
1556 Corrected size of file.
1557
1558 --*/
1559 {
1560 UINT32 TotalLength;
1561 UINT32 CurrentLength;
1562 UINT32 SectionLength;
1563 UINT32 SectionStreamLength;
1564 EFI_COMMON_SECTION_HEADER *SectionHeader;
1565 EFI_COMMON_SECTION_HEADER *NextSectionHeader;
1566
1567 TotalLength = 0;
1568 CurrentLength = 0;
1569 SectionStreamLength = FileSize;
1570
1571 SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileBuffer;
1572
1573 while (TotalLength < SectionStreamLength) {
1574 SectionLength = *((UINT32 *) SectionHeader->Size) & 0x00ffffff;
1575 TotalLength += SectionLength;
1576
1577 if (TotalLength == SectionStreamLength) {
1578 return TotalLength;
1579 }
1580 //
1581 // Move to the next byte following the section...
1582 //
1583 SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);
1584 CurrentLength = (UINTN) SectionHeader - (UINTN) FileBuffer;
1585
1586 //
1587 // Figure out where the next section begins
1588 //
1589 NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + 3);
1590 NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader &~ (UINTN) 3);
1591 TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;
1592 SectionHeader = NextSectionHeader;
1593 }
1594
1595 return CurrentLength;
1596 }
1597
1598 static
1599 INT32
1600 MainEntry (
1601 INT32 argc,
1602 CHAR8 *argv[],
1603 BOOLEAN ForceUncompress
1604 )
1605 /*++
1606
1607 Routine Description:
1608
1609 MainEntry function.
1610
1611 Arguments:
1612
1613 argc - Number of command line parameters.
1614 argv - Array of pointers to command line parameter strings.
1615 ForceUncompress - If TRUE, force to do not compress the sections even if compression
1616 is specified in the script. Otherwise, FALSE.
1617
1618 Returns:
1619 STATUS_SUCCESS - Function exits successfully.
1620 STATUS_ERROR - Some error occurred during execution.
1621
1622 --*/
1623 {
1624 FILE *PrimaryPackage;
1625 FILE *OverridePackage;
1626 FILE *Out;
1627 CHAR8 BaseName[_MAX_PATH];
1628 EFI_GUID FfsGuid;
1629 CHAR8 GuidString[_MAX_PATH];
1630 EFI_FFS_FILE_HEADER FileHeader;
1631 CHAR8 FileType[_MAX_PATH];
1632 EFI_FFS_FILE_ATTRIBUTES FfsAttrib;
1633 EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined;
1634 UINT64 FfsAlignment;
1635 UINT32 FfsAlignment32;
1636 CHAR8 InputString[_MAX_PATH];
1637 BOOLEAN ImageScriptInOveride;
1638 UINT32 FileSize;
1639 UINT8 *FileBuffer;
1640 EFI_STATUS Status;
1641 UINT32 LineNumber;
1642 EFI_FFS_FILE_TAIL TailValue;
1643
1644 BaseName[0] = 0;
1645 FileType[0] = 0;
1646 FfsAttrib = 0;
1647 FfsAttribDefined = 0;
1648 FfsAlignment = 0;
1649 FfsAlignment32 = 0;
1650 PrimaryPackage = NULL;
1651 Out = NULL;
1652 OverridePackage = NULL;
1653 FileBuffer = NULL;
1654
1655 strcpy (GuidString, "00000000-0000-0000-0000-000000000000");
1656 Status = StringToGuid (GuidString, &FfsGuid);
1657 if (Status != 0) {
1658 Error (NULL, 0, 0, GuidString, "error parsing GUID string");
1659 return STATUS_ERROR;
1660 }
1661
1662 GuidString[0] = 0;
1663 ImageScriptInOveride = FALSE;
1664 //
1665 // Initialize the simple file parsing routines. Then open
1666 // the primary package file for parsing.
1667 //
1668 SFPInit ();
1669 if (SFPOpenFile (mGlobals.PrimaryPackagePath) != STATUS_SUCCESS) {
1670 Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");
1671 goto Done;
1672 }
1673 //
1674 // First token in the file must be "PACKAGE.INF"
1675 //
1676 if (!SFPIsToken ("PACKAGE.INF")) {
1677 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL);
1678 goto Done;
1679 }
1680 //
1681 // Find the [.] section
1682 //
1683 if (!SFPSkipToToken ("[.]")) {
1684 Error (mGlobals.PrimaryPackagePath, 1, 0, "could not locate [.] section in package file", NULL);
1685 goto Done;
1686 }
1687 //
1688 // Start parsing the data. The algorithm is essentially the same for each keyword:
1689 // 1. Identify the keyword
1690 // 2. Verify that the keyword/value pair has not already been defined
1691 // 3. Set some flag indicating that the keyword/value pair has been defined
1692 // 4. Skip over the "="
1693 // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
1694 //
1695 while (1) {
1696 if (SFPIsToken ("BASE_NAME")) {
1697 //
1698 // Found BASE_NAME, format:
1699 // BASE_NAME = MyBaseName
1700 //
1701 if (BaseName[0] != 0) {
1702 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL);
1703 goto Done;
1704 }
1705
1706 if (!SFPIsToken ("=")) {
1707 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1708 goto Done;
1709 }
1710
1711 if (!SFPGetNextToken (BaseName, sizeof (BaseName))) {
1712 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid base name", NULL);
1713 goto Done;
1714 }
1715 } else if (SFPIsToken ("IMAGE_SCRIPT")) {
1716 //
1717 // Found IMAGE_SCRIPT. Break out and process below.
1718 //
1719 break;
1720 } else if (SFPIsToken ("FFS_FILEGUID")) {
1721 //
1722 // found FILEGUID, format:
1723 // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
1724 //
1725 if (GuidString[0] != 0) {
1726 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL);
1727 goto Done;
1728 }
1729
1730 if (!SFPIsToken ("=")) {
1731 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1732 goto Done;
1733 }
1734
1735 if (SFPGetGuidToken (GuidString, sizeof (GuidString)) != TRUE) {
1736 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected file GUID", NULL);
1737 goto Done;
1738 }
1739
1740 Status = StringToGuid (GuidString, &FfsGuid);
1741 if (Status != 0) {
1742 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid file GUID", NULL);
1743 goto Done;
1744 }
1745 } else if (SFPIsToken ("FFS_FILETYPE")) {
1746 //
1747 // ***********************************************************************
1748 //
1749 // Found FFS_FILETYPE, format:
1750 // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
1751 //
1752 if (FileType[0] != 0) {
1753 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL);
1754 goto Done;
1755 }
1756
1757 if (!SFPIsToken ("=")) {
1758 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1759 goto Done;
1760 }
1761
1762 if (!SFPGetNextToken (FileType, sizeof (FileType))) {
1763 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL);
1764 goto Done;
1765 }
1766 } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
1767 //
1768 // ***********************************************************************
1769 //
1770 // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
1771 // Spec says the bit is for future expansion, and must be false.
1772 //
1773 if (FfsAttribDefined & FFS_ATTRIB_HEADER_EXTENSION) {
1774 Error (
1775 mGlobals.PrimaryPackagePath,
1776 SFPGetLineNumber (),
1777 0,
1778 "FFS_ATTRIB_HEADER_EXTENSION previously defined",
1779 NULL
1780 );
1781 goto Done;
1782 }
1783
1784 FfsAttribDefined |= FFS_ATTRIB_HEADER_EXTENSION;
1785 if (!SFPIsToken ("=")) {
1786 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1787 goto Done;
1788 }
1789
1790 if (SFPIsToken ("TRUE")) {
1791 Error (
1792 mGlobals.PrimaryPackagePath,
1793 SFPGetLineNumber (),
1794 0,
1795 "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
1796 NULL
1797 );
1798 goto Done;
1799 } else if (SFPIsToken ("FALSE")) {
1800 //
1801 // Default is FALSE
1802 //
1803 } else {
1804 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL);
1805 goto Done;
1806 }
1807 } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
1808 //
1809 // ***********************************************************************
1810 //
1811 // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
1812 //
1813 if (FfsAttribDefined & FFS_ATTRIB_TAIL_PRESENT) {
1814 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL);
1815 goto Done;
1816 }
1817
1818 FfsAttribDefined |= FFS_ATTRIB_TAIL_PRESENT;
1819 if (!SFPIsToken ("=")) {
1820 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1821 goto Done;
1822 }
1823
1824 if (SFPIsToken ("TRUE")) {
1825 FfsAttrib |= FFS_ATTRIB_TAIL_PRESENT;
1826 } else if (SFPIsToken ("FALSE")) {
1827 //
1828 // Default is FALSE
1829 //
1830 } else {
1831 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
1832 goto Done;
1833 }
1834 } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
1835 //
1836 // ***********************************************************************
1837 //
1838 // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
1839 //
1840 if (FfsAttribDefined & FFS_ATTRIB_RECOVERY) {
1841 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL);
1842 goto Done;
1843 }
1844
1845 FfsAttribDefined |= FFS_ATTRIB_RECOVERY;
1846 if (!SFPIsToken ("=")) {
1847 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1848 goto Done;
1849 }
1850
1851 if (SFPIsToken ("TRUE")) {
1852 FfsAttrib |= FFS_ATTRIB_RECOVERY;
1853 } else if (SFPIsToken ("FALSE")) {
1854 //
1855 // Default is FALSE
1856 //
1857 } else {
1858 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
1859 goto Done;
1860 }
1861 } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
1862 //
1863 // ***********************************************************************
1864 //
1865 // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
1866 //
1867 if (FfsAttribDefined & FFS_ATTRIB_CHECKSUM) {
1868 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL);
1869 goto Done;
1870 }
1871
1872 FfsAttribDefined |= FFS_ATTRIB_CHECKSUM;
1873 if (!SFPIsToken ("=")) {
1874 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1875 goto Done;
1876 }
1877
1878 if (SFPIsToken ("TRUE")) {
1879 FfsAttrib |= FFS_ATTRIB_CHECKSUM;
1880 } else if (SFPIsToken ("FALSE")) {
1881 //
1882 // Default is FALSE
1883 //
1884 } else {
1885 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
1886 goto Done;
1887 }
1888 } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
1889 //
1890 // ***********************************************************************
1891 //
1892 // Found FFS_ALIGNMENT, formats:
1893 // FFS_ALIGNMENT = 0-7
1894 // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
1895 //
1896 if (FfsAttribDefined & FFS_ATTRIB_DATA_ALIGNMENT) {
1897 Error (
1898 mGlobals.PrimaryPackagePath,
1899 SFPGetLineNumber (),
1900 0,
1901 "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
1902 NULL
1903 );
1904 goto Done;
1905 }
1906
1907 FfsAttribDefined |= FFS_ATTRIB_DATA_ALIGNMENT;
1908 if (!SFPIsToken ("=")) {
1909 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
1910 goto Done;
1911 }
1912
1913 if (!SFPGetNumber (&FfsAlignment32)) {
1914 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL);
1915 goto Done;
1916 }
1917
1918 if (FfsAlignment32 > 7) {
1919 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL);
1920 goto Done;
1921 }
1922
1923 FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment32) << 3);
1924 } else {
1925 SFPGetNextToken (InputString, sizeof (InputString));
1926 Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, InputString, "unrecognized/unexpected token");
1927 goto Done;
1928 }
1929 }
1930 //
1931 // Close the primary package file
1932 //
1933 SFPCloseFile ();
1934 //
1935 // TODO: replace code below with basically a copy of the code above. Don't
1936 // forget to reset the FfsAttribDefined variable first. Also, you'll need
1937 // to somehow keep track of whether or not the basename is defined multiple
1938 // times in the override package. Ditto on the file GUID.
1939 //
1940 if (mGlobals.OverridePackagePath[0] != 0) {
1941 OverridePackage = fopen (mGlobals.OverridePackagePath, "r");
1942 //
1943 // NOTE: For package override to work correctly, the code below must be modified to
1944 // SET or CLEAR bits properly. For example, if the primary package set
1945 // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
1946 // we'd need to clear the bit below. Since this is not happening, I'm guessing that
1947 // the override functionality is not being used, so should be made obsolete. If I'm
1948 // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
1949 // used, and we'll address it then. 4/10/2003
1950 //
1951 Error (__FILE__, __LINE__, 0, "package override functionality is not implemented correctly", NULL);
1952 goto Done;
1953 } else {
1954 OverridePackage = NULL;
1955 }
1956
1957 #ifdef OVERRIDE_SUPPORTED
1958 if (OverridePackage != NULL) {
1959 //
1960 // Parse override package file
1961 //
1962 fscanf (OverridePackage, "%s", &InputString);
1963 if (strcmpi (InputString, "PACKAGE.INF") != 0) {
1964 Error (mGlobals.OverridePackagePath, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
1965 goto Done;
1966 }
1967 //
1968 // Match [dir] to Build Directory
1969 //
1970 if (FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber) != 0) {
1971 Error (mGlobals.OverridePackagePath, 1, 0, mGlobals.BuildDirectory, "section not found in package file");
1972 goto Done;
1973 }
1974
1975 InputString[0] = 0;
1976 while ((InputString[0] != '[') && (!feof (OverridePackage))) {
1977 if (GetNextLine (InputString, OverridePackage, &LineNumber) != -1) {
1978 if (InputString[0] != '[') {
1979 here:
1980 if (strcmpi (InputString, "BASE_NAME") == 0) {
1981 //
1982 // found BASE_NAME, next is = and string.
1983 //
1984 fscanf (OverridePackage, "%s", &InputString);
1985 CheckSlash (InputString, OverridePackage, &LineNumber);
1986 if (strlen (InputString) == 1) {
1987 //
1988 // string is just =
1989 //
1990 fscanf (OverridePackage, "%s", &InputString);
1991 CheckSlash (InputString, OverridePackage, &LineNumber);
1992 strcpy (BaseName, InputString);
1993 } else {
1994 BreakString (InputString, InputString, 1);
1995 strcpy (BaseName, InputString);
1996 }
1997 } else if (strcmpi (InputString, "IMAGE_SCRIPT") == 0) {
1998 //
1999 // found IMAGE_SCRIPT, come back later to process it
2000 //
2001 ImageScriptInOveride = TRUE;
2002 fscanf (OverridePackage, "%s", &InputString);
2003 } else if (strcmpi (InputString, "FFS_FILEGUID") == 0) {
2004 //
2005 // found FILEGUID, next is = and string.
2006 //
2007 fscanf (OverridePackage, "%s", &InputString);
2008 CheckSlash (InputString, OverridePackage, &LineNumber);
2009 if (strlen (InputString) == 1) {
2010 //
2011 // string is just =
2012 //
2013 fscanf (OverridePackage, "%s", &InputString);
2014 CheckSlash (InputString, OverridePackage, &LineNumber);
2015 Status = StringToGuid (InputString, &FfsGuid);
2016 if (Status != 0) {
2017 Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");
2018 goto Done;
2019 }
2020 } else {
2021 BreakString (InputString, InputString, 1);
2022 Status = StringToGuid (InputString, &FfsGuid);
2023 if (Status != 0) {
2024 Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");
2025 goto Done;
2026 }
2027 }
2028 } else if (strcmpi (InputString, "FFS_FILETYPE") == 0) {
2029 //
2030 // found FILETYPE, next is = and string.
2031 //
2032 fscanf (OverridePackage, "%s", &InputString);
2033 CheckSlash (InputString, OverridePackage, &LineNumber);
2034 if (strlen (InputString) == 1) {
2035 //
2036 // string is just =
2037 //
2038 fscanf (OverridePackage, "%s", &InputString);
2039 CheckSlash (InputString, OverridePackage, &LineNumber);
2040 strcpy (FileType, InputString);
2041 } else {
2042 BreakString (InputString, InputString, 1);
2043 strcpy (FileType, InputString);
2044 }
2045
2046 } else if (strcmpi (InputString, "FFS_ATTRIB_RECOVERY") == 0) {
2047 //
2048 // found FFS_ATTRIB_RECOVERY, next is = and string.
2049 //
2050 fscanf (OverridePackage, "%s", &InputString);
2051 CheckSlash (InputString, OverridePackage, &LineNumber);
2052 if (strlen (InputString) == 1) {
2053 //
2054 // string is just =
2055 //
2056 fscanf (OverridePackage, "%s", &InputString);
2057 CheckSlash (InputString, OverridePackage, &LineNumber);
2058 if (strcmpi (InputString, "TRUE") == 0) {
2059 FfsAttrib |= FFS_ATTRIB_RECOVERY;
2060 }
2061 } else {
2062 BreakString (InputString, InputString, 1);
2063 if (strcmpi (InputString, "TRUE") == 0) {
2064 FfsAttrib |= FFS_ATTRIB_RECOVERY;
2065 }
2066 }
2067 } else if (strcmpi (InputString, "FFS_ATTRIB_CHECKSUM") == 0) {
2068 //
2069 // found FFS_ATTRIB_CHECKSUM, next is = and string.
2070 //
2071 fscanf (OverridePackage, "%s", &InputString);
2072 CheckSlash (InputString, OverridePackage, &LineNumber);
2073 if (strlen (InputString) == 1) {
2074 //
2075 // string is just =
2076 //
2077 fscanf (OverridePackage, "%s", &InputString);
2078 CheckSlash (InputString, OverridePackage, &LineNumber);
2079 if (strcmpi (InputString, "TRUE") == 0) {
2080 FfsAttrib |= FFS_ATTRIB_CHECKSUM;
2081 }
2082 } else {
2083 BreakString (InputString, InputString, 1);
2084 if (strcmpi (InputString, "TRUE") == 0) {
2085 FfsAttrib |= FFS_ATTRIB_CHECKSUM;
2086 }
2087 }
2088 } else if (strcmpi (InputString, "FFS_ALIGNMENT") == 0) {
2089 //
2090 // found FFS_ALIGNMENT, next is = and string.
2091 //
2092 fscanf (OverridePackage, "%s", &InputString);
2093 CheckSlash (InputString, OverridePackage, &LineNumber);
2094 if (strlen (InputString) == 1) {
2095 //
2096 // string is just =
2097 //
2098 fscanf (OverridePackage, "%s", &InputString);
2099 CheckSlash (InputString, OverridePackage, &LineNumber);
2100 } else {
2101 BreakString (InputString, InputString, 1);
2102 }
2103
2104 AsciiStringToUint64 (InputString, FALSE, &FfsAlignment);
2105 if (FfsAlignment > 7) {
2106 Error (mGlobals.OverridePackagePath, 1, 0, InputString, "invalid FFS_ALIGNMENT value");
2107 goto Done;
2108 }
2109
2110 FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment) << 3);
2111 } else if (strchr (InputString, '=') != NULL) {
2112 BreakString (InputString, String, 1);
2113 fseek (OverridePackage, (-1 * (strlen (String) + 1)), SEEK_CUR);
2114 BreakString (InputString, InputString, 0);
2115 goto here;
2116 }
2117 }
2118 }
2119 }
2120 }
2121 #endif // #ifdef OVERRIDE_SUPPORTED
2122 //
2123 // Require that they specified a file GUID at least, since that's how we're
2124 // naming the file.
2125 //
2126 if (GuidString[0] == 0) {
2127 Error (mGlobals.PrimaryPackagePath, 1, 0, "FFS_FILEGUID must be specified", NULL);
2128 return STATUS_ERROR;
2129 }
2130 //
2131 // Build Header and process image script
2132 //
2133 FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 16) * sizeof (UINT8));
2134 if (FileBuffer == NULL) {
2135 Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);
2136 goto Done;
2137 }
2138
2139 FileSize = 0;
2140 if (ImageScriptInOveride) {
2141 #ifdef OVERRIDE_SUPORTED
2142 rewind (OverridePackage);
2143 LineNumber = 0;
2144 FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber);
2145 while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {
2146 GetNextLine (InputString, OverridePackage, &LineNumber);
2147 CheckSlash (InputString, OverridePackage, &LineNumber);
2148 if (strchr (InputString, '=') != NULL) {
2149 BreakString (InputString, InputString, 0);
2150 }
2151 }
2152
2153 while (InputString[0] != '{') {
2154 GetNextLine (InputString, OverridePackage, &LineNumber);
2155 CheckSlash (InputString, OverridePackage, &LineNumber);
2156 }
2157 //
2158 // Found start of image script, process it
2159 //
2160 FileSize += ProcessScript (FileBuffer, OverridePackage, mGlobals.BuildDirectory, ForceUncompress);
2161 if (FileSize == -1) {
2162 return -1;
2163 }
2164
2165 if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {
2166 FileSize = AdjustFileSize (FileBuffer, FileSize);
2167 }
2168
2169 if (BaseName[0] == '\"') {
2170 StripQuotes (BaseName);
2171 }
2172
2173 if (BaseName[0] != 0) {
2174 sprintf (InputString, "%s-%s", GuidString, BaseName);
2175 } else {
2176 strcpy (InputString, GuidString);
2177 }
2178
2179 switch (StringToType (FileType)) {
2180
2181 case EFI_FV_FILETYPE_SECURITY_CORE:
2182 strcat (InputString, ".SEC");
2183 break;
2184
2185 case EFI_FV_FILETYPE_PEIM:
2186 case EFI_FV_FILETYPE_PEI_CORE:
2187 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
2188 strcat (InputString, ".PEI");
2189 break;
2190
2191 case EFI_FV_FILETYPE_DRIVER:
2192 case EFI_FV_FILETYPE_DXE_CORE:
2193 strcat (InputString, ".DXE");
2194 break;
2195
2196 case EFI_FV_FILETYPE_APPLICATION:
2197 strcat (InputString, ".APP");
2198 break;
2199
2200 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
2201 strcat (InputString, ".FVI");
2202 break;
2203
2204 case EFI_FV_FILETYPE_ALL:
2205 Error (mGlobals.OverridePackagePath, 1, 0, "invalid FFS file type for this utility", NULL);
2206 goto Done;
2207
2208 default:
2209 strcat (InputString, ".FFS");
2210 break;
2211 }
2212
2213 if (ForceUncompress) {
2214 strcat (InputString, ".ORG");
2215 }
2216
2217 Out = fopen (InputString, "wb");
2218 if (Out == NULL) {
2219 Error (NULL, 0, 0, InputString, "could not open output file for writing");
2220 goto Done;
2221 }
2222 //
2223 // create ffs header
2224 //
2225 memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
2226 memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));
2227 FileHeader.Type = StringToType (FileType);
2228 FileHeader.Attributes = FfsAttrib;
2229 //
2230 // Now FileSize includes the EFI_FFS_FILE_HEADER
2231 //
2232 FileSize += sizeof (EFI_FFS_FILE_HEADER);
2233 FileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
2234 FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
2235 FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
2236 //
2237 // Fill in checksums and state, these must be zero for checksumming
2238 //
2239 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2240 // FileHeader.IntegrityCheck.Checksum.File = 0;
2241 // FileHeader.State = 0;
2242 //
2243 FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
2244 (UINT8 *) &FileHeader,
2245 sizeof (EFI_FFS_FILE_HEADER)
2246 );
2247 if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
2248 FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) &FileHeader, FileSize);
2249 } else {
2250 FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2251 }
2252
2253 FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
2254 //
2255 // write header
2256 //
2257 if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {
2258 Error (NULL, 0, 0, "failed to write file header to output file", NULL);
2259 goto Done;
2260 }
2261 //
2262 // write data
2263 //
2264 if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {
2265 Error (NULL, 0, 0, "failed to write all bytes to output file", NULL);
2266 goto Done;
2267 }
2268
2269 fclose (Out);
2270 Out = NULL;
2271 #endif // #ifdef OVERRIDE_SUPPORTED
2272 } else {
2273 //
2274 // Open primary package file and process the IMAGE_SCRIPT section
2275 //
2276 PrimaryPackage = fopen (mGlobals.PrimaryPackagePath, "r");
2277 if (PrimaryPackage == NULL) {
2278 Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");
2279 goto Done;
2280 }
2281
2282 LineNumber = 1;
2283 FindSectionInPackage (".", PrimaryPackage, &LineNumber);
2284 while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {
2285 GetNextLine (InputString, PrimaryPackage, &LineNumber);
2286 CheckSlash (InputString, PrimaryPackage, &LineNumber);
2287 if (strchr (InputString, '=') != NULL) {
2288 BreakString (InputString, InputString, 0);
2289 }
2290 }
2291
2292 while (InputString[0] != '{') {
2293 GetNextLine (InputString, PrimaryPackage, &LineNumber);
2294 CheckSlash (InputString, PrimaryPackage, &LineNumber);
2295 }
2296 //
2297 // Found start of image script, process it
2298 //
2299 FileSize += ProcessScript (FileBuffer, PrimaryPackage, mGlobals.BuildDirectory, ForceUncompress);
2300 if (FileSize == -1) {
2301 goto Done;
2302 }
2303
2304 if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {
2305 FileSize = AdjustFileSize (FileBuffer, FileSize);
2306 }
2307
2308 if (BaseName[0] == '\"') {
2309 StripQuotes (BaseName);
2310 }
2311
2312 if (BaseName[0] != 0) {
2313 sprintf (InputString, "%s-%s", GuidString, BaseName);
2314 } else {
2315 strcpy (InputString, GuidString);
2316 }
2317
2318 switch (StringToType (FileType)) {
2319
2320 case EFI_FV_FILETYPE_SECURITY_CORE:
2321 strcat (InputString, ".SEC");
2322 break;
2323
2324 case EFI_FV_FILETYPE_PEIM:
2325 case EFI_FV_FILETYPE_PEI_CORE:
2326 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
2327 strcat (InputString, ".PEI");
2328 break;
2329
2330 case EFI_FV_FILETYPE_DRIVER:
2331 case EFI_FV_FILETYPE_DXE_CORE:
2332 strcat (InputString, ".DXE");
2333 break;
2334
2335 case EFI_FV_FILETYPE_APPLICATION:
2336 strcat (InputString, ".APP");
2337 break;
2338
2339 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
2340 strcat (InputString, ".FVI");
2341 break;
2342
2343 case EFI_FV_FILETYPE_ALL:
2344 Error (mGlobals.PrimaryPackagePath, 1, 0, "invalid FFS file type for this utility", NULL);
2345 goto Done;
2346
2347 default:
2348 strcat (InputString, ".FFS");
2349 break;
2350 }
2351
2352 if (ForceUncompress) {
2353 strcat (InputString, ".ORG");
2354 }
2355
2356 Out = fopen (InputString, "wb");
2357 if (Out == NULL) {
2358 Error (NULL, 0, 0, InputString, "failed to open output file for writing");
2359 goto Done;
2360 }
2361 //
2362 // Initialize the FFS file header
2363 //
2364 memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
2365 memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));
2366 FileHeader.Type = StringToType (FileType);
2367 FileHeader.Attributes = FfsAttrib;
2368 //
2369 // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
2370 //
2371 FileSize += sizeof (EFI_FFS_FILE_HEADER);
2372 //
2373 // If using a tail, then it adds two bytes
2374 //
2375 if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2376 //
2377 // Tail is not allowed for pad and 0-length files
2378 //
2379 if ((FileHeader.Type == EFI_FV_FILETYPE_FFS_PAD) || (FileSize == sizeof (EFI_FFS_FILE_HEADER))) {
2380 Error (
2381 mGlobals.PrimaryPackagePath,
2382 1,
2383 0,
2384 "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
2385 NULL
2386 );
2387 goto Done;
2388 }
2389
2390 FileSize += sizeof (EFI_FFS_FILE_TAIL);
2391 }
2392
2393 FileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
2394 FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
2395 FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
2396 //
2397 // Fill in checksums and state, they must be 0 for checksumming.
2398 //
2399 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2400 // FileHeader.IntegrityCheck.Checksum.File = 0;
2401 // FileHeader.State = 0;
2402 //
2403 FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
2404 (UINT8 *) &FileHeader,
2405 sizeof (EFI_FFS_FILE_HEADER)
2406 );
2407 if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
2408 //
2409 // Cheating here. Since the header checksums, just calculate the checksum of the body.
2410 // Checksum does not include the tail
2411 //
2412 if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2413 FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
2414 FileBuffer,
2415 FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL)
2416 );
2417 } else {
2418 FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
2419 FileBuffer,
2420 FileSize - sizeof (EFI_FFS_FILE_HEADER)
2421 );
2422 }
2423 } else {
2424 FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2425 }
2426 //
2427 // Set the state now. Spec says the checksum assumes the state is 0
2428 //
2429 FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
2430 //
2431 // If there is a tail, then set it
2432 //
2433 if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2434 TailValue = FileHeader.IntegrityCheck.TailReference;
2435 TailValue = (UINT16) (~TailValue);
2436 memcpy (
2437 (UINT8 *) FileBuffer + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL),
2438 &TailValue,
2439 sizeof (TailValue)
2440 );
2441 }
2442 //
2443 // Write the FFS file header
2444 //
2445 if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {
2446 Error (NULL, 0, 0, "failed to write file header contents", NULL);
2447 goto Done;
2448 }
2449 //
2450 // Write data
2451 //
2452 if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {
2453 Error (NULL, 0, 0, "failed to write file contents", NULL);
2454 goto Done;
2455 }
2456 }
2457
2458 Done:
2459 SFPCloseFile ();
2460 if (Out != NULL) {
2461 fclose (Out);
2462 }
2463
2464 if (PrimaryPackage != NULL) {
2465 fclose (PrimaryPackage);
2466 }
2467
2468 if (FileBuffer != NULL) {
2469 free (FileBuffer);
2470 }
2471
2472 if (OverridePackage != NULL) {
2473 fclose (OverridePackage);
2474 }
2475
2476 return GetUtilityStatus ();
2477 }
2478
2479 int
2480 main (
2481 INT32 argc,
2482 CHAR8 *argv[]
2483 )
2484 /*++
2485
2486 Routine Description:
2487
2488 Main function.
2489
2490 Arguments:
2491
2492 argc - Number of command line parameters.
2493 argv - Array of pointers to parameter strings.
2494
2495 Returns:
2496 STATUS_SUCCESS - Utility exits successfully.
2497 STATUS_ERROR - Some error occurred during execution.
2498
2499 --*/
2500 {
2501 STATUS Status;
2502 //
2503 // Set the name of our utility for error reporting purposes.
2504 //
2505 SetUtilityName (UTILITY_NAME);
2506 Status = ProcessCommandLineArgs (argc, argv);
2507 if (Status != STATUS_SUCCESS) {
2508 return Status;
2509 }
2510
2511 Status = MainEntry (argc, argv, TRUE);
2512 if (Status == STATUS_SUCCESS) {
2513 MainEntry (argc, argv, FALSE);
2514 }
2515 //
2516 // If any errors were reported via the standard error reporting
2517 // routines, then the status has been saved. Get the value and
2518 // return it to the caller.
2519 //
2520 return GetUtilityStatus ();
2521 }
2522
2523 static
2524 STATUS
2525 ProcessCommandLineArgs (
2526 int Argc,
2527 char *Argv[]
2528 )
2529 /*++
2530
2531 Routine Description:
2532 Process the command line arguments.
2533
2534 Arguments:
2535 Argc - as passed in to main()
2536 Argv - as passed in to main()
2537
2538 Returns:
2539 STATUS_SUCCESS - arguments all ok
2540 STATUS_ERROR - problem with args, so caller should exit
2541
2542 --*/
2543 {
2544 //
2545 // If no args, then print usage instructions and return an error
2546 //
2547 if (Argc == 1) {
2548 PrintUsage ();
2549 return STATUS_ERROR;
2550 }
2551
2552 memset (&mGlobals, 0, sizeof (mGlobals));
2553 Argc--;
2554 Argv++;
2555 while (Argc > 0) {
2556 if (strcmpi (Argv[0], "-b") == 0) {
2557 //
2558 // OPTION: -b BuildDirectory
2559 // Make sure there is another argument, then save it to our globals.
2560 //
2561 if (Argc < 2) {
2562 Error (NULL, 0, 0, "-b option requires the build directory name", NULL);
2563 return STATUS_ERROR;
2564 }
2565
2566 if (mGlobals.BuildDirectory[0]) {
2567 Error (NULL, 0, 0, Argv[0], "option can only be specified once");
2568 return STATUS_ERROR;
2569 }
2570
2571 strcpy (mGlobals.BuildDirectory, Argv[1]);
2572 Argc--;
2573 Argv++;
2574 } else if (strcmpi (Argv[0], "-p1") == 0) {
2575 //
2576 // OPTION: -p1 PrimaryPackageFile
2577 // Make sure there is another argument, then save it to our globals.
2578 //
2579 if (Argc < 2) {
2580 Error (NULL, 0, 0, Argv[0], "option requires the primary package file name");
2581 return STATUS_ERROR;
2582 }
2583
2584 if (mGlobals.PrimaryPackagePath[0]) {
2585 Error (NULL, 0, 0, Argv[0], "option can only be specified once");
2586 return STATUS_ERROR;
2587 }
2588
2589 strcpy (mGlobals.PrimaryPackagePath, Argv[1]);
2590 Argc--;
2591 Argv++;
2592 } else if (strcmpi (Argv[0], "-p2") == 0) {
2593 //
2594 // OPTION: -p2 OverridePackageFile
2595 // Make sure there is another argument, then save it to our globals.
2596 //
2597 if (Argc < 2) {
2598 Error (NULL, 0, 0, Argv[0], "option requires the override package file name");
2599 return STATUS_ERROR;
2600 }
2601
2602 if (mGlobals.OverridePackagePath[0]) {
2603 Error (NULL, 0, 0, Argv[0], "option can only be specified once");
2604 return STATUS_ERROR;
2605 }
2606
2607 strcpy (mGlobals.OverridePackagePath, Argv[1]);
2608 Argc--;
2609 Argv++;
2610 } else if (strcmpi (Argv[0], "-v") == 0) {
2611 //
2612 // OPTION: -v verbose
2613 //
2614 mGlobals.Verbose = TRUE;
2615 } else if (strcmpi (Argv[0], "-h") == 0) {
2616 //
2617 // OPTION: -h help
2618 //
2619 PrintUsage ();
2620 return STATUS_ERROR;
2621 } else if (strcmpi (Argv[0], "-?") == 0) {
2622 //
2623 // OPTION: -? help
2624 //
2625 PrintUsage ();
2626 return STATUS_ERROR;
2627 } else {
2628 Error (NULL, 0, 0, Argv[0], "unrecognized option");
2629 PrintUsage ();
2630 return STATUS_ERROR;
2631 }
2632
2633 Argv++;
2634 Argc--;
2635 }
2636 //
2637 // Must have at least specified the package file name
2638 //
2639 if (mGlobals.PrimaryPackagePath[0] == 0) {
2640 Error (NULL, 0, 0, "must specify primary package file", NULL);
2641 return STATUS_ERROR;
2642 }
2643
2644 return STATUS_SUCCESS;
2645 }