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