]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFvImageTask.java
Remove dependence check of FD upon FlashMap.fdf
[mirror_edk2.git] / Tools / Source / FrameworkTasks / org / tianocore / framework / tasks / GenFvImageTask.java
1 /** @file
2 GenFvImageTask class.
3
4 GenFvImageTask is to call GenFvImage.exe to generate FvImage.
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 org.apache.tools.ant.BuildException;
19 import org.apache.tools.ant.Project;
20 import org.apache.tools.ant.Task;
21 import org.apache.tools.ant.taskdefs.Execute;
22 import org.apache.tools.ant.taskdefs.LogStreamHandler;
23 import org.apache.tools.ant.types.Commandline;
24
25 import java.io.File;
26 import java.io.InputStreamReader;
27 import java.lang.ProcessBuilder;
28 import java.util.LinkedList;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import java.util.List;
32 import java.util.StringTokenizer;
33 import java.util.Iterator;
34 import java.io.BufferedReader;
35 import java.io.FileReader;
36
37 import org.tianocore.common.logger.EdkLog;
38
39 /**
40 GenFvImageTask
41
42 GenFvImageTask is to call GenFvImage.exe to generate the FvImage.
43
44 **/
45 public class GenFvImageTask extends Task implements EfiDefine{
46 //
47 // tool name
48 //
49 static final private String toolName = "GenFvImage";
50 //
51 // Pattern to match the section header (e.g. [options], [files])
52 //
53 static final private Pattern sectionHeader = Pattern.compile("\\[([^\\[\\]]+)\\]");
54 //
55 // The name of input inf file
56 //
57 private FileArg infFile = new FileArg();
58 //
59 // Output directory
60 //
61 private String outputDir = ".";
62
63 /**
64 execute
65
66 GenFvImageTask execute is to assemble tool command line & execute tool
67 command line.
68 **/
69 public void execute() throws BuildException {
70 Project project = this.getOwningTarget().getProject();
71 String path = project.getProperty("env.FRAMEWORK_TOOLS_PATH");
72
73 if (isUptodate()) {
74 EdkLog.log(this, EdkLog.EDK_VERBOSE, infFile.toFileList() + " is uptodate!");
75 return;
76 }
77
78 String command;
79 if (path == null) {
80 command = toolName;
81 } else {
82 command = path + File.separator + toolName;
83 }
84
85 String argument = "" + infFile;
86 //
87 // lauch the program
88 //
89 int exitCode = 0;
90 try {
91 Commandline cmdline = new Commandline();
92 cmdline.setExecutable(command);
93 cmdline.createArgument().setLine(argument);
94
95 LogStreamHandler streamHandler = new LogStreamHandler(this,
96 Project.MSG_INFO, Project.MSG_WARN);
97 Execute runner = new Execute(streamHandler, null);
98
99 runner.setAntRun(project);
100 runner.setCommandline(cmdline.getCommandline());
101 runner.setWorkingDirectory(new File(outputDir));
102 //
103 // log command line string.
104 //
105 EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmdline.getCommandline()));
106 EdkLog.log(this, infFile.toFileList());
107
108 exitCode = runner.execute();
109 if (exitCode != 0) {
110 EdkLog.log(this, "ERROR = " + Integer.toHexString(exitCode));
111 } else {
112 EdkLog.log(this, EdkLog.EDK_VERBOSE, "GenFvImage succeeded!");
113 }
114 } catch (Exception e) {
115 throw new BuildException(e.getMessage());
116 } finally {
117 if (exitCode != 0) {
118 throw new BuildException("GenFvImage: failed to generate FV file!");
119 }
120 }
121 }
122 /**
123 getInfFile
124
125 This function is to get class member of infFile
126 @return String name of infFile
127 **/
128 public String getInfFile() {
129 return infFile.getValue();
130 }
131
132 /**
133 setInfFile
134
135 This function is to set class member of infFile.
136
137 @param infFile name of infFile
138 **/
139 public void setInfFile(String infFile) {
140 this.infFile.setArg(" -I ", infFile);
141 }
142
143 /**
144 getOutputDir
145
146 This function is to get output directory.
147
148 @return Path of output directory.
149 **/
150 public String getOutputDir() {
151 return outputDir;
152 }
153
154 /**
155 setOutputDir
156
157 This function is to set output directory.
158
159 @param outputDir The output direcotry.
160 **/
161 public void setOutputDir(String outputDir) {
162 this.outputDir = outputDir;
163 }
164
165 //
166 // dependency check
167 //
168 private boolean isUptodate() {
169 String infName = this.infFile.getValue();
170 String fvName = "";
171 List<String> ffsFiles = new LinkedList<String>();
172 File inf = new File(infName);
173
174 try {
175 FileReader reader = new FileReader(inf);
176 BufferedReader in = new BufferedReader(reader);
177 String str;
178
179 //
180 // Read the inf file line by line
181 //
182 boolean inFiles = false;
183 boolean inOptions = false;
184 while ((str = in.readLine()) != null) {
185 str = str.trim();
186 if (str.length() == 0) {
187 continue;
188 }
189
190 Matcher matcher = sectionHeader.matcher(str);
191 if (matcher.find()) {
192 //
193 // We take care of only "options" and "files" section
194 //
195 String sectionName = str.substring(matcher.start(1), matcher.end(1));
196 if (sectionName.equalsIgnoreCase("options")) {
197 inOptions = true;
198 inFiles = false;
199 } else if (sectionName.equalsIgnoreCase("files")) {
200 inFiles = true;
201 inOptions = false;
202 } else {
203 inFiles = false;
204 inOptions = false;
205 }
206 continue;
207 }
208
209 //
210 // skip invalid line
211 //
212 int equalMarkPos = str.indexOf("=");
213 if (equalMarkPos < 0) {
214 continue;
215 }
216
217 //
218 // we have only interest in EFI_FILE_NAME
219 //
220 String fileNameFlag = str.substring(0, equalMarkPos).trim();
221 String fileName = str.substring(equalMarkPos + 1).trim();
222 if (!fileNameFlag.equalsIgnoreCase("EFI_FILE_NAME")
223 || fileName.length() == 0) {
224 continue;
225 }
226
227 if (inFiles) {
228 //
229 // files specified beneath the [files] section are source files
230 //
231 ffsFiles.add(fileName);
232 } else if (inOptions) {
233 //
234 // file specified beneath the [options] section is the target file
235 //
236 fvName = outputDir + File.separator + fileName;
237 }
238 }
239 } catch (Exception ex) {
240 throw new BuildException(ex.getMessage());
241 }
242
243 //
244 // if destionation file doesn't exist, we need to generate it.
245 //
246 File fvFile = new File(fvName);
247 if (!fvFile.exists()) {
248 EdkLog.log(this, EdkLog.EDK_VERBOSE, fvName + " doesn't exist!");
249 return false;
250 }
251
252 //
253 // the inf file itself will be taken as source file, check its timestamp
254 // against the target file
255 //
256 long fvFileTimeStamp = fvFile.lastModified();
257 if (inf.lastModified() > fvFileTimeStamp) {
258 EdkLog.log(this, EdkLog.EDK_VERBOSE, infName + " has been changed since last build!");
259 return false;
260 }
261
262 //
263 // no change in the inf file, we need to check each source files in it
264 // against the target file
265 //
266 for (Iterator it = ffsFiles.iterator(); it.hasNext(); ) {
267 String fileName = (String)it.next();
268 File file = new File(fileName);
269 if (file.lastModified() > fvFileTimeStamp) {
270 EdkLog.log(this, EdkLog.EDK_VERBOSE, fileName + " has been changed since last build!");
271 return false;
272 }
273 }
274
275 return true;
276 }
277 }