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