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