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 List
<GenSectionTask
> genSectList
= new ArrayList
<GenSectionTask
>();
125 GenFfsFileTask execute is to generate ffs file according to input section
126 dscriptive information.
128 public void execute() throws BuildException
{
130 String ffsSuffix
= "";
131 String outputPath
= "";
134 // Get Fraemwork_Tools_Path
136 Project pj
= this.getOwningTarget().getProject();
137 path
= pj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
140 // Check does the BaseName, Guid, FileType set value.
142 if (this.baseName
.equals("")) {
143 throw new BuildException ("Must set OutputFileBasename!\n");
146 if (this.ffsFileGuid
.equals("")) {
147 throw new BuildException ("Must set ffsFileGuid!\n");
150 if (this.ffsFileType
.equals("")) {
151 throw new BuildException ("Must set ffsFileType!\n");
155 // Create ffs file. File name = FfsFileGuid + BaseName + ffsSuffix.
156 // If outputDir's value was set, file will output to the outputDir.
158 ffsSuffix
= TypeToSuffix (this.moduleType
);
159 if (!this.outputDir
.equals("")) {
161 outputPath
= this.outputDir
;
162 temp
= outputPath
.replace('\\', File
.separatorChar
);
163 outputPath
= temp
.replace('/', File
.separatorChar
);
164 if (outputPath
.charAt(outputPath
.length()-1) != File
.separatorChar
) {
165 outputPath
= outputPath
+ File
.separator
;
170 String ffsFilePath
= outputPath
+ this.ffsFileGuid
+ '-' + this.baseName
+ ffsSuffix
;
171 File ffsFile
= new File (ffsFilePath
);
178 This function is to add compress section to section list.
179 @param compress Section of compress
181 public void addCompress(CompressSection compress
) {
182 this.sectionList
.add(compress
);
188 This function is to add tool section to section list.
189 @param tool Section of tool
191 public void addTool(Tool tool
) {
192 this.sectionList
.add(tool
);
198 This function is to add sectFile section to section list.
199 @param sectFile Section of sectFile.
201 public void addSectFile (SectFile sectFile
) {
202 this.sectionList
.add(sectFile
);
208 This function is to get basename
210 @return String of base name
212 public String
getBaseName() {
213 return this.baseName
;
219 This function is to set base name.
222 public void setBaseName(String baseName
) {
223 this.baseName
= baseName
.trim();
229 This function is to get the ffsAligment
230 @return The value of ffsAligment.
232 public int getFfsAttribDataAlignment() {
233 return this.ffsAttribDataAlignment
;
239 This function is to set ffsAligment
240 @param ffsAligment The value of ffsAligment.
242 public void setFfsAttribDataAlignment(String ffsAligment
) {
243 this.ffsAttribDataAlignment
= stringToInt(ffsAligment
.replaceAll(" ", "").toLowerCase());
244 if (this.ffsAttribDataAlignment
< 0 || this.ffsAttribDataAlignment
> 7) {
245 throw new BuildException ("FFS_ATTRIB_DATA_ALIGMENT must be an integer value from 0 through 7, inclusive");
247 attributes
|= (((byte)this.ffsAttribDataAlignment
) << 3);
254 This function is to get ffsAttribCheckSum
256 @return Value of ffsAttribChecksum
258 public boolean getFfsAttribChecksum() {
259 return this.FfsAttribChecksum
;
265 This function is to set ffsAttribChecksum
266 @param ffsAttributeCheckSum Value of ffsAttribCheckSum
268 public void setFfsAttribChecksum(boolean ffsAttributeCheckSum
) {
269 this.FfsAttribChecksum
= ffsAttributeCheckSum
;
270 if (ffsAttributeCheckSum
) {
271 attributes
|= FFS_ATTRIB_CHECKSUM
;
278 This function is to get ffsAttribRecovery
279 @return Value of ffsAttribRecovery
281 public boolean getFfsAttribRecovery() {
282 return this.ffsAttribRecovery
;
288 This function is to set ffsAttributeRecovery
290 @param ffsAttributeRecovery Value of ffsAttributeRecovery
292 public void setRecovery(boolean ffsAttributeRecovery
) {
293 this.ffsAttribRecovery
= ffsAttributeRecovery
;
294 if (ffsAttributeRecovery
) {
295 attributes
|= FFS_ATTRIB_RECOVERY
;
302 This function is to get fileGuid
305 public String
getFileGuid() {
306 return this.ffsFileGuid
;
312 This function is to set fileGuid
313 @param ffsFileGuid String of GUID
315 public void setFileGuid(String ffsFileGuid
) {
316 this.ffsFileGuid
= ffsFileGuid
.trim();
322 This function is to get ffsFileType.
324 @return value of ffsFileType
326 public String
getFfsFileType() {
327 return this.ffsFileType
;
333 This function is to set ffsFileType.
337 public void setFfsFileType(String ffsFileType
) {
338 this.ffsFileType
= ffsFileType
.trim();
342 ffsAttribHeaderExtension
344 This function is to get ffsAttribHeaderExtension
346 @return Value of ffsAttribHeaderExtension
348 public boolean isFfsAttribHeaderExtension() {
349 return this.ffsAttribHeaderExtension
;
355 This function is to set headerExtension
356 @param headerExtension Value of headerExension
358 public void setHeaderExtension(boolean headerExtension
) {
359 this.ffsAttribHeaderExtension
= headerExtension
;
360 if (headerExtension
) {
361 attributes
|= FFS_ATTRIB_HEADER_EXTENSION
;
366 isFfsAttribTailPresent
368 This function is to get ffsAttribTailPresent value.
369 @return Value of ffsAttribTailPresent.
371 public boolean isFfsAttribTailPresent() {
372 return this.ffsAttribTailPresent
;
376 setFfsAttribTailPresent
378 This function is to set ffsAttribTailPresent.
379 @param tailPresent Value of ffsAttribTailPresent.
381 public void setFfsAttribTailPresent(boolean tailPresent
) {
382 this.ffsAttribTailPresent
= tailPresent
;
384 attributes
|= FFS_ATTRIB_TAIL_PRESENT
;
392 This function is to convert string to GUID.
393 * @param GuidStr String of GUID.
394 * @param Guid GUID form.
396 private void stringToGuid (String GuidStr
, FfsHeader
.FfsGuid Guid
){
404 byte[] buffer
= new byte[16];
405 if (GuidStr
.length()!=36) {
406 throw new BuildException ("The GUID length [" + GuidStr
.length() + "] is not correct!");
410 SplitStr
= GuidStr
.split("-");
411 if (SplitStr
.length
!= 5) {
412 throw new BuildException ("The GUID format is not correct!");
417 for (i
= 0; i
< SplitStr
.length
; i
++) {
418 String str
= SplitStr
[i
];
419 charArry
= str
.toCharArray();
421 for (j
=0; j
< (str
.toCharArray().length
)/2; j
++) {
423 buffer
[k
] = hexCharToByte (charArry
[j
*2]);
424 buffer
[k
] = (byte)( buffer
[k
]& 0x0f);
425 buffer
[k
] = (byte)((buffer
[k
]<< 4));
426 buffer
[k
] = (byte)( buffer
[k
]& 0xf0);
427 buffer
[k
] = (byte)( buffer
[k
]|hexCharToByte(charArry
[j
*2+1]));
431 Guid
.bufferToStruct(buffer
);
437 This function is to get suffix of ffs file according to ffsFileType.
439 @param ffsFileType ffsFileType
440 @return The suffix of ffs file
442 private String
TypeToSuffix (String ffsFileType
){
443 String
[][] suffix
= { { "BASE", ".FFS"},
444 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
445 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
446 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
447 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
448 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
449 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
451 for (int i
= 0; i
< suffix
.length
; i
++) {
452 if (suffix
[i
][0].equalsIgnoreCase(moduleType
)) {
464 This function is to get ffsFileType integer value according to ffsFileType.
465 @param ffsFileType String value of ffsFileType
466 @return Integer value of ffsFileType.
468 private byte stringToType (String ffsFileType
){
470 if (ffsFileType
.equals("EFI_FV_FILETYPE_ALL")) {
471 return(byte)EFI_FV_FILETYPE_ALL
;
474 if (ffsFileType
.equals("EFI_FV_FILETYPE_RAW")) {
475 return(byte)EFI_FV_FILETYPE_RAW
;
478 if (ffsFileType
.equals("EFI_FV_FILETYPE_FREEFORM")) {
479 return(byte)EFI_FV_FILETYPE_FREEFORM
;
482 if (ffsFileType
.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {
483 return(byte)EFI_FV_FILETYPE_SECURITY_CORE
;
486 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEI_CORE")) {
487 return(byte) EFI_FV_FILETYPE_PEI_CORE
;
490 if (ffsFileType
.equals("EFI_FV_FILETYPE_DXE_CORE")) {
491 return(byte)EFI_FV_FILETYPE_DXE_CORE
;
494 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEIM")) {
495 return(byte)EFI_FV_FILETYPE_PEIM
;
498 if (ffsFileType
.equals("EFI_FV_FILETYPE_DRIVER")) {
499 return(byte) EFI_FV_FILETYPE_DRIVER
;
502 if (ffsFileType
.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {
503 return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
506 if (ffsFileType
.equals("EFI_FV_FILETYPE_APPLICATION")) {
507 return(byte)EFI_FV_FILETYPE_APPLICATION
;
510 if (ffsFileType
.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {
511 return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
513 if (ffsFileType
.equals("EFI_FV_FILETYPE_FFS_PAD")) {
514 return(byte) EFI_FV_FILETYPE_FFS_PAD
;
525 This function is to calculate the value needed for a valid UINT8 checksum
526 @param buffer Byte buffer containing byte data of component.
527 @param size Size of the buffer.
528 @return The 8 bit checksum value needed.
530 private byte calculateChecksum8 (byte[] buffer
, int size
){
531 return(byte) (0x100 - calculateSum8 (buffer
, size
));
538 This function is to calculate the UINT8 sum for the requested region.
539 @param buffer Byte buffer containing byte data of component
540 @param size Size of the buffer.
541 @return The 8 bit checksum value needed.
543 private short calculateSum8 (byte[] buffer
, int size
){
549 // Perform the word sum for buffer
551 for (Index
= 0; Index
< size
; Index
++) {
552 Sum
= (byte) (Sum
+ buffer
[Index
]);
561 This function is to convert hex character to byte
563 @param hexChar hex character
564 @return Byte which corresponding to the character.
566 private byte hexCharToByte (char hexChar
){
617 This function is used to adjusts file size to insure sectioned file is exactly the right length such
618 that it ends on exactly the last byte of the last section. ProcessScript()
619 may have padded beyond the end of the last section out to a 4 byte boundary.
620 This padding is stripped.
622 @param buffer Byte buffer contains a section stream
623 @return Corrected size of file.
625 private int adjustFileSize (byte[] buffer
){
627 int orignalLen
= buffer
.length
;
629 int sectionPoint
= 0;
630 int nextSectionPoint
= 0;
633 int firstSectionHeader
= 0;
636 firstSectionHeader
= buffer
[0]& 0xff;
637 firstSectionHeader
= ((buffer
[1]&0xff)<<8) | firstSectionHeader
;
638 firstSectionHeader
= ((buffer
[2]&0xff)<<16)| firstSectionHeader
;
641 while (sectionPoint
< buffer
.length
) {
642 sectionLen
= buffer
[0 + sectionPoint
]& 0xff;
643 sectionLen
= ((buffer
[1 + sectionPoint
]&0xff)<<8)| sectionLen
;
644 sectionLen
= ((buffer
[2 + sectionPoint
]&0xff)<<16)| sectionLen
;
645 totalLen
= totalLen
+ sectionLen
;
647 if (totalLen
== orignalLen
) {
651 sectionPoint
= sectionPoint
+ sectionLen
;
652 adjustLen
= sectionPoint
;
654 nextSectionPoint
= (sectionPoint
+ 0x03) & (~
0x03);
655 totalLen
= totalLen
+ nextSectionPoint
- sectionLen
;
656 sectionPoint
= nextSectionPoint
;
664 This function is to get output directory.
666 @return Path of output directory.
668 public String
getOutputDir() {
675 This function is to set output directory.
677 @param outputDir The output direcotry.
679 public void setOutputDir(String outputDir
) {
680 this.outputDir
= outputDir
;
686 This function is to get string of module type.
688 @return moduleType The string of module type.
690 public String
getModuleType() {
691 return this.moduleType
;
697 This function is to set moduleType.
699 @param moduleType The string of module type.
701 public void setModuleType(String moduleType
) {
702 this.moduleType
= moduleType
;
706 Convert a string to a integer.
708 @param intString The string representing a integer
710 @retval int The value of integer represented by the
711 given string; -1 is returned if the format
712 of the string is wrong.
714 private int stringToInt(String intString
) {
716 int hexPrefixPos
= intString
.indexOf("0x");
718 String intStringNoPrefix
;
720 if (hexPrefixPos
>= 0) {
722 intStringNoPrefix
= intString
.substring(hexPrefixPos
+ 2, intString
.length());
724 intStringNoPrefix
= intString
;
728 value
= Integer
.parseInt(intStringNoPrefix
, radix
);
729 } catch (NumberFormatException e
) {
730 log("Incorrect format of int [" + intString
+ "]. -1 is assumed");
740 This function is to generate FFS file.
742 @param ffsFile Name of FFS file.
743 @param isOrg Flag to indicate generate ORG ffs file or not.
745 private void genFfs(File ffsFile
) {
749 FfsHeader ffsHeader
= new FfsHeader();
750 FfsHeader orgFfsHeader
= new FfsHeader();
752 EdkLog
.log(this, EdkLog
.EDK_INFO
, ffsFile
.getName());
756 // Create file output stream -- dataBuffer.
758 FileOutputStream dataFs
= new FileOutputStream (ffsFile
.getAbsolutePath());
759 DataOutputStream dataBuffer
= new DataOutputStream (dataFs
);
762 // Search SectionList find earch section and call it's
763 // ToBuffer function.
765 Iterator sectionIter
= this.sectionList
.iterator();
766 while (sectionIter
.hasNext()) {
767 sect
= (Section
)sectionIter
.next();
771 // The last section don't need 4 byte ffsAligment.
773 sect
.toBuffer((DataOutputStream
)dataBuffer
);
774 } catch (Exception e
) {
775 throw new BuildException (e
.getMessage());
779 } catch (Exception e
) {
780 throw new BuildException (e
.getMessage());
784 // Creat Ffs file header
789 // create input stream to read file data
791 byte[] fileBuffer
= new byte[(int)ffsFile
.length()];
792 FileInputStream fi
= new FileInputStream (ffsFile
.getAbsolutePath());
793 DataInputStream di
= new DataInputStream (fi
);
798 // Add GUID to header struct
800 if (this.ffsFileGuid
!= null) {
801 stringToGuid (this.ffsFileGuid
, ffsHeader
.name
);
804 ffsHeader
.ffsAttributes
= this.attributes
;
805 if ((ffsHeader
.fileType
= stringToType(this.ffsFileType
))== -1) {
806 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
810 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
813 orgFfsHeader
.ffsAttributes
= ffsHeader
.ffsAttributes
;
814 orgFfsHeader
.fileType
= ffsHeader
.fileType
;
817 // Adjust file size. The function is used to tripe the last
818 // section padding of 4 binary boundary.
821 if (ffsHeader
.fileType
!= EFI_FV_FILETYPE_RAW
) {
823 fileDataSize
= adjustFileSize (fileBuffer
);
825 fileDataSize
= fileBuffer
.length
;
829 // 1. add header size to file size
831 fileSize
= fileDataSize
+ ffsHeader
.getSize();
833 if ((ffsHeader
.ffsAttributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
834 if (ffsHeader
.fileType
== EFI_FV_FILETYPE_FFS_PAD
) {
836 throw new BuildException (
837 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
838 "invalid for PAD files"
841 if (fileSize
== ffsHeader
.getSize()) {
842 throw new BuildException (
843 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
844 "invalid for 0-length files"
847 fileSize
= fileSize
+ 2;
851 // 2. set file size to header struct
853 ffsHeader
.ffsFileSize
[0] = (byte)(fileSize
& 0x00FF);
854 ffsHeader
.ffsFileSize
[1] = (byte)((fileSize
& 0x00FF00)>>8);
855 ffsHeader
.ffsFileSize
[2] = (byte)(((int)fileSize
& 0xFF0000)>>16);
858 // Fill in checksums and state, these must be zero for checksumming
860 ffsHeader
.integrityCheck
.header
= calculateChecksum8 (
861 ffsHeader
.structToBuffer(),
865 if ((this.attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
866 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
867 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
872 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
878 ffsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
879 orgFfsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
883 // Set the state now. Spec says the checksum assumes the state is 0.
885 ffsHeader
.ffsState
= EFI_FILE_HEADER_CONSTRUCTION
|
886 EFI_FILE_HEADER_VALID
|
890 // create output stream to first write header data in file, then write sect data in file.
892 FileOutputStream headerFfs
= new FileOutputStream (ffsFile
.getAbsolutePath());
893 DataOutputStream ffsBuffer
= new DataOutputStream (headerFfs
);
896 // Add header struct and file data to FFS file
898 ffsBuffer
.write(ffsHeader
.structToBuffer());
899 ffsBuffer
.write(fileBuffer
, 0, fileDataSize
);
904 // If there is a tail, then set it
906 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
908 byte [] tailByte
= new byte[2];
911 // reverse tailvalue , integritycheck.file as hight byte, and
912 // integritycheck.header as low byte.
914 tailValue
= (short)(ffsHeader
.integrityCheck
.header
& 0xff);
915 tailValue
= (short)((tailValue
) | ((ffsHeader
.integrityCheck
.file
<< 8) & 0xff00));
916 tailValue
= (short)~tailValue
;
919 // Change short to byte[2]
921 tailByte
[0] = (byte)(tailValue
& 0xff);
922 tailByte
[1] = (byte)((tailValue
& 0xff00)>>8);
923 ffsBuffer
.write(tailByte
[0]);
924 ffsBuffer
.write(tailByte
[1]);
929 // close output stream. Note if don't close output stream
930 // the buffer can't be rewritten to file.
933 } catch (Exception e
) {
934 log("genffsfile failed!");
935 throw new BuildException (e
.getMessage());
943 This function is to add gensection instance to list
945 @param task Instance of GenSectionTask
947 public void addGenSection (GenSectionTask task
){
948 this.sectionList
.add(task
);