Ejemplo n.º 1
0
uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t err_code;
    uint32_t total_image_size = p_packet->params.init_packet.total_image_size;
    dfu_update_status_t update_status;

    switch (m_dfu_state)
    {
        case DFU_STATE_IDLE:
        case DFU_STATE_RDY:
        case DFU_STATE_RX_DATA_PKT:
            m_dfu_state = DFU_STATE_RX_INIT_PKT;
            /* fall-through */

        case DFU_STATE_RX_INIT_PKT:
            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }

            // Reset the number of data received and the original m_storage_handle_app's start address.
            m_data_received = 0;
            m_storage_handle_app.block_id   = CODE_REGION_1_START;

            // Prepare the flash buffer for the upcoming image.
            if (total_image_size > DFU_IMAGE_MAX_SIZE_BANKED)
            {
                update_status.status_code = DFU_UPDATE_AP_INVALIDATED;
                bootloader_dfu_update_process(update_status);
                err_code = pstorage_raw_clear(&m_storage_handle_app, DFU_IMAGE_MAX_SIZE_FULL);
                m_active_bank = NEW_IMAGE_BANK_0;
            }
            else if ((total_image_size < DFU_IMAGE_MAX_SIZE_BANKED) && (total_image_size != 0))
            {
                err_code = pstorage_raw_clear(&m_storage_handle_swap, DFU_IMAGE_MAX_SIZE_BANKED);
                m_active_bank = NEW_IMAGE_BANK_1;
            }
            else
            {
                // do nothing
            }

            break;

        default:
            // Either the start packet was not received or dfu_init function was not called before.
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
Ejemplo n.º 2
0
uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t err_code = NRF_SUCCESS;
    uint32_t length;

    switch (m_dfu_state)
    {
        case DFU_STATE_RDY:
            m_dfu_state = DFU_STATE_RX_INIT_PKT;
            // When receiving init packet in state ready just update and fall through this case.         

        case DFU_STATE_RX_INIT_PKT:
            // DFU initialization has been done and a start packet has been received.
            if (IMAGE_WRITE_IN_PROGRESS())
            {
                // Image write is already in progress. Cannot handle an init packet now.
                return NRF_ERROR_INVALID_STATE;
            }

            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }

            length = p_packet->params.data_packet.packet_length * sizeof(uint32_t);
            if ((m_init_packet_length + length) > sizeof(m_init_packet))
            {
                return NRF_ERROR_INVALID_LENGTH;
            }

            memcpy(&m_init_packet[m_init_packet_length],
                   &p_packet->params.data_packet.p_data_packet[0],
                   length);
            m_init_packet_length += length;
            break;

        default:
            // Either the start packet was not received or dfu_init function was not called before.
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
uint32_t dfu_image_validate()
{
    uint32_t err_code;
    uint16_t received_crc;    
    
    switch (m_dfu_state)
    {
        case DFU_STATE_RX_DATA_PKT:
            m_dfu_state = DFU_STATE_VALIDATE;
            
            // Check if the application image write has finished.
            if (m_app_data_received != m_image_size)
            {
                // Image not yet fully transfered by the peer or the peer has attempted to write
                // too much data. Hence the validation should fail.
                err_code = NRF_ERROR_INVALID_STATE;
            }
            else
            {                        
                // Valid peer activity detected. Hence restart the DFU timer.
                err_code = dfu_timer_restart();
                if (err_code == NRF_SUCCESS)
                {                    
                    // calculate CRC from DFU_BANK_1_REGION_START to mp_app_write_address.
                    m_image_crc  = crc16_compute((uint8_t*)DFU_BANK_1_REGION_START, 
                                                 m_image_size, 
                                                 NULL);
                    received_crc = uint16_decode((uint8_t*)&m_init_packet[0]);
                    
                    if ((m_init_packet_length != 0) && (m_image_crc != received_crc))
                    {
                        return NRF_ERROR_INVALID_DATA;
                    }                    
                    
                    m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE;                                                                                
                }
            }
            break;
            
        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;              
    }
    
    return err_code;        
}
Ejemplo n.º 4
0
uint32_t dfu_image_validate(uint16_t crc_seed)
{
    uint32_t err_code;

    switch (m_dfu_state)
    {
        case DFU_STATE_RX_DATA_PKT:
            m_dfu_state = DFU_STATE_VALIDATE;

            // Check if the application image write has finished.
            if (m_data_received != m_image_size)
            {
                // Image not yet fully transfered by the peer or the peer has attempted to write
                // too much data. Hence the validation should fail.
                err_code = NRF_ERROR_INVALID_STATE;
            }
            else
            {
                // Valid peer activity detected. Hence restart the DFU timer.
                err_code = dfu_timer_restart();
                if (err_code == NRF_SUCCESS)
                {
                    if(crc_crc16_update(crc_seed, (uint32_t*)dfu_storage_start_address_get(), m_image_size) == 0)
                    {
                        m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE;
                        err_code = NRF_SUCCESS;
                    }
                    else
                    {
                        err_code = NRF_ERROR_INTERNAL;
                    }
                }
            }
            break;

        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
uint32_t dfu_image_validate()
{
    uint32_t err_code;

    switch (m_dfu_state)
    {
        case DFU_STATE_RX_DATA_PKT:
            // Check if the application image write has finished.
            if (m_data_received != m_image_size)
            {
                // Image not yet fully transfered by the peer or the peer has attempted to write
                // too much data. Hence the validation should fail.
                err_code = NRF_ERROR_INVALID_STATE;
            }
            else
            {
                m_dfu_state = DFU_STATE_VALIDATE;

                // Valid peer activity detected. Hence restart the DFU timer.
                err_code = dfu_timer_restart();
                if (err_code == NRF_SUCCESS)
                {
                	if(IS_UPDATING_BL(m_start_packet))
                	{
                		m_image_size = m_image_size - ((uint32_t)(&__end_protected_data) - (uint32_t)(&__start_protected_data));
                	}
                    err_code = dfu_init_postvalidate((uint8_t *)mp_storage_handle_active->block_id,
                                                     m_image_size);
                    VERIFY_SUCCESS(err_code);

                    m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE;
                }
            }
            break;

        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t err_code;
    uint32_t i;

    switch (m_dfu_state)
    {
        case DFU_STATE_RDY:
            m_dfu_state = DFU_STATE_RX_INIT_PKT;
            /* fall-through */         
        
        case DFU_STATE_RX_INIT_PKT:
            // DFU initialization has been done and a start packet has been received.
            if (IMAGE_WRITE_IN_PROGRESS())
            {
                // Image write is already in progress. Cannot handle an init packet now.
                return NRF_ERROR_INVALID_STATE;
            }
                    
            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }
            
            for (i = 0; i < p_packet->packet_length; i++)
            {
                m_init_packet[m_init_packet_length++] = p_packet->p_data_packet[i];
            }            
            break;
            
        default:
            // Either the start packet was not received or dfu_init function was not called before.
            err_code = NRF_ERROR_INVALID_STATE;        
            break;            
    }
    
    return err_code;       
}
uint32_t dfu_image_size_set(uint32_t image_size)
{
    uint32_t err_code;
    
    if (image_size > m_new_app_max_size)
    {
        return NRF_ERROR_DATA_SIZE;
    }

    if ((image_size & (sizeof(uint32_t) - 1)) != 0)
    {
        // Image_size is not a multiple of 4 (word size).
        return NRF_ERROR_NOT_SUPPORTED;
    }
    
    switch (m_dfu_state)
    {
        case DFU_STATE_IDLE:    
            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }        
            
            m_image_size = image_size;
            m_dfu_state  = DFU_STATE_RDY;    
            break;
            
        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }
    
    return err_code;    
}
Ejemplo n.º 8
0
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t   data_length;
    uint32_t   err_code;
    uint32_t * p_data;

    if (p_packet == NULL)
    {
        return NRF_ERROR_NULL;
    }

    // Check pointer alignment.
    if (!is_word_aligned(p_packet->params.data_packet.p_data_packet))
    {
        // The p_data_packet is not word aligned address.
        return NRF_ERROR_INVALID_ADDR;
    }

    switch (m_dfu_state)
    {
        case DFU_STATE_RDY:
        case DFU_STATE_RX_INIT_PKT:
            return NRF_ERROR_INVALID_STATE;

        case DFU_STATE_RX_DATA_PKT:
            data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t);

            if ((m_data_received + data_length) > m_image_size)
            {
                // The caller is trying to write more bytes into the flash than the size provided to
                // the dfu_image_size_set function. This is treated as a serious error condition and
                // an unrecoverable one. Hence point the variable mp_app_write_address to the top of
                // the flash area. This will ensure that all future application data packet writes
                // will be blocked because of the above check.
                m_data_received = 0xFFFFFFFF;

                return NRF_ERROR_DATA_SIZE;
            }

            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }

            p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet;

            err_code = pstorage_store(mp_storage_handle_active,
                                          (uint8_t *)p_data,
                                          data_length,
                                          m_data_received);
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }

            m_data_received += data_length;

            if (m_data_received != m_image_size)
            {
                // The entire image is not received yet. More data is expected.
                err_code = NRF_ERROR_INVALID_LENGTH;
            }
            else
            {
                // The entire image has been received. Return NRF_SUCCESS.
                err_code = NRF_SUCCESS;
            }
            break;

        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
