git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10502 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.<BR>
 | |
| # 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
 | |
|     
 |