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