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