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
= "";
127 Project project
= this.getOwningTarget().getProject();
131 FrameworkLogger logger
= new FrameworkLogger(project
, "genFfs");
132 EdkLog
.setLogLevel(project
.getProperty("env.LOGLEVEL"));
133 EdkLog
.setLogger(logger
);
136 // Get Fraemwork_Tools_Path
138 Project pj
= this.getOwningTarget().getProject();
139 path
= pj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
142 // Check does the BaseName, Guid, FileType set value.
144 if (this.baseName
.equals("")) {
145 throw new BuildException ("Must set OutputFileBasename!\n");
148 if (this.ffsFileGuid
.equals("")) {
149 throw new BuildException ("Must set ffsFileGuid!\n");
152 if (this.ffsFileType
.equals("")) {
153 throw new BuildException ("Must set ffsFileType!\n");
157 // Create ffs file. File name = FfsFileGuid + BaseName + ffsSuffix.
158 // If outputDir's value was set, file will output to the outputDir.
160 ffsSuffix
= TypeToSuffix (this.moduleType
);
161 if (!this.outputDir
.equals("")) {
163 outputPath
= this.outputDir
;
164 temp
= outputPath
.replace('\\', File
.separatorChar
);
165 outputPath
= temp
.replace('/', File
.separatorChar
);
166 if (outputPath
.charAt(outputPath
.length()-1) != File
.separatorChar
) {
167 outputPath
= outputPath
+ File
.separator
;
172 String ffsFilePath
= outputPath
+ this.ffsFileGuid
+ '-' + this.baseName
+ ffsSuffix
;
173 File ffsFile
= new File (ffsFilePath
);
180 This function is to add compress section to section list.
181 @param compress Section of compress
183 public void addCompress(CompressSection compress
) {
184 this.sectionList
.add(compress
);
190 This function is to add tool section to section list.
191 @param tool Section of tool
193 public void addTool(Tool tool
) {
194 this.sectionList
.add(tool
);
200 This function is to add sectFile section to section list.
201 @param sectFile Section of sectFile.
203 public void addSectFile (SectFile sectFile
) {
204 this.sectionList
.add(sectFile
);
210 This function is to get basename
212 @return String of base name
214 public String
getBaseName() {
215 return this.baseName
;
221 This function is to set base name.
224 public void setBaseName(String baseName
) {
225 this.baseName
= baseName
.trim();
231 This function is to get the ffsAligment
232 @return The value of ffsAligment.
234 public int getFfsAttribDataAlignment() {
235 return this.ffsAttribDataAlignment
;
241 This function is to set ffsAligment
242 @param ffsAligment The value of ffsAligment.
244 public void setFfsAttribDataAlignment(String ffsAligment
) {
245 this.ffsAttribDataAlignment
= stringToInt(ffsAligment
.replaceAll(" ", "").toLowerCase());
246 if (this.ffsAttribDataAlignment
< 0 || this.ffsAttribDataAlignment
> 7) {
247 throw new BuildException ("FFS_ATTRIB_DATA_ALIGMENT must be an integer value from 0 through 7, inclusive");
249 attributes
|= (((byte)this.ffsAttribDataAlignment
) << 3);
256 This function is to get ffsAttribCheckSum
258 @return Value of ffsAttribChecksum
260 public boolean getFfsAttribChecksum() {
261 return this.FfsAttribChecksum
;
267 This function is to set ffsAttribChecksum
268 @param ffsAttributeCheckSum Value of ffsAttribCheckSum
270 public void setFfsAttribChecksum(boolean ffsAttributeCheckSum
) {
271 this.FfsAttribChecksum
= ffsAttributeCheckSum
;
272 if (ffsAttributeCheckSum
) {
273 attributes
|= FFS_ATTRIB_CHECKSUM
;
280 This function is to get ffsAttribRecovery
281 @return Value of ffsAttribRecovery
283 public boolean getFfsAttribRecovery() {
284 return this.ffsAttribRecovery
;
290 This function is to set ffsAttributeRecovery
292 @param ffsAttributeRecovery Value of ffsAttributeRecovery
294 public void setRecovery(boolean ffsAttributeRecovery
) {
295 this.ffsAttribRecovery
= ffsAttributeRecovery
;
296 if (ffsAttributeRecovery
) {
297 attributes
|= FFS_ATTRIB_RECOVERY
;
304 This function is to get fileGuid
307 public String
getFileGuid() {
308 return this.ffsFileGuid
;
314 This function is to set fileGuid
315 @param ffsFileGuid String of GUID
317 public void setFileGuid(String ffsFileGuid
) {
318 this.ffsFileGuid
= ffsFileGuid
.trim();
324 This function is to get ffsFileType.
326 @return value of ffsFileType
328 public String
getFfsFileType() {
329 return this.ffsFileType
;
335 This function is to set ffsFileType.
339 public void setFfsFileType(String ffsFileType
) {
340 this.ffsFileType
= ffsFileType
.trim();
344 ffsAttribHeaderExtension
346 This function is to get ffsAttribHeaderExtension
348 @return Value of ffsAttribHeaderExtension
350 public boolean isFfsAttribHeaderExtension() {
351 return this.ffsAttribHeaderExtension
;
357 This function is to set headerExtension
358 @param headerExtension Value of headerExension
360 public void setHeaderExtension(boolean headerExtension
) {
361 this.ffsAttribHeaderExtension
= headerExtension
;
362 if (headerExtension
) {
363 attributes
|= FFS_ATTRIB_HEADER_EXTENSION
;
368 isFfsAttribTailPresent
370 This function is to get ffsAttribTailPresent value.
371 @return Value of ffsAttribTailPresent.
373 public boolean isFfsAttribTailPresent() {
374 return this.ffsAttribTailPresent
;
378 setFfsAttribTailPresent
380 This function is to set ffsAttribTailPresent.
381 @param tailPresent Value of ffsAttribTailPresent.
383 public void setFfsAttribTailPresent(boolean tailPresent
) {
384 this.ffsAttribTailPresent
= tailPresent
;
386 attributes
|= FFS_ATTRIB_TAIL_PRESENT
;
394 This function is to convert string to GUID.
395 * @param GuidStr String of GUID.
396 * @param Guid GUID form.
398 private void stringToGuid (String GuidStr
, FfsHeader
.FfsGuid Guid
){
406 byte[] buffer
= new byte[16];
407 if (GuidStr
.length()!=36) {
408 throw new BuildException ("The GUID length [" + GuidStr
.length() + "] is not correct!");
412 SplitStr
= GuidStr
.split("-");
413 if (SplitStr
.length
!= 5) {
414 throw new BuildException ("The GUID format is not correct!");
419 for (i
= 0; i
< SplitStr
.length
; i
++) {
420 String str
= SplitStr
[i
];
421 charArry
= str
.toCharArray();
423 for (j
=0; j
< (str
.toCharArray().length
)/2; j
++) {
425 buffer
[k
] = hexCharToByte (charArry
[j
*2]);
426 buffer
[k
] = (byte)( buffer
[k
]& 0x0f);
427 buffer
[k
] = (byte)((buffer
[k
]<< 4));
428 buffer
[k
] = (byte)( buffer
[k
]& 0xf0);
429 buffer
[k
] = (byte)( buffer
[k
]|hexCharToByte(charArry
[j
*2+1]));
433 Guid
.bufferToStruct(buffer
);
439 This function is to get suffix of ffs file according to ffsFileType.
441 @param ffsFileType ffsFileType
442 @return The suffix of ffs file
444 private String
TypeToSuffix (String ffsFileType
){
445 String
[][] suffix
= { { "BASE", ".FFS"},
446 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
447 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
448 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
449 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
450 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
451 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
453 for (int i
= 0; i
< suffix
.length
; i
++) {
454 if (suffix
[i
][0].equalsIgnoreCase(moduleType
)) {
466 This function is to get ffsFileType integer value according to ffsFileType.
467 @param ffsFileType String value of ffsFileType
468 @return Integer value of ffsFileType.
470 private byte stringToType (String ffsFileType
){
472 if (ffsFileType
.equals("EFI_FV_FILETYPE_ALL")) {
473 return(byte)EFI_FV_FILETYPE_ALL
;
476 if (ffsFileType
.equals("EFI_FV_FILETYPE_RAW")) {
477 return(byte)EFI_FV_FILETYPE_RAW
;
480 if (ffsFileType
.equals("EFI_FV_FILETYPE_FREEFORM")) {
481 return(byte)EFI_FV_FILETYPE_FREEFORM
;
484 if (ffsFileType
.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {
485 return(byte)EFI_FV_FILETYPE_SECURITY_CORE
;
488 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEI_CORE")) {
489 return(byte) EFI_FV_FILETYPE_PEI_CORE
;
492 if (ffsFileType
.equals("EFI_FV_FILETYPE_DXE_CORE")) {
493 return(byte)EFI_FV_FILETYPE_DXE_CORE
;
496 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEIM")) {
497 return(byte)EFI_FV_FILETYPE_PEIM
;
500 if (ffsFileType
.equals("EFI_FV_FILETYPE_DRIVER")) {
501 return(byte) EFI_FV_FILETYPE_DRIVER
;
504 if (ffsFileType
.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {
505 return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
508 if (ffsFileType
.equals("EFI_FV_FILETYPE_APPLICATION")) {
509 return(byte)EFI_FV_FILETYPE_APPLICATION
;
512 if (ffsFileType
.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {
513 return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
515 if (ffsFileType
.equals("EFI_FV_FILETYPE_FFS_PAD")) {
516 return(byte) EFI_FV_FILETYPE_FFS_PAD
;
527 This function is to calculate the value needed for a valid UINT8 checksum
528 @param buffer Byte buffer containing byte data of component.
529 @param size Size of the buffer.
530 @return The 8 bit checksum value needed.
532 private byte calculateChecksum8 (byte[] buffer
, int size
){
533 return(byte) (0x100 - calculateSum8 (buffer
, size
));
540 This function is to calculate the UINT8 sum for the requested region.
541 @param buffer Byte buffer containing byte data of component
542 @param size Size of the buffer.
543 @return The 8 bit checksum value needed.
545 private short calculateSum8 (byte[] buffer
, int size
){
551 // Perform the word sum for buffer
553 for (Index
= 0; Index
< size
; Index
++) {
554 Sum
= (byte) (Sum
+ buffer
[Index
]);
563 This function is to convert hex character to byte
565 @param hexChar hex character
566 @return Byte which corresponding to the character.
568 private byte hexCharToByte (char hexChar
){
619 This function is used to adjusts file size to insure sectioned file is exactly the right length such
620 that it ends on exactly the last byte of the last section. ProcessScript()
621 may have padded beyond the end of the last section out to a 4 byte boundary.
622 This padding is stripped.
624 @param buffer Byte buffer contains a section stream
625 @return Corrected size of file.
627 private int adjustFileSize (byte[] buffer
){
629 int orignalLen
= buffer
.length
;
631 int sectionPoint
= 0;
632 int nextSectionPoint
= 0;
635 int firstSectionHeader
= 0;
638 firstSectionHeader
= buffer
[0]& 0xff;
639 firstSectionHeader
= ((buffer
[1]&0xff)<<8) | firstSectionHeader
;
640 firstSectionHeader
= ((buffer
[2]&0xff)<<16)| firstSectionHeader
;
643 while (sectionPoint
< buffer
.length
) {
644 sectionLen
= buffer
[0 + sectionPoint
]& 0xff;
645 sectionLen
= ((buffer
[1 + sectionPoint
]&0xff)<<8)| sectionLen
;
646 sectionLen
= ((buffer
[2 + sectionPoint
]&0xff)<<16)| sectionLen
;
647 totalLen
= totalLen
+ sectionLen
;
649 if (totalLen
== orignalLen
) {
653 sectionPoint
= sectionPoint
+ sectionLen
;
654 adjustLen
= sectionPoint
;
656 nextSectionPoint
= (sectionPoint
+ 0x03) & (~
0x03);
657 totalLen
= totalLen
+ nextSectionPoint
- sectionLen
;
658 sectionPoint
= nextSectionPoint
;
666 This function is to get output directory.
668 @return Path of output directory.
670 public String
getOutputDir() {
677 This function is to set output directory.
679 @param outputDir The output direcotry.
681 public void setOutputDir(String outputDir
) {
682 this.outputDir
= outputDir
;
688 This function is to get string of module type.
690 @return moduleType The string of module type.
692 public String
getModuleType() {
693 return this.moduleType
;
699 This function is to set moduleType.
701 @param moduleType The string of module type.
703 public void setModuleType(String moduleType
) {
704 this.moduleType
= moduleType
;
708 Convert a string to a integer.
710 @param intString The string representing a integer
712 @retval int The value of integer represented by the
713 given string; -1 is returned if the format
714 of the string is wrong.
716 private int stringToInt(String intString
) {
718 int hexPrefixPos
= intString
.indexOf("0x");
720 String intStringNoPrefix
;
722 if (hexPrefixPos
>= 0) {
724 intStringNoPrefix
= intString
.substring(hexPrefixPos
+ 2, intString
.length());
726 intStringNoPrefix
= intString
;
730 value
= Integer
.parseInt(intStringNoPrefix
, radix
);
731 } catch (NumberFormatException e
) {
732 log("Incorrect format of int [" + intString
+ "]. -1 is assumed");
742 This function is to generate FFS file.
744 @param ffsFile Name of FFS file.
745 @param isOrg Flag to indicate generate ORG ffs file or not.
747 private void genFfs(File ffsFile
) {
751 FfsHeader ffsHeader
= new FfsHeader();
752 FfsHeader orgFfsHeader
= new FfsHeader();
754 EdkLog
.log(EdkLog
.EDK_INFO
, ffsFile
.getName());
758 // Create file output stream -- dataBuffer.
760 FileOutputStream dataFs
= new FileOutputStream (ffsFile
.getAbsolutePath());
761 DataOutputStream dataBuffer
= new DataOutputStream (dataFs
);
764 // Search SectionList find earch section and call it's
765 // ToBuffer function.
767 Iterator sectionIter
= this.sectionList
.iterator();
768 while (sectionIter
.hasNext()) {
769 sect
= (Section
)sectionIter
.next();
773 // The last section don't need 4 byte ffsAligment.
775 sect
.toBuffer((DataOutputStream
)dataBuffer
);
776 } catch (Exception e
) {
777 throw new BuildException (e
.getMessage());
781 } catch (Exception e
) {
782 throw new BuildException (e
.getMessage());
786 // Creat Ffs file header
791 // create input stream to read file data
793 byte[] fileBuffer
= new byte[(int)ffsFile
.length()];
794 FileInputStream fi
= new FileInputStream (ffsFile
.getAbsolutePath());
795 DataInputStream di
= new DataInputStream (fi
);
800 // Add GUID to header struct
802 if (this.ffsFileGuid
!= null) {
803 stringToGuid (this.ffsFileGuid
, ffsHeader
.name
);
806 ffsHeader
.ffsAttributes
= this.attributes
;
807 if ((ffsHeader
.fileType
= stringToType(this.ffsFileType
))== -1) {
808 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
812 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
815 orgFfsHeader
.ffsAttributes
= ffsHeader
.ffsAttributes
;
816 orgFfsHeader
.fileType
= ffsHeader
.fileType
;
819 // Adjust file size. The function is used to tripe the last
820 // section padding of 4 binary boundary.
823 if (ffsHeader
.fileType
!= EFI_FV_FILETYPE_RAW
) {
825 fileDataSize
= adjustFileSize (fileBuffer
);
827 fileDataSize
= fileBuffer
.length
;
831 // 1. add header size to file size
833 fileSize
= fileDataSize
+ ffsHeader
.getSize();
835 if ((ffsHeader
.ffsAttributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
836 if (ffsHeader
.fileType
== EFI_FV_FILETYPE_FFS_PAD
) {
838 throw new BuildException (
839 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
840 "invalid for PAD files"
843 if (fileSize
== ffsHeader
.getSize()) {
844 throw new BuildException (
845 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
846 "invalid for 0-length files"
849 fileSize
= fileSize
+ 2;
853 // 2. set file size to header struct
855 ffsHeader
.ffsFileSize
[0] = (byte)(fileSize
& 0x00FF);
856 ffsHeader
.ffsFileSize
[1] = (byte)((fileSize
& 0x00FF00)>>8);
857 ffsHeader
.ffsFileSize
[2] = (byte)(((int)fileSize
& 0xFF0000)>>16);
860 // Fill in checksums and state, these must be zero for checksumming
862 ffsHeader
.integrityCheck
.header
= calculateChecksum8 (
863 ffsHeader
.structToBuffer(),
867 if ((this.attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
868 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
869 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
874 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
880 ffsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
881 orgFfsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
885 // Set the state now. Spec says the checksum assumes the state is 0.
887 ffsHeader
.ffsState
= EFI_FILE_HEADER_CONSTRUCTION
|
888 EFI_FILE_HEADER_VALID
|
892 // create output stream to first write header data in file, then write sect data in file.
894 FileOutputStream headerFfs
= new FileOutputStream (ffsFile
.getAbsolutePath());
895 DataOutputStream ffsBuffer
= new DataOutputStream (headerFfs
);
898 // Add header struct and file data to FFS file
900 ffsBuffer
.write(ffsHeader
.structToBuffer());
901 ffsBuffer
.write(fileBuffer
, 0, fileDataSize
);
906 // If there is a tail, then set it
908 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
910 byte [] tailByte
= new byte[2];
913 // reverse tailvalue , integritycheck.file as hight byte, and
914 // integritycheck.header as low byte.
916 tailValue
= (short)(ffsHeader
.integrityCheck
.header
& 0xff);
917 tailValue
= (short)((tailValue
) | ((ffsHeader
.integrityCheck
.file
<< 8) & 0xff00));
918 tailValue
= (short)~tailValue
;
921 // Change short to byte[2]
923 tailByte
[0] = (byte)(tailValue
& 0xff);
924 tailByte
[1] = (byte)((tailValue
& 0xff00)>>8);
925 ffsBuffer
.write(tailByte
[0]);
926 ffsBuffer
.write(tailByte
[1]);
931 // close output stream. Note if don't close output stream
932 // the buffer can't be rewritten to file.
935 } catch (Exception e
) {
936 log("genffsfile failed!");
937 throw new BuildException (e
.getMessage());