From f32f631bc3783d2d21962a655ed01e503506b733 Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Wed, 11 Mar 2026 20:22:30 +0100 Subject: [PATCH] add binaries --- bin/bochs-experiment-runner.py | 147 ++++++++++++ bin/resultbrowser.py | 1 + bin/resultbrowser/README | 19 ++ bin/resultbrowser/app/__init__.py | 4 + bin/resultbrowser/app/data.py | 143 ++++++++++++ bin/resultbrowser/app/details.py | 216 ++++++++++++++++++ bin/resultbrowser/app/model.py | 211 +++++++++++++++++ bin/resultbrowser/app/static/css/barchart.css | 5 + bin/resultbrowser/app/static/css/main.css | 214 +++++++++++++++++ bin/resultbrowser/app/static/favicon.ico | Bin 0 -> 36885 bytes bin/resultbrowser/app/templates/about.html | 11 + bin/resultbrowser/app/templates/code.html | 50 ++++ bin/resultbrowser/app/templates/index.html | 55 +++++ .../app/templates/instr_details.html | 65 ++++++ bin/resultbrowser/app/templates/layout.html | 32 +++ bin/resultbrowser/app/views.py | 42 ++++ bin/resultbrowser/conf.yml | 69 ++++++ bin/resultbrowser/run.py | 5 + share/BIOS-bochs-latest | Bin 0 -> 131072 bytes share/vgabios.bin | Bin 0 -> 40448 bytes 20 files changed, 1289 insertions(+) create mode 100755 bin/bochs-experiment-runner.py create mode 120000 bin/resultbrowser.py create mode 100644 bin/resultbrowser/README create mode 100644 bin/resultbrowser/app/__init__.py create mode 100644 bin/resultbrowser/app/data.py create mode 100644 bin/resultbrowser/app/details.py create mode 100755 bin/resultbrowser/app/model.py create mode 100644 bin/resultbrowser/app/static/css/barchart.css create mode 100644 bin/resultbrowser/app/static/css/main.css create mode 100644 bin/resultbrowser/app/static/favicon.ico create mode 100644 bin/resultbrowser/app/templates/about.html create mode 100644 bin/resultbrowser/app/templates/code.html create mode 100644 bin/resultbrowser/app/templates/index.html create mode 100644 bin/resultbrowser/app/templates/instr_details.html create mode 100644 bin/resultbrowser/app/templates/layout.html create mode 100644 bin/resultbrowser/app/views.py create mode 100644 bin/resultbrowser/conf.yml create mode 100755 bin/resultbrowser/run.py create mode 100755 share/BIOS-bochs-latest create mode 100755 share/vgabios.bin diff --git a/bin/bochs-experiment-runner.py b/bin/bochs-experiment-runner.py new file mode 100755 index 0000000..17190a5 --- /dev/null +++ b/bin/bochs-experiment-runner.py @@ -0,0 +1,147 @@ +#!/usr/bin/python3 + +import os, sys +from optparse import OptionParser +from subprocess import * +from tempfile import mkstemp, mkdtemp +import shutil +from distutils.spawn import find_executable +import os.path + +def parseArgs(): + parser = OptionParser() + parser.add_option("-e", "--elf-file", dest="elf_file", + help="elf file to be executed", metavar="ELF") + parser.add_option("-i", "--iso-file", dest="iso_file", + help="iso file to be executed", metavar="ISO") + parser.add_option("-f", "--fail-client", dest="fail_client", + help="fail-client to be executed", metavar="ISO") + parser.add_option("-m", "--memory", dest="memory", default="16", + help="memory for the bochs VM", metavar="SIZE") + + parser.add_option("-b", "--bios", dest="bios", default="/fs/proj/i4ezs/tools/fail-ws21/buildartifacts/BIOS-bochs-latest", + help="bios image for bochs", metavar="BIOS") + + parser.add_option("-V", "--vgabios", dest="vgabios", default="/fs/proj/i4ezs/tools/fail-ws21/buildartifacts/vgabios.bin", + help="vgabios image for bochs", metavar="VGABIOS") + + parser.add_option("-F", "--freq", dest="freq", default="5", + help="frquency in MHZ", metavar="MHZ") + + parser.add_option("-1", "--once", + action="store_false", dest="forever", default=True, + help="fail-client to be executed") + + parser.add_option("-j", "--jobs", + dest="jobs", default="1", + help="parallel execution") + + + (options, args) = parser.parse_args() + + if not (options.elf_file and options.iso_file and options.fail_client): + parser.error("elf, iso and fail-client are required") + + return options, args + +def execute(options, args, bochsrc, statedir): + failcmd = options.fail_client + command = "FAIL_ELF_PATH=%s FAIL_STATEDIR=%s %s -q -f %s %s" % \ + (options.elf_file, statedir, failcmd, bochsrc, " ".join(args)) + print("executing: " + command) + p = Popen(command, shell=True, stdout=PIPE, stderr=STDOUT) + reconnect = 0 + while p.poll() is None: + line = p.stdout.readline() + if line is None: + break + if "Connection refused" in line.decode("utf-8", "ignore"): + reconnect += 1 + print(line), + if reconnect > 10: + return 1 + p.wait() + + if reconnect > 0: + return 123 + return p.returncode + +def main(options, args): + bochsrc_args = { + "memory": options.memory, + "bios": options.bios, + "vgabios": options.vgabios, + "iso": options.iso_file, + "ips": int(options.freq) * 1000000, + } + + bochsrc_text = """ +config_interface: textconfig +display_library: nogui +romimage: file="{bios}" +cpu: count=1, ips={ips}, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" +cpuid: mmx=1, sep=1, sse=sse4_2, xapic=1, aes=1, movbe=1, xsave=1, cpuid_limit_winnt=0 +memory: guest={memory}, host={memory} +vgaromimage: file="{vgabios}" +vga: extension=vbe +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 +ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 +ata0-slave: type=cdrom, path="{iso}", status=inserted +port_e9_hack: enabled=1 +com1: enabled=1, mode=file, dev=serial.out +boot: cdrom +clock: sync=none, time0=946681200 +floppy_bootsig_check: disabled=0 +panic: action=fatal +error: action=fatal +info: action=ignore +debug: action=ignore +pass: action=ignore +debugger_log: - +parport1: enabled=0 +vga_update_interval: 300000 +keyboard_serial_delay: 250 +keyboard_paste_delay: 100000 +private_colormap: enabled=0 +i440fxsupport: enabled=0, slot1=pcivga +""".format(**bochsrc_args) + + bochsrc = mkstemp() + fd = os.fdopen(bochsrc[0], "w") + fd.write(bochsrc_text) + fd.close() + bochsrc = bochsrc[1] + + statedir = mkdtemp() + + if options.forever: + while True: + res = execute(options, args, bochsrc, statedir) + if res != 0: + break + + ret = 0 + else: + ret = execute(options, args, bochsrc, statedir) + + os.unlink(bochsrc) + shutil.rmtree(statedir) + sys.exit(ret) + +if __name__ == "__main__": + (options, args) = parseArgs() + + import threading + i = 1 + # n-1 jobs in threads + while i < int(options.jobs): + fred = threading.Thread(target = main, args = (options, args)) + fred.start() + print("starting: "+str(i)) + i = i + 1 + + main(options, args) + + diff --git a/bin/resultbrowser.py b/bin/resultbrowser.py new file mode 120000 index 0000000..3dbc8a6 --- /dev/null +++ b/bin/resultbrowser.py @@ -0,0 +1 @@ +./resultbrowser/run.py \ No newline at end of file diff --git a/bin/resultbrowser/README b/bin/resultbrowser/README new file mode 100644 index 0000000..f955e93 --- /dev/null +++ b/bin/resultbrowser/README @@ -0,0 +1,19 @@ +FAIL* Result Browser + +Requirements: + * Python + * Flask (sudo pip install Flask) + * MySQLDB (sudo aptitude install python-mysqldb) + * YAML (sudo aptitude install python-yaml) + +Based on Flask web microframework (Werkzeug, Jinja 2) +and old school MySQL bindings. + +Connects to a FAIL* result database given by a mysql config file. + +Usage: + ./run.py + Defaults to mysql config file ~/.my.cnf, or + ./run.py -c + +YAML based configuration for table and variant details. diff --git a/bin/resultbrowser/app/__init__.py b/bin/resultbrowser/app/__init__.py new file mode 100644 index 0000000..a6c9e33 --- /dev/null +++ b/bin/resultbrowser/app/__init__.py @@ -0,0 +1,4 @@ +from flask import Flask + +app = Flask(__name__) +from app import views diff --git a/bin/resultbrowser/app/data.py b/bin/resultbrowser/app/data.py new file mode 100644 index 0000000..1552831 --- /dev/null +++ b/bin/resultbrowser/app/data.py @@ -0,0 +1,143 @@ +from pprint import pprint +from . import details +from . import model + +def scrub(table_name): + return ''.join( chr for chr in table_name if chr.isalnum() or chr == '_' ) + +class Resulttype: + def __init__(self, name, count): + self.name = name + self.count = count + + def getName(self): + return self.name + + def getCount(self): + return self.count + +class Variant: + def __init__(self, id, name, table, benchmark, detail): + self.id = id + self.dbname = name + self.parenttable = table # TableDetails + self.details = detail # VariantDetails + self.benchmark = benchmark # BenchmarkDetails + self.results = {} + self.totalresults = 0 + + + def getMapper(self): + mapper = self.benchmark.getMapper() + if not mapper: #try benchmark mapper + mapper = self.details.getMapper() + if not mapper: # of not there, try parent tables mapper + mapper = self.parenttable.getMapper() + if not mapper: # no mapper found at all, try default mapper + mapper = model.detaildealer.getDefaultMapper() + return mapper + + + def addResulttype(self, name, count): + mapper = self.getMapper() + label = mapper.getLabel(name) + oldcount = self.results.setdefault(label, 0) + self.results[label] = oldcount + count + self.totalresults += count + + def getResultLabels(self): + return self.results.keys() + + def getDBName(self): + return str(self.name) + + def getId(self): + return self.id + + def getResults(self): + return self.results + + def getTableDetails(self): + return self.parenttable + + def getBenchmarkDetails(self): + return self.benchmark + + def getDetails(self): + return self.details + + def getTotals(self): + return self.totalresults + + def __str__(self): + ret = "Variant: " + self.getDetails().getTitle() + " - " + self.getBenchmarkDetails().getTitle() +" (id: " + str( self.id )+ ")" + " " + ret += "Total Results: " + str( self.totalresults ) + "\n" + for v in self.results: + ret += "\t" + v.name + ": " + str( v.count ) + "\n" + return ret + + __repr__ = __str__ + +'''A ResultTable contains n Variants''' +class ResultTable: + + def __init__(self, name, cfg): + self.name = scrub(name) + self.details = cfg.getTable(name) + self.variants = {} + + def addVariant(self, var): + if var.getId() in self.variants: + return + self.variants[var.getId()] = var # Add if not existing yet + + def getVariant(self, id): + if id in self.variants: + return self.variants[id] + return None + + def getVariantById(self, varid): + for k,v in self.variants.items(): + if int(v.getId()) == int(varid): + return v + return None + + def getDetails(self): + return self.details + + def getVariants(self): + return self.variants + + def __str__(self): + ret = "Result: " + self.getDetails().getTitle() + "\n" + for k,v in self.variants.items(): + ret += "\t" + str(v) + "\n" + return ret + __repr__ = __str__ + +'''Overview has n ResultTables''' +class Overview: + def __init__(self): + self.tables = {} + + def add(self, table): + self.tables[table.getDetails().getDBName()] = table + + def getTables(self): + return self.tables + + def getTable(self, dbname): + return self.tables.get(dbname, None) + + def getVariantById(self, variant_id): + for key,table in self.tables.items(): + variant = table.getVariantById(variant_id) + if variant: + return variant + print("Variant not found.") + return None + + def length(self): + return len(self.tables) + + diff --git a/bin/resultbrowser/app/details.py b/bin/resultbrowser/app/details.py new file mode 100644 index 0000000..b288424 --- /dev/null +++ b/bin/resultbrowser/app/details.py @@ -0,0 +1,216 @@ + +class BasicDetails(object): + + def __init__(self,name): + self.dbname = name + self.title = name + self.details = '' + self.mapper = None + + def getDBName(self): + return self.dbname + + def getDetails(self): + return self.details + + def setDetails(self,det): + self.details = det + + def getTitle(self): + return self.title + + def addMapper(self, mapper): + self.mapper = mapper + + def getMapper(self): + return self.mapper + + def extractDetails(self, dictionary): + self.details = dictionary.pop(('details'), '') + self.title = dictionary.pop(('title'), self.dbname) + custommapping = dictionary.pop(('mapping'), None) + if custommapping: + self.mapper = ResulttypeMapper() + self.mapper.add(custommapping) + else: + self.mapper = None + + + def __repr__(self): + return self.getTitle() + ": " + self.getDetails() + + + __str__ = __repr__ + + + +class BenchmarkDetails(BasicDetails): + + def __init__(self, dbname): + BasicDetails.__init__(self, dbname) + + def __repr__(self): + return "Benchmark: " + BasicDetails.__repr__(self) + + __str__ = __repr__ + + + +class VariantDetails(BasicDetails): + + def __init__(self, dbname): + BasicDetails.__init__(self, dbname) + self.benchmarks = {} + + def addBenchmark(self, bm): + self.benchmarks[bm.getDBName()] = bm + + def getBenchmark(self, dbbm): + return self.benchmarks.get(dbbm, BenchmarkDetails(dbbm)) + + def __repr__(self): + ret = "Variant: " + BasicDetails.__repr__(self) + for v in self.benchmarks.values(): + ret += "\n\t\t" + str(v) + return ret + + + __str__ = __repr__ + +class TableDetails(BasicDetails): + + def __init__(self, tbl): + BasicDetails.__init__(self, tbl) + self.variants = {} + + def addVariant(self, var): + self.variants[var.getDBName()] = var + + def getVariant(self, varname): + return self.variants.get(varname, VariantDetails(varname)) + + def __repr__(self): + ret = "Table: " + BasicDetails.__repr__(self) + "(" + self.getDBName() + ")" + for v in self.variants.values(): + ret += "\n\t" + str(v) + return ret + + __str__ = __repr__ + +from pprint import pprint + + +class ResulttypeMapper(object): + + def __init__(self): + self.mappings = {} + + def add(self, mapping): + for label, dbnamelist in mapping.items(): + self.mappings[label] = dbnamelist + + def getLabel(self, dbname): + for label, dbnamelist in self.mappings.items(): + if dbname in dbnamelist: + return label + return dbname + + def getLabelList(self): + return self.mappings.keys() + + def getDBNames(self, label): + return self.mappings.get(label, None) + + def __repr__(self): + ret = "Resulttype Mapper:" + for label,dbnames in self.mappings.items(): + ret += "\n\t" + label + for db in dbnames: + ret += "\n\t\t" + db + return ret + + __str__ = __repr__ + +import yaml +class DetailDealer: + + def __init__(self, configfile=None): + self.tables = {} + self.defaultMapper = ResulttypeMapper() + + if not configfile: + return + self.reload(configfile) + + if not self.tables: + print("DetailDealer: no details found for " + configfile) + + def reload(self, configfile): + self.tables = {} + self.defaultMapper = ResulttypeMapper() + if not configfile: + return # no details. + f = open(configfile) + # use safe_load instead load + cfg = yaml.safe_load(f) + f.close() + # Read out default mapping, if existent + self.extractDefaults(cfg) + tables = cfg.pop('tables', None) + if tables: + for tablename,details in tables.items(): + tab = TableDetails(tablename) + # pop: return and remove when key present, else return 'notfound' + tab.extractDetails(details) + variants = details.pop('variants') + for variantname, vdetails in variants.items(): + var = VariantDetails(variantname) + var.extractDetails(vdetails) + benchmarks = vdetails.pop('benchmarks') + for benchmark, bdetails in benchmarks.items(): + bm = BenchmarkDetails(benchmark) + bm.extractDetails(bdetails) + var.addBenchmark(bm) + tab.addVariant(var) + self.tables[tab.getDBName()] = (tab) + + + def extractDefaults(self, cfg): + defs = cfg.pop('defaults', None) + if defs: + defmap = defs.pop('mapping', None) + if defmap: + self.defaultMapper.add(defmap) + + def getDefaultMapper(self): + return self.defaultMapper + + def getTable(self, tablename): + tab = self.tables.get(tablename, None) + if tab: + return tab + return TableDetails(tablename) + + def getVariant(self, tablename, variantname): + tab = self.getTable(tablename) + if tab: + return tab.getVariant(variantname) + return VariantDetails(variantname) # Default + + def getBenchmark(self, table, variant, bechmark): + tab = self.getTable(table) + if tab: + var = tab.getVariant(variant) + if var: + return var.getBenchmark(bechmark) + return BenchmarkDetails(benchmark) # Default + + def __repr__(self): + ret = str(self.defaultMapper) + '\n' + for tabledetails in self.tables.values(): + ret += str(tabledetails) + '\n' + return ret + +if __name__ == "__main__": + dd = DetailDealer('./test.yml') + pprint(dd) diff --git a/bin/resultbrowser/app/model.py b/bin/resultbrowser/app/model.py new file mode 100755 index 0000000..d9529f2 --- /dev/null +++ b/bin/resultbrowser/app/model.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python +import MySQLdb +import MySQLdb.cursors +import yaml + +import sys +import os.path + +from pprint import pprint +from . import data +from . import details + +"""Get command line options""" +from optparse import OptionParser +parser = OptionParser() +parser.add_option("-c", "--conf", type="string", help="MySQL config file", dest="config", default= os.path.join(os.path.expanduser("~"),".my.cnf")) +parser.add_option("-s", "--host", type="string", help="Webserver hostname", dest="host", default="localhost") +parser.add_option("-d", "--details", type="string", help="Detailed information (YAML configuration file)", dest="details", default=None) +parser.add_option("-p", "--port", type="string", help="Webserver port", dest="port", default="5000") +opts, args = parser.parse_args() + +"""Check if configuration files exist""" +def checkConfigFile(msg, fname): + if not os.path.isfile(fname): + sys.exit("Error: '" + fname + "' not found") + else: + print(msg, "->", fname) + +# Check sql config +sqlconfig = opts.config +checkConfigFile("MySQL config", sqlconfig) + +# Check details file +if opts.details: + checkConfigFile("Details", opts.details) + +# Instantiate global detail dealer, will be initialized in reloadOverview +detaildealer = details.DetailDealer() + + +"""Remove all characters from string except alphanuermics and _""" +def scrub(table_name): + return ''.join( chr for chr in table_name if chr.isalnum() or chr == '_' ) + +"""Global mysql handles""" +db = None +cur = None +def loadSession(dbconf): + global db + if db: + db.close() + db = MySQLdb.connect(read_default_file=dbconf, cursorclass=MySQLdb.cursors.DictCursor) + return db.cursor() + + +def closeSession(): + if cur: cur.close() + global db + db.close() + db = None + + +'''Populate variant results for overview data''' +def getVariants(cur, table): + restbl = table.getDetails().getDBName() + cur.execute("""SELECT sum((t.time2 - t.time1 + 1) * width) AS total, resulttype,variant, v.id as variant_id, benchmark, details FROM variant v JOIN trace t ON v.id = t.variant_id JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address JOIN %s r ON r.pilot_id = g.pilot_id JOIN fsppilot p ON r.pilot_id = p.id GROUP BY v.id, resulttype, details""" % (restbl)) # % is used here, as a tablename must not be quoted + res = cur.fetchall() + rdic = {} + # Build dict with variant id as key + for r in res: + # if variant entry already exists: + variant = table.getVariant(int(r['variant_id'])) + if not variant: # if variant did not exist yet, create it: + variant_details = detaildealer.getVariant(restbl, r['variant']) + benchmark_details = detaildealer.getBenchmark(restbl, r['variant'], r['benchmark']) + table_details = detaildealer.getTable(restbl) + variant = data.Variant(int(r['variant_id']), r['variant'], table_details, benchmark_details, variant_details) + variant.addResulttype(r['resulttype'], r['total']) + table.addVariant(variant) + +'''Get overview data for index page''' +def reloadOverview(): + overview = data.Overview() + detaildealer.reload(opts.details) + cur = loadSession(sqlconfig) + cur.execute("show tables like 'result_%'") + result_tables = cur.fetchall() + results = {} + for rdic in result_tables: + # r is the tablename, -> result_FOOBAR + for key, tablename in rdic.items(): + table = data.ResultTable(tablename,detaildealer) + getVariants(cur, table) + overview.add(table) + # Check if objdump table exists + cur.execute("SHOW TABLES like 'objdump'") + objdump_exists = (len(cur.fetchall()) == 1) + closeSession() + return overview, objdump_exists + +"""Load overview data at server startup""" +print("Loading overview data from database. This may take a while ...") +overview_data, objdump_exists = reloadOverview() +print("done.") +## Get overview data for views.index() +def getOverview(): + return overview_data + +def objdumpExists(): + return objdump_exists + + +"""Get Results for one variant id""" +def getVariantResult(table, variantid): + cur = loadSession(sqlconfig) + restbl = scrub(table) + + stmt = "SELECT resulttype, count(*) as total from %s r join fsppilot on r.pilot_id=fsppilot.id join variant on fsppilot.variant_id=variant.id" % (restbl) + where = " WHERE variant.id = %s group by resulttype ORDER BY resulttype " + stmt = stmt + where + cur.execute(stmt, variantid) + res = cur.fetchall() + closeSession() + return res + +'''Show objdump together with according injection result types.''' +def getCode(result_table, variant_id, resultlabel=None): + result_table = scrub(result_table) + filt = '' + if not variant_id or not result_table: + return None + variant = overview_data.getVariantById(variant_id) + mapper = variant.getMapper() + if resultlabel: + dbnames = mapper.getDBNames(resultlabel) + if dbnames: + filt = " and ( " + for dbn in dbnames[:-1]: + filt += "resulttype = '" + dbn + "' OR " + filt += "resulttype = '" + dbnames[-1] +"' ) " + else: + filt = " and resulttype = '" + resultlabel + "' " + + # I especially like this one: + select = "SELECT instr_address, opcode, disassemble, comment, sum(t.time2 - t.time1 + 1) as totals, GROUP_CONCAT(DISTINCT resulttype SEPARATOR ', ') as results FROM variant v " + join = " JOIN trace t ON v.id = t.variant_id JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address JOIN %s r ON r.pilot_id = g.pilot_id JOIN fsppilot p ON r.pilot_id = p.id JOIN objdump ON objdump.variant_id = v.id AND objdump.instr_address = injection_instr_absolute " %(scrub(result_table)) + where = "WHERE v.id = %s " + group = "GROUP BY injection_instr_absolute ORDER BY totals DESC " + + cur = loadSession(sqlconfig) + stmt = select + join + where + filt + group + cur.execute(stmt, (variant_id)) + dump = cur.fetchall() + + closeSession() + resulttypes = variant.getResultLabels() + return dump, resulttypes + +def getCodeExcerpt(variant_id, instr_addr): + code = {} + limit = 8 + cur = loadSession(sqlconfig) + cur.execute( """(SELECT instr_address, opcode, disassemble, comment FROM objdump \ + WHERE instr_address < %s AND variant_id = %s \ + ORDER BY instr_address DESC LIMIT %s) \ + ORDER BY instr_address ASC""" , (instr_addr, variant_id, limit)) + below = cur.fetchall() + code['below'] = below + cur.execute("""SELECT instr_address, opcode, disassemble, comment FROM objdump \ + WHERE instr_address >= %s AND variant_id = %s \ + ORDER BY instr_address ASC LIMIT %s""", (instr_addr, variant_id, limit+1)) + upper = cur.fetchall() + code['upper'] = upper + closeSession() + return code + +def getResultsbyInstruction(result_table, variant_id, instr_addr, resultlabel=None): + restypefilter = None + if resultlabel: + variant = overview_data.getVariantById(variant_id) + mapper = variant.getMapper() + if resultlabel: + dbnames = mapper.getDBNames(resultlabel) + if dbnames: + restypefilter = " and ( " + for dbn in dbnames[:-1]: + restypefilter += "resulttype = '" + dbn + "' OR " + restypefilter += "resulttype = '" + dbnames[-1] +"' ) " + + select = "SELECT bitoffset as 'Bit Offset', hex(injection_instr_absolute) as 'Instruction Address', hex(original_value) as 'Original Value', hex(data_address) as 'Data Address', resulttype as 'Result Type', details as 'Details' from %s " % scrub(result_table) + join = "JOIN fsppilot ON pilot_id = fsppilot.id " + where = "WHERE variant_id = %s and injection_instr_absolute = %s " + order = "ORDER BY data_address, bitoffset" + + cur = loadSession(sqlconfig) + if not restypefilter: + stmt = select + join + where + order + cur.execute(stmt, (variant_id, instr_addr)) + else: + stmt = select + join + where + restypefilter + order + cur.execute(stmt, (variant_id, instr_addr)) + + res = cur.fetchall() + closeSession() + return res + +def showDBstatus(): + res = "TODO" + return res + + diff --git a/bin/resultbrowser/app/static/css/barchart.css b/bin/resultbrowser/app/static/css/barchart.css new file mode 100644 index 0000000..b68912c --- /dev/null +++ b/bin/resultbrowser/app/static/css/barchart.css @@ -0,0 +1,5 @@ +dl.horizontal {font-size:12px; width:850px;} +dl.horizontal dt {float:left; width:300px; clear:both; margin:0 0 5px 0; padding:3px;} +dl.horizontal dd {float:left; width:500px; border:1px solid #aaaaaa; margin:0 0 5px 0; padding:2px; -moz-box-shadow: 1px 1px 3px #aaaaaa;} +dl.horizontal dd span {background:#91b4e6; display:block; color:black; text-indent:4px;} + diff --git a/bin/resultbrowser/app/static/css/main.css b/bin/resultbrowser/app/static/css/main.css new file mode 100644 index 0000000..a6ec20e --- /dev/null +++ b/bin/resultbrowser/app/static/css/main.css @@ -0,0 +1,214 @@ + +body { + margin: 0; + padding: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #444; +} + +a:visited { + color : #444; +} + +a:link { + color : #444; + text-decoration: none; +} +/* + * Create dark grey header with a white logo + */ + +header { + background-color: #2B2B2B; + height: 30px; + width: 100%; + opacity: .9; + margin-bottom: 10px; +} + +header h1.logo { + margin: 0; + font-size: 1.5em; + color: #fff; + text-transform: uppercase; + float: left; +} + +header h1.logo:hover { + color: #fff; + text-decoration: none; +} + + +/* + * Center the body content + */ + +.container { + width: 95%; + margin: 0 auto; +} + +div.jumbo { + padding: 10px 0 30px 0; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +h2 { + font-size: 1.2em; + margin-top: 40px; + text-align: center; + letter-spacing: -1px; +} + +h3 { + font-size: 1.0em; + font-weight: 100; + margin-top: 30px; + text-align: center; + /*letter-spacing: -1px;*/ + color: #999; +} + + +#footer { + text-align: center; + color: #444; + font-size:10pt; +} + +/* + * Table styles + */ + +.codetable, .resulttable, .overviewtable{ + font-family: monospace; + margin: auto; +} + +.overviewtable { + border: 1px gray solid; + margin: auto; +} +/* +.overviewtable tr:nth-child(4n), .overviewtable tr:nth-child(4n-1) { + background: #fff; +} +.overviewtable tr:nth-child(4n-2), .overviewtable tr:nth-child(4n-3) { + background: #e8ffb3; +} +*/ + +.resulttable, .codetable, .overviewtable{ + margin: auto; + border: solid #ccc 1px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 1px #ccc; + -moz-box-shadow: 0 1px 1px #ccc; + box-shadow: 0 1px 1px #ccc; +} + +.codetable tr:hover, .resulttable tr:hover { + background: #fbf8e9; +/* -o-transition: all 0.1s ease-in-out; + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + -ms-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; +*/ +} + +.resulttable td, .resulttable th, .codetable td, .codetable th { + border-left: none; + border-top: none; + padding: 2px; + text-align: left; + display: table-cell; +} + +.codetable td a { + text-decoration: none; + display: block; + padding: 0px; + height: 100%; +} + +.resulttable th, .codetable th, .overviewtable th { + background-color: #dce9f9; + background-image: -webkit-gradient(linear, left top, left bottom, from(#efe), to(#91b4e6)); + background-image: -webkit-linear-gradient(top, #efe, #91b4e6); + background-image: -moz-linear-gradient(top, #efe, #91b4e6); + background-image: -ms-linear-gradient(top, #efe, #91b4e6); + background-image: -o-linear-gradient(top, #efe, #91b4e6); + background-image: linear-gradient(top, #efe, #91b4e6); + -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; + -moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset; + box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; + border-top: none; + text-shadow: 0 1px 0 rgba(255,255,255,.5); +} + +.resulttable td:first-child, .resulttable th:first-child, .codetable td:first-child, .codetable th:first-child { + border-left: none; +} + +.resulttable th:first-child, .codetable th:first-child { + -moz-border-radius: 6px 0 0 0; + -webkit-border-radius: 6px 0 0 0; + border-radius: 6px 0 0 0; +} + +.resulttable th:last-child, .codetable th:last-child { + -moz-border-radius: 0 6px 0 0; + -webkit-border-radius: 0 6px 0 0; + border-radius: 0 6px 0 0; +} + +.resulttable th:only-child, .codetable th:only-child{ + -moz-border-radius: 6px 6px 0 0; + -webkit-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.resulttable tr:last-child td:first-child, .codetable tr:last-child td:first-child { + -moz-border-radius: 0 0 0 6px; + -webkit-border-radius: 0 0 0 6px; + border-radius: 0 0 0 6px; +} + +.resulttable tr:last-child td:last-child, .codetable tr:last-child td:last-child { + -moz-border-radius: 0 0 6px 0; + -webkit-border-radius: 0 0 6px 0; + border-radius: 0 0 6px 0; +} + +.resulttypemenu { + text-align: center; + font-size: 12px +} +/* + * Display navigation links inline + */ + +.menu { + float: right; + margin-top: 8px; +} + +.menu li { + display: inline; +} + +.menu li + li { + margin-left: 35px; +} + +.menu li a { + color: #999; + text-decoration: none; +} diff --git a/bin/resultbrowser/app/static/favicon.ico b/bin/resultbrowser/app/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf9bfb1659a3f504b9bc26cf79dd052fb35ce4db GIT binary patch literal 36885 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 literal 0 HcmV?d00001 diff --git a/bin/resultbrowser/app/templates/about.html b/bin/resultbrowser/app/templates/about.html new file mode 100644 index 0000000..22d0562 --- /dev/null +++ b/bin/resultbrowser/app/templates/about.html @@ -0,0 +1,11 @@ +{% extends "layout.html" %} + +{% block content %} + +{% if status %} +

