## @file # PreBuild operations for Vlv2TbltDevicePkg # # Copyright (c) 2019, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # ''' PreBuild ''' import os import sys import argparse import subprocess import glob import shutil import struct import datetime # # Globals for help information # __prog__ = 'PreBuild' __copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' __description__ = 'Vlv2Tbl2DevicePkg pre-build operations.\n' # # Globals # gWorkspace = '' gBaseToolsPath = '' gArgs = None def LogAlways(Message): sys.stdout.write (__prog__ + ': ' + Message + '\n') sys.stdout.flush() def Log(Message): global gArgs if not gArgs.Verbose: return sys.stdout.write (__prog__ + ': ' + Message + '\n') sys.stdout.flush() def Error(Message, ExitValue=1): sys.stderr.write (__prog__ + ': ERROR: ' + Message + '\n') sys.exit (ExitValue) def RelativePath(target): global gWorkspace Log('RelativePath' + target) return os.path.relpath (target, gWorkspace) def NormalizePath(target): if isinstance(target, tuple): return os.path.normpath (os.path.join (*target)) else: return os.path.normpath (target) def RemoveFile(target): target = NormalizePath(target) if not target or target == os.pathsep: Error ('RemoveFile() invalid target') if os.path.exists(target): os.remove (target) Log ('remove %s' % (RelativePath (target))) def RemoveDirectory(target): target = NormalizePath(target) if not target or target == os.pathsep: Error ('RemoveDirectory() invalid target') if os.path.exists(target): Log ('rmdir %s' % (RelativePath (target))) shutil.rmtree(target) def CreateDirectory(target): target = NormalizePath(target) if not os.path.exists(target): Log ('mkdir %s' % (RelativePath (target))) os.makedirs (target) def Copy(src, dst): src = NormalizePath(src) dst = NormalizePath(dst) for File in glob.glob(src): Log ('copy %s -> %s' % (RelativePath (File), RelativePath (dst))) shutil.copy (File, dst) def GenCapsuleDevice (BaseName, PayloadFileName, Guid, Version, Lsv, CapsulesPath, CapsulesSubDir): global gBaseToolsPath LogAlways ('Generate Capsule: {0} {1:08x} {2:08x} {3}'.format (Guid, Version, Lsv, PayloadFileName)) VersionString = '.'.join([str(ord(x)) for x in struct.pack('>I', Version).decode()]) FmpCapsuleFile = NormalizePath ((CapsulesPath, CapsulesSubDir, BaseName + '.' + VersionString + '.cap')) Command = GenerateCapsuleCommand.format ( FMP_CAPSULE_GUID = Guid, FMP_CAPSULE_VERSION = Version, FMP_CAPSULE_LSV = Lsv, BASE_TOOLS_PATH = gBaseToolsPath, FMP_CAPSULE_FILE = FmpCapsuleFile, FMP_CAPSULE_PAYLOAD = PayloadFileName ) Command = ' '.join(Command.splitlines()).strip() if gArgs.Verbose: Command = Command + ' -v' Log (Command) Process = subprocess.Popen(Command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) ProcessOutput = Process.communicate() if Process.returncode == 0: Log (ProcessOutput[0].decode()) else: LogAlways (Command) LogAlways (ProcessOutput[0].decode()) Error ('GenerateCapsule returned an error') Copy (PayloadFileName, (CapsulesPath, 'firmware.bin')) MetaInfoXml = MetaInfoXmlTemplate MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_GUID', Guid) MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_BASE_NAME', BaseName) MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_VERSION_DECIMAL', str(Version)) MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_STRING', VersionString) MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_DATE', str(datetime.date.today())) f = open (NormalizePath ((CapsulesPath, 'firmware.metainfo.xml')), 'w') f.write(MetaInfoXml) f.close() f = open (NormalizePath ((CapsulesPath, 'Lvfs.ddf')), 'w') f.write(LvfsDdfTemplate) f.close() if sys.platform == "win32": Command = 'makecab /f ' + NormalizePath ((CapsulesPath, 'Lvfs.ddf')) else: Command = 'gcab --create firmware.cab firmware.bin firmware.metainfo.xml' Log (Command) Process = subprocess.Popen(Command, cwd=CapsulesPath, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) ProcessOutput = Process.communicate() if Process.returncode == 0: Log (ProcessOutput[0].decode()) else: LogAlways (Command) LogAlways (ProcessOutput[0].decode()) Error ('GenerateCapsule returned an error') FmpCabinetFile = NormalizePath ((CapsulesPath, CapsulesSubDir, BaseName + '.' + VersionString + '.cab')) Copy ((CapsulesPath, 'firmware.cab'), FmpCabinetFile) RemoveFile ((CapsulesPath, 'firmware.cab')) RemoveFile ((CapsulesPath, 'setup.inf')) RemoveFile ((CapsulesPath, 'setup.rpt')) RemoveFile ((CapsulesPath, 'Lvfs.ddf')) RemoveFile ((CapsulesPath, 'firmware.metainfo.xml')) RemoveFile ((CapsulesPath, 'firmware.bin')) BiosIdTemplate = ''' BOARD_ID = MNW2MAX BOARD_REV = $BOARD_REV BOARD_EXT = $ARCH VERSION_MAJOR = 0090 BUILD_TYPE = $BUILD_TYPE VERSION_MINOR = 01 ''' if __name__ == '__main__': # # Create command line argument parser object # parser = argparse.ArgumentParser ( prog = __prog__, description = __description__ + __copyright__, conflict_handler = 'resolve' ) parser.add_argument ( '-a', '--arch', dest = 'Arch', nargs = '+', action = 'append', required = True, help = '''ARCHS is one of list: IA32, X64, IPF, ARM, AARCH64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.''' ) parser.add_argument ( '-t', '--tagname', dest = 'ToolChain', required = True, help = '''Using the Tool Chain Tagname to build the platform, overriding target.txt's TOOL_CHAIN_TAG definition.''' ) parser.add_argument ( '-p', '--platform', dest = 'PlatformFile', required = True, help = '''Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.''' ) parser.add_argument ( '-b', '--buildtarget', dest = 'BuildTarget', required = True, help = '''Using the TARGET to build the platform, overriding target.txt's TARGET definition.''' ) parser.add_argument ( '--conf=', dest = 'ConfDirectory', required = True, help = '''Specify the customized Conf directory.''' ) parser.add_argument ( '-D', '--define', dest = 'Define', nargs='*', action = 'append', help = '''Macro: "Name [= Value]".''' ) parser.add_argument ( '-v', '--verbose', dest = 'Verbose', action = 'store_true', help = '''Turn on verbose output with informational messages printed''' ) parser.add_argument ( '--package', dest = 'Package', nargs = '*', action = 'append', help = '''The directory name of a package of tests to copy''' ) # # Parse command line arguments # gArgs, remaining = parser.parse_known_args() gArgs.BuildType = 'all' for BuildType in ['all', 'fds', 'genc', 'genmake', 'clean', 'cleanall', 'modules', 'libraries', 'run']: if BuildType in remaining: gArgs.BuildType = BuildType remaining.remove(BuildType) break gArgs.Remaining = ' '.join(remaining) # # Get WORKSPACE environment variable # try: gWorkspace = os.environ['WORKSPACE'] except: Error ('WORKSPACE environment variable not set') # # Get PACKAGES_PATH and generate prioritized list of paths # PathList = [gWorkspace] try: PathList += os.environ['PACKAGES_PATH'].split(os.pathsep) except: pass # # Determine full path to BaseTools # Vlv2Tbl2DevicePkgPath = '' for Path in PathList: if gBaseToolsPath == '': if os.path.exists (os.path.join (Path, 'BaseTools')): gBaseToolsPath = os.path.join (Path, 'BaseTools') if Vlv2Tbl2DevicePkgPath == '': if os.path.exists (os.path.join (Path, 'Vlv2TbltDevicePkg')): Vlv2Tbl2DevicePkgPath = os.path.join (Path, 'Vlv2TbltDevicePkg') if gBaseToolsPath == '': Error ('Can not find BaseTools in WORKSPACE or PACKAGES_PATH') if Vlv2Tbl2DevicePkgPath == '': Error ('Can not find Vlv2Tbl2DevicePkg in WORKSPACE or PACKAGES_PATH') # # Parse OUTPUT_DIRECTORY from DSC file # for Path in PathList: if os.path.exists (os.path.join (Path, gArgs.PlatformFile)): Dsc = open (os.path.join (Path, gArgs.PlatformFile), 'r').readlines() break for Line in Dsc: if Line.strip().startswith('OUTPUT_DIRECTORY'): OutputDirectory = Line.strip().split('=')[1].strip() break # # Determine full paths to EDK II build directory, EDK II build output # directory and the CPU arch of the UEFI phase. # CommandDir = os.path.dirname(sys.argv[0]) EdkiiBuildDir = os.path.join (gWorkspace, OutputDirectory) EdkiiBuildOutput = os.path.join (EdkiiBuildDir, gArgs.BuildTarget + '_' + gArgs.ToolChain) UefiArch = gArgs.Arch[0][0] if len (gArgs.Arch) > 1: if ['X64'] in gArgs.Arch: UefiArch = 'X64' if gArgs.BuildType == 'run': Error ("'run' target not supported") if gArgs.BuildType == 'clean': sys.exit (0) # # Create output directories to put BiosId files # try: CreateDirectory ((gWorkspace, 'Build')) except: pass try: CreateDirectory ((EdkiiBuildDir)) except: pass try: CreateDirectory ((EdkiiBuildOutput)) except: pass # # Generate BiosId files # BiosId = BiosIdTemplate if sys.platform == "win32": # Built from a Windows Host OS BiosId = BiosId.replace ('$BOARD_REV', 'W') else: # Built from a Linux/Unix/Mac Host OS BiosId = BiosId.replace ('$BOARD_REV', 'L') if UefiArch == 'X64': BiosId = BiosId.replace ('$ARCH', 'X64') else: BiosId = BiosId.replace ('$ARCH', 'I32') BiosId = BiosId.replace ('$BUILD_TYPE', gArgs.BuildTarget[0]) BiosIdFileName = NormalizePath ((EdkiiBuildOutput, 'BiosId.env')) f = open (BiosIdFileName, 'w') f.write(BiosId) f.close() Command = 'python ' + NormalizePath ((Vlv2Tbl2DevicePkgPath, '../Tools/GenBiosId/GenBiosId.py')) Command = Command + ' -i ' + BiosIdFileName Command = Command + ' -o ' + NormalizePath ((EdkiiBuildOutput, 'BiosId.bin')) Command = Command + ' -ot ' + NormalizePath ((EdkiiBuildOutput, 'BiosId.txt')) LogAlways (Command) Process = subprocess.Popen(Command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) ProcessOutput = Process.communicate() if Process.returncode == 0: Log (ProcessOutput[0].decode()) else: LogAlways (Command) LogAlways (ProcessOutput[0].decode()) Error ('GenBiosId returned an error')