]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/Java/Source/GenBuild/org/tianocore/build/FfsProcess.java
1. Finish Enhancement EDKT345: Support deleting multiple rows together when remove...
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / FfsProcess.java
... / ...
CommitLineData
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.util.Vector;\r
18\r
19import javax.xml.namespace.QName;\r
20\r
21import org.apache.tools.ant.BuildException;\r
22import org.apache.tools.ant.Project;\r
23import org.apache.xmlbeans.XmlCursor;\r
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
28import org.tianocore.common.definitions.EdkDefinitions;\r
29import org.tianocore.common.logger.EdkLog;\r
30import org.w3c.dom.Document;\r
31import org.w3c.dom.Element;\r
32\r
33/** \r
34 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>\r
35 \r
36 <p>The FFS Layout is like following: </p>\r
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
56 private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;\r
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
86 public static final String[][] sectionExt = EdkDefinitions.SectionTypeExtensions;\r
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
107 Find the corresponding FFS layout in <code>FPD</code>. \r
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
113 If can't find FFS Layout in FPD.\r
114 **/\r
115 public boolean initSections(String buildType, Project project, FpdModuleIdentification fpdModuleId) throws BuildException {\r
116 //\r
117 // Try to find Ffs layout from FPD file\r
118 //\r
119 SurfaceAreaQuery saq = new SurfaceAreaQuery(GlobalData.getFpdBuildOptionsMap());\r
120 BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = saq.getFpdFfs();\r
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
128 //\r
129 // If FfsFormatKey is not null, report exception and fail build\r
130 // Otherwise report warning message\r
131 //\r
132 if (buildType == null) {\r
133 EdkLog.log(EdkLog.EDK_WARNING, "Warning: this module doesn't specify a FfsFormatKey. ");\r
134 } else {\r
135 throw new BuildException("Can't find the FfsFormatKey [" + buildType + "] attribute in the FPD file!"); \r
136 }\r
137\r
138 return false;\r
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
152 if (ffsXmlObject == null) {\r
153 return new String[0];\r
154 }\r
155 Vector<String> sectionList = new Vector<String>();\r
156 XmlCursor cursor = null;\r
157\r
158 cursor = ffsXmlObject.newCursor();\r
159\r
160 int mode = MODE_NONE;\r
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
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
172 genffsfileEle.setAttribute(changeAttributeName(name), value);\r
173 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
174 cursor.push();\r
175 dealSection(mode, document, genffsfileEle, cursor, sectionList);\r
176 cursor.pop();\r
177 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
178 cursor.push();\r
179 dealSections(mode, document, genffsfileEle, cursor, sectionList);\r
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
200 fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);\r
201 targetEle.appendChild(fileEle);\r
202 outofdateEle.appendChild(targetEle);\r
203 Element sequentialEle = document.createElement("sequential");\r
204 sequentialEle.appendChild(genffsfileEle);\r
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
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
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
260 Element toolEle = null;\r
261 if (type.equalsIgnoreCase("COMPRESS") && (toolName == null || toolName.equalsIgnoreCase(""))) {\r
262 mode = MODE_COMPRESS;\r
263 //\r
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
269 } else {\r
270 mode = MODE_GUID_DEFINED;\r
271 //\r
272 // <gensection sectiontype="EFI_SECTION_GUID_DEFINED">\r
273 // \r
274 ele = doc.createElement("gensection");\r
275 if (type != null) {\r
276 if (type.equalsIgnoreCase("COMPRESS")) {\r
277 ele.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");\r
278 }else {\r
279 ele.setAttribute("sectiontype", "EFI_SECTION_GUID_DEFINED"); \r
280 }\r
281 \r
282 } else {\r
283 ele.setAttribute("sectiontype", sectType);\r
284 }\r
285 //\r
286 // <tool toolName="${OEMTOOLPATH}\toolname"\r
287 // outputPath = "${DEST_DIR_OUTPUT}">\r
288 //\r
289 toolEle = doc.createElement("tool");\r
290 if (toolName == null || toolName.equalsIgnoreCase("")) {\r
291 toolEle.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
292 + File.separatorChar + "GenCRC32Section");\r
293 }else{\r
294 File toolExe = new File(toolName);\r
295 //\r
296 // If <Tool> element exist, add sub element under <tool> . \r
297 // \r
298 if (toolExe.isAbsolute()) {\r
299 toolEle.setAttribute("toolName", toolName);\r
300 } else {\r
301 toolEle.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
302 + File.separatorChar + toolName);\r
303 }\r
304 }\r
305 \r
306 toolEle.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");\r
307 ele.appendChild(toolEle);\r
308 }\r
309 if (cursor.toFirstChild()) {\r
310 do {\r
311 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
312 cursor.push();\r
313 if (toolEle == null) {\r
314 dealSection(mode, doc, ele, cursor, list);\r
315 } else {\r
316 dealSection(mode, doc, toolEle, cursor, list);\r
317 }\r
318 \r
319 cursor.pop();\r
320 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
321 cursor.push();\r
322 if (toolEle == null) {\r
323 dealSections(mode, doc, ele, cursor, list);\r
324 } else {\r
325 dealSections(mode, doc, toolEle, cursor, list);\r
326 }\r
327 \r
328 cursor.pop();\r
329 }\r
330 } while (cursor.toNextSibling());\r
331 }\r
332 root.appendChild(ele);\r
333 }\r
334 \r
335 /**\r
336 Recursively deal with section.\r
337 \r
338 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
339 @param doc Xml Document\r
340 @param root Root Node\r
341 @param cursor Current FFS layout cursor\r
342 @param list List of section type here used\r
343 **/\r
344 private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
345 String type = cursor.getAttributeText(new QName("SectionType"));\r
346 \r
347 //\r
348 // Judge if file is specified? Yes, just use the file, else call Build Macro\r
349 // If fileName is null, means without FileNames specify in FPD file\r
350 //\r
351 String fileName = null;\r
352 cursor.push();\r
353 if (cursor.toFirstChild()) {\r
354 do {\r
355 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filenames")) {\r
356 cursor.push();\r
357 if (cursor.toFirstChild()) {\r
358 do {\r
359 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filename")) {\r
360 fileName = cursor.getTextValue();\r
361 }\r
362 } while (cursor.toNextSibling());\r
363 }\r
364 cursor.pop();\r
365 }\r
366 } while (cursor.toNextSibling());\r
367 }\r
368\r
369 cursor.pop();\r
370 \r
371 if (fileName == null) {\r
372 list.addElement(type);\r
373 }\r
374 if (mode == MODE_GUID_DEFINED) {\r
375 //\r
376 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>\r
377 //\r
378 Element ele = doc.createElement("input");\r
379 if (fileName == null) {\r
380 ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
381 } else {\r
382 ele.setAttribute("file", fileName);\r
383 }\r
384 root.appendChild(ele);\r
385 } else {\r
386 //\r
387 // <sectFile fileName= "..."/>\r
388 //\r
389 Element ele = doc.createElement("sectFile");\r
390 if (fileName == null) {\r
391 ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
392 } else {\r
393 ele.setAttribute("fileName", fileName);\r
394 }\r
395 root.appendChild(ele);\r
396 }\r
397 }\r
398\r
399 /**\r
400 Get the corresponding section file suffix.\r
401 \r
402 @param type Section type\r
403 @return Corresponding section file extension\r
404 **/\r
405 private String getSectionExt(String type) {\r
406 for (int i = 0; i < sectionExt.length; i++) {\r
407 if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
408 return sectionExt[i][1];\r
409 }\r
410 }\r
411 return ".sec";\r
412 }\r
413\r
414 /**\r
415 Return the ANT script to call GenFfs Tool.\r
416 \r
417 @return ANT script to call GenFfs Tool\r
418 **/\r
419 public Element getFfsNode() {\r
420 return ffsNode;\r
421 }\r
422}\r