[Xposted to comp.arch.embedded - hopefully there are a few H8 asm gurus there who can help]
Hi, I'm currently trying to reverse-engineer the LZSS decompression engine used in the Cybiko PDA to compress firmware updates (and small ASM and C programs) that are sent over a serial link. I've disassembled the bootloader and found the decompress() routine (in Hitachi H8 assembler), but I haven't managed to work out what I need to do to write a C program to decompress the images. From the disassembly, I guessed that the code used is a variant of Haruhiko Okumura's LZSS.C. I've also found the value of THRESHOLD, but I don't know what the values of F and N (related to ring buffer sizing) are. All I know about the output file is that it should be 1288 bytes in size. Using { THRESHOLD=2, N=1024, F=18 } produces a file of that size, but my disassembler reports that the decompressed data is not valid code.
Here's the disassembly:
ROM:0000388A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:0000388A
> ROM:0000388A
> ROM:0000388A decompress: ; CODE XREF: sub_ABC+12Ep
> ROM:0000388A
> ROM:0000388A var_10 = -0x10
> ROM:0000388A var_C = -0xC
> ROM:0000388A inputPointer = -8
> ROM:0000388A outputPointer = -4
> ROM:0000388A
> ROM:0000388A sub.l #0x10, sp ; ER0 = output pointer
> ROM:0000388A ; ER1 = input pointer
> ROM:0000388A ; ER2 = compressed size
> ROM:00003890 stm.l er4-er6, @-sp
> ROM:00003894 mov.l er0, @(0x1C+outputPointer:16,sp) ;
Output pointer -> ER0
ROM:0000389A mov.l er1, @(0x1C+inputPointer:16,sp) ; Input
pointer -> ER1
ROM:000038A0 mov.l er2, er4 ; Counter -> ER4
> ROM:000038A2 sub.l er5, er5 ; ER5 = 0
> ROM:000038A4 mov.l er5, @(0x1C+var_10:16,sp) ; var_10 = 0
> ROM:000038AA sub.w r6, r6 ; R6 = 0
> ROM:000038AC mov.l er0, @(0x1C+var_C:16,sp) ; Output
pointer -> var_C
ROM:000038B2
> ROM:000038B2 loc_38B2: ; CODE XREF:
decompress+86j
ROM:000038B2 ; decompress+10Cj
> ROM:000038B2 shlr.w r6 ; Logical Shift Right
on R6
ROM:000038B4 btst #0, r6h ; Test R6high bit 0
> ROM:000038B6 bne loc_38D2:8 ; if (r6 & 256) then
branch
ROM:000038B8 mov.l er4, er2 ; ER2 = ER4 (counter)
> ROM:000038BA subs #1, er4 ; ER4 = ER4 - 1
(counter)
ROM:000038BC beq decompress_done:16 ; If it's zero, we've
decoded everything
ROM:000038C0 mov.l @(0x1C+inputPointer:16,sp), er5 ; ER5 =
input pointer
ROM:000038C6 mov.b @er5+, r6l ; R6low = @ER5 (inc.
ER5)
ROM:000038C8 mov.b #0, r6h ; R6high = 0
> ROM:000038CA mov.l er5, @(0x1C+inputPointer:16,sp) ; Input
pointer = ER5
ROM:000038D0 or.b #0xFF, r6h ; R6 |= 0xFF00
> ROM:000038D2
> ROM:000038D2 loc_38D2: ; CODE XREF:
decompress+2Cj
ROM:000038D2 mov.l er4, er3 ; ER3 = ER4 (counter)
> ROM:000038D4 subs #1, er3 ; Decrement counter
> ROM:000038D6 btst #0, r6l ; if (flags & 1)
> ROM:000038D8 beq loc_3912:8 ; then branch
> ROM:000038DA mov.l er4, er2
> ROM:000038DC mov.l er3, er4
> ROM:000038DE mov.l er2, er2
> ROM:000038E0 beq decompress_done:16
> ROM:000038E4 mov.l @(0x1C+inputPointer:16,sp), er5
> ROM:000038EA mov.b @er5+, r2l
> ROM:000038EC mov.l er5, @(0x1C+inputPointer:16,sp)
> ROM:000038F2 mov.l @(0x1C+var_C:16,sp), er5
> ROM:000038F8 mov.b r2l, @er5
> ROM:000038FA adds #1, er5
> ROM:000038FC mov.l er5, @(0x1C+var_C:16,sp)
> ROM:00003902 mov.l @(0x1C+var_10:16,sp), er5
> ROM:00003908 adds #1, er5
> ROM:0000390A mov.l er5, @(0x1C+var_10:16,sp)
> ROM:00003910 bra loc_38B2:8
> ROM:00003912 ;
---------------------------------------------------------------------------
ROM:00003912
> ROM:00003912 loc_3912: ; CODE XREF:
decompress+4Ej
ROM:00003912 mov.l er4, er4 ; if (count == 0)
> ROM:00003914 beq decompress_done:16 ; then branch
> ROM:00003918 mov.l @(0x1C+inputPointer:16,sp), er5 ; R2 =
next data byte (R2 = i)
ROM:0000391E mov.b @er5+, r2l
> ROM:00003920 mov.b #0, r2h
> ROM:00003922 mov.l er5, @(0x1C+inputPointer:16,sp) ; Update
pointer
ROM:00003928 mov.w r2, r0 ; R0 = R2 = i
> ROM:0000392A extu.l er0 ; er0 &= 0x0000FFFF
> ROM:0000392C mov.l er3, er4 ; ER4 = ER3
> ROM:0000392E subs #1, er4 ; ER4 = ER4 - 1
[counter]
ROM:00003930 mov.l er3, er3 ; if (ER3 = 0) then
decompress done
ROM:00003932 beq decompress_done:8
> ROM:00003934 mov.b @er5+, r3l ; R3 = next data byte
> ROM:00003936 mov.b #0, r3h
> ROM:00003938 mov.l er5, @(0x1C+inputPointer:16,sp) ; Update
pointer
ROM:0000393E mov.l er3, er2 ; ER2 = ER3 = j
> ROM:00003940 shll.l #2, er2 ; ER2 = ((ER2 ROM:00003942 shll.l #2, er2
> ROM:00003944 and.l #0xF00, er2
> ROM:0000394A or.l er2, er0 ; ER0 |= ER2
> ROM:0000394A ; note: ER0 = i
> ROM:0000394E mov.l @(0x1C+var_10:16,sp), er1
> ROM:00003954 sub.l er0, er1
> ROM:00003956 and.b #0xF, r3l ; j = (j & 0x0F) +
THRESHOLD
ROM:00003958 and.b #0, r3h
> ROM:0000395A adds #2, er3 ; *** THRESHOLD = 3
> ROM:0000395C adds #1, er3
> ROM:0000395E mov.l @(0x1C+var_10:16,sp), er0
> ROM:00003964 mov.l @(0x1C+outputPointer:16,sp), er5
> ROM:0000396A add.l er5, er0
> ROM:0000396C add.l er5, er1
> ROM:0000396E
> ROM:0000396E loc_396E: ; CODE XREF:
decompress+10Aj
ROM:0000396E mov.b @er1+, r2l
> ROM:00003970 mov.b r2l, @er0
> ROM:00003972 adds #1, er0
> ROM:00003974 mov.l @(0x1C+var_C:16,sp), er5
> ROM:0000397A adds #1, er5
> ROM:0000397C mov.l er5, @(0x1C+var_C:16,sp)
> ROM:00003982 mov.l @(0x1C+var_10:16,sp), er5
> ROM:00003988 adds #1, er5
> ROM:0000398A mov.l er5, @(0x1C+var_10:16,sp)
> ROM:00003990 subs #1, er3
> ROM:00003992 mov.w r3, r3
> ROM:00003994 bne loc_396E:8
> ROM:00003996 bra loc_38B2:16
> ROM:0000399A ;
---------------------------------------------------------------------------
ROM:0000399A
> ROM:0000399A decompress_done: ; CODE XREF:
decompress+32j
ROM:0000399A ; decompress+56j ...
> ROM:0000399A mov.l @(0x1C+var_10:16,sp), er0
> ROM:000039A0 ldm.l @sp+, er4-er6
> ROM:000039A4 add.l #0x10, sp
> ROM:000039AA rts
> ROM:000039AA ; End of function decompress
> ROM:000039AA
And a hex dump of the input data:
000 ff 12 34 ab cd 00 20 00 24 ff 54 2e 30 2e 30 31
> 010 00 4d ff 61 72 20 33 31 20 32 30 ff 30 30 00 31
> 020 35 3a 34 38 bf 3a 32 30 00 7a 00 22 00 4a ff 7a
> 030 03 00 ff f1 00 7a 01 ff 00 20 04 fa 1f 90 47 0a
> 040 ff 6c 0a 68 ba 0b 03 1f 90 f7 46 f6 5a 18 00 54
> 050 70 04 80 fb 7a 06 22 01 fd 00 6c ed fd 55 01 04
> 060 00 02 08 00 04 0c 00 08 10 00 55 10 14 00 20 18
> 070 00 40 1c 00 80 20 00 55 ff 24 00 fe 28 00 fd 2c
> 080 00 fb 30 00 55 f7 34 00 ef 38 00 df 3c 00 bf 40
> 090 00 df 7f 6c ed 6c 6d 78 02 00 0c df d2 68 82 52
> 0a0 12 02 01 68 02 ff 1c d2 58 60 01 c8 0b 70 ff 7a
> 0b0 20 00 28 00 00 46 e4 ff 6a 38 00 ff ff 61 71 30
> 0c0 ff 0c db 11 4b 11 4b eb 0f ff 8b 30 ab 39 4f 02
> 0d0 8b 07 fb 6a 2a 18 00 8c 4c f8 6a ab fa 20 00 8b
> 0e0 26 02 8c 72 70 0c db cc 22 0f 22 0b fb 0a 18 0f
> 0f0 3a 01 7a 26 de fc 01 58 60 ff 6a 72 03 70 30 ef
> 100 fa 20 6a aa 7c 00 8a fc 03 24 34 0f 4c 04 54 18
> 110 0f 64 02 45 18 0f 7c 02 91 53 18 0f 48 0f ac 08
> 120 20 18 0f c4 02 4f c4 18 0f dc 02 4b 18 0f f4 0f
> 130 2e 17 1a 0c c2 f0 00 3a 66 0f 7e 0f 18 0f 18 0f
> 140 7a 04 ff 00 1e 84 80 52 12 1b 74 ff 46 fa 1a 80
> 150 01 00 69 00 ab 59 00 4c 14 20 c6 13 72 54 16 0d
> 160 83 84 0c ce 10 d0 1f d0 1e 22 0f f2 1d cb cc 48
> 170 0f 26 0f 0c cb 22 0f 3a 2b 0d 04 00 92 0f 28 0f
> 180 92 0f 22 0f 92 0f 26 0f 92 0f 22 0f 64 68 1f e4
> 190 24 2b 60 0f 26 0f 0c 2b 22 0f 0c 16 2f 18 0f 72
> 1a0 70 f0 20 90 2f d8 2f d8 2f 90 18 0f 48 0f da 0f
> 1b0 92 09 4e 18 0f aa 02 47 b8 18 0f c2 0f d8 2d 40
> 1c0 fe 00 d6 41 08 0a fc 40 0f 00 50 1b
According to the header, this file should be 0x0508 bytes in size when expanded.
I can upload a binary image of this data (and a copy of the full disassembly) if it would help. Unfortunately I don't have any output data - just the input to the compression algorithm and the length. The first four bytes of the file should be 0x1234ABCD; I'm not sure about the rest of the file.
Thanks. Phil. snipped-for-privacy@despammed.com (valid address)
formatting link