]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java
add ContextTool to workspace/Tools
[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
118 SurfaceAreaQuery.push(GlobalData.getFpdBuildOptions());\r
119 BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = SurfaceAreaQuery.getFpdFfs();\r
120 SurfaceAreaQuery.pop();\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
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
133 System.out.println("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
157 try {\r
82516887 158 cursor = ffsXmlObject.newCursor();\r
878ddf1f 159 } catch (Exception e) {\r
160 return null;\r
161 }\r
162 int mode = MODE_NONE;\r
82516887 163 Element genffsfileEle = document.createElement("genffsfile");\r
164 genffsfileEle.setAttribute("outputDir", "${BIN_DIR}");\r
165 genffsfileEle.setAttribute("moduleType", "${MODULE_TYPE}");\r
166 genffsfileEle.setAttribute("BaseName", basename);\r
167 genffsfileEle.setAttribute("fileGuid", guid);\r
168\r
878ddf1f 169 if (cursor.toFirstChild()) {\r
170 do {\r
171 if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) {\r
172 String name = cursor.getAttributeText(new QName("Name"));\r
173 String value = cursor.getAttributeText(new QName("Value"));\r
82516887 174 genffsfileEle.setAttribute(changeAttributeName(name), value);\r
878ddf1f 175 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
176 cursor.push();\r
82516887 177 dealSection(mode, document, genffsfileEle, cursor, sectionList);\r
878ddf1f 178 cursor.pop();\r
179 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
180 cursor.push();\r
82516887 181 dealSections(mode, document, genffsfileEle, cursor, sectionList);\r
878ddf1f 182 cursor.pop();\r
183 }\r
184 } while (cursor.toNextSibling());\r
185 }\r
186 //\r
187 // Check dependency \r
188 //\r
189 Element outofdateEle = document.createElement("OnDependency");\r
190 Element sourceEle = document.createElement("sourcefiles");\r
191 String[] result = new String[sectionList.size()];\r
192 for (int i = 0; i < sectionList.size(); i++) {\r
193 result[i] = (String) sectionList.get(i);\r
194 Element pathEle = document.createElement("file");\r
195 pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename\r
196 + getSectionExt(result[i]));\r
197 sourceEle.appendChild(pathEle);\r
198 }\r
199 outofdateEle.appendChild(sourceEle);\r
200 Element targetEle = document.createElement("targetfiles");\r
201 Element fileEle = document.createElement("file");\r
52cbbdbc 202 fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);\r
878ddf1f 203 targetEle.appendChild(fileEle);\r
204 outofdateEle.appendChild(targetEle);\r
205 Element sequentialEle = document.createElement("sequential");\r
82516887 206 sequentialEle.appendChild(genffsfileEle);\r
878ddf1f 207 outofdateEle.appendChild(sequentialEle);\r
208 ffsNode = outofdateEle;\r
209 return result;\r
210 }\r
211\r
212 /**\r
213 Change the attribute name. For example: \r
214 \r
215 <pre>\r
216 Before change: FFS_ATTRIB_CHECKSUM \r
217 After change: ffsATTRIBCHECKSUM\r
218 </pre>\r
219 \r
220 @param name Original attribute name\r
221 @return Changed attribute name\r
222 **/\r
223 private String changeAttributeName(String name) {\r
224 String[] strs = name.split("_");\r
225 String str = strs[0].toLowerCase();\r
226 for (int j = 1; j < strs.length; j++) {\r
227 str += strs[j];\r
228 }\r
229 return str;\r
230 }\r
231\r
232 /**\r
233 Recursively deal with Sections. If sections does not specify a type, then omit it.\r
234 \r
235 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
236 @param doc Xml Document\r
237 @param root Root Node\r
238 @param cursor Current FFS layout cursor\r
239 @param list List of section type here used\r
240 **/\r
241 private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
242 String type = cursor.getAttributeText(new QName("EncapsulationType"));\r
243 if (type == 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 if (type.equalsIgnoreCase("COMPRESS")) {\r
261 mode = MODE_COMPRESS;\r
262 //\r
263 // <compress compressName = "dummy">\r
264 //\r
265 ele = doc.createElement("compress");\r
266 ele.setAttribute("compressName", "dummy");\r
267 } else {\r
268 mode = MODE_GUID_DEFINED;\r
269 //\r
270 // <tool toolName="${OEMTOOLPATH}\toolname"\r
271 // outputPath = "${DEST_DIR_OUTPUT}">\r
272 //\r
273 ele = doc.createElement("tool");\r
a33f3dd1 274 ele.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
878ddf1f 275 + File.separatorChar + "GenCRC32Section");\r
276 ele.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");\r
277 }\r
278 if (cursor.toFirstChild()) {\r
279 do {\r
280 if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
281 cursor.push();\r
282 dealSection(mode, doc, ele, cursor, list);\r
283 cursor.pop();\r
284 } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
285 cursor.push();\r
286 dealSections(mode, doc, ele, cursor, list);\r
287 cursor.pop();\r
288 }\r
289 } while (cursor.toNextSibling());\r
290 }\r
291 root.appendChild(ele);\r
292 }\r
293 \r
294 /**\r
295 Recursively deal with section.\r
296 \r
297 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
298 @param doc Xml Document\r
299 @param root Root Node\r
300 @param cursor Current FFS layout cursor\r
301 @param list List of section type here used\r
302 **/\r
303 private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
304 String type = cursor.getAttributeText(new QName("SectionType"));\r
8a9783c1 305 \r
306 //\r
307 // Judge if file is specified? Yes, just use the file, else call Build Macro\r
308 // If fileName is null, means without FileNames specify in FPD file\r
309 //\r
310 String fileName = null;\r
311 cursor.push();\r
312 if (cursor.toFirstChild()) {\r
313 do {\r
314 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filenames")) {\r
315 cursor.push();\r
316 if (cursor.toFirstChild()) {\r
317 do {\r
318 if (cursor.getName().getLocalPart().equalsIgnoreCase("Filename")) {\r
319 fileName = cursor.getTextValue();\r
320 }\r
321 } while (cursor.toNextSibling());\r
322 }\r
323 cursor.pop();\r
324 }\r
325 } while (cursor.toNextSibling());\r
326 }\r
327\r
328 cursor.pop();\r
329 \r
330 if (fileName == null) {\r
331 list.addElement(type);\r
332 }\r
878ddf1f 333 if (mode == MODE_GUID_DEFINED) {\r
334 //\r
335 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>\r
336 //\r
337 Element ele = doc.createElement("input");\r
8a9783c1 338 if (fileName == null) {\r
339 ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
340 } else {\r
341 ele.setAttribute("file", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
342 }\r
878ddf1f 343 root.appendChild(ele);\r
344 } else {\r
345 //\r
346 // <sectFile fileName= "..."/>\r
347 //\r
348 Element ele = doc.createElement("sectFile");\r
8a9783c1 349 if (fileName == null) {\r
350 ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
351 } else {\r
352 ele.setAttribute("fileName", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
353 }\r
878ddf1f 354 root.appendChild(ele);\r
355 }\r
356 }\r
357\r
358 /**\r
a29c47e0 359 Get the corresponding section file suffix.\r
878ddf1f 360 \r
361 @param type Section type\r
362 @return Corresponding section file extension\r
363 **/\r
364 private String getSectionExt(String type) {\r
365 for (int i = 0; i < sectionExt.length; i++) {\r
366 if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
367 return sectionExt[i][1];\r
368 }\r
369 }\r
370 return ".sec";\r
371 }\r
372\r
373 /**\r
374 Return the ANT script to call GenFfs Tool.\r
375 \r
376 @return ANT script to call GenFfs Tool\r
377 **/\r
378 public Element getFfsNode() {\r
379 return ffsNode;\r
380 }\r
381}\r