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 FfsFormatKey is not null, report exception and fail build
167 // Otherwise report warning message
169 if (buildType
== null) {
170 System
.out
.println("Warning: this module doesn't specify a FfsFormatKey. ");
173 throw new BuildException("Can't find FfsFormatKey [" + buildType
+ "] in FPD file. ");
184 Recursive parse the FFS layout. Find out all section type here used.
186 @param document BaseName_build.xml Xml document
187 @param basename Module's base name
188 @param guid Module's GUID
189 @param targetFilename Module's final file name (GUID-BaseName.APP)
190 @return List of section type
192 public String
[] getGenSectionElements(Document document
, String basename
, String guid
, String targetFilename
) {
193 this.basename
= basename
;
194 if (ffs
== null && ffsXmlObject
== null) {
195 return new String
[0];
197 Vector
<String
> sectionList
= new Vector
<String
>();
198 XmlCursor cursor
= null;
200 if (ffsXmlObject
== null) {
201 cursor
= XmlObject
.Factory
.parse(ffs
).newCursor();
204 cursor
= ffsXmlObject
.newCursor();
206 } catch (Exception e
) {
209 int mode
= MODE_NONE
;
210 Element root
= document
.createElement("genffsfile");
211 root
.setAttribute("outputDir", "${BIN_DIR}");
212 root
.setAttribute("moduleType", "${MODULE_TYPE}");
213 root
.setAttribute("BaseName", basename
);
214 root
.setAttribute("fileGuid", guid
);
215 if (ffsXmlObject
== null) {
216 cursor
.toFirstChild();
218 if (cursor
.toFirstChild()) {
220 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Attribute")) {
221 String name
= cursor
.getAttributeText(new QName("Name"));
222 String value
= cursor
.getAttributeText(new QName("Value"));
223 root
.setAttribute(changeAttributeName(name
), value
);
224 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
226 dealSection(mode
, document
, root
, cursor
, sectionList
);
228 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
230 dealSections(mode
, document
, root
, cursor
, sectionList
);
233 } while (cursor
.toNextSibling());
238 Element outofdateEle
= document
.createElement("OnDependency");
239 Element sourceEle
= document
.createElement("sourcefiles");
240 String
[] result
= new String
[sectionList
.size()];
241 for (int i
= 0; i
< sectionList
.size(); i
++) {
242 result
[i
] = (String
) sectionList
.get(i
);
243 Element pathEle
= document
.createElement("file");
244 pathEle
.setAttribute("name", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
245 + getSectionExt(result
[i
]));
246 sourceEle
.appendChild(pathEle
);
248 outofdateEle
.appendChild(sourceEle
);
249 Element targetEle
= document
.createElement("targetfiles");
250 Element fileEle
= document
.createElement("file");
251 fileEle
.setAttribute("name", "${BIN_DIR}" + File
.separatorChar
+ targetFilename
);
252 targetEle
.appendChild(fileEle
);
253 outofdateEle
.appendChild(targetEle
);
254 Element sequentialEle
= document
.createElement("sequential");
255 sequentialEle
.appendChild(root
);
256 outofdateEle
.appendChild(sequentialEle
);
257 ffsNode
= outofdateEle
;
262 Change the attribute name. For example:
265 Before change: FFS_ATTRIB_CHECKSUM
266 After change: ffsATTRIBCHECKSUM
269 @param name Original attribute name
270 @return Changed attribute name
272 private String
changeAttributeName(String name
) {
273 String
[] strs
= name
.split("_");
274 String str
= strs
[0].toLowerCase();
275 for (int j
= 1; j
< strs
.length
; j
++) {
282 Recursively deal with Sections. If sections does not specify a type, then omit it.
284 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
285 @param doc Xml Document
286 @param root Root Node
287 @param cursor Current FFS layout cursor
288 @param list List of section type here used
290 private void dealSections(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
291 String type
= cursor
.getAttributeText(new QName("EncapsulationType"));
293 if (cursor
.toFirstChild()) {
295 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
297 dealSection(mode
, doc
, root
, cursor
, list
);
299 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
301 dealSections(mode
, doc
, root
, cursor
, list
);
304 } while (cursor
.toNextSibling());
309 if (type
.equalsIgnoreCase("COMPRESS")) {
310 mode
= MODE_COMPRESS
;
312 // <compress compressName = "dummy">
314 ele
= doc
.createElement("compress");
315 ele
.setAttribute("compressName", "dummy");
317 mode
= MODE_GUID_DEFINED
;
319 // <tool toolName="${OEMTOOLPATH}\toolname"
320 // outputPath = "${DEST_DIR_OUTPUT}">
322 ele
= doc
.createElement("tool");
323 ele
.setAttribute("toolName", "${WORKSPACE_DIR}" + File
.separatorChar
+ "Tools" + File
.separatorChar
+ "bin"
324 + File
.separatorChar
+ "GenCRC32Section");
325 ele
.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");
327 if (cursor
.toFirstChild()) {
329 if (cursor
.getName().getLocalPart().equalsIgnoreCase("Section")) {
331 dealSection(mode
, doc
, ele
, cursor
, list
);
333 } else if (cursor
.getName().getLocalPart().equalsIgnoreCase("Sections")) {
335 dealSections(mode
, doc
, ele
, cursor
, list
);
338 } while (cursor
.toNextSibling());
340 root
.appendChild(ele
);
344 Recursively deal with section.
346 @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)
347 @param doc Xml Document
348 @param root Root Node
349 @param cursor Current FFS layout cursor
350 @param list List of section type here used
352 private void dealSection(int mode
, Document doc
, Element root
, XmlCursor cursor
, Vector
<String
> list
) {
353 String type
= cursor
.getAttributeText(new QName("SectionType"));
354 list
.addElement(type
);
355 if (mode
== MODE_GUID_DEFINED
) {
357 // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>
359 Element ele
= doc
.createElement("input");
360 ele
.setAttribute("file", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
361 root
.appendChild(ele
);
364 // <sectFile fileName= "..."/>
366 Element ele
= doc
.createElement("sectFile");
367 ele
.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File
.separatorChar
+ basename
+ getSectionExt(type
));
368 root
.appendChild(ele
);
373 Get the corresponding section file suffix.
375 @param type Section type
376 @return Corresponding section file extension
378 private String
getSectionExt(String type
) {
379 for (int i
= 0; i
< sectionExt
.length
; i
++) {
380 if (sectionExt
[i
][0].equalsIgnoreCase(type
)) {
381 return sectionExt
[i
][1];
388 Return the ANT script to call GenFfs Tool.
390 @return ANT script to call GenFfs Tool
392 public Element
getFfsNode() {