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
.apache
.xmlbeans
.XmlObject
;
25 import org
.tianocore
.BuildOptionsDocument
;
26 import org
.tianocore
.build
.global
.GlobalData
;
27 import org
.tianocore
.build
.global
.SurfaceAreaQuery
;
28 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
29 import org
.w3c
.dom
.Document
;
30 import org
.w3c
.dom
.Element
;
31 import org
.w3c
.dom
.Node
;
34 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>
36 <p>Property <code>COMMON_FILE</code> specified which file to search. The element
37 in <code>COMMON_FILE</code> is like following: </p>
40 <Ffs type="APPLICATION">
41 <Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" />
42 <Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" />
43 <Sections EncapsulationType="Compress">
44 <Sections EncapsulationType="Guid-Defined">
45 <Section SectionType="EFI_SECTION_PE32" />
46 <Section SectionType="EFI_SECTION_USER_INTERFACE" />
47 <Section SectionType="EFI_SECTION_VERSION" />
55 public class FfsProcess
{
58 /// Xml Document Node for corresponding FFS layout
62 private BuildOptionsDocument
.BuildOptions
.Ffs ffsXmlObject
;
65 /// ANT script to call GenFfs
67 private Element ffsNode
= null;
72 private String basename
;
75 /// Sections type: normal
77 private static int MODE_NONE
= 0;
80 /// Sections type: compress
82 private static int MODE_COMPRESS
= 1;
85 /// Sections type: guid-define
87 private static int MODE_GUID_DEFINED
= 2;
90 /// mapping from section type to section output file extension
92 public static final String
[][] sectionExt
= { { "EFI_SECTION_FREEFORM_SUBTYPE_GUID", ".sec" },
93 { "EFI_SECTION_VERSION", ".ver" },
94 { "EFI_SECTION_USER_INTERFACE", ".ui" },
95 { "EFI_SECTION_DXE_DEPEX", ".dpx" },
96 { "EFI_SECTION_PEI_DEPEX", ".dpx" },
97 { "EFI_SECTION_PE32", ".pe32" },
98 { "EFI_SECTION_PIC", ".pic" },
99 { "EFI_SECTION_TE", ".tes" },
100 { "EFI_SECTION_RAW", ".sec" },
101 { "EFI_SECTION_COMPRESSION", ".sec" },
102 { "EFI_SECTION_GUID_DEFINED", ".sec" },
103 { "EFI_SECTION_COMPATIBILITY16", ".sec" },
104 { "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", ".sec" } };
107 search in the type, if componentType is listed in type, return true;
108 otherwise return false.
110 @param type a list supported component type separated by comma
111 @param componentType current module component type
112 @return whether componentType is one of type
114 private boolean isMatch(String type
, String componentType
) {
115 String
[] items
= type
.split("[ \t]*,[ \t]*");
116 for (int i
= 0; i
< items
.length
; i
++) {
117 if (items
[i
].equalsIgnoreCase(componentType
)) {
125 Find the corresponding FFS layout in <code>COMMON_FILE</code> if it
126 does not specify in module's surface area.
128 @param buildType Current module's component type
129 @param project Ant project
130 @return whether find the corresponding FFS layout
131 @throws BuildException
132 If specified COMMON_FILE XML file is not valide.
134 public boolean initSections(String buildType
, Project project
, FpdModuleIdentification fpdModuleId
) throws BuildException
{
136 // Firstly, try to find in ModuleSA
138 // BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = SurfaceAreaQuery.getModuleFfs();
139 // for (int i = 0; i < ffsArray.length; i++) {
140 // if (isMatch(ffsArray[i].getFfsKey(), buildType)) {
141 // ffsXmlObject = ffsArray[i];
147 // secondly, try to sections defined in PLATFORM level
149 SurfaceAreaQuery
.push(GlobalData
.getFpdBuildOptions());
150 BuildOptionsDocument
.BuildOptions
.Ffs
[] ffsArray
= SurfaceAreaQuery
.getFpdFfs();
151 SurfaceAreaQuery
.pop();
152 for (int i
= 0; i
< ffsArray
.length
; i
++) {
153 if (isMatch(ffsArray
[i
].getFfsKey(), buildType
)) {
154 ffsXmlObject
= ffsArray
[i
];
160 // If FfsFormatKey is not null, report exception and fail build
161 // Otherwise report warning message
163 if (buildType
== null) {
164 System
.out
.println("Warning: this module doesn't specify a FfsFormatKey. ");
167 throw new BuildException("Can't find FfsFormatKey [" + buildType
+ "] in FPD file. ");
178 Recursive parse the FFS layout. Find out all section type here used.
180 @param document BaseName_build.xml Xml document
181 @param basename Module's base name
182 @param guid Module's GUID
183 @param targetFilename Module's final file name (GUID-BaseName.APP)
184 @return List of section type
186 public String
[] getGenSectionElements(Document document
, String basename
, String guid
, String targetFilename
) {
187 this.basename
= basename
;
188 if (ffs
== null && ffsXmlObject
== null) {
189 return new String
[0];
191 Vector
<String
> sectionList
= new Vector
<String
>();
192 XmlCursor cursor
= null;
194 if (ffsXmlObject
== null) {
195 cursor
= XmlObject
.Factory
.parse(ffs
).newCursor();
198 cursor
= ffsXmlObject
.newCursor();
200 } catch (Exception e
) {
203 int mode
= MODE_NONE
;
204 Element root
= document
.createElement("genffsfile");
205 root
.setAttribute("outputDir", "${BIN_DIR}");
206 root
.setAttribute("moduleType", "${MODULE_TYPE}");
207 root
.setAttribute("BaseName", basename
);
208 root
.setAttribute("fileGuid", guid
);
209 if (ffsXmlObject
== null) {
210 cursor
.toFirstChild();
212 if (cursor
.toFirstChild()) {
214 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Attribute")) {
215 String name
= cursor
.getAttributeText(new QName("Name"));
216 String value
= cursor
.getAttributeText(new QName("Value"));
217 root
.setAttribute(changeAttributeName(name
), value
);
218 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
220 dealSection(mode
, document
, root
, cursor
, sectionList
);
222 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
224 dealSections(mode
, document
, root
, cursor
, sectionList
);
227 } while (cursor
.toNextSibling());
232 Element outofdateEle
= document
.createElement("OnDependency");
233 Element sourceEle
= document
.createElement("sourcefiles");
234 String
[] result
= new String
[sectionList
.size()];
235 for (int i
= 0; i
< sectionList
.size(); i
++) {
236 result
[i
] = (String
) sectionList
.get(i
);
237 Element pathEle
= document
.createElement("file");
238 pathEle
.setAttribute("name", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
239 + getSectionExt(result
[i
]));
240 sourceEle
.appendChild(pathEle
);
242 outofdateEle
.appendChild(sourceEle
);
243 Element targetEle
= document
.createElement("targetfiles");
244 Element fileEle
= document
.createElement("file");
245 fileEle
.setAttribute("name", "${BIN_DIR}" + File
.separatorChar
+ targetFilename
);
246 targetEle
.appendChild(fileEle
);
247 outofdateEle
.appendChild(targetEle
);
248 Element sequentialEle
= document
.createElement("sequential");
249 sequentialEle
.appendChild(root
);
250 outofdateEle
.appendChild(sequentialEle
);
251 ffsNode
= outofdateEle
;
256 Change the attribute name. For example:
259 Before change: FFS_ATTRIB_CHECKSUM
260 After change: ffsATTRIBCHECKSUM
263 @param name Original attribute name
264 @return Changed attribute name
266 private String
changeAttributeName(String name
) {
267 String
[] strs
= name
.split("_");
268 String str
= strs
[0].toLowerCase();
269 for (int j
= 1; j
< strs
.length
; j
++) {
276 Recursively deal with Sections. If sections does not specify a type, then omit it.
278 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
279 @param doc Xml Document
280 @param root Root Node
281 @param cursor Current FFS layout cursor
282 @param list List of section type here used
284 private void dealSections(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
285 String type
= cursor
.getAttributeText(new QName("EncapsulationType"));
287 if (cursor
.toFirstChild()) {
289 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
291 dealSection(mode
, doc
, root
, cursor
, list
);
293 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
295 dealSections(mode
, doc
, root
, cursor
, list
);
298 } while (cursor
.toNextSibling());
303 if (type
.equalsIgnoreCase("COMPRESS")) {
304 mode
= MODE_COMPRESS
;
306 // <compress compressName = "dummy">
308 ele
= doc
.createElement("compress");
309 ele
.setAttribute("compressName", "dummy");
311 mode
= MODE_GUID_DEFINED
;
313 // <tool toolName="${OEMTOOLPATH}\toolname"
314 // outputPath = "${DEST_DIR_OUTPUT}">
316 ele
= doc
.createElement("tool");
317 ele
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
318 + File
.separatorChar
+ "GenCRC32Section");
319 ele
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
321 if (cursor
.toFirstChild()) {
323 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
325 dealSection(mode
, doc
, ele
, cursor
, list
);
327 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
329 dealSections(mode
, doc
, ele
, cursor
, list
);
332 } while (cursor
.toNextSibling());
334 root
.appendChild(ele
);
338 Recursively deal with section.
340 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
341 @param doc Xml Document
342 @param root Root Node
343 @param cursor Current FFS layout cursor
344 @param list List of section type here used
346 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
347 String type
= cursor
.getAttributeText(new QName("SectionType"));
348 list
.addElement(type
);
349 if (mode
== MODE_GUID_DEFINED
) {
351 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
353 Element ele
= doc
.createElement("input");
354 ele
.setAttribute("file", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
355 root
.appendChild(ele
);
358 // <sectFile fileName= "..."/>
360 Element ele
= doc
.createElement("sectFile");
361 ele
.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
362 root
.appendChild(ele
);
367 Get the corresponding section file suffix.
369 @param type Section type
370 @return Corresponding section file extension
372 private String
getSectionExt(String type
) {
373 for (int i
= 0; i
< sectionExt
.length
; i
++) {
374 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
375 return sectionExt
[i
][1];
382 Return the ANT script to call GenFfs Tool.
384 @return ANT script to call GenFfs Tool
386 public Element
getFfsNode() {