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