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