Beispiel #1
0
uint32_t nrf_dfu_continue(uint32_t * p_enter_dfu_mode)
{
    uint32_t            ret_val;
    nrf_dfu_bank_t    * p_bank;
    uint32_t            src_addr = CODE_REGION_1_START;

    NRF_LOG_INFO("Enter nrf_dfu_continue\r\n");

    if (s_dfu_settings.bank_layout == NRF_DFU_BANK_LAYOUT_SINGLE )
    {
        p_bank = &s_dfu_settings.bank_0;
    }
    else if(s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_0)
    {
        p_bank = &s_dfu_settings.bank_0;
    }
    else
    {
        p_bank = &s_dfu_settings.bank_1;
        src_addr += align_to_page(s_dfu_settings.bank_0.image_size, CODE_PAGE_SIZE);
    }

    ret_val = nrf_dfu_continue_bank(p_bank, src_addr, p_enter_dfu_mode);
    return ret_val;
}
Beispiel #2
0
static int fatelf_replace(const char *out, const char *fname,
                          const char *newobj)
{
    const int fd = xopen(fname, O_RDONLY, 0755);
    const int newfd = xopen(newobj, O_RDONLY, 0755);
    FATELF_header *header = xread_fatelf_header(fname, fd);
    const int idx = xfind_fatelf_record_by_elf(newobj, newfd, fname, header);
    const int outfd = xopen(out, O_WRONLY | O_CREAT | O_TRUNC, 0755);
    uint64_t offset = FATELF_DISK_FORMAT_SIZE(((int)header->num_records));
    int i;

    unlink_on_xfail = out;

    // pad out some bytes for the header we'll write at the end...
    xwrite_zeros(out, outfd, (size_t) offset);

    for (i = 0; i < ((int) header->num_records); i++)
    {
        const uint64_t binary_offset = align_to_page(offset);
        FATELF_record *rec = &header->records[i];

        // append this binary to the final file, padded to page alignment.
        xwrite_zeros(out, outfd, (size_t) (binary_offset - offset));

        if (i == idx)  // the thing we're replacing...
            rec->size = xcopyfile(newobj, newfd, out, outfd);
        else
            xcopyfile_range(fname, fd, out, outfd, binary_offset, rec->size);

        rec->offset = binary_offset;
        offset = binary_offset + rec->size;
    } // for

    // Write the actual FatELF header now...
    xwrite_fatelf_header(out, outfd, header);

    xappend_junk(fname, fd, out, outfd);

    xclose(out, outfd);
    xclose(newobj, newfd);
    xclose(fname, fd);
    free(header);

    unlink_on_xfail = NULL;

    return 0;  // success.
} // fatelf_replace
Beispiel #3
0
uint32_t nrf_dfu_find_cache(uint32_t size_req, bool dual_bank_only, uint32_t * p_address)
{
    // TODO: Prevalidate p_address and p_bank

    uint32_t free_size =  DFU_REGION_TOTAL_SIZE - DFU_APP_DATA_RESERVED;
    nrf_dfu_bank_t * p_bank;

    NRF_LOG_INFO("Enter nrf_dfu_find_cache\r\n");

    // Simple check if size requirement can me met
    if(free_size < size_req)
    {
        NRF_LOG_INFO("No way to fit the new firmware on device\r\n");
        return NRF_ERROR_NO_MEM;
    }

    NRF_LOG_INFO("Bank content\r\n");
    NRF_LOG_INFO("Bank type: %d\r\n", s_dfu_settings.bank_layout);
    NRF_LOG_INFO("Bank 0 code: 0x%02x: Size: %d\r\n", s_dfu_settings.bank_0.bank_code, s_dfu_settings.bank_0.image_size);
    NRF_LOG_INFO("Bank 1 code: 0x%02x: Size: %d\r\n", s_dfu_settings.bank_1.bank_code, s_dfu_settings.bank_1.image_size);

    // Setting bank_0 as candidate
    p_bank = &s_dfu_settings.bank_0;

    // Setting candidate address
    (*p_address) = MAIN_APPLICATION_START_ADDR;

    // Calculate free size
    if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP)
    {
        // Valid app present.

        NRF_LOG_INFO("free_size before bank select: %d\r\n", free_size);

        free_size -= align_to_page(p_bank->image_size, CODE_PAGE_SIZE);

        NRF_LOG_INFO("free_size: %d, size_req: %d\r\n", free_size, size_req);

        // Check if we can fit the new in the free space or if removal of old app is required.
        if(size_req > free_size)
        {
            // Not enough room in free space (bank_1)
            if ((dual_bank_only))
            {
                NRF_LOG_INFO("Failure: dual bank restriction\r\n");
                return NRF_ERROR_NO_MEM;
            }

            // Can only support single bank update, clearing old app.
            s_dfu_settings.bank_layout = NRF_DFU_BANK_LAYOUT_SINGLE;
            s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
            p_bank = &s_dfu_settings.bank_0;
            NRF_LOG_INFO("Enforcing single bank\r\n");
        }
        else
        {
            // Room in bank_1 for update
            // Ensure we are using dual bank layout
            s_dfu_settings.bank_layout = NRF_DFU_BANK_LAYOUT_DUAL;
            s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1;
            p_bank = &s_dfu_settings.bank_1;
            // Set to first free page boundry after previous app
            (*p_address) += align_to_page(s_dfu_settings.bank_0.image_size, CODE_PAGE_SIZE);
            NRF_LOG_INFO("Using second bank\r\n");
        }
    }
    else
    {
        // No valid app present. Promoting dual bank.
        s_dfu_settings.bank_layout  = NRF_DFU_BANK_LAYOUT_DUAL;
        s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;

        p_bank = &s_dfu_settings.bank_0;
        NRF_LOG_INFO("No previous, using bank 0\r\n");
    }

    // Set the bank-code to invalid, and reset size/CRC
    memset(p_bank, 0, sizeof(nrf_dfu_bank_t));

    // Store the Firmware size in the bank for continuations
    p_bank->image_size = size_req;
    return NRF_SUCCESS;
}
Beispiel #4
0
/** @brief Function to execute the continuation of a SoftDevice update.
 *
 * @param[in]       src_addr            Source address of the SoftDevice to copy from.
 * @param[in]       p_bank              Pointer to the bank where the SoftDevice resides.
 *
 * @retval NRF_SUCCESS Continuation was successful.
 * @retval NRF_ERROR_INVALID_LENGTH Invalid len
 * @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
 * @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
 * @retval NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
 * @retval NRF_ERROR_NULL If the content of the memory blocks differs after copying.
 */
