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