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