def write_image_footer(self, new_image, cur_image, config, configkey, imagenum, base_addr, name): load_addr = int(config.get(configkey, 'load_addr'), 0) exec_addr = int(config.get(configkey, 'exec_addr'), 0) type = int(config.get(configkey, 'type'), 0) # Prepare the image footer based on the data # we've stored previously fi = FirmwareImage() fi.imagenum = imagenum fi.base_address = base_addr fi.load_address = load_addr fi.exec_address = exec_addr fi.type = type fi.name = name fi.image_checksum = FirmwareImage.computeChecksum(cur_image) fi.length = len(cur_image) # Calculate the new checksum.. fi.footer_checksum = fi.computeFooterChecksum() # flash chip breaks data down into 64KB blocks. # Footer should be at the end of one of these curblock = int(math.floor(new_image.tell() / 65536)) curblockend = curblock * 65536 last_image_end = new_image.tell() # If we don't have space to write the footer # at the end of the current block, move to the next block if curblockend - 61 < last_image_end: curblock += 1 footerpos = (curblock * 65536) - 61 new_image.seek(footerpos) # And write the footer to the output file new_image.write(fi.getRawString()) return (footerpos, curblockend)
def parse(self, ipmifw, extract, config): bootloader = ipmifw[:64040] bootloader_md5 = hashlib.md5(bootloader).hexdigest() if extract: print("Dumping bootloader to data/bootloader.bin") with open('data/bootloader.bin', 'wb') as f: f.write(bootloader) imagecrc = [] # Start by parsing all the different images within the firmware # This method comes directly from the SDK. Read through the file in 64 byte chunks, and look for the signature at a certain point in the string # Seems kinda scary, as there might be other parts of the file that include this. for i in range(0, len(ipmifw), 64): footer = ipmifw[i:i + 64] fi = FirmwareImage() # 12 bytes of padding. I think this can really be anything, though it's usually \xFF fi.loadFromString(footer[12:]) if not fi.isValid(): continue print("\n" + str(fi)) imagestart = fi.base_address if imagestart > 0x40000000: # I'm unsure where this 0x40000000 byte offset is coming from. Perhaps I'm not parsing the footer correctly? imagestart -= 0x40000000 imageend = imagestart + fi.length curcrc = zlib.crc32(ipmifw[imagestart:imageend]) & 0xffffffff imagecrc.append(curcrc) if extract: print("Dumping 0x%s to 0x%s to data/%s.bin" % (imagestart, imageend, fi.name)) with open('data/%s.bin' % fi.name, 'wb') as f: f.write(ipmifw[imagestart:imageend]) computed_image_checksum = FirmwareImage.computeChecksum( ipmifw[imagestart:imageend]) if computed_image_checksum != fi.image_checksum: print( "Warning: Image checksum mismatch, footer: 0x%x computed: 0x%x" % (fi.image_checksum, computed_image_checksum)) else: print("Image checksum matches") config.set('images', str(fi.imagenum), 'present') configkey = 'image_%i' % fi.imagenum config.add_section(configkey) config.set(configkey, 'length', hex(fi.length)) config.set(configkey, 'base_addr', hex(fi.base_address)) config.set(configkey, 'load_addr', hex(fi.load_address)) config.set(configkey, 'exec_addr', hex(fi.exec_address)) config.set(configkey, 'name', fi.name) config.set(configkey, 'type', hex(fi.type)) # Next, find and validate the global footer for imageFooter in re.findall(b"ATENs_FW(.{8})", ipmifw, re.DOTALL): footer = FirmwareFooter() footer.loadFromString(imageFooter) computed_checksum = footer.computeFooterChecksum(imagecrc) print("\n" + str(footer)) if footer.checksum == computed_checksum: print("Firmware checksum matches") else: print( "Firwamre checksum mismatch, footer: 0x%x computed: 0x%x" % (footer.checksum, computed_checksum)) config.set('global', 'major_version', str(footer.rev1)) config.set('global', 'minor_version', str(footer.rev2)) config.set('global', 'footer_version', str(footer.footerver))
def write_image_footer(self, new_image, cur_image, config, configkey, imagenum, base_addr, name): load_addr = int(config.get(configkey, 'load_addr'),0) exec_addr = int(config.get(configkey, 'exec_addr'),0) type = int(config.get(configkey, 'type'),0) # Prepare the image footer based on the data # we've stored previously fi = FirmwareImage() fi.imagenum = imagenum fi.base_address = base_addr fi.load_address = load_addr fi.exec_address = exec_addr fi.type = type fi.name = name fi.image_checksum = FirmwareImage.computeChecksum(cur_image) fi.length = len(cur_image) # Calculate the new checksum.. fi.footer_checksum = fi.computeFooterChecksum() # flash chip breaks data down into 64KB blocks. # Footer should be at the end of one of these curblock = int(math.floor(new_image.tell() / 65536)) curblockend = curblock * 65536 last_image_end = new_image.tell() # If we don't have space to write the footer # at the end of the current block, move to the next block if curblockend - 61 < last_image_end: curblock += 1 footerpos = (curblock * 65536) - 61 new_image.seek(footerpos) # And write the footer to the output file new_image.write(fi.getRawString()) return (footerpos, curblockend)
def parse(self, ipmifw, extract, config): bootloader = ipmifw[:64040] bootloader_md5 = hashlib.md5(bootloader).hexdigest() if extract: print "Dumping bootloader to data/bootloader.bin" with open('data/bootloader.bin','w') as f: f.write(bootloader) imagecrc = [] # Start by parsing all the different images within the firmware # This method comes directly from the SDK. Read through the file in 64 byte chunks, and look for the signature at a certain point in the string # Seems kinda scary, as there might be other parts of the file that include this. for i in range(0,len(ipmifw),64): footer = ipmifw[i:i+64] fi = FirmwareImage() # 12 bytes of padding. I think this can really be anything, though it's usually \xFF fi.loadFromString(footer[12:]) if not fi.isValid(): continue print "\n"+str(fi) imagestart = fi.base_address if imagestart > 0x40000000: # I'm unsure where this 0x40000000 byte offset is coming from. Perhaps I'm not parsing the footer correctly? imagestart -= 0x40000000 imageend = imagestart + fi.length curcrc = zlib.crc32(ipmifw[imagestart:imageend]) & 0xffffffff imagecrc.append(curcrc) if extract: print "Dumping 0x%s to 0x%s to data/%s.bin" % (imagestart, imageend, fi.name) with open('data/%s.bin' % fi.name.replace("\x00",""),'w') as f: f.write(ipmifw[imagestart:imageend]) computed_image_checksum = FirmwareImage.computeChecksum(ipmifw[imagestart:imageend]) if computed_image_checksum != fi.image_checksum: print "Warning: Image checksum mismatch, footer: 0x%x computed: 0x%x" % (fi.image_checksum,computed_image_checksum) else: print "Image checksum matches" config.set('images', str(fi.imagenum), 'present') configkey = 'image_%i' % fi.imagenum config.add_section(configkey) config.set(configkey, 'length', hex(fi.length)) config.set(configkey, 'base_addr', hex(fi.base_address)) config.set(configkey, 'load_addr', hex(fi.load_address)) config.set(configkey, 'exec_addr', hex(fi.exec_address)) config.set(configkey, 'name', fi.name) config.set(configkey, 'type', hex(fi.type)) # Next, find and validate the global footer for imageFooter in re.findall("ATENs_FW(.{8})",ipmifw,re.DOTALL): footer = FirmwareFooter() footer.loadFromString(imageFooter) computed_checksum = footer.computeFooterChecksum(imagecrc) print "\n"+str(footer) if footer.checksum == computed_checksum: print "Firmware checksum matches" else: print "Firwamre checksum mismatch, footer: 0x%x computed: 0x%x" % (footer.checksum, computed_checksum) config.set('global', 'major_version', footer.rev1) config.set('global', 'minor_version', footer.rev2) config.set('global', 'footer_version', footer.footerver)
new_image.seek(imagestart) print "Using %s/data/%s.bin" % (os.getcwd(), name) with open('data/%s.bin' % name, 'r') as img: cur_image = img.read() print "Writing 0x%x bytes at 0x%x" % (len(cur_image), new_image.tell()) # Write the actual image contents new_image.write(cur_image) # Compute the CRC32 of this image. This is used for the global footer, not for each individual footer curcrc = zlib.crc32(cur_image) & 0xffffffff imagecrc.append(curcrc) # Prepare the image footer based on the data we've stored previously fi = FirmwareImage() fi.imagenum = imagenum fi.base_address = base_addr fi.exec_address = exec_addr fi.load_address = load_addr fi.name = name fi.image_checksum = FirmwareImage.computeChecksum(cur_image) fi.type = type fi.length = len(cur_image) # Calculate the new checksum.. fi.footer_checksum = fi.computeFooterChecksum() # flash chip breaks data down into 64KB blocks. Footer should be at the end of one of these curblock = int(math.floor(new_image.tell() / 65536))
# Seek to where this image will start new_image.seek(imagestart) with open('data/%s.bin' % name,'r') as img: cur_image = img.read() # Write the actual image contents new_image.write(cur_image) # Compute the CRC32 of this image. This is used for the global footer, not for each individual footer curcrc = zlib.crc32(cur_image) & 0xffffffff imagecrc.append(curcrc) # Prepare the image footer based on the data we've stored previously fi = FirmwareImage() fi.imagenum = imagenum fi.base_address = base_addr fi.exec_address = exec_addr fi.load_address = load_addr fi.name = name fi.image_checksum = FirmwareImage.computeChecksum(cur_image) fi.type = type fi.length = len(cur_image) # Calculate the new checksum.. fi.footer_checksum = fi.computeFooterChecksum() # flash chip breaks data down into 64KB blocks. Footer should be at the end of one of these curblock = int(math.floor(new_image.tell() / 65536))