Ejemplo n.º 9
0
uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t err_code;

    m_start_packet = *(p_packet->params.start_packet);

    // Check that the requested update procedure is supported.
    // Currently the following combinations are allowed:
    // - Application
    // - SoftDevice
    // - Bootloader
    // - SoftDevice with Bootloader
    if (IS_UPDATING_APP(m_start_packet) && 
        (IS_UPDATING_SD(m_start_packet) || IS_UPDATING_BL(m_start_packet)))
    {
        // App update is only supported independently.
        return NRF_ERROR_NOT_SUPPORTED;
    }

    if (!(IS_WORD_SIZED(m_start_packet.sd_image_size) &&
          IS_WORD_SIZED(m_start_packet.bl_image_size) &&
          IS_WORD_SIZED(m_start_packet.app_image_size)))
    {
        // Image_sizes are not a multiple of 4 (word size).
        return NRF_ERROR_NOT_SUPPORTED;
    }

    m_image_size = m_start_packet.sd_image_size + m_start_packet.bl_image_size +
                   m_start_packet.app_image_size;
    
    if (m_start_packet.bl_image_size > DFU_BL_IMAGE_MAX_SIZE)
    {
        return NRF_ERROR_DATA_SIZE;
    }

    if (m_image_size > (DFU_IMAGE_MAX_SIZE_FULL))
    {
        return NRF_ERROR_DATA_SIZE;
    }
    m_functions.prepare  = dfu_prepare_func_app_erase;
    m_functions.cleared  = dfu_cleared_func_app;
    
    if (IS_UPDATING_SD(m_start_packet))
    {
        m_functions.activate = dfu_activate_sd;
    }
    else if (IS_UPDATING_BL(m_start_packet))
    {
        m_functions.activate = dfu_activate_bl;
    }
    else
    {
        m_functions.activate = dfu_activate_app;
    }

    switch (m_dfu_state)
    {
        case DFU_STATE_IDLE:
            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }
            m_functions.prepare(m_image_size);

            break;

        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
