113 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/python
 | |
| 
 | |
| """
 | |
| This script patches the CRC checksums into an existing ELF file.
 | |
| 
 | |
| For this, it searches the follwoing sections:
 | |
| 	1) .text
 | |
| 	2) .data
 | |
| 	3) .ccmdata
 | |
| 	4) .vectors
 | |
| 
 | |
| All sections MUST be a multiple of 4 bytes long because the CRC calculation relies on whole 32 bit words.
 | |
| The sections are excrated and the CRC is calculated for each section.
 | |
| 
 | |
| In the section .flashcrc, the script expects a single struct with the prototype:
 | |
| struct flash_crcs {
 | |
| 	uint32_t start_magic;
 | |
| 	uint32_t crc_section_text;
 | |
| 	uint32_t crc_section_data;
 | |
| 	uint32_t crc_section_ccm_data;
 | |
| 	uint32_t crc_section_vectors;
 | |
| 	uint32_t end_magic;
 | |
| };
 | |
| 
 | |
| It checks, if the start magic and end magic are set to the appropriate values and then patches in the CRC values of the sections.
 | |
| The magic values checked for are: 0xA8BE53F9 and 0xFFA582FF
 | |
| """
 | |
| from elftools.elf.elffile import ELFFile
 | |
| from elftools.elf.segments import Segment
 | |
| import elftools.elf.constants as elf_const
 | |
| import sys
 | |
| import crcmod
 | |
| import crcmod.predefined
 | |
| import struct
 | |
| 
 | |
| crc_calc = crcmod.predefined.mkCrcFun('crc-32-mpeg')
 | |
| 
 | |
| if len(sys.argv) < 2:
 | |
| 	print("Usage:", sys.argv[0], ' <elf file>')
 | |
| 	sys.exit(-1)
 | |
| 
 | |
| filename=sys.argv[1]
 | |
| 
 | |
| def section_calculate_crc(section):
 | |
| 	data = bytearray(section.data())
 | |
| 	be_data = bytearray([0 for k in range(0, len(data))])
 | |
| 	# Rearrange data, because the STM controller sees it as 32 bit little endian words
 | |
| 	for i in range(0, int(len(data)/4)):
 | |
| 		be_data[i*4+0] = data[i*4+3]
 | |
| 		be_data[i*4+1] = data[i*4+2]
 | |
| 		be_data[i*4+2] = data[i*4+1]
 | |
| 		be_data[i*4+3] = data[i*4+0]
 | |
| 
 | |
| 	return crc_calc(be_data)
 | |
| 
 | |
| with open(filename, 'r+b') as f:
 | |
| 	elf = ELFFile(f)
 | |
| 	sections = {}
 | |
| 	sections['.text'] = elf.get_section_by_name('.text')
 | |
| 	sections['.data'] = elf.get_section_by_name('.data')
 | |
| 	sections['.ccmdata'] = elf.get_section_by_name('.ccmdata')
 | |
| 	sections['.vectors'] = elf.get_section_by_name('.vectors')
 | |
| 
 | |
| 	for key, sec in sections.items():
 | |
| 		if sec is None:
 | |
| 			print("Error! Section", key, "not found in ELF file!")
 | |
| 			sys.exit(-1)
 | |
| 		print('Found section', key, 'Size:',
 | |
| 			  sec.data_size, 'Type:', sec['sh_type'])
 | |
| 		if sec['sh_type'] != 'SHT_PROGBITS':
 | |
| 			print('Error! Section must be of type SHT_PROGBITS')
 | |
| 			sys.exit(-1)
 | |
| 		if (sec.data_size % 4 != 0):
 | |
| 			print("Section", key, "has wrong size. Must be a multiple of 4 bytes!")
 | |
| 			sys.exit(-1)
 | |
| 
 | |
| 	text_crc = section_calculate_crc(sections['.text'])
 | |
| 	print('CRC of .text section:', hex(text_crc))
 | |
| 	data_crc = section_calculate_crc(sections['.data'])
 | |
| 	print('CRC of .data section:', hex(data_crc))
 | |
| 	ccmdata_crc = section_calculate_crc(sections['.ccmdata'])
 | |
| 	print('CRC of .ccmdata section:', hex(ccmdata_crc))
 | |
| 	vextors_crc = section_calculate_crc(sections['.vectors'])
 | |
| 	print('CRC of .vectors section:', hex(vextors_crc))
 | |
| 
 | |
| 	# Check the flashcrc section
 | |
| 	flashcrc_sec = elf.get_section_by_name('.flashcrc')
 | |
| 	if flashcrc_sec is None:
 | |
| 		print('Section for flash CRC missing!')
 | |
| 		sys.exit(-1)
 | |
| 	if flashcrc_sec.data_size != 6*4:
 | |
| 		print("Warning!!! .flashcrc section has wrong size:",flashcrc_sec.data_size)
 | |
| 
 | |
| 	crc_sec_data = bytearray(flashcrc_sec.data())
 | |
| 	magic1 = struct.unpack('<I'*1, bytes(crc_sec_data[0:4]))[0]
 | |
| 	magic2 = struct.unpack('<I'*1, bytes(crc_sec_data[-4:]))[0]
 | |
| 	print("CRC section magic values:", hex(magic1), hex(magic2))
 | |
| 	if magic1 != 0xA8BE53F9 or magic2 != 0xFFA582FF:
 | |
| 		print("Wrong magics in CRC section. Data misalignment?")
 | |
| 		sys.exit(-2)
 | |
| 
 | |
| 	crc_sec_offset = flashcrc_sec['sh_offset']
 | |
| 	print('CRC section ELF file offset:', hex(crc_sec_offset))
 | |
| 	
 | |
| 	crc_sec_data[4:8] = struct.pack('<I',text_crc)
 | |
| 	crc_sec_data[8:12] = struct.pack('<I',data_crc)
 | |
| 	crc_sec_data[12:16] = struct.pack('<I',ccmdata_crc)
 | |
| 	crc_sec_data[16:20] = struct.pack('<I',vextors_crc)
 | |
| 	f.seek(crc_sec_offset)
 | |
| 	f.write(crc_sec_data)
 | |
| 	print('CRCs patched successfully')
 | |
| 
 | |
| 	 |