Example #1
0
def main() -> int:
    parser = argparse.ArgumentParser(
        description=
        "Tools for peeking/poking values into running memory on a Naomi/Triforce/Chihiro.",
    )
    subparsers = parser.add_subparsers(help='Action to take', dest='action')

    peek_parser = subparsers.add_parser(
        'peek',
        help='Peek at a value in an 8/16/32-bit memory location',
        description='Peek at a value in an 8/16/32-bit memory location',
    )
    peek_parser.add_argument(
        "ip",
        metavar="IP",
        type=str,
        help="The IP address that the NetDimm is configured on.",
    )
    peek_parser.add_argument(
        "address",
        metavar="ADDR",
        type=str,
        help="The hex address of memory that you would like to peek into.",
    )
    peek_parser.add_argument(
        "size",
        metavar="SIZE",
        type=int,
        help="The size in bytes you want to read. Valid values are 1, 2 and 4.",
    )

    poke_parser = subparsers.add_parser(
        'poke',
        help='Poke a value into an 8/16/32-bit memory location',
        description='Poke a value into an 8/16/32-bit memory location',
    )
    poke_parser.add_argument(
        "ip",
        metavar="IP",
        type=str,
        help="The IP address that the NetDimm is configured on.",
    )
    poke_parser.add_argument(
        "address",
        metavar="ADDR",
        type=str,
        help="The hex address of memory that you would like to poke into.",
    )
    poke_parser.add_argument(
        "size",
        metavar="SIZE",
        type=int,
        help=
        "The size in bytes you want to write. Valid values are 1, 2 and 4.",
    )
    poke_parser.add_argument(
        "data",
        metavar="VALUE",
        type=str,
        help="The hex value you wish to write into the address.",
    )

    dump_parser = subparsers.add_parser(
        'dump',
        help='Dump data from a memory location.',
        description='Dump data from a memory location.',
    )
    dump_parser.add_argument(
        "ip",
        metavar="IP",
        type=str,
        help="The IP address that the NetDimm is configured on.",
    )
    dump_parser.add_argument(
        "file",
        metavar="FILE",
        type=str,
        help="The file you want to dump data to.",
    )
    dump_parser.add_argument(
        "address",
        metavar="ADDR",
        type=str,
        help="The hex address of memory that you would like to dump from.",
    )
    dump_parser.add_argument(
        "size",
        metavar="SIZE",
        type=int,
        help="The size in bytes you want to read.",
    )

    load_parser = subparsers.add_parser(
        'load',
        help='Load data to a memory location.',
        description='Load data to a memory location.',
    )
    load_parser.add_argument(
        "ip",
        metavar="IP",
        type=str,
        help="The IP address that the NetDimm is configured on.",
    )
    load_parser.add_argument(
        "file",
        metavar="FILE",
        type=str,
        help="The file you want to load data to.",
    )
    load_parser.add_argument(
        "address",
        metavar="ADDR",
        type=str,
        help="The hex address of memory that you would like to load to.",
    )

    args = parser.parse_args()
    netdimm = NetDimm(args.ip)

    if args.action == "peek":
        if args.size == 1:
            data = netdimm.peek(int(args.address, 16),
                                PeekPokeTypeEnum.TYPE_BYTE) & 0xFF
        elif args.size == 2:
            data = netdimm.peek(int(args.address, 16),
                                PeekPokeTypeEnum.TYPE_SHORT) & 0xFFFF
        elif args.size == 4:
            data = netdimm.peek(int(args.address, 16),
                                PeekPokeTypeEnum.TYPE_LONG) & 0xFFFFFFFF
        else:
            raise Exception(f"Invalid size selection {args.size}!")

        hexdata = hex(data)[2:]
        while len(hexdata) < (2 * args.size):
            hexdata = "0" + hexdata
        print(hexdata)

    elif args.action == "poke":
        if args.size == 1:
            netdimm.poke(int(args.address, 16), PeekPokeTypeEnum.TYPE_BYTE,
                         int(args.data, 16) & 0xFF)
        elif args.size == 2:
            netdimm.poke(int(args.address, 16), PeekPokeTypeEnum.TYPE_SHORT,
                         int(args.data, 16) & 0xFFFF)
        elif args.size == 4:
            netdimm.poke(int(args.address, 16), PeekPokeTypeEnum.TYPE_LONG,
                         int(args.data, 16) & 0xFFFFFFFF)
        else:
            raise Exception(f"Invalid size selection {args.size}!")

    elif args.action == "dump":
        with open(args.file, "wb") as bfp:
            for i in range(args.size):
                data = netdimm.peek(
                    int(args.address, 16) + i,
                    PeekPokeTypeEnum.TYPE_BYTE) & 0xFF
                bfp.write(struct.pack("B", data))
        print(f"Dumped {args.size} bytes to {args.file}")

    elif args.action == "load":
        with open(args.file, "rb") as bfp:
            for amount, b in enumerate(bfp.read()):
                netdimm.poke(
                    int(args.address, 16) + amount, PeekPokeTypeEnum.TYPE_BYTE,
                    b)
        print(f"Loaded {amount} bytes from {args.file}")

    return 0
