git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			370 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			370 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python
 | 
						|
#
 | 
						|
#
 | 
						|
# Copyright (c) 2007, 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.
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Import Modules
 | 
						|
#
 | 
						|
import re, os, glob
 | 
						|
from Common.XmlRoutines import  *
 | 
						|
 | 
						|
#"ModuleType"=>(PackageGuid, headerFileName) List
 | 
						|
HeaderFiles = {}
 | 
						|
GuidList = []
 | 
						|
GuidMap = {}
 | 
						|
HeaderFileContents = {}
 | 
						|
gTest = {}
 | 
						|
GuidMacro2CName = {}
 | 
						|
GuidAliasList = []
 | 
						|
 | 
						|
def collectIncludeFolder(pkgDirName, guidType, pkgName):
 | 
						|
    includeFolder = os.path.join(pkgDirName, "Include", guidType)
 | 
						|
    if os.path.exists(includeFolder) and os.path.isdir(includeFolder):
 | 
						|
        for headerFileName in os.listdir(includeFolder):
 | 
						|
            if headerFileName[-2:] == ".h":
 | 
						|
                headerFile = open(os.path.join(includeFolder, headerFileName))
 | 
						|
                HeaderFileContents[(guidType, headerFileName, pkgName)] = headerFile.read()
 | 
						|
                headerFile.close()
 | 
						|
 | 
						|
GuidMacroReg = re.compile(r"\b(?!EFI_GUID\b)[A-Z0-9_]+_GUID\b")
 | 
						|
GuidCNameReg = re.compile(r"\bg\w+Guid\b")
 | 
						|
GuidAliasReg = re.compile(r"#define\s+([A-Z0-9_]+_GUID)\s+([A-Z0-9_]+_GUID)\b")
 | 
						|
 | 
						|
def collectPackageInfo(spdFileName):
 | 
						|
    pkgDirName = os.path.dirname(spdFileName)
 | 
						|
 | 
						|
    spd = XmlParseFile(spdFileName)
 | 
						|
 | 
						|
    pkgName = XmlElement(spd, "/PackageSurfaceArea/SpdHeader/PackageName")
 | 
						|
    pkgGuid = XmlElement(spd, "/PackageSurfaceArea/SpdHeader/GuidValue")
 | 
						|
 | 
						|
    
 | 
						|
    for IncludePkgHeader in XmlList(spd, "/PackageSurfaceArea/PackageHeaders/IncludePkgHeader"):
 | 
						|
        moduleType = XmlAttribute(IncludePkgHeader, "ModuleType")
 | 
						|
        headerFilePath = XmlElementData(IncludePkgHeader)
 | 
						|
        headerFilePath = re.sub("Include/", "", headerFilePath, 1)
 | 
						|
 | 
						|
        headerTuple = HeaderFiles.get(moduleType, [])
 | 
						|
        headerTuple.append((pkgGuid, headerFilePath))
 | 
						|
        HeaderFiles[moduleType] = headerTuple
 | 
						|
        
 | 
						|
    guidTypes = ["Guid", "Protocol", "Ppi"]
 | 
						|
 | 
						|
    for guidType in guidTypes:
 | 
						|
        for guidEntry in XmlList(spd, "/PackageSurfaceArea/" + guidType + "Declarations/Entry"):
 | 
						|
            guidCName = XmlElement(guidEntry, "Entry/C_Name")
 | 
						|
            GuidList.append(guidCName)
 | 
						|
                      
 | 
						|
        collectIncludeFolder(pkgDirName, guidType, pkgName)   
 | 
						|
 | 
						|
    for DecFile in glob.glob(os.path.join(pkgDirName, "*.dec")):
 | 
						|
        fileContents = open(DecFile).read()
 | 
						|
        for GuidCNameMatch in GuidCNameReg.finditer(fileContents):
 | 
						|
            GuidCName = GuidCNameMatch.group(0)
 | 
						|
            if GuidCName not in GuidList:
 | 
						|
                GuidList.append(GuidCName)
 | 
						|
 | 
						|
