Figuring out the .BIX checksums

The .BIX runtime format contains two checksums. A checksum over the runtime image and a checksum over the header. The bootloader does not verify these checksums when you’re uploading a file, but it does so when you’re trying to boot the files. If they’re wrong it will cause the following error:

Hardware EPLD 1.01
Image Loader 3.1.0.1
Loading Diagnostic Image File : diag.bix
Diagnostics 3.1.0.0
User Mode

--- Performing Power-On Self Tests (POST) ---
DUMMY Test 1 ................. PASS
UART Loopback Test ........... PASS
DRAM Test .................... PASS
Timer Test ................... PASS
PCI Device 1 Test ............ PASS
I2C Bus Initialization ....... PASS
Switch Int Loopback Test ..... PASS
Crossbar Int Loopback Test ... PASS
Fan Speed Test ............... PASS
Done All Pass.
------------------ DONE ---------------------

Loading Runtime Image File : op2.bix
<ERR> Runtime Loading Fail - System Halt.

When I loaded the dumped loader in IDA I was not able to find the correct offset, so it didn’t match up the strings. So instead I got a copy of the loader an ARM-powered Accton ES3550YA. This seems to be using the same filestructure, even though the CPU is different. When loading this on offset 0x0 it all matched up nicely, so I could continue the journey.

I found a routine referring to unmatched checksums, so that was probably what I was looking for. I named it ‘filecheck’.

