2 File is FfsProcess class which is used to get the corresponding FFS layout
3 information for driver module.
5 Copyright (c) 2006, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 package org
.tianocore
.build
;
17 import java
.util
.Vector
;
19 import javax
.xml
.namespace
.QName
;
21 import org
.apache
.tools
.ant
.BuildException
;
22 import org
.apache
.tools
.ant
.Project
;
23 import org
.apache
.xmlbeans
.XmlCursor
;
24 import org
.tianocore
.BuildOptionsDocument
;
25 import org
.tianocore
.build
.global
.GlobalData
;
26 import org
.tianocore
.build
.global
.SurfaceAreaQuery
;
27 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
28 import org
.tianocore
.common
.definitions
.EdkDefinitions
;
29 import org
.tianocore
.common
.logger
.EdkLog
;
30 import org
.w3c
.dom
.Document
;
31 import org
.w3c
.dom
.Element
;
34 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>
36 <p>The FFS Layout is like following: </p>
39 <Ffs type="APPLICATION">
40 <Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" />
41 <Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" />
42 <Sections EncapsulationType="Compress">
43 <Sections EncapsulationType="Guid-Defined">
44 <Section SectionType="EFI_SECTION_PE32" />
45 <Section SectionType="EFI_SECTION_USER_INTERFACE" />
46 <Section SectionType="EFI_SECTION_VERSION" />
54 public class FfsProcess
{
56 private BuildOptionsDocument
.BuildOptions
.Ffs ffsXmlObject
;
59 /// ANT script to call GenFfs
61 private Element ffsNode
= null;
66 private String basename
;
69 /// Sections type: normal
71 private static int MODE_NONE
= 0;
74 /// Sections type: compress
76 private static int MODE_COMPRESS
= 1;
79 /// Sections type: guid-define
81 private static int MODE_GUID_DEFINED
= 2;
84 /// mapping from section type to section output file extension
86 public static final String
[][] sectionExt
= EdkDefinitions
.SectionTypeExtensions
;
89 search in the type, if componentType is listed in type, return true;
90 otherwise return false.
92 @param type a list supported component type separated by comma
93 @param componentType current module component type
94 @return whether componentType is one of type
96 private boolean isMatch(String type
, String componentType
) {
97 String
[] items
= type
.split("[ \t]*,[ \t]*");
98 for (int i
= 0; i
< items
.length
; i
++) {
99 if (items
[i
].equalsIgnoreCase(componentType
)) {
107 Find the corresponding FFS layout in <code>FPD</code>.
109 @param buildType Current module's component type
110 @param project Ant project
111 @return whether find the corresponding FFS layout
112 @throws BuildException
113 If can't find FFS Layout in FPD.
115 public boolean initSections(String buildType
, Project project
, FpdModuleIdentification fpdModuleId
) throws BuildException
{
117 // Try to find Ffs layout from FPD file
119 SurfaceAreaQuery saq
= new SurfaceAreaQuery(GlobalData
.getFpdBuildOptionsMap());
120 BuildOptionsDocument
.BuildOptions
.Ffs
[] ffsArray
= saq
.getFpdFfs();
121 for (int i
= 0; i
< ffsArray
.length
; i
++) {
122 if (isMatch(ffsArray
[i
].getFfsKey(), buildType
)) {
123 ffsXmlObject
= ffsArray
[i
];
129 // If FfsFormatKey is not null, report exception and fail build
130 // Otherwise report warning message
132 if (buildType
== null) {
133 EdkLog
.log(EdkLog
.EDK_WARNING
, "Warning: this module doesn't specify a FfsFormatKey. ");
135 throw new BuildException("Can't find the FfsFormatKey [" + buildType
+ "] attribute in the FPD file!");
142 Recursive parse the FFS layout. Find out all section type here used.
144 @param document BaseName_build.xml Xml document
145 @param basename Module's base name
146 @param guid Module's GUID
147 @param targetFilename Module's final file name (GUID-BaseName.APP)
148 @return List of section type
150 public String
[] getGenSectionElements(Document document
, String basename
, String guid
, String targetFilename
) {
151 this.basename
= basename
;
152 if (ffsXmlObject
== null) {
153 return new String
[0];
155 Vector
<String
> sectionList
= new Vector
<String
>();
156 XmlCursor cursor
= null;
158 cursor
= ffsXmlObject
.newCursor();
160 int mode
= MODE_NONE
;
161 Element genffsfileEle
= document
.createElement("genffsfile");
162 genffsfileEle
.setAttribute("outputDir", "${BIN_DIR}");
163 genffsfileEle
.setAttribute("moduleType", "${MODULE_TYPE}");
164 genffsfileEle
.setAttribute("BaseName", basename
);
165 genffsfileEle
.setAttribute("fileGuid", guid
);
167 if (cursor
.toFirstChild()) {
169 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Attribute")) {
170 String name
= cursor
.getAttributeText(new QName("Name"));
171 String value
= cursor
.getAttributeText(new QName("Value"));
172 genffsfileEle
.setAttribute(changeAttributeName(name
), value
);
173 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
175 dealSection(mode
, document
, genffsfileEle
, cursor
, sectionList
);
177 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
179 dealSections(mode
, document
, genffsfileEle
, cursor
, sectionList
);
182 } while (cursor
.toNextSibling());
187 Element outofdateEle
= document
.createElement("OnDependency");
188 Element sourceEle
= document
.createElement("sourcefiles");
189 String
[] result
= new String
[sectionList
.size()];
190 for (int i
= 0; i
< sectionList
.size(); i
++) {
191 result
[i
] = (String
) sectionList
.get(i
);
192 Element pathEle
= document
.createElement("file");
193 pathEle
.setAttribute("name", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
194 + getSectionExt(result
[i
]));
195 sourceEle
.appendChild(pathEle
);
197 outofdateEle
.appendChild(sourceEle
);
198 Element targetEle
= document
.createElement("targetfiles");
199 Element fileEle
= document
.createElement("file");
200 fileEle
.setAttribute("name", "${BIN_DIR}" + File
.separatorChar
+ targetFilename
);
201 targetEle
.appendChild(fileEle
);
202 outofdateEle
.appendChild(targetEle
);
203 Element sequentialEle
= document
.createElement("sequential");
204 sequentialEle
.appendChild(genffsfileEle
);
205 outofdateEle
.appendChild(sequentialEle
);
206 ffsNode
= outofdateEle
;
211 Change the attribute name. For example:
214 Before change: FFS_ATTRIB_CHECKSUM
215 After change: ffsATTRIBCHECKSUM
218 @param name Original attribute name
219 @return Changed attribute name
221 private String
changeAttributeName(String name
) {
222 String
[] strs
= name
.split("_");
223 String str
= strs
[0].toLowerCase();
224 for (int j
= 1; j
< strs
.length
; j
++) {
231 Recursively deal with Sections. If sections does not specify a type, then omit it.
233 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
234 @param doc Xml Document
235 @param root Root Node
236 @param cursor Current FFS layout cursor
237 @param list List of section type here used
239 private void dealSections(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
240 String type
= cursor
.getAttributeText(new QName("EncapsulationType"));
241 String toolName
= cursor
.getAttributeText(new QName("ToolName"));
242 String sectType
= cursor
.getAttributeText(new QName("SectionType"));
243 if (type
== null && sectType
== null) {
244 if (cursor
.toFirstChild()) {
246 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
248 dealSection(mode
, doc
, root
, cursor
, list
);
250 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
252 dealSections(mode
, doc
, root
, cursor
, list
);
255 } while (cursor
.toNextSibling());
260 Element toolEle
= null;
261 if (type
.equalsIgnoreCase("COMPRESS") && (toolName
== null || toolName
.equalsIgnoreCase(""))) {
262 mode
= MODE_COMPRESS
;
264 // <gensection sectiontype="EFI_SECTION_COMPRESSION">
266 ele
= doc
.createElement("gensection");
267 ele
.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");
270 mode
= MODE_GUID_DEFINED
;
272 // <gensection sectiontype="EFI_SECTION_GUID_DEFINED">
274 ele
= doc
.createElement("gensection");
276 if (type
.equalsIgnoreCase("COMPRESS")) {
277 ele
.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");
279 ele
.setAttribute("sectiontype", "EFI_SECTION_GUID_DEFINED");
283 ele
.setAttribute("sectiontype", sectType
);
286 // <tool toolName="${OEMTOOLPATH}\toolname"
287 // outputPath = "${DEST_DIR_OUTPUT}">
289 toolEle
= doc
.createElement("tool");
290 if (toolName
== null || toolName
.equalsIgnoreCase("")) {
291 toolEle
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
292 + File
.separatorChar
+ "GenCRC32Section");
294 File toolExe
= new File(toolName
);
296 // If <Tool> element exist, add sub element under <tool> .
298 if (toolExe
.isAbsolute()) {
299 toolEle
.setAttribute("toolName", toolName
);
301 toolEle
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
302 + File
.separatorChar
+ toolName
);
306 toolEle
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
307 ele
.appendChild(toolEle
);
309 if (cursor
.toFirstChild()) {
311 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
313 if (toolEle
== null) {
314 dealSection(mode
, doc
, ele
, cursor
, list
);
316 dealSection(mode
, doc
, toolEle
, cursor
, list
);
320 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
322 if (toolEle
== null) {
323 dealSections(mode
, doc
, ele
, cursor
, list
);
325 dealSections(mode
, doc
, toolEle
, cursor
, list
);
330 } while (cursor
.toNextSibling());
332 root
.appendChild(ele
);
336 Recursively deal with section.
338 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
339 @param doc Xml Document
340 @param root Root Node
341 @param cursor Current FFS layout cursor
342 @param list List of section type here used
344 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
345 String type
= cursor
.getAttributeText(new QName("SectionType"));
348 // Judge if file is specified? Yes, just use the file, else call Build Macro
349 // If fileName is null, means without FileNames specify in FPD file
351 String fileName
= null;
353 if (cursor
.toFirstChild()) {
355 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Filenames")) {
357 if (cursor
.toFirstChild()) {
359 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Filename")) {
360 fileName
= cursor
.getTextValue();
362 } while (cursor
.toNextSibling());
366 } while (cursor
.toNextSibling());
371 if (fileName
== null) {
372 list
.addElement(type
);
374 if (mode
== MODE_GUID_DEFINED
) {
376 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
378 Element ele
= doc
.createElement("input");
379 if (fileName
== null) {
380 ele
.setAttribute("file", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
382 ele
.setAttribute("file", "${PLATFORM_DIR}" + File
.separatorChar
+ fileName
);
384 root
.appendChild(ele
);
387 // <sectFile fileName= "..."/>
389 Element ele
= doc
.createElement("sectFile");
390 if (fileName
== null) {
391 ele
.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
393 ele
.setAttribute("fileName", "${PLATFORM_DIR}" + File
.separatorChar
+ fileName
);
395 root
.appendChild(ele
);
400 Get the corresponding section file suffix.
402 @param type Section type
403 @return Corresponding section file extension
405 private String
getSectionExt(String type
) {
406 for (int i
= 0; i
< sectionExt
.length
; i
++) {
407 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
408 return sectionExt
[i
][1];
415 Return the ANT script to call GenFfs Tool.
417 @return ANT script to call GenFfs Tool
419 public Element
getFfsNode() {