## @file
# Generate capsules for Vlv2TbltDevicePkg
# openssl must be install and in path
#
# Copyright (c) 2019, Intel Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
'''
GenCapsuleAll
'''
import os
import sys
import argparse
import subprocess
import glob
import shutil
import struct
import datetime
#
# Globals for help information
#
__prog__ = 'GenCapsuleAll'
__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.'
__description__ = 'Generate Vlv2Tbl2DevicePkg capsules.\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)
GenerateCapsuleCommand = '''
GenerateCapsule
--encode
--guid {FMP_CAPSULE_GUID}
--fw-version {FMP_CAPSULE_VERSION}
--lsv {FMP_CAPSULE_LSV}
--capflag PersistAcrossReset
--capflag InitiateReset
--signer-private-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestCert.pem
--other-public-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestSub.pub.pem
--trusted-public-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestRoot.pub.pem
-o {FMP_CAPSULE_FILE}
{FMP_CAPSULE_PAYLOAD}
'''
MetaInfoXmlTemplate = '''
com.intel.FMP_CAPSULE_BASE_NAME.firmware
FMP_CAPSULE_BASE_NAME
System firmware for the FMP_CAPSULE_BASE_NAME
Description of System firmware for the FMP_CAPSULE_BASE_NAME
FMP_CAPSULE_GUID
http://www.tianocore.org
CC0-1.0
BSD
Tianocore
Build FMP_CAPSULE_STRING
'''
LvfsDdfTemplate = '''
.OPTION EXPLICIT ; Generate errors on variable typos
.Set CabinetNameTemplate=firmware.cab ; The name of the file
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set Cabinet=on ;
.Set Compress=on ;
.Set DiskDirectory1=.
.Set MaxDiskSize=99999744 ; multiple of 512
;*** Files to zip ;
;
firmware.bin
firmware.metainfo.xml
;***
'''
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'))
def GenCapsuleSampleDevice (SampleDeviceName, Guid, Version, Lsv, CapsulesPath, CapsulesSubDir):
BinaryPayload = SampleDeviceName.encode() + bytearray(0x18 - len (SampleDeviceName.encode()))
BinaryPayload = BinaryPayload + struct.pack(' 1:
if ['X64'] in gArgs.Arch:
UefiArch = 'X64'
CapsulesPath = NormalizePath((EdkiiBuildDir, 'Capsules'))
CapsulesSubDir = 'TestCert' + '_' + UefiArch + '_' + gArgs.BuildTarget + '_' + gArgs.ToolChain
#
# Create output directories
#
try:
CreateDirectory ((CapsulesPath))
except:
pass
try:
CreateDirectory ((CapsulesPath, CapsulesSubDir))
except:
pass
#
# Copy CapsuleApp
#
Copy ((EdkiiBuildOutput, UefiArch, 'CapsuleApp.efi'), (CapsulesPath, CapsulesSubDir))
#
# Generate capsules for the Red Sample Device
#
GenCapsuleSampleDevice('Red','72e2945a-00da-448e-9aa7-075ad840f9d4',0x00000010,0x00000000, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Red','72e2945a-00da-448e-9aa7-075ad840f9d4',0x00000011,0x00000000, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Red','72e2945a-00da-448e-9aa7-075ad840f9d4',0x00000012,0x00000000, CapsulesPath, CapsulesSubDir)
#
# Generate capsules for the Green Sample Device
#
GenCapsuleSampleDevice('Green','79179bfd-704d-4c90-9e02-0ab8d968c18a',0x00000020,0x00000020, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Green','79179bfd-704d-4c90-9e02-0ab8d968c18a',0x00000021,0x00000020, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Green','79179bfd-704d-4c90-9e02-0ab8d968c18a',0x00000022,0x00000020, CapsulesPath, CapsulesSubDir)
#
# Generate capsules for the Blue Sample Device
#
GenCapsuleSampleDevice('Blue','149da854-7d19-4faa-a91e-862ea1324be6',0x00000010,0x00000000, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Blue','149da854-7d19-4faa-a91e-862ea1324be6',0x00000011,0x00000000, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Blue','149da854-7d19-4faa-a91e-862ea1324be6',0x00000012,0x00000012, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Blue','149da854-7d19-4faa-a91e-862ea1324be6',0x00000013,0x00000012, CapsulesPath, CapsulesSubDir)
GenCapsuleSampleDevice('Blue','149da854-7d19-4faa-a91e-862ea1324be6',0x00000014,0x00000012, CapsulesPath, CapsulesSubDir)
#
# Generate capsules for Minnow Max Firmware Updates
#
RomFileName = os.path.join (EdkiiBuildOutput, 'FV', 'VLV.fd')
GenCapsuleDevice('MinnowMax', RomFileName,'4096267b-da0a-42eb-b5eb-fef31d207cb4',0x0000000C,0x00000000, CapsulesPath, CapsulesSubDir)