def AddGuidMacro2GuidCName(GuidMacros, GuidCNames):
 | 
						|
   for GuidMacro in GuidMacros:
 | 
						|
       GuessGuidCName = "g" + GuidMacro.lower().title().replace("_", "")
 | 
						|
       if GuessGuidCName in GuidCNames:
 | 
						|
           GuidMacro2CName[GuidMacro] = GuessGuidCName
 | 
						|
       elif len(GuidCNames) == 1:
 | 
						|
           GuidMacro2CName[GuidMacro] = GuidCNames[0]
 | 
						|
       else:
 | 
						|
           for GuidCName in GuidCNames:
 | 
						|
               if GuidCName.lower() == GuessGuidCName.lower():
 | 
						|
                   GuidMacro2CName[GuidMacro] = GuidCName
 | 
						|
                   break
 | 
						|
           else:
 | 
						|
               pass
 | 
						|
               #print "No matching GuidMacro %s" % GuidMacro
 | 
						|
               
 | 
						|
 | 
						|
def TranslateGuid(GuidMacroMatch):
 | 
						|
    GuidMacro = GuidMacroMatch.group(0)
 | 
						|
    return GuidMacro2CName.get(GuidMacro, GuidMacro)
 | 
						|
 | 
						|
DepexReg = re.compile(r"DEPENDENCY_START(.*?)DEPENDENCY_END", re.DOTALL)
 | 
						|
 | 
						|
def TranslateDpxSection(fileContents):
 | 
						|
    DepexMatch = DepexReg.search(fileContents)
 | 
						|
    if not DepexMatch:
 | 
						|
        return "", []
 | 
						|
    
 | 
						|
    fileContents = DepexMatch.group(1)
 | 
						|
    fileContents = re.sub(r"\s+", " ", fileContents).strip()
 | 
						|
    fileContents = GuidMacroReg.sub(TranslateGuid, fileContents)
 | 
						|
    return fileContents, GuidMacroReg.findall(fileContents)
 | 
						|
 | 
						|
def InitializeAutoGen(workspace, db):
 | 
						|
    
 | 
						|
    
 | 
						|
    for spdFile in XmlList(db, "/FrameworkDatabase/PackageList/Filename"):
 | 
						|
        spdFileName = XmlElementData(spdFile)
 | 
						|
        collectPackageInfo(os.path.join(workspace, spdFileName))
 | 
						|
 | 
						|
 | 
						|
    BlockCommentReg = re.compile(r"/\*.*?\*/", re.DOTALL)
 | 
						|
    LineCommentReg = re.compile(r"//.*")
 | 
						|
    GuidReg = re.compile(r"\b(" + '|'.join(GuidList) + r")\b")
 | 
						|
 | 
						|
    for headerFile in HeaderFileContents:
 | 
						|
        Contents = HeaderFileContents[headerFile]
 | 
						|
        Contents = BlockCommentReg.sub("", Contents)
 | 
						|
        Contents = LineCommentReg.sub("", Contents)
 | 
						|
        
 | 
						|
        FoundGuids = GuidReg.findall(Contents)
 | 
						|
        for FoundGuid in FoundGuids:
 | 
						|
            GuidMap[FoundGuid] = "%s/%s" % (headerFile[0], headerFile[1])
 | 
						|
            #print "%-40s %s/%s" % (FoundGuid, headerFile[0], headerFile[1])
 | 
						|
 | 
						|
        GuidMacros = GuidMacroReg.findall(Contents)
 | 
						|
        GuidCNames = GuidCNameReg.findall(Contents)
 | 
						|
        
 | 
						|
        for GuidAliasMatch in  GuidAliasReg.finditer(Contents):
 | 
						|
            Name1, Name2 = GuidAliasMatch.group(1), GuidAliasMatch.group(2)
 | 
						|
            GuidAliasList.append((Name1, Name2))
 | 
						|
 | 
						|
        AddGuidMacro2GuidCName(GuidMacros, GuidCNames)
 | 
						|
 | 
						|
def AddSystemIncludeStatement(moduleType, PackageList):
 | 
						|
    IncludeStatement = "\n"
 | 
						|
 | 
						|
    headerList = HeaderFiles.get(moduleType, [])
 | 
						|
 | 
						|
    for pkgGuid in PackageList:
 | 
						|
        
 | 
						|
        for pkgTuple in headerList:
 | 
						|
            if pkgTuple[0] == pkgGuid:
 | 
						|
                IncludeStatement += "#include <%s>\n" % pkgTuple[1]
 | 
						|
 | 
						|
    return IncludeStatement
 | 
						|
        
 | 
						|
    
 | 
						|
