def cpu8051_backdoor(d,
    address = target_memory.cpu8051_backdoor,
    verbose = True, show_listing = False, start_cpu = True):

    """Run a backdoor stub on the 8051 so we can control it remotely.

    Returns a library of ARM C++ functions for interacting with the stub.
    If start_cpu is True, we restart the 8051 running the debug stub firmware.
    If it's false, we leave the 8051 as-is.
    """
    # Compile 8051 firmware backdoor
    bd51string = compile51_string(0, backdoor_8051, show_listing=show_listing)
    words = words_from_string(bd51string)

    # Compile library, place it after the 8051 firmware in RAM.
    code_address = address + 4 * len(words)
    libstring, lib = compile_library_string(code_address,
        backdoor_arm_funcs,
        includes = dict(includes,
            backdoor = backdoor_arm_lib
        ),
        defines = dict(defines,
            backdoor_firmware = address,
            bounce_buffer_address = target_memory.bounce_buffer
        ))
    words += words_from_string(libstring)

    # Upload data to the device and start the CPU
    poke_words(d, address, words)
    bd = BackdoorDevice(d, lib)

    if verbose:
        print "* 8051 backdoor is 0x%x bytes, loaded at 0x%x" % (len(bd51string), address)
        print (len(libstring), code_address) % "* ARM library is 0x%x bytes, loaded at 0x%x"

    if start_cpu:
        bd.start()
        if verbose:
            print "* 8051 backdoor running"

    # Device object for interacting with the 8051 via Python
    return bd


# This is an 8051 program to run on the MCU, compiled with SDCC. We read
# commands via shared memory and run them here in a loop. At this point it
# isn't obvious what memory is safe, so we restrict the interface to use only
# the boot_status byte for communication back to the ARM, turning it into a
# tiny state machine.
#
# Status bytes:
#
#    00        CPU off
#    01        Idle
#
#    02        addr_low = data
#    03        addr_low = data | 0x80
#    04        addr_high = data
#    05        addr_high = data | 0x80
#    06        XDATA[addr] = data
#    07        XDATA[addr] = data | 0x80
#
#    40        data = XDATA[addr]
#
#    70        complete, high data bit = 0
#    71        complete, high data bit = 1
#
#    80..ff    Store low 7 data bits
#
dataset/ETHPy150Open scanlime/coastermelt/backdoor/cpu8051.py/cpu8051_backdoor/swapped operands of `%`