3fdeb8d76aa5b74bde31d5b84dfb7e37cb9d921e
[people/mcb30/edk2.git] / edk2 / Tools / Java / Source / FrameworkTasks / org / tianocore / framework / tasks / GenFfsFileTask.java
1 /** @file\r
2  GenFfsFileTask class.\r
3 \r
4  GenFfsFileTaks is to generate ffs file.\r
5  \r
6  Copyright (c) 2006, Intel Corporation\r
7  All rights reserved. This program and the accompanying materials\r
8  are licensed and made available under the terms and conditions of the BSD License\r
9  which accompanies this distribution.  The full text of the license may be found at\r
10  http://opensource.org/licenses/bsd-license.php\r
11  \r
12  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14 \r
15  **/\r
16 package org.tianocore.framework.tasks;\r
17 \r
18 import java.io.DataInputStream;\r
19 import java.io.DataOutputStream;\r
20 import java.io.File;\r
21 import java.io.FileInputStream;\r
22 import java.io.FileOutputStream;\r
23 import java.util.ArrayList;\r
24 import java.util.Iterator;\r
25 import java.util.List;\r
26 \r
27 import org.apache.tools.ant.BuildException;\r
28 import org.apache.tools.ant.Project;\r
29 import org.apache.tools.ant.Task;\r
30 import org.tianocore.common.logger.EdkLog;\r
31 \r
32 /**\r
33   GenFfsFileTask\r
34   \r
35   GenFfsFileTaks is to generate ffs file.\r
36 \r
37 **/\r
38 public class GenFfsFileTask extends Task implements EfiDefine, FfsTypes {\r
39     /**\r
40       *  GenFfsFile Task Class\r
41       *  class member \r
42       *      -baseName               : module baseName\r
43       *      -ffsFileGuid            : module Guid.\r
44       *      -ffsFileType            : Ffs file type.  \r
45       *      -ffsAttributeRecovery   : The file is required for recovery.\r
46       *      -ffsAligment            : The file data alignment (0 if none required).  See FFS \r
47       *                                specification for supported alignments (0-7 are only possible \r
48       *                                 values).     *\r
49       *      -ffsAttributeCheckSum   : The file data is checksummed.  If this is FALSE a \r
50       *                                value of 0x5A will be inserted in the file \r
51       *                                checksum field of the file header.     *\r
52       *      -sectFileDir            : specifies the full path to the component build directory.\r
53       *                                Required.\r
54       *      -ffsAttrib              : Data recorde attribute added result.\r
55       *      -sectionList            : List recorded all section elemet in task.\r
56       */\r
57     ///\r
58     /// module baseName\r
59     ///\r
60     String  baseName        = "";\r
61     ///\r
62     /// \r
63     /// \r
64     String moduleType;\r
65     ///\r
66     /// module Guid\r
67     ///\r
68     String  ffsFileGuid        = "";\r
69     ///\r
70     /// Ffs file type\r
71     ///\r
72     String  ffsFileType        = "";\r
73     ///\r
74     /// ffsAttribHeaderExtension value is used to set the corresponding bit in \r
75     /// the output FFS file header \r
76     ///\r
77     boolean ffsAttribHeaderExtension = false;\r
78     ///\r
79     /// ffsAttribTailPresent value is used to set the corresponding bit in the \r
80     /// output FFS file header\r
81     ///\r
82     boolean ffsAttribTailPresent     = false;\r
83     ///\r
84     /// ffsAttribRecovery value is used to set the corresponding bit in the \r
85     /// output FFS file header\r
86     ///\r
87     boolean ffsAttribRecovery        = false;\r
88     ///\r
89     /// ffsAttribDataAlignment value is used to set the corresponding bit in the output \r
90     /// FFS file header.The specified FFS alignment must be a value between 0 \r
91     /// and 7 inclusive\r
92     ///\r
93     int     ffsAttribDataAlignment       = 0;\r
94     ///\r
95     /// ffsAttribChecksum value is used to set the corresponding bit in the \r
96     /// output FFS file header\r
97     ///\r
98     boolean FfsAttribChecksum        = false;\r
99     ///\r
100     /// Attribute is used to record the sum of all bit in the output FFS file.\r
101     ///\r
102     byte    attributes      = 0;\r
103     ///\r
104     /// The output directory of ffs file.\r
105     ///\r
106     String  outputDir       = "";\r
107     ///\r
108     /// List of section.\r
109     ///\r
110     List<Object> sectionList  = new ArrayList<Object>();\r
111 \r
112     ///\r
113     /// The path of Framewor_Tools_Paht.\r
114     ///\r
115     static String path = "";  \r
116     \r
117     ///\r
118     /// Gensection\r
119     ///\r
120     List<GenSectionTask> genSectList = new ArrayList<GenSectionTask>();\r
121     \r
122     /**\r
123       execute\r
124       \r
125       GenFfsFileTask execute is to generate ffs file according to input section \r
126       dscriptive information.\r
127     **/\r
128     public void execute() throws BuildException {\r
129 \r
130         String            ffsSuffix = "";\r
131         String            outputPath = "";\r
132         \r
133         //\r
134         //  Get Fraemwork_Tools_Path\r
135         //\r
136         Project pj = this.getOwningTarget().getProject();\r
137         path       = pj.getProperty("env.FRAMEWORK_TOOLS_PATH");\r
138 \r
139         //\r
140         //  Check does the BaseName, Guid, FileType set value.\r
141         //\r
142         if (this.baseName.equals("")) {\r
143             throw new BuildException ("Must set OutputFileBasename!\n");\r
144         }\r
145 \r
146         if (this.ffsFileGuid.equals("")) {\r
147             throw new BuildException ("Must set ffsFileGuid!\n");\r
148         }\r
149 \r
150         if (this.ffsFileType.equals("")) {\r
151             throw new BuildException ("Must set ffsFileType!\n");\r
152         }\r
153         //\r
154         //  Create ffs file. File name = FfsFileGuid + BaseName + ffsSuffix.\r
155         //  If outputDir's value was set,  file will output to the outputDir.\r
156         //\r
157         ffsSuffix = TypeToSuffix (this.moduleType);\r
158         if (!this.outputDir.equals("")) {\r
159             String temp;\r
160             outputPath = this.outputDir;\r
161             temp       = outputPath.replace('\\', File.separatorChar);\r
162             outputPath = temp.replace('/', File.separatorChar);\r
163             if (outputPath.charAt(outputPath.length()-1) != File.separatorChar) {\r
164                 outputPath = outputPath + File.separator;\r
165             }\r
166 \r
167         }\r
168 \r
169         String ffsFilePath = outputPath + this.ffsFileGuid + '-' + this.baseName + ffsSuffix;\r
170         File ffsFile = new File (ffsFilePath);\r
171         try{\r
172             genFfs(ffsFile);\r
173         }catch (BuildException e){\r
174             if (ffsFile != null && ffsFile.exists()){\r
175                 ffsFile.deleteOnExit();\r
176             }\r
177             throw new BuildException(e.getMessage());\r
178             \r
179         }\r
180         \r
181     }   \r
182 \r
183     /**\r
184       addCompress\r
185       \r
186       This function is to add compress section to section list.\r
187       @param compress   Section of compress   \r
188     **/\r
189     public void addCompress(CompressSection compress) {\r
190         this.sectionList.add(compress);\r
191     }\r
192 \r
193     /**\r
194       addTool\r
195       \r
196       This function is to add tool section to section list.\r
197       @param tool       Section of tool\r
198     **/\r
199     public void addTool(Tool tool) {\r
200         this.sectionList.add(tool);\r
201     }\r
202 \r
203     /**\r
204       addSectionFile\r
205       \r
206       This function is to add sectFile section to section list.\r
207       @param sectFile    Section of sectFile.\r
208     **/\r
209     public void addSectFile (SectFile sectFile) {\r
210         this.sectionList.add(sectFile);   \r
211     }\r
212 \r
213     /**\r
214       getBaseName\r
215       \r
216       This function is to get basename\r
217       \r
218       @return              String of base name\r
219     **/\r
220     public String getBaseName() {\r
221         return this.baseName;\r
222     }\r
223 \r
224     /**\r
225       setBaseName\r
226       \r
227       This function is to set base name.\r
228       @param  baseName\r
229     **/\r
230     public void setBaseName(String baseName) {\r
231         this.baseName = baseName.trim();\r
232     }\r
233 \r
234     /**\r
235       getFfsAligment\r
236       \r
237       This function is to get the ffsAligment\r
238       @return  The value of ffsAligment.\r
239     **/\r
240     public int getFfsAttribDataAlignment() {\r
241         return this.ffsAttribDataAlignment;\r
242     }\r
243 \r
244     /**\r
245       setFfsAligment\r
246       \r
247       This function is to set ffsAligment \r
248       @param  ffsAligment     The value of ffsAligment.\r
249     **/\r
250     public void setFfsAttribDataAlignment(String ffsAligment) {\r
251         this.ffsAttribDataAlignment = stringToInt(ffsAligment.replaceAll(" ", "").toLowerCase());\r
252         if (this.ffsAttribDataAlignment < 0 || this.ffsAttribDataAlignment > 7) {\r
253             throw new BuildException ("FFS_ATTRIB_DATA_ALIGMENT must be an integer value from 0 through 7, inclusive");\r
254         } else {\r
255             attributes |= (((byte)this.ffsAttribDataAlignment) << 3);\r
256         }\r
257     }\r
258 \r
259     /**\r
260       getFfsAttribCheckSum\r
261       \r
262       This function is to get ffsAttribCheckSum\r
263       \r
264       @return                      Value of ffsAttribChecksum \r
265     **/\r
266     public boolean getFfsAttribChecksum() {\r
267         return this.FfsAttribChecksum;\r
268     }\r
269 \r
270     /**\r
271       setFfsAttribChecksum\r
272       \r
273       This function is to set ffsAttribChecksum\r
274       @param ffsAttributeCheckSum  Value of ffsAttribCheckSum\r
275     **/\r
276     public void setFfsAttribChecksum(boolean ffsAttributeCheckSum) {\r
277         this.FfsAttribChecksum = ffsAttributeCheckSum;\r
278         if (ffsAttributeCheckSum) {\r
279             attributes |= FFS_ATTRIB_CHECKSUM;\r
280         }\r
281     }\r
282 \r
283     /**\r
284       getFfsAttribRecovery\r
285       \r
286       This function is to get ffsAttribRecovery\r
287       @return                        Value of ffsAttribRecovery\r
288     **/\r
289     public boolean getFfsAttribRecovery() {\r
290         return this.ffsAttribRecovery;\r
291     }\r
292 \r
293     /**\r
294       setRecovery\r
295       \r
296       This function is to set ffsAttributeRecovery\r
297       \r
298       @param  ffsAttributeRecovery    Value of ffsAttributeRecovery\r
299     **/\r
300     public void setRecovery(boolean ffsAttributeRecovery) {\r
301         this.ffsAttribRecovery = ffsAttributeRecovery;\r
302         if (ffsAttributeRecovery) {\r
303             attributes |= FFS_ATTRIB_RECOVERY;\r
304         }\r
305     }\r
306 \r
307     /**\r
308       getFileGuid\r
309       \r
310       This function is to get fileGuid\r
311       @return          Guid\r
312     **/\r
313     public String getFileGuid() {\r
314         return this.ffsFileGuid;\r
315     }\r
316 \r
317     /**\r
318       setFileGuid\r
319       \r
320       This function is to set fileGuid\r
321       @param ffsFileGuid    String of GUID\r
322     **/\r
323     public void setFileGuid(String ffsFileGuid) {\r
324         this.ffsFileGuid = ffsFileGuid.trim();\r
325     }\r
326 \r
327     /**\r
328       getFfsFileType\r
329       \r
330       This function is to get ffsFileType.\r
331       \r
332       @return               value of ffsFileType\r
333     **/\r
334     public String getFfsFileType() {\r
335         return this.ffsFileType;\r
336     }\r
337 \r
338     /**\r
339       setFfsFileType\r
340       \r
341       This function is to set ffsFileType.\r
342       \r
343       @param ffsFileType      \r
344     **/\r
345     public void setFfsFileType(String ffsFileType) {\r
346         this.ffsFileType = ffsFileType.trim();\r
347     }\r
348 \r
349     /**\r
350       ffsAttribHeaderExtension\r
351       \r
352       This function is to get ffsAttribHeaderExtension\r
353       \r
354       @return             Value of ffsAttribHeaderExtension\r
355     **/\r
356     public boolean isFfsAttribHeaderExtension() {\r
357         return this.ffsAttribHeaderExtension;\r
358     }\r
359 \r
360     /**\r
361       setHeaderExension\r
362       \r
363       This function is to set headerExtension\r
364       @param headerExtension     Value of headerExension\r
365     **/\r
366     public void setHeaderExtension(boolean headerExtension) {\r
367         this.ffsAttribHeaderExtension = headerExtension;\r
368         if (headerExtension) {\r
369             attributes |= FFS_ATTRIB_HEADER_EXTENSION;\r
370         }\r
371     }\r
372 \r
373     /**\r
374       isFfsAttribTailPresent\r
375       \r
376       This function is to get ffsAttribTailPresent value.\r
377       @return          Value of ffsAttribTailPresent.\r
378     **/\r
379     public boolean isFfsAttribTailPresent() {\r
380         return this.ffsAttribTailPresent;\r
381     }\r
382 \r
383     /**\r
384       setFfsAttribTailPresent\r
385       \r
386       This function is to set ffsAttribTailPresent.\r
387       @param tailPresent  Value of ffsAttribTailPresent.\r
388     **/\r
389     public void setFfsAttribTailPresent(boolean tailPresent) {\r
390         this.ffsAttribTailPresent = tailPresent;\r
391         if (tailPresent) {\r
392             attributes |= FFS_ATTRIB_TAIL_PRESENT;\r
393         }\r
394     }   \r
395 \r
396 \r
397     /**\r
398       stringToGuid\r
399       \r
400       This function is to convert string to GUID.\r
401      * @param GuidStr         String of GUID.\r
402      * @param Guid            GUID form.\r
403      */\r
404     private void stringToGuid (String GuidStr, FfsHeader.FfsGuid Guid){   \r
405 \r
406         int i  = 0;\r
407         int j  = 0;\r
408         int k  = 0;\r
409         char   [] charArry;\r
410         String [] SplitStr;\r
411 \r
412         byte[] buffer = new byte[16];\r
413         if (GuidStr.length()!=36) {\r
414             throw new BuildException ("The GUID length [" + GuidStr.length() + "] is not correct!");\r
415         }\r
416 \r
417 \r
418         SplitStr = GuidStr.split("-");\r
419         if (SplitStr.length != 5) {\r
420             throw new BuildException ("The GUID format is not correct!");\r
421         }\r
422 \r
423 \r
424 \r
425         for (i= 0; i < SplitStr.length; i++) {\r
426             String str = SplitStr[i];         \r
427             charArry   = str.toCharArray();\r
428 \r
429             for (j =0; j < (str.toCharArray().length)/2; j++) {\r
430 \r
431                 buffer[k] = hexCharToByte (charArry[j*2]);        \r
432                 buffer[k] = (byte)( buffer[k]& 0x0f);       \r
433                 buffer[k] = (byte)((buffer[k]<< 4));\r
434                 buffer[k] = (byte)( buffer[k]& 0xf0);       \r
435                 buffer[k] = (byte)( buffer[k]|hexCharToByte(charArry[j*2+1]));\r
436                 k++;            \r
437             }\r
438         }\r
439         Guid.bufferToStruct(buffer);\r
440     }\r
441 \r
442     /**\r
443       typeToSuffix\r
444       \r
445       This function is to get suffix of ffs file according to ffsFileType.\r
446       \r
447       @param  ffsFileType    ffsFileType\r
448       @return                The suffix of ffs file\r
449     **/\r
450     private String TypeToSuffix (String ffsFileType){\r
451         String[][] suffix = { { "BASE", ".FFS"},\r
452                               { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" }, \r
453                               { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },\r
454                               { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" }, \r
455                               { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" }, \r
456                               { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },\r
457                               { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };\r
458 \r
459         for (int i = 0; i < suffix.length; i++) {\r
460             if (suffix[i][0].equalsIgnoreCase(moduleType)) {\r
461                 return suffix[i][1];\r
462             }\r
463         }\r
464 \r
465         return ".FFS";\r
466     }\r
467 \r
468 \r
469     /**\r
470       stringToType\r
471       \r
472       This function is to get ffsFileType integer value according to ffsFileType.\r
473       @param   ffsFileType       String value of ffsFileType\r
474       @return                    Integer value of ffsFileType.\r
475     **/\r
476     private byte stringToType (String ffsFileType){\r
477 \r
478         if (ffsFileType.equals("EFI_FV_FILETYPE_ALL")) {\r
479             return(byte)EFI_FV_FILETYPE_ALL;\r
480         }\r
481 \r
482         if (ffsFileType.equals("EFI_FV_FILETYPE_RAW")) {\r
483             return(byte)EFI_FV_FILETYPE_RAW;\r
484         }\r
485 \r
486         if (ffsFileType.equals("EFI_FV_FILETYPE_FREEFORM")) {\r
487             return(byte)EFI_FV_FILETYPE_FREEFORM;\r
488         }\r
489 \r
490         if (ffsFileType.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {\r
491             return(byte)EFI_FV_FILETYPE_SECURITY_CORE;\r
492         }\r
493 \r
494         if (ffsFileType.equals("EFI_FV_FILETYPE_PEI_CORE")) {\r
495             return(byte) EFI_FV_FILETYPE_PEI_CORE;\r
496         }\r
497 \r
498         if (ffsFileType.equals("EFI_FV_FILETYPE_DXE_CORE")) {\r
499             return(byte)EFI_FV_FILETYPE_DXE_CORE;\r
500         }\r
501 \r
502         if (ffsFileType.equals("EFI_FV_FILETYPE_PEIM")) {\r
503             return(byte)EFI_FV_FILETYPE_PEIM;\r
504         }\r
505 \r
506         if (ffsFileType.equals("EFI_FV_FILETYPE_DRIVER")) {\r
507             return(byte) EFI_FV_FILETYPE_DRIVER;\r
508         }\r
509 \r
510         if (ffsFileType.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {\r
511             return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER;\r
512         }\r
513 \r
514         if (ffsFileType.equals("EFI_FV_FILETYPE_APPLICATION")) {\r
515             return(byte)EFI_FV_FILETYPE_APPLICATION;\r
516         }\r
517 \r
518         if (ffsFileType.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {\r
519             return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;\r
520         }\r
521         if (ffsFileType.equals("EFI_FV_FILETYPE_FFS_PAD")) {\r
522             return(byte) EFI_FV_FILETYPE_FFS_PAD;\r
523         }\r
524 \r
525         return -1;\r
526     }\r
527 \r
528 \r
529 \r
530     /**\r
531       calculateCheckSum8\r
532       \r
533       This function is to calculate the value needed for a valid UINT8 checksum\r
534       @param  buffer  Byte buffer containing byte data of component.\r
535       @param  size    Size of the buffer.\r
536       @return         The 8 bit checksum value needed.\r
537     **/\r
538     private byte calculateChecksum8 (byte[] buffer, int size){\r
539         return(byte) (0x100 - calculateSum8 (buffer, size));\r
540     }\r
541 \r
542 \r
543     /**\r
544       calculateSum8\r
545       \r
546       This function is to calculate the UINT8 sum for the requested region.\r
547       @param buffer   Byte buffer containing byte data of component\r
548       @param size     Size of the buffer.\r
549       @return         The 8 bit checksum value needed.\r
550     **/ \r
551     private short calculateSum8 (byte[] buffer, int size){\r
552         int   Index;\r
553         byte  Sum;\r
554         Sum   = 0;\r
555 \r
556         //\r
557         // Perform the word sum for buffer\r
558         //\r
559         for (Index = 0; Index < size; Index++) {\r
560             Sum = (byte) (Sum + buffer[Index]);     \r
561         }\r
562 \r
563         return(byte) Sum; \r
564     }\r
565 \r
566     /**\r
567       hexCharToByte\r
568       \r
569       This function is to convert hex character to byte\r
570       \r
571       @param     hexChar          hex character\r
572       @return                     Byte which corresponding to the character.\r
573     **/\r
574     private byte hexCharToByte (char hexChar){\r
575         switch (hexChar) {\r
576         case '0':\r
577             return(byte)0x00;\r
578         case '1':\r
579             return(byte)0x01;\r
580         case '2':\r
581             return(byte)0x02;\r
582         case '3':\r
583             return(byte)0x03;\r
584         case '4':\r
585             return(byte)0x04;\r
586         case '5':\r
587             return(byte)0x05;\r
588         case '6':\r
589             return(byte)0x06;\r
590         case '7':\r
591             return(byte)0x07;\r
592         case '8':\r
593             return(byte)0x08;\r
594         case '9':\r
595             return(byte)0x09;\r
596         case 'a':\r
597         case 'A':\r
598             return(byte)0x0a;\r
599         case 'b':\r
600         case 'B':\r
601             return(byte)0x0b;\r
602         case 'c':\r
603         case 'C':\r
604             return(byte)0x0c;\r
605 \r
606         case 'd':\r
607         case 'D':           \r
608             return(byte)0x0d;\r
609 \r
610         case 'e':\r
611         case 'E':\r
612             return(byte)0x0e;\r
613         case 'f':\r
614         case 'F':\r
615             return(byte)0x0f;\r
616 \r
617         default:\r
618             return(byte)0xff;  \r
619         }\r
620     }\r
621 \r
622     /**\r
623       adjustFileSize\r
624       \r
625       This function is used to adjusts file size to insure sectioned file is exactly the right length such\r
626       that it ends on exactly the last byte of the last section.  ProcessScript()\r
627       may have padded beyond the end of the last section out to a 4 byte boundary.\r
628       This padding is stripped.  \r
629       \r
630       @param    buffer  Byte buffer contains a section stream\r
631       @return           Corrected size of file.\r
632     **/\r
633     private int adjustFileSize (byte[] buffer){ \r
634 \r
635         int orignalLen         = buffer.length;\r
636         int adjustLen          = 0;\r
637         int sectionPoint       = 0;\r
638         int nextSectionPoint   = 0;\r
639         int sectionLen         = 0;\r
640         int totalLen           = 0;\r
641         int firstSectionHeader = 0;\r
642 \r
643 \r
644         firstSectionHeader = buffer[0]& 0xff;\r
645         firstSectionHeader = ((buffer[1]&0xff)<<8) | firstSectionHeader;\r
646         firstSectionHeader = ((buffer[2]&0xff)<<16)| firstSectionHeader;\r
647 \r
648 \r
649         while (sectionPoint < buffer.length) {\r
650             sectionLen = buffer[0 + sectionPoint]& 0xff;\r
651             sectionLen = ((buffer[1 + sectionPoint]&0xff)<<8)| sectionLen;\r
652             sectionLen = ((buffer[2 + sectionPoint]&0xff)<<16)| sectionLen; \r
653             totalLen   = totalLen + sectionLen;\r
654 \r
655             if (totalLen == orignalLen) {\r
656                 return totalLen;\r
657             }\r
658 \r
659             sectionPoint     = sectionPoint + sectionLen;\r
660             adjustLen        = sectionPoint;\r
661 \r
662             nextSectionPoint = (sectionPoint + 0x03) & (~0x03);\r
663             totalLen         = totalLen + nextSectionPoint - sectionLen;\r
664             sectionPoint     = nextSectionPoint;\r
665         }\r
666         return adjustLen;\r
667     }\r
668 \r
669     /**\r
670       getOutputDir\r
671       \r
672       This function is to get output directory.\r
673       \r
674       @return                Path of output directory.\r
675     **/\r
676     public String getOutputDir() {\r
677         return outputDir;\r
678     }\r
679 \r
680     /**\r
681       setOutputDir\r
682       \r
683       This function is to set output directory.\r
684       \r
685       @param outputDir        The output direcotry.\r
686     **/\r
687     public void setOutputDir(String outputDir) {\r
688         this.outputDir = outputDir;\r
689     }\r
690 \r
691     /**\r
692       getModuleTyp\r
693       \r
694       This function is to get string of module type.\r
695      \r
696       @return moduleType      The string of module type.\r
697     **/\r
698     public String getModuleType() {\r
699         return this.moduleType;\r
700     }\r
701 \r
702     /**\r
703       setModuleType\r
704       \r
705       This function is to set moduleType.\r
706       \r
707       @param moduleType       The string of module type.\r
708     **/\r
709     public void setModuleType(String moduleType) {\r
710         this.moduleType = moduleType;\r
711     }\r
712     \r
713     /**\r
714     Convert a string to a integer.\r
715     \r
716     @param     intString   The string representing a integer\r
717     \r
718     @retval    int     The value of integer represented by the\r
719                        given string; -1 is returned if the format\r
720                        of the string is wrong.\r
721     **/\r
722    private int stringToInt(String intString) {\r
723        int value;\r
724        int hexPrefixPos = intString.indexOf("0x");\r
725        int radix = 10;\r
726        String intStringNoPrefix;\r
727 \r
728        if (hexPrefixPos >= 0) {\r
729            radix = 16;\r
730            intStringNoPrefix = intString.substring(hexPrefixPos + 2, intString.length());\r
731        } else {\r
732            intStringNoPrefix = intString;\r
733        }\r
734 \r
735        try {\r
736            value = Integer.parseInt(intStringNoPrefix, radix);\r
737        } catch (NumberFormatException e) {\r
738            EdkLog.log(this, EdkLog.EDK_ERROR, "Incorrect format of int [" + intString + "]. -1 is assumed");\r
739            return -1;\r
740        }\r
741 \r
742        return value;\r
743    }\r
744     \r
745     /**\r
746       genFfs\r
747       \r
748       This function is to generate FFS file.\r
749       \r
750        @param ffsFile          Name of FFS file.\r
751        @param isOrg            Flag to indicate generate ORG ffs file or not.\r
752     **/\r
753     private void genFfs(File ffsFile) throws BuildException {\r
754         Section           sect;\r
755         int               fileSize;\r
756         int               fileDataSize;\r
757         FfsHeader         ffsHeader = new FfsHeader();  \r
758         FfsHeader         orgFfsHeader = new FfsHeader();\r
759            \r
760         EdkLog.log(this, EdkLog.EDK_INFO, ffsFile.getName());\r
761       \r
762         try {\r
763             //\r
764             //  Create file output stream -- dataBuffer.\r
765             //\r
766             FileOutputStream dataFs     = new FileOutputStream (ffsFile.getAbsolutePath());\r
767             DataOutputStream dataBuffer = new DataOutputStream (dataFs);\r
768             \r
769             //\r
770             //  Search SectionList find earch section and call it's \r
771             //  ToBuffer function.\r
772             //\r
773             Iterator sectionIter = this.sectionList.iterator();\r
774             while (sectionIter.hasNext()) {\r
775                 sect = (Section)sectionIter.next(); \r
776 \r
777                 try {\r
778                     //\r
779                     //  The last section don't need 4 byte ffsAligment.\r
780                     //\r
781                     sect.toBuffer((DataOutputStream)dataBuffer);\r
782                 } catch (Exception e) {\r
783                     if (dataBuffer != null){\r
784                         dataBuffer.close();\r
785                     }\r
786                     throw new BuildException (e.getMessage());\r
787                 }\r
788             }\r
789             dataBuffer.close();\r
790         } catch (Exception e) {\r
791             throw new BuildException (e.getMessage());\r
792         }\r
793 \r
794         //\r
795         //  Creat Ffs file header\r
796         //\r
797         try {\r
798 \r
799             //\r
800             //  create input stream to read file data\r
801             //\r
802             byte[] fileBuffer  = new byte[(int)ffsFile.length()];\r
803             FileInputStream fi = new FileInputStream (ffsFile.getAbsolutePath());\r
804             DataInputStream di = new DataInputStream (fi);\r
805             di.read(fileBuffer);\r
806             di.close();\r
807             \r
808             //\r
809             //  Add GUID to header struct\r
810             //\r
811             if (this.ffsFileGuid != null) {\r
812                 stringToGuid (this.ffsFileGuid, ffsHeader.name);\r
813             }\r
814 \r
815             ffsHeader.ffsAttributes = this.attributes;\r
816             if ((ffsHeader.fileType = stringToType(this.ffsFileType))== -1) {\r
817                 throw new BuildException ("FFS_FILE_TYPE unknow!\n");\r
818             }\r
819             \r
820             //\r
821             // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute\r
822             // and fileType\r
823             //            \r
824             orgFfsHeader.ffsAttributes = ffsHeader.ffsAttributes;\r
825             orgFfsHeader.fileType      = ffsHeader.fileType;\r
826             \r
827             //\r
828             //  Adjust file size. The function is used to tripe the last \r
829             //  section padding of 4 binary boundary. \r
830             //  \r
831             //\r
832             if (ffsHeader.fileType != EFI_FV_FILETYPE_RAW) {\r
833 \r
834                 fileDataSize = adjustFileSize (fileBuffer);\r
835             } else {\r
836                 fileDataSize = fileBuffer.length;\r
837             }\r
838 \r
839             //\r
840             //  1. add header size to file size\r
841             //\r
842             fileSize = fileDataSize + ffsHeader.getSize();\r
843 \r
844             if ((ffsHeader.ffsAttributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {\r
845                 if (ffsHeader.fileType == EFI_FV_FILETYPE_FFS_PAD) {\r
846 \r
847                     throw new BuildException (\r
848                                              "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +\r
849                                              "invalid for PAD files"\r
850                                              );\r
851                 }\r
852                 if (fileSize == ffsHeader.getSize()) {\r
853                     throw new BuildException (\r
854                                              "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +\r
855                                              "invalid for 0-length files"\r
856                                              );            \r
857                 }\r
858                 fileSize = fileSize + 2;\r
859             }\r
860 \r
861             //\r
862             //  2. set file size to header struct\r
863             //\r
864             ffsHeader.ffsFileSize[0] = (byte)(fileSize & 0x00FF);\r
865             ffsHeader.ffsFileSize[1] = (byte)((fileSize & 0x00FF00)>>8);\r
866             ffsHeader.ffsFileSize[2] = (byte)(((int)fileSize & 0xFF0000)>>16);\r
867             \r
868             //\r
869             //  Fill in checksums and state, these must be zero for checksumming\r
870             //\r
871             ffsHeader.integrityCheck.header = calculateChecksum8 (\r
872                                                                  ffsHeader.structToBuffer(),\r
873                                                                  ffsHeader.getSize()\r
874                                                                  );\r
875             \r
876             if ((this.attributes & FFS_ATTRIB_CHECKSUM) != 0) {\r
877                 if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {\r
878                     ffsHeader.integrityCheck.file = calculateChecksum8 (\r
879                                                                        fileBuffer, \r
880                                                                        fileDataSize\r
881                                                                        );\r
882                 } else {\r
883                     ffsHeader.integrityCheck.file = calculateChecksum8 (\r
884                                                                        fileBuffer,\r
885                                                                        fileDataSize\r
886                                                                        );\r
887                 }\r
888             } else {\r
889                 ffsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM;\r
890                 orgFfsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM;\r
891             }\r
892 \r
893             //\r
894             //   Set the state now. Spec says the checksum assumes the state is 0.\r
895             //\r
896             ffsHeader.ffsState = EFI_FILE_HEADER_CONSTRUCTION | \r
897                                  EFI_FILE_HEADER_VALID | \r
898                                  EFI_FILE_DATA_VALID;\r
899             \r
900             //\r
901             // create output stream to first write header data in file, then write sect data in file.\r
902             //\r
903             FileOutputStream headerFfs = new FileOutputStream (ffsFile.getAbsolutePath());\r
904             DataOutputStream ffsBuffer = new DataOutputStream (headerFfs);\r
905             \r
906             //\r
907             //  Add header struct and file data to FFS file\r
908             //\r
909             ffsBuffer.write(ffsHeader.structToBuffer());\r
910             ffsBuffer.write(fileBuffer, 0, fileDataSize);\r
911             \r
912 \r
913 \r
914             //\r
915             //  If there is a tail, then set it\r
916             //\r
917             if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {\r
918                 short tailValue ;\r
919                 byte [] tailByte = new byte[2];\r
920 \r
921                 //\r
922                 //  reverse tailvalue , integritycheck.file as hight byte, and \r
923                 //  integritycheck.header as low byte.\r
924                 //\r
925                 tailValue = (short)(ffsHeader.integrityCheck.header & 0xff);\r
926                 tailValue = (short)((tailValue) | ((ffsHeader.integrityCheck.file << 8) & 0xff00)); \r
927                 tailValue = (short)~tailValue;\r
928 \r
929                 //\r
930                 //  Change short to byte[2]\r
931                 //\r
932                 tailByte[0] = (byte)(tailValue & 0xff);\r
933                 tailByte[1] = (byte)((tailValue & 0xff00)>>8);  \r
934                 ffsBuffer.write(tailByte[0]);\r
935                 ffsBuffer.write(tailByte[1]);\r
936 \r
937             }\r
938 \r
939             //\r
940             //  close output stream. Note if don't close output stream \r
941             //  the buffer can't be rewritten to file. \r
942             //\r
943             ffsBuffer.close();\r
944         } catch (Exception e) {\r
945             EdkLog.log(this, EdkLog.EDK_ERROR, "genffsfile failed!");\r
946             throw new BuildException (e.getMessage());\r
947         }\r
948 \r
949     }\r
950     \r
951     /**\r
952       addGenSection\r
953       \r
954       This function is to add gensection instance to list\r
955       \r
956       @param task    Instance of GenSectionTask\r
957     **/\r
958     public void addGenSection (GenSectionTask task){\r
959         this.sectionList.add(task);\r
960     }\r
961 }\r