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
.w3c
.dom
.Document
;
30 import org
.w3c
.dom
.Element
;
31 import org
.w3c
.dom
.NamedNodeMap
;
32 import org
.w3c
.dom
.Node
;
33 import org
.w3c
.dom
.NodeList
;
36 <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>
38 <p>Property <code>COMMON_FILE</code> specified which file to search. The element
39 in <code>COMMON_FILE</code> is like following: </p>
42 <Ffs type="APPLICATION">
43 <Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" />
44 <Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" />
45 <Sections EncapsulationType="Compress">
46 <Sections EncapsulationType="Guid-Defined">
47 <Section SectionType="EFI_SECTION_PE32" />
48 <Section SectionType="EFI_SECTION_USER_INTERFACE" />
49 <Section SectionType="EFI_SECTION_VERSION" />
57 public class FfsProcess
{
60 /// Xml Document Node for corresponding FFS layout
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
) throws BuildException
{
136 // first try to sections defined in PLATFORM level
140 // if module specify sections itself, it's okay
141 // otherwise find sections from WORKSPACE default setting with
145 File file
= new File(project
.getProperty("COMMON_FILE"));
147 // if common file is not existed, just return
149 if (!file
.exists()) {
152 DocumentBuilderFactory domfac
= DocumentBuilderFactory
.newInstance();
154 DocumentBuilder dombuilder
= domfac
.newDocumentBuilder();
155 InputStream is
= new FileInputStream(file
);
156 Document doc
= dombuilder
.parse(is
);
157 Element root
= doc
.getDocumentElement();
158 NodeList items
= root
.getChildNodes();
159 for (int i
= 0; i
< items
.getLength(); i
++) {
160 Node node
= items
.item(i
);
161 if (node
.getNodeType() == Node
.ELEMENT_NODE
) {
162 String nodeName
= node
.getNodeName();
163 if (nodeName
.equalsIgnoreCase("Ffs")) {
164 NamedNodeMap attr
= node
.getAttributes();
165 Node type
= attr
.getNamedItem("type");
167 if (isMatch(type
.getTextContent(), buildType
)) {
175 } catch (Exception e
) {
176 throw new BuildException("Parse COMMON_FILE [" + file
.getPath() + "] error!\n" + e
.getMessage());
187 Recursive parse the FFS layout. Find out all section type here used.
189 @param document BaseName_build.xml Xml document
190 @param basename Module's base name
191 @param guid Module's GUID
192 @param targetFilename Module's final file name (GUID-BaseName.APP)
193 @return List of section type
195 public String
[] getGenSectionElements(Document document
, String basename
, String guid
, String targetFilename
) {
196 this.basename
= basename
;
198 return new String
[0];
200 Vector
<String
> sectionList
= new Vector
<String
>();
201 XmlCursor cursor
= null;
203 cursor
= XmlObject
.Factory
.parse(ffs
).newCursor();
204 } catch (Exception e
) {
207 int mode
= MODE_NONE
;
208 Element root
= document
.createElement("genffsfile");
209 root
.setAttribute("outputDir", "${BIN_DIR}");
210 root
.setAttribute("BaseName", basename
);
211 root
.setAttribute("fileGuid", guid
);
212 cursor
.toFirstChild();
213 if (cursor
.toFirstChild()) {
215 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Attribute")) {
216 String name
= cursor
.getAttributeText(new QName("Name"));
217 String value
= cursor
.getAttributeText(new QName("Value"));
218 root
.setAttribute(changeAttributeName(name
), value
);
219 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
221 dealSection(mode
, document
, root
, cursor
, sectionList
);
223 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
225 dealSections(mode
, document
, root
, cursor
, sectionList
);
228 } while (cursor
.toNextSibling());
233 Element outofdateEle
= document
.createElement("OnDependency");
234 Element sourceEle
= document
.createElement("sourcefiles");
235 String
[] result
= new String
[sectionList
.size()];
236 for (int i
= 0; i
< sectionList
.size(); i
++) {
237 result
[i
] = (String
) sectionList
.get(i
);
238 Element pathEle
= document
.createElement("file");
239 pathEle
.setAttribute("name", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
240 + getSectionExt(result
[i
]));
241 sourceEle
.appendChild(pathEle
);
243 outofdateEle
.appendChild(sourceEle
);
244 Element targetEle
= document
.createElement("targetfiles");
245 Element fileEle
= document
.createElement("file");
246 fileEle
.setAttribute("name", "${BIN_DIR}\\" + targetFilename
);
247 targetEle
.appendChild(fileEle
);
248 outofdateEle
.appendChild(targetEle
);
249 Element sequentialEle
= document
.createElement("sequential");
250 sequentialEle
.appendChild(root
);
251 outofdateEle
.appendChild(sequentialEle
);
252 ffsNode
= outofdateEle
;
257 Change the attribute name. For example:
260 Before change: FFS_ATTRIB_CHECKSUM
261 After change: ffsATTRIBCHECKSUM
264 @param name Original attribute name
265 @return Changed attribute name
267 private String
changeAttributeName(String name
) {
268 String
[] strs
= name
.split("_");
269 String str
= strs
[0].toLowerCase();
270 for (int j
= 1; j
< strs
.length
; j
++) {
277 Recursively deal with Sections. If sections does not specify a type, then omit it.
279 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
280 @param doc Xml Document
281 @param root Root Node
282 @param cursor Current FFS layout cursor
283 @param list List of section type here used
285 private void dealSections(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
286 String type
= cursor
.getAttributeText(new QName("EncapsulationType"));
288 if (cursor
.toFirstChild()) {
290 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
292 dealSection(mode
, doc
, root
, cursor
, list
);
294 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
296 dealSections(mode
, doc
, root
, cursor
, list
);
299 } while (cursor
.toNextSibling());
304 if (type
.equalsIgnoreCase("COMPRESS")) {
305 mode
= MODE_COMPRESS
;
307 // <compress compressName = "dummy">
309 ele
= doc
.createElement("compress");
310 ele
.setAttribute("compressName", "dummy");
312 mode
= MODE_GUID_DEFINED
;
314 // <tool toolName="${OEMTOOLPATH}\toolname"
315 // outputPath = "${DEST_DIR_OUTPUT}">
317 ele
= doc
.createElement("tool");
318 ele
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "Bin"
319 + File
.separatorChar
+ "GenCRC32Section");
320 ele
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
322 if (cursor
.toFirstChild()) {
324 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
326 dealSection(mode
, doc
, ele
, cursor
, list
);
328 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
330 dealSections(mode
, doc
, ele
, cursor
, list
);
333 } while (cursor
.toNextSibling());
335 root
.appendChild(ele
);
339 Recursively deal with section.
341 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
342 @param doc Xml Document
343 @param root Root Node
344 @param cursor Current FFS layout cursor
345 @param list List of section type here used
347 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
348 String type
= cursor
.getAttributeText(new QName("SectionType"));
349 list
.addElement(type
);
350 if (mode
== MODE_GUID_DEFINED
) {
352 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
354 Element ele
= doc
.createElement("input");
355 ele
.setAttribute("file", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
356 root
.appendChild(ele
);
359 // <sectFile fileName= "..."/>
361 Element ele
= doc
.createElement("sectFile");
362 ele
.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
363 root
.appendChild(ele
);
368 Get the corresponding section file suffix.
370 @param type Section type
371 @return Corresponding section file extension
373 private String
getSectionExt(String type
) {
374 for (int i
= 0; i
< sectionExt
.length
; i
++) {
375 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
376 return sectionExt
[i
][1];
383 Return the ANT script to call GenFfs Tool.
385 @return ANT script to call GenFfs Tool
387 public Element
getFfsNode() {