]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java
Support calling customized compression tool in FrameworkTask.
[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
a29c47e0 24import org.tianocore.BuildOptionsDocument;\r
25import org.tianocore.build.global.GlobalData;\r
26import org.tianocore.build.global.SurfaceAreaQuery;\r
27import org.tianocore.build.id.FpdModuleIdentification;\r
4a6a5026 28import org.tianocore.common.definitions.EdkDefinitions;\r
91f7d582 29import org.tianocore.common.logger.EdkLog;\r
878ddf1f 30import org.w3c.dom.Document;\r
31import org.w3c.dom.Element;\r
878ddf1f 32\r
33/** \r
34 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>\r
35 \r
4b5f5549 36 <p>The FFS Layout is like following: </p>\r
878ddf1f 37 \r
38 <pre>\r
39 &lt;Ffs type="APPLICATION"&gt;\r
40 &lt;Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" /&gt;\r
41 &lt;Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" /&gt;\r
42 &lt;Sections EncapsulationType="Compress"&gt;\r
43 &lt;Sections EncapsulationType="Guid-Defined"&gt;\r
44 &lt;Section SectionType="EFI_SECTION_PE32" /&gt; \r
45 &lt;Section SectionType="EFI_SECTION_USER_INTERFACE" /&gt;\r
46 &lt;Section SectionType="EFI_SECTION_VERSION" /&gt; \r
47 &lt;/Sections&gt;\r
48 &lt;/Sections&gt;\r
49 &lt;/Ffs&gt;\r
50 </pre>\r
51 \r
52 @since GenBuild 1.0\r
53**/\r
54public class FfsProcess {\r
55\r
a29c47e0 56 private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;\r
878ddf1f 57\r
58 ///\r
59 /// ANT script to call GenFfs\r
60 ///\r
61 private Element ffsNode = null;\r
62\r
63 ///\r
64 /// Module base name\r
65 ///\r
66 private String basename;\r
67\r
68 ///\r
69 /// Sections type: normal\r
70 ///\r
71 private static int MODE_NONE = 0;\r
72\r
73 ///\r
74 /// Sections type: compress\r
75 ///\r
76 private static int MODE_COMPRESS = 1;\r
77\r
78 ///\r
79 /// Sections type: guid-define\r
80 ///\r
81 private static int MODE_GUID_DEFINED = 2;\r
82\r
83 ///\r
84 /// mapping from section type to section output file extension\r
85 ///\r
4a6a5026 86 public static final String[][] sectionExt = EdkDefinitions.SectionTypeExtensions;\r
878ddf1f 87\r
88 /**\r
89 search in the type, if componentType is listed in type, return true; \r
90 otherwise return false.\r
91 \r
92 @param type a list supported component type separated by comma\r
93 @param componentType current module component type\r
94 @return whether componentType is one of type \r
95 **/\r
96 private boolean isMatch(String type, String componentType) {\r
97 String[] items = type.split("[ \t]*,[ \t]*");\r
98 for (int i = 0; i < items.length; i++) {\r
99 if (items[i].equalsIgnoreCase(componentType)) {\r
100 return true;\r
101 }\r
102 }\r
103 return false;\r
104 }\r
105\r
106 /**\r
4b5f5549 107 Find the corresponding FFS layout in <code>FPD</code>. \r
878ddf1f 108 \r
109 @param buildType Current module's component type\r
110 @param project Ant project\r
111 @return whether find the corresponding FFS layout\r
112 @throws BuildException\r
4b5f5549 113 If can't find FFS Layout in FPD.\r
878ddf1f 114 **/\r
a29c47e0 115 public boolean initSections(String buildType, Project project, FpdModuleIdentification fpdModuleId) throws BuildException {\r
878ddf1f 116 //\r
82516887 117 // Try to find Ffs layout from FPD file\r
a29c47e0 118 //\r
19bf6b15 119 SurfaceAreaQuery saq = new SurfaceAreaQuery(GlobalData.getFpdBuildOptionsMap());\r
83fba802 120 BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = saq.getFpdFfs();\r
a29c47e0 121 for (int i = 0; i < ffsArray.length; i++) {\r
122 if (isMatch(ffsArray[i].getFfsKey(), buildType)) {\r
123 ffsXmlObject = ffsArray[i];\r
124 return true;\r
125 }\r
126 }\r
127 \r
878ddf1f 128 //\r
e64c74dd 129 // If FfsFormatKey is not null, report exception and fail build\r
130 // Otherwise report warning message\r
878ddf1f 131 //\r
e64c74dd 132 if (buildType == null) {\r
91f7d582 133 EdkLog.log(EdkLog.EDK_WARNING, "Warning: this module doesn't specify a FfsFormatKey. ");\r
82516887 134 } else {\r
391dbbb1 135 throw new BuildException("Can't find the FfsFormatKey [" + buildType + "] attribute in the FPD file!"); \r
878ddf1f 136 }\r
e64c74dd 137\r
82516887 138 return false;\r
878ddf1f 139 }\r
140 \r
141 /**\r
142 Recursive parse the FFS layout. Find out all section type here used. \r
143 \r
144 @param document BaseName_build.xml Xml document\r
145 @param basename Module's base name\r
146 @param guid Module's GUID\r
147 @param targetFilename Module's final file name (GUID-BaseName.APP)\r
148 @return List of section type\r
149 **/\r
150 public String[] getGenSectionElements(Document document, String basename, String guid, String targetFilename) {\r
151 this.basename = basename;\r
82516887 152 if (ffsXmlObject == null) {\r
878ddf1f 153 return new String[0];\r
154 }\r
155 Vector<String> sectionList = new Vector<String>();\r
156 XmlCursor cursor = null;\r
2eb7d78d 157\r
158 cursor = ffsXmlObject.newCursor();\r
159\r
878ddf1f 160 int mode = MODE_NONE;\r
82516887 161 Element genffsfileEle = document.createElement("genffsfile");\r
162 genffsfileEle.setAttribute("outputDir", "${BIN_DIR}");\r
163 genffsfileEle.setAttribute("moduleType", "${MODULE_TYPE}");\r
164 genffsfileEle.setAttribute("BaseName", basename);\r
165 genffsfileEle.setAttribute("fileGuid", guid);\r
166\r
878ddf1f 167 if (cursor.toFirstChild()) {\r
168 do {\r
169 if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) {\r
170 String name = cursor.getAttributeText(new QName("Name"));\r
171 String value = cursor.getAttributeText(new QName("Value"));\r
82516887 172 genffsfileEle.setAttribute(changeAttributeName(name), value);\r
878ddf1f 173 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
174 cursor.push();\r
82516887 175 dealSection(mode, document, genffsfileEle, cursor, sectionList);\r
878ddf1f 176 cursor.pop();\r
177 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
178 cursor.push();\r
82516887 179 dealSections(mode, document, genffsfileEle, cursor, sectionList);\r
878ddf1f 180 cursor.pop();\r
181 }\r
182 } while (cursor.toNextSibling());\r
183 }\r
184 //\r
185 // Check dependency \r
186 //\r
187 Element outofdateEle = document.createElement("OnDependency");\r
188 Element sourceEle = document.createElement("sourcefiles");\r
189 String[] result = new String[sectionList.size()];\r
190 for (int i = 0; i < sectionList.size(); i++) {\r
191 result[i] = (String) sectionList.get(i);\r
192 Element pathEle = document.createElement("file");\r
193 pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename\r
194 + getSectionExt(result[i]));\r
195 sourceEle.appendChild(pathEle);\r
196 }\r
197 outofdateEle.appendChild(sourceEle);\r
198 Element targetEle = document.createElement("targetfiles");\r
199 Element fileEle = document.createElement("file");\r
52cbbdbc 200 fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);\r
878ddf1f 201 targetEle.appendChild(fileEle);\r
202 outofdateEle.appendChild(targetEle);\r
203 Element sequentialEle = document.createElement("sequential");\r
82516887 204 sequentialEle.appendChild(genffsfileEle);\r
878ddf1f 205 outofdateEle.appendChild(sequentialEle);\r
206 ffsNode = outofdateEle;\r
207 return result;\r
208 }\r
209\r
210 /**\r
211 Change the attribute name. For example: \r
212 \r
213 <pre>\r
214 Before change: FFS_ATTRIB_CHECKSUM \r
215 After change: ffsATTRIBCHECKSUM\r
216 </pre>\r
217 \r
218 @param name Original attribute name\r
219 @return Changed attribute name\r
220 **/\r
221 private String changeAttributeName(String name) {\r
222 String[] strs = name.split("_");\r
223 String str = strs[0].toLowerCase();\r
224 for (int j = 1; j < strs.length; j++) {\r
225 str += strs[j];\r
226 }\r
227 return str;\r
228 }\r
229\r
230 /**\r
231 Recursively deal with Sections. If sections does not specify a type, then omit it.\r
232 \r
233 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
234 @param doc Xml Document\r
235 @param root Root Node\r
236 @param cursor Current FFS layout cursor\r
237 @param list List of section type here used\r
238 **/\r
239 private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
240 String type = cursor.getAttributeText(new QName("EncapsulationType"));\r
a1ffb10f 241 String toolName = cursor.getAttributeText(new QName("ToolName"));\r
242 String sectType = cursor.getAttributeText(new QName("SectionType"));\r
243 if (type == null && sectType == null) {\r
878ddf1f 244 if (cursor.toFirstChild()) {\r
245 do {\r
246 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
247 cursor.push();\r
248 dealSection(mode, doc, root, cursor, list);\r
249 cursor.pop();\r
250 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
251 cursor.push();\r
252 dealSections(mode, doc, root, cursor, list);\r
253 cursor.pop();\r
254 }\r
255 } while (cursor.toNextSibling());\r
256 }\r
257 return;\r
258 }\r
259 Element ele;\r
a1ffb10f 260 Element toolEle = null;\r
261 if (type.equalsIgnoreCase("COMPRESS") && (toolName == null || toolName.equalsIgnoreCase(""))) {\r
878ddf1f 262 mode = MODE_COMPRESS;\r
263 //\r
a1ffb10f 264 // <gensection sectiontype="EFI_SECTION_COMPRESSION"> \r
265 // \r
266 ele = doc.createElement("gensection");\r
267 ele.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");\r
268 \r
878ddf1f 269 } else {\r
270 mode = MODE_GUID_DEFINED;\r
271 //\r
a1ffb10f 272 // <gensection sectiontype="EFI_SECTION_GUID_DEFINED">\r
273 // \r
274 ele = doc.createElement("gensection");\r
275 if (type != null) {\r
276 ele.setAttribute("sectiontype", "EFI_SECTION_GUID_DEFINED");\r
277 } else {\r
278 ele.setAttribute("sectiontype", sectType);\r
279 }\r
280 //\r
878ddf1f 281 // <tool toolName="${OEMTOOLPATH}\toolname"\r
282 // outputPath = "${DEST_DIR_OUTPUT}">\r
283 //\r
a1ffb10f 284 toolEle = doc.createElement("tool");\r
285 if (toolName == null || toolName.equalsIgnoreCase("")) {\r
286 toolEle.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
878ddf1f 287 + File.separatorChar + "GenCRC32Section");\r
a1ffb10f 288 }else{\r
289 File toolExe = new File(toolName);\r
290 //\r
291 // If <Tool> element exist, add sub element under <tool> . \r
292 // \r
293 if (toolExe.isAbsolute()) {\r
294 toolEle.setAttribute("toolName", toolName);\r
295 } else {\r
296 toolEle.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
297 + File.separatorChar + toolName);\r
298 }\r
299 }\r
300 \r
301 toolEle.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");\r
302 ele.appendChild(toolEle);\r
878ddf1f 303 }\r
304 if (cursor.toFirstChild()) {\r
305 do {\r
306 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
307 cursor.push();\r
a1ffb10f 308 if (toolEle == null) {\r
309 dealSection(mode, doc, ele, cursor, list);\r
310 } else {\r
311 dealSection(mode, doc, toolEle, cursor, list);\r
312 }\r
313 \r
878ddf1f 314 cursor.pop();\r
315 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
316 cursor.push();\r
a1ffb10f 317 if (toolEle == null) {\r
318 dealSections(mode, doc, ele, cursor, list);\r
319 } else {\r
320 dealSections(mode, doc, toolEle, cursor, list);\r
321 }\r
322 \r
878ddf1f 323 cursor.pop();\r
324 }\r
325 } while (cursor.toNextSibling());\r
326 }\r
327 root.appendChild(ele);\r
328 }\r
329 \r
330 /**\r
331 Recursively deal with section.\r
332 \r
333 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
334 @param doc Xml Document\r
335 @param root Root Node\r
336 @param cursor Current FFS layout cursor\r
337 @param list List of section type here used\r
338 **/\r
339 private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
340 String type = cursor.getAttributeText(new QName("SectionType"));\r
8a9783c1 341 \r
342 //\r
343 // Judge if file is specified? Yes, just use the file, else call Build Macro\r
344 // If fileName is null, means without FileNames specify in FPD file\r
345 //\r
346 String fileName = null;\r
347 cursor.push();\r
348 if (cursor.toFirstChild()) {\r
349 do {\r
350 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filenames")) {\r
351 cursor.push();\r
352 if (cursor.toFirstChild()) {\r
353 do {\r
354 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filename")) {\r
355 fileName = cursor.getTextValue();\r
356 }\r
357 } while (cursor.toNextSibling());\r
358 }\r
359 cursor.pop();\r
360 }\r
361 } while (cursor.toNextSibling());\r
362 }\r
363\r
364 cursor.pop();\r
365 \r
366 if (fileName == null) {\r
367 list.addElement(type);\r
368 }\r
878ddf1f 369 if (mode == MODE_GUID_DEFINED) {\r
370 //\r
371 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>\r
372 //\r
373 Element ele = doc.createElement("input");\r
8a9783c1 374 if (fileName == null) {\r
375 ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
376 } else {\r
377 ele.setAttribute("file", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
378 }\r
878ddf1f 379 root.appendChild(ele);\r
380 } else {\r
381 //\r
382 // <sectFile fileName= "..."/>\r
383 //\r
384 Element ele = doc.createElement("sectFile");\r
8a9783c1 385 if (fileName == null) {\r
386 ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
387 } else {\r
388 ele.setAttribute("fileName", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
389 }\r
878ddf1f 390 root.appendChild(ele);\r
391 }\r
392 }\r
393\r
394 /**\r
a29c47e0 395 Get the corresponding section file suffix.\r
878ddf1f 396 \r
397 @param type Section type\r
398 @return Corresponding section file extension\r
399 **/\r
400 private String getSectionExt(String type) {\r
401 for (int i = 0; i < sectionExt.length; i++) {\r
402 if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
403 return sectionExt[i][1];\r
404 }\r
405 }\r
406 return ".sec";\r
407 }\r
408\r
409 /**\r
410 Return the ANT script to call GenFfs Tool.\r
411 \r
412 @return ANT script to call GenFfs Tool\r
413 **/\r
414 public Element getFfsNode() {\r
415 return ffsNode;\r
416 }\r
417}\r