3 # Customizations for Chitu boards
6 if pioutil
.is_pio_build():
7 import os
,random
,struct
,uuid
,marlin
8 # Relocate firmware from 0x08000000 to 0x08008800
9 marlin
.relocate_firmware("0x08008800")
11 def calculate_crc(contents
, seed
):
12 accumulating_xor_value
= seed
;
14 for i
in range(0, len(contents
), 4):
15 value
= struct
.unpack('<I', contents
[ i
: i
+ 4])[0]
16 accumulating_xor_value
= accumulating_xor_value ^ value
17 return accumulating_xor_value
19 def xor_block(r0
, r1
, block_number
, block_size
, file_key
):
20 # This is the loop counter
23 # This is the key length
26 # This is an initial seed
29 # This is the block counter
30 block_number
= xor_seed
* block_number
32 #load the xor key from the file
35 for loop_counter
in range(0, block_size
):
36 # meant to make sure different bits of the key are used.
37 xor_seed
= int(loop_counter
/ key_length
)
39 # IP is a scratch register / R12
40 ip
= loop_counter
- (key_length
* xor_seed
)
42 # xor_seed = (loop_counter * loop_counter) + block_number
43 xor_seed
= (loop_counter
* loop_counter
) + block_number
45 # shift the xor_seed left by the bits in IP.
46 xor_seed
= xor_seed
>> ip
51 # XOR the seed with r7
52 xor_seed
= xor_seed ^ r7
55 xor_seed
= xor_seed ^ ip
57 #Now store the byte back
58 r1
[loop_counter
] = xor_seed
& 0xFF
60 #increment the loop_counter
61 loop_counter
= loop_counter
+ 1
63 def encrypt_file(input, output_file
, file_length
):
64 input_file
= bytearray(input.read())
68 uid_value
= uuid
.uuid4()
69 file_key
= int(uid_value
.hex[0:8], 16)
73 # the input file is exepcted to be in chunks of 0x800
75 while len(input_file
) % block_size
!= 0:
76 input_file
.extend(b
'0x0')
78 # write the file header
79 output_file
.write(struct
.pack(">I", 0x443D2D3F))
80 # encrypt the contents using a known file header key
83 output_file
.write(struct
.pack("<I", file_key
))
85 #TODO - how to enforce that the firmware aligns to block boundaries?
86 block_count
= int(len(input_file
) / block_size
)
87 print ("Block Count is ", block_count
)
88 for block_number
in range(0, block_count
):
89 block_offset
= (block_number
* block_size
)
90 block_end
= block_offset
+ block_size
91 block_array
= bytearray(input_file
[block_offset
: block_end
])
92 xor_block(block_array
, block_array
, block_number
, block_size
, file_key
)
93 for n
in range (0, block_size
):
94 input_file
[block_offset
+ n
] = block_array
[n
]
96 # update the expected CRC value.
97 xor_crc
= calculate_crc(block_array
, xor_crc
)
100 output_file
.write(struct
.pack("<I", xor_crc
))
102 # finally, append the encrypted results.
103 output_file
.write(input_file
)
106 # Encrypt ${PROGNAME}.bin and save it as 'update.cbd'
107 def encrypt(source
, target
, env
):
108 firmware
= open(target
[0].path
, "rb")
109 update
= open(target
[0].dir.path
+ '/update.cbd', "wb")
110 length
= os
.path
.getsize(target
[0].path
)
112 encrypt_file(firmware
, update
, length
)
117 marlin
.add_post_action(encrypt
);