]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java
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
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.apache.xmlbeans.XmlObject;\r
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
29import org.w3c.dom.Document;\r
30import org.w3c.dom.Element;\r
31import org.w3c.dom.Node;\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>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
61 \r
62 private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;\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, FpdModuleIdentification fpdModuleId) throws BuildException {\r
135 //\r
136 // Firstly, try to find in ModuleSA\r
137 //\r
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
159 //\r
160 // If FfsFormatKey is not null, report exception and fail build\r
161 // Otherwise report warning message\r
162 //\r
163 if (buildType == null) {\r
164 System.out.println("Warning: this module doesn't specify a FfsFormatKey. ");\r
165 }\r
166 else {\r
167 throw new BuildException("Can't find FfsFormatKey [" + buildType + "] in FPD file. "); \r
168 }\r
169\r
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
188 if (ffs == null && ffsXmlObject == null) {\r
189 return new String[0];\r
190 }\r
191 Vector<String> sectionList = new Vector<String>();\r
192 XmlCursor cursor = null;\r
193 try {\r
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
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
206 root.setAttribute("moduleType", "${MODULE_TYPE}");\r
207 root.setAttribute("BaseName", basename);\r
208 root.setAttribute("fileGuid", guid);\r
209 if (ffsXmlObject == null) {\r
210 cursor.toFirstChild();\r
211 }\r
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
245 fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);\r
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
317 ele.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
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
367 Get the corresponding section file suffix.\r
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