Example #2
0
def write_scratch2_register(netdimm: NetDimm, value: int) -> None:
    with netdimm.connection():
        netdimm.poke(SCRATCH2_REGISTER, PeekPokeTypeEnum.TYPE_LONG, value)
Example #3
0
def write_send_status_register(netdimm: NetDimm, value: int) -> None:
    with netdimm.connection():
        netdimm.poke(SEND_STATUS_REGISTER, PeekPokeTypeEnum.TYPE_LONG,
                     checksum_stamp(value, SEND_STATUS_REGISTER_SEED))
Example #4
0
def send_packet(netdimm: NetDimm, data: bytes) -> bool:
    length = len(data)
    if length > MAX_PACKET_LENGTH:
        raise Exception("Packet is too long to send!")

    with netdimm.connection():
        start = time.time()
        sent_length = False
        while True:
            if time.time() - start > MAX_READ_TIMEOUT:
                # Failed to request a new packet send in time.
                return False

            # First, attempt to see if there is any existing transfer in progress.
            status = read_recv_status_register(netdimm)
            if status is None:
                return False

            # Now, grab the length of the available packet.
            newlength = (status >> 12) & 0xFFF
            if newlength == 0:
                # Ready to start transferring!
                write_recv_status_register(netdimm, (length << 12) & 0xFFF000)
                sent_length = True
            elif sent_length is False or newlength != length:
                # Cancel old transfer.
                write_recv_status_register(netdimm, 0)
                sent_length = False
            elif newlength == length:
                # Ready to send data.
                break
            else:
                # Shouldn't be possible.
                raise Exception("Logic error!")

        # Now set the current transfer location. This can be rewound by the target
        # if it failed to receive all of the data.
        location = 0
        while True:
            while location < length:
                # Sum up the next amount of data, up to 3 bytes.
                chunk: int = ((((location // 3) + 1) << 24) & 0xFF000000)

                for shift in [16, 8, 0]:
                    if location < length:
                        chunk |= (data[location] & 0xFF) << shift
                        location += 1
                    else:
                        break

                # Send it.
                netdimm.poke(DATA_REGISTER, PeekPokeTypeEnum.TYPE_LONG, chunk)

            # Now, see if the data transfer was successful.
            status = read_recv_status_register(netdimm)
            if status is None:
                # Give up, we can't read from the status.
                return False

            # See if the packet was sent successfully. If not, then our location will
            # be set to where the target needs data sent from.
            newlength = (status >> 12) & 0xFFF
            location = status & 0xFFF

            if newlength == 0 and location == 0:
                # We succeeded! Time to exit
                return True
            elif newlength != length:
                raise Exception("Logic error!")