diff options
Diffstat (limited to 'oncology/dpfhack_display/fw')
42 files changed, 61310 insertions, 0 deletions
diff --git a/oncology/dpfhack_display/fw/Debug b/oncology/dpfhack_display/fw/Debug new file mode 120000 index 00000000..89798698 --- /dev/null +++ b/oncology/dpfhack_display/fw/Debug @@ -0,0 +1 @@ +../Debug
\ No newline at end of file diff --git a/oncology/dpfhack_display/fw/README b/oncology/dpfhack_display/fw/README new file mode 100644 index 00000000..46ffa999 --- /dev/null +++ b/oncology/dpfhack_display/fw/README @@ -0,0 +1,115 @@ +This is rudimentary code to inject your own source into the AX206 based DPFs. +Since this chip is very much undocumented and no information about the internal +firmware is available, the following strategy was chosen: + +- Leave original firmware as intact as possible (NEVER touch sector 0) +- Allow to manually put unit into "Developer Mode" +- Allow to return to default state using the RESET button + +Note that the Developer Mode uses two sectors at the end of the internal +flash. Therefore, DO NOT fill up the frame with images to the maximum, +or weird things may happen. + +When the DPF is hacked using the scripts described below, the Developer Mode +is simply entered by connecting the DPF to a PC via the USB cable and holding +the MENU button for approx. 2 seconds. + +See more about the Developer Mode below. + +---------------------------------------------------------------------------- + +The tar file contents are merely: + +- simple (yet unfinished and quirky) library to access the DPF flash and + the extended functionality when in "Developer Mode". +- Python wrapper around the above library +- Python scripts to patch various DPFs (listed in profiles.py) and other + auxiliaries + +Description of a few tools +--------------------------- + +app_detect.s, detect.py: Simple rudimentary detection for Sitronix/NXP + compatible LCD controllers and SPI flash chip. +fulldump.py: Performs a dump of the flash according to detected + flash size (often specified wrong by vendor) + +Developer Mode +--------------- + +When the unit is in Developer Mode, it registers itself as USB device with +the same VID:PID, but not as USB storage. This allows much faster access using +libusb and as non-root. However, the unit will still use USB storage SCSI +commands, see dpflib for the wrapping over libusb. + +Specific commands are implemented using the handler for the SCSI command +0xcd, mode 6. These commands are handled on the DPF by cmdhandler.s +(up to v0.1alpha) and by dpflib/dpflib.c on the target. + +Note that the protocol may change in future, once the internal firmware +is fully replaced by something more structured. Thus, you should implement +extras on the dpflib level only, never access USB directly. + +Prerequisites +-------------- + +You need: + +- A proper Linux system with GCC, python-dev (libraries and headers to + compilee your own modules) +Optionally: +- Possibly some knowledge of the 8051, if you want to mess around +- A working sdcc distribution including asx8051, aslink, etc. + +Usage +------ + +1. run 'make' to build the tools and patches +2. Initiate USB connection from the DPF via the menu +3. Wait a while and check dmesg for the /dev/sgX assignment +4. Run 'python hackit.py /dev/sgX' as root (CAREFUL!!!) to probe for + known DPFs and confirm that you wish to patch the DPF according to the + instructions. + +The hackit.py script checks for a valid DPF, so you can not accidentally +damage your hard disk. Also, it runs a crc32 check on critical modules +for more safety. DO NOT CHANGE the existing checksums. Only *add* new +profiles in profiles.py, don't EVER change existing ones. + +Before messing around, you might want to dump the entire flash using the +fulldump.py script. + +For those desiring to try adding hacks for other frame models, there is +now a short howto in the reverse/ folder. + +---------------------------------------------------------------------------- +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +WARNING: Do not modify the script unless you REALLY know what you are doing. + +DISCLAIMER: There is no guarantee that you will not brick your DPF. +The Author(s) of this code take no responsibilities. You are completely on +your own there! +If you bricked your DPF, check the URL below for information how to restore +the flash image. + +LICENSE: +You are allowed to modify and distribute the code, as long as you keep it +OpenSource. We just trust you that you have a notion of fair usage :-) + +TODO: +1. Windows support, fully featured lcd4linux support via generic DPF library + (I leave this to others. I hate Windows.) +2. Replace flash firmware with improved opensource environment + +---------------------------------------------------------------------------- + +Find updates and documentation here: + +http://picframe.spritesserver.nl/wiki/index.php/DPF_with_AppoTech_AX206 + +or here: + +http://tech.section5.ch/news/?p=68 + +---------------------------------------------------------------------------- diff --git a/oncology/dpfhack_display/fw/chartbl.py b/oncology/dpfhack_display/fw/chartbl.py new file mode 100755 index 00000000..a3015c6a --- /dev/null +++ b/oncology/dpfhack_display/fw/chartbl.py @@ -0,0 +1,96 @@ +import struct +import sys + +rgbformat = "BBB" +CHAR_WIDTH = 4 +CHAR_HEIGHT = 8 + +context = { + 'nrows' : 0, + 'ncols' : 0, + 'width' : 0, + 'height' : 0, +} + + +def rgbto565(r, g, b): + return (( (r & 0xf8) ) | ((g & 0xe0) >> 5), + ( (g & 0x1c) << 3 ) | ((b & 0xf8) >> 3)) + + +def gentbl(): + c = 0 + a = "" + for i in range(32, 127): + a += "%c" % chr(i) + c += 1 + if c == 16: + c = 0 + a = "" + + +def output_chr(context, out, data, offset): + width = context['width'] + for i in range(CHAR_HEIGHT): + off = offset + i * width + for j in range(CHAR_WIDTH): + o = 3 * (off + j) + r, g, b = struct.unpack(rgbformat, data[o:o + 3]) + rgb565 = rgbto565(r, g, b) + out += chr(rgb565[0]) + out += chr(rgb565[1]) + return out + +def convert2table(context, data): + out = "" + width = context['width'] + for i in xrange(context['nrows']): + off = i * CHAR_HEIGHT * width + for j in xrange(context['ncols']): + o = off + j * CHAR_WIDTH + out = output_chr(context, out, data, o) + return out + +def readpnm(context, prefix): + pnm = open(prefix + ".pnm", "r") + + d = pnm.readline() + d = pnm.readline() + l = pnm.readline() + a, b = l.split() + x, y = int(a), int(b) + a = pnm.readline() + + l = x * y + context['width'] = x + context['height'] = y + context['ncols'] = x / CHAR_WIDTH + context['nrows'] = y / CHAR_HEIGHT + + data = pnm.read() + pnm.close() + + return data + +def convert2raw(context, data): + + out = "" + + for i in xrange(l): + off = 3 * i + r, g, b = struct.unpack(rgbformat, data[off:off + 3]) + rgb565 = rgbto565(r, g, b) + out += chr(rgb565[0]) + out += chr(rgb565[1]) + + return out + +# gentbl() +c = {} + +out = readpnm(c, sys.argv[1]) +out = convert2table(c, out) + +f = open(sys.argv[1] + ".bin", "w") +f.write(out) +f.close() diff --git a/oncology/dpfhack_display/fw/detect.py b/oncology/dpfhack_display/fw/detect.py new file mode 100755 index 00000000..e667ae5f --- /dev/null +++ b/oncology/dpfhack_display/fw/detect.py @@ -0,0 +1,94 @@ +# Simple detection module for AX206 based DPF hardware +# (c) 2011 <hackfin@section5.ch> +# +# Run with argument: +# +# - generic scsi device, e.g. /dev/sg1 +# or: +# - "usb0" for hacked device +# +# NOTE: The LCD detection will only work on a hacked device + +import struct +import sys +sys.path.append("./Debug") +import dpf + +g_spansion_types = { + 0x13: ("s25fl008", 16, 0x10000) +} + +g_stm_types = { + 0x14: ("m25p80", 16, 0x10000), + 0x15: ("m25p16", 32, 0x10000), + 0x16: ("m25p32", 64, 0x10000) +} + +g_amic_types = { + 0x13: ("a25l080", 16, 0x10000), +} + +g_vendors = { + 0x00: ("ST legacy", g_stm_types), + 0x01: ("Spansion", g_spansion_types), + 0x20: ("ST/Numonyx", g_stm_types), + 0x1c: ("EON", g_stm_types), + 0x37: ("AMIC", g_amic_types), + 0xc2: ("Macronix", g_stm_types), + 0xc8: ("Apple", g_stm_types), + 0xef: ("Winbond", g_stm_types) +} + +g_lcdmanu = { + 0x45: "Philips/NXP", + 0x5c: "Sitronix", + 0x54: "Ilitek" +} + +g_lcdctrl = { + 0x66: "ILI9163B", + 0xf0: "ST7735R" +} + + +def detect_lcd(d): + d.writeMemory("app_detect.ihx") + d.run(0x18a0) + buf = d.readMemory(0x1900, 4) + + v = struct.unpack("BBBB", buf) + + if v[1] != 0xff: + try: + manu = g_lcdmanu[v[1]] + print "Manufacturer:", manu + print "Module/driver version:", hex(v[2]) + print "Identified module:", g_lcdctrl[v[3]] + except KeyError: + print "Unknown module id", hex(v[1]), hex(v[2]), hex(v[3]) + else: + print "Does not support RDID" + +def detect_flash(d): + manu, dev0, dev1 = d.probeFlash() + try: + print "Manufacturer: %s" % g_vendors[manu][0] + f = g_vendors[manu][1][dev1] + except KeyError: + print "Unknown Manufacturer" + print "Got id[3]: %x, %x, %x" % (manu, dev0, dev1) + try: + f = g_stm_types[1][dev1] + print "Compatible : %s" % f[0] + except KeyError: + print "Unable to detect flash, just assuming 2MB size" + f = ("m25p16", 32, 0x10000) + bytes = f[1] * f[2] + print "Size : %d MB" % (bytes / (1024 * 1024)) + return bytes + +if __name__ == "__main__": + d = dpf.open(sys.argv[1]) + detect_flash(d) + detect_lcd(d) + d.close() diff --git a/oncology/dpfhack_display/fw/font4x8.bin b/oncology/dpfhack_display/fw/font4x8.bin Binary files differnew file mode 100644 index 00000000..cd158c61 --- /dev/null +++ b/oncology/dpfhack_display/fw/font4x8.bin diff --git a/oncology/dpfhack_display/fw/fulldump.py b/oncology/dpfhack_display/fw/fulldump.py new file mode 100755 index 00000000..28c0ad2c --- /dev/null +++ b/oncology/dpfhack_display/fw/fulldump.py @@ -0,0 +1,29 @@ +# Script to extract flash +# +# <hackfin@section5.ch> +# +# Argument is either: +# +# /dev/sgX : scsi device (unhacked mode) +# usb0 : developer mode (already hacked) + +import sys +sys.path.append("./Debug") +import dpf + +import detect + +d = dpf.open(sys.argv[1]) + +size = detect.detect_flash(d) + +# Offset, size +print "Reading %x bytes..." % size +buf = d.readFlash(0x00, size) + +f = open("full.bin", "wb") +f.write(buf) +f.close() + +d.close() + diff --git a/oncology/dpfhack_display/fw/hackit.py b/oncology/dpfhack_display/fw/hackit.py new file mode 100755 index 00000000..5c7a5ae9 --- /dev/null +++ b/oncology/dpfhack_display/fw/hackit.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +import struct +import sys +sys.path.append("./Debug") +import dpf +import time +import binascii + +# DPF profiles +import profiles + +# If you are an expert, set this to 0 to avoid the warnings +paranoia_mode = 1 + +JUMPTABLE_OFFSET = 0x80 +HEXDIR = "hexfiles/" + +instructions = [ + """Press and hold MENU while USB is plugged in. +If successful, you will get the 'USB connect' message and the device +will appear as non-USB storage device""" +] + +ins_common = """To put the device back into (almost) original state working +as USB storage, press the RESET button.""" + +############################################################################ + +bswap = lambda x: ( (x >> 8) & 0xff ) | ((x << 8) & 0xff00) + +def dump_flash(d, fname, offset, size): + data = d.readFlash(offset, size) + f = open(fname, "wb") + f.write(data) + f.close() + +def find_dpf(version): + for i in profiles.KNOWN_DPFS: + v = i[0] + if v[0] == str(version[0]) and v[1] == str(version[1]) and v[2] == str(version[2]): + print "Found matching version info" + return i + return None + +def get_module(buf, n): + n *= 8 + start, end, flashaddr = struct.unpack("<HHI", buf[n:n+8]) + + start = bswap(start) + end = bswap(end) + + return start, end, flashaddr + +def patch_module(d, record, buf): + n = record[0] + if n == profiles.BINARY: # Write full binary into sector + start, flashaddr = record[1] + f = open(record[2]) + d.eraseFlash(flashaddr) + buf = f.read() + f.close() + d.writeFlash(flashaddr, buf) + elif n == profiles.PATCH: # We make a copy of a full sector + start, flashaddr = record[1] + print "Patching sector addr %06x with %s" % (flashaddr, record[2]) + d.patchSector(start, flashaddr, HEXDIR + record[2]) + elif n == profiles.COPY: # We make a copy of a full sector + src, dest = record[1] + print "Copying sector from 0x%06x to 0x%06x..." %(src, dest) + data = d.readFlash(src, 0x10000) + d.eraseFlash(dest) + d.writeFlash(dest, data) + else: + print "Analyzing module %d..." % n + start, end, flashaddr = get_module(buf, n) + l = end - start + start += 0x800 + data = d.readFlash(flashaddr, l) + c = binascii.crc32(data) & 0xffffffff + checksums = record[1] + i = 0 + try: + i = checksums.index(c) + except ValueError: + print "CRC32 does not match: 0x%08lx" % c + return False + + n = len(checksums) - 1 + + if i == n: + print "Seems up to date. Do you still wish to patch?" + a = raw_input("Type 'yes' to continue > ") + if a != "yes": + return True + print "Updating module.." + else: + print "Patching from version %d to %d" % (i, n) + + d.patchSector(start, flashaddr, HEXDIR + record[2]) + + return True + +def recognize(d): + print "Reading flash..." + buf = d.readFlash(0x0, 0x280) + + print "done" + b = buf[:7] + xmem, code, dummy, offset = struct.unpack(">HHBH", b) + version = (buf[0x50:0x58], buf[0x60: 0x70], buf[0x80:0x88]) + + dpf = find_dpf(version) + if not dpf: + print "No DPF found. Create a record or look for one" + print version + else: + print "Identifier:", dpf[1] + di = dpf[3] + di['offset'] = offset + + return dpf + +def patch(d, dpf): + if (paranoia_mode): + print """Now patching. There is no 100% guarantee that your device will + work after doing this. You must never unplug the device from USB while + it is being updated. + Are you sure you take all risks and that you want to continue?""" + a = raw_input("Type 'yes' to continue > ") + if a != "yes": + print "Aborting." + return False + + p = dpf[4] + + buf = d.readFlash(JUMPTABLE_OFFSET, dpf[3]['offset']) + for i in p[2]: + if not patch_module(d, i, buf): + return False + + return True +# +# +# MAIN + +if len(sys.argv) != 2: + print "Usage: %s [<generic scsi device> | usb0]" % sys.argv[0] + print "You may have to run this as root when accessing generic scsi devices" + sys.exit(-1) + +d = dpf.open(sys.argv[1]) + +dpf = recognize(d) +if dpf: + r = dpf[4] + ret = patch(d, dpf) + if ret: + print + print "Now disconnect the DPF from USB." + print "To activate the 'developer mode':" + print + print instructions[r[0]] + print + print ins_common + else: + print "DPF might not be completely patched." +d.close() diff --git a/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14e5.ihx b/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14e5.ihx new file mode 100644 index 00000000..3841cc6a --- /dev/null +++ b/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14e5.ihx @@ -0,0 +1,64 @@ +:0913300043C80530CEFDE5C922D9 +:0713390075CA143004012203 +:0E13400043C80530CEFDC2CEE5C930E0EF2235 +:07134E0075CA1130040122F1 +:0E13550043C80530CEFDC2CEE5C920E0EF2230 +:0A13630053C8FB43C80130CEFD2241 +:0D136D0075CA0E75C901716375CA1475C982 +:03137A000080E60A +:0D137D0075CA0E75C901716375CA1175C975 +:03138A000180D609 +:04138D00F5C980D24C +:09139100E6F5C9716308D9F822E0 +:09139A00E493F5C97163D9F8224E +:0E13A3004386108C828D83EA2CC5F0EB3DA8AA +:0213B100F0F951 +:0713B30071397C4075CA216D +:0B13BA007130F0E8B58207E9B583034D +:0313C500716D2225 +:0613C800DCF0716D80E510 +:0B13CE00714E75CA218C828D83EAF9F4 +:0413D900719A717D17 +:0313DD00714E222C +:0C13E0008C828D837CF87D001215427415 +:0913EC00F5C0E07413C0E0E473E5 +:0113F50022D5 +:0C13F600438610E4F550F551F552F55314 +:0B140200714E75CA217455718D745332 +:08140D00718D7442718D74535E +:0C141500718D788479047191789F7904BE +:0614210071917400718D51 +:08142700717D714E7904789F7C +:03142F00913222D5 +:01143200E4D5 +:05143300F608D9FC22BF +:0E14E5007895E6C5F008E6FC08E6FD08E6FA94 +:0C14F30008E6FBC5F0B4010471A38025DD +:0714FF00B4020471E0801E3D +:07150600B4040471CE80174C +:07150D00B41004B1298010A5 +:07151400B41104B15D800970 +:07151B00B41204B16180026B +:02152200B142D4 +:0515240071F602181829 +:0C152900E4F577F578F579F57A757B7FAD +:08153500757C00757D7F757E59 +:05153D000012128022E3 +:05154200B129E4F8F9F5 +:0E154700EC120F25ED120F25D3E438F8E4392D +:08155500F9B800EEB940EB22E9 +:04155D00B129A17D92 +:0E1561008C778D788A798B7A789AE6F57B08FC +:0E156F00E6F57C08E6F57D08E6F57E121280B2 +:0A157D007888E6FB08E6FC08E6FDAE +:0E158700EBF5F033CC33CD33FBEC33CD33CB6F +:0815950033FCE5F003541FFDD7 +:0B159D00EB4C601C71397F2075CA21E7 +:0C15A8007130120F257130120F25DFF496 +:0715B400716D1BBBFF011C60 +:0215BB0080E0CE +:0815BD00ED6013713975CA21BC +:0C15C5007130120F257130120F25DDF47B +:0215D100716D3A +:0115D30022F5 +:00000001FF diff --git a/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14f4.ihx b/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14f4.ihx new file mode 100644 index 00000000..c71b29fa --- /dev/null +++ b/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14f4.ihx @@ -0,0 +1,64 @@ +:0913300043C80530CEFDE5C922D9 +:0713390075CA143004012203 +:0E13400043C80530CEFDC2CEE5C930E0EF2235 +:07134E0075CA1130040122F1 +:0E13550043C80530CEFDC2CEE5C920E0EF2230 +:0A13630053C8FB43C80130CEFD2241 +:0D136D0075CA0E75C901716375CA1475C982 +:03137A000080E60A +:0D137D0075CA0E75C901716375CA1175C975 +:03138A000180D609 +:04138D00F5C980D24C +:09139100E6F5C9716308D9F822E0 +:09139A00E493F5C97163D9F8224E +:0E13A3004386108C828D83EA2CC5F0EB3DA8AA +:0213B100F0F951 +:0713B30071397C4075CA216D +:0B13BA007130F0E8B58207E9B583034D +:0313C500716D2225 +:0613C800DCF0716D80E510 +:0B13CE00714E75CA218C828D83EAF9F4 +:0413D900719A717D17 +:0313DD00714E222C +:0C13E0008C828D837CF87D001215517406 +:0913EC00F5C0E07413C0E0E473E5 +:0113F50022D5 +:0C13F600438610E4F550F551F552F55314 +:0B140200714E75CA217455718D745332 +:08140D00718D7442718D74535E +:0C141500718D788479047191789F7904BE +:0614210071917400718D51 +:08142700717D714E7904789F7C +:03142F00913222D5 +:01143200E4D5 +:05143300F608D9FC22BF +:0E14F4007895E6C5F008E6FC08E6FD08E6FA85 +:0C15020008E6FBC5F0B4010471A38025CD +:07150E00B4020471E0801E2D +:07151500B4040471CE80173D +:07151C00B41004B138801087 +:07152300B41104B16C800952 +:07152A00B41204B17080024D +:02153100B151B6 +:0515330071F60218181A +:0C153800E4F577F578F579F57A757B7F9E +:08154400757C00757D7F757E4A +:05154C000012128022D4 +:05155100B138E4F8F9D7 +:0E155600EC120F25ED120F25D3E438F8E4391E +:08156400F9B800EEB940EB22DA +:04156C00B138A18C65 +:0E1570008C778D788A798B7A789AE6F57B08ED +:0E157E00E6F57C08E6F57D08E6F57E121280A3 +:0A158C007888E6FB08E6FC08E6FD9F +:0E159600EBF5F033CC33CD33FBEC33CD33CB60 +:0815A40033FCE5F003541FFDC8 +:0B15AC00EB4C601C71397F2075CA21D8 +:0C15B7007130120F257130120F25DFF487 +:0715C300716D1BBBFF011C51 +:0215CA0080E0BF +:0815CC00ED6013713975CA21AD +:0C15D4007130120F257130120F25DDF46C +:0215E000716D2B +:0115E20022E6 +:00000001FF diff --git a/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14fb.ihx b/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14fb.ihx new file mode 100644 index 00000000..2e6cf3a4 --- /dev/null +++ b/oncology/dpfhack_display/fw/hexfiles/cmdhandler_14fb.ihx @@ -0,0 +1,63 @@ +:0913300043C80530CEFDE5C922D9 +:0713390075CA143004012203 +:0E13400043C80530CEFDC2CEE5C930E0EF2235 +:07134E0075CA1130040122F1 +:0E13550043C80530CEFDC2CEE5C920E0EF2230 +:0A13630053C8FB43C80130CEFD2241 +:0D136D0075CA0E75C901716375CA1475C982 +:03137A000080E60A +:0D137D0075CA0E75C901716375CA1175C975 +:03138A000180D609 +:04138D00F5C980D24C +:09139100E6F5C9716308D9F822E0 +:09139A00E493F5C97163D9F8224E +:0E13A3004386108C828D83EA2CC5F0EB3DA8AA +:0213B100F0F951 +:0713B30071397C4075CA216D +:0B13BA007130F0E8B58207E9B583034D +:0313C500716D2225 +:0613C800DCF0716D80E510 +:0B13CE00714E75CA218C828D83EAF9F4 +:0413D900719A717D17 +:0313DD00714E222C +:0C13E0008C828D837CF87D0012155874FF +:0913EC00F5C0E07413C0E0E473E5 +:0113F50022D5 +:0C13F600438610E4F550F551F552F55314 +:0B140200714E75CA217455718D745332 +:08140D00718D7442718D74535E +:0C141500718D788479047191789F7904BE +:0614210071917400718D51 +:08142700717D714E7904789F7C +:03142F00913222D5 +:01143200E4D5 +:05143300F608D9FC22BF +:0E14FB007895E6C5F008E6FC08E6FD08E6FA7E +:0C15090008E6FBC5F0B4010471A38025C6 +:07151500B4020471E0801E26 +:07151C00B4040471CE801736 +:07152300B41004B13F801079 +:07152A00B41104B173800944 +:07153100B41204B17780023F +:02153800B158A8 +:05153A0071F602181813 +:0E153F00E4F577F578F579F57A757B7F757CA4 +:0B154D0000757D7F757E001212802269 +:05155800B13FE4F8F9C9 +:0E155D00EC120F25ED120F25D3E438F8E43917 +:08156B00F9B800EEB940EB22D3 +:04157300B13FA19350 +:0E1577008C778D788A798B7A789AE6F57B08E6 +:0E158500E6F57C08E6F57D08E6F57E1212809C +:0A1593007888E6FB08E6FC08E6FD98 +:0E159D00EBF5F033CC33CD33FBEC33CD33CB59 +:0815AB0033FCE5F003541FFDC1 +:0B15B300EB4C601C71397F2075CA21D1 +:0C15BE007130120F257130120F25DFF480 +:0715CA00716D1BBBFF011C4A +:0215D10080E0B8 +:0815D300ED6013713975CA21A6 |