<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def boot(hostname, boot_port=consts.BOOT_PORT, scamp_binary=None, sark_struct=None, boot_delay=0.05, post_boot_delay=2.0, sv_overrides=dict(), **kwargs):
 """Boot a SpiNNaker machine of the given size. Parameters hostname : str Hostname or IP address of the SpiNNaker chip to use to boot the system. boot_port : int The port number to sent boot packets to. scamp_binary : filename or None Filename of the binary to boot the machine with or None to use the SC&MP binary bundled with Rig. sark_struct : filename or None The 'sark.struct' file which defines the datastructures or None to use the one bundled with Rig. boot_delay : float Number of seconds to pause between sending boot data packets. post_boot_delay : float Number of seconds to wait after sending last piece of boot data to give SC&MP time to re-initialise the Ethernet interface. Note that this does *not* wait for the system to fully boot. Values used to override the defaults in the 'sv' struct defined in the struct file. Notes ----- The constants `rig.machine_control.boot.spinX_boot_options` provide boot parameters for specific SpiNNaker board revisions, for example:: boot("board1", **spin3_boot_options) Will boot the Spin3 board connected with hostname "board1". Returns ------- {struct_name: :py:class:`~rig.machine_control.struct_file.Struct`} Layout of structs in memory. """

    # Get the boot data if not specified.
    scamp_binary = (scamp_binary if scamp_binary is not None else
                    pkg_resources.resource_filename("rig", "boot/scamp.boot"))
    sark_struct = (sark_struct if sark_struct is not None else
                   pkg_resources.resource_filename("rig", "boot/sark.struct"))
    with open(scamp_binary, "rb") as f:
        boot_data = f.read()

    # Read the struct file and modify the "sv" struct to contain the
    # configuration values and write this into the boot data.
    with open(sark_struct, "rb") as f:
        struct_data = f.read()
    structs = struct_file.read_struct_file(struct_data)
    sv = structs[b"sv"]
    sv_overrides.update(kwargs)  # Allow non-explicit keyword arguments for SV
    sv.update_default_values(**sv_overrides)
    sv.update_default_values(unix_time=int(time.time()),
                             boot_sig=int(time.time()),
                             root_chip=1)
    struct_packed = sv.pack()
    assert len(struct_packed) >= 128  # Otherwise shoving this data in is nasty

    buf = bytearray(boot_data)
    buf[BOOT_DATA_OFFSET:BOOT_DATA_OFFSET+BOOT_DATA_LENGTH] = \
        struct_packed[:BOOT_DATA_LENGTH]
    assert len(buf) < DTCM_SIZE  # Assert that we fit in DTCM
    boot_data = bytes(buf)

    # Create a socket to communicate with the board
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect((hostname, boot_port))

    # Transmit the boot data as a series of SDP packets.  First determine
    # how many blocks must be sent and transmit that, then transmit each
    # block.
    n_blocks = (len(buf) + BOOT_BYTE_SIZE - 1) // BOOT_BYTE_SIZE
    assert n_blocks <= BOOT_MAX_BLOCKS

    boot_packet(sock, BootCommand.start, arg3=n_blocks - 1)
    time.sleep(boot_delay)

    block = 0
    while len(boot_data) > 0:
        # Get the data to transmit
        data, boot_data = (boot_data[:BOOT_BYTE_SIZE],
                           boot_data[BOOT_BYTE_SIZE:])

        # Transmit, delay and increment the block count
        a1 = ((BOOT_WORD_SIZE - 1) << 8) | block
        boot_packet(sock, BootCommand.send_block, a1, data=data)
        time.sleep(boot_delay)
        block += 1

    # Send the END command
    boot_packet(sock, BootCommand.end, 1)

    # Close the socket and give time to boot
    sock.close()
    time.sleep(post_boot_delay)

    return structs