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