Example #1
0
def flash_block(
    client: Client,
    filename: str,
    block: constants.PreparedBlockData,
    vin: str,
    flash_info: constants.FlashInfo,
    tuner_tag: str = "",
    callback=None,
):
    block_number = block.block_number
    data = block.block_encrypted_bytes
    block_identifier = flash_info.block_identifiers[block_number]

    logger.info(vin + ": Flashing block: " + str(block_number) +
                " from file " + filename)
    detailedLogger.info("Beginning block flashing process for block " +
                        str(block_number) + " : " + block.block_name +
                        " - with file named " + filename + " ...")

    if callback:
        callback(
            flasher_step="FLASHING",
            flasher_status="Erasing block " + str(block_number),
            flasher_progress=0,
        )

    # Erase Flash
    if block.should_erase:
        detailedLogger.info("Erasing block " + str(block_number) +
                            ", routine 0xFF00...")
        client.start_routine(Routine.EraseMemory,
                             data=bytes([0x1, block_identifier]))

    if callback:
        callback(
            flasher_step="FLASHING",
            flasher_status="Requesting Download for block " +
            str(block_number),
            flasher_progress=0,
        )

    detailedLogger.info("Requesting download for block " + str(block_number) +
                        " of length " +
                        str(flash_info.block_lengths[block_number]) +
                        " with block identifier: " + str(block_identifier))
    # Request Download
    dfi = udsoncan.DataFormatIdentifier(compression=block.compression_type,
                                        encryption=block.encryption_type)
    memloc = udsoncan.MemoryLocation(
        block_identifier,
        flash_info.block_lengths[block_number],
        address_format=8,
        memorysize_format=32,
    )
    client.request_download(memloc, dfi=dfi)

    if callback:
        callback(
            flasher_step="FLASHING",
            flasher_status="Transferring data... " + str(len(data)),
            flasher_progress=0,
        )

    detailedLogger.info("Transferring data... " + str(len(data)) +
                        " bytes to write")
    # Transfer Data
    counter = 1
    for block_base_address in range(
            0, len(data), flash_info.block_transfer_sizes[block_number]):
        if callback:
            progress = (100 * counter *
                        flash_info.block_transfer_sizes[block_number] /
                        len(data))
            callback(
                flasher_step="FLASHING",
                flasher_status="Transferring data... ",
                flasher_progress=str(progress),
            )

        block_end = min(
            len(data),
            block_base_address + flash_info.block_transfer_sizes[block_number],
        )
        client.transfer_data(counter, data[block_base_address:block_end])
        counter = next_counter(counter)

    if callback:
        callback(
            flasher_step="FLASHING",
            flasher_status="Exiting transfer... ",
            flasher_progress=100,
        )
    detailedLogger.info("Exiting transfer...")
    # Exit Transfer
    client.request_transfer_exit()

    if (len(tuner_tag) > 0) and (block_number > 1):
        detailedLogger.info("Sending tuner ASW magic number...")

        # Send Magic
        # In the case of a tuned CBOOT, send tune-specific magic bytes after this 3E to force-overwrite the CAL validity area.
        def tuner_payload(payload, tune_block_number=block_number):
            return payload + bytes(tuner_tag, "ascii") + bytes(
                [tune_block_number])

        with client.payload_override(tuner_payload):
            client.tester_present()
    else:
        client.tester_present()
    if callback:
        callback(
            flasher_step="FLASHING",
            flasher_status="Checksumming block... ",
            flasher_progress=100,
        )

    detailedLogger.info("Checksumming block " + str(block_number) +
                        " , routine 0x0202...")
    # Checksum
    checksum_data = bytearray([0x01, block_identifier, 0, 0x4])
    checksum_data.extend(block.uds_checksum)

    client.start_routine(0x0202, data=bytes(checksum_data))

    if callback:
        callback(
            flasher_step="FLASHING",
            flasher_status="Success flashing block... ",
            flasher_progress=100,
        )

    logger.info(vin + ": Success flashing block: " + str(block_number) +
                " with " + filename)
    detailedLogger.info("Successfully flashed " + filename + " to block " +
                        str(block_number))
Example #2
0
def patch_block(
    client: Client,
    filename: str,
    block: constants.PreparedBlockData,
    vin: str,
    flash_info: constants.FlashInfo,
    callback=None,
):
    block_number = block.block_number
    block_number = block_number - 5
    data = block.block_encrypted_bytes

    detailedLogger.info(
        "Erasing next block for PATCH process - erasing block " +
        str(block_number + 1) + " to patch " + str(block_number) +
        " routine 0xFF00...")
    # Erase Flash
    # Hardcoded to erase block 5 (CAL) prior to patch. This means we must ALWAYS flash CAL after patching.

    client.start_routine(Routine.EraseMemory, data=bytes([0x1, 5]))

    logger.info(vin + ": PATCHING block: " + str(block_number) + " with " +
                filename)
    detailedLogger.info("Requesting download to PATCH block " +
                        str(block_number) + " of length " +
                        str(flash_info.block_lengths[block_number]) +
                        " using file " + filename + " ...")
    # Request Download
    dfi = udsoncan.DataFormatIdentifier(compression=0x0, encryption=0xA)
    memloc = udsoncan.MemoryLocation(block_number,
                                     flash_info.block_lengths[block_number],
                                     memorysize_format=32)
    client.request_download(memloc, dfi=dfi)

    detailedLogger.info("Transferring PATCH data... " + str(len(data)) +
                        " bytes to write")

    # Transfer Data
    counter = 1
    transfer_address = 0
    while transfer_address < len(data):
        transfer_size = flash_info.patch_info.block_transfer_sizes_patch(
            block_number, transfer_address)
        block_end = min(len(data), transfer_address + transfer_size)
        transfer_data = data[transfer_address:block_end]
        if callback:
            progress = transfer_address * 100 / len(data)
            callback(
                flasher_step="PATCHING",
                flasher_status="Patching data... ",
                flasher_progress=str(progress),
            )
        success = False

        while not success:
            try:
                time.sleep(0.025)
                client.transfer_data(counter, transfer_data)
                success = True
                counter = next_counter(counter)
            except exceptions.NegativeResponseException:
                success = False
                counter = next_counter(counter)

        transfer_address += transfer_size
    detailedLogger.info("Exiting PATCH transfer...")
    # Exit Transfer
    client.request_transfer_exit()
    detailedLogger.info("PATCH successful.")
    logger.info(vin + ": PATCHED block: " + str(block_number) + " with " +
                filename)