About

+{{ status }} +{% else %} +

Sorry, no status information.

+{% endif %} +{% endblock %} diff --git a/bin/resultbrowser/app/templates/code.html b/bin/resultbrowser/app/templates/code.html new file mode 100644 index 0000000..920b1da --- /dev/null +++ b/bin/resultbrowser/app/templates/code.html @@ -0,0 +1,50 @@ +{% extends "layout.html" %} + +{% block content %} + +

Variant Results

+ +{% if resulttypes %} + + + + + + + +
Result Table{{ variant_details.getTableDetails().getTitle() }}
Variant {{ variant_details.getDetails().getTitle() }}
Details {{ variant_details.getDetails().getDetails() }}
Benchmark {{ variant_details.getBenchmarkDetails().getTitle() }}
Details {{ variant_details.getBenchmarkDetails().getDetails() }}
Result Count {{ results|length }}
+
+

| All Results | + {% for restype in resulttypes %} + {{ restype}} | + {% endfor %} +

+
+ + + + + + + + + + {% for d in results %} + {% set link = url_for('instr_details', table=request.args.get('table'), variant_id=request.args.get('variant_id'), benchmark=request.args.get('benchmark'), variant=request.args.get('variant'), resulttype=request.args.get('resulttype'), instr_address=d['instr_address'] ) %} + + + + + + + + + {% endfor %} +
AddressOpcodeDisassemblyCommentResults# Results
{{ "0x%x"|format(d['instr_address']) }}{{ d['opcode'] }}{{ d['disassemble'] }}{{ d['comment'] }}{{ d['results'] }}{{ d['totals'] }}
+{% else %} +

