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