mirror of
				https://github.com/esp8266/Arduino.git
				synced 2025-11-03 14:33:37 +03:00 
			
		
		
		
	Use subprocess.run in elf2bin (#8799)
Properly handle Popen object, it takes care of everything we need to do like .communicate() and handle timeouts. Introduce a small timeout to run so we also know when that happens Clean-up with pythonic path join and formatting through f"" strings
This commit is contained in:
		@@ -20,6 +20,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
import argparse
 | 
					import argparse
 | 
				
			||||||
 | 
					import io
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
@@ -33,37 +34,75 @@ fsizeb = { '512K': 0, '256K': 1, '1M': 2, '2M': 3, '4M': 4, '8M': 8, '16M': 9 }
 | 
				
			|||||||
crcsize_offset = 4096 + 16
 | 
					crcsize_offset = 4096 + 16
 | 
				
			||||||
crcval_offset =  4096 + 16 + 4
 | 
					crcval_offset =  4096 + 16 + 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Elf2BinException(Exception):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_elf_entry(elf, path):
 | 
					def get_elf_entry(elf, path):
 | 
				
			||||||
    p = subprocess.Popen([path + "/xtensa-lx106-elf-readelf", '-h', elf], stdout=subprocess.PIPE, universal_newlines=True )
 | 
					    result = subprocess.run(
 | 
				
			||||||
    lines = p.stdout.readlines()
 | 
					        [os.path.join(path, "xtensa-lx106-elf-readelf"), "-h", elf],
 | 
				
			||||||
    for line in lines:
 | 
					        check=True,
 | 
				
			||||||
 | 
					        timeout=15,
 | 
				
			||||||
 | 
					        stdout=subprocess.PIPE,
 | 
				
			||||||
 | 
					        universal_newlines=True,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lines = io.StringIO(result.stdout)
 | 
				
			||||||
 | 
					    for line in lines.readlines():
 | 
				
			||||||
        if 'Entry point address' in line:
 | 
					        if 'Entry point address' in line:
 | 
				
			||||||
            words = re.split('\s+', line)
 | 
					            words = re.split('\s+', line)
 | 
				
			||||||
            entry_point = words[-2]
 | 
					            entry_point = words[-2]
 | 
				
			||||||
            return int(entry_point, 16)
 | 
					            return int(entry_point, 16)
 | 
				
			||||||
    raise Exception('Unable to find entry point in file "' + elf + '"')
 | 
					
 | 
				
			||||||
 | 
					    raise Elf2BinException(f'Unable to find entry point in file "{elf}"')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_segment_size_addr(elf, segment, path):
 | 
					def get_segment_size_addr(elf, segment, path):
 | 
				
			||||||
    p = subprocess.Popen([path + '/xtensa-lx106-elf-objdump', '-h', '-j', segment,  elf], stdout=subprocess.PIPE, universal_newlines=True )
 | 
					    result = subprocess.run(
 | 
				
			||||||
    lines = p.stdout.readlines()
 | 
					        [os.path.join(path, "xtensa-lx106-elf-objdump"), "-h", "-j", segment, elf],
 | 
				
			||||||
    for line in lines:
 | 
					        check=True,
 | 
				
			||||||
 | 
					        timeout=15,
 | 
				
			||||||
 | 
					        stdout=subprocess.PIPE,
 | 
				
			||||||
 | 
					        universal_newlines=True,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lines = io.StringIO(result.stdout)
 | 
				
			||||||
 | 
					    for line in lines.readlines():
 | 
				
			||||||
        if segment in line:
 | 
					        if segment in line:
 | 
				
			||||||
            words = re.split('\s+', line)
 | 
					            words = re.split('\s+', line)
 | 
				
			||||||
            size = int(words[3], 16)
 | 
					            size = int(words[3], 16)
 | 
				
			||||||
            addr = int(words[4], 16)
 | 
					            addr = int(words[4], 16)
 | 
				
			||||||
            return [ size, addr ]
 | 
					            return [ size, addr ]
 | 
				
			||||||
    raise Exception('Unable to find size and start point in file "' + elf + '" for "' + segment + '"')
 | 
					
 | 
				
			||||||
 | 
					    raise Elf2BinException(
 | 
				
			||||||
 | 
					        f'Unable to find size and start point in file "{elf}" for "{segment}"'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read_segment(elf, segment, path):
 | 
					def read_segment(elf, segment, path):
 | 
				
			||||||
    fd, tmpfile = tempfile.mkstemp()
 | 
					    fd, tmpfile = tempfile.mkstemp()
 | 
				
			||||||
    os.close(fd)
 | 
					    os.close(fd)
 | 
				
			||||||
    subprocess.check_call([path + "/xtensa-lx106-elf-objcopy", '-O', 'binary', '--only-section=' + segment, elf, tmpfile], stdout=subprocess.PIPE)
 | 
					    try:
 | 
				
			||||||
    with open(tmpfile, "rb") as f:
 | 
					        subprocess.check_call(
 | 
				
			||||||
        raw = f.read()
 | 
					            [
 | 
				
			||||||
    os.remove(tmpfile)
 | 
					                os.path.join(path, "xtensa-lx106-elf-objcopy"),
 | 
				
			||||||
 | 
					                "-O",
 | 
				
			||||||
 | 
					                "binary",
 | 
				
			||||||
 | 
					                f"--only-section={segment}",
 | 
				
			||||||
 | 
					                elf,
 | 
				
			||||||
 | 
					                tmpfile,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            stdout=subprocess.PIPE,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        with open(tmpfile, "rb") as f:
 | 
				
			||||||
 | 
					            raw = f.read()
 | 
				
			||||||
 | 
					    finally:
 | 
				
			||||||
 | 
					        os.remove(tmpfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return raw
 | 
					    return raw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def write_bin(out, args, elf, segments, to_addr):
 | 
					def write_bin(out, args, elf, segments, to_addr):
 | 
				
			||||||
    entry = int(get_elf_entry( elf, args.path ))
 | 
					    entry = int(get_elf_entry( elf, args.path ))
 | 
				
			||||||
    header = [ 0xe9, len(segments), fmodeb[args.flash_mode], ffreqb[args.flash_freq] + 16 * fsizeb[args.flash_size],
 | 
					    header = [ 0xe9, len(segments), fmodeb[args.flash_mode], ffreqb[args.flash_freq] + 16 * fsizeb[args.flash_size],
 | 
				
			||||||
@@ -85,7 +124,7 @@ def write_bin(out, args, elf, segments, to_addr):
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            for data in raw:
 | 
					            for data in raw:
 | 
				
			||||||
                checksum = checksum ^ ord(data)
 | 
					                checksum = checksum ^ ord(data)
 | 
				
			||||||
        except Exception:
 | 
					        except:
 | 
				
			||||||
            for data in raw:
 | 
					            for data in raw:
 | 
				
			||||||
                checksum = checksum ^ data
 | 
					                checksum = checksum ^ data
 | 
				
			||||||
    total_size += 1
 | 
					    total_size += 1
 | 
				
			||||||
@@ -95,11 +134,14 @@ def write_bin(out, args, elf, segments, to_addr):
 | 
				
			|||||||
    out.write(bytearray([checksum]))
 | 
					    out.write(bytearray([checksum]))
 | 
				
			||||||
    if to_addr != 0:
 | 
					    if to_addr != 0:
 | 
				
			||||||
        if total_size + 8 > to_addr:
 | 
					        if total_size + 8 > to_addr:
 | 
				
			||||||
            raise Exception('Bin image of ' + elf + ' is too big, actual size ' + str(total_size  + 8) + ', target size ' + str(to_addr) + '.')
 | 
					            raise Elf2BinException(
 | 
				
			||||||
 | 
					                f'Bin image of "{elf}" is too big! Actual size {str(total_size  + 8)}, target size {str(to_addr)}'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        while total_size < to_addr:
 | 
					        while total_size < to_addr:
 | 
				
			||||||
            out.write(bytearray([0xaa]))
 | 
					            out.write(bytearray([0xaa]))
 | 
				
			||||||
            total_size += 1
 | 
					            total_size += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def crc8266(ldata):
 | 
					def crc8266(ldata):
 | 
				
			||||||
    "Return the CRC of ldata using same algorithm as eboot"
 | 
					    "Return the CRC of ldata using same algorithm as eboot"
 | 
				
			||||||
    crc = 0xffffffff
 | 
					    crc = 0xffffffff
 | 
				
			||||||
@@ -119,6 +161,7 @@ def crc8266(ldata):
 | 
				
			|||||||
                crc = int(crc ^ 0x04c11db7)
 | 
					                crc = int(crc ^ 0x04c11db7)
 | 
				
			||||||
    return crc
 | 
					    return crc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def store_word(raw, offset, val):
 | 
					def store_word(raw, offset, val):
 | 
				
			||||||
    "Place a 4-byte word in 8266-dependent order in the raw image"
 | 
					    "Place a 4-byte word in 8266-dependent order in the raw image"
 | 
				
			||||||
    raw[offset] = val & 255
 | 
					    raw[offset] = val & 255
 | 
				
			||||||
@@ -127,6 +170,7 @@ def store_word(raw, offset, val):
 | 
				
			|||||||
    raw[offset + 3] = (val >> 24) & 255
 | 
					    raw[offset + 3] = (val >> 24) & 255
 | 
				
			||||||
    return raw
 | 
					    return raw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def add_crc(out):
 | 
					def add_crc(out):
 | 
				
			||||||
    with open(out, "rb") as binfile:
 | 
					    with open(out, "rb") as binfile:
 | 
				
			||||||
        raw = bytearray(binfile.read())
 | 
					        raw = bytearray(binfile.read())
 | 
				
			||||||
@@ -141,15 +185,16 @@ def add_crc(out):
 | 
				
			|||||||
    with open(out, "wb") as binfile:
 | 
					    with open(out, "wb") as binfile:
 | 
				
			||||||
        binfile.write(raw)
 | 
					        binfile.write(raw)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def gzip_bin(mode, out):
 | 
					def gzip_bin(mode, out):
 | 
				
			||||||
    import gzip
 | 
					    import gzip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    firmware_path = out
 | 
					    firmware_path = out
 | 
				
			||||||
    gzip_path = firmware_path + '.gz'
 | 
					    gzip_path = f"{firmware_path}.gz"
 | 
				
			||||||
    orig_path = firmware_path + '.orig'
 | 
					    orig_path = f"{firmware_path}.orig"
 | 
				
			||||||
    if os.path.exists(gzip_path):
 | 
					    if os.path.exists(gzip_path):
 | 
				
			||||||
        os.remove(gzip_path)
 | 
					        os.remove(gzip_path)
 | 
				
			||||||
    print('GZipping firmware ' + firmware_path)
 | 
					    print(f'GZipping firmware {firmware_path}')
 | 
				
			||||||
    with open(firmware_path, 'rb') as firmware_file, \
 | 
					    with open(firmware_path, 'rb') as firmware_file, \
 | 
				
			||||||
            gzip.open(gzip_path, 'wb') as dest:
 | 
					            gzip.open(gzip_path, 'wb') as dest:
 | 
				
			||||||
        data = firmware_file.read()
 | 
					        data = firmware_file.read()
 | 
				
			||||||
@@ -162,10 +207,11 @@ def gzip_bin(mode, out):
 | 
				
			|||||||
    if mode == "PIO":
 | 
					    if mode == "PIO":
 | 
				
			||||||
        if os.path.exists(orig_path):
 | 
					        if os.path.exists(orig_path):
 | 
				
			||||||
            os.remove(orig_path)
 | 
					            os.remove(orig_path)
 | 
				
			||||||
        print('Moving original firmware to ' + orig_path)
 | 
					        print(f'Moving original firmware to {orig_path}')
 | 
				
			||||||
        os.rename(firmware_path, orig_path)
 | 
					        os.rename(firmware_path, orig_path)
 | 
				
			||||||
        os.rename(gzip_path, firmware_path)
 | 
					        os.rename(gzip_path, firmware_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main():
 | 
					def main():
 | 
				
			||||||
    parser = argparse.ArgumentParser(description='Create a BIN file from eboot.elf and Arduino sketch.elf for upload by esptool.py')
 | 
					    parser = argparse.ArgumentParser(description='Create a BIN file from eboot.elf and Arduino sketch.elf for upload by esptool.py')
 | 
				
			||||||
    parser.add_argument('-e', '--eboot', action='store', required=True, help='Path to the Arduino eboot.elf bootloader')
 | 
					    parser.add_argument('-e', '--eboot', action='store', required=True, help='Path to the Arduino eboot.elf bootloader')
 | 
				
			||||||
@@ -179,8 +225,7 @@ def main():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    args = parser.parse_args()
 | 
					    args = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print('Creating BIN file "{out}" using "{eboot}" and "{app}"'.format(
 | 
					    print(f'Creating BIN file "{args.out}" using "{args.eboot}" and "{args.app}"')
 | 
				
			||||||
        out=args.out, eboot=args.eboot, app=args.app))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with open(args.out, "wb") as out:
 | 
					    with open(args.out, "wb") as out:
 | 
				
			||||||
        def wrapper(**kwargs):
 | 
					        def wrapper(**kwargs):
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user