1# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, 2# Espressif Systems (Shanghai) CO LTD, other contributors as noted. 3# 4# SPDX-License-Identifier: GPL-2.0-or-later 5 6import struct 7import sys 8 9 10def byte(bitstr, index): 11 return bitstr[index] 12 13 14def mask_to_shift(mask): 15 """Return the index of the least significant bit in the mask""" 16 shift = 0 17 while mask & 0x1 == 0: 18 shift += 1 19 mask >>= 1 20 return shift 21 22 23def div_roundup(a, b): 24 """Return a/b rounded up to nearest integer, 25 equivalent result to int(math.ceil(float(int(a)) / float(int(b))), only 26 without possible floating point accuracy errors. 27 """ 28 return (int(a) + int(b) - 1) // int(b) 29 30 31def flash_size_bytes(size): 32 """Given a flash size of the type passed in args.flash_size 33 (ie 512KB or 1MB) then return the size in bytes. 34 """ 35 if "MB" in size: 36 return int(size[: size.index("MB")]) * 1024 * 1024 37 elif "KB" in size: 38 return int(size[: size.index("KB")]) * 1024 39 else: 40 raise FatalError("Unknown size %s" % size) 41 42 43def hexify(s, uppercase=True): 44 format_str = "%02X" if uppercase else "%02x" 45 return "".join(format_str % c for c in s) 46 47 48def pad_to(data, alignment, pad_character=b"\xFF"): 49 """Pad to the next alignment boundary""" 50 pad_mod = len(data) % alignment 51 if pad_mod != 0: 52 data += pad_character * (alignment - pad_mod) 53 return data 54 55 56def print_overwrite(message, last_line=False): 57 """Print a message, overwriting the currently printed line. 58 59 If last_line is False, don't append a newline at the end 60 (expecting another subsequent call will overwrite this one.) 61 62 After a sequence of calls with last_line=False, call once with last_line=True. 63 64 If output is not a TTY (for example redirected a pipe), 65 no overwriting happens and this function is the same as print(). 66 """ 67 if sys.stdout.isatty(): 68 print("\r%s" % message, end="\n" if last_line else "") 69 else: 70 print(message) 71 72 73class FatalError(RuntimeError): 74 """ 75 Wrapper class for runtime errors that aren't caused by internal bugs, but by 76 ESP ROM responses or input content. 77 """ 78 79 def __init__(self, message): 80 RuntimeError.__init__(self, message) 81 82 @staticmethod 83 def WithResult(message, result): 84 """ 85 Return a fatal error object that appends the hex values of 86 'result' and its meaning as a string formatted argument. 87 """ 88 89 err_defs = { 90 # ROM error codes 91 0x101: "Out of memory", 92 0x102: "Invalid argument", 93 0x103: "Invalid state", 94 0x104: "Invalid size", 95 0x105: "Requested resource not found", 96 0x106: "Operation or feature not supported", 97 0x107: "Operation timed out", 98 0x108: "Received response was invalid", 99 0x109: "CRC or checksum was invalid", 100 0x10A: "Version was invalid", 101 0x10B: "MAC address was invalid", 102 # Flasher stub error codes 103 0xC000: "Bad data length", 104 0xC100: "Bad data checksum", 105 0xC200: "Bad blocksize", 106 0xC300: "Invalid command", 107 0xC400: "Failed SPI operation", 108 0xC500: "Failed SPI unlock", 109 0xC600: "Not in flash mode", 110 0xC700: "Inflate error", 111 0xC800: "Not enough data", 112 0xC900: "Too much data", 113 0xFF00: "Command not implemented", 114 } 115 116 err_code = struct.unpack(">H", result[:2]) 117 message += " (result was {}: {})".format( 118 hexify(result), err_defs.get(err_code[0], "Unknown result") 119 ) 120 return FatalError(message) 121 122 123class NotImplementedInROMError(FatalError): 124 """ 125 Wrapper class for the error thrown when a particular ESP bootloader function 126 is not implemented in the ROM bootloader. 127 """ 128 129 def __init__(self, bootloader, func): 130 FatalError.__init__( 131 self, 132 "%s ROM does not support function %s." 133 % (bootloader.CHIP_NAME, func.__name__), 134 ) 135 136 137class NotSupportedError(FatalError): 138 def __init__(self, esp, function_name): 139 FatalError.__init__( 140 self, 141 "Function %s is not supported for %s." % (function_name, esp.CHIP_NAME), 142 ) 143 144 145class UnsupportedCommandError(RuntimeError): 146 """ 147 Wrapper class for when ROM loader returns an invalid command response. 148 149 Usually this indicates the loader is running in Secure Download Mode. 150 """ 151 152 def __init__(self, esp, op): 153 if esp.secure_download_mode: 154 msg = "This command (0x%x) is not supported in Secure Download Mode" % op 155 else: 156 msg = "Invalid (unsupported) command 0x%x" % op 157 RuntimeError.__init__(self, msg) 158