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