| #!/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 | |