+ def ConvertJsonValue (Config, FieldName, Convert, Required = True, Default = None, Open = False):\r
+ if FieldName not in Config:\r
+ if Required:\r
+ print ('GenerateCapsule: error: Payload descriptor invalid syntax. Could not find {Key} in payload descriptor.'.format(Key = FieldName))\r
+ sys.exit (1)\r
+ return Default\r
+ try:\r
+ Value = Convert (Config[FieldName])\r
+ except:\r
+ print ('GenerateCapsule: error: {Key} in payload descriptor has invalid syntax.'.format (Key = FieldName))\r
+ sys.exit (1)\r
+ if Open:\r
+ try:\r
+ Value = open (Value, "rb")\r
+ except:\r
+ print ('GenerateCapsule: error: can not open file {File}'.format (File = FieldName))\r
+ sys.exit (1)\r
+ return Value\r
+\r
+ def DecodeJsonFileParse (Json):\r
+ if 'Payloads' not in Json:\r
+ print ('GenerateCapsule: error "Payloads" section not found in JSON file {File}'.format (File = args.JsonFile.name))\r
+ sys.exit (1)\r
+ for Config in Json['Payloads']:\r
+ #\r
+ # Parse fields from JSON\r
+ #\r
+ PayloadFile = ConvertJsonValue (Config, 'Payload', os.path.expandvars, Required = False)\r
+ Guid = ConvertJsonValue (Config, 'Guid', ValidateRegistryFormatGuid, Required = False)\r
+ FwVersion = ConvertJsonValue (Config, 'FwVersion', ValidateUnsignedInteger, Required = False)\r
+ LowestSupportedVersion = ConvertJsonValue (Config, 'LowestSupportedVersion', ValidateUnsignedInteger, Required = False)\r
+ HardwareInstance = ConvertJsonValue (Config, 'HardwareInstance', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ MonotonicCount = ConvertJsonValue (Config, 'MonotonicCount', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ SignToolPfxFile = ConvertJsonValue (Config, 'SignToolPfxFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslSignerPrivateCertFile = ConvertJsonValue (Config, 'OpenSslSignerPrivateCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslOtherPublicCertFile = ConvertJsonValue (Config, 'OpenSslOtherPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslTrustedPublicCertFile = ConvertJsonValue (Config, 'OpenSslTrustedPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ SigningToolPath = ConvertJsonValue (Config, 'SigningToolPath', os.path.expandvars, Required = False, Default = None)\r
+ UpdateImageIndex = ConvertJsonValue (Config, 'UpdateImageIndex', ValidateUnsignedInteger, Required = False, Default = 1)\r
+\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ PayloadFile,\r
+ Guid,\r
+ FwVersion,\r
+ LowestSupportedVersion,\r
+ MonotonicCount,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ SignToolPfxFile,\r
+ OpenSslSignerPrivateCertFile,\r
+ OpenSslOtherPublicCertFile,\r
+ OpenSslTrustedPublicCertFile,\r
+ SigningToolPath\r
+ ))\r
+\r
+ def EncodeJsonFileParse (Json):\r
+ if 'EmbeddedDrivers' not in Json:\r
+ print ('GenerateCapsule: warning "EmbeddedDrivers" section not found in JSON file {File}'.format (File = args.JsonFile.name))\r
+ else:\r
+ for Config in Json['EmbeddedDrivers']:\r
+ EmbeddedDriverFile = ConvertJsonValue(Config, 'Driver', os.path.expandvars, Open = True)\r
+ #\r
+ #Read EmbeddedDriver file\r
+ #\r
+ try:\r
+ if args.Verbose:\r
+ print ('Read EmbeddedDriver file {File}'.format (File = EmbeddedDriverFile.name))\r
+ Driver = EmbeddedDriverFile.read()\r
+ except:\r
+ print ('GenerateCapsule: error: can not read EmbeddedDriver file {File}'.format (File = EmbeddedDriverFile.name))\r
+ sys.exit (1)\r
+ EmbeddedDriverDescriptorList.append (Driver)\r
+\r
+ if 'Payloads' not in Json:\r
+ print ('GenerateCapsule: error: "Payloads" section not found in JSON file {File}'.format (File = args.JsonFile.name))\r
+ sys.exit (1)\r
+ for Config in Json['Payloads']:\r
+ #\r
+ # Parse fields from JSON\r
+ #\r
+ PayloadFile = ConvertJsonValue (Config, 'Payload', os.path.expandvars, Open = True)\r
+ Guid = ConvertJsonValue (Config, 'Guid', ValidateRegistryFormatGuid)\r
+ FwVersion = ConvertJsonValue (Config, 'FwVersion', ValidateUnsignedInteger)\r
+ LowestSupportedVersion = ConvertJsonValue (Config, 'LowestSupportedVersion', ValidateUnsignedInteger)\r
+ HardwareInstance = ConvertJsonValue (Config, 'HardwareInstance', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ UpdateImageIndex = ConvertJsonValue (Config, 'UpdateImageIndex', ValidateUnsignedInteger, Required = False, Default = 1)\r
+ MonotonicCount = ConvertJsonValue (Config, 'MonotonicCount', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ SignToolPfxFile = ConvertJsonValue (Config, 'SignToolPfxFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslSignerPrivateCertFile = ConvertJsonValue (Config, 'OpenSslSignerPrivateCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslOtherPublicCertFile = ConvertJsonValue (Config, 'OpenSslOtherPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslTrustedPublicCertFile = ConvertJsonValue (Config, 'OpenSslTrustedPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ SigningToolPath = ConvertJsonValue (Config, 'SigningToolPath', os.path.expandvars, Required = False, Default = None)\r
+\r
+ #\r
+ # Read binary input file\r
+ #\r
+ try:\r
+ if args.Verbose:\r
+ print ('Read binary input file {File}'.format (File = PayloadFile.name))\r
+ Payload = PayloadFile.read()\r
+ PayloadFile.close ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = PayloadFile.name))\r
+ sys.exit (1)\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ Payload,\r
+ Guid,\r
+ FwVersion,\r
+ LowestSupportedVersion,\r
+ MonotonicCount,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ SignToolPfxFile,\r
+ OpenSslSignerPrivateCertFile,\r
+ OpenSslOtherPublicCertFile,\r
+ OpenSslTrustedPublicCertFile,\r
+ SigningToolPath\r
+ ))\r
+\r
+ def GenerateOutputJson (PayloadJsonDescriptorList):\r
+ PayloadJson = {\r
+ "Payloads" : [\r
+ {\r
+ "Guid": str(PayloadDescriptor.Guid).upper(),\r
+ "FwVersion": str(PayloadDescriptor.FwVersion),\r
+ "LowestSupportedVersion": str(PayloadDescriptor.LowestSupportedVersion),\r
+ "MonotonicCount": str(PayloadDescriptor.MonotonicCount),\r
+ "Payload": PayloadDescriptor.Payload,\r
+ "HardwareInstance": str(PayloadDescriptor.HardwareInstance),\r
+ "UpdateImageIndex": str(PayloadDescriptor.UpdateImageIndex),\r
+ "SignToolPfxFile": str(PayloadDescriptor.SignToolPfxFile),\r
+ "OpenSslSignerPrivateCertFile": str(PayloadDescriptor.OpenSslSignerPrivateCertFile),\r
+ "OpenSslOtherPublicCertFile": str(PayloadDescriptor.OpenSslOtherPublicCertFile),\r
+ "OpenSslTrustedPublicCertFile": str(PayloadDescriptor.OpenSslTrustedPublicCertFile),\r
+ "SigningToolPath": str(PayloadDescriptor.SigningToolPath)\r
+ }for PayloadDescriptor in PayloadJsonDescriptorList\r
+ ]\r
+ }\r
+ OutputJsonFile = args.OutputFile.name + '.json'\r
+ if 'Payloads' in PayloadJson:\r
+ PayloadSection = PayloadJson ['Payloads']\r
+ Index = 0\r
+ for PayloadField in PayloadSection:\r
+ if PayloadJsonDescriptorList[Index].SignToolPfxFile is None:\r
+ del PayloadField ['SignToolPfxFile']\r
+ if PayloadJsonDescriptorList[Index].OpenSslSignerPrivateCertFile is None:\r
+ del PayloadField ['OpenSslSignerPrivateCertFile']\r
+ if PayloadJsonDescriptorList[Index].OpenSslOtherPublicCertFile is None:\r
+ del PayloadField ['OpenSslOtherPublicCertFile']\r
+ if PayloadJsonDescriptorList[Index].OpenSslTrustedPublicCertFile is None:\r
+ del PayloadField ['OpenSslTrustedPublicCertFile']\r
+ if PayloadJsonDescriptorList[Index].SigningToolPath is None:\r
+ del PayloadField ['SigningToolPath']\r
+ Index = Index + 1\r
+ Result = json.dumps (PayloadJson, indent=4, sort_keys=True, separators=(',', ': '))\r
+ with open (OutputJsonFile, 'w') as OutputFile:\r
+ OutputFile.write (Result)\r
+\r
+ def CheckArgumentConflict (args):\r
+ if args.Encode:\r
+ if args.InputFile:\r
+ print ('GenerateCapsule: error: Argument InputFile conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.EmbeddedDriver:\r
+ print ('GenerateCapsule: error: Argument --embedded-driver conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.Guid:\r
+ print ('GenerateCapsule: error: Argument --guid conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.FwVersion:\r
+ print ('GenerateCapsule: error: Argument --fw-version conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.LowestSupportedVersion:\r
+ print ('GenerateCapsule: error: Argument --lsv conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.MonotonicCount:\r
+ print ('GenerateCapsule: error: Argument --monotonic-count conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.HardwareInstance:\r
+ print ('GenerateCapsule: error: Argument --hardware-instance conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.SignToolPfxFile:\r
+ print ('GenerateCapsule: error: Argument --pfx-file conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.OpenSslSignerPrivateCertFile:\r
+ print ('GenerateCapsule: error: Argument --signer-private-cert conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.OpenSslOtherPublicCertFile:\r
+ print ('GenerateCapsule: error: Argument --other-public-cert conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.OpenSslTrustedPublicCertFile:\r
+ print ('GenerateCapsule: error: Argument --trusted-public-cert conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.SigningToolPath:\r
+ print ('GenerateCapsule: error: Argument --signing-tool-path conflicts with Argument -j')\r
+ sys.exit (1)\r
+\r
+ class PayloadDescriptor (object):\r
+ def __init__(self,\r
+ Payload,\r
+ Guid,\r
+ FwVersion,\r
+ LowestSupportedVersion,\r
+ MonotonicCount = 0,\r
+ HardwareInstance = 0,\r
+ UpdateImageIndex = 1,\r
+ SignToolPfxFile = None,\r
+ OpenSslSignerPrivateCertFile = None,\r
+ OpenSslOtherPublicCertFile = None,\r
+ OpenSslTrustedPublicCertFile = None,\r
+ SigningToolPath = None\r
+ ):\r
+ self.Payload = Payload\r
+ self.Guid = Guid\r
+ self.FwVersion = FwVersion\r
+ self.LowestSupportedVersion = LowestSupportedVersion\r
+ self.MonotonicCount = MonotonicCount\r
+ self.HardwareInstance = HardwareInstance\r
+ self.UpdateImageIndex = UpdateImageIndex\r
+ self.SignToolPfxFile = SignToolPfxFile\r
+ self.OpenSslSignerPrivateCertFile = OpenSslSignerPrivateCertFile\r
+ self.OpenSslOtherPublicCertFile = OpenSslOtherPublicCertFile\r
+ self.OpenSslTrustedPublicCertFile = OpenSslTrustedPublicCertFile\r
+ self.SigningToolPath = SigningToolPath\r
+\r
+ self.UseSignTool = self.SignToolPfxFile is not None\r
+ self.UseOpenSsl = (self.OpenSslSignerPrivateCertFile is not None and\r
+ self.OpenSslOtherPublicCertFile is not None and\r
+ self.OpenSslTrustedPublicCertFile is not None)\r
+ self.AnyOpenSsl = (self.OpenSslSignerPrivateCertFile is not None or\r
+ self.OpenSslOtherPublicCertFile is not None or\r
+ self.OpenSslTrustedPublicCertFile is not None)\r
+\r
+ def Validate(self, args):\r
+ if self.UseSignTool and self.AnyOpenSsl:\r
+ raise argparse.ArgumentTypeError ('Providing both signtool and OpenSSL options is not supported')\r
+ if not self.UseSignTool and not self.UseOpenSsl and self.AnyOpenSsl:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('the following JSON fields are required for OpenSSL: OpenSslSignerPrivateCertFile, OpenSslOtherPublicCertFile, OpenSslTrustedPublicCertFile')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')\r
+ if self.UseSignTool and platform.system() != 'Windows':\r
+ raise argparse.ArgumentTypeError ('Use of signtool is not supported on this operating system.')\r
+ if args.Encode:\r
+ if self.FwVersion is None or self.LowestSupportedVersion is None:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('the following JSON fields are required: FwVersion, LowestSupportedVersion')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('the following options are required: --fw-version, --lsv')\r
+ if self.FwVersion > 0xFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field FwVersion must be an integer in range 0x0..0xffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--fw-version must be an integer in range 0x0..0xffffffff')\r
+ if self.LowestSupportedVersion > 0xFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field LowestSupportedVersion must be an integer in range 0x0..0xffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--lsv must be an integer in range 0x0..0xffffffff')\r
+\r
+ if args.Encode:\r
+ if self.Guid is None:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('the following JSON field is required: Guid')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('the following option is required: --guid')\r
+ if self.HardwareInstance > 0xFFFFFFFFFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field HardwareInstance must be an integer in range 0x0..0xffffffffffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--hardware-instance must be an integer in range 0x0..0xffffffffffffffff')\r
+ if self.MonotonicCount > 0xFFFFFFFFFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field MonotonicCount must be an integer in range 0x0..0xffffffffffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--monotonic-count must be an integer in range 0x0..0xffffffffffffffff')\r
+ if self.UpdateImageIndex >0xFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field UpdateImageIndex must be an integer in range 0x0..0xff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--update-image-index must be an integer in range 0x0..0xff')\r
+\r
+ if self.UseSignTool:\r
+ self.SignToolPfxFile.close()\r
+ self.SignToolPfxFile = self.SignToolPfxFile.name\r
+ if self.UseOpenSsl:\r
+ self.OpenSslSignerPrivateCertFile.close()\r
+ self.OpenSslOtherPublicCertFile.close()\r
+ self.OpenSslTrustedPublicCertFile.close()\r
+ self.OpenSslSignerPrivateCertFile = self.OpenSslSignerPrivateCertFile.name\r
+ self.OpenSslOtherPublicCertFile = self.OpenSslOtherPublicCertFile.name\r
+ self.OpenSslTrustedPublicCertFile = self.OpenSslTrustedPublicCertFile.name\r
+\r
+ #\r
+ # Perform additional argument verification\r
+ #\r
+ if args.Encode:\r
+ if 'PersistAcrossReset' not in args.CapsuleFlag:\r
+ if 'InitiateReset' in args.CapsuleFlag:\r
+ raise argparse.ArgumentTypeError ('--capflag InitiateReset also requires --capflag PersistAcrossReset')\r
+ if args.CapsuleOemFlag > 0xFFFF:\r
+ raise argparse.ArgumentTypeError ('--capoemflag must be an integer between 0x0000 and 0xffff')\r
+\r
+ return True\r
+\r
+\r
+ def Encode (PayloadDescriptorList, EmbeddedDriverDescriptorList, Buffer):\r
+ if args.JsonFile:\r
+ CheckArgumentConflict(args)\r
+ try:\r
+ Json = json.loads (args.JsonFile.read ())\r
+ except:\r
+ print ('GenerateCapsule: error: {JSONFile} loads failure. '.format (JSONFile = args.JsonFile))\r
+ sys.exit (1)\r
+ EncodeJsonFileParse(Json)\r
+ else:\r
+ for Driver in args.EmbeddedDriver:\r
+ EmbeddedDriverDescriptorList.append (Driver.read())\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ Buffer,\r
+ args.Guid,\r
+ args.FwVersion,\r
+ args.LowestSupportedVersion,\r
+ args.MonotonicCount,\r
+ args.HardwareInstance,\r
+ args.UpdateImageIndex,\r
+ args.SignToolPfxFile,\r
+ args.OpenSslSignerPrivateCertFile,\r
+ args.OpenSslOtherPublicCertFile,\r
+ args.OpenSslTrustedPublicCertFile,\r
+ args.SigningToolPath\r
+ ))\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ try:\r
+ SinglePayloadDescriptor.Validate (args)\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: error:' + str(Msg))\r
+ sys.exit (1)\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ Result = SinglePayloadDescriptor.Payload\r
+ try:\r
+ FmpPayloadHeader.FwVersion = SinglePayloadDescriptor.FwVersion\r
+ FmpPayloadHeader.LowestSupportedVersion = SinglePayloadDescriptor.LowestSupportedVersion\r
+ FmpPayloadHeader.Payload = SinglePayloadDescriptor.Payload\r
+ Result = FmpPayloadHeader.Encode ()\r
+ if args.Verbose:\r
+ FmpPayloadHeader.DumpInfo ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not encode FMP Payload Header')\r
+ sys.exit (1)\r
+ if SinglePayloadDescriptor.UseOpenSsl or SinglePayloadDescriptor.UseSignTool:\r
+ #\r
+ # Sign image with 64-bit MonotonicCount appended to end of image\r
+ #\r
+ try:\r
+ if SinglePayloadDescriptor.UseSignTool:\r
+ CertData = SignPayloadSignTool (\r
+ Result + struct.pack ('<Q', SinglePayloadDescriptor.MonotonicCount),\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.SignToolPfxFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ else:\r
+ CertData = SignPayloadOpenSsl (\r
+ Result + struct.pack ('<Q', SinglePayloadDescriptor.MonotonicCount),\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.OpenSslSignerPrivateCertFile,\r
+ SinglePayloadDescriptor.OpenSslOtherPublicCertFile,\r
+ SinglePayloadDescriptor.OpenSslTrustedPublicCertFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: error: can not sign payload \n' + str(Msg))\r
+ sys.exit (1)\r
+\r
+ try:\r
+ FmpAuthHeader.MonotonicCount = SinglePayloadDescriptor.MonotonicCount\r
+ FmpAuthHeader.CertData = CertData\r
+ FmpAuthHeader.Payload = Result\r
+ Result = FmpAuthHeader.Encode ()\r
+ if args.Verbose:\r
+ FmpAuthHeader.DumpInfo ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not encode FMP Auth Header')\r
+ sys.exit (1)\r
+ FmpCapsuleHeader.AddPayload (SinglePayloadDescriptor.Guid, Result, HardwareInstance = SinglePayloadDescriptor.HardwareInstance, UpdateImageIndex = SinglePayloadDescriptor.UpdateImageIndex)\r
+ try:\r
+ for EmbeddedDriver in EmbeddedDriverDescriptorList:\r
+ FmpCapsuleHeader.AddEmbeddedDriver(EmbeddedDriver)\r
+\r
+ Result = FmpCapsuleHeader.Encode ()\r
+ if args.Verbose:\r
+ FmpCapsuleHeader.DumpInfo ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not encode FMP Capsule Header')\r
+ sys.exit (1)\r
+\r
+ try:\r
+ UefiCapsuleHeader.OemFlags = args.CapsuleOemFlag\r
+ UefiCapsuleHeader.PersistAcrossReset = 'PersistAcrossReset' in args.CapsuleFlag\r
+ UefiCapsuleHeader.PopulateSystemTable = False\r
+ UefiCapsuleHeader.InitiateReset = 'InitiateReset' in args.CapsuleFlag\r
+ UefiCapsuleHeader.Payload = Result\r
+ Result = UefiCapsuleHeader.Encode ()\r
+ if args.Verbose:\r
+ UefiCapsuleHeader.DumpInfo ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not encode UEFI Capsule Header')\r
+ sys.exit (1)\r
+ try:\r
+ if args.Verbose:\r
+ print ('Write binary output file {File}'.format (File = args.OutputFile.name))\r
+ args.OutputFile.write (Result)\r
+ args.OutputFile.close ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = args.OutputFile.name))\r
+ sys.exit (1)\r
+\r
+ def Decode (PayloadDescriptorList, PayloadJsonDescriptorList, Buffer):\r
+ if args.JsonFile:\r
+ CheckArgumentConflict(args)\r
+ #\r
+ # Parse payload descriptors from JSON\r
+ #\r
+ try:\r
+ Json = json.loads (args.JsonFile.read())\r
+ except:\r
+ print ('GenerateCapsule: error: {JSONFile} loads failure. '.format (JSONFile = args.JsonFile))\r
+ sys.exit (1)\r
+ DecodeJsonFileParse (Json)\r
+ else:\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ Buffer,\r
+ args.Guid,\r
+ args.FwVersion,\r
+ args.LowestSupportedVersion,\r
+ args.MonotonicCount,\r
+ args.HardwareInstance,\r
+ args.UpdateImageIndex,\r
+ args.SignToolPfxFile,\r
+ args.OpenSslSignerPrivateCertFile,\r
+ args.OpenSslOtherPublicCertFile,\r
+ args.OpenSslTrustedPublicCertFile,\r
+ args.SigningToolPath\r
+ ))\r
+ #\r
+ # Perform additional verification on payload descriptors\r
+ #\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ try:\r
+ SinglePayloadDescriptor.Validate (args)\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: error:' + str(Msg))\r
+ sys.exit (1)\r
+ try:\r
+ Result = UefiCapsuleHeader.Decode (Buffer)\r
+ if len (Result) > 0:\r
+ Result = FmpCapsuleHeader.Decode (Result)\r
+ if args.JsonFile:\r
+ if FmpCapsuleHeader.PayloadItemCount != len (PayloadDescriptorList):\r
+ CapsulePayloadNum = FmpCapsuleHeader.PayloadItemCount\r
+ JsonPayloadNum = len (PayloadDescriptorList)\r
+ print ('GenerateCapsule: Decode error: {JsonPayloadNumber} payloads in JSON file {File} and {CapsulePayloadNumber} payloads in Capsule {CapsuleName}'.format (JsonPayloadNumber = JsonPayloadNum, File = args.JsonFile.name, CapsulePayloadNumber = CapsulePayloadNum, CapsuleName = args.InputFile.name))\r
+ sys.exit (1)\r
+ for Index in range (0, FmpCapsuleHeader.PayloadItemCount):\r
+ if Index < len (PayloadDescriptorList):\r
+ GUID = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageTypeId\r
+ HardwareInstance = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateHardwareInstance\r
+ UpdateImageIndex = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageIndex\r
+ if PayloadDescriptorList[Index].Guid != GUID or PayloadDescriptorList[Index].HardwareInstance != HardwareInstance:\r
+ print ('GenerateCapsule: Decode error: Guid or HardwareInstance pair in input JSON file {File} does not match the payload {PayloadIndex} in Capsule {InputCapsule}'.format (File = args.JsonFile.name, PayloadIndex = Index + 1, InputCapsule = args.InputFile.name))\r
+ sys.exit (1)\r
+ PayloadDescriptorList[Index].Payload = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).Payload\r
+ DecodeJsonOutput = args.OutputFile.name + '.Payload.{Index:d}.bin'.format (Index = Index + 1)\r
+ PayloadJsonDescriptorList.append (PayloadDescriptor (\r
+ DecodeJsonOutput,\r
+ GUID,\r
+ None,\r
+ None,\r
+ None,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ PayloadDescriptorList[Index].SignToolPfxFile,\r
+ PayloadDescriptorList[Index].OpenSslSignerPrivateCertFile,\r
+ PayloadDescriptorList[Index].OpenSslOtherPublicCertFile,\r
+ PayloadDescriptorList[Index].OpenSslTrustedPublicCertFile,\r
+ PayloadDescriptorList[Index].SigningToolPath\r
+ ))\r
+ else:\r
+ PayloadDescriptorList[0].Payload = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r
+ for Index in range (0, FmpCapsuleHeader.PayloadItemCount):\r
+ if Index > 0:\r
+ PayloadDecodeFile = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).Payload\r
+ PayloadDescriptorList.append (PayloadDescriptor (PayloadDecodeFile,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None\r
+ ))\r
+ GUID = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageTypeId\r
+ HardwareInstance = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateHardwareInstance\r
+ UpdateImageIndex = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageIndex\r
+ DecodeJsonOutput = args.OutputFile.name + '.Payload.{Index:d}.bin'.format (Index = Index + 1)\r
+ PayloadJsonDescriptorList.append (PayloadDescriptor (\r
+ DecodeJsonOutput,\r
+ GUID,\r
+ None,\r
+ None,\r
+ None,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ PayloadDescriptorList[Index].SignToolPfxFile,\r
+ PayloadDescriptorList[Index].OpenSslSignerPrivateCertFile,\r
+ PayloadDescriptorList[Index].OpenSslOtherPublicCertFile,\r
+ PayloadDescriptorList[Index].OpenSslTrustedPublicCertFile,\r
+ PayloadDescriptorList[Index].SigningToolPath\r
+ ))\r
+ JsonIndex = 0\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ if args.Verbose:\r
+ print ('========')\r
+ UefiCapsuleHeader.DumpInfo ()\r
+ print ('--------')\r
+ FmpCapsuleHeader.DumpInfo ()\r
+ if FmpAuthHeader.IsSigned(SinglePayloadDescriptor.Payload):\r
+ if not SinglePayloadDescriptor.UseOpenSsl and not SinglePayloadDescriptor.UseSignTool:\r
+ print ('GenerateCapsule: decode warning: can not verify singed payload without cert or pfx file. Index = {Index}'.format (Index = JsonIndex + 1))\r
+ SinglePayloadDescriptor.Payload = FmpAuthHeader.Decode (SinglePayloadDescriptor.Payload)\r
+ PayloadJsonDescriptorList[JsonIndex].MonotonicCount = FmpAuthHeader.MonotonicCount\r
+ if args.Verbose:\r
+ print ('--------')\r
+ FmpAuthHeader.DumpInfo ()\r
+\r
+ #\r
+ # Verify Image with 64-bit MonotonicCount appended to end of image\r
+ #\r
+ try:\r
+ if SinglePayloadDescriptor.UseSignTool:\r
+ CertData = VerifyPayloadSignTool (\r
+ FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+ FmpAuthHeader.CertData,\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.SignToolPfxFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ else:\r
+ CertData = VerifyPayloadOpenSsl (\r
+ FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+ FmpAuthHeader.CertData,\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.OpenSslSignerPrivateCertFile,\r
+ SinglePayloadDescriptor.OpenSslOtherPublicCertFile,\r
+ SinglePayloadDescriptor.OpenSslTrustedPublicCertFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: warning: payload verification failed Index = {Index} \n'.format (Index = JsonIndex + 1) + str(Msg))\r
+ else:\r
+ if args.Verbose:\r
+ print ('--------')\r
+ print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+ try:\r
+ SinglePayloadDescriptor.Payload = FmpPayloadHeader.Decode (SinglePayloadDescriptor.Payload)\r
+ PayloadJsonDescriptorList[JsonIndex].FwVersion = FmpPayloadHeader.FwVersion\r
+ PayloadJsonDescriptorList[JsonIndex].LowestSupportedVersion = FmpPayloadHeader.LowestSupportedVersion\r
+ JsonIndex = JsonIndex + 1\r
+ if args.Verbose:\r
+ print ('--------')\r
+ FmpPayloadHeader.DumpInfo ()\r
+ print ('========')\r
+ except:\r
+ if args.Verbose:\r
+ print ('--------')\r
+ print ('No FMP_PAYLOAD_HEADER')\r
+ print ('========')\r
+ sys.exit (1)\r
+ #\r
+ # Write embedded driver file(s)\r
+ #\r
+ for Index in range (0, FmpCapsuleHeader.EmbeddedDriverCount):\r
+ EmbeddedDriverBuffer = FmpCapsuleHeader.GetEmbeddedDriver (Index)\r
+ EmbeddedDriverPath = args.OutputFile.name + '.EmbeddedDriver.{Index:d}.efi'.format (Index = Index + 1)\r
+ try:\r
+ if args.Verbose:\r
+ print ('Write embedded driver file {File}'.format (File = EmbeddedDriverPath))\r
+ with open (EmbeddedDriverPath, 'wb') as EmbeddedDriverFile:\r
+ EmbeddedDriverFile.write (EmbeddedDriverBuffer)\r
+ except:\r
+ print ('GenerateCapsule: error: can not write embedded driver file {File}'.format (File = EmbeddedDriverPath))\r
+ sys.exit (1)\r
+\r
+ except:\r
+ print ('GenerateCapsule: error: can not decode capsule')\r
+ sys.exit (1)\r
+ GenerateOutputJson(PayloadJsonDescriptorList)\r
+ PayloadIndex = 0\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ if args.OutputFile is None:\r
+ print ('GenerateCapsule: Decode error: OutputFile is needed for decode output')\r
+ sys.exit (1)\r
+ try:\r
+ if args.Verbose:\r
+ print ('Write binary output file {File}'.format (File = args.OutputFile.name))\r
+ PayloadDecodePath = args.OutputFile.name + '.Payload.{Index:d}.bin'.format (Index = PayloadIndex + 1)\r
+ with open (PayloadDecodePath, 'wb') as PayloadDecodeFile:\r
+ PayloadDecodeFile.write (SinglePayloadDescriptor.Payload)\r
+ PayloadIndex = PayloadIndex + 1\r
+ except:\r
+ print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = SinglePayloadDescriptor.OutputFile.name))\r
+ sys.exit (1)\r
+\r
+ def DumpInfo (Buffer, args):\r
+ if args.OutputFile is not None:\r
+ raise argparse.ArgumentTypeError ('the following option is not supported for dumpinfo operations: --output')\r
+ try:\r
+ Result = UefiCapsuleHeader.Decode (Buffer)\r
+ print ('========')\r
+ UefiCapsuleHeader.DumpInfo ()\r
+ if len (Result) > 0:\r
+ FmpCapsuleHeader.Decode (Result)\r
+ print ('--------')\r
+ FmpCapsuleHeader.DumpInfo ()\r
+ for Index in range (0, FmpCapsuleHeader.PayloadItemCount):\r
+ Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).Payload\r
+ try:\r
+ Result = FmpAuthHeader.Decode (Result)\r
+ print ('--------')\r
+ FmpAuthHeader.DumpInfo ()\r
+ except:\r
+ print ('--------')\r
+ print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+ try:\r
+ Result = FmpPayloadHeader.Decode (Result)\r
+ print ('--------')\r
+ FmpPayloadHeader.DumpInfo ()\r
+ except:\r
+ print ('--------')\r
+ print ('No FMP_PAYLOAD_HEADER')\r
+ print ('========')\r
+ except:\r
+ print ('GenerateCapsule: error: can not decode capsule')\r
+ sys.exit (1)\r