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