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