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
;
34 GenFfsFileTaks is to generate ffs file.
37 public class GenFfsFileTask
extends Task
implements EfiDefine
, FfsTypes
{
39 * GenFfsFile Task Class
41 * -baseName : module baseName
42 * -ffsFileGuid : module Guid.
43 * -ffsFileType : Ffs file type.
44 * -ffsAttributeRecovery : The file is required for recovery.
45 * -ffsAligment : The file data alignment (0 if none required). See FFS
46 * specification for supported alignments (0-7 are only possible
48 * -ffsAttributeCheckSum : The file data is checksummed. If this is FALSE a
49 * value of 0x5A will be inserted in the file
50 * checksum field of the file header. *
51 * -sectFileDir : specifies the full path to the component build directory.
53 * -ffsAttrib : Data recorde attribute added result.
54 * -sectionList : List recorded all section elemet in task.
67 String ffsFileGuid
= "";
71 String ffsFileType
= "";
73 /// ffsAttribHeaderExtension value is used to set the corresponding bit in
74 /// the output FFS file header
76 boolean ffsAttribHeaderExtension
= false;
78 /// ffsAttribTailPresent value is used to set the corresponding bit in the
79 /// output FFS file header
81 boolean ffsAttribTailPresent
= false;
83 /// ffsAttribRecovery value is used to set the corresponding bit in the
84 /// output FFS file header
86 boolean ffsAttribRecovery
= false;
88 /// ffsAttribDataAlignment value is used to set the corresponding bit in the output
89 /// FFS file header.The specified FFS alignment must be a value between 0
92 int ffsAttribDataAlignment
= 0;
94 /// ffsAttribChecksum value is used to set the corresponding bit in the
95 /// output FFS file header
97 boolean FfsAttribChecksum
= false;
99 /// Attribute is used to record the sum of all bit in the output FFS file.
103 /// The output directory of ffs file.
105 String outputDir
= "";
109 List
<Object
> sectionList
= new ArrayList
<Object
>();
112 /// The path of Framewor_Tools_Paht.
114 static String path
= "";
119 GenFfsFileTask execute is to generate ffs file according to input section
120 dscriptive information.
122 public void execute() throws BuildException
{
130 FfsHeader ffsHeader
= new FfsHeader();
131 FfsHeader orgFfsHeader
= new FfsHeader();
132 String ffsSuffix
= "";
133 String outputPath
= "";
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 BaseName!\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 ffsFile
= new File (ffsFilePath
);
175 // Create ffs ORG file. fileName = FfsFileGuid + BaseName + ffsSuffix +
178 ffsOrgFile
= new File(ffsFilePath
+ ".org");
180 log(ffsFile
.getName());
181 log(ffsOrgFile
.getName());
184 // Create file output stream -- dataBuffer.
186 FileOutputStream dataFs
= new FileOutputStream (ffsFile
.getAbsolutePath());
187 DataOutputStream dataBuffer
= new DataOutputStream (dataFs
);
190 // Create org file output stream -- orgDataBuffer
192 FileOutputStream orgDataFs
= new FileOutputStream (ffsOrgFile
.getAbsolutePath());
193 DataOutputStream orgDataBuffer
= new DataOutputStream (orgDataFs
);
196 // Search SectionList find earch section and call it's
197 // ToBuffer function.
199 Iterator sectionIter
= this.sectionList
.iterator();
200 while (sectionIter
.hasNext()) {
201 sect
= (Section
)sectionIter
.next();
205 // The last section don't need 4 byte ffsAligment.
207 sect
.toBuffer((DataOutputStream
)dataBuffer
, (DataOutputStream
) orgDataBuffer
);
208 } catch (Exception e
) {
209 throw new BuildException (e
.getMessage());
213 orgDataBuffer
.close();
214 } catch (Exception e
) {
215 throw new BuildException (e
.getMessage());
219 // Creat Ffs file header
224 // create input stream to read file data
226 byte[] fileBuffer
= new byte[(int)ffsFile
.length()];
227 FileInputStream fi
= new FileInputStream (ffsFile
.getAbsolutePath());
228 DataInputStream di
= new DataInputStream (fi
);
233 // create input org stream to read file data
235 byte[] orgFileBuffer
= new byte[(int)ffsOrgFile
.length()];
236 FileInputStream ofi
= new FileInputStream (ffsOrgFile
.getAbsolutePath());
237 DataInputStream odi
= new DataInputStream (ofi
);
238 odi
.read(orgFileBuffer
);
242 // Add GUID to header struct
244 if (this.ffsFileGuid
!= null) {
245 stringToGuid (this.ffsFileGuid
, ffsHeader
.name
);
247 // Add Guid to org header struct
249 stringToGuid (this.ffsFileGuid
, orgFfsHeader
.name
);
252 ffsHeader
.ffsAttributes
= this.attributes
;
253 if ((ffsHeader
.fileType
= stringToType(this.ffsFileType
))== -1) {
254 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
258 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
261 orgFfsHeader
.ffsAttributes
= ffsHeader
.ffsAttributes
;
262 orgFfsHeader
.fileType
= ffsHeader
.fileType
;
265 // Adjust file size. The function is used to tripe the last
266 // section padding of 4 binary boundary.
269 if (ffsHeader
.fileType
!= EFI_FV_FILETYPE_RAW
) {
271 fileDataSize
= adjustFileSize (fileBuffer
);
272 orgFileDataSize
= adjustFileSize (orgFileBuffer
);
275 fileDataSize
= fileBuffer
.length
;
276 orgFileDataSize
= orgFileBuffer
.length
;
280 // 1. add header size to file size
282 fileSize
= fileDataSize
+ ffsHeader
.getSize();
284 // add header size to org file size
286 orgFileSize
= orgFileDataSize
+ ffsHeader
.getSize();
288 if ((ffsHeader
.ffsAttributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
289 if (ffsHeader
.fileType
== EFI_FV_FILETYPE_FFS_PAD
) {
291 throw new BuildException (
292 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
293 "invalid for PAD files"
296 if (fileSize
== ffsHeader
.getSize()) {
297 throw new BuildException (
298 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
299 "invalid for 0-length files"
302 fileSize
= fileSize
+ 2;
303 orgFileSize
= orgFileSize
+ 2;
307 // 2. set file size to header struct
309 ffsHeader
.ffsFileSize
[0] = (byte)(fileSize
& 0x00FF);
310 ffsHeader
.ffsFileSize
[1] = (byte)((fileSize
& 0x00FF00)>>8);
311 ffsHeader
.ffsFileSize
[2] = (byte)(((int)fileSize
& 0xFF0000)>>16);
314 // set file size to org header struct
316 orgFfsHeader
.ffsFileSize
[0] = (byte)(orgFileSize
& 0x00FF);
317 orgFfsHeader
.ffsFileSize
[1] = (byte)((orgFileSize
& 0x00FF00)>>8);
318 orgFfsHeader
.ffsFileSize
[2] = (byte)(((int)orgFileSize
& 0xFF0000)>>16);
321 // Fill in checksums and state, these must be zero for checksumming
323 ffsHeader
.integrityCheck
.header
= calculateChecksum8 (
324 ffsHeader
.structToBuffer(),
328 // Fill in org file's header check sum and state
330 orgFfsHeader
.integrityCheck
.header
= calculateChecksum8 (
331 orgFfsHeader
.structToBuffer(),
332 orgFfsHeader
.getSize()
335 if ((this.attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
336 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
337 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
342 // Add org file header
344 orgFfsHeader
.integrityCheck
.file
= calculateChecksum8 (
349 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
354 // Add org file header
356 orgFfsHeader
.integrityCheck
.file
= calculateChecksum8 (
362 ffsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
363 orgFfsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
367 // Set the state now. Spec says the checksum assumes the state is 0.
369 ffsHeader
.ffsState
= EFI_FILE_HEADER_CONSTRUCTION
|
370 EFI_FILE_HEADER_VALID
|
372 orgFfsHeader
.ffsState
= ffsHeader
.ffsState
;
375 // create output stream to first write header data in file, then write sect data in file.
377 FileOutputStream headerFfs
= new FileOutputStream (ffsFile
.getAbsolutePath());
378 DataOutputStream ffsBuffer
= new DataOutputStream (headerFfs
);
380 FileOutputStream orgHeaderFfs
= new FileOutputStream (ffsOrgFile
.getAbsolutePath());
381 DataOutputStream orgFfsBuffer
= new DataOutputStream (orgHeaderFfs
);
384 // Add header struct and file data to FFS file
386 ffsBuffer
.write(ffsHeader
.structToBuffer());
387 orgFfsBuffer
.write(orgFfsHeader
.structToBuffer());
389 for (int i
= 0; i
< fileDataSize
; i
++) {
390 ffsBuffer
.write(fileBuffer
[i
]);
393 for (int i
= 0; i
< orgFileDataSize
; i
++){
394 orgFfsBuffer
.write(orgFileBuffer
[i
]);
398 // If there is a tail, then set it
400 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
402 byte [] tailByte
= new byte[2];
405 // reverse tailvalue , integritycheck.file as hight byte, and
406 // integritycheck.header as low byte.
408 tailValue
= (short)(ffsHeader
.integrityCheck
.header
& 0xff);
409 tailValue
= (short)((tailValue
) | ((ffsHeader
.integrityCheck
.file
<< 8) & 0xff00));
410 tailValue
= (short)~tailValue
;
413 // Change short to byte[2]
415 tailByte
[0] = (byte)(tailValue
& 0xff);
416 tailByte
[1] = (byte)((tailValue
& 0xff00)>>8);
417 ffsBuffer
.write(tailByte
[0]);
418 ffsBuffer
.write(tailByte
[1]);
420 orgFfsBuffer
.write(tailByte
[0]);
421 orgFfsBuffer
.write(tailByte
[1]);
425 // close output stream. Note if don't close output stream
426 // the buffer can't be rewritten to file.
429 orgFfsBuffer
.close();
430 } catch (Exception e
) {
431 log("genffsfile failed!");
432 throw new BuildException (e
.getMessage());
439 This function is to add compress section to section list.
440 @param compress Section of compress
442 public void addCompress(CompressSection compress
) {
443 this.sectionList
.add(compress
);
449 This function is to add tool section to section list.
450 @param tool Section of tool
452 public void addTool(Tool tool
) {
453 this.sectionList
.add(tool
);
459 This function is to add sectFile section to section list.
460 @param sectFile Section of sectFile.
462 public void addSectFile (SectFile sectFile
) {
463 this.sectionList
.add(sectFile
);
469 This function is to get basename
471 @return String of base name
473 public String
getBaseName() {
474 return this.baseName
;
480 This function is to set base name.
483 public void setBaseName(String baseName
) {
484 this.baseName
= baseName
.trim();
490 This function is to get the ffsAligment
491 @return The value of ffsAligment.
493 public int getFfsAttribDataAlignment() {
494 return this.ffsAttribDataAlignment
;
500 This function is to set ffsAligment
501 @param ffsAligment The value of ffsAligment.
503 public void setFfsAttribDataAlignment(int ffsAligment
) {
504 this.ffsAttribDataAlignment
= ffsAligment
;
505 if (this.ffsAttribDataAlignment
> 7) {
506 throw new BuildException ("FFS_ALIGMENT Scope is 0-7");
508 attributes
|= (((byte)this.ffsAttribDataAlignment
) << 3);
515 This function is to get ffsAttribCheckSum
517 @return Value of ffsAttribChecksum
519 public boolean getFfsAttribChecksum() {
520 return this.FfsAttribChecksum
;
526 This function is to set ffsAttribChecksum
527 @param ffsAttributeCheckSum Value of ffsAttribCheckSum
529 public void setFfsAttribChecksum(boolean ffsAttributeCheckSum
) {
530 this.FfsAttribChecksum
= ffsAttributeCheckSum
;
531 if (ffsAttributeCheckSum
) {
532 attributes
|= FFS_ATTRIB_CHECKSUM
;
539 This function is to get ffsAttribRecovery
540 @return Value of ffsAttribRecovery
542 public boolean getFfsAttribRecovery() {
543 return this.ffsAttribRecovery
;
549 This function is to set ffsAttributeRecovery
551 @param ffsAttributeRecovery Value of ffsAttributeRecovery
553 public void setRecovery(boolean ffsAttributeRecovery
) {
554 this.ffsAttribRecovery
= ffsAttributeRecovery
;
555 if (ffsAttributeRecovery
) {
556 attributes
|= FFS_ATTRIB_RECOVERY
;
563 This function is to get fileGuid
566 public String
getFileGuid() {
567 return this.ffsFileGuid
;
573 This function is to set fileGuid
574 @param ffsFileGuid String of GUID
576 public void setFileGuid(String ffsFileGuid
) {
577 this.ffsFileGuid
= ffsFileGuid
.trim();
583 This function is to get ffsFileType.
585 @return value of ffsFileType
587 public String
getFfsFileType() {
588 return this.ffsFileType
;
594 This function is to set ffsFileType.
598 public void setFfsFileType(String ffsFileType
) {
599 this.ffsFileType
= ffsFileType
.trim();
603 ffsAttribHeaderExtension
605 This function is to get ffsAttribHeaderExtension
607 @return Value of ffsAttribHeaderExtension
609 public boolean isFfsAttribHeaderExtension() {
610 return this.ffsAttribHeaderExtension
;
616 This function is to set headerExtension
617 @param headerExtension Value of headerExension
619 public void setHeaderExtension(boolean headerExtension
) {
620 this.ffsAttribHeaderExtension
= headerExtension
;
621 if (headerExtension
) {
622 attributes
|= FFS_ATTRIB_HEADER_EXTENSION
;
627 isFfsAttribTailPresent
629 This function is to get ffsAttribTailPresent value.
630 @return Value of ffsAttribTailPresent.
632 public boolean isFfsAttribTailPresent() {
633 return this.ffsAttribTailPresent
;
637 setFfsAttribTailPresent
639 This function is to set ffsAttribTailPresent.
640 @param tailPresent Value of ffsAttribTailPresent.
642 public void setFfsAttribTailPresent(boolean tailPresent
) {
643 this.ffsAttribTailPresent
= tailPresent
;
645 attributes
|= FFS_ATTRIB_TAIL_PRESENT
;
653 This function is to convert string to GUID.
654 * @param GuidStr String of GUID.
655 * @param Guid GUID form.
657 private void stringToGuid (String GuidStr
, FfsHeader
.FfsGuid Guid
){
665 byte[] buffer
= new byte[16];
666 if (GuidStr
.length()!=36) {
667 throw new BuildException ("Guid length is not correct!");
671 SplitStr
= GuidStr
.split("-");
672 if (SplitStr
.length
!= 5) {
673 throw new BuildException ("Guid type is not correct!");
678 for (i
= 0; i
< SplitStr
.length
; i
++) {
679 String str
= SplitStr
[i
];
680 charArry
= str
.toCharArray();
682 for (j
=0; j
< (str
.toCharArray().length
)/2; j
++) {
684 buffer
[k
] = hexCharToByte (charArry
[j
*2]);
685 buffer
[k
] = (byte)( buffer
[k
]& 0x0f);
686 buffer
[k
] = (byte)((buffer
[k
]<< 4));
687 buffer
[k
] = (byte)( buffer
[k
]& 0xf0);
688 buffer
[k
] = (byte)( buffer
[k
]|hexCharToByte(charArry
[j
*2+1]));
692 Guid
.bufferToStruct(buffer
);
698 This function is to get suffix of ffs file according to ffsFileType.
700 @param ffsFileType ffsFileType
701 @return The suffix of ffs file
703 private String
TypeToSuffix (String ffsFileType
){
704 String
[][] suffix
= { { "BASE", ".FFS"},
705 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
706 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
707 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
708 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
709 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
710 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
712 for (int i
= 0; i
< suffix
.length
; i
++) {
713 if (suffix
[i
][0].equalsIgnoreCase(moduleType
)) {
725 This function is to get ffsFileType integer value according to ffsFileType.
726 @param ffsFileType String value of ffsFileType
727 @return Integer value of ffsFileType.
729 private byte stringToType (String ffsFileType
){
731 if (ffsFileType
.equals("EFI_FV_FILETYPE_ALL")) {
732 return(byte)EFI_FV_FILETYPE_ALL
;
735 if (ffsFileType
.equals("EFI_FV_FILETYPE_RAW")) {
736 return(byte)EFI_FV_FILETYPE_RAW
;
739 if (ffsFileType
.equals("EFI_FV_FILETYPE_FREEFORM")) {
740 return(byte)EFI_FV_FILETYPE_FREEFORM
;
743 if (ffsFileType
.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {
744 return(byte)EFI_FV_FILETYPE_SECURITY_CORE
;
747 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEI_CORE")) {
748 return(byte) EFI_FV_FILETYPE_PEI_CORE
;
751 if (ffsFileType
.equals("EFI_FV_FILETYPE_DXE_CORE")) {
752 return(byte)EFI_FV_FILETYPE_DXE_CORE
;
755 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEIM")) {
756 return(byte)EFI_FV_FILETYPE_PEIM
;
759 if (ffsFileType
.equals("EFI_FV_FILETYPE_DRIVER")) {
760 return(byte) EFI_FV_FILETYPE_DRIVER
;
763 if (ffsFileType
.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {
764 return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
767 if (ffsFileType
.equals("EFI_FV_FILETYPE_APPLICATION")) {
768 return(byte)EFI_FV_FILETYPE_APPLICATION
;
771 if (ffsFileType
.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {
772 return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
774 if (ffsFileType
.equals("EFI_FV_FILETYPE_FFS_PAD")) {
775 return(byte) EFI_FV_FILETYPE_FFS_PAD
;
786 This function is to calculate the value needed for a valid UINT8 checksum
787 @param buffer Byte buffer containing byte data of component.
788 @param size Size of the buffer.
789 @return The 8 bit checksum value needed.
791 private byte calculateChecksum8 (byte[] buffer
, int size
){
792 return(byte) (0x100 - calculateSum8 (buffer
, size
));
799 This function is to calculate the UINT8 sum for the requested region.
800 @param buffer Byte buffer containing byte data of component
801 @param size Size of the buffer.
802 @return The 8 bit checksum value needed.
804 private short calculateSum8 (byte[] buffer
, int size
){
810 // Perform the word sum for buffer
812 for (Index
= 0; Index
< size
; Index
++) {
813 Sum
= (byte) (Sum
+ buffer
[Index
]);
822 This function is to convert hex character to byte
824 @param hexChar hex character
825 @return Byte which corresponding to the character.
827 private byte hexCharToByte (char hexChar
){
878 This function is used to adjusts file size to insure sectioned file is exactly the right length such
879 that it ends on exactly the last byte of the last section. ProcessScript()
880 may have padded beyond the end of the last section out to a 4 byte boundary.
881 This padding is stripped.
883 @param buffer Byte buffer contains a section stream
884 @return Corrected size of file.
886 private int adjustFileSize (byte[] buffer
){
888 int orignalLen
= buffer
.length
;
890 int sectionPoint
= 0;
891 int nextSectionPoint
= 0;
894 int firstSectionHeader
= 0;
897 firstSectionHeader
= buffer
[0]& 0xff;
898 firstSectionHeader
= ((buffer
[1]&0xff)<<8) | firstSectionHeader
;
899 firstSectionHeader
= ((buffer
[2]&0xff)<<16)| firstSectionHeader
;
902 while (sectionPoint
< buffer
.length
) {
903 sectionLen
= buffer
[0 + sectionPoint
]& 0xff;
904 sectionLen
= ((buffer
[1 + sectionPoint
]&0xff)<<8)| sectionLen
;
905 sectionLen
= ((buffer
[2 + sectionPoint
]&0xff)<<16)| sectionLen
;
906 totalLen
= totalLen
+ sectionLen
;
908 if (totalLen
== orignalLen
) {
912 sectionPoint
= sectionPoint
+ sectionLen
;
913 adjustLen
= sectionPoint
;
915 nextSectionPoint
= (sectionPoint
+ 0x03) & (~
0x03);
916 totalLen
= totalLen
+ nextSectionPoint
- sectionLen
;
917 sectionPoint
= nextSectionPoint
;
925 This function is to get output directory.
927 @return Path of output directory.
929 public String
getOutputDir() {
936 This function is to set output directory.
938 @param outputDir The output direcotry.
940 public void setOutputDir(String outputDir
) {
941 this.outputDir
= outputDir
;
944 public String
getModuleType() {
945 return this.moduleType
;
948 public void setModuleType(String moduleType
) {
949 this.moduleType
= moduleType
;