Fixed grammar and column widths (set min, preferred and max widths for version and...
[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
878ddf1f 17import java.util.Vector;\r
18\r
19import javax.xml.namespace.QName;\r
878ddf1f 20\r
21import org.apache.tools.ant.BuildException;\r
22import org.apache.tools.ant.Project;\r
23import org.apache.xmlbeans.XmlCursor;\r
24import org.apache.xmlbeans.XmlObject;\r
a29c47e0 25import org.tianocore.BuildOptionsDocument;\r
26import org.tianocore.build.global.GlobalData;\r
27import org.tianocore.build.global.SurfaceAreaQuery;\r
28import org.tianocore.build.id.FpdModuleIdentification;\r
878ddf1f 29import org.w3c.dom.Document;\r
30import org.w3c.dom.Element;\r
878ddf1f 31import org.w3c.dom.Node;\r
878ddf1f 32\r
33/** \r
34 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>\r
35 \r
36 <p>Property <code>COMMON_FILE</code> specified which file to search. The element\r
37 in <code>COMMON_FILE</code> is like following: </p>\r
38 \r
39 <pre>\r
40 &lt;Ffs type="APPLICATION"&gt;\r
41 &lt;Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" /&gt;\r
42 &lt;Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" /&gt;\r
43 &lt;Sections EncapsulationType="Compress"&gt;\r
44 &lt;Sections EncapsulationType="Guid-Defined"&gt;\r
45 &lt;Section SectionType="EFI_SECTION_PE32" /&gt; \r
46 &lt;Section SectionType="EFI_SECTION_USER_INTERFACE" /&gt;\r
47 &lt;Section SectionType="EFI_SECTION_VERSION" /&gt; \r
48 &lt;/Sections&gt;\r
49 &lt;/Sections&gt;\r
50 &lt;/Ffs&gt;\r
51 </pre>\r
52 \r
53 @since GenBuild 1.0\r
54**/\r
55public class FfsProcess {\r
56\r
57 ///\r
58 /// Xml Document Node for corresponding FFS layout\r
59 ///\r
60 private Node ffs;\r
a29c47e0 61 \r
62 private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;\r
878ddf1f 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
a29c47e0 134 public boolean initSections(String buildType, Project project, FpdModuleIdentification fpdModuleId) throws BuildException {\r
878ddf1f 135 //\r
a29c47e0 136 // Firstly, try to find in ModuleSA\r
878ddf1f 137 //\r
a29c47e0 138// BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = SurfaceAreaQuery.getModuleFfs();\r
139// for (int i = 0; i < ffsArray.length; i++) {\r
140// if (isMatch(ffsArray[i].getFfsKey(), buildType)) {\r
141// ffsXmlObject = ffsArray[i];\r
142// return true;\r
143// }\r
144// }\r
145 \r
146 //\r
147 // secondly, try to sections defined in PLATFORM level\r
148 //\r
149 SurfaceAreaQuery.push(GlobalData.getFpdBuildOptions());\r
150 BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = SurfaceAreaQuery.getFpdFfs();\r
151 SurfaceAreaQuery.pop();\r
152 for (int i = 0; i < ffsArray.length; i++) {\r
153 if (isMatch(ffsArray[i].getFfsKey(), buildType)) {\r
154 ffsXmlObject = ffsArray[i];\r
155 return true;\r
156 }\r
157 }\r
158 \r
878ddf1f 159 //\r
e64c74dd 160 // If FfsFormatKey is not null, report exception and fail build\r
161 // Otherwise report warning message\r
878ddf1f 162 //\r
e64c74dd 163 if (buildType == null) {\r
164 System.out.println("Warning: this module doesn't specify a FfsFormatKey. ");\r
878ddf1f 165 }\r
e64c74dd 166 else {\r
167 throw new BuildException("Can't find FfsFormatKey [" + buildType + "] in FPD file. "); \r
878ddf1f 168 }\r
e64c74dd 169\r
878ddf1f 170 if (ffs == null) {\r
171 return false;\r
172 } else {\r
173 return true;\r
174 }\r
175 }\r
176 \r
177 /**\r
178 Recursive parse the FFS layout. Find out all section type here used. \r
179 \r
180 @param document BaseName_build.xml Xml document\r
181 @param basename Module's base name\r
182 @param guid Module's GUID\r
183 @param targetFilename Module's final file name (GUID-BaseName.APP)\r
184 @return List of section type\r
185 **/\r
186 public String[] getGenSectionElements(Document document, String basename, String guid, String targetFilename) {\r
187 this.basename = basename;\r
a29c47e0 188 if (ffs == null && ffsXmlObject == null) {\r
878ddf1f 189 return new String[0];\r
190 }\r
191 Vector<String> sectionList = new Vector<String>();\r
192 XmlCursor cursor = null;\r
193 try {\r
a29c47e0 194 if (ffsXmlObject == null) {\r
195 cursor = XmlObject.Factory.parse(ffs).newCursor();\r
196 }\r
197 else {\r
198 cursor = ffsXmlObject.newCursor();\r
199 }\r
878ddf1f 200 } catch (Exception e) {\r
201 return null;\r
202 }\r
203 int mode = MODE_NONE;\r
204 Element root = document.createElement("genffsfile");\r
205 root.setAttribute("outputDir", "${BIN_DIR}");\r
a29c47e0 206 root.setAttribute("moduleType", "${MODULE_TYPE}");\r
878ddf1f 207 root.setAttribute("BaseName", basename);\r
208 root.setAttribute("fileGuid", guid);\r
a29c47e0 209 if (ffsXmlObject == null) {\r
210 cursor.toFirstChild();\r
211 }\r
878ddf1f 212 if (cursor.toFirstChild()) {\r
213 do {\r
214 if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) {\r
215 String name = cursor.getAttributeText(new QName("Name"));\r
216 String value = cursor.getAttributeText(new QName("Value"));\r
217 root.setAttribute(changeAttributeName(name), value);\r
218 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
219 cursor.push();\r
220 dealSection(mode, document, root, cursor, sectionList);\r
221 cursor.pop();\r
222 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
223 cursor.push();\r
224 dealSections(mode, document, root, cursor, sectionList);\r
225 cursor.pop();\r
226 }\r
227 } while (cursor.toNextSibling());\r
228 }\r
229 //\r
230 // Check dependency \r
231 //\r
232 Element outofdateEle = document.createElement("OnDependency");\r
233 Element sourceEle = document.createElement("sourcefiles");\r
234 String[] result = new String[sectionList.size()];\r
235 for (int i = 0; i < sectionList.size(); i++) {\r
236 result[i] = (String) sectionList.get(i);\r
237 Element pathEle = document.createElement("file");\r
238 pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename\r
239 + getSectionExt(result[i]));\r
240 sourceEle.appendChild(pathEle);\r
241 }\r
242 outofdateEle.appendChild(sourceEle);\r
243 Element targetEle = document.createElement("targetfiles");\r
244 Element fileEle = document.createElement("file");\r
52cbbdbc 245 fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);\r
878ddf1f 246 targetEle.appendChild(fileEle);\r
247 outofdateEle.appendChild(targetEle);\r
248 Element sequentialEle = document.createElement("sequential");\r
249 sequentialEle.appendChild(root);\r
250 outofdateEle.appendChild(sequentialEle);\r
251 ffsNode = outofdateEle;\r
252 return result;\r
253 }\r
254\r
255 /**\r
256 Change the attribute name. For example: \r
257 \r
258 <pre>\r
259 Before change: FFS_ATTRIB_CHECKSUM \r
260 After change: ffsATTRIBCHECKSUM\r
261 </pre>\r
262 \r
263 @param name Original attribute name\r
264 @return Changed attribute name\r
265 **/\r
266 private String changeAttributeName(String name) {\r
267 String[] strs = name.split("_");\r
268 String str = strs[0].toLowerCase();\r
269 for (int j = 1; j < strs.length; j++) {\r
270 str += strs[j];\r
271 }\r
272 return str;\r
273 }\r
274\r
275 /**\r
276 Recursively deal with Sections. If sections does not specify a type, then omit it.\r
277 \r
278 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
279 @param doc Xml Document\r
280 @param root Root Node\r
281 @param cursor Current FFS layout cursor\r
282 @param list List of section type here used\r
283 **/\r
284 private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
285 String type = cursor.getAttributeText(new QName("EncapsulationType"));\r
286 if (type == null) {\r
287 if (cursor.toFirstChild()) {\r
288 do {\r
289 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
290 cursor.push();\r
291 dealSection(mode, doc, root, cursor, list);\r
292 cursor.pop();\r
293 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
294 cursor.push();\r
295 dealSections(mode, doc, root, cursor, list);\r
296 cursor.pop();\r
297 }\r
298 } while (cursor.toNextSibling());\r
299 }\r
300 return;\r
301 }\r
302 Element ele;\r
303 if (type.equalsIgnoreCase("COMPRESS")) {\r
304 mode = MODE_COMPRESS;\r
305 //\r
306 // <compress compressName = "dummy">\r
307 //\r
308 ele = doc.createElement("compress");\r
309 ele.setAttribute("compressName", "dummy");\r
310 } else {\r
311 mode = MODE_GUID_DEFINED;\r
312 //\r
313 // <tool toolName="${OEMTOOLPATH}\toolname"\r
314 // outputPath = "${DEST_DIR_OUTPUT}">\r
315 //\r
316 ele = doc.createElement("tool");\r
a33f3dd1 317 ele.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
878ddf1f 318 + File.separatorChar + "GenCRC32Section");\r
319 ele.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");\r
320 }\r
321 if (cursor.toFirstChild()) {\r
322 do {\r
323 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
324 cursor.push();\r
325 dealSection(mode, doc, ele, cursor, list);\r
326 cursor.pop();\r
327 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
328 cursor.push();\r
329 dealSections(mode, doc, ele, cursor, list);\r
330 cursor.pop();\r
331 }\r
332 } while (cursor.toNextSibling());\r
333 }\r
334 root.appendChild(ele);\r
335 }\r
336 \r
337 /**\r
338 Recursively deal with section.\r
339 \r
340 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
341 @param doc Xml Document\r
342 @param root Root Node\r
343 @param cursor Current FFS layout cursor\r
344 @param list List of section type here used\r
345 **/\r
346 private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
347 String type = cursor.getAttributeText(new QName("SectionType"));\r
348 list.addElement(type);\r
349 if (mode == MODE_GUID_DEFINED) {\r
350 //\r
351 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>\r
352 //\r
353 Element ele = doc.createElement("input");\r
354 ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
355 root.appendChild(ele);\r
356 } else {\r
357 //\r
358 // <sectFile fileName= "..."/>\r
359 //\r
360 Element ele = doc.createElement("sectFile");\r
361 ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
362 root.appendChild(ele);\r
363 }\r
364 }\r
365\r
366 /**\r
a29c47e0 367 Get the corresponding section file suffix.\r
878ddf1f 368 \r
369 @param type Section type\r
370 @return Corresponding section file extension\r
371 **/\r
372 private String getSectionExt(String type) {\r
373 for (int i = 0; i < sectionExt.length; i++) {\r
374 if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
375 return sectionExt[i][1];\r
376 }\r
377 }\r
378 return ".sec";\r
379 }\r
380\r
381 /**\r
382 Return the ANT script to call GenFfs Tool.\r
383 \r
384 @return ANT script to call GenFfs Tool\r
385 **/\r
386 public Element getFfsNode() {\r
387 return ffsNode;\r
388 }\r
389}\r