ebc26b92a4b7796856b252a8def838652ef3c681
[mirror_edk2.git] / Tools / Java / 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 EdkLog.log(this, EdkLog.EDK_ERROR, "Incorrect format of int [" + intString + "]. -1 is assumed");
739 return -1;
740 }
741
742 return value;
743 }
744
745 private void alignSection(DataOutputStream dataBuffer, int dataSize, int alignment) throws BuildException {
746 if (alignment == 0) {
747 return;
748 }
749 dataSize += 4; // take the section header into account
750 int[] alignedBytes = {0, 16, 128, 512, 1024, 4096, 32768, 65536};
751 int padSize = (alignedBytes[alignment] - dataSize) & (alignedBytes[alignment] - 1);
752 if (padSize == 0) {
753 //
754 // already aligned
755 //
756 return;
757 }
758 //
759 // if the pad size is not times of 4, there must be something wrong in previous sections
760 //
761 if (((4 - padSize) & (4 - 1)) != 0) {
762 EdkLog.log(this, EdkLog.EDK_ERROR, "PAD section size must be 4-byte aligned (" + padSize + ")!");
763 throw new BuildException ("Alignment can't be satisfied!");
764 }
765 byte[] pad = new byte[padSize];
766 //
767 // first three byte stores the section size
768 //
769 pad[0] = (byte)(padSize & 0xff);
770 pad[1] = (byte)((padSize >> 8) & 0xff);
771 pad[2] = (byte)((padSize >> 16) & 0xff);
772 //
773 // the fourth byte are section type. use raw type (0x19)
774 //
775 pad[3] = 0x19;
776 try {
777 dataBuffer.write(pad);
778 } catch (Exception e) {
779 throw new BuildException(e.getMessage());
780 }
781 }
782
783 /**
784 genFfs
785
786 This function is to generate FFS file.
787
788 @param ffsFile Name of FFS file.
789 @param isOrg Flag to indicate generate ORG ffs file or not.
790 **/
791 private void genFfs(File ffsFile) throws BuildException {
792 Section sect;
793 int fileSize;
794 int fileDataSize;
795 FfsHeader ffsHeader = new FfsHeader();
796 FfsHeader orgFfsHeader = new FfsHeader();
797
798 EdkLog.log(this, EdkLog.EDK_INFO, ffsFile.getName());
799
800 try {
801 //
802 // Create file output stream -- dataBuffer.
803 //
804 FileOutputStream dataFs = new FileOutputStream (ffsFile.getAbsolutePath());
805 DataOutputStream dataBuffer = new DataOutputStream (dataFs);
806
807 //
808 // Search SectionList find earch section and call it's
809 // ToBuffer function.
810 //
811 Iterator sectionIter = this.sectionList.iterator();
812 while (sectionIter.hasNext()) {
813 sect = (Section)sectionIter.next();
814
815 try {
816 int alignment = sect.getAlignment();
817 if (this.ffsAttribDataAlignment < alignment) {
818 this.ffsAttribDataAlignment = alignment;
819 }
820 alignSection(dataBuffer, dataBuffer.size(), alignment);
821 //
822 // The last section don't need 4 byte ffsAligment.
823 //
824 sect.toBuffer((DataOutputStream)dataBuffer);
825 } catch (Exception e) {
826 if (dataBuffer != null){
827 dataBuffer.close();
828 }
829 throw new BuildException (e.getMessage());
830 }
831 }
832 dataBuffer.close();
833 } catch (Exception e) {
834 throw new BuildException (e.getMessage());
835 }
836
837 //
838 // Creat Ffs file header
839 //
840 try {
841
842 //
843 // create input stream to read file data
844 //
845 byte[] fileBuffer = new byte[(int)ffsFile.length()];
846 FileInputStream fi = new FileInputStream (ffsFile.getAbsolutePath());
847 DataInputStream di = new DataInputStream (fi);
848 di.read(fileBuffer);
849 di.close();
850
851 //
852 // Add GUID to header struct
853 //
854 if (this.ffsFileGuid != null) {
855 stringToGuid (this.ffsFileGuid, ffsHeader.name);
856 }
857
858 //
859 // because we may have changed the ffsAttribDataAlignment, we need to refresh attributes
860 //
861 this.attributes &= ~(((byte)7) << 3);
862 this.attributes |= (((byte)this.ffsAttribDataAlignment) << 3);
863
864 ffsHeader.ffsAttributes = this.attributes;
865 if ((ffsHeader.fileType = stringToType(this.ffsFileType))== -1) {
866 throw new BuildException ("FFS_FILE_TYPE unknow!\n");
867 }
868
869 //
870 // Copy ffsHeader.ffsAttribute and fileType to orgFfsHeader.ffsAttribute
871 // and fileType
872 //
873 orgFfsHeader.ffsAttributes = ffsHeader.ffsAttributes;
874 orgFfsHeader.fileType = ffsHeader.fileType;
875
876 //
877 // Adjust file size. The function is used to tripe the last
878 // section padding of 4 binary boundary.
879 //
880 //
881 if (ffsHeader.fileType != EFI_FV_FILETYPE_RAW) {
882
883 fileDataSize = adjustFileSize (fileBuffer);
884 } else {
885 fileDataSize = fileBuffer.length;
886 }
887
888 //
889 // 1. add header size to file size
890 //
891 fileSize = fileDataSize + ffsHeader.getSize();
892
893 if ((ffsHeader.ffsAttributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {
894 if (ffsHeader.fileType == EFI_FV_FILETYPE_FFS_PAD) {
895
896 throw new BuildException (
897 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
898 "invalid for PAD files"
899 );
900 }
901 if (fileSize == ffsHeader.getSize()) {
902 throw new BuildException (
903 "FFS_ATTRIB_TAIL_PRESENT=TRUE is " +
904 "invalid for 0-length files"
905 );
906 }
907 fileSize = fileSize + 2;
908 }
909
910 //
911 // 2. set file size to header struct
912 //
913 ffsHeader.ffsFileSize[0] = (byte)(fileSize & 0x00FF);
914 ffsHeader.ffsFileSize[1] = (byte)((fileSize & 0x00FF00)>>8);
915 ffsHeader.ffsFileSize[2] = (byte)(((int)fileSize & 0xFF0000)>>16);
916
917 //
918 // Fill in checksums and state, these must be zero for checksumming
919 //
920 ffsHeader.integrityCheck.header = calculateChecksum8 (
921 ffsHeader.structToBuffer(),
922 ffsHeader.getSize()
923 );
924
925 if ((this.attributes & FFS_ATTRIB_CHECKSUM) != 0) {
926 if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {
927 ffsHeader.integrityCheck.file = calculateChecksum8 (
928 fileBuffer,
929 fileDataSize
930 );
931 } else {
932 ffsHeader.integrityCheck.file = calculateChecksum8 (
933 fileBuffer,
934 fileDataSize
935 );
936 }
937 } else {
938 ffsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM;
939 orgFfsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM;
940 }
941
942 //
943 // Set the state now. Spec says the checksum assumes the state is 0.
944 //
945 ffsHeader.ffsState = EFI_FILE_HEADER_CONSTRUCTION |
946 EFI_FILE_HEADER_VALID |
947 EFI_FILE_DATA_VALID;
948
949 //
950 // create output stream to first write header data in file, then write sect data in file.
951 //
952 FileOutputStream headerFfs = new FileOutputStream (ffsFile.getAbsolutePath());
953 DataOutputStream ffsBuffer = new DataOutputStream (headerFfs);
954
955 //
956 // Add header struct and file data to FFS file
957 //
958 ffsBuffer.write(ffsHeader.structToBuffer());
959 ffsBuffer.write(fileBuffer, 0, fileDataSize);
960
961
962
963 //
964 // If there is a tail, then set it
965 //
966 if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) {
967 short tailValue ;
968 byte [] tailByte = new byte[2];
969
970 //
971 // reverse tailvalue , integritycheck.file as hight byte, and
972 // integritycheck.header as low byte.
973 //
974 tailValue = (short)(ffsHeader.integrityCheck.header & 0xff);
975 tailValue = (short)((tailValue) | ((ffsHeader.integrityCheck.file << 8) & 0xff00));
976 tailValue = (short)~tailValue;
977
978 //
979 // Change short to byte[2]
980 //
981 tailByte[0] = (byte)(tailValue & 0xff);
982 tailByte[1] = (byte)((tailValue & 0xff00)>>8);
983 ffsBuffer.write(tailByte[0]);
984 ffsBuffer.write(tailByte[1]);
985
986 }
987
988 //
989 // close output stream. Note if don't close output stream
990 // the buffer can't be rewritten to file.
991 //
992 ffsBuffer.close();
993 } catch (Exception e) {
994 EdkLog.log(this, EdkLog.EDK_ERROR, "genffsfile failed!");
995 throw new BuildException (e.getMessage());
996 }
997
998 }
999
1000 /**
1001 addGenSection
1002
1003 This function is to add gensection instance to list
1004
1005 @param task Instance of GenSectionTask
1006 **/
1007 public void addGenSection (GenSectionTask task){
1008 this.sectionList.add(task);
1009 }
1010 }