Загрузка данных


#define MAGIC_M7_READY    0x4D37424CU  /* "M7BL" - Set by M7 to signal it has booted and cleared RAM */
#define MAGIC_UB_START    0x55424D37U  /* "UBM7" - Set by U-Boot to open a legitimate transfer session */

/* Function of sending firmware to M7 in fragments */
int imx_rproc_flash_firmware(struct udevice *dev, ulong src_image_addr, ulong image_size)
{
    struct imx_rproc *priv = dev_get_priv(dev);
    const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    
    /* CRITICAL: Ensure IMX95_M7_TCM_IPC_A55_BASE matches 0x20402000U (8 KB offset inside DTCM) */
    volatile struct rproc_update_ipc_a55 *ipc = (struct rproc_update_ipc_a55 *)IMX95_M7_TCM_IPC_A55_BASE;
    
    uint8_t *src_ptr = (uint8_t *)src_image_addr;
    uint32_t bytes_left = image_size;
    uint32_t chunk_len = 204800; /* 200 KB chunk size */
    uint32_t current_target_ddr = 0x80000000U;
    uint32_t timeout;
    
    printf("RPROC: Starting flash of %lu bytes to M7 via TCM...\n", image_size);
    
    /* ===================================================================== */
    /* TWO-WAY SAFE HANDSHAKE PHASE                                         */
    /* ===================================================================== */
    
    /* 1. Wait for M7 core to complete Cold Boot, wipe RAM, and set its ready token */
    printf("RPROC: Waiting for M7 Bootloader handshake (Looking for 0x%08X)...\n", MAGIC_M7_READY);
    timeout = 1000000; /* Timeout to protect U-Boot from locking up if M7 fails */
    while (ipc->magic_word != MAGIC_M7_READY)
    {
        udelay(1);
        if (--timeout == 0) {
            printf("RPROC: Error! Handshake timed out. M7 is not responding.\n");
            return -1;
        }
    }
    printf("RPROC: Handshake Phase 1 Success! M7 Bootloader is alive and ready.\n");

    /* 2. Overwrite the exact same field with U-Boot token to establish the session */
    ipc->magic_word = MAGIC_UB_START;
    printf("RPROC: Handshake Phase 2 Success! Session opened with token 0x%08X.\n", MAGIC_UB_START);

    /* ===================================================================== */
    /* DATA TRANSMISSION PHASE                                               */
    /* ===================================================================== */

    /* 3. Calculate full reference CRC32 of the source file using built-in U-Boot function */
    uint32_t total_expected_crc = crc32(0, src_ptr, image_size);
    printf("RPROC: Calculated reference image CRC32: 0x%08X\n", total_expected_crc);

    /* 4. Sequential chunk transmission loop */
    while (bytes_left > 0)
    {
        if (bytes_left < chunk_len) {
            chunk_len = bytes_left;
        }

        /* Runtime Protection: Verify M7 has not cleared the token due to internal faults */
        if (ipc->magic_word != MAGIC_UB_START) {
            printf("RPROC: Error! M7 broken session safety check during transmission.\n");
            return -1;
        }

        printf("RPROC: Sending chunk of %d bytes to DDR 0x%08X...\n", chunk_len, current_target_ddr);
        
        /* Copy data block directly into the now-isolated DTCM buffer area */
        memcpy((void *)ipc->buffer, src_ptr, chunk_len);

        /* Fill control and routing structures */
        ipc->chunk_size = chunk_len;
        ipc->target_ddr = current_target_ddr;
        
        /* Set busy state BEFORE command flag to prevent potential race conditions */
        ipc->status = STAT_BUSY;
        ipc->command = CMD_DATA_READY;
        
        /* Hardware Data Synchronization Barrier for ARMv8 (Cortex-A55) cache coherency */
        asm volatile("dsb sy" : : : "memory");

        /* Wait for chunk processing confirmation (ACK) from M7 with a 2-second timeout */
        timeout = 2000000; 
        while (ipc->command == CMD_DATA_READY)
        {
            udelay(1);
            if (--timeout == 0) {
                printf("RPROC: Error! M7 processing timeout at DDR 0x%08X\n", current_target_ddr);
                return -1;
            }
        }

        /* Evaluate processing response status */
        if (ipc->status != STAT_ACK) {
            printf("RPROC: Error! M7 rejected or failed chunk at DDR 0x%08X. Status: %d\n", 
                   current_target_ddr, ipc->status);
            return -1;
        }

        /* Shift memory and stream pointers */
        src_ptr += chunk_len;
        current_target_ddr += chunk_len;
        bytes_left -= chunk_len;
    }

    /* ===================================================================== */
    /* VERIFICATION AND FINALIZATION PHASE                                   */
    /* ===================================================================== */

    printf("RPROC: All chunks sent successfully. Verifying total CRC...\n");
    
    ipc->expected_crc = total_expected_crc;
    ipc->status = STAT_BUSY;
    ipc->command = CMD_VERIFY_CRC;
    
    asm volatile("dsb sy" : : : "memory");

    /* Wait for M7 to finish cumulative 4 MB CRC32 mathematical validation (5s max) */
    timeout = 5000000; 
    while (ipc->command == CMD_VERIFY_CRC)
    {
        udelay(1);
        if (--timeout == 0) {
            printf("RPROC: Error! CRC Verification timed out.\n");
            return -1;
        }
    }

    if (ipc->status == STAT_ACK) {
        printf("RPROC: SUCCESS! CRC matches. File is valid.\n");
        
        /* NOTE: Triggering the final Logical Machine clean reboot via SCMI/M33 
           should be executed right here to branch M7 execution into 0x80000000 cleanly */
        
        return 0;
    } else {
        printf("RPROC: CRC VERIFICATION FAILED! Firmware corrupted on M7 side.\n");
        return -1;
    }
}