summaryrefslogtreecommitdiff
path: root/Tools/CCode/Source/GenFvMap
diff options
context:
space:
mode:
authorbxing <bxing@6f19259b-4bc3-4df7-8a09-765794883524>2006-12-30 09:17:16 +0000
committerbxing <bxing@6f19259b-4bc3-4df7-8a09-765794883524>2006-12-30 09:17:16 +0000
commit8733430b83565480540d1d890986cbf22c54db0d (patch)
treea53fa90f7b3ed378eb58d46971572c792814599a /Tools/CCode/Source/GenFvMap
parent242c77a08512363429e22a2e1cceb77274a7ef44 (diff)
downloadedk2-8733430b83565480540d1d890986cbf22c54db0d.zip
edk2-8733430b83565480540d1d890986cbf22c54db0d.tar.gz
edk2-8733430b83565480540d1d890986cbf22c54db0d.tar.bz2
1. Added a new tool GenFvMap, which is able to generate FV map files upon LOG files generated by PeiRebase.
2. Updated PeiRebase to generate LOG files while processing FV images. The original MAP feature and its corresponding option '-M' are dropped, however, they are superceded by the FV map file. 3. The FV map file are not generated yet. My next check-in will update FPD files to generate FV map files. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2157 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'Tools/CCode/Source/GenFvMap')
-rw-r--r--Tools/CCode/Source/GenFvMap/GenFvMap.cpp507
-rw-r--r--Tools/CCode/Source/GenFvMap/build.xml72
2 files changed, 579 insertions, 0 deletions
diff --git a/Tools/CCode/Source/GenFvMap/GenFvMap.cpp b/Tools/CCode/Source/GenFvMap/GenFvMap.cpp
new file mode 100644
index 0000000..4a8c726
--- /dev/null
+++ b/Tools/CCode/Source/GenFvMap/GenFvMap.cpp
@@ -0,0 +1,507 @@
+//****************************************************************************
+//**
+//** Copyright (C) 2006 Intel Corporation. All rights reserved.
+//**
+//** The information and source code contained herein is the exclusive
+//** property of Intel Corporation and may not be disclosed, examined
+//** or reproduced in whole or in part without explicit written authorization
+//** from the company.
+//**
+//****************************************************************************
+
+#include <stdexcept>
+#include <list>
+#include <map>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <algorithm>
+#include <functional>
+using namespace std;
+
+typedef unsigned __int64 ulonglong_t;
+
+template <class T>
+class CMemoryLeakChecker : public list<T*>
+{
+public:
+ static CMemoryLeakChecker<T>& GetInstance(void);
+
+private:
+ CMemoryLeakChecker(void)
+ {
+ }
+
+ ~CMemoryLeakChecker(void);
+};
+
+template <class T>
+CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance(void)
+{
+ static CMemoryLeakChecker<T> s_memLeakChecker;
+ return s_memLeakChecker;
+}
+
+template <class T>
+CMemoryLeakChecker<T>::~CMemoryLeakChecker(void)
+{
+ if (!list<T*>::empty())
+ throw logic_error(__FUNCTION__ ": Memory leak detected!");
+}
+
+class CObjRoot
+{
+protected:
+ CObjRoot(void);
+ virtual ~CObjRoot(void);
+};
+
+CObjRoot::CObjRoot(void)
+{
+ CMemoryLeakChecker<CObjRoot>::GetInstance().push_back(this);
+}
+
+CObjRoot::~CObjRoot(void)
+{
+ CMemoryLeakChecker<CObjRoot>::GetInstance().remove(this);
+}
+
+class CIdentity : public CObjRoot
+{
+public:
+ CIdentity(void);
+ CIdentity(const string&);
+ CIdentity(const CIdentity&);
+
+ bool operator < (const CIdentity&) const;
+ friend istream& operator >> (istream&, CIdentity&);
+
+ static const string::size_type s_nIdStrLen;
+
+protected:
+ ulonglong_t m_ullId[2];
+};
+
+const string::size_type CIdentity::s_nIdStrLen = 36;
+
+CIdentity::CIdentity(void)
+{
+ memset(m_ullId, 0, sizeof(m_ullId));
+}
+
+CIdentity::CIdentity(const string& strId)
+{
+ if (strId.length() != CIdentity::s_nIdStrLen ||
+ strId[8] != '-' ||
+ strId[13] != '-' ||
+ strId[18] != '-' ||
+ strId[23] != '-')
+ throw runtime_error(
+ __FUNCTION__ ": Error GUID format " + strId);
+
+ string strIdCopy(strId);
+ strIdCopy.erase(23, 1);
+ strIdCopy[18] = ' ';
+ strIdCopy.erase(13, 1);
+ strIdCopy.erase(8, 1);
+
+ istringstream is(strIdCopy);
+ is >> hex >> m_ullId[0] >> m_ullId[1];
+ if (!is)
+ throw runtime_error(
+ __FUNCTION__ ": GUID contains invalid characters" + strId);
+}
+
+CIdentity::CIdentity(const CIdentity& idRight)
+{
+ memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId));
+}
+
+bool CIdentity::operator < (const CIdentity& idRight) const
+{
+ return memcmp(m_ullId, idRight.m_ullId, sizeof(m_ullId)) < 0;
+}
+
+istream& operator >> (istream& is, CIdentity& idRight)
+{
+ string strId;
+ is >> strId;
+ if (!!is)
+ idRight = CIdentity(strId);
+ return is;
+}
+
+class CInputFile : public CObjRoot
+{
+protected:
+ CInputFile(const string&);
+ CInputFile(istream&);
+ istream& GetLine(string&);
+
+private:
+ CInputFile(const CInputFile&);
+ CInputFile& operator = (const CInputFile&);
+
+private:
+ auto_ptr<istream> m_pIs;
+
+protected:
+ istream& m_is;
+};
+
+CInputFile::CInputFile(const string& strFName)
+: m_pIs(new ifstream(strFName.c_str()))
+, m_is(*m_pIs)
+{
+ if (!m_is)
+ throw runtime_error(__FUNCTION__ ": Error opening input file " + strFName);
+}
+
+CInputFile::CInputFile(istream& is)
+: m_is(is)
+{
+ if (!m_is)
+ throw runtime_error(__FUNCTION__ ": Error opening input stream");
+}
+
+istream& CInputFile::GetLine(string& strALine)
+{
+ if (!!m_is)
+ while (!!getline(m_is, strALine))
+ {
+ string::size_type pos = strALine.find_last_not_of(' ');
+ if (pos != string::npos)
+ {
+ strALine.erase(pos + 1);
+ strALine.erase(0, strALine.find_first_not_of(' '));
+ break;
+ }
+ }
+ return m_is;
+}
+
+class CIdAddressMap : public CInputFile, public map<CIdentity, ulonglong_t>
+{
+public:
+ CIdAddressMap(istream&);
+};
+
+CIdAddressMap::CIdAddressMap(istream& is)
+: CInputFile(is)
+{
+ CIdentity id;
+ ulonglong_t ullBase;
+
+ while (!!(m_is >> hex >> id >> ullBase))
+ if (!insert(value_type(id, ullBase)).second)
+ throw runtime_error(__FUNCTION__ ": Duplicated files");
+}
+
+class CIdPathMap : public CInputFile, public map<CIdentity, string>
+{
+public:
+ CIdPathMap(istream&);
+};
+
+CIdPathMap::CIdPathMap(istream& is)
+: CInputFile(is)
+{
+ static const char cszFileSec[] = "[files]";
+ static const char cszFfsFile[] = "EFI_FILE_NAME";
+
+ string strALine;
+
+ // Find the [files] section
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszFileSec) - 1, cszFileSec));
+
+ // m_is error means no FFS files listed in this INF file
+ if (!m_is)
+ return;
+
+ // Parse FFS files one by one
+ while (!!GetLine(strALine))
+ {
+ // Test if this begins a new section
+ if (strALine[0] == '[')
+ break;
+
+ // Is it a line of FFS file?
+ if (strALine.compare(0, sizeof(cszFfsFile) - 1, cszFfsFile))
+ continue;
+
+ string::size_type pos = strALine.find_first_not_of(' ', sizeof(cszFfsFile) - 1);
+ if (pos == string::npos || strALine[pos] != '=')
+ throw runtime_error(__FUNCTION__ ": Invalid FV INF format");
+ pos = strALine.find_first_not_of(' ', pos + 1);
+ if (pos == string::npos)
+ throw runtime_error(__FUNCTION__ ": Incomplete line");
+
+ strALine.erase(0, pos);
+ pos = strALine.rfind('\\');
+ if (pos == string::npos)
+ pos = 0;
+ else pos++;
+
+ CIdentity id(strALine.substr(pos, CIdentity::s_nIdStrLen));
+ if (!insert(value_type(id, strALine)).second)
+ throw runtime_error(__FUNCTION__ ": Duplicated FFS files");
+ }
+}
+
+class CSymbol : public CObjRoot
+{
+public:
+ string m_strAddress;
+ string m_strName;
+ ulonglong_t m_ullRva;
+ string m_strFrom;
+ bool m_bStatic;
+ bool m_bFunction;
+
+ CSymbol()
+ {
+ }
+ CSymbol(const string&, bool = false);
+ friend ostream& operator << (ostream&, const CSymbol&);
+};
+
+CSymbol::CSymbol(const string& strALine, bool bStatic)
+: m_bStatic(bStatic)
+{
+ istringstream is(strALine);
+
+ is >> m_strAddress >> m_strName >> hex >> m_ullRva >> m_strFrom;
+ if (m_strFrom == "F" || m_strFrom == "f")
+ {
+ m_bFunction = true;
+ is >> m_strFrom;
+ } else m_bFunction = false;
+}
+
+ostream& operator << (ostream& os, const CSymbol& symbol)
+{
+ os << hex << setw(16) << setfill('0') << symbol.m_ullRva << setw(0);
+ os << ' ' << (symbol.m_bFunction ? 'F' : ' ')
+ << (symbol.m_bStatic ? 'S' : ' ') << ' ';
+ return os << symbol.m_strName << endl;
+}
+
+class CMapFile : public CInputFile, public list<CSymbol>
+{
+public:
+ CMapFile(const string&);
+
+ void SetLoadAddress(ulonglong_t);
+ friend ostream& operator << (ostream&, const CMapFile&);
+
+ string m_strModuleName;
+ ulonglong_t m_ullLoadAddr;
+ string m_strEntryPoint;
+};
+
+CMapFile::CMapFile(const string& strFName)
+: CInputFile(strFName)
+{
+ static const char cszLoadAddr[] = "Preferred load address is";
+ static const char cszGlobal[] = "Address";
+ static const char cszEntryPoint[] = "entry point at";
+ static const char cszStatic[] = "Static symbols";
+
+ string strALine;
+
+ GetLine(m_strModuleName);
+
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszLoadAddr) - 1, cszLoadAddr));
+ if (!m_is)
+ throw runtime_error(__FUNCTION__ ": Load Address not listed in map file");
+
+ istringstream is(strALine.substr(sizeof(cszLoadAddr) - 1));
+ if (!(is >> hex >> m_ullLoadAddr))
+ throw runtime_error(__FUNCTION__ ": Unexpected Load Address format");
+
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszGlobal) - 1, cszGlobal));
+ if (!m_is)
+ throw runtime_error(__FUNCTION__ ": Global symbols not found in map file");
+
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszEntryPoint) - 1, cszEntryPoint))
+ push_back(CSymbol(strALine));
+ if (!m_is)
+ throw runtime_error(__FUNCTION__ ": Entry Point not listed in map file");
+
+ is.str(strALine.substr(strALine.find_first_not_of(' ', sizeof(cszEntryPoint) - 1)));
+ is.clear();
+ if (!getline(is, m_strEntryPoint))
+ throw runtime_error(__FUNCTION__ ": Unexpected Entry Point format");
+
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszStatic) - 1, cszStatic));
+ while (!!GetLine(strALine))
+ push_back(CSymbol(strALine, true));
+}
+
+void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr)
+{
+ for (iterator i = begin(); i != end(); i++)
+ if (i->m_ullRva != 0)
+ i->m_ullRva += ullLoadAddr - m_ullLoadAddr;
+ m_ullLoadAddr = ullLoadAddr;
+}
+
+ostream& operator << (ostream& os, const CMapFile& mapFile)
+{
+ CMapFile::const_iterator i = mapFile.begin();
+ while (i != mapFile.end() && i->m_strAddress != mapFile.m_strEntryPoint)
+ i++;
+ if (i == mapFile.end())
+ throw runtime_error(
+ __FUNCTION__ ": Entry point not found for module " +
+ mapFile.m_strModuleName);
+
+ os << endl << hex
+ << mapFile.m_strModuleName << " (EP=" << i->m_ullRva
+ << ", BA=" << mapFile.m_ullLoadAddr << ')' << endl
+ << endl;
+
+ for (i = mapFile.begin(); i != mapFile.end(); i++)
+ os << " " << *i;
+
+ return os << endl;
+}
+
+class COutputFile : public CObjRoot
+{
+protected:
+ COutputFile(ostream&);
+ ostream& m_os;
+
+private:
+ COutputFile(const COutputFile&);
+ COutputFile& operator = (const COutputFile&);
+};
+
+class CFvMapFile : public CObjRoot, public map<CIdentity, CMapFile*>
+{
+public:
+ CFvMapFile(const CIdAddressMap&, const CIdPathMap&);
+ ~CFvMapFile(void);
+
+ friend ostream& operator << (ostream&, const CFvMapFile&);
+
+private:
+ void Cleanup(void);
+};
+
+CFvMapFile::CFvMapFile(const CIdAddressMap& idAddr, const CIdPathMap& idPath)
+{
+ for (CIdAddressMap::const_iterator i = idAddr.begin(); i != idAddr.end(); i++)
+ {
+ CIdPathMap::const_iterator j = idPath.find(i->first);
+ if (j == idPath.end())
+ throw runtime_error(__FUNCTION__ ": Map file not found");
+
+ try
+ {
+ pair<iterator, bool> k = insert(value_type(i->first,
+ new CMapFile(j->second.substr(0, j->second.rfind('.')) + ".map")));
+ if (!k.second)
+ throw logic_error(__FUNCTION__ ": Duplicated file found in rebase log");
+
+ k.first->second->SetLoadAddress(i->second);
+ }
+ catch (const runtime_error& e)
+ {
+ cerr << e.what() << endl;
+ }
+ }
+}
+
+void CFvMapFile::Cleanup(void)
+{
+ for (iterator i = begin(); i != end(); i++)
+ delete i->second;
+}
+
+ostream& operator << (ostream& os, const CFvMapFile& fvMap)
+{
+ for (CFvMapFile::const_iterator i = fvMap.begin(); !!os && i != fvMap.end(); i++)
+ os << *i->second;
+ return os;
+}
+
+CFvMapFile::~CFvMapFile(void)
+{
+ Cleanup();
+}
+
+class CGenFvMapUsage : public invalid_argument
+{
+public:
+ CGenFvMapUsage(void) : invalid_argument(s_szUsage)
+ {
+ }
+
+private:
+ static const char s_szUsage[];
+};
+
+const char CGenFvMapUsage::s_szUsage[] = "Usage: GenFvMap <LOG> <INF> <MAP>";
+
+class CGenFvMapApp : public CObjRoot
+{
+public:
+ CGenFvMapApp(int, char *[]);
+ ~CGenFvMapApp(void);
+
+ int Run(void);
+
+private:
+ int m_cArgc;
+ char **m_ppszArgv;
+};
+
+CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[])
+: m_cArgc(cArgc)
+, m_ppszArgv(ppszArgv)
+{
+ if (cArgc != 4)
+ throw CGenFvMapUsage();
+}
+
+CGenFvMapApp::~CGenFvMapApp(void)
+{
+}
+
+int CGenFvMapApp::Run(void)
+{
+ ifstream isLog(m_ppszArgv[1]);
+ ifstream isInf(m_ppszArgv[2]);
+
+ CIdAddressMap idAddress(isLog);
+ CIdPathMap idPath(isInf);
+
+ CFvMapFile fvMap(idAddress, idPath);
+
+ ofstream osMap(m_ppszArgv[3], ios_base::out | ios_base::trunc);
+ osMap << fvMap;
+
+ if (!osMap)
+ throw runtime_error(__FUNCTION__ ": Error writing output file");
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ try
+ {
+ CGenFvMapApp app(argc, argv);
+ return app.Run();
+ }
+ catch (const exception& e)
+ {
+ cerr << e.what() << endl;
+ return -1;
+ }
+}
diff --git a/Tools/CCode/Source/GenFvMap/build.xml b/Tools/CCode/Source/GenFvMap/build.xml
new file mode 100644
index 0000000..6c236bf
--- /dev/null
+++ b/Tools/CCode/Source/GenFvMap/build.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenTEImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenFvMap"/>
+ <property name="FileSet" value="*.cpp"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <compilerarg value="/EHsc" unless="GCC"/>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>