]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FlashMapTask.java
1) Add FileTimeStamp class to centralize the cache mechanism for file time stamp...
[mirror_edk2.git] / Tools / 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 long dstTimeStamp = 0;
633 String dstName = "";
634 long timeStamp = 0;
635
636 if (!flashDefFile.isEmpty()) {
637 srcName = flashDefFile.getValue();
638 timeStamp = new File(srcName).lastModified();
639 if (timeStamp > srcTimeStamp) {
640 srcTimeStamp = timeStamp;
641 }
642 }
643
644 if (!mciFile.isEmpty()) {
645 srcName = mciFile.getValue();
646 timeStamp = new File(srcName).lastModified();
647 if (timeStamp > srcTimeStamp) {
648 srcTimeStamp = timeStamp;
649 }
650 }
651
652 if (!fdImage.isEmpty()) {
653 srcName = fdImage.getValue();
654 timeStamp = new File(srcName).lastModified();
655 if (timeStamp > srcTimeStamp) {
656 srcTimeStamp = timeStamp;
657 }
658 }
659
660 if (inStrFile.length() != 0) {
661 srcName = inStrFile;
662 timeStamp = new File(srcName).lastModified();
663 if (timeStamp > srcTimeStamp) {
664 srcTimeStamp = timeStamp;
665 }
666 }
667
668 if (!mciFileArray.isEmpty()) {
669 for (int i = 0; i < mciFileArray.nameList.size(); ++i) {
670 srcName += mciFileArray.nameList.get(i) + " ";
671 timeStamp = new File(mciFileArray.nameList.get(i)).lastModified();
672 if (timeStamp > srcTimeStamp) {
673 srcTimeStamp = timeStamp;
674 }
675 }
676 }
677
678 if (!headerFile.isEmpty()) {
679 dstName = headerFile.getValue();
680 File dstFile = new File(dstName);
681 if (!dstFile.isAbsolute()) {
682 dstName = outputDir + File.separator + dstName;
683 dstFile = new File(dstName);
684 }
685
686 if (srcTimeStamp > dstFile.lastModified()) {
687 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
688 return false;
689 }
690 }
691
692 if (!imageOutFile.isEmpty()) {
693 dstName = imageOutFile.getValue();
694 File dstFile = new File(dstName);
695 if (!dstFile.isAbsolute()) {
696 dstName = outputDir + File.separator + dstName;
697 dstFile = new File(dstName);
698 }
699
700 if (srcTimeStamp > dstFile.lastModified()) {
701 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
702 return false;
703 }
704
705 //
706 // we need to check the time stamp of each FV file specified in fdf file
707 //
708 if (!isFdUptodate(dstName, getFvFiles(flashDefFile.getValue()))) {
709 return false;
710 }
711 }
712
713 if (!mcoFile.isEmpty()) {
714 dstName = mcoFile.getValue();
715 File dstFile = new File(dstName);
716 if (!dstFile.isAbsolute()) {
717 dstName = outputDir + File.separator + dstName;
718 dstFile = new File(dstName);
719 }
720
721 if (srcTimeStamp > dstFile.lastModified()) {
722 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
723 return false;
724 }
725 }
726
727 if (!dscFile.isEmpty()) {
728 dstName = dscFile.getValue();
729 File dstFile = new File(dstName);
730 if (!dstFile.isAbsolute()) {
731 dstName = outputDir + File.separator + dstName;
732 dstFile = new File(dstName);
733 }
734
735 if (srcTimeStamp > dstFile.lastModified()) {
736 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
737 return false;
738 }
739 }
740
741 if (!asmIncFile.isEmpty()) {
742 dstName = asmIncFile.getValue();
743 File dstFile = new File(dstName);
744 if (!dstFile.isAbsolute()) {
745 dstName = outputDir + File.separator + dstName;
746 dstFile = new File(dstName);
747 }
748
749 if (srcTimeStamp > dstFile.lastModified()) {
750 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
751 return false;
752 }
753 }
754
755 if (outStrFile.length() != 0) {
756 dstName = outStrFile;
757 File dstFile = new File(dstName);
758 if (!dstFile.isAbsolute()) {
759 dstName = outputDir + File.separator + dstName;
760 dstFile = new File(dstName);
761 }
762
763 if (srcTimeStamp > dstFile.lastModified()) {
764 EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!");
765 return false;
766 }
767 }
768
769 return true;
770 }
771
772 //
773 // Parse the flash definition file and find out the FV file names
774 //
775 private List<String> getFvFiles(String fdfFileName) {
776 File fdfFile = new File(fdfFileName);
777 int fileLength = (int)fdfFile.length();
778 char[] fdfContent = new char[fileLength];
779 List<String> fileList = new ArrayList<String>();
780
781 try {
782 FileReader reader = new FileReader(fdfFile);
783 BufferedReader in = new BufferedReader(reader);
784
785 in.read(fdfContent, 0, fileLength);
786 String str = new String(fdfContent);
787
788 //
789 // match the
790 // File {
791 // ...
792 // }
793 // block
794 //
795 Matcher matcher = fileBlock.matcher(str);
796 while (matcher.find()) {
797 String fileBlockContent = str.substring(matcher.start(1), matcher.end(1));
798 //
799 // match the definition like
800 // Name = "..."
801 //
802 Matcher nameMatcher = fileNameDef.matcher(fileBlockContent);
803 if (nameMatcher.find()) {
804 fileList.add(fileBlockContent.substring(nameMatcher.start(1), nameMatcher.end(1)));
805 }
806 }
807
808 in.close();
809 reader.close();
810 } catch (Exception ex) {
811 throw new BuildException(ex.getMessage());
812 }
813
814 return fileList;
815 }
816
817 private boolean isFdUptodate(String fdFile, List<String> fvFileList) {
818 String fvDir = ".";
819 File fd = new File(fdFile);
820
821 if (outputDir.equals(".")) {
822 if (!fd.isAbsolute()) {
823 //
824 // If we cannot get the absolute path of fd file, we caanot
825 // get its time stamp. Re-generate it always in such situation.
826 //
827 EdkLog.log(this, EdkLog.EDK_VERBOSE, "Cannot retrieve the time stamp of " + fdFile);
828 return false;
829 }
830 fvDir = fd.getParent();
831 } else {
832 fvDir = outputDir;
833 if (!fd.isAbsolute()) {
834 fd = new File(fvDir + File.separator + fdFile);
835 }
836 }
837
838 long fdTimeStamp = fd.lastModified();
839 for (int i = 0; i < fvFileList.size(); ++i) {
840 File fv = new File(fvDir + File.separator + fvFileList.get(i));
841 if (fv.lastModified() > fdTimeStamp) {
842 EdkLog.log(this, EdkLog.EDK_VERBOSE, fv.getPath() + " has been changed since last build!");
843 return false;
844 }
845 }
846
847 return true;
848 }
849 }