ROM:00001928 filecheck                               ; CODE XREF: sub_180+14DC
ROM:00001928                                         ; sub_180+1550 ...
ROM:00001928
ROM:00001928 oldR4           = -0x1C
ROM:00001928 oldR5           = -0x18
ROM:00001928 oldR6           = -0x14
ROM:00001928 oldR7           = -0x10
ROM:00001928 oldR11          = -0xC
ROM:00001928 oldSP           = -8
ROM:00001928 oldLR           = -4
ROM:00001928
ROM:00001928                 MOV     R12, SP
ROM:0000192C                 STMFD   SP!, {R4-R7,R11,R12,LR,PC}
ROM:00001930                 SUB     R11, R12, #4
ROM:00001934                 MOV     R5, R0
ROM:00001938                 MOV     R7, R1
ROM:0000193C                 MOV     R4, R5
ROM:00001940                 LDR     R3, [R4]
ROM:00001944                 LDR     R2, =0x1A2B3C4D
ROM:00001948                 CMP     R3, R2
ROM:0000194C                 BEQ     loc_1964
ROM:00001950                 LDR     R0, =aFileHeaderMagi ; "\n\rFile Header MagicWord 0X%08x not matc"...
ROM:00001954                 LDR     R1, [R4]
ROM:00001958
ROM:00001958 loc_1958                                ; CODE XREF: filecheck+6C
ROM:00001958                                         ; filecheck+A4
ROM:00001958                 BL      printf
ROM:0000195C                 MOV     R0, #0
ROM:00001960                 LDMDB   R11, {R4-R7,R11,SP,PC}
ROM:00001964 ; ---------------------------------------------------------------------------
ROM:00001964
ROM:00001964 loc_1964                                ; CODE XREF: filecheck+24
ROM:00001964                 MOV     R0, R5
ROM:00001968                 MOV     R1, #0x1C
ROM:0000196C                 BL      checksum
ROM:00001970                 LDR     R3, [R4,#0x1C]
ROM:00001974                 CMP     R3, R0
ROM:00001978                 BEQ     loc_1998
ROM:0000197C                 MOV     R0, R5
ROM:00001980                 MOV     R1, #0x1C
ROM:00001984                 BL      checksum
ROM:00001988                 MOV     R1, R0
ROM:0000198C                 LDR     R0, =aFileHeaderChec ; "\n\rFile Header Checksum 0X%08x not match"...
ROM:00001990                 LDR     R2, [R4,#0x1C]
ROM:00001994                 B       loc_1958
ROM:00001998 ; ---------------------------------------------------------------------------
ROM:00001998
ROM:00001998 loc_1998                                ; CODE XREF: filecheck+50
ROM:00001998                 ADD     R6, R5, #0x20
ROM:0000199C                 MOV     R0, R6
ROM:000019A0                 LDR     R1, [R4,#0xC]
ROM:000019A4                 BL      checksum
ROM:000019A8                 LDR     R3, [R4,#4]
ROM:000019AC                 CMP     R3, R0
ROM:000019B0                 BEQ     loc_19D0
ROM:000019B4                 MOV     R0, R6
ROM:000019B8                 LDR     R1, [R4,#0xC]
ROM:000019BC                 BL      checksum
ROM:000019C0                 MOV     R1, R0
ROM:000019C4                 LDR     R0, =aImageChecksum0 ; "\n\rImage Checksum  0X%08x not match,shou"...
ROM:000019C8                 LDR     R2, [R4,#4]
ROM:000019CC                 B       loc_1958
ROM:000019D0 ; ---------------------------------------------------------------------------
ROM:000019D0
ROM:000019D0 loc_19D0                                ; CODE XREF: filecheck+88
ROM:000019D0                 LDRH    R3, [R4,#0x12]
ROM:000019D4                 CMP     R3, #0
ROM:000019D8                 BNE     loc_19F0
ROM:000019DC                 ADD     R0, R5, #0x20
ROM:000019E0                 MOV     R1, R7
ROM:000019E4                 LDR     R2, [R4,#0xC]
ROM:000019E8                 BL      sub_1A2C
ROM:000019EC                 LDMDB   R11, {R4-R7,R11,SP,PC}
ROM:000019F0 ; ---------------------------------------------------------------------------
ROM:000019F0
ROM:000019F0 loc_19F0                                ; CODE XREF: filecheck+B0
ROM:000019F0                 CMP     R3, #0
ROM:000019F4                 BLT     loc_1A14
ROM:000019F8                 CMP     R3, #2
ROM:000019FC                 BGT     loc_1A14
ROM:00001A00                 ADD     R0, R5, #0x20
ROM:00001A04                 MOV     R1, R7
ROM:00001A08                 LDR     R2, [R4,#0xC]
ROM:00001A0C                 BL      sub_1A68
ROM:00001A10                 LDMDB   R11, {R4-R7,R11,SP,PC}
ROM:00001A14 ; ---------------------------------------------------------------------------
ROM:00001A14
ROM:00001A14 loc_1A14                                ; CODE XREF: filecheck+CC
ROM:00001A14                                         ; filecheck+D4
ROM:00001A14                 MOV     R0, #0
ROM:00001A18                 LDMDB   R11, {R4-R7,R11,SP,PC}
ROM:00001A18 ; End of function filecheck

It first checked the ‘ magic’  of the binary. This was the same 0x1A2B3C4D I had seen before, so I could be assured that the binary was at the address in r4.

After the image check it was calling a small subroutine a few times with varying parameters. First with 0x1c in R1, then with the contents of r4+0xc in R1. Judging from the errormessage printed it seems like 0x1c is the length of the header that it’s checking. 32-bytes – 4-bytes of the checksum is 28 decimal, 1c hexidecimal. I had already noticed earlier that the filesize of the image is located on 0xc. At the second call it also adds 0x20 to the parameter r0, to skip the header.

So it seems like r0 contains the address to the data to be checksummed and r1 the length of the data to checksum.

ROM:00005944 checksum                                ; CODE XREF: filecheck+44
ROM:00005944                                         ; filecheck+5C ...
ROM:00005944
ROM:00005944 oldR4           = -0x14
ROM:00005944 oldR5           = -0x10
ROM:00005944 oldR11          = -0xC
ROM:00005944 oldSP           = -8
ROM:00005944 oldLR           = -4
ROM:00005944
ROM:00005944                 MOV     R12, SP
ROM:00005948                 STMFD   SP!, {R4,R5,R11,R12,LR,PC}
ROM:0000594C                 SUB     R11, R12, #4
ROM:00005950                 MOV     R4, R0
ROM:00005954                 MOV     R0, #0
ROM:00005958                 MOV     R12, R0
ROM:0000595C                 CMP     R0, R1
ROM:00005960                 LDMCSDB R11, {R4,R5,R11,SP,PC}
ROM:00005964                 SUB     LR, R1, #4
ROM:00005968                 MVN     R5, #0
ROM:0000596C
ROM:0000596C loop                                    ; CODE XREF: checksum+54
ROM:0000596C                 ADD     R3, R12, #4
ROM:00005970                 CMP     R3, R1
ROM:00005974                 RSBHI   R3, LR, R12
ROM:00005978                 MOVHI   R3, R3,LSL#3
ROM:0000597C                 MOVHI   R2, R5,LSL R3
ROM:00005980                 MOVLS   R2, 0xFFFFFFFF
ROM:00005984                 LDR     R3, [R4,R12]
ROM:00005988                 AND     R3, R2, R3
ROM:0000598C                 EOR     R0, R0, R3
ROM:00005990                 ADD     R12, R12, #4
ROM:00005994                 CMP     R12, R1
ROM:00005998                 BCC     loop
ROM:0000599C                 LDMDB   R11, {R4,R5,R11,SP,PC}
ROM:0000599C ; End of function checksum

In the loop the address gets moved to R4 and the counter adds 4 to R12 until it’s equal to the length in R1. However, most of the code appears to be NOOP.

“MOVLS   R2, 0xFFFFFFFF” means: move 0xFFFFFFFF to R2 if it’s larger or same. Which it will always be. Then 32 bits are copied from the address+counter to R3 and ANDed to R2. AND with all bits set  is a NOP. Then this is XOR (called EOR in ARM) with R0. So basically, it just XORs every 32-bit block over each other and all red code is extraneous. I’m curious if anybody has an idea why.

I made a small script that XORs every 32-bit block over each other and this works:

PC:/tmp$ xxd SMC87XXML3_Opcode_V3.1.1.66.BIX | head -2
0000000: 1a2b 3c4d 74cb 21c3 0301 0142 0036 2554  .+<Mt.!....B.6%T
0000010: 0098 0001 0186 0719 000e 342a 6cc7 0aaa  ..........4*l...
PC:/tmp$ dd if=SMC87XXML3_Opcode_V3.1.1.66.BIX bs=28 count=1 2> /dev/null | perl /tmp/xor.pl
6cc70aaa
PC:/tmp$ dd if=SMC87XXML3_Opcode_V3.1.1.66.BIX bs=32 skip=1 2> /dev/null | perl /tmp/xor.pl
74cb21c3

Hurrah! You  can see the result corresponds with the file header checksum on 0x1c and the image checksum on 0x4.

For test I uncompressed and recompressed the runtime image, replaced the image checksum, replaced the image filesize and then recalculated the  file header. This results in a smaller, but still working firmware. Succes!

For the next step I tried replacing the “Press ENTER to start session” with “Press ENTAR to start session”. This was successful. Then I replaced the “Press ENTER to start session” with “Press BALLZ to start session”. This resulted in a “<ERR> Runtime Loading Fail – System Halt.”, so there’s still more work to do.

It’s easy to make mistakes when manually hexediting the checksum, size, etc. into the header. So I made a small tool to do this for me, you can find them at github.

Advertisements

One Response to “Figuring out the .BIX checksums”

  1. www.geo-express.pl Says:

    jak schudnąć 8 kg w pół roku co trzeba robić aby schudnąć jak schudnąć na twarzy forum

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: