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