def AddLibraryClassStatement(LibraryClassList):
 | 
						|
    IncludeStatement = "\n"
 | 
						|
    for LibraryClass in LibraryClassList:
 | 
						|
        IncludeStatement += "#include <Library/%s.h>\n" % LibraryClass
 | 
						|
 | 
						|
    return IncludeStatement
 | 
						|
 | 
						|
def AddGuidStatement(GuidList):
 | 
						|
    IncludeStatement = "\n"
 | 
						|
    GuidIncludeSet = {}
 | 
						|
    for Guid in GuidList:
 | 
						|
        if Guid in GuidMap:
 | 
						|
            GuidIncludeSet[GuidMap[Guid]] = 1
 | 
						|
        else:
 | 
						|
            print "GUID CName: %s cannot be found in any public header file" % Guid
 | 
						|
 | 
						|
    for GuidInclude in GuidIncludeSet:
 | 
						|
        IncludeStatement += "#include <%s>\n" % GuidInclude
 | 
						|
 | 
						|
    return IncludeStatement
 | 
						|
 | 
						|
DriverBindingMap = {
 | 
						|
    "gEfiDriverBindingProtocolGuid" : "EFI_DRIVER_BINDING_PROTOCOL",
 | 
						|
    "gEfiComponentNameProtocolGuid" : "EFI_COMPONENT_NAME_PROTOCOL",
 | 
						|
    "gEfiDriverConfigurationProtocolGuid" : "EFI_DRIVER_CONFIGURATION_PROTOCOL",
 | 
						|
    "gEfiDriverDiagnosticProtocolGuid" : "EFI_DRIVER_CONFIGURATION_PROTOCOL"
 | 
						|
    }
 | 
						|
 | 
						|
def AddDriverBindingProtocolStatement(AutoGenDriverModel):
 | 
						|
    InstallStatement   = "\n"
 | 
						|
    DBindingHandle     = "ImageHandle"
 | 
						|
    GlobalDeclaration  = "\n"
 | 
						|
    
 | 
						|
    
 | 
						|
    for DriverModelItem in AutoGenDriverModel:
 | 
						|
        
 | 
						|
        if DriverModelItem[1] == "NULL" and DriverModelItem[2] == "NULL" and DriverModelItem[3] == "NULL":
 | 
						|
            InstallStatement += "  Status = EfiLibInstallDriverBinding (\n"
 | 
						|
            InstallStatement += "             ImageHandle,\n"
 | 
						|
            InstallStatement += "             SystemTable,\n"
 | 
						|
            InstallStatement += "             %s,\n" % DriverModelItem[0]
 | 
						|
            InstallStatement += "             %s\n" % DBindingHandle
 | 
						|
            InstallStatement += "             );\n"
 | 
						|
        else:
 | 
						|
            InstallStatement += "  Status = EfiLibInstallAllDriverProtocols (\n"
 | 
						|
            InstallStatement += "             ImageHandle,\n"
 | 
						|
            InstallStatement += "             SystemTable,\n"
 | 
						|
            InstallStatement += "             %s,\n" % DriverModelItem[0]
 | 
						|
            InstallStatement += "             %s,\n" % DBindingHandle
 | 
						|
            InstallStatement += "             %s,\n" % DriverModelItem[1]
 | 
						|
            InstallStatement += "             %s,\n" % DriverModelItem[2]
 | 
						|
            InstallStatement += "             %s\n" % DriverModelItem[3]
 | 
						|
            InstallStatement += "             );\n"
 | 
						|
 | 
						|
        InstallStatement += "  ASSERT_EFI_ERROR (Status);\n\n"
 | 
						|
            
 | 
						|
        GlobalDeclaration += "extern EFI_DRIVER_BINDING_PROTOCOL %s;\n" % DriverModelItem[0][1:]
 | 
						|
        if (DriverModelItem[1] != "NULL"):
 | 
						|
            GlobalDeclaration += "extern EFI_COMPONENT_NAME_PROTOCOL %s;\n" % DriverModelItem[1][1:]
 | 
						|
        if (DriverModelItem[2] != "NULL"):
 | 
						|
            GlobalDeclaration += "extern EFI_DRIVER_CONFIGURATION_PROTOCOL %s;\n" % DriverModelItem[2][1:]
 | 
						|
        if (DriverModelItem[3] != "NULL"):
 | 
						|
            GlobalDeclaration += "extern EFI_DRIVER_CONFIGURATION_PROTOCOL %s;\n" % DriverModelItem[3][1:]
 | 
						|
 | 
						|
        DBindingHandle = "NULL"
 | 
						|
         
 | 
						|
    return (InstallStatement, "", "", GlobalDeclaration)
 | 
						|
 | 
						|