static uint32_t nrf_dfu_sd_continue_impl(uint32_t             src_addr,
                                         nrf_dfu_bank_t     * p_bank)
{
    uint32_t   ret_val      = NRF_SUCCESS;
    uint32_t   target_addr  = SOFTDEVICE_REGION_START + s_dfu_settings.write_offset;
    uint32_t   length_left  = align_to_page(s_dfu_settings.sd_size - s_dfu_settings.write_offset, CODE_PAGE_SIZE);
    uint32_t   split_size   = align_to_page(length_left / 4, CODE_PAGE_SIZE);

    NRF_LOG_INFO("Enter nrf_bootloader_dfu_sd_continue\r\n");

    // This can be a continuation due to a power failure
    src_addr += s_dfu_settings.write_offset;

    if (s_dfu_settings.sd_size != 0 && s_dfu_settings.write_offset == s_dfu_settings.sd_size)
    {
        NRF_LOG_INFO("SD already copied\r\n");
        return NRF_SUCCESS;
    }

    NRF_LOG_INFO("Updating SD. Old SD ver: 0x%04x\r\n", SD_FWID_GET(MBR_SIZE));

    do
    {
        NRF_LOG_INFO("Copying [0x%08x-0x%08x] to [0x%08x-0x%08x]: Len: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);

        // Copy a chunk of the SD. Size in words
        ret_val = nrf_dfu_mbr_copy_sd((uint32_t*)target_addr, (uint32_t*)src_addr, split_size);
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_INFO("Failed to copy SD: target: 0x%08x, src: 0x%08x, len: 0x%08x\r\n", target_addr, src_addr, split_size);
            return ret_val;
        }

        NRF_LOG_INFO("Finished copying [0x%08x-0x%08x] to [0x%08x-0x%08x]: Len: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);

        // Validate copy. Size in words
        ret_val = nrf_dfu_mbr_compare((uint32_t*)target_addr, (uint32_t*)src_addr, split_size);
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_INFO("Failed to Compare SD: target: 0x%08x, src: 0x%08x, len: 0x%08x\r\n", target_addr, src_addr, split_size);
            return ret_val;
        }

        NRF_LOG_INFO("Validated 0x%08x-0x%08x to 0x%08x-0x%08x: Size: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);

        target_addr += split_size;
        src_addr += split_size;

        if (split_size > length_left)
        {
            length_left = 0;
        }
        else
        {
            length_left -= split_size;
        }

        NRF_LOG_INFO("Finished with the SD update.\r\n");

        // Save the updated point of writes in case of power loss
        s_dfu_settings.write_offset = s_dfu_settings.sd_size - length_left;
        (void)nrf_dfu_settings_write(NULL);
    }
    while (length_left > 0);

    return ret_val;
}
Beispiel #5
0
/*-----------------------------------------------------------------------------
    DetourFunctionWithTrampoline
-----------------------------------------------------------------------------*/
int  DetourFunctionWithTrampoline(void* pOriginalFunction, void* pTargetFunction, void* pTrampoline)
{
    int          pagesize              = sysconf(_SC_PAGE_SIZE);
    void*        pOriginalFunctionPage = align_to_page(pOriginalFunction, pagesize);
    void*        pTrampolinePage       = align_to_page(pTrampoline, pagesize);
    void*        pOriginalFunctionPage2;
    void*        pTrampolinePage2;
    int          mprotect_error        = 0;
    unsigned int cpysize               = 0;
    hde32s       s;
    DetourInfo*  newInfo;

    while (cpysize < 5)
    {
        cpysize += hde32_disasm((void*)((unsigned int)pOriginalFunction + cpysize), &s);

        /* this would require reassembling at the trampoline location */
        if (s.flags & F_RELATIVE)
        {
            printf("ERROR: DetourFunctionWithTrampoline - found function with relative addressing. Bailing out :(\n");
            return -1;
        }
    }

    /* check if the end of the areas that are about to be overwritten lie in a different page */
    pOriginalFunctionPage2 = align_to_page((void*)((unsigned int)pOriginalFunction + sizeof(__uint32_t)), pagesize);
    pTrampolinePage2       = align_to_page((void*)((unsigned int)pTrampoline + cpysize - 1), pagesize);

    if (mprotect(pOriginalFunctionPage, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1
        || mprotect(pTrampolinePage, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
        mprotect_error = 1;

    /* if the end of the areas lie in a different page, mprotect needs to be called for that page too */
    if (!mprotect_error && pOriginalFunctionPage2 != pOriginalFunctionPage)
    {
        if (mprotect(pOriginalFunctionPage2, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
            mprotect_error = 1;
    }

    if (!mprotect_error && pTrampolinePage2 != pTrampolinePage)
    {
        if (mprotect(pTrampolinePage2, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
            mprotect_error = 1;
    }

    if (mprotect_error)
    {
        printf("ERROR: DetourFunctionWithTrampoline - Couldn't set memory access rights - errno: %d (%s)\n", errno, strerror(errno));
        return -1;
    }

    /* copy original code */
    memcpy(pTrampoline, pOriginalFunction, cpysize);
    /* assemble jmp instruction in the original function */
    *(unsigned char*)pOriginalFunction                      = 0xE9;
    /* addressing is relative to the program counter */
    *(__uint32_t*)((unsigned int)pOriginalFunction + 1)     = (__uint32_t)pTargetFunction - (__uint32_t)pOriginalFunction - 5;
    /* assemble jmp instruction in the trampoline */
    *(unsigned char*)((unsigned int)pTrampoline + cpysize)  = 0xE9;
    /* Still relative, jump over partial instructions (if any!) */
    *(__uint32_t*)((unsigned int)pTrampoline + cpysize + 1) = (__uint32_t)pOriginalFunction + cpysize - (__uint32_t)pTrampoline - 5 - cpysize;

    /* Add to detour list */
    CheckDetourList();

    /* Skip to the end of the list */
    for (newInfo = DetourList; newInfo->nextDetour != (void*)0; newInfo = (DetourInfo*)newInfo->nextDetour) ;

    /* Initialize */
    newInfo->nextDetour                                     = (DetourInfo*)malloc(sizeof(DetourInfo));
    newInfo                                                 = (DetourInfo*)newInfo->nextDetour;
    newInfo->nextDetour                                     = (void*)0;
    newInfo->pOriginalFunction                              = pOriginalFunction;
    newInfo->OriginalOffset                                 = 0;
    newInfo->pTrampoline                                    = pTrampoline;
    newInfo->TrampolineSize                                 = cpysize;

    return 0;
}
Beispiel #6
0
 bool is_small(SearchRange range) const {
     auto ps = get_page_size();
     auto b = align_to_page(reinterpret_cast<void const*>(page_->read_entry_at(range.begin)), ps);
     auto e = align_to_page(reinterpret_cast<void const*>(page_->read_entry_at(range.end)), ps);
     return b == e;
 }