]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java
Remove static from SurfaceAreaQuery.java for preparing parallel build.(1)
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / FfsProcess.java
1 /** @file
2 File is FfsProcess class which is used to get the corresponding FFS layout
3 information for driver module.
4
5 Copyright (c) 2006, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 **/
14 package org.tianocore.build;
15
16 import java.io.File;
17 import java.util.Vector;
18
19 import javax.xml.namespace.QName;
20
21 import org.apache.tools.ant.BuildException;
22 import org.apache.tools.ant.Project;
23 import org.apache.xmlbeans.XmlCursor;
24 import org.tianocore.BuildOptionsDocument;
25 import org.tianocore.build.global.GlobalData;
26 import org.tianocore.build.global.SurfaceAreaQuery;
27 import org.tianocore.build.id.FpdModuleIdentification;
28 import org.tianocore.common.definitions.EdkDefinitions;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31
32 /**
33 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>
34
35 <p>The FFS Layout is like following: </p>
36
37 <pre>
38 &lt;Ffs type="APPLICATION"&gt;
39 &lt;Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" /&gt;
40 &lt;Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" /&gt;
41 &lt;Sections EncapsulationType="Compress"&gt;
42 &lt;Sections EncapsulationType="Guid-Defined"&gt;
43 &lt;Section SectionType="EFI_SECTION_PE32" /&gt;
44 &lt;Section SectionType="EFI_SECTION_USER_INTERFACE" /&gt;
45 &lt;Section SectionType="EFI_SECTION_VERSION" /&gt;
46 &lt;/Sections&gt;
47 &lt;/Sections&gt;
48 &lt;/Ffs&gt;
49 </pre>
50
51 @since GenBuild 1.0
52 **/
53 public class FfsProcess {
54
55 private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;
56
57 ///
58 /// ANT script to call GenFfs
59 ///
60 private Element ffsNode = null;
61
62 ///
63 /// Module base name
64 ///
65 private String basename;
66
67 ///
68 /// Sections type: normal
69 ///
70 private static int MODE_NONE = 0;
71
72 ///
73 /// Sections type: compress
74 ///
75 private static int MODE_COMPRESS = 1;
76
77 ///
78 /// Sections type: guid-define
79 ///
80 private static int MODE_GUID_DEFINED = 2;
81
82 ///
83 /// mapping from section type to section output file extension
84 ///
85 public static final String[][] sectionExt = EdkDefinitions.SectionTypeExtensions;
86
87 private SurfaceAreaQuery saq = null;
88
89 public FfsProcess(SurfaceAreaQuery saq) {
90 this.saq = saq;
91 }
92
93 /**
94 search in the type, if componentType is listed in type, return true;
95 otherwise return false.
96
97 @param type a list supported component type separated by comma
98 @param componentType current module component type
99 @return whether componentType is one of type
100 **/
101 private boolean isMatch(String type, String componentType) {
102 String[] items = type.split("[ \t]*,[ \t]*");
103 for (int i = 0; i < items.length; i++) {
104 if (items[i].equalsIgnoreCase(componentType)) {
105 return true;
106 }
107 }
108 return false;
109 }
110
111 /**
112 Find the corresponding FFS layout in <code>FPD</code>.
113
114 @param buildType Current module's component type
115 @param project Ant project
116 @return whether find the corresponding FFS layout
117 @throws BuildException
118 If can't find FFS Layout in FPD.
119 **/
120 public boolean initSections(String buildType, Project project, FpdModuleIdentification fpdModuleId) throws BuildException {
121 //
122 // Try to find Ffs layout from FPD file
123 //
124 saq.push(GlobalData.getFpdBuildOptions());
125 BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = saq.getFpdFfs();
126 saq.pop();
127 for (int i = 0; i < ffsArray.length; i++) {
128 if (isMatch(ffsArray[i].getFfsKey(), buildType)) {
129 ffsXmlObject = ffsArray[i];
130 return true;
131 }
132 }
133
134 //
135 // If FfsFormatKey is not null, report exception and fail build
136 // Otherwise report warning message
137 //
138 if (buildType == null) {
139 System.out.println("Warning: this module doesn't specify a FfsFormatKey. ");
140 } else {
141 throw new BuildException("Can't find the FfsFormatKey [" + buildType + "] attribute in the FPD file!");
142 }
143
144 return false;
145 }
146
147 /**
148 Recursive parse the FFS layout. Find out all section type here used.
149
150 @param document BaseName_build.xml Xml document
151 @param basename Module's base name
152 @param guid Module's GUID
153 @param targetFilename Module's final file name (GUID-BaseName.APP)
154 @return List of section type
155 **/
156 public String[] getGenSectionElements(Document document, String basename, String guid, String targetFilename) {
157 this.basename = basename;
158 if (ffsXmlObject == null) {
159 return new String[0];
160 }
161 Vector<String> sectionList = new Vector<String>();
162 XmlCursor cursor = null;
163 try {
164 cursor = ffsXmlObject.newCursor();
165 } catch (Exception e) {
166 return null;
167 }
168 int mode = MODE_NONE;
169 Element genffsfileEle = document.createElement("genffsfile");
170 genffsfileEle.setAttribute("outputDir", "${BIN_DIR}");
171 genffsfileEle.setAttribute("moduleType", "${MODULE_TYPE}");
172 genffsfileEle.setAttribute("BaseName", basename);
173 genffsfileEle.setAttribute("fileGuid", guid);
174
175 if (cursor.toFirstChild()) {
176 do {
177 if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) {
178 String name = cursor.getAttributeText(new QName("Name"));
179 String value = cursor.getAttributeText(new QName("Value"));
180 genffsfileEle.setAttribute(changeAttributeName(name), value);
181 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {
182 cursor.push();
183 dealSection(mode, document, genffsfileEle, cursor, sectionList);
184 cursor.pop();
185 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {
186 cursor.push();
187 dealSections(mode, document, genffsfileEle, cursor, sectionList);
188 cursor.pop();
189 }
190 } while (cursor.toNextSibling());
191 }
192 //
193 // Check dependency
194 //
195 Element outofdateEle = document.createElement("OnDependency");
196 Element sourceEle = document.createElement("sourcefiles");
197 String[] result = new String[sectionList.size()];
198 for (int i = 0; i < sectionList.size(); i++) {
199 result[i] = (String) sectionList.get(i);
200 Element pathEle = document.createElement("file");
201 pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename
202 + getSectionExt(result[i]));
203 sourceEle.appendChild(pathEle);
204 }
205 outofdateEle.appendChild(sourceEle);
206 Element targetEle = document.createElement("targetfiles");
207 Element fileEle = document.createElement("file");
208 fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);
209 targetEle.appendChild(fileEle);
210 outofdateEle.appendChild(targetEle);
211 Element sequentialEle = document.createElement("sequential");
212 sequentialEle.appendChild(genffsfileEle);
213 outofdateEle.appendChild(sequentialEle);
214 ffsNode = outofdateEle;
215 return result;
216 }
217
218 /**
219 Change the attribute name. For example:
220
221 <pre>
222 Before change: FFS_ATTRIB_CHECKSUM
223 After change: ffsATTRIBCHECKSUM
224 </pre>
225
226 @param name Original attribute name
227 @return Changed attribute name
228 **/
229 private String changeAttributeName(String name) {
230 String[] strs = name.split("_");
231 String str = strs[0].toLowerCase();
232 for (int j = 1; j < strs.length; j++) {
233 str += strs[j];
234 }
235 return str;
236 }
237
238 /**
239 Recursively deal with Sections. If sections does not specify a type, then omit it.
240
241 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
242 @param doc Xml Document
243 @param root Root Node
244 @param cursor Current FFS layout cursor
245 @param list List of section type here used
246 **/
247 private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {
248 String type = cursor.getAttributeText(new QName("EncapsulationType"));
249 if (type == null) {
250 if (cursor.toFirstChild()) {
251 do {
252 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {
253 cursor.push();
254 dealSection(mode, doc, root, cursor, list);
255 cursor.pop();
256 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {
257 cursor.push();
258 dealSections(mode, doc, root, cursor, list);
259 cursor.pop();
260 }
261 } while (cursor.toNextSibling());
262 }
263 return;
264 }
265 Element ele;
266 if (type.equalsIgnoreCase("COMPRESS")) {
267 mode = MODE_COMPRESS;
268 //
269 // <compress compressName = "dummy">
270 //
271 ele = doc.createElement("compress");
272 ele.setAttribute("compressName", "dummy");
273 } else {
274 mode = MODE_GUID_DEFINED;
275 //
276 // <tool toolName="${OEMTOOLPATH}\toolname"
277 // outputPath = "${DEST_DIR_OUTPUT}">
278 //
279 ele = doc.createElement("tool");
280 ele.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"
281 + File.separatorChar + "GenCRC32Section");
282 ele.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
283 }
284 if (cursor.toFirstChild()) {
285 do {
286 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {
287 cursor.push();
288 dealSection(mode, doc, ele, cursor, list);
289 cursor.pop();
290 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {
291 cursor.push();
292 dealSections(mode, doc, ele, cursor, list);
293 cursor.pop();
294 }
295 } while (cursor.toNextSibling());
296 }
297 root.appendChild(ele);
298 }
299
300 /**
301 Recursively deal with section.
302
303 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
304 @param doc Xml Document
305 @param root Root Node
306 @param cursor Current FFS layout cursor
307 @param list List of section type here used
308 **/
309 private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {
310 String type = cursor.getAttributeText(new QName("SectionType"));
311
312 //
313 // Judge if file is specified? Yes, just use the file, else call Build Macro
314 // If fileName is null, means without FileNames specify in FPD file
315 //
316 String fileName = null;
317 cursor.push();
318 if (cursor.toFirstChild()) {
319 do {
320 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filenames")) {
321 cursor.push();
322 if (cursor.toFirstChild()) {
323 do {
324 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filename")) {
325 fileName = cursor.getTextValue();
326 }
327 } while (cursor.toNextSibling());
328 }
329 cursor.pop();
330 }
331 } while (cursor.toNextSibling());
332 }
333
334 cursor.pop();
335
336 if (fileName == null) {
337 list.addElement(type);
338 }
339 if (mode == MODE_GUID_DEFINED) {
340 //
341 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
342 //
343 Element ele = doc.createElement("input");
344 if (fileName == null) {
345 ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));
346 } else {
347 ele.setAttribute("file", "${PLATFORM_DIR}" + File.separatorChar + fileName);
348 }
349 root.appendChild(ele);
350 } else {
351 //
352 // <sectFile fileName= "..."/>
353 //
354 Element ele = doc.createElement("sectFile");
355 if (fileName == null) {
356 ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));
357 } else {
358 ele.setAttribute("fileName", "${PLATFORM_DIR}" + File.separatorChar + fileName);
359 }
360 root.appendChild(ele);
361 }
362 }
363
364 /**
365 Get the corresponding section file suffix.
366
367 @param type Section type
368 @return Corresponding section file extension
369 **/
370 private String getSectionExt(String type) {
371 for (int i = 0; i < sectionExt.length; i++) {
372 if (sectionExt[i][0].equalsIgnoreCase(type)) {
373 return sectionExt[i][1];
374 }
375 }
376 return ".sec";
377 }
378
379 /**
380 Return the ANT script to call GenFfs Tool.
381
382 @return ANT script to call GenFfs Tool
383 **/
384 public Element getFfsNode() {
385 return ffsNode;
386 }
387 }