Sorry, no dump found.

+{% endif %} + +{%endblock %} + + diff --git a/bin/resultbrowser/app/templates/index.html b/bin/resultbrowser/app/templates/index.html new file mode 100644 index 0000000..31abf68 --- /dev/null +++ b/bin/resultbrowser/app/templates/index.html @@ -0,0 +1,55 @@ +{% extends "layout.html" %} + +{% block content %} +{%if overview %} + {% for tablekey, resulttable in overview.getTables().items() %} +

Result table: {{ resulttable.getDetails().getTitle() }}

+ -> Reload data <- +
+
Details: +
+ {{ resulttable.getDetails().getDetails() }} +
+
+ {% if not objdump_there %} + No objdump found + {% endif %} + + {% for varid, variant in resulttable.getVariants().items() %} + + + {% endif %} + + {% endfor %} +
+ {% set variant_title=variant.getDetails().getTitle() ~ " - " ~ variant.getBenchmarkDetails().getTitle() ~ " id: " ~ variant.getId() %} + {% if objdump_there %} + {{ variant_title }} + {% else %} + {{ variant_title }} + {% endif %} + (Total: {{ variant.getTotals() }}) +
+ {% if variant.getDetails().getDetails() %} + Variant Details: {{ variant.getDetails().getDetails() }} + {% endif %} + {% if variant.getBenchmarkDetails().getDetails() %} +
Benchmark Details: {{ variant.getBenchmarkDetails().getDetails() }}
+
+ {% for reslabel,count in variant.getResults().items() %} +
+ {% if objdump_there %} + {{ reslabel }} + {% else %} + {{ reslabel }} + {% endif %} +
+
{{count}}
+ {% endfor %} +
+ {% endfor %} +{% else %} +

Sorry, no results found.

+{% endif %} + +{% endblock %} diff --git a/bin/resultbrowser/app/templates/instr_details.html b/bin/resultbrowser/app/templates/instr_details.html new file mode 100644 index 0000000..232c379 --- /dev/null +++ b/bin/resultbrowser/app/templates/instr_details.html @@ -0,0 +1,65 @@ +{% extends "layout.html" %} + +{% block content %} +{% if code %} +

Result by Instruction

+ + + + + + + +
Result Table{{ variant_details.getTableDetails().getTitle() }}
Variant {{ variant_details.getDetails().getTitle() }}
Benchmark {{ variant_details.getBenchmarkDetails().getTitle() }}
Details {{ variant_details.getDetails().getDetails() }}
Instruction Address {{ "0x%x (Dec: %d)"|format(request.args.get('instr_address')|int, request.args.get('instr_address')|int) }}
Total Results{{ result|length }}
+
+

Code

+ + + + + + + + {% for d in code['below'] %} + + + + + + + {% endfor %} + + + + + + + {% for d in code['upper'][1:] %} + + + + + + + {% endfor %}
AddressOpcodeDisassemblyComment
{{ "0x%x"|format(d['instr_address']) }}{{ d['opcode'] }}{{ d['disassemble'] }}{{ d['comment'] }}
{{ "0x%x"|format(code['upper'][0]['instr_address']) }}{{ code['upper'][0]['opcode'] }}{{ code['upper'][0]['disassemble'] }}{{ code['upper'][0]['comment'] }}
{{ "0x%x"|format(d['instr_address']) }}{{ d['opcode'] }}{{ d['disassemble'] }}{{ d['comment'] }}
+
+

Results ({{ result|length }})

+ + + {% for key, value in result[0].items() -%} + + {% endfor -%} + + {% for r in result -%} + + {% for k,v in r.items() -%} + + {% endfor -%} + + {% endfor -%} + +
{{ key }}
{{ v }}
+{% else %} +

Sorry, no details found.

+{% endif %} +{% endblock %} diff --git a/bin/resultbrowser/app/templates/layout.html b/bin/resultbrowser/app/templates/layout.html new file mode 100644 index 0000000..5aa0805 --- /dev/null +++ b/bin/resultbrowser/app/templates/layout.html @@ -0,0 +1,32 @@ + + + + FAIL* Results + + + + + +
+
+

FAIL*

