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 /// ffsAligenment 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
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 ffsFile
= new File (outputPath
+ this.ffsFileGuid
+ '-' + this.baseName
+ ffsSuffix
);
173 System
.out
.print("General Ffs file: file name is:\n");
174 System
.out
.print(outputPath
+ this.ffsFileGuid
+ '-' + this.baseName
+ ffsSuffix
);
175 System
.out
.print("\n");
178 // Create ffs ORG file. fileName = FfsFileGuid + BaseName + ffsSuffix +
181 ffsOrgFile
= new File(outputPath
+ this.ffsFileGuid
+ '-' + this.baseName
+ ffsSuffix
+ ".org");
185 // Create file output stream -- dataBuffer.
187 FileOutputStream dataFs
= new FileOutputStream (ffsFile
.getAbsolutePath());
188 DataOutputStream dataBuffer
= new DataOutputStream (dataFs
);
191 // Create org file output stream -- orgDataBuffer
193 FileOutputStream orgDataFs
= new FileOutputStream (ffsOrgFile
.getAbsolutePath());
194 DataOutputStream orgDataBuffer
= new DataOutputStream (orgDataFs
);
197 // Search SectionList find earch section and call it's
198 // ToBuffer function.
200 Iterator sectionIter
= this.sectionList
.iterator();
201 while (sectionIter
.hasNext()) {
202 sect
= (Section
)sectionIter
.next();
206 // The last section don't need 4 byte ffsAligment.
208 sect
.toBuffer((DataOutputStream
)dataBuffer
, (DataOutputStream
) orgDataBuffer
);
209 } catch (Exception e
) {
210 throw new BuildException (e
.getMessage());
214 orgDataBuffer
.close();
215 } catch (Exception e
) {
216 throw new BuildException (e
.getMessage());
220 // Creat Ffs file header
225 // create input stream to read file data
227 byte[] fileBuffer
= new byte[(int)ffsFile
.length()];
228 FileInputStream fi
= new FileInputStream (ffsFile
.getAbsolutePath());
229 DataInputStream di
= new DataInputStream (fi
);
234 // create input org stream to read file data
236 byte[] orgFileBuffer
= new byte[(int)ffsOrgFile
.length()];
237 FileInputStream ofi
= new FileInputStream (ffsOrgFile
.getAbsolutePath());
238 DataInputStream odi
= new DataInputStream (ofi
);
239 odi
.read(orgFileBuffer
);
243 // Add GUID to header struct
245 if (this.ffsFileGuid
!= null) {
246 stringToGuid (this.ffsFileGuid
, ffsHeader
.name
);
248 // Add Guid to org header struct
250 stringToGuid (this.ffsFileGuid
, orgFfsHeader
.name
);
253 ffsHeader
.ffsAttributes
= this.attributes
;
254 if ((ffsHeader
.fileType
= stringToType(this.ffsFileType
))== -1) {
255 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
259 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
262 orgFfsHeader
.ffsAttributes
= ffsHeader
.ffsAttributes
;
263 orgFfsHeader
.fileType
= ffsHeader
.fileType
;
266 // Adjust file size. The function is used to tripe the last
267 // section padding of 4 binary boundary.
270 if (ffsHeader
.fileType
!= EFI_FV_FILETYPE_RAW
) {
272 fileDataSize
= adjustFileSize (fileBuffer
);
273 orgFileDataSize
= adjustFileSize (orgFileBuffer
);
276 fileDataSize
= fileBuffer
.length
;
277 orgFileDataSize
= orgFileBuffer
.length
;
281 // 1. add header size to file size
283 fileSize
= fileDataSize
+ ffsHeader
.getSize();
285 // add header size to org file size
287 orgFileSize
= orgFileDataSize
+ ffsHeader
.getSize();
289 if ((ffsHeader
.ffsAttributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
290 if (ffsHeader
.fileType
== EFI_FV_FILETYPE_FFS_PAD
) {
292 throw new BuildException (
293 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
294 "invalid for PAD files"
297 if (fileSize
== ffsHeader
.getSize()) {
298 throw new BuildException (
299 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
300 "invalid for 0-length files"
303 fileSize
= fileSize
+ 2;
304 orgFileSize
= orgFileSize
+ 2;
308 // 2. set file size to header struct
310 ffsHeader
.ffsFileSize
[0] = (byte)(fileSize
& 0x00FF);
311 ffsHeader
.ffsFileSize
[1] = (byte)((fileSize
& 0x00FF00)>>8);
312 ffsHeader
.ffsFileSize
[2] = (byte)(((int)fileSize
& 0xFF0000)>>16);
315 // set file size to org header struct
317 orgFfsHeader
.ffsFileSize
[0] = (byte)(orgFileSize
& 0x00FF);
318 orgFfsHeader
.ffsFileSize
[1] = (byte)((orgFileSize
& 0x00FF00)>>8);
319 orgFfsHeader
.ffsFileSize
[2] = (byte)(((int)orgFileSize
& 0xFF0000)>>16);
322 // Fill in checksums and state, these must be zero for checksumming
324 ffsHeader
.integrityCheck
.header
= calculateChecksum8 (
325 ffsHeader
.structToBuffer(),
329 // Fill in org file's header check sum and state
331 orgFfsHeader
.integrityCheck
.header
= calculateChecksum8 (
332 orgFfsHeader
.structToBuffer(),
333 orgFfsHeader
.getSize()
336 if ((this.attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
337 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
338 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
343 // Add org file header
345 orgFfsHeader
.integrityCheck
.file
= calculateChecksum8 (
350 ffsHeader
.integrityCheck
.file
= calculateChecksum8 (
355 // Add org file header
357 orgFfsHeader
.integrityCheck
.file
= calculateChecksum8 (
363 ffsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
364 orgFfsHeader
.integrityCheck
.file
= FFS_FIXED_CHECKSUM
;
368 // Set the state now. Spec says the checksum assumes the state is 0.
370 ffsHeader
.ffsState
= EFI_FILE_HEADER_CONSTRUCTION
|
371 EFI_FILE_HEADER_VALID
|
373 orgFfsHeader
.ffsState
= ffsHeader
.ffsState
;
376 // create output stream to first write header data in file, then write sect data in file.
378 FileOutputStream headerFfs
= new FileOutputStream (ffsFile
.getAbsolutePath());
379 DataOutputStream ffsBuffer
= new DataOutputStream (headerFfs
);
381 FileOutputStream orgHeaderFfs
= new FileOutputStream (ffsOrgFile
.getAbsolutePath());
382 DataOutputStream orgFfsBuffer
= new DataOutputStream (orgHeaderFfs
);
385 // Add header struct and file data to FFS file
387 ffsBuffer
.write(ffsHeader
.structToBuffer());
388 orgFfsBuffer
.write(orgFfsHeader
.structToBuffer());
390 for (int i
= 0; i
< fileDataSize
; i
++) {
391 ffsBuffer
.write(fileBuffer
[i
]);
394 for (int i
= 0; i
< orgFileDataSize
; i
++){
395 orgFfsBuffer
.write(orgFileBuffer
[i
]);
399 // If there is a tail, then set it
401 if ((this.attributes
& FFS_ATTRIB_TAIL_PRESENT
) != 0) {
403 byte [] tailByte
= new byte[2];
406 // reverse tailvalue , integritycheck.file as hight byte, and
407 // integritycheck.header as low byte.
409 tailValue
= (short)(ffsHeader
.integrityCheck
.header
& 0xff);
410 tailValue
= (short)((tailValue
) | ((ffsHeader
.integrityCheck
.file
<< 8) & 0xff00));
411 tailValue
= (short)~tailValue
;
414 // Change short to byte[2]
416 tailByte
[0] = (byte)(tailValue
& 0xff);
417 tailByte
[1] = (byte)((tailValue
& 0xff00)>>8);
418 ffsBuffer
.write(tailByte
[0]);
419 ffsBuffer
.write(tailByte
[1]);
421 orgFfsBuffer
.write(tailByte
[0]);
422 orgFfsBuffer
.write(tailByte
[1]);
426 // close output stream. Note if don't close output stream
427 // the buffer can't be rewritten to file.
430 orgFfsBuffer
.close();
431 System
.out
.print ("Successful create ffs file!\n");
432 } catch (Exception e
) {
433 throw new BuildException (e
.getMessage());
440 This function is to add compress section to section list.
441 @param compress Section of compress
443 public void addCompress(CompressSection compress
) {
444 this.sectionList
.add(compress
);
450 This function is to add tool section to section list.
451 @param tool Section of tool
453 public void addTool(Tool tool
) {
454 this.sectionList
.add(tool
);
460 This function is to add sectFile section to section list.
461 @param sectFile Section of sectFile.
463 public void addSectFile (SectFile sectFile
) {
464 this.sectionList
.add(sectFile
);
470 This function is to get basename
472 @return String of base name
474 public String
getBaseName() {
475 return this.baseName
;
481 This function is to set base name.
484 public void setBaseName(String baseName
) {
485 this.baseName
= baseName
.trim();
491 This function is to get the ffsAligment
492 @return The value of ffsAligment.
494 public int getFfsAligment() {
495 return this.ffsAlignment
;
501 This function is to set ffsAligment
502 @param ffsAligment The value of ffsAligment.
504 public void setFfsAligment(int ffsAligment
) {
505 this.ffsAlignment
= ffsAligment
;
506 if (this.ffsAlignment
> 7) {
507 throw new BuildException ("FFS_ALIGMENT Scope is 0-7");
509 attributes
|= (((byte)this.ffsAlignment
) << 3);
516 This function is to get ffsAttribCheckSum
518 @return Value of ffsAttribChecksum
520 public boolean getFfsAttribChecksum() {
521 return this.FfsAttribChecksum
;
527 This function is to set ffsAttribChecksum
528 @param ffsAttributeCheckSum Value of ffsAttribCheckSum
530 public void setFfsAttribChecksum(boolean ffsAttributeCheckSum
) {
531 this.FfsAttribChecksum
= ffsAttributeCheckSum
;
532 if (ffsAttributeCheckSum
) {
533 attributes
|= FFS_ATTRIB_CHECKSUM
;
540 This function is to get ffsAttribRecovery
541 @return Value of ffsAttribRecovery
543 public boolean getFfsAttribRecovery() {
544 return this.ffsAttribRecovery
;
550 This function is to set ffsAttributeRecovery
552 @param ffsAttributeRecovery Value of ffsAttributeRecovery
554 public void setRecovery(boolean ffsAttributeRecovery
) {
555 this.ffsAttribRecovery
= ffsAttributeRecovery
;
556 if (ffsAttributeRecovery
) {
557 attributes
|= FFS_ATTRIB_RECOVERY
;
564 This function is to get fileGuid
567 public String
getFileGuid() {
568 return this.ffsFileGuid
;
574 This function is to set fileGuid
575 @param ffsFileGuid String of GUID
577 public void setFileGuid(String ffsFileGuid
) {
578 this.ffsFileGuid
= ffsFileGuid
.trim();
584 This function is to get ffsFileType.
586 @return value of ffsFileType
588 public String
getFfsFileType() {
589 return this.ffsFileType
;
595 This function is to set ffsFileType.
599 public void setFfsFileType(String ffsFileType
) {
600 this.ffsFileType
= ffsFileType
.trim();
604 ffsAttribHeaderExtension
606 This function is to get ffsAttribHeaderExtension
608 @return Value of ffsAttribHeaderExtension
610 public boolean isFfsAttribHeaderExtension() {
611 return this.ffsAttribHeaderExtension
;
617 This function is to set headerExtension
618 @param headerExtension Value of headerExension
620 public void setHeaderExtension(boolean headerExtension
) {
621 this.ffsAttribHeaderExtension
= headerExtension
;
622 if (headerExtension
) {
623 attributes
|= FFS_ATTRIB_HEADER_EXTENSION
;
628 isFfsAttribTailPresent
630 This function is to get ffsAttribTailPresent value.
631 @return Value of ffsAttribTailPresent.
633 public boolean isFfsAttribTailPresent() {
634 return this.ffsAttribTailPresent
;
638 setFfsAttribTailPresent
640 This function is to set ffsAttribTailPresent.
641 @param tailPresent Value of ffsAttribTailPresent.
643 public void setFfsAttribTailPresent(boolean tailPresent
) {
644 this.ffsAttribTailPresent
= tailPresent
;
646 attributes
|= FFS_ATTRIB_TAIL_PRESENT
;
654 This function is to convert string to GUID.
655 * @param GuidStr String of GUID.
656 * @param Guid GUID form.
658 private void stringToGuid (String GuidStr
, FfsHeader
.FfsGuid Guid
){
666 byte[] buffer
= new byte[16];
667 if (GuidStr
.length()!=36) {
668 throw new BuildException ("Guid length is not correct!");
672 SplitStr
= GuidStr
.split("-");
673 if (SplitStr
.length
!= 5) {
674 throw new BuildException ("Guid type is not correct!");
679 for (i
= 0; i
< SplitStr
.length
; i
++) {
680 String str
= SplitStr
[i
];
681 charArry
= str
.toCharArray();
683 for (j
=0; j
< (str
.toCharArray().length
)/2; j
++) {
685 buffer
[k
] = hexCharToByte (charArry
[j
*2]);
686 buffer
[k
] = (byte)( buffer
[k
]& 0x0f);
687 buffer
[k
] = (byte)((buffer
[k
]<< 4));
688 buffer
[k
] = (byte)( buffer
[k
]& 0xf0);
689 buffer
[k
] = (byte)( buffer
[k
]|hexCharToByte(charArry
[j
*2+1]));
693 Guid
.bufferToStruct(buffer
);
699 This function is to get suffix of ffs file according to ffsFileType.
701 @param ffsFileType ffsFileType
702 @return The suffix of ffs file
704 private String
TypeToSuffix (String ffsFileType
){
705 String
[][] suffix
= { { "BASE", ".FFS"},
706 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
707 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
708 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
709 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
710 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
711 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
713 for (int i
= 0; i
< suffix
.length
; i
++) {
714 if (suffix
[i
][0].equalsIgnoreCase(moduleType
)) {
726 This function is to get ffsFileType integer value according to ffsFileType.
727 @param ffsFileType String value of ffsFileType
728 @return Integer value of ffsFileType.
730 private byte stringToType (String ffsFileType
){
732 if (ffsFileType
.equals("EFI_FV_FILETYPE_ALL")) {
733 return(byte)EFI_FV_FILETYPE_ALL
;
736 if (ffsFileType
.equals("EFI_FV_FILETYPE_RAW")) {
737 return(byte)EFI_FV_FILETYPE_RAW
;
740 if (ffsFileType
.equals("EFI_FV_FILETYPE_FREEFORM")) {
741 return(byte)EFI_FV_FILETYPE_FREEFORM
;
744 if (ffsFileType
.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {
745 return(byte)EFI_FV_FILETYPE_SECURITY_CORE
;
748 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEI_CORE")) {
749 return(byte) EFI_FV_FILETYPE_PEI_CORE
;
752 if (ffsFileType
.equals("EFI_FV_FILETYPE_DXE_CORE")) {
753 return(byte)EFI_FV_FILETYPE_DXE_CORE
;
756 if (ffsFileType
.equals("EFI_FV_FILETYPE_PEIM")) {
757 return(byte)EFI_FV_FILETYPE_PEIM
;
760 if (ffsFileType
.equals("EFI_FV_FILETYPE_DRIVER")) {
761 return(byte) EFI_FV_FILETYPE_DRIVER
;
764 if (ffsFileType
.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {
765 return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
768 if (ffsFileType
.equals("EFI_FV_FILETYPE_APPLICATION")) {
769 return(byte)EFI_FV_FILETYPE_APPLICATION
;
772 if (ffsFileType
.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {
773 return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
775 if (ffsFileType
.equals("EFI_FV_FILETYPE_FFS_PAD")) {
776 return(byte) EFI_FV_FILETYPE_FFS_PAD
;
787 This function is to calculate the value needed for a valid UINT8 checksum
788 @param buffer Byte buffer containing byte data of component.
789 @param size Size of the buffer.
790 @return The 8 bit checksum value needed.
792 private byte calculateChecksum8 (byte[] buffer
, int size
){
793 return(byte) (0x100 - calculateSum8 (buffer
, size
));
800 This function is to calculate the UINT8 sum for the requested region.
801 @param buffer Byte buffer containing byte data of component
802 @param size Size of the buffer.
803 @return The 8 bit checksum value needed.
805 private short calculateSum8 (byte[] buffer
, int size
){
811 // Perform the word sum for buffer
813 for (Index
= 0; Index
< size
; Index
++) {
814 Sum
= (byte) (Sum
+ buffer
[Index
]);
823 This function is to convert hex character to byte
825 @param hexChar hex character
826 @return Byte which corresponding to the character.
828 private byte hexCharToByte (char hexChar
){
879 This function is used to adjusts file size to insure sectioned file is exactly the right length such
880 that it ends on exactly the last byte of the last section. ProcessScript()
881 may have padded beyond the end of the last section out to a 4 byte boundary.
882 This padding is stripped.
884 @param buffer Byte buffer contains a section stream
885 @return Corrected size of file.
887 private int adjustFileSize (byte[] buffer
){
889 int orignalLen
= buffer
.length
;
891 int sectionPoint
= 0;
892 int nextSectionPoint
= 0;
895 int firstSectionHeader
= 0;
898 firstSectionHeader
= buffer
[0]& 0xff;
899 firstSectionHeader
= ((buffer
[1]&0xff)<<8) | firstSectionHeader
;
900 firstSectionHeader
= ((buffer
[2]&0xff)<<16)| firstSectionHeader
;
903 while (sectionPoint
< buffer
.length
) {
904 sectionLen
= buffer
[0 + sectionPoint
]& 0xff;
905 sectionLen
= ((buffer
[1 + sectionPoint
]&0xff)<<8)| sectionLen
;
906 sectionLen
= ((buffer
[2 + sectionPoint
]&0xff)<<16)| sectionLen
;
907 totalLen
= totalLen
+ sectionLen
;
909 if (totalLen
== orignalLen
) {
913 sectionPoint
= sectionPoint
+ sectionLen
;
914 adjustLen
= sectionPoint
;
916 nextSectionPoint
= (sectionPoint
+ 0x03) & (~
0x03);
917 totalLen
= totalLen
+ nextSectionPoint
- sectionLen
;
918 sectionPoint
= nextSectionPoint
;
926 This function is to get output directory.
928 @return Path of output directory.
930 public String
getOutputDir() {
937 This function is to set output directory.
939 @param outputDir The output direcotry.
941 public void setOutputDir(String outputDir
) {
942 this.outputDir
= outputDir
;
945 public String
getModuleType() {
946 return this.moduleType
;
949 public void setModuleType(String moduleType
) {
950 this.moduleType
= moduleType
;