4 GenFfsFileTaks is to generate ffs file.
6 Copyright (c) 2006, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 package org
.tianocore
.framework
.tasks
;
18 import java
.io
.DataInputStream
;
19 import java
.io
.DataOutputStream
;
21 import java
.io
.FileInputStream
;
22 import java
.io
.FileOutputStream
;
23 import java
.util
.ArrayList
;
24 import java
.util
.Iterator
;
25 import java
.util
.List
;
27 import org
.apache
.tools
.ant
.BuildException
;
28 import org
.apache
.tools
.ant
.Project
;
29 import org
.apache
.tools
.ant
.Task
;
30 import org
.tianocore
.common
.logger
.EdkLog
;
35 GenFfsFileTaks is to generate ffs file.
38 public class GenFfsFileTask
extends Task
implements EfiDefine
, FfsTypes
{
40 * GenFfsFile Task Class
42 * -baseName : module baseName
43 * -ffsFileGuid : module Guid.
44 * -ffsFileType : Ffs file type.
45 * -ffsAttributeRecovery : The file is required for recovery.
46 * -ffsAligment : The file data alignment (0 if none required). See FFS
47 * specification for supported alignments (0-7 are only possible
49 * -ffsAttributeCheckSum : The file data is checksummed. If this is FALSE a
50 * value of 0x5A will be inserted in the file
51 * checksum field of the file header. *
52 * -sectFileDir : specifies the full path to the component build directory.
54 * -ffsAttrib : Data recorde attribute added result.
55 * -sectionList : List recorded all section elemet in task.
68 String ffsFileGuid
= "";
72 String ffsFileType
= "";
74 /// ffsAttribHeaderExtension value is used to set the corresponding bit in
75 /// the output FFS file header
77 boolean ffsAttribHeaderExtension
= false;
79 /// ffsAttribTailPresent value is used to set the corresponding bit in the
80 /// output FFS file header
82 boolean ffsAttribTailPresent
= false;
84 /// ffsAttribRecovery value is used to set the corresponding bit in the
85 /// output FFS file header
87 boolean ffsAttribRecovery
= false;
89 /// ffsAttribDataAlignment value is used to set the corresponding bit in the output
90 /// FFS file header.The specified FFS alignment must be a value between 0
93 int ffsAttribDataAlignment
= 0;
95 /// ffsAttribChecksum value is used to set the corresponding bit in the
96 /// output FFS file header
98 boolean FfsAttribChecksum
= false;
100 /// Attribute is used to record the sum of all bit in the output FFS file.
104 /// The output directory of ffs file.
106 String outputDir
= "";
110 List
<Object
> sectionList
= new ArrayList
<Object
>();
113 /// The path of Framewor_Tools_Paht.
115 static String path
= "";
120 GenFfsFileTask execute is to generate ffs file according to input section
121 dscriptive information.
123 public void execute() throws BuildException
{
125 String ffsSuffix
= "";
126 String outputPath
= "";
129 // Get Fraemwork_Tools_Path
131 Project pj
= this.getOwningTarget().getProject();
132 path
= pj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
135 // Check does the BaseName, Guid, FileType set value.
137 if (this.baseName
.equals("")) {
138 throw new BuildException ("Must set OutputFileBasename!\n");
141 if (this.ffsFileGuid
.equals("")) {
142 throw new BuildException ("Must set ffsFileGuid!\n");
145 if (this.ffsFileType
.equals("")) {
146 throw new BuildException ("Must set ffsFileType!\n");
150 // Create ffs file. File name = FfsFileGuid + BaseName + ffsSuffix.
151 // If outputDir's value was set, file will output to the outputDir.
153 ffsSuffix
= TypeToSuffix (this.moduleType
);
154 if (!this.outputDir
.equals("")) {
156 outputPath
= this.outputDir
;
157 temp
= outputPath
.replace('\\', File
.separatorChar
);
158 outputPath
= temp
.replace('/', File
.separatorChar
);
159 if (outputPath
.charAt(outputPath
.length()-1) != File
.separatorChar
) {
160 outputPath
= outputPath
+ File
.separator
;
165 String ffsFilePath
= outputPath
+ this.ffsFileGuid
+ '-' + this.baseName
+ ffsSuffix
;
166 File ffsFile
= new File (ffsFilePath
);
173 This function is to add compress section to section list.
174 @param compress Section of compress
176 public void addCompress(CompressSection compress
) {
177 this.sectionList
.add(compress
);
183 This function is to add tool section to section list.
184 @param tool Section of tool
186 public void addTool(Tool tool
) {
187 this.sectionList
.add(tool
);
193 This function is to add sectFile section to section list.
194 @param sectFile Section of sectFile.
196 public void addSectFile (SectFile sectFile
) {
197 this.sectionList
.add(sectFile
);
203 This function is to get basename
205 @return String of base name
207 public String
getBaseName() {
208 return this.baseName
;
214 This function is to set base name.
217 public void setBaseName(String baseName
) {
218 this.baseName
= baseName
.trim();
224 This function is to get the ffsAligment
225 @return The value of ffsAligment.
227 public int getFfsAttribDataAlignment() {
228 return this.ffsAttribDataAlignment
;
234 This function is to set ffsAligment
235 @param ffsAligment The value of ffsAligment.
237 public void setFfsAttribDataAlignment(String ffsAligment
) {
238 this.ffsAttribDataAlignment
= stringToInt(ffsAligment
.replaceAll(" ", "").toLowerCase());
239 if (this.ffsAttribDataAlignment
< 0 || this.ffsAttribDataAlignment
> 7) {
240 throw new BuildException ("FFS_ATTRIB_DATA_ALIGMENT must be an integer value from 0 through 7, inclusive");
242 attributes
|= (((byte)this.ffsAttribDataAlignment
) << 3);
249 This function is to get ffsAttribCheckSum
251 @return Value of ffsAttribChecksum
253 public boolean getFfsAttribChecksum() {
254 return this.FfsAttribChecksum
;
260 This function is to set ffsAttribChecksum
261 @param ffsAttributeCheckSum Value of ffsAttribCheckSum
263 public void setFfsAttribChecksum(boolean ffsAttributeCheckSum
) {
264 this.FfsAttribChecksum
= ffsAttributeCheckSum
;
265 if (ffsAttributeCheckSum
) {
266 attributes
|= FFS_ATTRIB_CHECKSUM
;
273 This function is to get ffsAttribRecovery
274 @return Value of ffsAttribRecovery
276 public boolean getFfsAttribRecovery() {
277 return this.ffsAttribRecovery
;
283 This function is to set ffsAttributeRecovery
285 @param ffsAttributeRecovery Value of ffsAttributeRecovery
287 public void setRecovery(boolean ffsAttributeRecovery
) {
288 this.ffsAttribRecovery
= ffsAttributeRecovery
;
289 if (ffsAttributeRecovery
) {
290 attributes
|= FFS_ATTRIB_RECOVERY
;
297 This function is to get fileGuid
300 public String
getFileGuid() {
301 return this.ffsFileGuid
;
307 This function is to set fileGuid
308 @param ffsFileGuid String of GUID
310 public void setFileGuid(String ffsFileGuid
) {
311 this.ffsFileGuid
= ffsFileGuid
.trim();
317 This function is to get ffsFileType.
319 @return value of ffsFileType
321 public String
getFfsFileType() {
322 return this.ffsFileType
;
328 This function is to set ffsFileType.
332 public void setFfsFileType(String ffsFileType
) {
333 this.ffsFileType
= ffsFileType
.trim();
337 ffsAttribHeaderExtension
339 This function is to get ffsAttribHeaderExtension
341 @return Value of ffsAttribHeaderExtension
343 public boolean isFfsAttribHeaderExtension() {
344 return this.ffsAttribHeaderExtension
;
350 This function is to set headerExtension
351 @param headerExtension Value of headerExension
353 public void setHeaderExtension(boolean headerExtension
) {
354 this.ffsAttribHeaderExtension
= headerExtension
;
355 if (headerExtension
) {
356 attributes
|= FFS_ATTRIB_HEADER_EXTENSION
;
361 isFfsAttribTailPresent
363 This function is to get ffsAttribTailPresent value.
364 @return Value of ffsAttribTailPresent.
366 public boolean isFfsAttribTailPresent() {
367 return this.ffsAttribTailPresent
;
371 setFfsAttribTailPresent
373 This function is to set ffsAttribTailPresent.
374 @param tailPresent Value of ffsAttribTailPresent.
376 public void setFfsAttribTailPresent(boolean tailPresent
) {
377 this.ffsAttribTailPresent
= tailPresent
;
379 attributes
|= FFS_ATTRIB_TAIL_PRESENT
;
387 This function is to convert string to GUID.
388 * @param GuidStr String of GUID.
389 * @param Guid GUID form.
391 private void stringToGuid (String GuidStr
, FfsHeader
.FfsGuid Guid
){
399 byte[] buffer
= new byte[16];
400 if (GuidStr
.length()!=36) {
401 throw new BuildException ("The GUID length [" + GuidStr
.length() + "] is not correct!");
405 SplitStr
= GuidStr
.split("-");
406 if (SplitStr
.length
!= 5) {
407 throw new BuildException ("The GUID format is not correct!");
412 for (i
= 0; i
< SplitStr
.length
; i
++) {
413 String str
= SplitStr
[i
];
414 charArry
= str
.toCharArray();
416 for (j
=0; j
< (str
.toCharArray().length
)/2; j
++) {
418 buffer
[k
] = hexCharToByte (charArry
[j
*2]);
419 buffer
[k
] = (byte)( buffer
[k
]& 0x0f);
420 buffer
[k
] = (byte)((buffer
[k
]<< 4));
421 buffer
[k
] = (byte)( buffer
[k
]& 0xf0);
422 buffer
[k
] = (byte)( buffer
[k
]|hexCharToByte(charArry
[j
*2+1]));
426 Guid
.bufferToStruct(buffer
);
432 This function is to get suffix of ffs file according to ffsFileType.
434 @param ffsFileType ffsFileType
435 @return The suffix of ffs file
437 private String
TypeToSuffix (String ffsFileType
){
438 String
[][] suffix
= { { "BASE", ".FFS"},
439 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
440 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
441 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
442 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
443 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
444 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
446 for (int i
= 0; i
< suffix
.length
; i
++) {
447 if (suffix
[i
][0].equalsIgnoreCase(moduleType
)) {
459 This function is to get ffsFileType integer value according to ffsFileType.
460 @param ffsFileType String value of ffsFileType
461 @return Integer value of ffsFileType.
463 private byte stringToType (String ffsFileType
){
465 if (ffsFileType
.equals("EFI_FV_FILETYPE_ALL")) {
466 return(byte)EFI_FV_FILETYPE_ALL
;
469 if (ffsFileType
.equals("EFI_FV_FILETYPE_RAW")) {
470 return(byte)EFI_FV_FILETYPE_RAW
;
473 if (ffsFileType
.equals("EFI_FV_FILETYPE_FREEFORM")) {
474 return(byte)EFI_FV_FILETYPE_FREEFORM
;
477 if (ffsFileType
.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {
478 return(byte)EFI_FV_FILETYPE_SECURITY_CORE
;
481 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEI_CORE")) {
482 return(byte) EFI_FV_FILETYPE_PEI_CORE
;
485 if (ffsFileType
.equals("EFI_FV_FILETYPE_DXE_CORE")) {
486 return(byte)EFI_FV_FILETYPE_DXE_CORE
;
489 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEIM")) {
490 return(byte)EFI_FV_FILETYPE_PEIM
;
493 if (ffsFileType
.equals("EFI_FV_FILETYPE_DRIVER")) {
494 return(byte) EFI_FV_FILETYPE_DRIVER
;
497 if (ffsFileType
.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {
498 return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
501 if (ffsFileType
.equals("EFI_FV_FILETYPE_APPLICATION")) {
502 return(byte)EFI_FV_FILETYPE_APPLICATION
;
505 if (ffsFileType
.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {
506 return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
508 if (ffsFileType
.equals("EFI_FV_FILETYPE_FFS_PAD")) {
509 return(byte) EFI_FV_FILETYPE_FFS_PAD
;
520 This function is to calculate the value needed for a valid UINT8 checksum
521 @param buffer Byte buffer containing byte data of component.
522 @param size Size of the buffer.
523 @return The 8 bit checksum value needed.
525 private byte calculateChecksum8 (byte[] buffer
, int size
){
526 return(byte) (0x100 - calculateSum8 (buffer
, size
));
533 This function is to calculate the UINT8 sum for the requested region.
534 @param buffer Byte buffer containing byte data of component
535 @param size Size of the buffer.
536 @return The 8 bit checksum value needed.
538 private short calculateSum8 (byte[] buffer
, int size
){
544 // Perform the word sum for buffer
546 for (Index
= 0; Index
< size
; Index
++) {
547 Sum
= (byte) (Sum
+ buffer
[Index
]);
556 This function is to convert hex character to byte
558 @param hexChar hex character
559 @return Byte which corresponding to the character.
561 private byte hexCharToByte (char hexChar
){
612 This function is used to adjusts file size to insure sectioned file is exactly the right length such
613 that it ends on exactly the last byte of the last section. ProcessScript()
614 may have padded beyond the end of the last section out to a 4 byte boundary.
615 This padding is stripped.
617 @param buffer Byte buffer contains a section stream
618 @return Corrected size of file.
620 private int adjustFileSize (byte[] buffer
){
622 int orignalLen
= buffer
.length
;
624 int sectionPoint
= 0;
625 int nextSectionPoint
= 0;
628 int firstSectionHeader
= 0;
631 firstSectionHeader
= buffer
[0]& 0xff;
632 firstSectionHeader
= ((buffer
[1]&0xff)<<8) | firstSectionHeader
;
633 firstSectionHeader
= ((buffer
[2]&0xff)<<16)| firstSectionHeader
;
636 while (sectionPoint
< buffer
.length
) {
637 sectionLen
= buffer
[0 + sectionPoint
]& 0xff;
638 sectionLen
= ((buffer
[1 + sectionPoint
]&0xff)<<8)| sectionLen
;
639 sectionLen
= ((buffer
[2 + sectionPoint
]&0xff)<<16)| sectionLen
;
640 totalLen
= totalLen
+ sectionLen
;
642 if (totalLen
== orignalLen
) {
646 sectionPoint
= sectionPoint
+ sectionLen
;
647 adjustLen
= sectionPoint
;
649 nextSectionPoint
= (sectionPoint
+ 0x03) & (~
0x03);
650 totalLen
= totalLen
+ nextSectionPoint
- sectionLen
;
651 sectionPoint
= nextSectionPoint
;
659 This function is to get output directory.
661 @return Path of output directory.
663 public String
getOutputDir() {
670 This function is to set output directory.
672 @param outputDir The output direcotry.
674 public void setOutputDir(String outputDir
) {
675 this.outputDir
= outputDir
;
681 This function is to get string of module type.
683 @return moduleType The string of module type.
685 public String
getModuleType() {
686 return this.moduleType
;
692 This function is to set moduleType.
694 @param moduleType The string of module type.
696 public void setModuleType(String moduleType
) {
697 this.moduleType
= moduleType
;
701 Convert a string to a integer.
703 @param intString The string representing a integer
705 @retval int The value of integer represented by the
706 given string; -1 is returned if the format
707 of the string is wrong.
709 private int stringToInt(String intString
) {
711 int hexPrefixPos
= intString
.indexOf("0x");
713 String intStringNoPrefix
;
715 if (hexPrefixPos
>= 0) {
717 intStringNoPrefix
= intString
.substring(hexPrefixPos
+ 2, intString
.length());
719 intStringNoPrefix
= intString
;
723 value
= Integer
.parseInt(intStringNoPrefix
, radix
);
724 } catch (NumberFormatException e
) {
725 log("Incorrect format of int [" + intString
+ "]. -1 is assumed");
735 This function is to generate FFS file.
737 @param ffsFile Name of FFS file.
738 @param isOrg Flag to indicate generate ORG ffs file or not.
740 private void genFfs(File ffsFile
) {
744 FfsHeader ffsHeader
= new FfsHeader();
745 FfsHeader orgFfsHeader
= new FfsHeader();
747 EdkLog
.log(this, EdkLog
.EDK_INFO
, ffsFile
.getName());
751 // Create file output stream -- dataBuffer.
753 FileOutputStream dataFs
= new FileOutputStream (ffsFile
.getAbsolutePath());
754 DataOutputStream dataBuffer
= new DataOutputStream (dataFs
);
757 // Search SectionList find earch section and call it's
758 // ToBuffer function.
760 Iterator sectionIter
= this.sectionList
.iterator();
761 while (sectionIter
.hasNext()) {
762 sect
= (Section
)sectionIter
.next();
766 // The last section don't need 4 byte ffsAligment.
768 sect
.toBuffer((DataOutputStream
)dataBuffer
);
769 } catch (Exception e
) {
770 throw new BuildException (e
.getMessage());
774 } catch (Exception e
) {
775 throw new BuildException (e
.getMessage());
779 // Creat Ffs file header
784 // create input stream to read file data
786 byte[] fileBuffer
= new byte[(int)ffsFile
.length()];
787 FileInputStream fi
= new FileInputStream (ffsFile
.getAbsolutePath());
788 DataInputStream di
= new DataInputStream (fi
);
793 // Add GUID to header struct
795 if (this.ffsFileGuid
!= null) {
796 stringToGuid (this.ffsFileGuid
, ffsHeader
.name
);
799 ffsHeader
.ffsAttributes
= this.attributes
;
800 if ((ffsHeader
.fileType
= stringToType(this.ffsFileType
))== -1) {
801 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
805 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
808 orgFfsHeader
.ffsAttributes
= ffsHeader
.ffsAttributes
;
809 orgFfsHeader
.fileType
= ffsHeader
.fileType
;
812 // Adjust file size. The function is used to tripe the last
813 // section padding of 4 binary boundary.
816 if (ffsHeader
.fileType
!= EFI_FV_FILETYPE_RAW
) {
818 fileDataSize
= adjustFileSize (fileBuffer
);
820 fileDataSize
= fileBuffer
.length
;
824 // 1. add header size to file size
826 fileSize
= fileDataSize
+ ffsHeader
.getSize();
828 if ((ffsHeader
.ffsAttributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
829 if (ffsHeader
.fileType
== EFI_FV_FILETYPE_FFS_PAD
) {
831 throw new BuildException (
832 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
833 "invalid for PAD files"
836 if (fileSize
== ffsHeader
.getSize()) {
837 throw new BuildException (
838 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
839 "invalid for 0-length files"
842 fileSize
= fileSize
+ 2;
846 // 2. set file size to header struct
848 ffsHeader
.ffsFileSize
[0] = (byte)(fileSize
& 0x00FF);
849 ffsHeader
.ffsFileSize
[1] = (byte)((fileSize
& 0x00FF00)>>8);
850 ffsHeader
.ffsFileSize
[2] = (byte)(((int)fileSize
& 0xFF0000)>>16);
853 // Fill in checksums and state, these must be zero for checksumming
855 ffsHeader
.integrityCheck
.header
= calculateChecksum8 (
856 ffsHeader
.structToBuffer(),
860 if ((this.attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
861 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
862 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
867 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
873 ffsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
874 orgFfsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
878 // Set the state now. Spec says the checksum assumes the state is 0.
880 ffsHeader
.ffsState
= EFI_FILE_HEADER_CONSTRUCTION
|
881 EFI_FILE_HEADER_VALID
|
885 // create output stream to first write header data in file, then write sect data in file.
887 FileOutputStream headerFfs
= new FileOutputStream (ffsFile
.getAbsolutePath());
888 DataOutputStream ffsBuffer
= new DataOutputStream (headerFfs
);
891 // Add header struct and file data to FFS file
893 ffsBuffer
.write(ffsHeader
.structToBuffer());
894 ffsBuffer
.write(fileBuffer
, 0, fileDataSize
);
899 // If there is a tail, then set it
901 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
903 byte [] tailByte
= new byte[2];
906 // reverse tailvalue , integritycheck.file as hight byte, and
907 // integritycheck.header as low byte.
909 tailValue
= (short)(ffsHeader
.integrityCheck
.header
& 0xff);
910 tailValue
= (short)((tailValue
) | ((ffsHeader
.integrityCheck
.file
<< 8) & 0xff00));
911 tailValue
= (short)~tailValue
;
914 // Change short to byte[2]
916 tailByte
[0] = (byte)(tailValue
& 0xff);
917 tailByte
[1] = (byte)((tailValue
& 0xff00)>>8);
918 ffsBuffer
.write(tailByte
[0]);
919 ffsBuffer
.write(tailByte
[1]);
924 // close output stream. Note if don't close output stream
925 // the buffer can't be rewritten to file.
928 } catch (Exception e
) {
929 log("genffsfile failed!");
930 throw new BuildException (e
.getMessage());