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
.io
.FileInputStream
;
18 import java
.io
.InputStream
;
19 import java
.util
.Vector
;
21 import javax
.xml
.namespace
.QName
;
22 import javax
.xml
.parsers
.DocumentBuilder
;
23 import javax
.xml
.parsers
.DocumentBuilderFactory
;
25 import org
.apache
.tools
.ant
.BuildException
;
26 import org
.apache
.tools
.ant
.Project
;
27 import org
.apache
.xmlbeans
.XmlCursor
;
28 import org
.apache
.xmlbeans
.XmlObject
;
29 import org
.tianocore
.BuildOptionsDocument
;
30 import org
.tianocore
.build
.global
.GlobalData
;
31 import org
.tianocore
.build
.global
.SurfaceAreaQuery
;
32 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
33 import org
.w3c
.dom
.Document
;
34 import org
.w3c
.dom
.Element
;
35 import org
.w3c
.dom
.NamedNodeMap
;
36 import org
.w3c
.dom
.Node
;
37 import org
.w3c
.dom
.NodeList
;
40 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>
42 <p>Property <code>COMMON_FILE</code> specified which file to search. The element
43 in <code>COMMON_FILE</code> is like following: </p>
46 <Ffs type="APPLICATION">
47 <Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" />
48 <Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" />
49 <Sections EncapsulationType="Compress">
50 <Sections EncapsulationType="Guid-Defined">
51 <Section SectionType="EFI_SECTION_PE32" />
52 <Section SectionType="EFI_SECTION_USER_INTERFACE" />
53 <Section SectionType="EFI_SECTION_VERSION" />
61 public class FfsProcess
{
64 /// Xml Document Node for corresponding FFS layout
68 private BuildOptionsDocument
.BuildOptions
.Ffs ffsXmlObject
;
71 /// ANT script to call GenFfs
73 private Element ffsNode
= null;
78 private String basename
;
81 /// Sections type: normal
83 private static int MODE_NONE
= 0;
86 /// Sections type: compress
88 private static int MODE_COMPRESS
= 1;
91 /// Sections type: guid-define
93 private static int MODE_GUID_DEFINED
= 2;
96 /// mapping from section type to section output file extension
98 public static final String
[][] sectionExt
= { { "EFI_SECTION_FREEFORM_SUBTYPE_GUID", ".sec" },
99 { "EFI_SECTION_VERSION", ".ver" },
100 { "EFI_SECTION_USER_INTERFACE", ".ui" },
101 { "EFI_SECTION_DXE_DEPEX", ".dpx" },
102 { "EFI_SECTION_PEI_DEPEX", ".dpx" },
103 { "EFI_SECTION_PE32", ".pe32" },
104 { "EFI_SECTION_PIC", ".pic" },
105 { "EFI_SECTION_TE", ".tes" },
106 { "EFI_SECTION_RAW", ".sec" },
107 { "EFI_SECTION_COMPRESSION", ".sec" },
108 { "EFI_SECTION_GUID_DEFINED", ".sec" },
109 { "EFI_SECTION_COMPATIBILITY16", ".sec" },
110 { "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", ".sec" } };
113 search in the type, if componentType is listed in type, return true;
114 otherwise return false.
116 @param type a list supported component type separated by comma
117 @param componentType current module component type
118 @return whether componentType is one of type
120 private boolean isMatch(String type
, String componentType
) {
121 String
[] items
= type
.split("[ \t]*,[ \t]*");
122 for (int i
= 0; i
< items
.length
; i
++) {
123 if (items
[i
].equalsIgnoreCase(componentType
)) {
131 Find the corresponding FFS layout in <code>COMMON_FILE</code> if it
132 does not specify in module's surface area.
134 @param buildType Current module's component type
135 @param project Ant project
136 @return whether find the corresponding FFS layout
137 @throws BuildException
138 If specified COMMON_FILE XML file is not valide.
140 public boolean initSections(String buildType
, Project project
, FpdModuleIdentification fpdModuleId
) throws BuildException
{
142 // Firstly, try to find in ModuleSA
144 // BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = SurfaceAreaQuery.getModuleFfs();
145 // for (int i = 0; i < ffsArray.length; i++) {
146 // if (isMatch(ffsArray[i].getFfsKey(), buildType)) {
147 // ffsXmlObject = ffsArray[i];
153 // secondly, try to sections defined in PLATFORM level
155 SurfaceAreaQuery
.push(GlobalData
.getFpdBuildOptions());
156 BuildOptionsDocument
.BuildOptions
.Ffs
[] ffsArray
= SurfaceAreaQuery
.getFpdFfs();
157 SurfaceAreaQuery
.pop();
158 for (int i
= 0; i
< ffsArray
.length
; i
++) {
159 if (isMatch(ffsArray
[i
].getFfsKey(), buildType
)) {
160 ffsXmlObject
= ffsArray
[i
];
166 // if module specify sections itself, it's okay
167 // otherwise find sections from WORKSPACE default setting with
171 File file
= new File(project
.getProperty("COMMON_FILE"));
173 // if common file is not existed, just return
175 if (!file
.exists()) {
178 DocumentBuilderFactory domfac
= DocumentBuilderFactory
.newInstance();
180 DocumentBuilder dombuilder
= domfac
.newDocumentBuilder();
181 InputStream is
= new FileInputStream(file
);
182 Document doc
= dombuilder
.parse(is
);
183 Element root
= doc
.getDocumentElement();
184 NodeList items
= root
.getChildNodes();
185 for (int i
= 0; i
< items
.getLength(); i
++) {
186 Node node
= items
.item(i
);
187 if (node
.getNodeType() == Node
.ELEMENT_NODE
) {
188 String nodeName
= node
.getNodeName();
189 if (nodeName
.equalsIgnoreCase("Ffs")) {
190 NamedNodeMap attr
= node
.getAttributes();
191 Node type
= attr
.getNamedItem("type");
193 if (isMatch(type
.getTextContent(), buildType
)) {
201 } catch (Exception e
) {
202 throw new BuildException("Parse COMMON_FILE [" + file
.getPath() + "] error!\n" + e
.getMessage());
213 Recursive parse the FFS layout. Find out all section type here used.
215 @param document BaseName_build.xml Xml document
216 @param basename Module's base name
217 @param guid Module's GUID
218 @param targetFilename Module's final file name (GUID-BaseName.APP)
219 @return List of section type
221 public String
[] getGenSectionElements(Document document
, String basename
, String guid
, String targetFilename
) {
222 this.basename
= basename
;
223 if (ffs
== null && ffsXmlObject
== null) {
224 return new String
[0];
226 Vector
<String
> sectionList
= new Vector
<String
>();
227 XmlCursor cursor
= null;
229 if (ffsXmlObject
== null) {
230 cursor
= XmlObject
.Factory
.parse(ffs
).newCursor();
233 cursor
= ffsXmlObject
.newCursor();
235 } catch (Exception e
) {
238 int mode
= MODE_NONE
;
239 Element root
= document
.createElement("genffsfile");
240 root
.setAttribute("outputDir", "${BIN_DIR}");
241 root
.setAttribute("moduleType", "${MODULE_TYPE}");
242 root
.setAttribute("BaseName", basename
);
243 root
.setAttribute("fileGuid", guid
);
244 if (ffsXmlObject
== null) {
245 cursor
.toFirstChild();
247 if (cursor
.toFirstChild()) {
249 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Attribute")) {
250 String name
= cursor
.getAttributeText(new QName("Name"));
251 String value
= cursor
.getAttributeText(new QName("Value"));
252 root
.setAttribute(changeAttributeName(name
), value
);
253 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
255 dealSection(mode
, document
, root
, cursor
, sectionList
);
257 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
259 dealSections(mode
, document
, root
, cursor
, sectionList
);
262 } while (cursor
.toNextSibling());
267 Element outofdateEle
= document
.createElement("OnDependency");
268 Element sourceEle
= document
.createElement("sourcefiles");
269 String
[] result
= new String
[sectionList
.size()];
270 for (int i
= 0; i
< sectionList
.size(); i
++) {
271 result
[i
] = (String
) sectionList
.get(i
);
272 Element pathEle
= document
.createElement("file");
273 pathEle
.setAttribute("name", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
274 + getSectionExt(result
[i
]));
275 sourceEle
.appendChild(pathEle
);
277 outofdateEle
.appendChild(sourceEle
);
278 Element targetEle
= document
.createElement("targetfiles");
279 Element fileEle
= document
.createElement("file");
280 fileEle
.setAttribute("name", "${BIN_DIR}\\" + targetFilename
);
281 targetEle
.appendChild(fileEle
);
282 outofdateEle
.appendChild(targetEle
);
283 Element sequentialEle
= document
.createElement("sequential");
284 sequentialEle
.appendChild(root
);
285 outofdateEle
.appendChild(sequentialEle
);
286 ffsNode
= outofdateEle
;
291 Change the attribute name. For example:
294 Before change: FFS_ATTRIB_CHECKSUM
295 After change: ffsATTRIBCHECKSUM
298 @param name Original attribute name
299 @return Changed attribute name
301 private String
changeAttributeName(String name
) {
302 String
[] strs
= name
.split("_");
303 String str
= strs
[0].toLowerCase();
304 for (int j
= 1; j
< strs
.length
; j
++) {
311 Recursively deal with Sections. If sections does not specify a type, then omit it.
313 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
314 @param doc Xml Document
315 @param root Root Node
316 @param cursor Current FFS layout cursor
317 @param list List of section type here used
319 private void dealSections(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
320 String type
= cursor
.getAttributeText(new QName("EncapsulationType"));
322 if (cursor
.toFirstChild()) {
324 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
326 dealSection(mode
, doc
, root
, cursor
, list
);
328 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
330 dealSections(mode
, doc
, root
, cursor
, list
);
333 } while (cursor
.toNextSibling());
338 if (type
.equalsIgnoreCase("COMPRESS")) {
339 mode
= MODE_COMPRESS
;
341 // <compress compressName = "dummy">
343 ele
= doc
.createElement("compress");
344 ele
.setAttribute("compressName", "dummy");
346 mode
= MODE_GUID_DEFINED
;
348 // <tool toolName="${OEMTOOLPATH}\toolname"
349 // outputPath = "${DEST_DIR_OUTPUT}">
351 ele
= doc
.createElement("tool");
352 ele
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "Bin"
353 + File
.separatorChar
+ "GenCRC32Section");
354 ele
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
356 if (cursor
.toFirstChild()) {
358 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
360 dealSection(mode
, doc
, ele
, cursor
, list
);
362 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
364 dealSections(mode
, doc
, ele
, cursor
, list
);
367 } while (cursor
.toNextSibling());
369 root
.appendChild(ele
);
373 Recursively deal with section.
375 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
376 @param doc Xml Document
377 @param root Root Node
378 @param cursor Current FFS layout cursor
379 @param list List of section type here used
381 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
382 String type
= cursor
.getAttributeText(new QName("SectionType"));
383 list
.addElement(type
);
384 if (mode
== MODE_GUID_DEFINED
) {
386 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
388 Element ele
= doc
.createElement("input");
389 ele
.setAttribute("file", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
390 root
.appendChild(ele
);
393 // <sectFile fileName= "..."/>
395 Element ele
= doc
.createElement("sectFile");
396 ele
.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
397 root
.appendChild(ele
);
402 Get the corresponding section file suffix.
404 @param type Section type
405 @return Corresponding section file extension
407 private String
getSectionExt(String type
) {
408 for (int i
= 0; i
< sectionExt
.length
; i
++) {
409 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
410 return sectionExt
[i
][1];
417 Return the ANT script to call GenFfs Tool.
419 @return ANT script to call GenFfs Tool
421 public Element
getFfsNode() {