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 ele
.setAttribute("sectiontype", "EFI_SECTION_GUID_DEFINED");
278 ele
.setAttribute("sectiontype", sectType
);
281 // <tool toolName="${OEMTOOLPATH}\toolname"
282 // outputPath = "${DEST_DIR_OUTPUT}">
284 toolEle
= doc
.createElement("tool");
285 if (toolName
== null || toolName
.equalsIgnoreCase("")) {
286 toolEle
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
287 + File
.separatorChar
+ "GenCRC32Section");
289 File toolExe
= new File(toolName
);
291 // If <Tool> element exist, add sub element under <tool> .
293 if (toolExe
.isAbsolute()) {
294 toolEle
.setAttribute("toolName", toolName
);
296 toolEle
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
297 + File
.separatorChar
+ toolName
);
301 toolEle
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
302 ele
.appendChild(toolEle
);
304 if (cursor
.toFirstChild()) {
306 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
308 if (toolEle
== null) {
309 dealSection(mode
, doc
, ele
, cursor
, list
);
311 dealSection(mode
, doc
, toolEle
, cursor
, list
);
315 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
317 if (toolEle
== null) {
318 dealSections(mode
, doc
, ele
, cursor
, list
);
320 dealSections(mode
, doc
, toolEle
, cursor
, list
);
325 } while (cursor
.toNextSibling());
327 root
.appendChild(ele
);
331 Recursively deal with section.
333 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
334 @param doc Xml Document
335 @param root Root Node
336 @param cursor Current FFS layout cursor
337 @param list List of section type here used
339 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
340 String type
= cursor
.getAttributeText(new QName("SectionType"));
343 // Judge if file is specified? Yes, just use the file, else call Build Macro
344 // If fileName is null, means without FileNames specify in FPD file
346 String fileName
= null;
348 if (cursor
.toFirstChild()) {
350 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Filenames")) {
352 if (cursor
.toFirstChild()) {
354 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Filename")) {
355 fileName
= cursor
.getTextValue();
357 } while (cursor
.toNextSibling());
361 } while (cursor
.toNextSibling());
366 if (fileName
== null) {
367 list
.addElement(type
);
369 if (mode
== MODE_GUID_DEFINED
) {
371 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
373 Element ele
= doc
.createElement("input");
374 if (fileName
== null) {
375 ele
.setAttribute("file", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
377 ele
.setAttribute("file", "${PLATFORM_DIR}" + File
.separatorChar
+ fileName
);
379 root
.appendChild(ele
);
382 // <sectFile fileName= "..."/>
384 Element ele
= doc
.createElement("sectFile");
385 if (fileName
== null) {
386 ele
.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
388 ele
.setAttribute("fileName", "${PLATFORM_DIR}" + File
.separatorChar
+ fileName
);
390 root
.appendChild(ele
);
395 Get the corresponding section file suffix.
397 @param type Section type
398 @return Corresponding section file extension
400 private String
getSectionExt(String type
) {
401 for (int i
= 0; i
< sectionExt
.length
; i
++) {
402 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
403 return sectionExt
[i
][1];
410 Return the ANT script to call GenFfs Tool.
412 @return ANT script to call GenFfs Tool
414 public Element
getFfsNode() {