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 Vector
<String
> sections
= new Vector
<String
>();
190 for (int i
= 0; i
< sectionList
.size(); i
++) {
191 String section
= (String
) sectionList
.get(i
);
192 if (isSectionType(section
)) {
193 sections
.addElement(section
);
195 Element pathEle
= document
.createElement("file");
196 pathEle
.setAttribute("name", getSectionFile(basename
, section
));
197 sourceEle
.appendChild(pathEle
);
199 String
[] result
= sections
.toArray(new String
[sections
.size()]);
201 outofdateEle
.appendChild(sourceEle
);
202 Element targetEle
= document
.createElement("targetfiles");
203 Element fileEle
= document
.createElement("file");
204 fileEle
.setAttribute("name", "${BIN_DIR}" + File
.separatorChar
+ targetFilename
);
205 targetEle
.appendChild(fileEle
);
206 outofdateEle
.appendChild(targetEle
);
207 Element sequentialEle
= document
.createElement("sequential");
208 sequentialEle
.appendChild(genffsfileEle
);
209 outofdateEle
.appendChild(sequentialEle
);
210 ffsNode
= outofdateEle
;
215 Change the attribute name. For example:
218 Before change: FFS_ATTRIB_CHECKSUM
219 After change: ffsATTRIBCHECKSUM
222 @param name Original attribute name
223 @return Changed attribute name
225 private String
changeAttributeName(String name
) {
226 String
[] strs
= name
.split("_");
227 String str
= strs
[0].toLowerCase();
228 for (int j
= 1; j
< strs
.length
; j
++) {
235 Recursively deal with Sections. If sections does not specify a type, then omit it.
237 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
238 @param doc Xml Document
239 @param root Root Node
240 @param cursor Current FFS layout cursor
241 @param list List of section type here used
243 private void dealSections(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
244 String type
= cursor
.getAttributeText(new QName("EncapsulationType"));
245 String toolName
= cursor
.getAttributeText(new QName("ToolName"));
246 String sectType
= cursor
.getAttributeText(new QName("SectionType"));
247 if (type
== null && sectType
== null) {
248 if (cursor
.toFirstChild()) {
250 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
252 dealSection(mode
, doc
, root
, cursor
, list
);
254 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
256 dealSections(mode
, doc
, root
, cursor
, list
);
259 } while (cursor
.toNextSibling());
264 Element toolEle
= null;
265 if (type
.equalsIgnoreCase("COMPRESS") && (toolName
== null || toolName
.equalsIgnoreCase(""))) {
266 mode
= MODE_COMPRESS
;
268 // <gensection sectiontype="EFI_SECTION_COMPRESSION">
270 ele
= doc
.createElement("gensection");
271 ele
.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");
274 mode
= MODE_GUID_DEFINED
;
276 // <gensection sectiontype="EFI_SECTION_GUID_DEFINED">
278 ele
= doc
.createElement("gensection");
280 if (type
.equalsIgnoreCase("COMPRESS")) {
281 ele
.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");
283 ele
.setAttribute("sectiontype", "EFI_SECTION_GUID_DEFINED");
287 ele
.setAttribute("sectiontype", sectType
);
290 // <tool toolName="${OEMTOOLPATH}\toolname"
291 // outputPath = "${DEST_DIR_OUTPUT}">
293 toolEle
= doc
.createElement("tool");
294 if (toolName
== null || toolName
.equalsIgnoreCase("")) {
295 toolEle
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
296 + File
.separatorChar
+ "GenCRC32Section");
298 File toolExe
= new File(toolName
);
300 // If <Tool> element exist, add sub element under <tool> .
302 if (toolExe
.isAbsolute()) {
303 toolEle
.setAttribute("toolName", toolName
);
305 toolEle
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
306 + File
.separatorChar
+ toolName
);
310 toolEle
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
311 ele
.appendChild(toolEle
);
313 if (cursor
.toFirstChild()) {
315 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
317 if (toolEle
== null) {
318 dealSection(mode
, doc
, ele
, cursor
, list
);
320 dealSection(mode
, doc
, toolEle
, cursor
, list
);
324 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
326 if (toolEle
== null) {
327 dealSections(mode
, doc
, ele
, cursor
, list
);
329 dealSections(mode
, doc
, toolEle
, cursor
, list
);
334 } while (cursor
.toNextSibling());
336 root
.appendChild(ele
);
340 Recursively deal with section.
342 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
343 @param doc Xml Document
344 @param root Root Node
345 @param cursor Current FFS layout cursor
346 @param list List of section type here used
348 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
349 String type
= cursor
.getAttributeText(new QName("SectionType"));
350 String alignment
= cursor
.getAttributeText(new QName("Alignment"));
353 // Judge if file is specified? Yes, just use the file, else call Build Macro
354 // If fileName is null, means without FileNames specify in FPD file
356 String fileName
= null;
358 if (cursor
.toFirstChild()) {
360 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Filenames")) {
362 if (cursor
.toFirstChild()) {
364 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Filename")) {
365 fileName
= cursor
.getTextValue();
367 } while (cursor
.toNextSibling());
371 } while (cursor
.toNextSibling());
376 if (fileName
== null) {
377 list
.addElement(type
);
379 list
.addElement(fileName
);
382 if (mode
== MODE_GUID_DEFINED
) {
384 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
386 Element ele
= doc
.createElement("input");
387 if (fileName
== null) {
388 ele
.setAttribute("file", getSectionFile(basename
, type
));
390 ele
.setAttribute("file", fileName
);
392 root
.appendChild(ele
);
395 // <sectFile fileName= "..."/>
397 Element ele
= doc
.createElement("sectFile");
398 if (fileName
== null) {
399 ele
.setAttribute("fileName", getSectionFile(basename
, type
));
401 ele
.setAttribute("fileName", fileName
);
403 if (alignment
!= null) {
404 ele
.setAttribute("Alignment", alignment
);
406 root
.appendChild(ele
);
411 Get the corresponding section file suffix.
413 @param type Section type
414 @return Corresponding section file extension
416 private String
getSectionFile(String basename
, String type
) {
417 for (int i
= 0; i
< sectionExt
.length
; i
++) {
418 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
419 return "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ sectionExt
[i
][1];
425 private boolean isSectionType(String type
) {
426 for (int i
= 0; i
< sectionExt
.length
; i
++) {
427 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
435 Return the ANT script to call GenFfs Tool.
437 @return ANT script to call GenFfs Tool
439 public Element
getFfsNode() {