From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.20, mailfrom: zhijux.fan@intel.com) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by groups.io with SMTP; Thu, 20 Jun 2019 18:58:22 -0700 X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2019 18:58:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,398,1557212400"; d="dat'59?scan'59,208,59";a="171075650" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga002.jf.intel.com with ESMTP; 20 Jun 2019 18:58:20 -0700 Received: from fmsmsx608.amr.corp.intel.com (10.18.126.88) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 20 Jun 2019 18:58:20 -0700 Received: from fmsmsx608.amr.corp.intel.com (10.18.126.88) by fmsmsx608.amr.corp.intel.com (10.18.126.88) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Thu, 20 Jun 2019 18:58:19 -0700 Received: from shsmsx153.ccr.corp.intel.com (10.239.6.53) by fmsmsx608.amr.corp.intel.com (10.18.126.88) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Thu, 20 Jun 2019 18:58:19 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.87]) by SHSMSX153.ccr.corp.intel.com ([169.254.12.76]) with mapi id 14.03.0439.000; Fri, 21 Jun 2019 09:58:18 +0800 From: "Fan, ZhijuX" To: "devel@edk2.groups.io" CC: "Gao, Liming" , "Feng, Bob C" , Ard Biesheuvel , "Leif Lindholm" , "Kinney, Michael D" Subject: [edk2-platform patch 1/2] Platform/Intel:Add GenBiosId into edk2-platforms/Platform/Intel/Tools Thread-Topic: [edk2-platform patch 1/2] Platform/Intel:Add GenBiosId into edk2-platforms/Platform/Intel/Tools Thread-Index: AdUn1MqHf8imMAQ4TZu3CECNkVVq/g== Date: Fri, 21 Jun 2019 01:58:17 +0000 Message-ID: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.0.600.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: zhijux.fan@intel.com X-Groupsio-MsgNum: 42676 Content-Type: multipart/mixed; boundary="_000_FAD0D7E0AE0FA54D987F6E72435CAFD50AF8412CSHSMSX101ccrcor_" Content-Language: en-US --_000_FAD0D7E0AE0FA54D987F6E72435CAFD50AF8412CSHSMSX101ccrcor_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1855 GenBiosId is a tool to generate the BIOS ID binary file which uses the data from the configuration file. This tool can be run in both Py2 and Py3. This patch is going to add GenBiosId to Platform/Intel/Tools Cc: Liming Gao Cc: Bob Feng Cc: Ard Biesheuvel Cc: Leif Lindholm Cc: Michael D Kinney Signed-off-by: Zhiju.Fan --- Platform/Intel/Tools/GenBiosId/BiosId.env | 27 +++++ Platform/Intel/Tools/GenBiosId/GenBiosId.py | 180 ++++++++++++++++++++++++= ++++ 2 files changed, 207 insertions(+) create mode 100644 Platform/Intel/Tools/GenBiosId/BiosId.env create mode 100644 Platform/Intel/Tools/GenBiosId/GenBiosId.py diff --git a/Platform/Intel/Tools/GenBiosId/BiosId.env b/Platform/Intel/Too= ls/GenBiosId/BiosId.env new file mode 100644 index 0000000000..e1e913da76 --- /dev/null +++ b/Platform/Intel/Tools/GenBiosId/BiosId.env @@ -0,0 +1,27 @@ +## @file +# This file is used to define the BIOS ID parameters of the build. +# This file is processed by GenBiosId. +# Here, it is just a template and can be customized by user. +# +# BIOS ID string format: +# $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$(BUILD_TYPE)$(= VERSION_MINOR).YYMMDDHHMM +# All fields must have a fixed length. YYMMDDHHMM is UTC time. +# Example: "EMLATOR1.000.0001.D01.1906141517" +# +# If DATE is specified for YYMMDD and TIME is specified for HHMM like bel= ow, +# GenBiosId will use the value of DATE and TIME to fill YYMMDDHHMM, +# otherwise GenBiosId will fill YYMMDDHHMM with current UTC time of the b= uild machine. +# DATE =3D 190614 +# TIME =3D 1517 +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## +[config] +BOARD_ID =3D KBLRVP3 +BOARD_REV =3D 1 +BOARD_EXT =3D 000 +BUILD_TYPE =3D D +VERSION_MAJOR =3D 0001 +VERSION_MINOR =3D 01 diff --git a/Platform/Intel/Tools/GenBiosId/GenBiosId.py b/Platform/Intel/T= ools/GenBiosId/GenBiosId.py new file mode 100644 index 0000000000..20fb7592b4 --- /dev/null +++ b/Platform/Intel/Tools/GenBiosId/GenBiosId.py @@ -0,0 +1,180 @@ +## @file +# Trim files preprocessed by compiler +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +## +# Import Modules +# +import os +import sys +import time +import logging +import struct +import datetime +import argparse +import platform + +try: + from configparser import ConfigParser +except: + from ConfigParser import ConfigParser + +# Config message +_BIOS_Signature =3D "$IBIOSI$" +_SectionKeyName =3D '__name__' +_SectionName =3D 'config' + +_ConfigItem =3D { + "BOARD_ID": {'Value': '', 'Length': 7}, + "BOARD_REV": {'Value': '', 'Length': 1}, + "BOARD_EXT": {'Value': '', 'Length': 3}, + "BUILD_TYPE": {'Value': '', 'Length': 1}, + "VERSION_MAJOR": {'Value': '0000', 'Length': 4}, + "VERSION_MINOR": {'Value': '00', 'Length': 2}, +} + +# Version message +__prog__ =3D 'GenBiosld' +__description__ =3D 'Trim files preprocessed by compiler' +__copyright__ =3D 'Copyright (c) 2019, Intel Corporation. All rights reser= ved.
' +__version__ =3D '%s Version %s' % (__prog__, '0.1 ') + +# ExtraData message +_Usage =3D "Usage: GenBiosId -i Configfile -o OutputFile [-ot OutputTextFi= le]" +_ConfigSectionNotDefine =3D "Not support the config file format, need conf= ig section" +_ErrorMessageTemplate =3D '\n\n%(tool)s...\n : error: %(msg)s\n\t%(extra)s= ' +_ErrorLogger =3D logging.getLogger("tool_error") +_ErrorFormatter =3D logging.Formatter("%(message)s") +_ConfigLenInvalid =3D "Config item %s length is invalid" +_ConfigItemInvalid =3D "Item %s is invalid" + +# Error message +INFO =3D 20 +ERRORCODE =3D 50 +OPTION_MISSING =3D 'Missing option' +FORMAT_INVALID =3D 'Invalid syntax/format' +FILE_NOT_FOUND =3D 'File/directory not found in workspace' +FORMAT_UNKNOWN_ERROR =3D 'Unknown error in syntax/format' +FORMAT_NOT_SUPPORTED =3D 'Not supported syntax/format' + + +def SetEdkLogger(): + _ErrorLogger.setLevel(INFO) + _ErrorCh =3D logging.StreamHandler(sys.stderr) + _ErrorCh.setFormatter(_ErrorFormatter) + _ErrorLogger.addHandler(_ErrorCh) + return _ErrorLogger + + +# Output the error message and exit the tool +def EdkLogger(ToolName, Message, ExtraData): + _ErrorLogger =3D SetEdkLogger() + TemplateDict =3D {"tool": ToolName, "msg": Message, "extra": ExtraData= } + LogText =3D _ErrorMessageTemplate % TemplateDict + _ErrorLogger.log(ERRORCODE, LogText) + sys.exit() + + +# Open the file in the correct way +def FileOpen(FileName, Mode, Buffer=3D-1): + def LongFilePath(FileName): + FileName =3D os.path.normpath(FileName) + if platform.system() =3D=3D 'Windows': + if FileName.startswith('\\\\?\\'): + return FileName + if FileName.startswith('\\\\'): + return '\\\\?\\UNC\\' + FileName[2:] + if os.path.isabs(FileName): + return '\\\\?\\' + FileName + return FileName + + return open(LongFilePath(FileName), Mode, Buffer) + + +# Parse command line options +def MyOptionParser(): + parser =3D argparse.ArgumentParser(prog=3D__prog__, + description=3D__description__ + __cop= yright__ + _Usage, + conflict_handler=3D'resolve') + parser.add_argument('-v', '--version', action=3D'version', version=3D_= _version__, + help=3D"show program's version number and exit") + parser.add_argument('-i', '--int', metavar=3D'FILENAME', dest=3D'Input= File', help=3D"Input Config file") + parser.add_argument('-o', '--out', metavar=3D'FILENAME', dest=3D'Outpu= tFile', help=3D"Output file") + parser.add_argument('-ot', '--text', metavar=3D'FILENAME', dest=3D'Out= putTextFile', help=3D"Output Text file") + Options =3D parser.parse_args() + return Options + + +# Check the Tool for missing variables +def CheckOptions(Options): + if len(sys.argv) !=3D 5 and not (len(sys.argv) =3D=3D 7 and Options.Ou= tputTextFile): + EdkLogger("GenBiosId", OPTION_MISSING, ExtraData=3D_Usage) + elif not Options.InputFile or not Options.OutputFile: + EdkLogger("GenBiosId", OPTION_MISSING, ExtraData=3D_Usage) + InputFile =3D Options.InputFile + OutputFile =3D Options.OutputFile + OutputTextFile =3D Options.OutputTextFile + if not os.path.exists(InputFile): + EdkLogger("GenBiosId", FILE_NOT_FOUND, ExtraData=3D"Input file not= found") + return InputFile, OutputFile, OutputTextFile + + +# Parse the input file and extract the information +def ParserInputFile(InputFile): + cf =3D ConfigParser() + cf.optionxform =3D str + cf.read(InputFile) + if _SectionName not in cf._sections: + EdkLogger("GenBiosId", FORMAT_NOT_SUPPORTED, ExtraData=3D_ConfigSe= ctionNotDefine) + for Item in cf._sections[_SectionName]: + if Item =3D=3D _SectionKeyName: + continue + if Item not in _ConfigItem: + EdkLogger("GenBiosId", FORMAT_INVALID, ExtraData=3D_ConfigItem= Invalid % Item) + _ConfigItem[Item]['Value'] =3D cf._sections[_SectionName][Item] + if len(_ConfigItem[Item]['Value']) !=3D _ConfigItem[Item]['Length'= ]: + EdkLogger("GenBiosId", FORMAT_INVALID, ExtraData=3D_ConfigLenI= nvalid % Item) + for Item in _ConfigItem: + if not _ConfigItem[Item]['Value']: + EdkLogger("GenBiosId", FORMAT_UNKNOWN_ERROR, ExtraData=3D"Item= %s is missing" % Item) + utcnow =3D datetime.datetime.utcnow() + TimeStamp =3D time.strftime("%y%m%d%H%M", utcnow.timetuple()) + + Id_Str =3D _ConfigItem['BOARD_ID']['Value'] + _ConfigItem['BOARD_REV']= ['Value'] + '.' + _ConfigItem['BOARD_EXT'][ + 'Value'] + '.' + _ConfigItem['VERSION_MAJOR']['Value'] + \ + '.' + _ConfigItem["BUILD_TYPE"]['Value'] + _ConfigItem['VERSI= ON_MINOR']['Value'] + '.' + TimeStamp + return Id_Str + + +# Output information to a file +def PrintOutputFile(OutputFile, OutputTextFile, Id_Str): + with FileOpen(OutputFile, 'wb') as FdOut: + for i in _BIOS_Signature: + FdOut.write(struct.pack('B', ord(i))) + + for i in Id_Str: + FdOut.write(struct.pack('H', ord(i))) + + FdOut.write(struct.pack('H', 0x00)) + if OutputTextFile: + with FileOpen(OutputTextFile, 'w') as FdOut: + FdOut.write(Id_Str) + + +# Tool entrance method +def Main(): + Options =3D MyOptionParser() + InputFile, OutputFile, OutputTextFile =3D CheckOptions(Options) + Id_Str =3D ParserInputFile(InputFile) + PrintOutputFile(OutputFile, OutputTextFile, Id_Str) + return 0 + + +if __name__ =3D=3D '__main__': + r =3D Main() + ## 0-127 is a safe return range, and 1 is a standard default error + if r < 0 or r > 127: r =3D 1 + sys.exit(r) --=20 2.14.1.windows.1 --_000_FAD0D7E0AE0FA54D987F6E72435CAFD50AF8412CSHSMSX101ccrcor_ Content-Disposition: attachment; filename="winmail.dat" Content-Transfer-Encoding: base64 Content-Type: application/ms-tnef; name="winmail.dat" eJ8+IrgWAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEJgAEAIQAAAEJGNzNFNkRD RjM2QUE1NDI5QjdDOTlDNzIxQThENUYxAG0HAQ2ABAACAAAAAgACAAEFgAMADgAAAOMHBgAVAAEA OgARAAUAVgEBIIADAA4AAADjBwYAFQABADoAEQAFAFYBAQiABwAYAAAASVBNLk1pY3Jvc29mdCBN YWlsLk5vdGUAMQgBBIABAGAAAABbZWRrMi1wbGF0Zm9ybSBwYXRjaCAxLzJdIFBsYXRmb3JtL0lu dGVsOkFkZCBHZW5CaW9zSWQgaW50byBlZGsyLXBsYXRmb3Jtcy9QbGF0Zm9ybS9JbnRlbC9Ub29s cwAdIgELgAEAIQAAAEJGNzNFNkRDRjM2QUE1NDI5QjdDOTlDNzIxQThENUYxAG0HAQOQBgDAGgAA MwAAAAIBfwABAAAASAAAADxGQUQwRDdFMEFFMEZBNTREOTg3RjZFNzI0MzVDQUZENTBBRjg0MTJD QFNIU01TWDEwMS5jY3IuY29ycC5pbnRlbC5jb20+AAsAHw4BAAAAAgEJEAEAAACQEAAAjBAAAOUp AABMWkZ14fqIX2EACmZiaWQEAABjY8BwZzEyNTIA/gND8HRleHQB9wKkA+MCAARjaArAc2V0MCDv B20CgwBQEU0yCoAGtAKAln0KgAjIOwliMTkOwL8JwxZyCjIWcQKAFWIqCbBzCfAEkGF0BbIOUANg c6JvAYAgRXgRwW4YMF0GUnYEkBe2AhByAMB0fQhQbhoxECAFwAWgG2RkmiADUiAQIheyXHYIkOR3 awuAZDUdUwTwB0ANF3AwCnEX8mJrbWsGcwGQACAgQk1fQuBFR0lOfQr8AfEL8REfsFo6aAJAcHM6 wC8vYnVnegMQC2AkLnQHMG5vBaFlLgEFsGcvc2hvd19BIlEuY2dpPw3QPagxODUd4GwLgGUKgaUl FEcJ8EJpGRBJHGBpBAAgYRzAbwbwJsEgExg1GeB0aBngQklPUQXwSUQgDcBuCsB5JxxwAxAZ4Hdo DlBoIN51EgAOACUUJ+JkGIAmsO8chCfxG+EpEGcIcBiAJiDrA6ApEi4lBVQpcAQgJtPLHlADoGIZ 4HJ1A6ALgIUokG8n4CBQeTImoLsdwC7xMyy2LMoKsHQpkSkmgWdvC4BnJxJhZHccYCXoJyFQC2AA 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 cKrAJ4VLqLKLZI46wiNmoDAtMTLjAEaxf2gg8aCiUGRGieGxQb+zMT+gpQEQtPDXQL/g3aFhdX5s 4cC+4KqAESsgMdvwPLd/QOvC2/A+omCggDqes+4xjjrgcsACKIenuGBb8OGORDIuMTSpMH3QhXCe ZL4A6xCmlo41fX270AGrQB8AQgABAAAAGAAAAEYAYQBuACwAIABaAGgAaQBqAHUAWAAAAB8AZQAB AAAAKgAAAHoAaABpAGoAdQB4AC4AZgBhAG4AQABpAG4AdABlAGwALgBjAG8AbQAAAAAAHwBkAAEA AAAKAAAAUwBNAFQAUAAAAAAAAgFBAAEAAABkAAAAAAAAAIErH6S+oxAZnW4A3QEPVAIAAACARgBh AG4ALAAgAFoAaABpAGoAdQBYAAAAUwBNAFQAUAAAAHoAaABpAGoAdQB4AC4AZgBhAG4AQABpAG4A dABlAGwALgBjAG8AbQAAAB8AAl0BAAAAKgAAAHoAaABpAGoAdQB4AC4AZgBhAG4AQABpAG4AdABl AGwALgBjAG8AbQAAAAAAHwDlXwEAAAAyAAAAcwBpAHAAOgB6AGgAaQBqAHUAeAAuAGYAYQBuAEAA aQBuAHQAZQBsAC4AYwBvAG0AAAAAAB8AGgwBAAAAGAAAAEYAYQBuACwAIABaAGgAaQBqAHUAWAAA AB8AHwwBAAAAKgAAAHoAaABpAGoAdQB4AC4AZgBhAG4AQABpAG4AdABlAGwALgBjAG8AbQAAAAAA HwAeDAEAAAAKAAAAUwBNAFQAUAAAAAAAAgEZDAEAAABkAAAAAAAAAIErH6S+oxAZnW4A3QEPVAIA AACARgBhAG4ALAAgAFoAaABpAGoAdQBYAAAAUwBNAFQAUAAAAHoAaABpAGoAdQB4AC4AZgBhAG4A QABpAG4AdABlAGwALgBjAG8AbQAAAB8AAV0BAAAAKgAAAHoAaABpAGoAdQB4AC4AZgBhAG4AQABp AG4AdABlAGwALgBjAG8AbQAAAAAAHwD4PwEAAAAYAAAARgBhAG4ALAAgAFoAaABpAGoAdQBYAAAA HwAjQAEAAAAqAAAAegBoAGkAagB1AHgALgBmAGEAbgBAAGkAbgB0AGUAbAAuAGMAbwBtAAAAAAAf ACJAAQAAAAoAAABTAE0AVABQAAAAAAACAfk/AQAAAGQAAAAAAAAAgSsfpL6jEBmdbgDdAQ9UAgAA AIBGAGEAbgAsACAAWgBoAGkAagB1AFgAAABTAE0AVABQAAAAegBoAGkAagB1AHgALgBmAGEAbgBA AGkAbgB0AGUAbAAuAGMAbwBtAAAAHwAJXQEAAAAqAAAAegBoAGkAagB1AHgALgBmAGEAbgBAAGkA bgB0AGUAbAAuAGMAbwBtAAAAAAALAEA6AQAAAB8AGgABAAAAEgAAAEkAUABNAC4ATgBvAHQAZQAA AAAAAwDxPwkEAAALAEA6AQAAAAMA/T/kBAAAAgELMAEAAAAQAAAAv3Pm3PNqpUKbfJnHIajV8QMA FwABAAAAQAA5AIDCBcvUJ9UBQAAIMKnDPsvUJ9UBHwAAgIYDAgAAAAAAwAAAAAAAAEYBAAAAHgAA AGEAYwBjAGUAcAB0AGwAYQBuAGcAdQBhAGcAZQAAAAAAAQAAAAwAAABlAG4ALQBVAFMAAAAfADcA AQAAAMAAAABbAGUAZABrADIALQBwAGwAYQB0AGYAbwByAG0AIABwAGEAdABjAGgAIAAxAC8AMgBd ACAAUABsAGEAdABmAG8AcgBtAC8ASQBuAHQAZQBsADoAQQBkAGQAIABHAGUAbgBCAGkAbwBzAEkA ZAAgAGkAbgB0AG8AIABlAGQAawAyAC0AcABsAGEAdABmAG8AcgBtAHMALwBQAGwAYQB0AGYAbwBy AG0ALwBJAG4AdABlAGwALwBUAG8AbwBsAHMAAAAfAD0AAQAAAAIAAAAAAAAAAwA2AAAAAAACAXEA AQAAABYAAAAB1SfUyod/yKYwBDhNm7cIQI2RVWr+AAAfAHAAAQAAAMAAAABbAGUAZABrADIALQBw AGwAYQB0AGYAbwByAG0AIABwAGEAdABjAGgAIAAxAC8AMgBdACAAUABsAGEAdABmAG8AcgBtAC8A SQBuAHQAZQBsADoAQQBkAGQAIABHAGUAbgBCAGkAbwBzAEkAZAAgAGkAbgB0AG8AIABlAGQAawAy AC0AcABsAGEAdABmAG8AcgBtAHMALwBQAGwAYQB0AGYAbwByAG0ALwBJAG4AdABlAGwALwBUAG8A bwBsAHMAAAAfADUQAQAAAJAAAAA8AEYAQQBEADAARAA3AEUAMABBAEUAMABGAEEANQA0AEQAOQA4 ADcARgA2AEUANwAyADQAMwA1AEMAQQBGAEQANQAwAEEARgA4ADQAMQAyAEMAQABTAEgAUwBNAFMA WAAxADAAMQAuAGMAYwByAC4AYwBvAHIAcAAuAGkAbgB0AGUAbAAuAGMAbwBtAD4AAAADAN4/n04A AEAABzDpADrL1CfVAQIBCwABAAAAEAAAAL9z5tzzaqVCm3yZxyGo1fEDACYAAAAAAAIBRwABAAAA MgAAAGM9VVM7YT1NQ0k7cD1JbnRlbDtsPVNIU01TWDEwMS0xOTA2MjEwMTU4MTdaLTgzNzQAAAAC ARAwAQAAAEYAAAAAAAAAJne9OTvsOEmkphU9y6V7QgcA+tDX4K4PpU2Yf25yQ1yv1QAAAEQRXgAA ppNoNoh2bEunStPrR5pMZAAACVSPvAAAAAAfAPo/AQAAABgAAABGAGEAbgAsACAAWgBoAGkAagB1 AFgAAAADAAlZAQAAAEAAAIAIIAYAAAAAAMAAAAAAAABGAAAAAL+FAABgYovK1CfVAQsAAIAIIAYA AAAAAMAAAAAAAABGAAAAAIKFAAAAAAAAHwAAgIYDAgAAAAAAwAAAAAAAAEYBAAAAGAAAAGQAbABw AC0AcAByAG8AZAB1AGMAdAAAAAEAAAAaAAAAZABsAHAAZQAtAHcAaQBuAGQAbwB3AHMAAAAAAB8A AICGAwIAAAAAAMAAAAAAAABGAQAAABgAAABkAGwAcAAtAHYAZQByAHMAaQBvAG4AAAABAAAAFgAA ADEAMQAuADAALgA2ADAAMAAuADcAAAAAAB8AAICGAwIAAAAAAMAAAAAAAABGAQAAABoAAABkAGwA cAAtAHIAZQBhAGMAdABpAG8AbgAAAAAAAQAAABQAAABuAG8ALQBhAGMAdABpAG8AbgAAAAMADTT9 PwAAHwAAgIYDAgAAAAAAwAAAAAAAAEYBAAAAIAAAAHgALQBtAHMALQBoAGEAcwAtAGEAdAB0AGEA YwBoAAAAAQAAAAIAAAAAAAAAHwAAgIYDAgAAAAAAwAAAAAAAAEYBAAAAIgAAAHgALQBvAHIAaQBn AGkAbgBhAHQAaQBuAGcALQBpAHAAAAAAAAEAAAAgAAAAWwAxADAALgAyADMAOQAuADEAMgA3AC4A NAAwAF0AAADiwA== --_000_FAD0D7E0AE0FA54D987F6E72435CAFD50AF8412CSHSMSX101ccrcor_--