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