package org.tianocore.build;\r
\r
import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.FileReader;\r
+import java.io.FileWriter;\r
+import java.security.MessageDigest;\r
import java.util.Vector;\r
\r
import javax.xml.namespace.QName;\r
\r
private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;\r
\r
+ private Project project = null;\r
///\r
/// ANT script to call GenFfs\r
///\r
If can't find FFS Layout in FPD.\r
**/\r
public boolean initSections(String buildType, Project project, FpdModuleIdentification fpdModuleId) throws BuildException {\r
+ this.project = project;\r
//\r
// Try to find Ffs layout from FPD file\r
//\r
for (int i = 0; i < ffsArray.length; i++) {\r
if (isMatch(ffsArray[i].getFfsKey(), buildType)) {\r
ffsXmlObject = ffsArray[i];\r
+ genDigest();\r
return true;\r
}\r
}\r
//\r
Element outofdateEle = document.createElement("OnDependency");\r
Element sourceEle = document.createElement("sourcefiles");\r
- String[] result = new String[sectionList.size()];\r
+ Vector<String> sections = new Vector<String>();\r
for (int i = 0; i < sectionList.size(); i++) {\r
- result[i] = (String) sectionList.get(i);\r
+ String section = (String) sectionList.get(i);\r
+ if (isSectionType(section)) {\r
+ sections.addElement(section);\r
+ }\r
Element pathEle = document.createElement("file");\r
- pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename\r
- + getSectionExt(result[i]));\r
+ pathEle.setAttribute("name", getSectionFile(basename, section));\r
sourceEle.appendChild(pathEle);\r
}\r
+ //\r
+ // add FFS layout digest into the source file list\r
+ // \r
+ Element pathEle = document.createElement("file");\r
+ pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separator + "ffs.md5");\r
+ sourceEle.appendChild(pathEle);\r
+\r
+ String[] result = sections.toArray(new String[sections.size()]);\r
+\r
outofdateEle.appendChild(sourceEle);\r
Element targetEle = document.createElement("targetfiles");\r
Element fileEle = document.createElement("file");\r
**/\r
private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
String type = cursor.getAttributeText(new QName("SectionType"));\r
+ String alignment = cursor.getAttributeText(new QName("Alignment"));\r
\r
//\r
// Judge if file is specified? Yes, just use the file, else call Build Macro\r
\r
if (fileName == null) {\r
list.addElement(type);\r
+ } else {\r
+ list.addElement(fileName);\r
}\r
+\r
if (mode == MODE_GUID_DEFINED) {\r
//\r
// <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>\r
//\r
Element ele = doc.createElement("input");\r
if (fileName == null) {\r
- ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
+ ele.setAttribute("file", getSectionFile(basename, type));\r
} else {\r
- ele.setAttribute("file", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
+ ele.setAttribute("file", fileName);\r
}\r
root.appendChild(ele);\r
} else {\r
//\r
Element ele = doc.createElement("sectFile");\r
if (fileName == null) {\r
- ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
+ ele.setAttribute("fileName", getSectionFile(basename, type));\r
} else {\r
- ele.setAttribute("fileName", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
+ ele.setAttribute("fileName", fileName);\r
+ }\r
+ if (alignment != null) {\r
+ ele.setAttribute("Alignment", alignment);\r
}\r
root.appendChild(ele);\r
}\r
@param type Section type\r
@return Corresponding section file extension\r
**/\r
- private String getSectionExt(String type) {\r
+ private String getSectionFile(String basename, String type) {\r
+ for (int i = 0; i < sectionExt.length; i++) {\r
+ if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
+ return "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + sectionExt[i][1];\r
+ }\r
+ }\r
+ return type;\r
+ }\r
+\r
+ private boolean isSectionType(String type) {\r
for (int i = 0; i < sectionExt.length; i++) {\r
if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
- return sectionExt[i][1];\r
+ return true;\r
}\r
}\r
- return ".sec";\r
+ return false;\r
}\r
\r
/**\r
public Element getFfsNode() {\r
return ffsNode;\r
}\r
+\r
+ private void genDigest() {\r
+ String digestFilePath = project.getProperty("DEST_DIR_OUTPUT");\r
+ if (digestFilePath == null) {\r
+ EdkLog.log(EdkLog.EDK_WARNING, "Warning: cannot get DEST_DIR_OUTPUT!");\r
+ return;\r
+ }\r
+\r
+ //\r
+ // use MD5 algorithm\r
+ // \r
+ MessageDigest md5 = null;\r
+ try {\r
+ md5 = MessageDigest.getInstance("MD5");\r
+ //\r
+ // convert the FFS layout XML DOM tree into string and use it to\r
+ // calculate its MD5 digest value\r
+ // \r
+ md5.update(ffsXmlObject.xmlText().getBytes());\r
+ } catch (Exception e) {\r
+ EdkLog.log(EdkLog.EDK_WARNING, "Warning: " + e.getMessage());\r
+ return;\r
+ }\r
+\r
+ //\r
+ // get the MD5 digest value\r
+ // \r
+ byte[] digest = md5.digest();\r
+\r
+ //\r
+ // put the digest in a file named "ffs.md5" if it doesn't exist, otherwise\r
+ // we will compare the digest in the file with the one just calculated\r
+ // \r
+ digestFilePath += File.separator + "ffs.md5";\r
+ File digestFile = new File(digestFilePath);\r
+ if (digestFile.exists()) {\r
+ byte[] oldDigest = new byte[digest.length];\r
+ try {\r
+ FileInputStream fIn = new FileInputStream(digestFile);\r
+ fIn.read(oldDigest);\r
+ fIn.close();\r
+ } catch (Exception e) {\r
+ throw new BuildException(e.getMessage());\r
+ }\r
+\r
+ boolean noChange = true;\r
+ for (int i = 0; i < oldDigest.length; ++i) {\r
+ if (digest[i] != oldDigest[i]) {\r
+ noChange = false;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (noChange) {\r
+ return;\r
+ }\r
+ }\r
+\r
+ //\r
+ // update the "ffs.md5" file content with new digest value\r
+ // \r
+ try {\r
+ FileOutputStream fOut = new FileOutputStream(digestFile);\r
+ fOut.write(digest);\r
+ fOut.close();\r
+ } catch (Exception e) {\r
+ throw new BuildException(e.getMessage());\r
+ }\r
+ }\r
}\r