]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/FlashMapTask.java
- Fixed EDKT240. Now the Blank.pad file for alignment purpose will no longer be needed.
[mirror_edk2.git] / Tools / Java / Source / FrameworkTasks / org / tianocore / framework / tasks / FlashMapTask.java
1 /** @file
2 FlashMapTask class.
3
4 FlashMapTask is used to call FlashMap.exe to lay out the flash.
5
6
7 Copyright (c) 2006, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17 package org.tianocore.framework.tasks;
18
19 import java.io.File;
20 import java.io.FileReader;
21 import java.io.BufferedReader;
22
23 import java.util.List;
24 import java.util.ArrayList;
25 import java.util.regex.Pattern;
26 import java.util.regex.Matcher;
27
28 import org.apache.tools.ant.Task;
29 import org.apache.tools.ant.Project;
30 import org.apache.tools.ant.BuildException;
31 import org.apache.tools.ant.taskdefs.Execute;
32 import org.apache.tools.ant.taskdefs.LogStreamHandler;
33 import org.apache.tools.ant.types.Commandline;
34
35 import org.tianocore.common.logger.EdkLog;
36
37 /**
38 * FlashMapTask class.
39 *
40 * FlashMapTask is used to call FlashMap.exe to generate flash map defition files and fd files.
41 */
42 public class FlashMapTask extends Task implements EfiDefine {
43 //
44 // tool name
45 //
46 private static final String toolName = "FlashMap";
47
48 //
49 //
50 //
51 private static Pattern fileBlock = Pattern.compile("\\s*File\\s*\\{([^\\{\\}]+)\\}");
52 private static Pattern fileNameDef = Pattern.compile("\\bName\\s*=\\s*\"([^\"]+)\"");
53
54 //
55 // Flash definition file
56 //
57 private FileArg flashDefFile = new FileArg();
58
59 //
60 // Flash device
61 //
62 private ToolArg flashDevice = new ToolArg();
63
64 //
65 // Flash device Image
66 //
67 private ToolArg flashDeviceImage = new ToolArg();
68
69 //
70 // MCI file
71 //
72 private FileArg mciFile = new FileArg();
73
74 //
75 // MCO file
76 //
77 private FileArg mcoFile = new FileArg();
78
79 //
80 // Discover FD image
81 //
82 private ToolArg fdImage = new ToolArg();
83
84 //
85 // Dsc file
86 //
87 private FileArg dscFile = new FileArg();
88
89 //
90 // Asm INC file
91 //
92 private FileArg asmIncFile = new FileArg();
93
94 //
95 // Image out file
96 //
97 private FileArg imageOutFile = new FileArg();
98
99 //
100 // Header file
101 //
102 private FileArg headerFile = new FileArg();
103
104 //
105 // Input string file
106 //
107 private String inStrFile = "";
108
109 //
110 // Output string file
111 //
112 private String outStrFile = "";
113
114 //
115 //
116 //
117 private FileArg strFile = new FileArg();
118 //
119 // Base address
120 //
121 private ToolArg baseAddr = new ToolArg();
122
123 //
124 // Aligment
125 //
126 private ToolArg aligment = new ToolArg();
127
128 //
129 // Padding value
130 //
131 private ToolArg padValue = new ToolArg();
132
133 //
134 // output directory
135 //
136 private String outputDir = ".";
137
138 //
139 // MCI file array
140 //
141 FileArg mciFileArray = new FileArg();
142
143 /**
144 execute
145
146 FlashMapTask execute function is to assemble tool command line & execute
147 tool command line
148
149 @throws BuidException
150 **/
151 public void execute() throws BuildException {
152 if (isUptodate()) {
153 EdkLog.log(this, EdkLog.EDK_VERBOSE, headerFile.toFileList()
154 + imageOutFile.toFileList()
155 + mcoFile.toFileList()
156 + dscFile.toFileList()
157 + asmIncFile.toFileList()
158 + outStrFile
159 + " is up-to-date!");
160 return;
161 }
162
163 Project project = this.getOwningTarget().getProject();
164 //
165 // absolute path of efi tools
166 //
167 String path = project.getProperty("env.FRAMEWORK_TOOLS_PATH");
168 String command;
169 if (path == null) {
170 command = toolName;
171 } else {
172 command = path + File.separator + toolName;
173 }
174
175 //
176 // add substituted input file and output file
177 //
178 if (this.inStrFile != null && this.outStrFile != null
179 && this.inStrFile.length() > 0 && this.outStrFile.length() > 0) {
180 strFile.setPrefix(" -strsub ");
181 strFile.insValue(this.inStrFile);
182 strFile.insValue(this.outStrFile);
183 }
184
185 String argument = "" + flashDefFile + flashDevice + flashDeviceImage
186 + mciFile + mcoFile + fdImage + dscFile + asmIncFile
187 + imageOutFile + headerFile + strFile + baseAddr
188 + aligment + padValue + mciFileArray;
189
190
191 //
192 // lauch the program
193 //
194 // ProcessBuilder pb = new ProcessBuilder(argList);
195 // pb.directory(new File(outputDir));
196 int exitCode = 0;
197 try {
198 Commandline cmdline = new Commandline();
199 cmdline.setExecutable(command);
200 cmdline.createArgument().setLine(argument);
201
202 LogStreamHandler streamHandler = new LogStreamHandler(this,
203 Project.MSG_INFO, Project.MSG_WARN);
204 Execute runner = new Execute(streamHandler, null);
205
206 runner.setAntRun(project);
207 runner.setCommandline(cmdline.getCommandline());
208
209 if (outputDir != null) {
210 runner.setWorkingDirectory(new File(outputDir));
211 }
212 //
213 // log command line string.
214 //
215 EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmdline.getCommandline()));
216 EdkLog.log(this, flashDefFile.toFileList()
217 + mciFile.toFileList()
218 + mciFileArray.toFileList()
219 + fdImage.toFileList()
220 + inStrFile
221 + " => "
222 + headerFile.toFileList()
223 + imageOutFile.toFileList()
224 + mcoFile.toFileList()
225 + dscFile.toFileList()
226 + asmIncFile.toFileList()
227 + outStrFile);
228
229 exitCode = runner.execute();
230 if (exitCode != 0) {
231 EdkLog.log(this, "ERROR = " + Integer.toHexString(exitCode));
232 } else {
233 EdkLog.log(this, EdkLog.EDK_VERBOSE, "FlashMap succeeded!");
234 }
235 } catch (Exception e) {
236 throw new BuildException(e.getMessage());
237 } finally {
238 if (exitCode != 0) {
239 throw new BuildException("FlashMap failed!");
240 }
241 }
242 }
243
244 /**
245 getFlashDefFile
246
247 This function is to get class member "flashDefFile"
248
249 @return flashDeFile Name of flash definition file.
250 **/
251 public String getFlashDefFile() {
252 return this.flashDefFile.getValue();
253 }
254
255 /**
256 setFlashDefFile
257
258 This function is to set class member "flashDefFile"
259
260 @param flashDefFile
261 Name of flash definition file.
262 **/
263 public void setFlashDefFile(String flashDefFile) {
264 this.flashDefFile.setArg(" -fdf ", flashDefFile);
265 }
266
267 /**
268 getAligment
269
270 This function is to get class member "aligment"
271
272 @return aligment String of aligment value.
273 **/
274 public String getAligment() {
275 return this.aligment.getValue();
276 }
277
278 /**
279 setAligment
280
281 This function is to set class member "aligment"
282
283 @param aligment
284 String of aligment value.
285 **/
286 public void setAligment(String aligment) {
287 this.aligment.setArg(" -align ", aligment);
288 }
289
290 /**
291 getAsmIncFile
292
293 This function is to get class member "asmIncFile"
294
295 @return asmIncFile String of ASM include file.
296 **/
297 public String getAsmIncFile() {
298 return this.asmIncFile.getValue();
299 }
300
301 /**
302 setAsmIncFile
303
304 This function is to set class member "asmIncFile"
305
306 @param asmIncFile
307 String of ASM include file.
308 **/
309 public void setAsmIncFile(String asmIncFile) {
310 this.asmIncFile.setArg(" -asmincfile ", asmIncFile);
311 }
312
313 /**
314 getBaseAddr
315
316 This function is to get class member "baseAddr"
317
318 @return baseAddr String of base address value.
319 **/
320 public String getBaseAddr() {
321 return this.baseAddr.getValue();
322 }
323
324 /**
325 setBaseAddr
326
327 This function is to set class member "baseAddr"
328
329 @param baseAddr
330 String of base address value.
331 **/
332 public void setBaseAddr(String baseAddr) {
333 this.baseAddr.setArg(" -baseaddr ", baseAddr);
334 }
335
336 /**
337 getDscFile
338
339 This function is to get class member "dscFile"
340
341 @return dscFile name of DSC file
342 **/
343 public String getDscFile() {
344 return this.dscFile.getValue();
345 }
346
347 /**
348 setDscFile
349
350 This function is to set class member "dscFile"
351
352 @param dscFile
353 name of DSC file
354 **/
355 public void setDscFile(String dscFile) {
356 this.dscFile.setArg(" -dsc ", dscFile);
357 }
358
359 /**
360 getFdImage
361
362 This function is to get class member "fdImage"
363
364 @return fdImage name of input FDI image file.
365 **/
366 public String getFdImage() {
367 return this.fdImage.getValue();
368 }
369
370 /**
371 setFdImage
372
373 This function is to set class member "fdImage"
374
375 @param fdImage
376 name of input FDI image file.
377 **/
378 public void setFdImage(String fdImage) {
379 this.fdImage.setArg(" -discover ", fdImage);
380 }
381
382 /**
383 getFlashDevice
384
385 This function is to get class member "flashDevice".
386
387 @return flashDevice name of flash device.
388 **/
389 public String getFlashDevice() {
390 return this.flashDevice.getValue();
391 }
392
393 /**
394 setFlashDevice
395
396 This function is to set class member "flashDevice"
397
398 @param flashDevice
399 name of flash device.
400 **/
401 public void setFlashDevice(String flashDevice) {
402 this.flashDevice.setArg(" -flashdevice ", flashDevice);
403 }
404
405 /**
406 getFlashDeviceImage
407
408 This function is to get class member "flashDeviceImage"
409
410 @return flashDeviceImage name of flash device image
411 **/
412 public String getFlashDeviceImage() {
413 return this.flashDeviceImage.getValue();
414 }
415
416 /**
417 setFlashDeviceImage
418
419 This function is to set class member "flashDeviceImage"
420
421 @param flashDeviceImage
422 name of flash device image
423 **/
424 public void setFlashDeviceImage(String flashDeviceImage) {
425 this.flashDeviceImage.setArg(" -flashdeviceimage ", flashDeviceImage);
426
427 }
428
429 /**
430 getHeaderFile
431
432 This function is to get class member "headerFile"
433
434 @return headerFile name of include file
435 **/
436 public String getHeaderFile() {
437 return this.headerFile.getValue();
438 }
439
440 /**
441 setHeaderFile
442
443 This function is to set class member "headerFile"
444
445 @param headerFile
446 name of include file
447 **/
448 public void setHeaderFile(String headerFile) {
449 this.headerFile.setArg(" -hfile ", headerFile);
450 }
451
452 /**
453 getImageOutFile
454
455 This function is to get class member "imageOutFile"
456
457 @return imageOutFile name of output image file
458 **/
459 public String getImageOutFile() {
460 return this.imageOutFile.getValue();
461 }
462
463 /**
464 setImageOutFile
465
466 This function is to set class member "ImageOutFile"
467
468 @param imageOutFile
469 name of output image file
470 **/
471 public void setImageOutFile(String imageOutFile) {
472 this.imageOutFile.setArg(" -imageout ", imageOutFile);
473 }
474
475 /**
476 getInStrFile
477
478 This function is to get class member "inStrFile"
479
480 @return inStrFile name of input file which used to replace symbol names.
481 **/
482 public String getInStrFile() {
483 return this.inStrFile;
484 }
485
486 /**
487 setInStrFile
488
489 This function is to set class member "inStrFile"
490
491 @param inStrFile
492 name of input file which used to replace symbol names.
493 **/
494 public void setInStrFile(String inStrFile) {
495 this.inStrFile = inStrFile;
496 }
497
498 /**
499 getMciFile
500
501 This function is to get class member "mciFile"
502
503 @return mciFile name of input microcode file
504 **/
505 public String getMciFile() {
506 return this.mciFile.getValue();
507 }
508
509 /**
510 setMciFile
511
512 This function is to set class member "mciFile"
513
514 @param mciFile
515 name of input microcode file
516 **/
517 public void setMciFile(String mciFile) {
518 this.mciFile.setArg(" -mci ", mciFile);
519 }
520
521 /**
522 getMcoFile
523
524 This function is to get class member "mcoFile"
525
526 @return mcoFile name of output binary microcode image
527 **/
528 public String getMcoFile() {
529 return this.mcoFile.getValue();
530 }
531
532 /**
533 setMcoFile
534
535 This function is to set class member "mcoFile"
536
537 @param mcoFile
538 name of output binary microcode image
539 **/
540 public void setMcoFile(String mcoFile) {
541 this.mcoFile.setArg(" -mco ", mcoFile);
542 }
543
544 /**
545 getOutStrFile
546
547 This function is to get class member "outStrFile"
548
549 @return outStrFile name of output string substitution file
550 **/
551 public String getOutStrFile() {
552 return this.outStrFile;
553 }
554
555 /**
556 setOutStrFile
557
558 This function is to set class member "outStrFile"
559
560 @param outStrFile
561 name of output string substitution file
562 **/
563 public void setOutStrFile(String outStrFile) {
564 this.outStrFile = outStrFile;
565 }
566
567 /**
568 getPadValue
569
570 This function is to get class member "padValue"
571
572 @return padValue string of byte value to use as padding
573 **/
574 public String getPadValue() {
575 return this.padValue.getValue();
576 }
577
578 /**
579 setPadValue
580
581 This function is to set class member "padValue"
582
583 @param padValue
584 string of byte value to use as padding
585 **/
586 public void setPadValue(String padValue) {
587 this.padValue.setArg(" -padvalue ", padValue);
588 }
589
590 /**
591 addMciFile
592
593 This function is to add Microcode binary file
594
595 @param mciFile
596 instance of input class
597 **/
598 public void addConfiguredMciFile(FileArg mciFile) {
599 this.mciFileArray.setPrefix(" -mcmerge ");
600 this.mciFileArray.insert(mciFile);
601 }
602
603 /**
604 getOutputDir
605
606 This function is to get class member "outputDir"
607
608 @return outputDir string of output directory
609 **/
610 public String getOutputDir() {
611 return outputDir;
612 }
613
614 /**
615 setOutputDir
616
617 This function is to set class member "outputDir"
618
619 @param outputDir
620 string of output directory
621 **/
622 public void setOutputDir(String outputDir) {
623 this.outputDir = outputDir;
624 }
625
626 //
627 // Dependency check
628 //
629 private boolean isUptodate() {
630 long srcTimeStamp = 0;
631 String srcName = "";
632 String dstName = "";
633 long timeStamp = 0;
634
635 if (!flashDefFile.isEmpty()) {
636 srcName = flashDefFile.getValue();
637 timeStamp = new File(srcName).lastModified();
638 if (timeStamp > srcTimeStamp) {
639 srcTimeStamp = timeStamp;
640 }
641 }
642
643 if (!mciFile.isEmpty()) {
644 srcName = mciFile.getValue();
645 timeStamp = new File(srcName).lastModified();
646 if (timeStamp > srcTimeStamp) {
647 srcTimeStamp = timeStamp;
648 }
649 }
650
651 if (!fdImage.isEmpty()) {
652 srcName = fdImage.getValue();
653 timeStamp = new File(srcName).lastModified();
654 if (timeStamp > srcTimeStamp) {
655 srcTimeStamp = timeStamp;
656 }
657 }
658
659 if (inStrFile.length() != 0) {
660 srcName = inStrFile;
661 timeStamp = new File(srcName).lastModified();
662 if (timeStamp > srcTimeStamp) {
663 srcTimeStamp = timeStamp;
664 }
665 }
666
667 if (!mciFileArray.isEmpty()) {
668 for (int i = 0; i < mciFileArray.nameList.size(); ++i) {
669 srcName += mciFileArray.nameList.get(i) + " ";
670 timeStamp = new File(mciFileArray.nameList.get(i)).lastModified();
671 if (timeStamp > srcTimeStamp) {
672 srcTimeStamp = timeStamp;
673 }
674 }
675 }
676
677 if (!headerFile.isEmpty()) {
678 dstName = headerFile.getValue();
679 File dstFile = new File(dstName);
680 if (!dstFile.isAbsolute()) {
681 dstName = outputDir + File.separator + dstName;
682 dstFile = new File(dstName);
683 }
684
685 if (srcTimeStamp > dstFile.lastModified()) {
686 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
687 return false;
688 }
689 }
690
691 if (!imageOutFile.isEmpty()) {
692 dstName = imageOutFile.getValue();
693 File dstFile = new File(dstName);
694 if (!dstFile.isAbsolute()) {
695 dstName = outputDir + File.separator + dstName;
696 dstFile = new File(dstName);
697 }
698
699 if (srcTimeStamp > dstFile.lastModified()) {
700 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
701 return false;
702 }
703
704 //
705 // we need to check the time stamp of each FV file specified in fdf file
706 //
707 if (!isFdUptodate(dstName, getFvFiles(flashDefFile.getValue()))) {
708 return false;
709 }
710 }
711
712 if (!mcoFile.isEmpty()) {
713 dstName = mcoFile.getValue();
714 File dstFile = new File(dstName);
715 if (!dstFile.isAbsolute()) {
716 dstName = outputDir + File.separator + dstName;
717 dstFile = new File(dstName);
718 }
719
720 if (srcTimeStamp > dstFile.lastModified()) {
721 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
722 return false;
723 }
724 }
725
726 if (!dscFile.isEmpty()) {
727 dstName = dscFile.getValue();
728 File dstFile = new File(dstName);
729 if (!dstFile.isAbsolute()) {
730 dstName = outputDir + File.separator + dstName;
731 dstFile = new File(dstName);
732 }
733
734 if (srcTimeStamp > dstFile.lastModified()) {
735 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
736 return false;
737 }
738 }
739
740 if (!asmIncFile.isEmpty()) {
741 dstName = asmIncFile.getValue();
742 File dstFile = new File(dstName);
743 if (!dstFile.isAbsolute()) {
744 dstName = outputDir + File.separator + dstName;
745 dstFile = new File(dstName);
746 }
747
748 if (srcTimeStamp > dstFile.lastModified()) {
749 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
750 return false;
751 }
752 }
753
754 if (outStrFile.length() != 0) {
755 dstName = outStrFile;
756 File dstFile = new File(dstName);
757 if (!dstFile.isAbsolute()) {
758 dstName = outputDir + File.separator + dstName;
759 dstFile = new File(dstName);
760 }
761
762 if (srcTimeStamp > dstFile.lastModified()) {
763 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
764 return false;
765 }
766 }
767
768 return true;
769 }
770
771 //
772 // Parse the flash definition file and find out the FV file names
773 //
774 private List<String> getFvFiles(String fdfFileName) {
775 File fdfFile = new File(fdfFileName);
776 int fileLength = (int)fdfFile.length();
777 char[] fdfContent = new char[fileLength];
778 List<String> fileList = new ArrayList<String>();
779
780 try {
781 FileReader reader = new FileReader(fdfFile);
782 BufferedReader in = new BufferedReader(reader);
783
784 in.read(fdfContent, 0, fileLength);
785 String str = new String(fdfContent);
786
787 //
788 // match the
789 // File {
790 // ...
791 // }
792 // block
793 //
794 Matcher matcher = fileBlock.matcher(str);
795 while (matcher.find()) {
796 String fileBlockContent = str.substring(matcher.start(1), matcher.end(1));
797 //
798 // match the definition like
799 // Name = "..."
800 //
801 Matcher nameMatcher = fileNameDef.matcher(fileBlockContent);
802 if (nameMatcher.find()) {
803 fileList.add(fileBlockContent.substring(nameMatcher.start(1), nameMatcher.end(1)));
804 }
805 }
806
807 in.close();
808 reader.close();
809 } catch (Exception ex) {
810 throw new BuildException(ex.getMessage());
811 }
812
813 return fileList;
814 }
815
816 private boolean isFdUptodate(String fdFile, List<String> fvFileList) {
817 String fvDir = ".";
818 File fd = new File(fdFile);
819
820 if (outputDir.equals(".")) {
821 if (!fd.isAbsolute()) {
822 //
823 // If we cannot get the absolute path of fd file, we caanot
824 // get its time stamp. Re-generate it always in such situation.
825 //
826 EdkLog.log(this, EdkLog.EDK_VERBOSE, "Cannot retrieve the time stamp of " + fdFile);
827 return false;
828 }
829 fvDir = fd.getParent();
830 } else {
831 fvDir = outputDir;
832 if (!fd.isAbsolute()) {
833 fd = new File(fvDir + File.separator + fdFile);
834 }
835 }
836
837 long fdTimeStamp = fd.lastModified();
838 for (int i = 0; i < fvFileList.size(); ++i) {
839 File fv = new File(fvDir + File.separator + fvFileList.get(i));
840 if (fv.lastModified() > fdTimeStamp) {
841 EdkLog.log(this, EdkLog.EDK_VERBOSE, fv.getPath() + " has been changed since last build!");
842 return false;
843 }
844 }
845
846 return true;
847 }
848 }