+ +
+
+ +
+ {% block content %} + {% endblock %} +
+ +
+ + + diff --git a/bin/resultbrowser/app/views.py b/bin/resultbrowser/app/views.py new file mode 100644 index 0000000..240802d --- /dev/null +++ b/bin/resultbrowser/app/views.py @@ -0,0 +1,42 @@ +from flask import render_template,request +from app import app + +# import model +# import data + +from . import model +from . import data + +@app.route('/') +@app.route('/index') +def index(): + reload_overview = request.args.get('reload', False) + if reload_overview: + print("Reloading overview...") + model.reloadOverview() + return render_template("index.html", overview=model.getOverview(), objdump_there = model.objdumpExists()) + +@app.route('/code') +def code(): + variant_id = request.args.get('variant_id', None) + resulttype = request.args.get('resulttype', None) + table = request.args.get('table', None) + res,restypes = model.getCode(table, variant_id, resulttype) + var_dets = model.getOverview().getVariantById(variant_id) + return render_template("code.html", results=res, resulttypes=restypes, variant_details=var_dets ) + +@app.route('/instr_details') +def instr_details(): + table = request.args.get('table', None) + variant_id = request.args.get('variant_id', None) + instr_addr = request.args.get('instr_address', None) + resulttype = request.args.get('resulttype', None) + codeexcerpt = model.getCodeExcerpt(variant_id, instr_addr) + var_dets = model.getOverview().getVariantById(variant_id) + results = model.getResultsbyInstruction(table, variant_id, instr_addr, resulttype) + return render_template("instr_details.html", code=codeexcerpt, result=results, variant_details=var_dets) + +@app.route('/about') +def about(): + stat = model.showDBstatus() + return render_template("about.html", status=stat) diff --git a/bin/resultbrowser/conf.yml b/bin/resultbrowser/conf.yml new file mode 100644 index 0000000..14105de --- /dev/null +++ b/bin/resultbrowser/conf.yml @@ -0,0 +1,69 @@ +# YAML-based: http://yaml.org/ +# Online parser for testing: http://yaml-online-parser.appspot.com/ +# Some notes: +# YAML is case-sensitive and structured by indention! +# +# The 'defaults' section describes an *optional* default result type mapping for all tables. +# The 'tables' section describes result tables in more detail. +# A table consists of variants, each variant of benchmarks. +# Each of these configuration items +# title: Table title +# details: Some textual description +# mapping: A distinct mapping, if not set, the parent item's mapping is used + +defaults: + mapping: + Everything OK: + - OK + - OK_DETECTED_ERROR + - OK_WRONG_CONTROL_FLOW + Outside Data Section: + - ERR_OUTSIDE_DATA + Hardware Trap: + - ERR_OUTSIDE_TEXT + - ERR_TRAP + Silent Data Corruption: + - ERR_WRONG_RESULT + +tables: + result_CoredVoterProtoMsg: + title: CoRed Voter Experiment Results + variants: + x86_cored_voter: + title: x86 CoRed Voter Experiment + details: Some interesting details about the experiment. + + benchmarks: + ean-random-4: + title: Random 4 bit injections + details: | + The details can also written this way. + The pipe insert the newlines. Cool, isn't it? + + ean-random-5: + title: Random 5 bit injections + details: Details about 5 bit random injection benchmark. + mapping: + Alright: + - OK + - OK_DETECTED_ERROR + - OK_WRONG_CONTROL_FLOW + Not Alright: + - ERR_OUTSIDE_DATA + - ERR_OUTSIDE_TEXT + - ERR_TRAP + - ERR_WRONG_RESULT + Timeout: + - ERR_TIMEOUT + # Another variant within result_CoredVoterProtoMsg + x86_cored_voter2: + title: variant title + details: variant details + benchmarks: + ean-random-2: + title: benchmarktitle + details: some benchmark details + + ean-random-3: + title: benchmark random 3 + details: some benchmark 3 details diff --git a/bin/resultbrowser/run.py b/bin/resultbrowser/run.py new file mode 100755 index 0000000..1084893 --- /dev/null +++ b/bin/resultbrowser/run.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from app import app +from app import model + +app.run(debug=False, port=int(model.opts.port), host=model.opts.host) diff --git a/share/BIOS-bochs-latest b/share/BIOS-bochs-latest new file mode 100755 index 0000000000000000000000000000000000000000..2d3fea31f67a8c140e70b71cf14ceacd397923ab GIT binary patch literal 131072 zcmeFZd0t2n_}VSxndj31gF`StQsJg2)m;A#NxPq=SxviJipU zwC(U_d$T=9W*ol)0!)J70>~f&Y6N6%(*a_@B!ndW`<$wKdr5*b?|uLL zHJa|Kb55N)=hUfFr>gGl^qPI<7{+$b$H$l(*WTJ&GCPs&V+4v9px3>RSr}_iuX*KE zVYNAmu}2GCafRjY6(ymNrN>8}!IW0$JP_~us>vTcIp(^rv#`3OOUE9q(q*hEG89&~ zq2h}!tY&^4EA%jC1P@8KgYEercE$A8o}H{Qqsd|1qu+7a+0b>>7oYL9!@z5YG*?Y; zvCx0{(pRorbDk^5011*!yH>=fA9ojxVwFS8&i$I{haD};RvaLJ``tUJ9q1Q>IM21h z>~h4HpD9Wf^rl_${VU^no70ZwWd&%oOQC;oF|h|VI-1_Jc_ca-fJT2AMR?P$A^nxU zj#0anD-LXXy&BWrA^oAtm{UcUg8b8KL^(gbhAdzxna-rcMG4zLSaJ_@v`I(D99nUp za2xamcW0y3l@pIXoU%sBIpoScoM>@vbx!0uJzbO5}E~Z^^W$zV@D7i7x z(bqRvftR$8j1`Br>Rc-hkv&}wGjtaA96)36 zv7>p+ibI+&OuGzHj=AhTQ`vvPa4;rhFztOn1BUfEH5R~}?P;d6DlHZ6G?o1v1=osX z_q?O&EzTRU(u(&t58mcZ-UWL1a@&x(8`TXvN7mdL|vhC=?}eJE7l_X&8qwhoqdN zGgchk5>tL=t4>;Rw7g~OoiiL{F2|v<4yq0|?aHr7uMz%MnH+bY1) zr|;jYmG+k(hu_r%{Z3OkgwyVKG;2N?1NrmcmGYCl6a9WaWOL`9gpgA1!TKBzjKYMZ zE-hp=ql!VV%elt3&B#4iJS6?N)2C^59EG!$pE2$FL3wr}tL*c_`SKda7tSpnjj3$B z1{}6{wA&oUx>^2boL+66Ce5|tFJq2CCGTkJGB+9hp);}sIx$e6wR$P{U3cyYmllHf zTx7ERWL1*#8dK#B5+(nHluu$REsgm0E+>{SGPr63Z0d6U!76i3cwfd4aTQMlRHU{l zV?{-83V4X|hd&iPLymL?4r6-hbf@31*wLN*3y`>ng!xnM`%-SQ_gzqJgM(_NL(Ur5 zttO57fM=E$0>c&2KtAVwy_EmHD;;j;eTEqGxB*kvX~ug$B}wz&M;ET#_c>*w4M?p1oM*7xazCXCcVa60t!BVF?-Ff6^8npHd4}+(>DFU*33PtQFa%j(e+G} z8l_t2muA!(oek#cwMB8R-0KiQ%Dpbtx^k|U*Sv5M4Ize<(?%RlJzwWMXhvw{@e|&H6=z-4g=Eva@=v%6;$1ms|NKyWW<22$%x#AB8dF+*mYyX3^JDc{ zG!dA)Af?_G{}4!mxW@yy)OuUWV_~=_0=Tq#Tk7LsxF-X+jCxzz6JfY@0ojciW=qVKb{Inu)fMgZqw5@uYaO=C{)|t|1uGXZzr(iHvs+!N#+t#h; ztUb)YYW}PdBsD>jSIf}0-u4U=RMGISKl_Oa5$JR=R60D4sT;1CNgh#UjzR`SD zIwYM=C?T-$^yVuZf^G@&=OE2d4v9r?JG%tU5`sw0mwykKR;n|VccS1*pyX+1+jc#^ z;JCF7hS=KD_cnl5I&{@DPqg>25*?%U1xsrs`iem?)68T{&m5Ploh*@+`WEA}Xo$K_ zn09R=0BF$=w9^kb8eK822lddb_M9R1=pNEGfs0i7AqljzLuwK_6;hs+RGm7V|7 zSXSe>iQbJV-&8x%Ove;oDy8{R)j5!OEesDGo{zbTe?N@`IcgIUC~$pd0A|9WsA ziMBWo!MJgpZ-D5x(Anj8SZU(jWQZ_DbEQwEb_`VMd*D=3pVNRZEU?mw3s?8ha1~yb z>ZEpbwWo{M3Y~5KqCM`M2C$Iyss4O}VB~nmd2n2a7>G~K#*}(}YJ)kE!V?CC)xeFS zlBtBUycDYj@b-j6CNDtwJtY%#?;|{KA1@6_MMRd0QuTXD7wP#_gVgMbL;4#WVGz>@ z@9co6^-?nxy9zHC&b&LxF`%&2Us2*PyL7HR{cp%Wq<-WcF0chp7qM#;X{*v-pr;|J zUkl>%vDc&La6@7Z&?@(8;fWCR9jb=nM}|YKjI)pYG8DEApaR{+19RC>iLE$zu#W4VvrJSanZM=vnfKiJl3zE=3L861PM#oG}qKqSsw+!rol3w0QNn$r^a$iAF}>3y9hOdU$1%NAgL2MUs=|4wn$rLUQeb8zpl9)A#+;WH zVK8Dyp|+fWLVP4I)@9eV^qdSFBU&W@|XFr>rf@|vP~(thW; zCh27B=Wk-Ezl28HY2H=ShkJfBQn?Gmk6|*$$%#B&x&VM?l53+L!TM_mCAx!Xv9-w6 zojFZBHLxJ#TYuxlsCE24qrwXJ==lX;%%bG|ZJR*S722%gtRX&Us$9v%|E@SqeA3 zQo5y~?|0$(3C@F)xtsC%r0C(e#8)?3s+8r77A6Uc*J=2@)Qmowq&8`a1%lK^&A}(z zL8VkG!I1KaHcaEFY*a~cwTr@S;Qu82z*IgE(mS^_jKBtPOTz$Dc`WL?p+^a~TRy^u zw}qT-%h_a3@8y*SKirMhwW4@5vlVVLl^+EH4a-EsA=L1104dWRTK3^uqF~-Y9j^q^ zH9#!h@X=#Z6P8efSz1M{G`RVVq&7U^D%LS9JD7=FYf>RXnR9LDu`8I;@zQ(|y0UG7nJz!rj3|hbQs>^%4xXbf$bT_OXMTh zm3+XAe1NZ7y`&jvwX@TCD2g?2`>Ll(&iz@ecP&w4AiB1&K58=e z$f8Btn^;5FZc2Gd-q)0RN2Bl?0u>EHM#S@`Z3II;(iF?{ky=M%eH7C*bg`UxI69Sn zWkX4yO1X*rdNY=&cQ|{Bo4*e(1QcXx5!2qFwLjl8nG8dRDAjOB2A7deU)c>8#d%93 za*)%WDJWk-1q+%{x>k0^RQ3fRoLV%#1-)t4q0)<(9>@v}v0r27ftd%tmJ(?D!<(yP zy(cK0{3Ir-XBl-L!nPh_ELX(fGObW6Bv1MGiM+k+xNuYKv&y#svR!Pmq<%xt-)~az zVfy3Ix|vWfjToOM<$15^O0PXMgBRC+X%w1yhr=7UiT2&} zsKoZ|7K-4EL>AUUw3J$F{liSJx27N(+^oHU;xTjVk=lzXNDphznWbxSITvC-mR87E zJg_Ci?$BAooX0g>NujUT3@NYZ|B49LVQjoA0jybQSGiYvdteP5D?Ds`E9jdYmL8`G{7 zq8mhX*90AM;o4~FaGf;@6UiFQ8a#vu%*!BsSAg%VxVlV(t}ZiHgI-)K8l3x$&I3s_ zzvvhYXL+X`E!6)KP02jtHtCa+d2zoinHT?F$-IOa(@)oBCTZ$2`$DW_eD}k5e}7%( z0Ds-AIGj^7!8urw5qbR=V{;p%+$QL%ao;z%E=x1mon03|ytdBT2e2gk^~E7$6Suyuuzps5IP|eGwbPH(TN6m&O&X+sE^RqxCuO!?%$}9KnX)J!}#M+eYI% zh80Sg+U<~y71n1a@y}%bN&ROU_~8jKgZwa{8HVfwXuRhjP9EzrQ)bm=4%7fU1P4U* znM1iBE8{=VS*w|O1Z0jY?%8S1t~)9-Q{5|d?#w$jMeV(VBz-4=u9mYtJD&XfjLom_lhz!sZx^dLML(0~4vO{J7~AH>`%VHT{g_IK+>lPatVSVI(of z_)7c1LCQacW%szSqbv8+j1?zL@8lepaxWCc*XLXSKaGc3VW-dCKVe{B7t^P1wx(a9 z^q{s7xtIIFes!}GW9w#{Slw*1rfxO{dUjGwVf}19gG#fbNu}8aD=a_Th)-#DJW74R zFaMyFoGLBnfzLpbf&w5N-^eGilX2xA+)aaC@AB=E@bXMeU&u-PKP9Wxewk8OTE~(hYGa{f*ShjANOSac)&l~-2 zJB&oQF07InT|SLQqJPu%tdOdRH3 z!2N+jRKg1oNDtT3vKP<>Ltxs~FB&@!XHDPA{wT+wT)7z61pN%Wq(vzfr8-;GusU0` zw$2u#uUxD%y_4TmXEOpEhrf6zu-LFCj?*OoK=h_yyrR%nN&a2hZU&9xvb5io+fX>B z*?DOgTK2~=tF#~`{k=Nd(9}Ac9^ne^uo!3Cb+&$Nn>KzT+B@6Lj&Dr63Zhy+P4`zW z(5JuWylLLr2kU^qPe1*9OY5i7M^gKkrpm?ru+!q(#6IXx*(PeDD5;WhvxSUHTnp4* zNtPUq-l0gsl=G&K7U!9E4RUWVR;HMCE!9*mfhm@1E0@3yOLcs-4FKw@$ANDk9>-yn zDifV`I02c+^)v0dZ4wHVOK>A|+hktqgVGdUNeA2D zTT{qm%l(!10T=?#%{~Mr&dq)sN}QX0C`!bw-fE!+mG)s<`=y^rKTi4IWV#g7T$|qR zxYl~6a!D-Tdq^$8^PI(|ccxHGpt>xOz*U~lZ)L$e&W7Q@4WFH1YqX2 zkF2w%noZyTjGVGoQ#og(+ditirB1ujy;KjUve#v57uIF!Ru;X0r6>J8UzT*F_NLx> zGxh~sD5g~|^-D*b=S@_%Q+=L>xD0YHjX^^*8ty=x#bm(hkr^HB+@CQ0>!K+wwU~tM z%jz<3I_ok!u)=j_)n#_s9j~jr>N5TLTX#4Q-0gdN8-4y1{xIgio@p?M^r?I&ri^ro z-w4t=DAcI_2yv5i**zDk?4>NO(pb4v1E=$j1Ik&ebsmUzera;PXRY<=edogS2WR7C zo_$F<7sk_$YbKIWhSkMX;YAX#om|Yd;)2U@!C7N+HZ+y`ZbJ{w^EKE=?@ukgauhY> z6K?01w^8A&`#CEz6`X2I{kV5NO0yh?(`7mt1kQ#wDMwb4UAO-4(;zGo4@6$*8C+Kp z!aXygvY7w4tfPE_=N&nKQr^+%A%}JDk43vsJa^YCuAC;2NLx<1wlqqaxC2CDPIU3p zz({l0*_Q0U#-g$Hv}?<$N;|IBE=WzKmzF~no?k#tvA);Y#%XpJLB=}Uc($E3taY}@ zU)R~DG)V=ig_3Q;cG|v5TSw#YdnYGbqDKsqZ0N@zEw=8l(YV>>ONcEGA=E5Gq_VB@ zoACLt-&Ak2H~fiMF4x!FHaO5;o{KH0bV`|riapvKEv8*j_kmNT4u$zt$igg+%H<_Y zE3vyiZGMac%?T$B}23a)>V9OUqnNQ^3ZHfN1_CSzt+G_7=6X7)bg21y7=4TqCpq+Kr zu0EA>{H_E_x$)pb`5KDf2t9LUZO=!aHfEH2M9f+NS??tJ-PNS)&An!RsrpGn| zvAqy}f@Fk}?pi)RYIJ?pP^ZyiAJPXxYNP{|voz^7A+n+z)5YylmtBjER(5SH!v|8J z>{{eN*|qVkGP^dRa(QhczD?-F*=BZp?7Ui%erC)kIKaD6+h(YohrFdSGb+8N+`ly? zkU!vo7sT05r?)w-Nk_0!FOA{rNcBqcgyZB1MKQGV6x&Tn*{5{#3!GunNYfqb4Rhrj zEq$k8sL&yX9$Oe|6x=RsTLr^Gerp_DF@8)FR>u_mH15P`G@}&jjb8Tth zA{H3wq?cz@6ftlrZ&p*T(Rl1gomJ2L6O+`5jLVfk2b45?l?ZaCSaG+;PxJWon$#S; zep!M{9Y>%0_#sz&qjUhredkSpIFFcd)_m%Un3?K~{sab6`!k?FZo3&#G{HB=IS*!t zgMGShk6%Ti<iE z_uK`G<`0jGwU~!2XUj^mGiR^V#AWX=>X((qQALN3`4)55@s)X*E0?`^-!XgE+%&_= zIdik)XB{=_3@c}4FJy+5`E#>1hL!e(i<0i!RFV{@kAq$2FSsw8iLwUeSu81@;6^Pf znQBFcN)}5>(8v4zFu9;pYSapZi2}#lfmE$hOYrBk$R7o*QlpkCsh07UAmuGlrIwI} z(_%>yv`URys-!y65~RE(s?-t^aawqUpjB#$j+|64TB^dM8mcFb$$dmL^V`ToSB8_nGmLDLb#r&hU%FZre|W9o{8alq8h3v&PmXxI-aI5Jx$?yq8h5F zIZRJ;n4acvJy8wS6K5VFdiDv^vro95sD|o^!#=cB$1^ER&!liYQ4Q4-M@S)h_6^gs zZ@8YQhU$rDmU8mcEwk3#h97p7;wa6M5C)e{GqA$s-?)3blLo~VZE zIUr2W0bzO$2-g$UP(4$^^h^oUGbLP4R73R~7^dgIFg*u`>xpWpo`b^l92BPKpm04= z4b^jSn4W{f^c)(;ln4Y(V>xpWpo)wi zcXyC3CP-HjN*A;2#XIt*1?dbd*(}V0MIn^XK!nqSgs~xnp$0U@5@C8;z|h7J!Y~sW zIbnK$FfN2J%!YBCaAJTkK7=sLi1D0oQh+cagfPsC37l|pfG{zHFwBgJoN!8j&=f)# zW=GSq7suqKPYn>7S#pxFBlopXOPV?9-2u`*p`=;}nv%y*Q)XC{YhNiCtYWK}2CdhyHTWK(WzVwL3A^mYNxApu2bh@p zhA6zCoc%V@5{hJu2E3HBxFld>1)&06)`DjM37Rj)<=a22e$T~8_w z59!BjOqi{CM)!=)U>H#nWIii8>;Bwy)u2(>wbI_TmoBoDE)4&oi#A=Gju}RngI#1& z7Zba6Vbp$0AOA{?Hf@_0eHem$Sfj`iV$FvI$!F3h!Dp5mQW%vp^v%rG0$SYpF8ie($u?j zq4E^9Y@YkZ%GvfDu2aISEc@KFw6v)d!RM!?vDY=p^M8p_I(u#8bIb42siB_|cB7V6 zgn%eJ*St2W8&!5MR7PDd%=F>Rki+-JtS42k%naeokm&cutS42k%*^4;up8)&Sx>57 znOVY_Vaw1Pvz}DFGP8y=!@i<7W<9BTWmXc-?C#!~^`ru`?t`9>%||#lY*93?-O=4Q zdL!$dT{l<5My6MGJ;{1!*UgQv-RYHGPqNwHv$1y|e2{);qhBZtSM?&aNjJ*p2SyQ2Bhb){Ws*FdWm3FuQlc zTd>5rdw8I``xY#FA-n}kMB#9j({91C7s6Yx#0hpd%jvgZ*$d$hj3qXmz1y-E z!dtMkbZ1F(rMKbfh42|s3#ZzZKQoFxtcZZSMP32()+q#Mgy%^ud1(5OQ)M_JuO%Ic^v zNi9rP3scm>RJCxoT9~F5rmF?)w*{X}wUDJ2u;Uk~9JOFWAucv9HZ6VPq{&mJ-aT#l z>W3d$v$l|JT>I$b>z}raTyu{l?U|8j)1EOh+j_^-YXGr4vcWNW(-r>pn=JN?>z`QrND<>TmX>}O{-2nZb~nqO zo0|)sY-L{VO13gPckW7-mzz2F{ya<3>W9~@wX9yVW@C_l=KWc7@^C;#7s+{ai@Y!| z+hSj|(86p;k?A9k*&g5c)aKP2*IG8Oe)93BAGH*t-}M_UBR3e?Ec@InYO;vs6|LS_ zMA(h%pL+Q5^_wP5G_t(M97Su^Z+_ZRxNh~MmXS~=Z<1x>+D(q9)`l{%XXV-%7X-K7 zENw!%Mg7OHZ$+7{#P*L7*Ogp{m5(?!t|UDaQ<9;kxykhl4X7OXC0NcN5fd`{hN_8FAUN0EdD|t%qg_AE2d3(xruM~m;Yh!q zvBKK(=EB%hg|$BO)WR822d0jVnmV{Uc4}ek$U^A=5gnLX=r8?9WO|69_h-!o~_JyX&wsVw+!u!jC) z8phJK!?l1v!`MWfRmXJfS;i*mZ`T9%J;o+SrADFj9Ai_WM@FOcJY!R13Sx%Fuq}+; zZ5U+$Y%62aV(*Ma=>^878%G;aDq$=wZcH3XrHqY_Ul~6vp1sJ}%!IKCfH@g6BpMQ5 zNJN>%nwW{c8T+pJ0dpTSGh5l_J`eU8(1-Q0vb9M$Nl{5G$;vkNUD!9NFY9Y%Mahej zlapDpl|9?yJF zdJD5yS>bTo@aW-exRpIRV)lrb5p0B&J$Cz?+YPs~+pX-0)Oo4KRF-OGPma8AWZXzL z(#qD2nm;Oj6dPq_Gw!(O4$;pYqeqMurB!3LjtTZHO3TMSKX%AiDt~X>(s6^vv2j-R z%=jhaQ^vFLR`$q*tO>daY=V^)-?jLz{&%svtnA^m%rtEpOS7`4(-)*Crn7V_dun3t z#Ds}#qLq!Clrc$go-p}4lSS#SDfdnhrQqkCci(w;uqH~D>EgdI_zbp)6|lzu%V7Cz zC3_sDnQSpz#hyUvJM2NWnmviqy=)14n5{#}${u2mu%}R(#g?))>}ixT*)q14tw$+~ zEoX&n14`L!1$&fz7p30*&Axj!+sv4Su{qP`5CKYar_W_&R2n~T{5*o;-+hzsW1Bd3 z{*?IyurQW8HJ24pY3zcr3kZgP_ov^_92{$(XeWS$u?HqSz>0ZkVcJ3kmNy|!DbZKA zf6Es?zgPj4vzM5}T&PvBN>;^QW(<*Wp=+_eaVd{hRJ<&Tb}CodqOUAf;wRM+Sg$Je zDx3b|2H-D#m$&5A3!>~9#q1sa9Po2w;T zm#-gh_9uUKc4|pkjUzg}hA3RNt~tP#*EkwH8m6=f#?>kWQ_dy`a;YGD5Qg=jQiNSv z4T5m207^K1`OtxvkJ4I^_m@QIlYZs{vtW!$s-di=$OL`UF4#Rfy@Dh#(JZ{}&?M3Xb!%~wO3@_0 zrBDbiqSy4A^fP3WXIf1!Kksk z%%IYnFhq6C={yP@@&WQy@1r^xI%A|Gk@qSZdhgRgq4FA2*(8ol+c=ttrf(k32PNvL zAMVr`oCZ3ZoSlshy;_~Cpe-v4viOVfe~Y}IdV~?E`7=c^^tHrMjK&B#(H=eYgp@!z z44&1fT=GSGX3;k&;AQQ;SuR^UO*RRk>bmsl$8xGE?Sf>(h&9iQWt$E7#?85=C{-1=Vn*Goou~TmTz3o&c+NkDKq?{t3W0-i-0%$%MrUqF)3`s zUiR+b60dPggGGdS2L;TVUNhEqosV@AhQi=W3LDifa5MP6OPX$SBw?uKEjKvvZ(xdO z-x5OPIVONF#<1JanniSkci{gf8l9(kquZ&`BaTGHaWaX_msox2(>zZMCQ~uSMbD?6 z4{MnkxrT7Hf-cq4W|x0Sp^%3zQ@OK)7CH@Px4!+luQL$+Jbph#fCOmeDFOFGt!U#} zgVLL=Sixxpj0>*apL&>u$j7SWKMRmQOXS4gK1%y10`2F0n~aodrK&Po zKnb(PdKw^OB0=9)WE{e|y{Xg^g~X_lW=z!h;3m?F&qwzX%~d`Ehrjt2`IEumb!~|J z!>A^(?$$iD*T^wQ~R(heasK^G49)BoCwy@#BH^radH?p^vuV)>zbRRRvLCg-liHL0MuC#s z?*iT^=gaG^A^Y%DFv=1sayI?SF2`NQ$^kRkJ!MdeAY-9aG~yFh3ToI)%XcuV z6ZxTlQC{dlOmY`AZ_X*=TWU?gXi?MT{% zfTUs+56QQYs2pXrSH~#KD#0uoS)UhKR6&z;`q=qn=QST6J70R>S4nx*I)&KWQrZhWdt#*DzDrQa}I76JPWF*hMp*~k`hV6>! z#Wsu{cTwM5%nrq*8cN&WN7`=Sv!Kp59@Vr9Xt4Qq0payIf}A$->eOkv%B@s~#CS(_ ziy~QWNRV(IJS|_mD%noE3iPgFd_USXvxF%-1KQ`HDRTU-nR-^7SbY&JDAzI)3+!9F z+x?`{#U*l7(aP}zSi{;ai|wx22G>fXd+SO0Yp=WTbdjB`4Xl5&(Z8AIJemE3e9#N# z1Q+ze_@BY}r{yG|xbZvP1sqa+RO#^<^k}F)qST&1O^t(aexZYYrj8XSR97oH*qRZ~ z{-iXRjtU5&A9&|fZD7K(KKt1Dfb~f#OxC+V0YU8yuyo9L~0xY#t zh22gtf=~jcY;3Vv6B1H}=Q-PDmpdC32!&h%G^zmS!FJCMP+7r$Gx4gl-Sq5K0N?ym z*~L?o<>xm@oo~`=Vp62P-oz*B&5SO}e)ze@1G0M1MV+a1-?{KP-8Y1yUp z@*SYyZ`637p2?$R;5-U$1mObB{tL~5gq^5Ww|pYZ_#_00_fOcRr`aL2hd~n+Haie+ zDNfFxPt&;5yO}|@DjTf$XWhrx=awEAp@Fw`$v+1n0!273Rp5To8*Y@qeXlp%Xo0g4 z4xM4zcj7BUzwt$qqQhIG;XQSvUD!R8wR%a6OwpuofL$muOCVbi9EFUb$ZUc9v{z(~ zK)%~6(k76<>J>RhAb;K~a-Kl0?G-s+AXoK@Tp*BHy&~-bIjUFWLV=9!6}d_W<>|j3{huPS3DaBj3l5q6$@18&hM%GQ!vQfd3f`y=fC^%+`6KMp}q zRALI@p5Zv1<2DtSKm|HU4ifnmQG0z)nh-|5G@^;>Mq>@<6Av16A4Qh^rpopWuozM@ zfQSHCBWS_?`S~K8&{6CFKqQ7F6z#raDD&p@I9D#h38O)*|3qBbP@&IPWgJUaa-$ydQQ|%Su$~hk3}izC9vJfh;0Q>A{Xp8nqD`K59z=j`lQZ?4DEs zSSg8;HTej^B|5Pv1A;RD=WT1_(L&OQ(1AnvkKK<_*Fuz0W9=VMO!zl z5@au3j*jv~)(%(mR}>Rp7||XNOO_<29^ME->L}EulU6)S#`?YPHK>V}9%D z_=S_`z~PHf2$6iq0ZN-FB6&9yLL`3(ZNo`^Mi8}=;;*oZS2TA9`dG^WUqi9x&WwCh z`Td%zimy8}-ZGWvXlR+{mg&9>#6xyO2wHLFKgDNf-&)Hdp`G8j(5-Ws1C-7+rt;&A zcaG8_#wDagKzjAX~?s*0f8$JH+y(;VKtHh>9AIj=jN=Wys?VWk@?=SG95o%z^w5_y$v+cpQ+1UU*E)RzssNx^OVJi6z~&Hw3Yd6b5}HT} zMTFf9uB3B6`I3*wXPv&x>K`lp$D@Be>i?nCJIHr^6RTZHy^+^PRF^6Bv%H?hO0Qf1gvw-qjj!k;Zc`lPVfI@x_;A_?e6RZ12fV`LVN-;&$l8!*IKZyg!s+ zHp~Y1KZn?Kt`nQr;#l|>)qOKL1P^P(;*f+x#&U>-AXWhx$RTEeSOg>nM-eK!9-W;& z!#lgs>D`BDiT=#YvC&m=p_3>*{;Q(FNr-<6;vesnqtCeCINe!{{Nt(wGHhQ2Z>5D< zQ8=VU^JzFr@E)fk1hpK!8;Ff>81;EfrZS0v`#F4afnH!pTw)15lj%2~@}>CtkHcZZ z&$`BGOl3d8XVHEt&GIWG5RJin7vOP0&#Nv{#?FEXXC!|NpN>jCzwHY?+q%yfC86Ia zu-#{jlF=_BEawW(ga3tO$-@PTZ<3q`vF~lq(3#3hG_*g(ViYcl60k3S4tBQ+*hdK| zf^FO9-x9F52LkqQqt$>t7nY!a-5)a?0sAH*>|Z{&%MXI3K6O}S#bty;S_ysyU?vBK zMRAIj6vaz`zMasaQQX(*VHi&tQ}A-nDX3`HmxQmXXzWR#1jXjhIDxMxff5vt5dnps zaLXw{@d$6u6N|uhMcI}7RG|3w1}vNhKg3vg<8WCUy7DRk?!+g2kqFJEA3a6;s!&=b z)V(Qa{~Yyk1KrK;^>oSuPw|`+ zCvLrAz8$8@imy6-BdYL8o<#fpPd{$B9VjehT3;VRAo_g;Lw`ll?<7)EEJnWPs_=;* z*&z8e*rlbTlTXgtOWI8+` zYU;{2PF*hozNuyMk$*r_au<8`<NNkr{!LPD%)aONa5IB_zd!8wJ{*qa8&6y#+w z9edN@xzl!eXs8C^lS7&C9iP$wM>(*93;EtrIRB71`(QEw{;dLjo`dfRNL@x!ZwX56 zQs@?e4j1)Uhxz(zDqF3Mpn$#9Q;6>g z5Sh^9psgRqwvb@e&nZ2gqv_D|1a1N;h!Z&M2XVBC{KR$x-`EP;+Nx|fdTa#!JTlM$ zO9)Qc2A&tVb~@d|(+hl;H-umwT-M^EgYt0s)D;ND_lXKc`zN44mx26HIcj^6TB=73 zrm`}eakTMx9oR|QI(Qem1%nRS{r%@BbV!Snl@7l3tK`*I96aDGWnz`B6<=d^)PcY;PzR+ANkstqJR;(90NI(_JfkO4@qo%eK)gs%+O06me{I9RjM}{4)qd zV>Sn)qsm3obpsvCs&bWl%;f?Zp07a;`%UV58CIM_;*mQNZvfrh5Nr-$Q3A%i%lvdW ztj_klkD<6Y=M;}6suTS(A;JRaw@&oEg1py>{%e8jZK4+u>VG-Wx1vqAiGJdP?h}3O z@xYK#uH4&1UveCMyKLVw(OW(UOmyD|ArsyGK`#@%}Fx@BmuL1kl6aD%3|GkO6i0Hy6`f1Gl zkcoaoR09*en(E;b{Y?UOpXfgnbhn)7n*`s$lzD{e>V%?+K8#M0)d_Xi(SXmSeD!%npe;Xn}0zTDMLEiYN`^@(8nH}BB%#KlK_7h<< z``M46X>T*TFPVVP?2A}>DK+|9S;CvDY)Nz%Q++>@EAqN>nx4uUS!Ih?t~tb-S!MgW z$8ztXK5^VTpYE-EXw?B z-$wgzHC8@_=G_9qf%o8Wsxcq>kc@e?%63&*^hNj%UG(RF2nhm<(04*=R=a#xu*%b~ zVN~}tQ4kfAGm!&u&PxDVemW74;Jr=3qe6A{skBIk}8hEfp*5QQ=8+12{r>Kp5O)4JkvW;>rNTp?H5WEtLP7>Cw z+trysOH04dUPp>vz0YaI^E&6|&v)6*VVN1Bt{gf+p>iO(Kc=J8@O-m|Kxm0Y{+v1< z@4e48LX{GqYF_(Nsr@%n~JImXL?p`U_S2 zQwQX>kAX>GES8}nHuGBB=OribEF1Dhywxzn)>e!bZT!YEek>J`hER41j`7Mf_LOvv zwYBgTZIpf`%0I0y#(M!uWqUmy6T=$9Q&Do>M5(~+8%}%x1`$Q@L|1{?z4feI1Y*Kt z_<_S?W>vN;c*uwD4|VVqe)Wi2TUhOSSgnnlVJMozpwQwv&K}?h*M)UZN4|he;xh7O z5>m;RUA7ic!VcoPC|&oZa6IP%EVlx1XihoI;-RhuDd+oD6`CkviMouFPD7!+@bbBi z!X>T+gU%0dZJp+_O?{ljlk3?1KIe?-uJqCUPH`>XtX^fKMVT3SqmG@CDqf11is~lpa zw+GG;Bt(dlfhR!TCh;WO$NCoFapgb!Td`|bCpL+km+y#w!@(YKBdWJCd9tTuW@0%N3JqM22nAeR) zr}NweXK?>>m}~!6Y?mpOoK#|f7Vs-xqItzdFesPM)E>+m#x87aE>NK?m^Q_IsQN|*Tk-;%GOMU z$}cL<(-9mU?_s6kZ&*;di6epFZ(JOfvtb~;d+Uet3{f~PPo#omlcj=7IQtZG$gYA* zB**Ck?!uErld!Q2hwta`!T#b){$jcMtAB{onsUlp6!`=ybUgXt=1KX%10dpVK`gn) zgiC)pMEb^V(pR7{mwt;V9G8ozASOl+>4%V%4!nqT!Buc^A5NHFIv^-R#o}kBC*?Qy z^RrT#XkYCwN)>I?O&dLjF#Z6ZXZlFd^cP2h+&XY^)aJ*B4f!Z;;5>p6);Remcb}C(`k8kLsWk;V% zTdVuk=GHv<{yGsa#3bS25PYTsig=-lU;7PWh9ZHw&&5*(t$bG{;xas=LT>fVaJ?$G zmL3>%Z=Q!W+2x-i0PAs&CbwGYfVJwS=GJ>E&b7MVxX>Edj|wbEs4z2%ZG2bZHB<1i zD7@wec;OhQ7j7ai4(B$2ZQN5;F};mu9Oh-kJt*yFnpUr<&QK8igcr+n#i>@;tEXGt zdr!2=$M?aE)FvZH#56>70z@Z4bhK6eZz6Kj2zfdPK{U~dDw1kjKHZnzdYz+yK+1Dt_}g0bS#Q35V>#dyamRdXBO-HAa4 zEwFvs@Ipwin$(t2iE5mJ?F%E?JOd}9ffq2EOB zdZ`!($MoS(p)14>3obOlj>&e<3c-7R5Spr?J_`hVvViwf9Y9-=+=fh0s%V7YHDYRE zsjG>hs()8wtEW)3>QAjmj5VSjEw~H}a!C}kcLoa z%-wI7JE~P@#2rTK9Lf)^h!i+ZqeJrm2$3Y{qRw}FbJ3^X?e3z>-tE;zv)_e_!nEAn zNXV!cvW~heSDeN)JBw*{vQ@T`%>1zzcLAc)FKWY__x7(toj0C)oa$-=YGDemMT2uk zyXR?Pfmwh>d+Y$L6M!@h!2ZYcga8a9fLE(Qk{DVJ5vpD@osJkkc&lh**CPra9XR}pv{Z}WErpG|msfP4y7>2C2@gBGEc z?{2IC)$)1M14`3aK?}5^=u|@c2KiFxX6-b;r!o4ed=LM`X@W9kKcY~EaKBKUkb4CH z+eb6Br8}8F5+r^W$*qF+0Tk^Usy<&@MHFcl(7p1&>8}W{cCn7I=%No#&y{tZ!fLeI z=RDD#2XG2HSbv=d+wd-UBHqyFGRzFs;#>FtUck~n(7*ey#G*Pi}R?euY>1hH{!(kzv{$0>@@k4}P|BbfEeMulX zvi>2j;zV~)YFDLgkoQ52XPu(uED{69F1}F#&;$XZH=}3RI*JnT&Cg|S;1v$sgoz%k zV41oqV->ypaRc$VmVXslNNpkbx(shDVwb}|nt_q9$d)uIRWJTomcx1)Tua*DG zoqrnKzR2VI+=pad&?tTulIMNGqbps1T_OMZMHEcsmFR9q{sT^#T(*?dF3FZciB@0l zON_i({y}$yZ#{p#Vt+LqOdONxQW7bBNK4;>uqs_H*y6dHVOXjiN&+a;^Z;SJ20iYm zK#$@vobU4K>m+Ud6Muj4)q5X|3ZwJR4%EFFR16V%9I1piuF7i}ol)_b^&wUW+?^8i zmt3a+<}@&P*(=%eQ-$pSl4*+5*%Y5<95ut% zUQB*%1;}$3g^uVb+`zzU^8cV8m=EouqwtI|fnFmJzlP?7eB+)hZzQPahoUil{DmkB z2nOA#F>Y-L^av-z`+Nkm2-y80WFrJ9gOg!ZBr+^m)YQyjzYwsI0@krR*uy9R(h!;4 ze-A$|Y9YQVhDlV*`&f=M&<d}}Ta$ETk@x#jS&+#E36hy~LW!@*{!@c7~@HBuv{+Ug}smOQj% z2`T@;5pNswe#5-YtlFl8rd-T2tal-^$9n=lMG+EbJl|YIOv64A2e@7ja0r_;-*_bQ z{*G1O1y-0PvbHBHiQ#u_{KZMt-<%Lz;m_feIPnhY&R6JLGcMIswz7TPZKg8K&2fpQ zvbdY$bfz-%&2i})_hlq*9z%JPbYO!2cTx8z&HL*D`ft*G*4*#rin92$EttDtT!yLa zb{muG0#Jin&?w}#>lJB6d#alxB_n)Y_ zSRA4hV)@5?=w);Hi=>eLC-DCJhxG5jFE3I5$#PP_bH7D|KsQ*(xJYW3Bf4 zzVMEuMI|H3R9=9`T@r8#6ckOXv{99K_^$ya@c5lA0s2tac&?B?1jNHomrPW!DSuQ* z(f)n{$$v3pBW#zu`UDj;mA{0OPHY_}saiMV^+BBM3*(RxapZ`%-Eo7ClSg~?VYn6D z%e+KW2$n`(V&gVy4&myUjUbVa7@uZZhziZ9?zE2XpwQ?J#1e z?_0DZnZ9!A_~yFLwj+bS?%iRhuW38h&{z77L-chgS>(F!_Hk_EHyP2J2L?R(qX)_! za6RyY2Y&XzYY+VHfwv#U3XV z!`EByy*hb{2^%{aV!g@fW*!;6ZVK)7Np8otR1lnutWKR*zp7Zh&pX`e2_(?nsz5l? zcl6e1qtfUsTtARQa990yS^4uw_%Rgl^j2!+t%;syh-lZCOWFqY0@q+id5ZdYY6zR6lYw*+?)NCC-lS5KM=s(b ztqKLr;$EH`3YySO*nm6Y(x|!8hTm!9N0dv^rl)@@$e9XKUV_QU2Umk1lDY_;ewxVb z<%{?H6SXQ)6A};P64wI6LrLJ36E*1JCAyG#(#?KK#|P2ccPA`K?lDfWO7mY}6<;z1 znAdpP{-_#ePI~uZ9l?zt(ka~E(XUf^c*4^q-}h%ULJmT^bBdHRsIEqwrX3>U;64l| zLAPP2gfILuSqHx@#;b}QsV^W3$q&WT&Y&Z{M1)ufrE)j{4&A(OG9A4l2@o;HHxg6z zaz@PN!GWpzz5GY-f7JfM1Gx+Jd5_v3%=>VW?|t8RWnpXnSS)N&P`2B`X7m}x?KhRZ zdBgWHjTpAU_`y4IK}8o>t9Q^_<_1@R5l1m}`50}rLS?-?2Z$=08B$X&fgLOXCjqEr z9N1zKWH@gh?814)RVN*b$|8~;R|QX{of zkgB%y7@D{0$g#PdUkDo zm2J2;9~+w?JWWl(rRGgaf@bRrYa8%etFyI*)%4S(h3Uunuddc!Se`R6f&gBK-If?N6*o5o$7-tYV)Qn9|KD#y=0r7x zv+~ADfMefaD>|~HgX;k9*qedgIF1jsN{G^`M0JK7}llb9Ioj`VLK? z*U}&ky_)%RhN_PD263L{;C=OvstDp|`RMmEf~F*xXBo&2DP$yq_=$}x@-(m#uO$af zsp7hR7sROsQ*q})a4W!j9eCrZG(;2cBrWas;I8-|>1uT>WT)#_{(FZ0;#B$h4(Gun z(9qZ?O9lPCqqKA|C|W>SBO0g;;m6cuE^nd@Ho2w=YeM$%u#)OTd@D`*Qxk4F8nEQw zZA`%LK&V~%;&4QuR=jWU7d!*~YrsSuepzmM18&BjUZYMF=DTl_3Q<88kA%w;&f>oV zEJEQIs(f2ToI&Xs$ z1{AS)U_A*Ncqg$9X>u1`s_$XGJA5O@;|G<$o*Bb74^*}ok1ZSV(4vQ4dg#PM1C~0M z{(Wi6GT$)~QY4#2Dj0!B$!YwCNCkMdV>Bg@qkU1}=X=uks0!da&Evl(&m6+%Y8@|Q z!5T7?WnibtGQfd{nLlz&3Xe>$@$x_(3@r#>@KRr2Vr|Bo6`G>$H6{fP^wvT(*RQ6T7?}I={ZlM!Weps~q_k20+ z^!%p+*d_pYD6Atj1~x?=PX{EaF%xb0tu6X-pWm={&t*`r!qnUUCYt*aJ;PBiL47CH z`7d|<;7xHzSahBfI#IB7PHkqEAOeRDBZ+W6^>OQpf z{#+Xv9UbY7?G&`3?Nujr{T#AYkrnQ5Mb3-9a;!9-OeX1b^W0pB%UbCaQl!Iq$_(Y?%WhboMEVxa59{ zw|@f!7~ECeS-c)#QFdzR8;bxb!XWBUACfidNy*mR3gOrxJz3Gf-E@abg~zl}>^+|IGUxZOvJhmRYMvHrjI zz6LJpD(n9ajDR=-sTrw@lVMq@p;;1v`PQiA3qdbNDIm-Qi9pN@Vws_~2BOr~R@?Tn z1?^jHEtc($vK5AzC8m~{sTrw@zj0hOa|r=wp6@yL_nSANdiMG6=fD5|1LgegJ@?#m z?>+aPd(VA4S4!N~6c%qqsN-oBG=xD0RIoO6rltnrgC5t1#ExoiB_`wW_Z8(-!KE%6 zyvY${oP(jbdV$$LH~Q52>1wB7g)oP?Zl(_Ia7sV1_-eI-n~`B_?U7M2!nVfsqPGV*!~44vQC}s$MR~AF+>I2C;>PThwYBG=touxP(iyQou4QeC>$#;2%jjK*8U1Z&S1I% zS!a`Ftx6xDVai4GQ66ksm9s#DYEKqDaM7cEB4knB$|wOCl8a%X-J7q&gpKZj3gyCD z9)0QGaBGrrp?S%IBC=eUUs!Cn85h_s7ITTwVlOC&R1cGoWV~Jr$spTG{pwRbORqO) z%RZ&^_e9u;(h|~(waB|muzM**&|#VTTW;%%;6-19o(4vp7~yUo#j$=AUnPoU$O$b3 zM#4M>BSpwkQ%I&1xQmkVJW~2$oLf6SL-`Os(j)vx&k4xvw>7@Z?x+dKYy-SnHrG>- zEO?wBtxz?a2J|tM&G@hVv-uR!_RHqa$sd@h0MPaUJIRCW`mner}91ssMhg7fa~G2mn)BR0WYZU?U#{Z zzpFg%&Bq78@z#L@9zIGXtKg6Ds`DT0EaFHbu>*ZrzxtD(%Gu%;H1VNsdI*i^HZ1-oB|;Qrx52&fhr|91;Huo2&GE- z{`?fa`Au*cfE1j<-w27>MfDn-!iyB@T!a)l=!~;Hk=Tk}C>XC)CUtHc!h&lpgK1ph zr7?tBAi9WP8el_j2&>5$xghqEP2^ zy*R$ExvSV!k8aj!QActHP;b$X zJOMqTi`*iE!=_O=uRAYzH4*9}dwvPHlFo}Ixr4UaUAaQE%suuaIZFQ5X}iXq7xyQW z2652BFT}8nPgMPKwMh(zkU@rNlbfmH7Q6t&b(iZ-+PAv7V`SgxN4B<)G(}6K^dnn3>9Eeob0hDJex!;q-(k#uwiAwtF&8mrGh?QlbKZr|V#0Czs2J z#%*IG(m+tXvG*y$$RyOR_|_Q zI8j8ctlWGA6BkFdIwFS>Iwpn5kOaoENZ2Knou?!XiE< zk-f@2UMnlD%2UrW_x95bf{62I7*rZVH5wgJSf3#J&SK1*_ahx;M8njnFh%6-8|~Z| z<*=#wOObT<;Yxy>*ny|9G_%33Iu657Q8d&f%Xeo6(h~iy=HVg~6D0|u19|j_fIQv7?;J$%`ICMyE?s3h0E zMFuwGZqE&-Bi0z)uerf=$clY~Q#Y8JONa9d2dD9*fj3WU)I9wTl7Xpylye2`o8P25=7{~^yT9u75u%*hRAOm(}pamJQl^`Q>MX*_Z zaQ%mtBoE0Cp3qpk>~Biu6QI0yS%Z=w9h;R|(y>*EBL`MQX^oX4ZmpXC@!DmZm3Y8W z547Mem*HsXmm~u{!*p*1`$7eka!#y$tb`9-uiD7Y2v<-h(}!3e!H-FP z1#mUWw)bTec@wc!aXgKjB8NBtrnN=c^hR+@r4T7TnQ9HhL(tF_qZRfQ*t3cy)(ftZ zAqJNxFaasEsI*(#MUEz(BPT4VHmjHzM~_9J5)T&TLio zlV6pMBUqt1!iA#cAE-4)yg~h=0<@fwpgqx zA|f&8f=K6XJcDE4Jv}^LBlCjp%Rom&=|SPDQ5kyi4qTYBrdk@? z6xbt0%I|gn5*UGdHR+$c_3=&r6Q!PTt7ro*zw08e~ zgAEV1Dndp&78t1Z`G^o zH8!n`O98{`8*k#It+4~H$dRE%e&o*LX65lUsw_TA4vZk48v{p>rm9l)k`)-AaDq^>o@*%c7&bc}!lknmu0v9b&&7oIRE|Fk0$6m>d zB(NN&C_UZ{4^z&pW+-hz5p;kQ?1K`zmq1vFA@N@z^KdXF4wY>Uam4wUHjRRyQxi6n zX2KpvAji}YE*khtFeAaZCde|tm$>bT?Hbi+x!MnZDtoq_0bzX0zg78*4ErP?Yy?@d zZdD$ounN-`f%VKLf6(E`Kpa@|Z=Y-;vQ?QS13z1B`V8|YtjxjcE-v_RzD!M3rX~Z9 zgEp-;?ZG;z_txCH@Xwn2m|({O0iXE?&=|DKFDMjoLg|GzIjm_xp3l#o z3H7oLlZ1U=tuZQIXNclGt>#q6bQ$ zw&$2B{SRsWS<=6V{GQS#$871hYvHNVZzexU`eeMR>Y#^@(qzCm3c$U5v?dL734v$= z@j3nMcEztY?S}TQmiMc*sHub_A*Ro9r35$##GGO`KFQG~@O_?eRoQDXx7wLZ48TN zBzfF9OqotFDZst3he&AG`hkW?P!fSwoA#nL-RhVj34jh^hcnT13FCv%Vaj*tKj_gq zPMl|kVanG8QxoDNh+#?-fv{ApBJ#{GO!*5(zD-8vxm}o2<4=%hcVSAkAHl0+ULGWn z%;p47>24BTj5?IdC4R_bCCDN{TK6+fLN}~J*Wto?2*fI$F2xa%L>V^3j|gnM65ZZ@ zAU=c~rbGqOO_qq+M3>sm7j7b&q~@eS&xR@{TX zD)>{uIsWg3qN5KSeZWz)6~9Lx*oyz?`&6;!|E8GyM;{n9Nt8U15-k>Ap%Te?@QM51 zo+((y`AslaYRl8`+P)eQ@VFoFc%eSv#Qd)NrGAkq$=HSND!t?-l6@Xm8v#$ta3iizezbg zRyF_l+GRVH$t%}dcH4Zq?(<+59VQ4R;iFte`RmzDEBr`ldhhu6 z3bw)70KMAaJP_{uBk9%2A*Iaj-@t=KJny_webHp|DsJOgEsb@4j^3#w*+Ylrxjn6y zk}D5PaLY1-2phaaUb-ar9LPbgv0Ols9qXi(bUK%yk*xEQq=`4>vmcS1jS)bB!U$w@sUXuTyiI z8-^ZeecJX5D=cx=un)tA2%VTG#WEQ6dS?6WVa{P-h@8sYN3>z^1XFEwDr0blBb0p6 zE1JM7{|u?7hOd>80_F=d0SlvU#MfA^XAs#u#5pk%QdMqOKa3WFIl31fA%~@sV7NMy z&IpF98vEp6_y9@gN`iYz{dM*?9^ppN%sTs7oxjfhBn4qMKp9kZ_HqIR>FfmrV{VYn z{`G3p*FieFTZsb-cnNjOFHE(}6(YkhIQxaM&W`o(m0Z7H1@fA8cDM2u8F&DSCA76F z({6)N{Z7PpwdsJr*4@Xn8$c9YD%CPJYIBcIsdg(hpeRdno>J{r7Ez#2sdg*(NbIj5 z3sR|eD>E1e{f<yh^oO8KL=Esdg)|{jB$3<$E9W9$KlAnlrR8(t7}hOVym+%9BKs8unx~ zY|@<3u+Ohb)|}nSL`tHM3c_~M}EkJY5^Czfk z&bRpyR5j;G1d`c==Dd$mS2gDw{g747d87mdY0eKn2vH@?8I=*NIUgzqc~$vWHRm0E zAXRhTEkPPxRdc?a=u+GHiZtf~s^)w^)10#riCfTD+=3u^2hf5JkTkL8jMh#q2yklm zR4{OtH0Rlr8uivOI_Fo&HV;a;mCEDBDdGHxV5ChOoF@cn(+1~;uC-}Db$O0Daz036 zKvBHv@|pA0>O7?b z>*G|#>^_nM(uF_JIp5bg`cor~L_O%0Er{neZ15xz;d+Xk$f1AWP}Piy-7i!IS8}jw z&*TnYFc~Qz;`tn|n)CRejMX9IsT9qSG~3o#-XZ}lTW;%eDzqbC;)_MMm1ibP+4m2LPs5kt41vz@(ag0 z1r_XZ4p&W6%<~IZuYVL%_-fNY^gA)sovSt??jkU%!Bv2#IAleo)}Q@E&Na43i4d+~ zE~6`M)Xlgvbc35;$($`eqvYo@w+n|du$R$Spgm!qf-BrNLprk*iQoV=DQQFG^lPA; zehu`WNNrcqs68=S;PmS`1XFv$69<~X8ash#zY$x}TAgJ}ScvHy%l|q56c$nnTG0~; z5lYv^nu(0d2>?a2Uy|wLwU#E^Fh0nM>X*f-->9d9Z;%bALU zQp^ZU!La2ZoHzG^i2&~uY%}^Uj6DHUFuy$@|Gd5jR8*Kc1ryGTdeIb2;4Y}srPr*R zJWBNFoUUq(WwG?PYBoylmHu|kfX!!ib>h=fIUfts1LV%^X?157WgifaRXp0iRkx*1 zsV7*qtzF)>MW=`n0ZWEZ!%kqgmh-hz&l{(0i(`1>w3Rkcv7y>t!l8)>Wmc&>q{5jF zNDLih=d1rjPgVIyNiwq+_cxnjDoT znkFJq+8jGU8%KI|`%_LCw<>Q+v_qBik5rkC#fPf9btj1aF~w=?V#oBf4K)wAMoQaB zy%(gglX|dnzR!$eQ@V2X1F6bED}rdgh-KD;Rr8zIE<2>W))nnCqODCRKl33k>k9c6 zLdJ?Bwur0dD@5~ppz-{ZSf%A_2%&kWqM!J%`$%kQuw27FL0RQF>JA^~H&&FFOlJAh z-AtI;Y_h_%(}(^hp_8R`fApsq-LwnJD|87ts|A~huxdu|{i^w!*DiZkd6qCK>VXX+ zf6x8ZmqhZ zi>=#s|6}F6%S%VbL6;7XYsP&ZTa4VeE|Uo&AVzZ|%Q3D&5)PTf?GnC{vIo=7gZS5i z{?l;~PX|v}Gdp=675Z!8{4=zefDY<&;d~Cudnya(sw~|0fE*W`4-3~rt_Mk1+3&x! zceXlW_3+iDt1sYxTdKEIzq2-CHGLyi2Y=rLj6z6PdD?$zZ^B~){-OVzW}MRH>~=Y@ zJXiXY1{Rx&7BsM&4oy`avhxvYI@U!?0uF*bOdSIt1{#7HvWOs#GYFgI!*56~x4XP& zf;t^A9Kq+Unh9AwZHQD+Z_mRifj5^3m zPteNhwzW`(Jni0Qwx7afDBb>6-^WH*iTAPLbv#A6bfLC9bQ0X-_@&HsKnr{aG-#5j zW%+gTQ^mi1Cft4&h1!0OT-Gw>E2mbJP2t1v+tTAYo@ zChQJStYlrO(XRudp-VXmqX+)VEa&2Z`zaR+qM+@gSc;Ylg>s=#E)b|7P@`8)I!QU` zJrhI^>G_mnWr+;st_!?C0_aSX2QdxhGndE+2RSC`=`@Ctb3gO_TekVD4ld|F`CAAdAbmM~+Rd@3A(!~0o zsbj}uB-g=QTL&u${)4A~2DnHg+03i`N;RUFJ!L-@aXwpnwZn=W)A>|-H99yIHjviv zm4qLl(?YL}t`Eiid0Nkx%?G!a!{BO$<_kqOl+@ieK6HD=iV}Y}5%-(9Pi94hbOi*4 zlBsjFrbD`vhTP-g0b`?{a1O>q<^sV^DP+aYx@w~c%q-U0C*B8P_=xV_s)DSg|5o7E+KyR8gu zq`ruVP#-7B*j}bS?pt3U_dTU4L#dCGGUprU-3Sh2r6G0^bq*Ac<977I?78i7cgjrC z%K86i0iihA?PT{cc7Mfg7rS?{`#8HlVD~@Ry@A~)*!?=Y@m7PAI6oQOp^?@~Sy^p5 zMzAR=EK|Z<1e>bDZjmq;*-mxbq{7Ba7>sb^=!OcrRKm!%yJMOPiZ63*1O)p_eCr_wN?oZzH?Q ztXFuaEks5&flMNgCcLA_6Ck{U{c)ott`uIK#Pt*2llLKZ-OYi*yN`f=!uv7#y~6u9 z8Oq|C`A>-J2dEK}npznUEUs%L*ek9}y=XF8f%JRD^&awj#dWqfG(cR(6Ic`1D>;TH zu0zP@6W7D?{+HF3=&B0nIm(|w6_C9ZQ2EX6fHKS*4^QpNQz zXyQ^_O^hPNHHqC)Tt~B8it8|TOK}~@ZYi#j?3Uu{&ZDG)#dUN3`Qln9VFBX$yo3da zYlVabh^tM)0>m{-!UDu~ri4jx#Z{(be3@^6L(pQDzs}%_s&}Y7sey>29a76t2jH)< zA>56;x<&+GzD<~#Jo_Y^CHo-^vI7GYlOIz_&Lz)T?5~paD}}n^ojbDXHZq)AkyJg@ z+`bLzfc|`*R;Keqr3|U)-=1c4P1!Ji$6l>#^C}ySVcj*?e@Vxnq4g)J7`JqruD6$Z z*#f3(z0@zsqxDjck|&^-visxaNnF`W-7RtbdZ`%%3GSuF5zw!fiYLFfml`NTxtH2- z3cb`UwU;_)=4ipaR11Nu%~9wN<6}I{AFv%>+u<+udBMoP+>! zL-8t|p}l+!g=*hBuL-57ex1x~K{~-OyJaWy5xZq4^A5XZC$o;-vXl8OyJaWyEW3j{nM}$`kWO%mgavdm<0UMhletvF z0y>#!2@B|CI&wLUfKKM9g#DyWrbOjQN*;LP>mX3cN_Obfsrag5xiAz6T2CUy)jMk` zy_V+5*lEBD8T|~P9~hp&4KVt_WC+vpNYha^*WjC$@U*TrhpK?i`IwH%@RLdSFz z+CTfF1N=WY_luE}x)@%ri^S_HrWjv|{HF!p+#o?Gy?e>`9Qw)V{hYgmqxa?z^s7Ythto9jU^SD_<9O+ro8b&oeu4RW&=N6Ut5e0`c)VQWZC zT$jUY+wtUx#XqCT0hDTXUyY09 z*MZcz8VT_AH7Z7ns_mv3a`d!o;>^p^abx3ua!S!LJO1E%~UF zP#Br-#B#J7&&NLU9UM`;%2fOc!j}u}yu#HVb#0MbbhI1$Q6_f*Zk%RQexFJ0fmZzt z^2n|V1;*n5vQ=!PL8wnqG#4&-bYg(TvWFY6JVcM5h>KAKhH`+LO#QKZI9`o1!%Lml zjJ;5mIxicmz;RlpV7ks5Yut1;ZAg@{Hq@UMz`WMrX|Pm`3C9K|d!lXWW9NKr3yKJ3~N5Ixoze!c5N~+ic zJe}h4*hb<@Bw>Wwi!u`^xWWO*3N=y^L0lI~_C(cx+a%|+Pc1+W0VGz^gJD>?Q~pT` zBC6^_cb`6k`rci0%EY^8W6CjJxihi!OxTb>p`XJf(+}=V?)e+96Tb z341j2YwJAli)`i(bGY%uLus3mG#_{=x4&wm4RVT@tdh$;R$i<=><7(%yI;y$5!n z2BhLn-0C|n9<#rCe|2N!S36WGo;edD(%)Ga+WvAOauf4%0e+)iDux1sL8zu!k6`t+ z1bZm9zG7+%QM*yK1vnW=p;SZOmg`IlRo2}DzN0&pE!a6Rlt${zdq^0gNpDlq*&V}e zU>dtG;H9V=;HJ%kD3v7MSi%iHHSMz@%3LBGsu=HCZHh)GLuAk14Hn8<)lAwc{TI;s z12wTP$jU%mQbbUa!pa%Mz_Q&gCq<3|A~=$@>z4QR2alg2AZO zz(@&GD?CEx>N1%t%Fvw}VkjYYRg&ET53J%eaZLU1R5^$sadwpvcsbdlg;B25`f@eU z1py3mf%%5ymG=Iy$XcJLhV0@H?8_LESJ{&g4ckKyZJcq8A+%%_?Ny*fx(0CoW}U=^ zdZC6@Qy2(H>7f37kn38lo?TaAXg(ca%hvR#5B}i%gW-?nKYsnk@vk<#ddF)c*F`@v z+T+@$2`ZJ?Gn0PZTw#6g;tJzsV$WQ1V;J?sXOTIPli-A#t5Dyu{bp?Ix#K4i{0rZM z6e)LsH3VxE*jMvDE%A1`dOD=Na(<^{S16r?XjhJ=mttw8)B8k4e~OG=&-+A0hy2Q30O<5C)hlfs>^Z0PR)tJJ&8dtt?B2 zkucCEn)6?JIFCROgC>wdFRa~G3A}J7Wc^tiyJsJZ}uC`gfD5hQJjw_3)@vn z?_Xr3CGNCG(*WZ|nYX|EP&1$gf~MY@mhS%86`{G)ZolJBqSg9-xjl>sKJoYR_U4jk z%O+P$x>CFSZp)^_F|NLrO-f9v^1FBDl5O3g;n_PJZcpWAyq>VL{?u=(_gBTO5K}7g zQ@uCcbrJF#7+gyMsmkZyZ;#zUFD}%HnhE-v8}&64^)-|9HIwxDJTE4BgBJMFgs64K(`Gvmb34P6z z`kG(rYo5~MwS!2UCa5hFu*O>ZfNlusboS|>*3{~Cj)vdVhUu^v zP#eqcLAttrl;8MM$){|gcnP8IV)7wd=mO?8*@_x0_MBOMV2HqlEnU!%S_@=`* zi6M0_)l3vXj947D%eC_x*D$za7DsGyg*1E<;u-*-k$j;I--NotHo5c--{>`h>!ROH z5p^O&Z*qTRKij&~-B6)dix_R!H6};Pf_*>iWZfXjkXBNUR?-oi&CPX})3-KF)LlW2 zn%hO)RcgqU9CDYa8?FN4>5GzH#{NxpBl#;!+P5-p7RojU<+@umR>s`{&s=zJWdI7A z`rj_7q=$me3NC0PSJsv=AzLT!}M)7&CYd8RX3{bqkfqzDd z<{5o2)_SV<((5Ah$_O`p&9m)q?r7!qaOD%rTjG)iynx&}TKQX+7QL~evHWl}n*LuS zTaSvpjg~PDb%MB|{M}>Oc-4*zb(ZfBS?VWFj`kV2CY%t)*#w;OKmSfJPR!+ABiOo4 zgrjGi7l0G`GbNO9lu&=1$|zNNYD|s8EQrcqEj&WW_6(i7BQ+h9;V2Q9ik2hs|;q?k3l6%?1JI*+tCTF-k&9brs zPY&btB&56YY^W^?zah4Z@vF1N+pX=EjiS=x$b3^->+yKbxXz_XK;E0mQUEesx2k~R zHfZ9aUA_+G^LQ-p3gL=R?qk=lFLxP}qwHbpb#)=Ge#z0m zHYCT`4Q~m{2H*(G3vJshFPzn&xC$CBZiDZRJ9r94F56fVwq6emV2 z4oX9Xxl}DooVPF+aAEqOFp+NwE(?nCua!jDqliC$O?_+DhEU=BL|{f4>ikeZz35jz z?=5tm@1F8(5U1Wd<#DbPc)@!xK$iNlHw6+tWkKL6&qf*ig!pgrC2GAg)5n*K)+-bI z_%d|8a`jK+i?5P>d_g6vd~yD+?S-?>m)p?p{Qfep8Jn5#Hmt?#6ox*Z5}!I{hW!c$ zeC3vnZHAMUjh%*nq^v3*-_PE^UWjO-C&b3$w}s$~>g6wNSIEv zb!`MSW1Y@9ScldhVo%)kO^l^-mu1X;%X>m720)qq^;_+IEi2suBJ(W>S!P?NSkOi5 z><8Aba_$2J48N9RMF?dNVNk9%DG`1VDa*cyUm_w)Uxao#-^taG(P&9cvv9SbRxBrxAIm>1Tralp49nd0p0kbkfcJwi!3Fohd<%1*I2|qC zD}KAJ(Q=37PSnCU3#y@V*O>iO2UqJPDR8nk)j+88Lfz~s%>2WZA6qs#V;mu?oE=mH zV-W-VKPO}iu;1c~^|erAeXYg{UFG~hK$r(8O(Lzb9jy0q{w)E%4^Y-icnHCXxj5;_ z9DiPBTu9nLRy}nu~&OB zOgu}{W5&F9;9xKyNX-u137XmnD zf|KdD|IG;vCo&jC5Xw@ZWHe^Qjlrtan2*MMx_Weo*!7LImo4>KRfZ1#{*C0~zf*VDRC>YcaV7m5+5x?$~v)Qxx*Wxi-%xjE#n>MyI} z28pV0bldhUy!??;m};L}HEm#u5VnhM#hmw4bz@)**Y#D?22t>ss)u9LIZU}&*%4tg zZaS?0FdQv=PFUqM{YsCpg;maptb7=1vL17sa*;WAQ*$rfrn%Q|S{&+}iuH)$KJ0#_l_?AG0A!yjQO4{O&ch*xDnQx`^5qomP*N zr*^!moZtR}YPrYT!+{HnR+$JY!BeUd1ZRvE>&P zs_Dy=C?tt#P!h!@W~;f-7AYnd71{C&?=@OViWV7%BNHGxqp&o)AV1f*0AX6uMxZQZ zS44{0MGVefP+(SrMn?*(*_N4`Z(V4%+02L<3&s|`e%O9^c3P%q_7ke6&Ei_0-u1KWTb*ikkPiJ*c?nGQ!8tdadAn$&1^K6 zloXW&VvR$I2sZauGr=cA4`PRTC3 z+-9^R>FdTV$hTRI1q-r+k`E$oFI<#eTnsT&Wu4e@(@Zc#HrpS{7oi2zZvYST@TwgN zPf&g3{dhJ1K+OC_#RcX?5JPjWuZdXgIXPylRV!yV(YtOa-5`%P&YV0cplm-vy{iad zk z-KN@I8@grkRPHMiuFuQN!`XlWa|!jj)|~7@9)d12W?OUe^VywUVm3ZtE-AV(Qgjo| zUbwIj#|?bZsXI(k#}O3K7tN?9mSmhXGbMqCfQ1WkbBY!%!e~&KyQm1VCCr7{3xZww zg?afZ(9g+){l^2;ym8ERd4YYHF9Qfl(yB4=X~>_3bLEv+(gcsAEb;6*B%_Uavxr+-_a!@YbTr&kkFe$y*$Xfho6!$1 z!~p#7#U-_X21y!Iy3NAB&Vrj}q)#%kjuN1RbWL!2$^uK5RY1MMwMj-3)Ewj3ae3(Y z?F*>4W{$x-X>5Y=-fSoXIYouGk|H_qd+RV#WZSYc^R1bz3iy>3{mt;)S(A;6%(?mY zMd;^k<{b2&cwf{{$+7~5p5L1PfY~_Q9x3k3&X@WVfa=I#D^laCltzypZ4^{qzfPG) z)54;{QIl?)l&a~EGG{r9ax;rj*JfLiaVml{=iGi9v%y;eBidx7h!l&mtRN29@8skf_AEb|j7jGV|Qgid8W)gLlt>Zr7$MORO~gTLTFPPb&44pEto5o^>` z>a9l%A7?jCo4mwkwxVfLI$ea%(!zg;HgZ2oavT*4RR)dE$Hzb>8D~zJo}My1_iFw> zQk0A`=j2&ML3YW#W`S`Wye?GPf!vVJOXzlqP6JFK7)IJn3i0d*Q&p=JD)H2tjJEtm zX6keBB>gpLHdZ^l_t_T}Q$|(I*%v^%4$3gRj5^N(=(WQ!?xF`6lbB?jJZH{rM$@Dj zGjC732^#gR8Q>`Q+}?3-%G9(uv!wn_dYv5|H}~L4JX)ddBL&n=?ie(s)@aK!s~S6M z2EnYl`6=rJC2gNIMRTs03`JKe=TfmoGes5NJv@D0(4@e69x63Hi8rGQ>yAB~{w;zbMci>$`toP7B$EatCQVT9&JfNRDY zft_&O)d`7Lk4Zr8P~EZ@8HI;{^9xYN;4c23Q%uzg2@q*o561Hv>opK|sxOrA_CkL# zw5kW})XtaqOOudWwAY4tI*~+zP8rE8EEb|$4MsTqVdYc zeU67iYWwSzc{?4yb=Tqu9`17t6LsTSrXanEEfXD&I&0$@dYN#HR%++6I|C=8aMj}? zeNC*s=3;%#{rZ|`aKWVJX?=a1sEiwgTMt8|vs_<40gx4XWx~jpWAt?cs6e$bdYs#; zO=emXnAVv6>jrEr3svshyRj@p$=$o@a1_vodv5H#SH(_X?6J5zai+21oga%F}z5g$YXY9;K{F>13Hsc*q_omZb!>0<=`jVLw5X!W$iybJI*a1 z{ikQKCx1O0_&>@4=aLU2M5oZ%CjO7e#%0mCp_FE35B=ZM>vY6DpH<$8al5=T#x|4= zPw!XU*6bIC+SEI#?`d~ZC(heZkNaW!+v)iA4RJ$Y6rtmB*S9jtHj47UhigBfowcXd zz21^r*QdpJ#26o9n{XtnBQ9(GoU_|6w2n+}wntH0d+BMtAq0AfYf$nxK8TJW5t6UX zOR|TyD_?$C_eM+Z+#de^1its6{JS{d+_>rAMY@M>4+s9kIgpyR@l5D(HkTW>@t>h} z5hpaiy%qlBn$LC`m#&~j41fQn39u*u;|D`C{*|8l&mqG@`VICJv_?m$ipkAyLox9K z&k?wz_HX(lGX^WJI@#@r(`~@NDL*}AdpOX;fgTR@aG-|+JskM=azL7adAYy9gkE*W zko)=a&UD+5xUllhRkoj%cPh46tQ@>=>#O`JH5(=boQZEcU#(X*-QoJylBHZe-;(We zQbwaaxWnJ`_y0KumM#D7@^_wHzHFIizo+r2XIX*U?OvJ~BVrPl@;7m5A_11hNWfB< zeMnA*DF%<{Xe01FBH1!|vL#t~8lQdVoo5?8(c#e#H8nMrC0i_(U+*t{P-O$kB#wXt5vBcwx z2yC*!<6(5dpudE&vV;VYAPNc!*k4fK#(xDOVQE8|p$&w#G{q)Zwur=n#L@#zr6Mb< zf$?G!va+%gVg>%i!VL>1$)02jf)WxsK~VlBPykjqwLb)e8GzkTE|zZjWwmV!i1FAMaLeA9ulA?&AkWlhb+L#UkVC0zvLuanXP`2>O3d)y~L4@5wV z;K)LmaBo=?I~M7cA>FL3GC_qmgoTJQY9O&?XwN|Q{dp3YHv}j%EJeLGXJw)M2gu*l zfb@qL00x}=o#0bqK^BU13jR{!cw2K;L8%4#O%TOgeuIz5d{BNg$USa1wN)^Hiv&3GgL?i| zLT;xRl914xkT8Vgg8z{RAW=$1qd#KA7PlzxTnDo@w>wHgKMoNUhu5!*%UZLudao-? zowQ!@DkiOQ7P++k!Rr=vZN0;i%G2bRCh8*^Y%%VwFb`<&owo5brr0}9WLRMM)iTkN zQYT_XNjU77xxc0RQ0Y>Kl literal 0 HcmV?d00001 diff --git a/share/vgabios.bin b/share/vgabios.bin new file mode 100755 index 0000000000000000000000000000000000000000..fa9806b76fca32f6e44cbb4a8e0bec637fb9e8ab GIT binary patch literal 40448 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