Modify GenFfsFileTask.
[mirror_edk2.git] / Tools / Source / FrameworkTasks / org / tianocore / framework / tasks / GenFfsFileTask.java
1 /** @file
2 GenFfsFileTask class.
3
4 GenFfsFileTaks is to generate ffs file.
5
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
11
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.
14
15 **/
16 package org.tianocore.framework.tasks;
17
18 import java.io.DataInputStream;
19 import java.io.DataOutputStream;
20 import java.io.File;
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;
26
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;
31
32 /**
33 GenFfsFileTask
34
35 GenFfsFileTaks is to generate ffs file.
36
37 **/
38 public class GenFfsFileTask extends Task implements EfiDefine, FfsTypes {
39 /**
40 * GenFfsFile Task Class
41 * class member
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
48 * values). *
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.
53 * Required.
54 * -ffsAttrib : Data recorde attribute added result.
55 * -sectionList : List recorded all section elemet in task.
56 */
57 ///
58 /// module baseName
59 ///
60 String baseName = "";
61 ///
62 ///
63 ///
64 String moduleType;
65 ///
66 /// module Guid
67 ///
68 String ffsFileGuid = "";
69 ///
70 /// Ffs file type
71 ///
72 String ffsFileType = "";
73 ///
74 /// ffsAttribHeaderExtension value is used to set the corresponding bit in
75 /// the output FFS file header
76 ///
77 boolean ffsAttribHeaderExtension = false;
78 ///
79 /// ffsAttribTailPresent value is used to set the corresponding bit in the
80 /// output FFS file header
81 ///
82 boolean ffsAttribTailPresent = false;
83 ///
84 /// ffsAttribRecovery value is used to set the corresponding bit in the
85 /// output FFS file header
86 ///
87 boolean ffsAttribRecovery = false;
88 ///
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
91 /// and 7 inclusive
92 ///
93 int ffsAttribDataAlignment = 0;
94 ///
95 /// ffsAttribChecksum value is used to set the corresponding bit in the
96 /// output FFS file header
97 ///
98 boolean FfsAttribChecksum = false;
99 ///
100 /// Attribute is used to record the sum of all bit in the output FFS file.
101 ///
102 byte attributes = 0;
103 ///
104 /// The output directory of ffs file.
105 ///
106 String outputDir = "";
107 ///
108 /// List of section.
109 ///
110 List<Object> sectionList = new ArrayList<Object>();
111
112 ///
113 /// The path of Framewor_Tools_Paht.
114 ///
115 static String path = "";
116
117 ///
118 /// Gensection
119 ///
120 List<GenSectionTask> genSectList = new ArrayList<GenSectionTask>();
121
122 /**
123 execute
124
125 GenFfsFileTask execute is to generate ffs file according to input section
126 dscriptive information.
127 **/
128 public void execute() throws BuildException {
129
130 String ffsSuffix = "";
131 String outputPath = "";
132
133 //
134 // Get Fraemwork_Tools_Path
135 //
136 Project pj = this.getOwningTarget().getProject();
137 path = pj.getProperty("env.FRAMEWORK_TOOLS_PATH");
138
139 //
140 // Check does the BaseName, Guid, FileType set value.
141 //
142 if (this.baseName.equals("")) {
143 throw new BuildException ("Must set OutputFileBasename!\n");
144 }
145
146 if (this.ffsFileGuid.equals("")) {
147 throw new BuildException ("Must set ffsFileGuid!\n");
148 }
149
150 if (this.ffsFileType.equals("")) {
151 throw new BuildException ("Must set ffsFileType!\n");
152 }
153 //
154 // Create ffs file. File name = FfsFileGuid + BaseName + ffsSuffix.
155 // If outputDir's value was set, file will output to the outputDir.
156 //
157 ffsSuffix = TypeToSuffix (this.moduleType);
158 if (!this.outputDir.equals("")) {
159 String temp;
160 outputPath = this.outputDir;
161 temp = outputPath.replace('\\', File.separatorChar);
162 outputPath = temp.replace('/', File.separatorChar);
163 if (outputPath.charAt(outputPath.length()-1) != File.separatorChar) {
164 outputPath = outputPath + File.separator;
165 }
166
167 }
168
169 String ffsFilePath = outputPath + this.ffsFileGuid + '-' + this.baseName + ffsSuffix;
170 File ffsFile = new File (ffsFilePath);
171 try{
172 genFfs(ffsFile);
173 }catch (BuildException e){
174 if (ffsFile != null && ffsFile.exists()){
175 ffsFile.deleteOnExit();
176 }
177 throw new BuildException(e.getMessage());
178
179 }
180
181 }
182
183 /**
184 addCompress
185
186 This function is to add compress section to section list.
187 @param compress Section of compress
188 **/
189 public void addCompress(CompressSection compress) {
190 this.sectionList.add(compress);
191 }
192
193 /**
194 addTool
195
196 This function is to add tool section to section list.
197 @param tool Section of tool
198 **/
199 public void addTool(Tool tool) {
200 this.sectionList.add(tool);
201 }
202
203 /**
204 addSectionFile
205
206 This function is to add sectFile section to section list.
207 @param sectFile Section of sectFile.
208 **/
209 public void addSectFile (SectFile sectFile) {
210 this.sectionList.add(sectFile);
211 }
212
213 /**
214 getBaseName
215
216 This function is to get basename
217
218 @return String of base name
219 **/
220 public String getBaseName() {
221 return this.baseName;
222 }
223
224 /**
225 setBaseName
226
227 This function is to set base name.
228 @param baseName
229 **/
230 public void setBaseName(String baseName) {
231 this.baseName = baseName.trim();
232 }
233
234 /**
235 getFfsAligment
236
237 This function is to get the ffsAligment
238 @return The value of ffsAligment.
239 **/
240 public int getFfsAttribDataAlignment() {
241 return this.ffsAttribDataAlignment;
242 }
243
244 /**
245 setFfsAligment
246
247 This function is to set ffsAligment
248 @param ffsAligment The value of ffsAligment.
249 **/
250 public void setFfsAttribDataAlignment(String ffsAligment) {
251 this.ffsAttribDataAlignment = stringToInt(ffsAligment.replaceAll(" ", "").toLowerCase());
252 if (this.ffsAttribDataAlignment < 0 || this.ffsAttribDataAlignment > 7) {
253 throw new BuildException ("FFS_ATTRIB_DATA_ALIGMENT must be an integer value from 0 through 7, inclusive");
254 } else {
255 attributes |= (((byte)this.ffsAttribDataAlignment) << 3);
256 }
257 }
258
259 /**
260 getFfsAttribCheckSum
261
262 This function is to get ffsAttribCheckSum
263
264 @return Value of ffsAttribChecksum
265 **/
266 public boolean getFfsAttribChecksum() {
267 return this.FfsAttribChecksum;
268 }
269
270 /**
271 setFfsAttribChecksum
272
273 This function is to set ffsAttribChecksum
274 @param ffsAttributeCheckSum Value of ffsAttribCheckSum
275 **/
276 public void setFfsAttribChecksum(boolean ffsAttributeCheckSum) {
277 this.FfsAttribChecksum = ffsAttributeCheckSum;
278 if (ffsAttributeCheckSum) {
279 attributes |= FFS_ATTRIB_CHECKSUM;
280 }
281 }
282
283 /**
284 getFfsAttribRecovery
285
286 This function is to get ffsAttribRecovery
287 @return Value of ffsAttribRecovery
288 **/
289 public boolean getFfsAttribRecovery() {
290 return this.ffsAttribRecovery;
291 }
292
293 /**
294 setRecovery
295
296 This function is to set ffsAttributeRecovery
297
298 @param ffsAttributeRecovery Value of ffsAttributeRecovery
299 **/
300 public void setRecovery(boolean ffsAttributeRecovery) {
301 this.ffsAttribRecovery = ffsAttributeRecovery;
302 if (ffsAttributeRecovery) {
303 attributes |= FFS_ATTRIB_RECOVERY;
304 }
305 }
306
307 /**
308 getFileGuid
309
310 This function is to get fileGuid
311 @return Guid
312 **/
313 public String getFileGuid() {
314 return this.ffsFileGuid;
315 }
316
317 /**
318 setFileGuid
319
320 This function is to set fileGuid
321 @param ffsFileGuid String of GUID
322 **/
323 public void setFileGuid(String ffsFileGuid) {
324 this.ffsFileGuid = ffsFileGuid.trim();
325 }
326
327 /**
328 getFfsFileType
329
330 This function is to get ffsFileType.
331
332 @return value of ffsFileType
333 **/
334 public String getFfsFileType() {
335 return this.ffsFileType;
336 }
337
338 /**
339 setFfsFileType
340
341 This function is to set ffsFileType.
342
343 @param ffsFileType
344 **/
345 public void setFfsFileType(String ffsFileType) {
346 this.ffsFileType = ffsFileType.trim();
347 }
348
349 /**
350 ffsAttribHeaderExtension
351
352 This function is to get ffsAttribHeaderExtension
353
354 @return Value of ffsAttribHeaderExtension
355 **/
356 public boolean isFfsAttribHeaderExtension() {
357 return this.ffsAttribHeaderExtension;
358 }
359
360 /**
361 setHeaderExension
362
363 This function is to set headerExtension
364 @param headerExtension Value of headerExension
365 **/
366 public void setHeaderExtension(boolean headerExtension) {
367 this.ffsAttribHeaderExtension = headerExtension;
368 if (headerExtension) {
369 attributes |= FFS_ATTRIB_HEADER_EXTENSION;
370 }
371 }
372
373 /**
374 isFfsAttribTailPresent
375
376 This function is to get ffsAttribTailPresent value.
377 @return Value of ffsAttribTailPresent.
378 **/
379 public boolean isFfsAttribTailPresent() {
380 return this.ffsAttribTailPresent;
381 }
382
383 /**
384 setFfsAttribTailPresent
385
386 This function is to set ffsAttribTailPresent.
387 @param tailPresent Value of ffsAttribTailPresent.
388 **/
389 public void setFfsAttribTailPresent(boolean tailPresent) {
390 this.ffsAttribTailPresent = tailPresent;
391 if (tailPresent) {
392 attributes |= FFS_ATTRIB_TAIL_PRESENT;
393 }
394 }
395
396
397 /**
398 stringToGuid
399
400 This function is to convert string to GUID.
401 * @param GuidStr String of GUID.
402 * @param Guid GUID form.
403 */
404 private void stringToGuid (String GuidStr, FfsHeader.FfsGuid Guid){
405
406 int i = 0;
407 int j = 0;
408 int k = 0;
409 char [] charArry;
410 String [] SplitStr;
411
412 byte[] buffer = new byte[16];
413 if (GuidStr.length()!=36) {
414 throw new BuildException ("The GUID length [" + GuidStr.length() + "] is not correct!");
415 }
416
417
418 SplitStr = GuidStr.split("-");
419 if (SplitStr.length != 5) {
420 throw new BuildException ("The GUID format is not correct!");
421 }
422
423
424
425 for (i= 0; i < SplitStr.length; i++) {
426 String str = SplitStr[i];
427 charArry = str.toCharArray();
428
429 for (j =0; j < (str.toCharArray().length)/2; j++) {
430
431 buffer[k] = hexCharToByte (charArry[j*2]);
432 buffer[k] = (byte)( buffer[k]& 0x0f);
433 buffer[k] = (byte)((buffer[k]<< 4));
434 buffer[k] = (byte)( buffer[k]& 0xf0);
435 buffer[k] = (byte)( buffer[k]|hexCharToByte(charArry[j*2+1]));
436 k++;
437 }
438 }
439 Guid.bufferToStruct(buffer);
440 }
441
442 /**
443 typeToSuffix
444
445 This function is to get suffix of ffs file according to ffsFileType.
446
447 @param ffsFileType ffsFileType
448 @return The suffix of ffs file
449 **/
450 private String TypeToSuffix (String ffsFileType){
451 String[][] suffix = { { "BASE", ".FFS"},
452 { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" },
453 { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },
454 { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" },
455 { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" },
456 { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },
457 { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };
458
459 for (int i = 0; i < suffix.length; i++) {
460 if (suffix[i][0].equalsIgnoreCase(moduleType)) {
461 return suffix[i][1];
462 }
463 }
464
465 return ".FFS";
466 }
467
468
469 /**
470 stringToType
471
472 This function is to get ffsFileType integer value according to ffsFileType.
473 @param ffsFileType String value of ffsFileType
474 @return Integer value of ffsFileType.
475 **/
476 private byte stringToType (String ffsFileType){
477
478 if (ffsFileType.equals("EFI_FV_FILETYPE_ALL")) {
479 return(byte)EFI_FV_FILETYPE_ALL;
480 }
481
482 if (ffsFileType.equals("EFI_FV_FILETYPE_RAW")) {
483 return(byte)EFI_FV_FILETYPE_RAW;
484 }
485
486 if (ffsFileType.equals("EFI_FV_FILETYPE_FREEFORM")) {
487 return(byte)EFI_FV_FILETYPE_FREEFORM;
488 }
489
490 if (ffsFileType.equals("EFI_FV_FILETYPE_SECURITY_CORE")) {
491 return(byte)EFI_FV_FILETYPE_SECURITY_CORE;
492 }
493
494 if (ffsFileType.equals("EFI_FV_FILETYPE_PEI_CORE")) {
495 return(byte) EFI_FV_FILETYPE_PEI_CORE;
496 }
497
498 if (ffsFileType.equals("EFI_FV_FILETYPE_DXE_CORE")) {
499 return(byte)EFI_FV_FILETYPE_DXE_CORE;
500 }
501
502 if (ffsFileType.equals("EFI_FV_FILETYPE_PEIM")) {
503 return(byte)EFI_FV_FILETYPE_PEIM;
504 }
505
506 if (ffsFileType.equals("EFI_FV_FILETYPE_DRIVER")) {
507 return(byte) EFI_FV_FILETYPE_DRIVER;
508 }
509
510 if (ffsFileType.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) {
511 return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER;
512 }
513
514 if (ffsFileType.equals("EFI_FV_FILETYPE_APPLICATION")) {
515 return(byte)EFI_FV_FILETYPE_APPLICATION;
516 }
517
518 if (ffsFileType.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) {
519 return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;
520 }
521 if (ffsFileType.equals("EFI_FV_FILETYPE_FFS_PAD")) {
522 return(byte) EFI_FV_FILETYPE_FFS_PAD;
523 }
524
525 return -1;
526 }
527
528
529
530 /**
531 calculateCheckSum8
532
533 This function is to calculate the value needed for a valid UINT8 checksum
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.
537 **/
538 private byte calculateChecksum8 (byte[] buffer, int size){
539 return(byte) (0x100 - calculateSum8 (buffer, size));
540 }
541
542
543 /**
544 calculateSum8
545
546 This function is to calculate the UINT8 sum for the requested region.
547 @param buffer Byte buffer containing byte data of component
548 @param size Size of the buffer.
549 @return The 8 bit checksum value needed.
550 **/
551 private short calculateSum8 (byte[] buffer, int size){
552 int Index;
553 byte Sum;
554 Sum = 0;
555
556 //
557 // Perform the word sum for buffer
558 //
559 for (Index = 0; Index < size; Index++) {
560 Sum = (byte) (Sum + buffer[Index]);
561 }
562
563 return(byte) Sum;
564 }
565
566 /**
567 hexCharToByte
568
569 This function is to convert hex character to byte
570
571 @param hexChar hex character
572 @return Byte which corresponding to the character.
573 **/
574 private byte hexCharToByte (char hexChar){
575 switch (hexChar) {
576 case '0':
577 return(byte)0x00;
578 case '1':
579 return(byte)0x01;
580 case '2':
581 return(byte)0x02;
582 case '3':
583 return(byte)0x03;
584 case '4':
585 return(byte)0x04;
586 case '5':
587 return(byte)0x05;
588 case '6':
589 return(byte)0x06;
590 case '7':
591 return(byte)0x07;
592 case '8':
593 return(byte)0x08;
594 case '9':
595 return(byte)0x09;
596 case 'a':
597 case 'A':
598 return(byte)0x0a;
599 case 'b':
600 case 'B':
601 return(byte)0x0b;
602 case 'c':
603 case 'C':
604 return(byte)0x0c;
605
606 case 'd':
607 case 'D':
608 return(byte)0x0d;
609
610 case 'e':
611 case 'E':
612 return(byte)0x0e;
613 case 'f':
614 case 'F':
615 return(byte)0x0f;
616
617 default:
618 return(byte)0xff;
619 }
620 }
621
622 /**
623 adjustFileSize
624
625 This function is used to adjusts file size to insure sectioned file is exactly the right length such
626 that it ends on exactly the last byte of the last section. ProcessScript()
627 may have padded beyond the end of the last section out to a 4 byte boundary.
628 This padding is stripped.
629
630 @param buffer Byte buffer contains a section stream
631 @return Corrected size of file.
632 **/
633 private int adjustFileSize (byte[] buffer){
634
635 int orignalLen = buffer.length;
636 int adjustLen = 0;
637 int sectionPoint = 0;
638 int nextSectionPoint = 0;
639 int sectionLen = 0;
640 int totalLen = 0;
641 int firstSectionHeader = 0;
642
643
644 firstSectionHeader = buffer[0]& 0xff;
645 firstSectionHeader = ((buffer[1]&0xff)<<8) | firstSectionHeader;
646 firstSectionHeader = ((buffer[2]&0xff)<<16)| firstSectionHeader;
647
648
649 while (sectionPoint < buffer.length) {
650 sectionLen = buffer[0 + sectionPoint]& 0xff;
651 sectionLen = ((buffer[1 + sectionPoint]&0xff)<<8)| sectionLen;
652 sectionLen = ((buffer[2 + sectionPoint]&0xff)<<16)| sectionLen;
653 totalLen = totalLen + sectionLen;
654
655 if (totalLen == orignalLen) {
656 return totalLen;
657 }
658
659 sectionPoint = sectionPoint + sectionLen;
660 adjustLen = sectionPoint;
661
662 nextSectionPoint = (sectionPoint + 0x03) & (~0x03);
663 totalLen = totalLen + nextSectionPoint - sectionLen;
664 sectionPoint = nextSectionPoint;
665 }
666 return adjustLen;
667 }
668
669 /**
670 getOutputDir
671
672 This function is to get output directory.
673
674 @return Path of output directory.
675 **/
676 public String getOutputDir() {
677 return outputDir;
678 }
679
680 /**
681 setOutputDir
682
683 This function is to set output directory.
684
685 @param outputDir The output direcotry.
686 **/
687 public void setOutputDir(String outputDir) {
688 this.outputDir = outputDir;
689 }
690
691 /**
692 getModuleTyp
693
694 This function is to get string of module type.
695
696 @return moduleType The string of module type.
697 **/
698 public String getModuleType() {
699 return this.moduleType;
700 }
701
702 /**
703 setModuleType
704
705 This function is to set moduleType.
706
707 @param moduleType The string of module type.
708 **/
709 public void setModuleType(String moduleType) {
710 this.moduleType = moduleType;
711 }
712
713 /**
714 Convert a string to a integer.
715
716 @param intString The string representing a integer
717
718 @retval int The value of integer represented by the
719 given string; -1 is returned if the format
720 of the string is wrong.
721 **/
722 private int stringToInt(String intString) {
723 int value;
724 int hexPrefixPos = intString.indexOf("0x");
725 int radix = 10;
726 String intStringNoPrefix;
727
728 if (hexPrefixPos >= 0) {
729 radix = 16;
730 intStringNoPrefix = intString.substring(hexPrefixPos + 2, intString.length());
731 } else {
732 intStringNoPrefix = intString;
733 }
734
735 try {
736 value = Integer.parseInt(intStringNoPrefix, radix);
737 } catch (NumberFormatException e) {
738 log("Incorrect format of int [" + intString + "]. -1 is assumed");
739 return -1;
740 }
741
742 return value;
743 }
744
745 /**
746 genFfs
747
748 This function is to generate FFS file.
749
750 @param ffsFile Name of FFS file.
751 @param isOrg Flag to indicate generate ORG ffs file or not.
752 **/
753 private void genFfs(File ffsFile) throws BuildException {
754 Section sect;
755 int fileSize;
756 int fileDataSize;
757 FfsHeader ffsHeader = new FfsHeader();
758 FfsHeader orgFfsHeader = new FfsHeader();
759
760 EdkLog.log(this, EdkLog.EDK_INFO, ffsFile.getName());
761
762 try {
763 //
764 // Create file output stream -- dataBuffer.
765 //
766 FileOutputStream dataFs = new FileOutputStream (ffsFile.getAbsolutePath());
767 DataOutputStream dataBuffer = new DataOutputStream (dataFs);
768
769 //
770 // Search SectionList find earch section and call it's
771 // ToBuffer function.
772 //
773 Iterator sectionIter = this.sectionList.iterator();
774 while (sectionIter.hasNext()) {
775 sect = (Section)sectionIter.next();
776
777 try {
778 //
779 // The last section don't need 4 byte ffsAligment.
780 //
781 sect.toBuffer((DataOutputStream)dataBuffer);
782 } catch (Exception e) {
783 if (dataBuffer != null){
784 dataBuffer.close();
785 }
786 throw new BuildException (e.getMessage());
787 }
788 }
789 dataBuffer.close();
790 } catch (Exception e) {
791 throw new BuildException (e.getMessage());
792 }
793
794 //
795 // Creat Ffs file header
796 //
797 try {
798
799 //
800 // create input stream to read file data
801 //
802 byte[] fileBuffer = new byte[(int)ffsFile.length()];
803 FileInputStream fi = new FileInputStream (ffsFile.getAbsolutePath());
804 DataInputStream di = new DataInputStream (fi);
805 di.read(fileBuffer);
806 di.close();
807
808 //
809 // Add GUID to header struct
810 //
811 if (this.ffsFileGuid != null) {
812 stringToGuid (this.ffsFileGuid, ffsHeader.name);
813 }
814
815 ffsHeader.ffsAttributes = this.attributes;
816 if ((ffsHeader.fileType = stringToType(this.ffsFileType))== -1) {
817 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
818 }
819
820 //
821 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
822 // and fileType
823 //
824 orgFfsHeader.ffsAttributes = ffsHeader.ffsAttributes;
825 orgFfsHeader.fileType = ffsHeader.fileType;
826
827 //
828 // Adjust file size. The function is used to tripe the last
829 // section padding of 4 binary boundary.
830 //
831 //
832 if (ffsHeader.fileType != EFI_FV_FILETYPE_RAW) {
833
834 fileDataSize = adjustFileSize (fileBuffer);
835 } else {
836 fileDataSize = fileBuffer.length;
837 }
838
839 //
840 // 1. add header size to file size
841 //
842 fileSize = fileDataSize + ffsHeader.getSize();
843
844 if ((ffsHeader.ffsAttributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {
845 if (ffsHeader.fileType == EFI_FV_FILETYPE_FFS_PAD) {
846
847 throw new BuildException (
848 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
849 "invalid for PAD files"
850 );
851 }
852 if (fileSize == ffsHeader.getSize()) {
853 throw new BuildException (
854 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
855 "invalid for 0-length files"
856 );
857 }
858 fileSize = fileSize + 2;
859 }
860
861 //
862 // 2. set file size to header struct
863 //
864 ffsHeader.ffsFileSize[0] = (byte)(fileSize & 0x00FF);
865 ffsHeader.ffsFileSize[1] = (byte)((fileSize & 0x00FF00)>>8);
866 ffsHeader.ffsFileSize[2] = (byte)(((int)fileSize & 0xFF0000)>>16);
867
868 //
869 // Fill in checksums and state, these must be zero for checksumming
870 //
871 ffsHeader.integrityCheck.header = calculateChecksum8 (
872 ffsHeader.structToBuffer(),
873 ffsHeader.getSize()
874 );
875
876 if ((this.attributes & FFS_ATTRIB_CHECKSUM) != 0) {
877 if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {
878 ffsHeader.integrityCheck.file = calculateChecksum8 (
879 fileBuffer,
880 fileDataSize
881 );
882 } else {
883 ffsHeader.integrityCheck.file = calculateChecksum8 (
884 fileBuffer,
885 fileDataSize
886 );
887 }
888 } else {
889 ffsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM;
890 orgFfsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM;
891 }
892
893 //
894 // Set the state now. Spec says the checksum assumes the state is 0.
895 //
896 ffsHeader.ffsState = EFI_FILE_HEADER_CONSTRUCTION |
897 EFI_FILE_HEADER_VALID |
898 EFI_FILE_DATA_VALID;
899
900 //
901 // create output stream to first write header data in file, then write sect data in file.
902 //
903 FileOutputStream headerFfs = new FileOutputStream (ffsFile.getAbsolutePath());
904 DataOutputStream ffsBuffer = new DataOutputStream (headerFfs);
905
906 //
907 // Add header struct and file data to FFS file
908 //
909 ffsBuffer.write(ffsHeader.structToBuffer());
910 ffsBuffer.write(fileBuffer, 0, fileDataSize);
911
912
913
914 //
915 // If there is a tail, then set it
916 //
917 if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {
918 short tailValue ;
919 byte [] tailByte = new byte[2];
920
921 //
922 // reverse tailvalue , integritycheck.file as hight byte, and
923 // integritycheck.header as low byte.
924 //
925 tailValue = (short)(ffsHeader.integrityCheck.header & 0xff);
926 tailValue = (short)((tailValue) | ((ffsHeader.integrityCheck.file << 8) & 0xff00));
927 tailValue = (short)~tailValue;
928
929 //
930 // Change short to byte[2]
931 //
932 tailByte[0] = (byte)(tailValue & 0xff);
933 tailByte[1] = (byte)((tailValue & 0xff00)>>8);
934 ffsBuffer.write(tailByte[0]);
935 ffsBuffer.write(tailByte[1]);
936
937 }
938
939 //
940 // close output stream. Note if don't close output stream
941 // the buffer can't be rewritten to file.
942 //
943 ffsBuffer.close();
944 } catch (Exception e) {
945 log("genffsfile failed!");
946 throw new BuildException (e.getMessage());
947 }
948
949 }
950
951 /**
952 addGenSection
953
954 This function is to add gensection instance to list
955
956 @param task Instance of GenSectionTask
957 **/
958 public void addGenSection (GenSectionTask task){
959 this.sectionList.add(task);
960 }
961 }