EventDeclarationTemplate = """
 | 
						|
//
 | 
						|
// Declaration for callback Event.
 | 
						|
//
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
%s (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  );
 | 
						|
"""
 | 
						|
 | 
						|
def AddBootServiceEventStatement(EventList):
 | 
						|
    FinalEvent = ""
 | 
						|
    if len(EventList) > 1:
 | 
						|
        
 | 
						|
        print "Current prototype does not support multi boot service event"
 | 
						|
    else:
 | 
						|
        FinalEvent       = EventList[0]
 | 
						|
    
 | 
						|
    CreateStatement  = "\n"
 | 
						|
    CreateStatement += "  Status = gBS->CreateEvent (\n"
 | 
						|
    CreateStatement += "                  EVT_SIGNAL_EXIT_BOOT_SERVICES,\n"
 | 
						|
    CreateStatement += "                  EFI_TPL_NOTIFY,\n"
 | 
						|
    CreateStatement += "                  " + FinalEvent + ",\n"
 | 
						|
    CreateStatement += "                  NULL,\n"
 | 
						|
    CreateStatement += "                  &mExitBootServicesEvent\n"
 | 
						|
    CreateStatement += "                  );\n"
 | 
						|
    CreateStatement += "  ASSERT_EFI_ERROR (Status);\n"
 | 
						|
 | 
						|
    GlobalDefinition  = "\n"
 | 
						|
    GlobalDefinition += "STATIC EFI_EVENT mExitBootServicesEvent = NULL;\n"
 | 
						|
 | 
						|
    GlobalDeclaration = EventDeclarationTemplate % FinalEvent
 | 
						|
    
 | 
						|
    DestroyStatement  = "\n"
 | 
						|
    DestroyStatement += "  Status = gBS->CloseEvent (mExitBootServicesEvent);\n"
 | 
						|
    DestroyStatement += "  ASSERT_EFI_ERROR (Status);\n"
 | 
						|
    return (CreateStatement, "", GlobalDefinition, GlobalDeclaration)
 | 
						|
 | 
						|
def AddVirtualAddressEventStatement(EventList):
 | 
						|
    FinalEvent = ""
 | 
						|
    if len(EventList) > 1:
 | 
						|
        print "Current prototype does not support multi virtual address change event"
 | 
						|
    else:
 | 
						|
        FinalEvent       = EventList[0]
 | 
						|
    
 | 
						|
    CreateStatement  = "\n"
 | 
						|
 | 
						|
    CreateStatement += "  Status = gBS->CreateEvent (\n"
 | 
						|
    CreateStatement += "                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\n"
 | 
						|
    CreateStatement += "                  TPL_NOTIFY,\n"
 | 
						|
    CreateStatement += "                  " + FinalEvent + ",\n"
 | 
						|
    CreateStatement += "                  NULL,\n"
 | 
						|
    CreateStatement += "                  &mVirtualAddressChangedEvent\n"
 | 
						|
    CreateStatement += "                  );\n"
 | 
						|
    CreateStatement += "  ASSERT_EFI_ERROR (Status);\n"
 | 
						|
 | 
						|
    GlobalDefinition  = "\n"
 | 
						|
    GlobalDefinition += "STATIC EFI_EVENT mVirtualAddressChangedEvent = NULL;\n"
 | 
						|
    
 | 
						|
    GlobalDeclaration = EventDeclarationTemplate % FinalEvent
 | 
						|
 | 
						|
    DestroyStatement  = "\n"
 | 
						|
    DestroyStatement += "  Status = gBS->CloseEvent (mVirtualAddressChangedEvent);\n"
 | 
						|
    DestroyStatement += "  ASSERT_EFI_ERROR (Status);\n"
 | 
						|
    
 | 
						|
    return (CreateStatement, "", GlobalDefinition, GlobalDeclaration)
 | 
						|
    
 | 
						|
 | 
						|
