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