diff options
author | Yonghong Zhu <yonghong.zhu@intel.com> | 2016-08-15 13:52:12 +0800 |
---|---|---|
committer | Yonghong Zhu <yonghong.zhu@intel.com> | 2016-08-19 15:37:59 +0800 |
commit | 91ae2988c62f03987fe02159d26b001a5201d812 (patch) | |
tree | 91d5acf87f9d24b2a0a32face10cfb1f71935122 /BaseTools | |
parent | 9b98c4164013845ba80befd66fd38ce827a4c034 (diff) | |
download | edk2-platforms-91ae2988c62f03987fe02159d26b001a5201d812.tar.xz |
BaseTools: FMP capsule add the support to generate auth info
Current BaseTools cannot generate EFI_FIRMWARE_IMAGE_AUTHENTICATION
for FMP capsule. this patch fix it by FDF spec's update to add the
definition for CERTIFICATE_GUID and MONOTONIC_COUNT. BaseTools call
the tool by CERTIFICATE_GUID to generate the certdata and fill the header
info.
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Diffstat (limited to 'BaseTools')
-rw-r--r-- | BaseTools/Source/Python/GenFds/Capsule.py | 80 | ||||
-rw-r--r-- | BaseTools/Source/Python/GenFds/CapsuleData.py | 4 | ||||
-rw-r--r-- | BaseTools/Source/Python/GenFds/FdfParser.py | 64 | ||||
-rw-r--r-- | BaseTools/Source/Python/GenFds/GenFds.py | 59 | ||||
-rw-r--r-- | BaseTools/Source/Python/GenFds/GuidSection.py | 59 |
5 files changed, 194 insertions, 72 deletions
diff --git a/BaseTools/Source/Python/GenFds/Capsule.py b/BaseTools/Source/Python/GenFds/Capsule.py index 1683433e43..f8af12a7c2 100644 --- a/BaseTools/Source/Python/GenFds/Capsule.py +++ b/BaseTools/Source/Python/GenFds/Capsule.py @@ -1,7 +1,7 @@ ## @file
# generate capsule
#
-# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2016, 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
@@ -25,9 +25,16 @@ from GenFds import GenFds from Common.Misc import PackRegistryFormatGuid
import uuid
from struct import pack
+from GenFds import FindExtendTool
+from Common import EdkLogger
+from Common.BuildToolError import *
T_CHAR_LF = '\n'
+WIN_CERT_REVISION = 0x0200
+WIN_CERT_TYPE_EFI_GUID = 0x0EF1
+EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')
+EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}')
## create inf file describes what goes into capsule and call GenFv to generate capsule
#
@@ -98,6 +105,32 @@ class Capsule (CapsuleClassObject) : FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))
FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))
+ #
+ # typedef struct _WIN_CERTIFICATE {
+ # UINT32 dwLength;
+ # UINT16 wRevision;
+ # UINT16 wCertificateType;
+ # //UINT8 bCertificate[ANYSIZE_ARRAY];
+ # } WIN_CERTIFICATE;
+ #
+ # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
+ # WIN_CERTIFICATE Hdr;
+ # EFI_GUID CertType;
+ # //UINT8 CertData[ANYSIZE_ARRAY];
+ # } WIN_CERTIFICATE_UEFI_GUID;
+ #
+ # typedef struct {
+ # UINT64 MonotonicCount;
+ # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+ # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
+ #
+ # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
+ # EFI_GUID HashType;
+ # UINT8 PublicKey[256];
+ # UINT8 Signature[256];
+ # } EFI_CERT_BLOCK_RSA_2048_SHA256;
+ #
+
PreSize = FwMgrHdrSize
Content = StringIO.StringIO()
for driver in self.CapsuleDataList:
@@ -108,10 +141,47 @@ class Capsule (CapsuleClassObject) : Content.write(File.read())
File.close()
for fmp in self.FmpPayloadList:
- payload = fmp.GenCapsuleSubItem()
- FwMgrHdr.write(pack('=Q', PreSize))
- PreSize += len(payload)
- Content.write(payload)
+ if fmp.Certificate_Guid:
+ ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)
+ CmdOption = ''
+ CapInputFile = fmp.ImageFile
+ if not os.path.isabs(fmp.ImageFile):
+ CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)
+ CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'
+ if ExternalTool == None:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)
+ else:
+ CmdOption += ExternalTool
+ if ExternalOption:
+ CmdOption = CmdOption + ' ' + ExternalOption
+ CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile
+ CmdList = CmdOption.split()
+ GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")
+ if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:
+ dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)
+ else:
+ dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256
+ Buffer = pack('Q', fmp.MonotonicCount)
+ Buffer += pack('I', dwLength)
+ Buffer += pack('H', WIN_CERT_REVISION)
+ Buffer += pack('H', WIN_CERT_TYPE_EFI_GUID)
+ Buffer += uuid.UUID(fmp.Certificate_Guid).get_bytes_le()
+ if os.path.exists(CapOutputTmp):
+ TmpFile = open(CapOutputTmp, 'rb')
+ Buffer += TmpFile.read()
+ TmpFile.close()
+ if fmp.VendorCodeFile:
+ VendorFile = open(fmp.VendorCodeFile, 'rb')
+ Buffer += VendorFile.read()
+ VendorFile.close()
+ FwMgrHdr.write(pack('=Q', PreSize))
+ PreSize += len(Buffer)
+ Content.write(Buffer)
+ else:
+ payload = fmp.GenCapsuleSubItem()
+ FwMgrHdr.write(pack('=Q', PreSize))
+ PreSize += len(payload)
+ Content.write(payload)
BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())
Header.write(pack('=I', HdrSize + BodySize))
#
diff --git a/BaseTools/Source/Python/GenFds/CapsuleData.py b/BaseTools/Source/Python/GenFds/CapsuleData.py index efc281222b..2a5c4545de 100644 --- a/BaseTools/Source/Python/GenFds/CapsuleData.py +++ b/BaseTools/Source/Python/GenFds/CapsuleData.py @@ -1,7 +1,7 @@ ## @file
# generate capsule
#
-# Copyright (c) 2007-2013, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007-2016, 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
@@ -180,6 +180,8 @@ class CapsulePayload(CapsuleData): self.HardwareInstance = None
self.ImageFile = None
self.VendorCodeFile = None
+ self.Certificate_Guid = None
+ self.MonotonicCount = None
def GenCapsuleSubItem(self):
if not self.Version:
diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py index 8709cfc091..02ae7c9f9c 100644 --- a/BaseTools/Source/Python/GenFds/FdfParser.py +++ b/BaseTools/Source/Python/GenFds/FdfParser.py @@ -52,11 +52,13 @@ import Common.GlobalData as GlobalData from Common.Expression import *
from Common import GlobalData
from Common.String import ReplaceMacro
-
+import uuid
from Common.Misc import tdict
import Common.LongFilePathOs as os
from Common.LongFilePathSupport import OpenLongFilePath as open
+from Capsule import EFI_CERT_TYPE_PKCS7_GUID
+from Capsule import EFI_CERT_TYPE_RSA2048_SHA256_GUID
##define T_CHAR_SPACE ' '
##define T_CHAR_NULL '\0'
@@ -1124,6 +1126,26 @@ class FdfParser: self.__UndoToken()
return False
+ def __Verify(self, Name, Value, Scope):
+ if Scope in ['UINT64', 'UINT8']:
+ ValueNumber = 0
+ try:
+ if Value.upper().startswith('0X'):
+ ValueNumber = int (Value, 16)
+ else:
+ ValueNumber = int (Value)
+ except:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)
+ if ValueNumber < 0:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)
+ if Scope == 'UINT64':
+ if ValueNumber >= 0x10000000000000000:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
+ if Scope == 'UINT8':
+ if ValueNumber >= 0x100:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
+ return True
+
## __UndoToken() method
#
# Go back one token unit in file buffer
@@ -3187,7 +3209,7 @@ class FdfParser: if not self.__GetNextToken():
raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)
- FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE']
+ FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']
while self.__Token in FmpKeyList:
Name = self.__Token
FmpKeyList.remove(Name)
@@ -3195,32 +3217,58 @@ class FdfParser: raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
if Name == 'IMAGE_TYPE_ID':
if not self.__GetNextGuid():
- raise Warning("expected GUID value for IMAGE_TYPE_ID", self.FileName, self.CurrentLineNumber)
+ raise Warning("expected GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)
FmpData.ImageTypeId = self.__Token
+ elif Name == 'CERTIFICATE_GUID':
+ if not self.__GetNextGuid():
+ raise Warning("expected GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
+ FmpData.Certificate_Guid = self.__Token
+ if uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:
+ raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
else:
if not self.__GetNextToken():
raise Warning("expected value of %s" % Name, self.FileName, self.CurrentLineNumber)
Value = self.__Token
if Name == 'IMAGE_HEADER_INIT_VERSION':
- FmpData.Version = Value
+ if self.__Verify(Name, Value, 'UINT8'):
+ FmpData.Version = Value
elif Name == 'IMAGE_INDEX':
- FmpData.ImageIndex = Value
+ if self.__Verify(Name, Value, 'UINT8'):
+ FmpData.ImageIndex = Value
elif Name == 'HARDWARE_INSTANCE':
- FmpData.HardwareInstance = Value
+ if self.__Verify(Name, Value, 'UINT8'):
+ FmpData.HardwareInstance = Value
+ elif Name == 'MONOTONIC_COUNT':
+ if self.__Verify(Name, Value, 'UINT64'):
+ FmpData.MonotonicCount = Value
+ if FmpData.MonotonicCount.upper().startswith('0X'):
+ FmpData.MonotonicCount = (long)(FmpData.MonotonicCount, 16)
+ else:
+ FmpData.MonotonicCount = (long)(FmpData.MonotonicCount)
if not self.__GetNextToken():
break
else:
self.__UndoToken()
+ if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")
+ # remove CERTIFICATE_GUID and MONOTONIC_COUNT from FmpKeyList, since these keys are optional
+ if 'CERTIFICATE_GUID' in FmpKeyList:
+ FmpKeyList.remove('CERTIFICATE_GUID')
+ if 'MONOTONIC_COUNT' in FmpKeyList:
+ FmpKeyList.remove('MONOTONIC_COUNT')
if FmpKeyList:
- raise Warning("Missing keywords %s in FMP payload section" % ', '.join(FmpKeyList), self.FileName, self.CurrentLineNumber)
+ raise Warning("Missing keywords %s in FMP payload section." % ', '.join(FmpKeyList), self.FileName, self.CurrentLineNumber)
ImageFile = self.__ParseRawFileStatement()
if not ImageFile:
- raise Warning("Missing image file in FMP payload section", self.FileName, self.CurrentLineNumber)
+ raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)
FmpData.ImageFile = ImageFile
VendorCodeFile = self.__ParseRawFileStatement()
if VendorCodeFile:
FmpData.VendorCodeFile = VendorCodeFile
+ AdditionalFile = self.__ParseRawFileStatement()
+ if AdditionalFile:
+ raise Warning("At most one Image file and one Vendor code file are allowed in FMP payload section.", self.FileName, self.CurrentLineNumber)
self.Profile.FmpPayloadDict[FmpUiName] = FmpData
return True
diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py index f2de47ea83..c2e9418b84 100644 --- a/BaseTools/Source/Python/GenFds/GenFds.py +++ b/BaseTools/Source/Python/GenFds/GenFds.py @@ -415,7 +415,64 @@ def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Val Value = '0'
return Value
-
+## FindExtendTool()
+#
+# Find location of tools to process data
+#
+# @param KeyStringList Filter for inputs of section generation
+# @param CurrentArchList Arch list
+# @param NameGuid The Guid name
+#
+def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
+ # if user not specify filter, try to deduce it from global data.
+ if KeyStringList == None or KeyStringList == []:
+ Target = GenFdsGlobalVariable.TargetName
+ ToolChain = GenFdsGlobalVariable.ToolChainTag
+ ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase
+ if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
+ KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]
+ for Arch in CurrentArchList:
+ if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
+ KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
+
+ if GenFdsGlobalVariable.GuidToolDefinition:
+ if NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys():
+ return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
+
+ ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
+ ToolPathTmp = None
+ ToolOption = None
+ for ToolDef in ToolDefinition.items():
+ if NameGuid == ToolDef[1]:
+ KeyList = ToolDef[0].split('_')
+ Key = KeyList[0] + \
+ '_' + \
+ KeyList[1] + \
+ '_' + \
+ KeyList[2]
+ if Key in KeyStringList and KeyList[4] == 'GUID':
+
+ ToolPath = ToolDefinition.get(Key + \
+ '_' + \
+ KeyList[3] + \
+ '_' + \
+ 'PATH')
+
+ ToolOption = ToolDefinition.get(Key + \
+ '_' + \
+ KeyList[3] + \
+ '_' + \
+ 'FLAGS')
+ if ToolPathTmp == None:
+ ToolPathTmp = ToolPath
+ else:
+ if ToolPathTmp != ToolPath:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
+
+ GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
+ return ToolPathTmp, ToolOption
+
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
diff --git a/BaseTools/Source/Python/GenFds/GuidSection.py b/BaseTools/Source/Python/GenFds/GuidSection.py index ac5ae585f9..f199dcd2cc 100644 --- a/BaseTools/Source/Python/GenFds/GuidSection.py +++ b/BaseTools/Source/Python/GenFds/GuidSection.py @@ -27,6 +27,7 @@ from Common import EdkLogger from Common.BuildToolError import *
from FvImageSection import FvImageSection
from Common.LongFilePathSupport import OpenLongFilePath as open
+from GenFds import FindExtendTool
## generate GUIDed section
#
@@ -128,7 +129,7 @@ class GuidSection(GuidSectionClassObject) : ExternalTool = None
ExternalOption = None
if self.NameGuid != None:
- ExternalTool, ExternalOption = self.__FindExtendTool__()
+ ExternalTool, ExternalOption = FindExtendTool(self.KeyStringList, self.CurrentArchList, self.NameGuid)
#
# If not have GUID , call default
@@ -249,61 +250,5 @@ class GuidSection(GuidSectionClassObject) : self.ProcessRequired = "TRUE"
return OutputFileList, self.Alignment
- ## __FindExtendTool()
- #
- # Find location of tools to process section data
- #
- # @param self The object pointer
- #
- def __FindExtendTool__(self):
- # if user not specify filter, try to deduce it from global data.
- if self.KeyStringList == None or self.KeyStringList == []:
- Target = GenFdsGlobalVariable.TargetName
- ToolChain = GenFdsGlobalVariable.ToolChainTag
- ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase
- if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
- EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
- self.KeyStringList = [Target + '_' + ToolChain + '_' + self.CurrentArchList[0]]
- for Arch in self.CurrentArchList:
- if Target + '_' + ToolChain + '_' + Arch not in self.KeyStringList:
- self.KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
-
- if GenFdsGlobalVariable.GuidToolDefinition:
- if self.NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys():
- return GenFdsGlobalVariable.GuidToolDefinition[self.NameGuid]
-
- ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
- ToolPathTmp = None
- ToolOption = None
- for ToolDef in ToolDefinition.items():
- if self.NameGuid == ToolDef[1]:
- KeyList = ToolDef[0].split('_')
- Key = KeyList[0] + \
- '_' + \
- KeyList[1] + \
- '_' + \
- KeyList[2]
- if Key in self.KeyStringList and KeyList[4] == 'GUID':
-
- ToolPath = ToolDefinition.get(Key + \
- '_' + \
- KeyList[3] + \
- '_' + \
- 'PATH')
-
- ToolOption = ToolDefinition.get(Key + \
- '_' + \
- KeyList[3] + \
- '_' + \
- 'FLAGS')
- if ToolPathTmp == None:
- ToolPathTmp = ToolPath
- else:
- if ToolPathTmp != ToolPath:
- EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
-
- GenFdsGlobalVariable.GuidToolDefinition[self.NameGuid] = (ToolPathTmp, ToolOption)
- return ToolPathTmp, ToolOption
-
|