EntryPointDeclarationTemplate = """
 | 
						|
//
 | 
						|
// Declaration for original Entry Point. 
 | 
						|
//
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
%s (
 | 
						|
  IN EFI_HANDLE           ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE     *SystemTable
 | 
						|
  );
 | 
						|
"""
 | 
						|
    
 | 
						|
EntryPointHeader = r"""
 | 
						|
/**
 | 
						|
  The user Entry Point for module %s. The user code starts with this function.
 | 
						|
 | 
						|
  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
 | 
						|
  @param[in] SystemTable    A pointer to the EFI System Table.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS       The entry point is executed successfully.
 | 
						|
  @retval other             Some error occurs when executing this entry point.
 | 
						|
 | 
						|
**/
 | 
						|
"""
 | 
						|
def AddNewEntryPointContentsStatement (moduleName, EntryPoint, InstallStatement = ""):
 | 
						|
    if EntryPoint != "Initialize%s" % moduleName:
 | 
						|
        NewEntryPoint = "Initialize%s" % moduleName
 | 
						|
    else:
 | 
						|
        NewEntryPoint = "NewInitialize%s" % moduleName
 | 
						|
 | 
						|
    EntryPointContents  = EntryPointHeader % moduleName
 | 
						|
    EntryPointContents += "EFI_STATUS\n"
 | 
						|
    EntryPointContents += "EFIAPI\n"
 | 
						|
    EntryPointContents += NewEntryPoint + "(\n"
 | 
						|
    EntryPointContents += "  IN EFI_HANDLE           ImageHandle,\n"
 | 
						|
    EntryPointContents += "  IN EFI_SYSTEM_TABLE     *SystemTable\n"
 | 
						|
    EntryPointContents += "  )\n"
 | 
						|
    EntryPointContents += "{\n"
 | 
						|
    EntryPointContents += "  EFI_STATUS              Status;\n"
 | 
						|
    EntryPointContents += InstallStatement + "\n"
 | 
						|
    GlobalDeclaration   = ""
 | 
						|
 | 
						|
    if EntryPoint != "":
 | 
						|
        EntryPointContents += "  //\n  // Call the original Entry Point\n  //\n"
 | 
						|
        EntryPointContents += "  Status = %s (ImageHandle, SystemTable);\n\n" % EntryPoint
 | 
						|
        GlobalDeclaration  += EntryPointDeclarationTemplate % EntryPoint
 | 
						|
 | 
						|
    EntryPointContents += "  return Status;\n"
 | 
						|
    EntryPointContents += "}\n"
 | 
						|
 | 
						|
    return (NewEntryPoint, EntryPointContents, GlobalDeclaration)
 | 
						|
 | 
						|
reFileHeader = re.compile(r"^\s*/\*.*?\*/\s*", re.DOTALL)
 | 
						|
reNext       = re.compile(r"#ifndef\s*(\w+)\s*#define\s*\1\s*")
 | 
						|
 | 
						|
def AddCommonInclusionStatement(fileContents, includeStatement):
 | 
						|
    if includeStatement in fileContents:
 | 
						|
        return fileContents
 | 
						|
 | 
						|
    insertPos       = 0
 | 
						|
    matchFileHeader = reFileHeader.search(fileContents)
 | 
						|
    if matchFileHeader:
 | 
						|
        insertPos = matchFileHeader.end()
 | 
						|
 | 
						|
    matchFileHeader = reNext.search(fileContents, insertPos)
 | 
						|
    if matchFileHeader:
 | 
						|
        insertPos = matchFileHeader.end()
 | 
						|
                          
 | 
						|
    includeStatement = "\n%s\n\n" % includeStatement 
 | 
						|
    fileContents = fileContents[0:insertPos] + includeStatement + fileContents[insertPos:] 
 | 
						|
    return fileContents 
 | 
						|
 | 
						|
# This acts like the main() function for the script, unless it is 'import'ed into another
 | 
						|
# script.
 | 
						|
if __name__ == '__main__':
 | 
						|
 | 
						|
    pass
 | 
						|
    
 |