Open ghost opened 7 years ago
Excellent! I'll look into ordering one this week.
Side note (put here for googlers) - the connector on the MD2017 is the same as on Motorola EX500, EX600, GP328, etc. Planet Headset knows it as the M5. Pryme knows it as the HYT x43. I know it is this connector because I now have an accessory meant for that group of Motorola radios that works great with the MD2017. This was extremely frustrating to figure out, so hopefully I can save others some time - I believe it was W1IRA who first pointed out that connector, talking to the NEDECN group.
I can wrap / unwrap firmware images for 2017 and flash them to the radio. Also can read/write the spi flash. I have the users DB working and most of the symbols ported to the 2017. I have yet to get the extra usb DNLOAD commands working for peek/poke but its all coming along. How can I help out?
I use the stock updater utility to program firmware images to the 2017 as of now but I should be able to port the md380tools scripts to work without too much hassle
I've got the encryption keystream that the 2017 / RT82 use
@KG5RKI I'll be happy for pull requests, and I can also help merge, and/or port your C# to Python - whatever's easiest! Where can I find the keystream for the MD2017 for wrapping and unwrapping firmware?
alright, please just make sure I get a little credit on this.. took me many hours to get it working..
On Thu, Jul 6, 2017 at 3:59 PM, Mike M notifications@github.com wrote:
@KG5RKI https://github.com/kg5rki I'll be happy for pull requests, and I can also port your C# back to Python - whatever's easiest! Where can I find the keystream for the MD2017 for wrapping and unwrapping?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/travisgoodspeed/md380tools/issues/789#issuecomment-313517840, or mute the thread https://github.com/notifications/unsubscribe-auth/Abe5494tX5vvg0l53bcDh8gzW69dn6D0ks5sLUrMgaJpZM4OPmL0 .
On Thu, Jul 6, 2017 at 4:16 PM, Ty Weaver tydweaver@gmail.com wrote:
alright, please just make sure I get a little credit on this.. took me many hours to get it working..
On Thu, Jul 6, 2017 at 3:59 PM, Mike M notifications@github.com wrote:
@KG5RKI https://github.com/kg5rki I'll be happy for pull requests, and I can also port your C# back to Python - whatever's easiest! Where can I find the keystream for the MD2017 for wrapping and unwrapping?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/travisgoodspeed/md380tools/issues/789#issuecomment-313517840, or mute the thread https://github.com/notifications/unsubscribe-auth/Abe5494tX5vvg0l53bcDh8gzW69dn6D0ks5sLUrMgaJpZM4OPmL0 .
from future import print_function
import argparse import binascii import struct import sys
class MD380FW(object):
# to a cyclic, static XOR key block, and here it is:
key = '00aa89891f4beccf424514540065eb66417d4c88495a210df2f5c8e638edbcb9fb357133010a7f9e3b2903b6493e42b83f9f90bdaa3a7146cecdfd183255894a5fc8839ce4069e0a9d0d2fa1356dd792eafd638590cbf02fd9595327d306b8f5b2ca886cd026913bf25b61becddbf21ac9fd8d8804f4e8f19a0292bc24e990e47ea3494dce529f58c17a5fb5186edb786408d56f0d9d9fb39930817e2be65b3c4aba8be5e472118993d2f12d1e0fd9d5438704e2b4ae5e9e5f4ce916f2e65f289f7919dc1d6f2ff8efcbe1cee8a73659efe0e28800106dda73bc922b81cfe6ce0447badb7e2f41ca5dcdf6417d1c382bef7d370af9a9148e5dea4466de8b3656018c358a119b8f2a6540f72ee6582874cbc4cb0fa7629be3a63cc76f130097e91eb15390dd9b613e908cad3c29414e5b0c1f664013244900d51ce2ed281853afe41cdc96ea18fe2e6519e01450c1f10939f5cf4544d5680d72f15f8823b9b1cfda36984341f8af236d50575e62bf5aa5daadcfc5425e3e34062304e90ecdf87189674e40e925bc452e97dcc16822d25877b12e6916a8149b181a9ab8f03b71bf7718c834ea856dbb325735e569d49f4a9968b4d8c79a316a303de89cd2eb64de2eafccc84d0209ae01f92b736dbc09a2c73a28ba5d1bdfcad6f6b83ebbc518f9369623a41983da4521e386137dc25a898a8f54b9e11564e393add046b3b1d7361533956f56ef26a91c7f0e6c9fced82669cffe7b5a6f09dceec8f95bc397e7bd55f0e9d10c3036017a348b27ddc8cda2ec62efa8d01116dd70b0fb25f15f91b77d34e974442d5276c169c4eb3f987f249bb1efe94be3d3109fcd9e4e47f11d4c16665bfd06cec2307b888261cc2737d5ff22c6e6d4cc879b0687aa7bcd35d3a3a7f0081758fbcd562ff88d318c5b3cdc9f1e3b4672b77ca62a47e6568a14fbe5b839b868449cbc106621ad02871dd862030e17b12e89f85a95731b878674dc39d2a93298d199d788a76baa7cc656518fb45822d10f2b44dece7511b6c93fbfc87ca8405007da66e37a3e4b4850ecf08a3966244b1d85a85b5db3908a5c5becba3e9ea838ef48b14c6702590e2dc9fd7c1a9ee5ca607f6bf9cb9760ab46b2ab36a0f333f790c900e9f71f9d7566d3c08ce06a2cf4e102d7df9e8748c28f2a44642b0fa936f3469ae2b1fddc2602f480e31231c371a7f4323661ed127740adfe6d665bd29c1ea8c8601e04e1c9091387a8385a70eaba3fc525993084715f222379d93d76d21bd5d28bc49d730584171b04db4ffc0723c9d8d5d0b86759f770f9af0d1e5c7ff2b7008a2d2e59827aea851f82772f6fe97cb36e8ded82d60d81c93889674d4ca9359986e1215ce9f3730d20b53ad0cb143e9d1759379f91ab3cda3cd57e11e04a36e7a666dc44e2f79afa30fc00a9c2adf9e0f8bbfe8431d88976e2'.decode('hex')
def __init__(self, base_address=0x800c000):
self.magic = b'OutSecurityBin'
self.jst = b'MD-9600\x00\x00'
self.foo = '\x30\x02\x00\x30\x00\x40\x00\x47'
self.bar = ('\x02\x19\x0C\x03\x04\x05\x06\x07'
'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
'\x10\x11\x12\x13\x14\x15\x16\x17'
'\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'
'\x20')
self.foob = ('\x02\x00\x00\x00\x00\x00\x06\x00')
self.start = base_address
self.app = None
self.footer = 'OutputBinDataEnd'
self.header_fmt = '<16s9s7s16s33s43s8sLLL112s'
self.footer_fmt = '<240s16s'
self.rsrcSize = 0x5D400
def pad(self, align=512, byte=b'\xff'):
pad_length = (align - len(self.app) % align) % align
self.app += byte * pad_length
def wrap(self):
bin = b''
header = struct.Struct(self.header_fmt)
footer = struct.Struct(self.footer_fmt)
self.pad()
app = self.crypt(self.app)
bin += header.pack(
self.magic, self.jst, b'\xff' * 7, self.foo,
self.bar, b'\xff' * 43, self.foob, self.rsrcSize, self.start, len(app)-self.rsrcSize,
b'\xff' * 112)
bin += self.crypt(self.app)
bin += footer.pack(b'\xff' * 240, self.footer)
return bin
def unwrap(self, img):
header = struct.Struct(self.header_fmt)
header = header.unpack(img[:256])
self.start = header[6]
app_len = header[7]
self.app = self.crypt(img[256:256 + app_len])
assert header[0].startswith(self.magic)
assert header[1].startswith(self.jst)
assert header[3].startswith(self.foo)
assert header[4] == self.bar
assert 0x8000000 <= header[6] < 0x8200000
assert header[7] == len(img) - 512
def crypt(self, data):
return self.xor(data, self.key)
@staticmethod
def xor(a, b):
# FIXME: optimized version
out = b''
l = max(len(a), len(b))
for i in range(l):
out += chr(ord(a[i % len(a)]) ^ ord(b[i % len(b)]))
return out
def main(): def hex_int(x): return int(x, 0)
parser = argparse.ArgumentParser(description='Wrap and unwrap MD-380 firmware')
parser.add_argument('--wrap', '-w', dest='wrap', action='store_true',
default=False,
help='wrap app into firmware image')
parser.add_argument('--unwrap', '-u', dest='unwrap', action='store_true',
default=False,
help='unwrap app from firmware image')
parser.add_argument('--addr', '-a', dest='addr', type=hex_int,
default=0x800c000,
help='base address in flash')
parser.add_argument('--offset', '-o', dest='offset', type=hex_int,
default=0,
help='offset to skip in app binary')
parser.add_argument('input', nargs=1, help='input file')
parser.add_argument('output', nargs=1, help='output file')
args = parser.parse_args()
if not (args.wrap ^ args.unwrap):
sys.stderr.write('ERROR: --wrap or --unwrap?')
sys.exit(5)
print('DEBUG: reading "%s"' % args.input[0])
with open(args.input[0], 'rb') as f:
input = f.read()
if args.wrap:
if args.offset > 0:
print('INFO: skipping 0x%x bytes in input file' % args.offset)
md = MD380FW(args.addr)
md.app = input[args.offset:]
if len(md.app) == 0:
sys.stderr.write('ERROR: seeking beyond end of input file\n')
sys.exit(5)
output = md.wrap()
print('INFO: base address 0x{0:x}'.format(md.start))
print('INFO: length 0x{0:x}'.format(len(md.app)))
elif args.unwrap:
md = MD380FW()
try:
md.unwrap(input)
except AssertionError:
sys.stderr.write('WARNING: Funky header:\n')
for i in range(0, 256, 16):
hl = binascii.hexlify(input[i:i + 16])
hl = ' '.join(hl[i:i + 2] for i in range(0, 32, 2))
sys.stderr.write(hl + '\n')
sys.stderr.write('Trying anyway.\n')
output = md.app
print('INFO: base address 0x{0:x}'.format(md.start))
print('INFO: length 0x{0:x}'.format(len(md.app)))
print('DEBUG: writing "%s"' % args.output[0])
with open(args.output[0], 'wb') as f:
f.write(output)
if name == "main": main()
Credit is no problem - git has facilities for just such an occasion, and I'll make sure to note it in the code itself. Thank you for sharing!
Looks like a good group - makes me regret not having a facebook account. With your permission, I'll add it to the list of related communities in the README and wiki here?
yes please. I am still learning how to use git. Whatever I share with you you can assume I share with everyone.
On Thu, Jul 6, 2017 at 4:53 PM, Mike M notifications@github.com wrote:
Looks like a good group - makes me regret not having a facebook account. With your permission, I'll add it to the list of related communities in the README and wiki here?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/travisgoodspeed/md380tools/issues/789#issuecomment-313529811, or mute the thread https://github.com/notifications/unsubscribe-auth/Abe54xNa9XOr6DvDg9L6rkEga6mSOzkvks5sLVdRgaJpZM4OPmL0 .
can you message me in google hangouts at tydweaver@gmail.com? If you have a md2017 I can send you my fw for the userDB.
Roger. I'm relatively new to git myself. Hangouts: will do! Might be a half hour or so, replying on the fly.
Still porting the symbols for the gps version of the radio, but so far the fw works on RT82 and md2017 with nonGPS.
@KG5RKI check email, hangouts seems down
I'll have some merged commits of Ty's MD2017 wrap/unwrap on my repo tomorrow (edit, maybe later), and if it works well I will push to master here.
Pushed changes to md380_fw.py to include @KG5RKI's work for the MD2017 shared above.
@travisgoodspeed Who can add some stock fw for MD2017/RT82 support to archive.org/download? I'd like to add 4 files (stock fw S003.031 S003.033, D003.031, D003.033) for my next pr to firmware_files.txt If anyone has an account I'll send a link to the current firmware images.
@d235j can take care of merging @DL2MF's MD2017 firmware images. We might need to specify a hardware model in addition to their version numbers, in case more MD380 firmware images are released.
https://dd1go.de/file.php?dir=RT82/&file=RT82-UV%28REC%29-D3.33.bin
https://dd1go.de/file.php?dir=RT82/&file=RT82-UV%28REC%29-D3.33.bin
https://dd1go.de/file.php?dir=MD-2017firmware/&file=TYT2017-UV%28GPS-REC%29-S3.31.bin
https://dd1go.de/file.php?dir=MD-2017firmware/&file=TYT2017-UV%28REC%29-D3.31.bin
@travisgoodspeed @ispkorte I prefer we use public services for download archive, like for all other (except the last pr hosted from W2FBI) images. This is also the reason cause I didn't share them on my webservices.
Any suggest for the model identifier? Otherwise I'll name them MD2017_ in prefix to differ them from MD3x0/MD446 firmware versions and we continue using D/S for all versions for NonGPS/GPS like Tytera/Retevis also does for the genuine images (without adding GPS explicitly.
FYI the donation is for DMR Track, not related to md380tools. The firmware images are hosted on facebook, not the server.
@travis , this is a public service ; no problem
MD2017 Symbols
gfx_set_bg_color = 0x080249FD ; gfx_set_fg_color = 0x08024369 ;
gfx_drawchar_pos = 0x08029BA5 ;
gfx_blockfill = 0x080249FD ; gfx_drawtext7 = 0x0802E035 ;
gfx_select_font = 0x08029AD0 ;
md380_spiflash_read = 0x080439CB ;
md380_spiflash_write = 0x08043AB3 ;
md380_spiflash_security_registers_read = 0x08043E0D ;
md380_spiflash_disable = 0x08043A9B ;
md380_spiflash_enable = 0x08043A7F ;
md380_spiflash_wait = 0x08043A5D ;
md380_spi_sendrecv = 0x08043A11;
md380_spiflash_block_erase64k = 0x080437E9 ;
md380_spiflash_sektor_erase4k = 0x080437B5 ;
md380_OSMboxPost = 0x0803E711 ;
md380_OSMboxPend = 0x0803E5FB ;
md380_blockadr = 0x2001FB14 ; md380_packetlen = 0x2001FB18 ;
md380_dfutargetadr = 0x20001228 ; md380_dfu_target_adr = 0x20001228 ;
md380_dfu_state = 0x2001FE3F ; md380_thingy2 = 0x2001FE40 ;
usb_upld_handle = 0x080D94BD ; usb_dnld_handle = 0x080D8AC5 ;
usb_send_packet = 0x08079CF3 ;
md380_packet = 0x2001BD20 ; md380_usbstring = 0x2001E554 ;
dmr_call_start = 0x0804C52B ; dmr_before_squelch = 0x0804CADD ; dmr_call_end = 0x0804D2E1 ; dmr_CSBK_handler = 0x0804D845 ; dmr_handle_data = 0x08050D83 ;
kb_keypressed = 0x2001FB64 ; kb_row_col_pressed = 0x2001FCFE ; kb_keycode = 0x2001FE30 ; kb_handler = 0x0806E709 ;
gui_opmode3 = 0x2001FE4F ;
gui_opmode2 = 0x2001FDFC ; gui_opmode1 = 0x2001FDFE ; gui_opmode1_prev = 0x2001FDFD ;
m_cntr2 = 0x2001FCC8 ; gfx_font_small = 0x080EB018 ; gfx_font_norm = 0x080EB058 ;
MD2017 merge.py
merger.hookbl(0x08030D76, sapplet.getadr("rx_screen_blue_hook"), 0)
merger.hookbl(0x08030DF0, sapplet.getadr("rx_screen_blue_hook"), 0)
#merger.hookbl(0x080D8A20, sapplet.getadr("usb_upld_hook"), 0x080D94BC) # Old handler adr.
# keyboard
merger.hookbl(0x0806CE92, sapplet.getadr("kb_handler_hook"));
dmr_call_start_hook_list = [0x804C3DC, 0x0804BE34, 0x804BE0C, 0x804BDA6]
for adr in dmr_call_start_hook_list:
merger.hookbl(adr, sapplet.getadr("dmr_call_start_hook"))
gfxblockfill = [
0x0800CAA6,
0x0800CAB2,
0x0800CABE,
0x0800CACA,
0x0800CADE,
0x0800CAEA,
0x0800CAF6,
0x0800CB02,
0x0800CB0E,
0x0800CB28,
0x0800CB4E,
0x0800CB5A,
0x0800CB6E,
0x0800CC4E,
0x0800CC5A,
0x0800CC66,
0x0800CC78,
0x0800CC96,
0x0800CCA2,
0x0800CCB6,
0x0800CD4C,
0x0800CD58,
0x0800CD64,
0x0800CDDC,
0x0800CDE8,
0x0800CDF4,
0x0800CE00,
0x0800CE14,
0x0800CE20,
0x0800CE34,
0x0800CE40,
0x0800CE54,
0x0800CECA,
0x0800D258,
0x0800D28A,
0x0800D450,
0x0800D45C,
0x0800D4C0,
0x0800D5EC,
0x0800D5F8,
0x0800D604,
0x0800D610,
0x0800D722,
0x0800D72E,
0x0800D73A,
0x0800D746,
0x0800D7FA,
0x0800D87A,
0x0800D886,
0x0800D892,
0x0800D89E,
0x0800DB3A,
0x0800DC82,
0x0800DC9C,
0x0800DCA8,
0x0800DCF8,
0x0800DD04,
0x0800DD10,
0x0800DFF2,
0x0800E27E,
0x0800E292,
0x0800E29E,
0x0800E2AA,
0x0800E2B6,
0x0800E558,
0x0800E5CE,
0x0800E5DC,
0x0800E5E8,
0x0800E5F4,
0x0800E608,
0x0800E6E2,
0x0800E74C,
0x0800E774,
0x0800E90C,
0x0800E920,
0x0800E92C,
0x0800E938,
0x0800E944,
0x0800ECBE,
0x0800ECCC,
0x0800EE84,
0x0800EF9C,
0x0800F074,
0x0800F0DE,
0x0800F0EC,
0x0800F1E4,
0x0800F2CE,
0x0800F3C6,
0x0800F702,
0x0800F71C,
0x0800F75E
]
for adr in gfxblockfill:
merger.hookbl(adr, sapplet.getadr("gfx_blockfill_hook"))
ported all the usb related symbols but the usb hooks are still not working. Probably just forgot something stupid, but the code is a bit different so something might have changed slightly
Has there been any progress on this?
I have the toolchain running and symbols ported, just have not gotten every feature added yet. Lastheard, userdb, manual dial talkgroup. Thats about it so far
On Wed, Jan 3, 2018 at 11:53 AM, Richard notifications@github.com wrote:
Has there been any progress on this?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/travisgoodspeed/md380tools/issues/789#issuecomment-355079155, or mute the thread https://github.com/notifications/unsubscribe-auth/Abe546ubBuuCxMIRHCcPI-sKg_D5UPDFks5tG76ZgaJpZM4OPmL0 .
Any news/progress on MD-2017 toolz?
Any way I could help out with porting? Still working on reading codeplugs?
@Wferr No work done yet on reading codeplugs. It should look almost identical to reading a codeplug from the MD-380, just more data. Pull requests are always welcome - it looks like just about everybody has been busy lately with other projects and day jobs, including me, but I still have a few hours a week to work on this stuff.
I have writing MD-2017 firmware working as of a few days ago, need to merge it upstream.
Hi, I bought a MD-2017 (my first DMR radio) and would like to help porting the md380toolz. @mach327 , @KG5RKI : Is the current state (toolz as well as firmware) available for download?
@KG5RKI has a full setup for the MD2017, including ported application code. He's friendly, get in touch and talk a bit. I previously started to help port his stuff back to this repo, but I got overwhelmed with work and school and flaked out on him, and just haven't had the spare cycles since.
We (md380tools) have codeplug writing to the MD2017, and I have firmware writing to the MD2017. Right now, I don't remember if I merged that up to this repo entirely - I might not have.
@mach327 : based on your branch 'md2017', I started work on reading codeplug (I put it in a separate function). However, after the first 256k read from radio, the codeplug (downloaded with CPS1.22) contains 16 bytes that look like a DFU-Suffix. At the moment I hardcoded those bytes, as I was not able to figure out how to calculate the CRC. Do you have any ideas regarding that?
@OE4AMW I haven't looked at your code yet, but if it's CRC32, try the Python binascii.crc32()
and see if it gives you the same output. I can poke at it too, if you like - maybe this weekend or so.
I tried already using dfu_suffix.crc() - but I haven't figured out which parts of the codeplug need to be taken into account for CRC calculation. (Neither 0..0x4022D, nor 0+rdt-header..0x4022D returns the checksum that CPS 1.22 reads out ...) It anyhow looks strange for me that the DFU-suffix is at 0x4022D (of the .rdt) - and not at the end of the file ...
My embedded dev experience leaves much to be desired, but is there anything I can do to help with this effort? Just got a 2017 and I'm itching to get TYToolz on there!
You can bypass all of this if you just write it directly to spi flash. I have made minor changes to it after dumping from flash and just writing it back straight. Maybe I am not understanding the crc your talking about right, but if you can convert the format of the rdf into the format it would be raw in flash you shouldn't have a problem I would think.
On Thu, Aug 16, 2018 at 4:37 PM OE4AMW notifications@github.com wrote:
I tried already using dfu_suffix.crc() - but I haven't figured out which parts of the codeplug need to be taken into account for CRC calculation. (Neither 0..0x4022D, nor 0+rdt-header..0x4022D returns the checksum that CPS 1.22 reads out ...) It anyhow looks strange for me that the DFU-suffix is at 0x4022D (of the .rdt) - and not at the end of the file ...
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/travisgoodspeed/md380tools/issues/789#issuecomment-413692572, or mute the thread https://github.com/notifications/unsubscribe-auth/Abe543FtHZUwoZeGRgnSd_PhVUDWFtk8ks5uReYcgaJpZM4OPmL0 .
What I wanted to achieve, is to read a RDT from the radio, that can be edited in the Tytera CPS software (which works under Linux using wine, but without USB-functionality). There are 16 bytes in the RDT (starting at x4022D) that look like a DFU suffix - but the as I figured out (at least in my case), the CRC part of the DFU suffix always have the same values - so I hardcoded them for now. I just committed a version ( https://github.com/OE4AMW/md380tools/tree/md2017 ) that successfully read a RDT-file from the radio. The header is now static as well (serial-number, device-id, hardware-versions are blank), but that does not bother the Tytera-software - It loads and edits the RDT file successfully. As I do not have a MD380, I copied added the functionality for MD2017 into a new function of md380_dfu.py - so this shouldn't cause any harm. However, I had to add one line in DFU.py - maybe someone with a MD380 can test whether it breaks anything. If not, maybe the "starter goals" 2 and 3 are finished as well ...
There is a discord server with beta firmwares by @KG5RKI If anyone is interested/wants download links. https://discord.gg/EHY78Uz
The firmware by @KG5RKI is now open source at https://github.com/KG5RKI/RT82Toolz if that helps add support for the MD2017/RT82
I am now able the build the rt82 firmware. python has to be python2 and than "make image_2017_GPS" or "make image_2017_nonGPS" does the job
You can look at https://github.com/DaleFarnsworth-DMR/editcp by @DaleFarnsworth-DMR for inspiration, they have made some progress as well in that direction.
Right now, I can write codeplugs (which means we can write codeplugs from Linux, running the TYT CPS in wine), and have been poking at the codeplug format. So far, it's all the same structures, everything is just shifted around for the larger memory. I also was able to fix a few minor issues (such as the DFU client crash when sending md380_custom(0xA2 0x01)). https://github.com/mach327/md380tools/tree/md2017
Starter goals: