Exemplo n.º 1
0
def receive_packet(netdimm: NetDimm) -> Optional[bytes]:
    with netdimm.connection():
        # First, attempt to grab the next packet available.
        status = read_send_status_register(netdimm)
        if status is None:
            return None

        # Now, grab the length of the available packet.
        length = (status >> 12) & 0xFFF
        if length == 0:
            return None

        # Now, see if the transfer was partially done, if so rewind it.
        loc = status & 0xFFF
        if loc > 0:
            write_send_status_register(netdimm, 0)

        # Now, grab and assemble the data itself.
        data: List[Optional[int]] = [None] * length
        tries: int = 0
        while any(d is None for d in data):
            chunk = netdimm.peek(DATA_REGISTER, PeekPokeTypeEnum.TYPE_LONG)
            if ((chunk & 0xFF000000) >> 24) in {0x00, 0xFF}:
                tries += 1
                if tries > MAX_EMPTY_READS:
                    # We need to figure out where we left off.
                    for loc, val in enumerate(data):
                        if val is None:
                            # We found a spot to resume from.
                            write_send_status_register(netdimm, loc & 0xFFF)
                            tries = 0
                            break
                    else:
                        # We should always find a spot to resume from or there's an issue,
                        # since in this case we should be done.
                        raise Exception("Logic error!")
            else:
                # Grab the location for this chunk, stick the data in the right spot.
                location = (((chunk >> 24) & 0xFF) - 1) * 3

                for off, shift in enumerate([16, 8, 0]):
                    actual = off + location
                    if actual < length:
                        data[actual] = (chunk >> shift) & 0xFF

        # Grab the actual return data.
        bytedata = bytes([d for d in data if d is not None])
        if len(bytedata) != length:
            raise Exception("Logic error!")

        # Acknowledge the data transfer completed.
        write_send_status_register(netdimm, length & 0xFFF)

        # Return the actual data!
        return bytedata
Exemplo n.º 2
0
def read_recv_status_register(netdimm: NetDimm) -> Optional[int]:
    with netdimm.connection():
        valid = False
        status: int = 0
        start = time.time()

        while not valid:
            status = 0
            while status == 0 or status == 0xFFFFFFFF and (
                    time.time() - start <= MAX_READ_TIMEOUT):
                status = netdimm.peek(RECV_STATUS_REGISTER,
                                      PeekPokeTypeEnum.TYPE_LONG)

            valid = checksum_valid(status, RECV_STATUS_REGISTER_SEED)
            if not valid and (time.time() - start > MAX_READ_TIMEOUT):
                return None

        return status
Exemplo n.º 3
0
def read_config_register(netdimm: NetDimm) -> Optional[int]:
    with netdimm.connection():
        valid = False
        config: int = 0
        start = time.time()

        while not valid:
            config = 0
            while config == 0 or config == 0xFFFFFFFF and (
                    time.time() - start <= MAX_READ_TIMEOUT):
                config = netdimm.peek(CONFIG_REGISTER,
                                      PeekPokeTypeEnum.TYPE_LONG)

            valid = checksum_valid(config, CONFIG_REGISTER_SEED)
            if not valid and (time.time() - start > MAX_READ_TIMEOUT):
                return None

        return config
Exemplo n.º 4
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
Exemplo n.º 5
0
def read_scratch2_register(netdimm: NetDimm) -> Optional[int]:
    with netdimm.connection():
        return netdimm.peek(SCRATCH2_REGISTER, PeekPokeTypeEnum.TYPE_LONG)