Ejemplo n.º 10
0
uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t err_code = NRF_SUCCESS;

    m_start_packet = p_packet->params.start_packet;

    // Check that the requested update procedure is supported.
    // Currently the following combinations are allowed:
    // - Application
    // - SoftDevice
    // - Bootloader
    // - SoftDevice with Bootloader
    if (IS_UPDATING_APP() && //lint !e655 suppress lint warning 655: bit-wise operations
        (IS_UPDATING_SD() || //lint !e655 suppress Lint Warning 655: Bit-wise operations
         IS_UPDATING_BL() || //lint !e655 suppress lint warning 655: bit-wise operations
         ((m_start_packet.app_image_size & (sizeof(uint32_t) - 1)) != 0)))
    {
        // Image_size is not a multiple of 4 (word size).
        return NRF_ERROR_NOT_SUPPORTED;
    }

    if (IS_UPDATING_SD() && //lint !e655 suppress lint warning 655: bit-wise operations
        ((m_start_packet.sd_image_size & (sizeof(uint32_t) - 1)) != 0))
    {
        // Image_size is not a multiple of 4 (word size).
        return NRF_ERROR_NOT_SUPPORTED;
    }

    if (IS_UPDATING_BL() && //lint !e655 suppress lint warning 655: bit-wise operations
        ((m_start_packet.bl_image_size & (sizeof(uint32_t) - 1)) != 0))
    {
        // Image_size is not a multiple of 4 (word size).
        return NRF_ERROR_NOT_SUPPORTED;
    }

    m_image_size =  m_start_packet.sd_image_size    +
                    m_start_packet.bl_image_size    +
                    m_start_packet.app_image_size   +
                    m_start_packet.info_bytes_size;

    if (IS_UPDATING_BL() && m_start_packet.bl_image_size > DFU_BL_IMAGE_MAX_SIZE)//lint !e655 suppress Lint Warning 655: Bit-wise operations
    {
        return NRF_ERROR_DATA_SIZE;
    }
    else if (m_image_size > DFU_IMAGE_MAX_SIZE_FULL)
    {
        return NRF_ERROR_DATA_SIZE;
    }
    else
    {
        // Do nothing.
    }

    // If new softdevice size is greater than the code region 1 boundary
    if (IS_UPDATING_SD() && m_start_packet.sd_image_size > (CODE_REGION_1_START - SOFTDEVICE_REGION_START))//lint !e655 suppress Lint Warning 655: Bit-wise operations
    {
        //calculate storage starting offset.
        uint32_t storage_starting_offset;
        storage_starting_offset       = m_start_packet.sd_image_size - (CODE_REGION_1_START - SOFTDEVICE_REGION_START);
        storage_starting_offset       = CODE_REGION_1_START + storage_starting_offset;
        if (storage_starting_offset & ~(NRF_FICR->CODEPAGESIZE - 1))
        {
            storage_starting_offset &= ~(NRF_FICR->CODEPAGESIZE - 1);
            storage_starting_offset += NRF_FICR->CODEPAGESIZE;
        }

        m_storage_handle_app.block_id = storage_starting_offset;
    }

    switch (m_dfu_state)
    {
        case DFU_STATE_RX_INIT_PKT:
            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }

            m_dfu_state  = DFU_STATE_RDY;
            //break; fallthrough
        case DFU_STATE_RDY:
            break;

        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet)
{
    uint32_t   data_length;
    uint32_t   err_code;
    uint32_t * p_data;

    VERIFY_PARAM_NOT_NULL(p_packet);

    // Check pointer alignment.
    if (!is_word_aligned(p_packet->params.data_packet.p_data_packet))
    {
        // The p_data_packet is not word aligned address.
        return NRF_ERROR_INVALID_ADDR;
    }

    switch (m_dfu_state)
    {
        case DFU_STATE_RDY:
        case DFU_STATE_RX_INIT_PKT:
            return NRF_ERROR_INVALID_STATE;

        case DFU_STATE_RX_DATA_PKT:
            data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t);

            if ((m_data_received + data_length) > m_image_size)
            {
                // The caller is trying to write more bytes into the flash than the size provided to
                // the dfu_image_size_set function. This is treated as a serious error condition and
                // an unrecoverable one. Hence point the variable mp_app_write_address to the top of
                // the flash area. This will ensure that all future application data packet writes
                // will be blocked because of the above check.
                m_data_received = 0xFFFFFFFF;

                return NRF_ERROR_DATA_SIZE;
            }

            // Valid peer activity detected. Hence restart the DFU timer.
            err_code = dfu_timer_restart();
            VERIFY_SUCCESS(err_code);

            p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet;

            // Do AES Decrption.
            dfu_aes_128_ofb_decrypt(p_data, data_length/sizeof(uint32_t), m_data_received);

            // Check the protected data before copying it and make sure its retain or update the data.
            uint32_t bootloader_position = m_data_received - m_start_packet.sd_image_size;
    	    for (int w = 0; w < data_length/sizeof(uint32_t); w++)
    	    {
    			bootloader_position = bootloader_position + 4;
    			if(m_start_packet.bl_image_size > 0 && (m_data_received > m_start_packet.sd_image_size) && (bootloader_position >= ((uint32_t)(&__start_protected_data) - m_uicr_bootloader_start_address)))
    			{
    				if(p_data[w] == 0x00000000)
    				{
    					p_data[w] = 0xFFFFFFFF;
    				}
    				else if(p_data[w] == 0xFFFFFFFF)
    				p_data[w] = (uint32_t)(*((uint32_t *)(bootloader_position - 4 + m_uicr_bootloader_start_address)));
    			}
    	    }
            err_code = pstorage_store(mp_storage_handle_active,
                                          (uint8_t *)p_data,
                                          data_length,
                                          m_data_received);
            VERIFY_SUCCESS(err_code);

            m_data_received += data_length;

            if (m_data_received != m_image_size)
            {
                // The entire image is not received yet. More data is expected.
                err_code = NRF_ERROR_INVALID_LENGTH;
            }
            else
            {
                // The entire image has been received. Return NRF_SUCCESS.
                err_code = NRF_SUCCESS;
            }
            break;

        default:
            err_code = NRF_ERROR_INVALID_STATE;
            break;
    }

    return err_code;
}