/* Changes the encryption level of the drive. If encrypt is true: encrypt drive, else decrypt */ uint8_t sd_change_encryption(uint8_t slot, bool encrypt, bool change_key, uint8_t *old_passwd, uint8_t *new_passwd) { sd_mmc_err_t err; uint32_t i, nb_blocks; encrypt_config_t *config_ptr = NULL; security_get_config(&config_ptr); if ((encrypt == config_ptr->encryption_level) && !change_key) return CTRL_GOOD; if (change_key) { sha2(old_passwd, MAX_PASS_LENGTH, old_hash_cipher_key, 0); sha2(new_passwd, MAX_PASS_LENGTH, new_hash_cipher_key, 0); } if (old_hash_cipher_key == new_hash_cipher_key) return CTRL_GOOD; do { err = sd_mmc_check(slot); if ((SD_MMC_ERR_NO_CARD != err) && (SD_MMC_INIT_ONGOING != err) && (SD_MMC_OK != err)) { while (SD_MMC_ERR_NO_CARD != sd_mmc_check(slot)) { } } } while (SD_MMC_OK != err); nb_blocks = sd_mmc_get_capacity(slot) * (1024 / SD_MMC_BLOCK_SIZE); for (i = 0; i < nb_blocks / SD_BLOCKS_PER_ACCESS; ++i) { if (SD_MMC_OK != sd_mmc_init_read_blocks(slot, i, SD_BLOCKS_PER_ACCESS)) return CTRL_FAIL; if (SD_MMC_OK != sd_mmc_start_read_blocks(src_buf, SD_BLOCKS_PER_ACCESS)) return CTRL_FAIL; if (SD_MMC_OK != sd_mmc_wait_end_of_read_blocks()) return CTRL_FAIL; aes_set_key(&AVR32_AES, (unsigned int *)old_hash_cipher_key); ram_aes_ram(change_key ? false : encrypt, SD_MMC_BLOCK_SIZE * SD_BLOCKS_PER_ACCESS / sizeof(unsigned int), (unsigned int *)src_buf, (unsigned int *)dest_buf); if (change_key) { aes_set_key(&AVR32_AES, (unsigned int *)new_hash_cipher_key); ram_aes_ram(true, SD_MMC_BLOCK_SIZE * SD_BLOCKS_PER_ACCESS / sizeof(unsigned int), (unsigned int *)dest_buf, (unsigned int *)src_buf); } if (SD_MMC_OK != sd_mmc_init_write_blocks(slot, i, SD_BLOCKS_PER_ACCESS)) return CTRL_FAIL; if (SD_MMC_OK != sd_mmc_start_write_blocks(src_buf, SD_BLOCKS_PER_ACCESS)) return CTRL_FAIL; if (SD_MMC_OK != sd_mmc_wait_end_of_write_blocks()) return CTRL_FAIL; } return CTRL_GOOD; }
Ctrl_status sd_mmc_usb_write_10(uint8_t slot, uint32_t addr, uint16_t nb_sector) { bool b_first_step = true; uint16_t nb_step; switch (sd_mmc_init_write_blocks(slot, addr, nb_sector)) { case SD_MMC_OK: break; case SD_MMC_ERR_NO_CARD: return CTRL_NO_PRESENT; default: return CTRL_FAIL; } // Pipeline the 2 transfer in order to speed-up the performances nb_step = nb_sector + 1; while (nb_step--) { if (!b_first_step) { // Skip first step // RAM -> MCI if (SD_MMC_OK != sd_mmc_start_write_blocks(((nb_step % 2) == 0) ? sector_buf_0 : sector_buf_1, 1)) { return CTRL_FAIL; } } if (nb_step) { // Skip last step // USB -> RAM if (!udi_msc_trans_block(false, ((nb_step % 2) == 0) ? sector_buf_1 : sector_buf_0, SD_MMC_BLOCK_SIZE, NULL)) { if (!b_first_step) { sd_mmc_wait_end_of_write_blocks(true); } return CTRL_FAIL; } } if (!b_first_step) { // Skip first step if (SD_MMC_OK != sd_mmc_wait_end_of_write_blocks(false)) { return CTRL_FAIL; } } else { b_first_step = false; } } return CTRL_GOOD; }
Ctrl_status sd_mmc_ram_2_mem(uint8_t slot, uint32_t addr, const void *ram) { switch (sd_mmc_init_write_blocks(slot, addr, 1)) { case SD_MMC_OK: break; case SD_MMC_ERR_NO_CARD: return CTRL_NO_PRESENT; default: return CTRL_FAIL; } if (SD_MMC_OK != sd_mmc_start_write_blocks(ram, 1)) { return CTRL_FAIL; } if (SD_MMC_OK != sd_mmc_wait_end_of_write_blocks(false)) { return CTRL_FAIL; } return CTRL_GOOD; }
/** * \brief Card R/W tests * * \param slot SD/MMC slot to test */ static void main_test_memory(uint8_t slot) { uint32_t last_blocks_addr, i, nb_trans; REDTIMESTAMP tick_start; uint32_t time_ms; // Compute the last address last_blocks_addr = sd_mmc_get_capacity(slot) * (1024 / SD_MMC_BLOCK_SIZE); if (last_blocks_addr < (TEST_MEM_START_OFFSET / 512lu)) { printf("[Memory is too small.]\n\r"); return; } last_blocks_addr -= (TEST_MEM_START_OFFSET / SD_MMC_BLOCK_SIZE); printf("Card R/W test:\n\r"); // Read the last block printf(" Read... "); tick_start = RedOsTimestamp(); if (SD_MMC_OK != sd_mmc_init_read_blocks(slot, last_blocks_addr, TEST_MEM_AREA_SIZE / SD_MMC_BLOCK_SIZE)) { printf("[FAIL]\n\r"); return; } for (nb_trans = 0; nb_trans < (TEST_MEM_AREA_SIZE / TEST_MEM_ACCESS_SIZE); nb_trans++) { if (SD_MMC_OK != sd_mmc_start_read_blocks(buf_test, TEST_MEM_ACCESS_SIZE / SD_MMC_BLOCK_SIZE)) { printf("[FAIL]\n\r"); return; } if (SD_MMC_OK != sd_mmc_wait_end_of_read_blocks(false)) { printf("[FAIL]\n\r"); return; } } time_ms = RedOsTimePassed(tick_start) / 1000U; if (time_ms) { // Valid time_ms printf(" %d KBps ", (int)(((TEST_MEM_AREA_SIZE * 1000lu) / 1024lu) / time_ms)); } printf("[OK]\n\r"); if (sd_mmc_is_write_protected(slot)) { printf("Card is write protected [WRITE TEST SKIPPED]\n\r"); return; } // Fill buffer with a pattern for (i = 0; i < (TEST_MEM_ACCESS_SIZE / sizeof(uint32_t)); i++) { ((uint32_t*)buf_test)[i] = TEST_FILL_VALUE_U32; } printf(" Write pattern... "); if (SD_MMC_OK != sd_mmc_init_write_blocks(slot, last_blocks_addr, TEST_MEM_AREA_SIZE / SD_MMC_BLOCK_SIZE)) { printf("[FAIL]\n\r"); return; } tick_start = RedOsTimestamp(); for (nb_trans = 0; nb_trans < (TEST_MEM_AREA_SIZE / TEST_MEM_ACCESS_SIZE); nb_trans++) { ((uint32_t*)buf_test)[0] = nb_trans; // Unique value for each area if (SD_MMC_OK != sd_mmc_start_write_blocks(buf_test, TEST_MEM_ACCESS_SIZE / SD_MMC_BLOCK_SIZE)) { printf("[FAIL]\n\r"); return; } if (SD_MMC_OK != sd_mmc_wait_end_of_write_blocks(false)) { printf("[FAIL]\n\r"); return; } } time_ms = RedOsTimePassed(tick_start) / 1000U; if (time_ms) { // Valid time_ms printf(" %d KBps ", (int)(((TEST_MEM_AREA_SIZE * 1000lu) / 1024lu) / time_ms)); } printf("[OK]\n\r"); printf(" Read and check pattern... "); if (SD_MMC_OK != sd_mmc_init_read_blocks(slot, last_blocks_addr, TEST_MEM_AREA_SIZE / SD_MMC_BLOCK_SIZE)) { printf("Read [FAIL]\n\r"); return; } for (nb_trans = 0; nb_trans < (TEST_MEM_AREA_SIZE / TEST_MEM_ACCESS_SIZE); nb_trans++) { // Clear buffer for (i = 0; i < (TEST_MEM_ACCESS_SIZE / sizeof(uint32_t)); i++) { ((uint32_t*)buf_test)[i] = 0xFFFFFFFF; } // Fill buffer if (SD_MMC_OK != sd_mmc_start_read_blocks(buf_test, TEST_MEM_ACCESS_SIZE / SD_MMC_BLOCK_SIZE)) { printf("Read [FAIL]\n\r"); return; } if (SD_MMC_OK != sd_mmc_wait_end_of_read_blocks(false)) { printf("Read [FAIL]\n\r"); return; } // Check the unique value of the area if (((uint32_t*)buf_test)[0] != nb_trans) { printf("Check [FAIL]\n\r"); return; } // Check buffer for (i = 1; i < (TEST_MEM_ACCESS_SIZE / sizeof(uint32_t)); i++) { if (((uint32_t*)buf_test)[i] != TEST_FILL_VALUE_U32) { printf("Check [FAIL]\n\r"); return; } } } printf("[OK]\n\r"); }
/** * \brief SD/MMC card read and write test. * * \param test Current test case. */ static void run_sd_mmc_rw_test(const struct test_case *test) { uint32_t i; uint32_t last_blocks_addr; uint16_t nb_block, nb_trans; bool split_tansfer = false; /* Compute the last address */ last_blocks_addr = sd_mmc_get_capacity(0) * (1024/SD_MMC_BLOCK_SIZE) - 50; test_assert_true(test, last_blocks_addr > NB_MULTI_BLOCKS, "Error: SD/MMC capacity."); last_blocks_addr -= NB_MULTI_BLOCKS; nb_block = 1; run_sd_mmc_rw_test_next: /* Read (save blocks) the last blocks */ test_assert_true(test, SD_MMC_OK == sd_mmc_init_read_blocks(0, last_blocks_addr, nb_block), "Error: SD/MMC initialize read sector(s)."); for (nb_trans = 0; nb_trans < (split_tansfer? nb_block : 1); nb_trans++) { test_assert_true(test, SD_MMC_OK == sd_mmc_start_read_blocks( &buf_save[nb_trans * SD_MMC_BLOCK_SIZE], split_tansfer? 1 : nb_block), "Error: SD/MMC start read sector(s)."); test_assert_true(test, SD_MMC_OK == sd_mmc_wait_end_of_read_blocks(false), "Error: SD/MMC wait end of read sector(s)."); } test_assert_true(test, !sd_mmc_is_write_protected(0), "Error: SD/MMC is write protected."); /* Fill buffer */ for (i = 0; i < (SD_MMC_BLOCK_SIZE * nb_block / sizeof(uint32_t)); i++) { ((uint32_t*)buf_test)[i] = TEST_FILL_VALUE_U32; } /* Write the last blocks */ test_assert_true(test, SD_MMC_OK == sd_mmc_init_write_blocks(0, last_blocks_addr, nb_block), "Error: SD/MMC initialize write sector(s)."); for (nb_trans = 0; nb_trans < (split_tansfer? nb_block : 1); nb_trans++) { test_assert_true(test, SD_MMC_OK == sd_mmc_start_write_blocks( &buf_test[nb_trans * SD_MMC_BLOCK_SIZE], split_tansfer? 1 : nb_block), "Error: SD/MMC start write sector(s)."); test_assert_true(test, SD_MMC_OK == sd_mmc_wait_end_of_write_blocks(false), "Error: SD/MMC wait end of write sector(s)."); } /* Clean buffer */ for (i = 0; i < (SD_MMC_BLOCK_SIZE * nb_block / sizeof(uint32_t)); i++) { ((uint32_t*)buf_test)[i] = 0xFFFFFFFF; } /* Read the last block */ test_assert_true(test, SD_MMC_OK == sd_mmc_init_read_blocks(0, last_blocks_addr, nb_block), "Error: SD/MMC initialize read sector(s)."); for (nb_trans = 0; nb_trans < (split_tansfer? nb_block : 1); nb_trans++) { test_assert_true(test, SD_MMC_OK == sd_mmc_start_read_blocks( &buf_test[nb_trans * SD_MMC_BLOCK_SIZE], split_tansfer? 1 : nb_block), "Error: SD/MMC start read sector(s)."); test_assert_true(test, SD_MMC_OK == sd_mmc_wait_end_of_read_blocks(false), "Error: SD/MMC wait end of read sector(s)."); } /* Check buffer */ for (i = 0; i < (SD_MMC_BLOCK_SIZE * nb_block / sizeof(uint32_t)); i++) { test_assert_true(test, ((uint32_t*)buf_test)[i] == TEST_FILL_VALUE_U32, "Error: SD/MMC verify write operation."); } /* Write (restore) the last block */ test_assert_true(test, SD_MMC_OK == sd_mmc_init_write_blocks(0, last_blocks_addr, nb_block), "Error: SD/MMC initialize write restore sector(s)."); for (nb_trans = 0; nb_trans < (split_tansfer? nb_block : 1); nb_trans++) { test_assert_true(test, SD_MMC_OK == sd_mmc_start_write_blocks( &buf_save[nb_trans * SD_MMC_BLOCK_SIZE], split_tansfer? 1 : nb_block), "Error: SD/MMC start write restore sector(s)."); test_assert_true(test, SD_MMC_OK == sd_mmc_wait_end_of_write_blocks(false), "Error: SD/MMC wait end of write restore sector(s)."); } /* Read (check restore) the last block */ test_assert_true(test, SD_MMC_OK == sd_mmc_init_read_blocks(0, last_blocks_addr, nb_block), "Error: SD/MMC initialize read sector(s)."); for (nb_trans = 0; nb_trans < (split_tansfer? nb_block : 1); nb_trans++) { test_assert_true(test, SD_MMC_OK == sd_mmc_start_read_blocks( &buf_test[nb_trans * SD_MMC_BLOCK_SIZE], split_tansfer? 1 : nb_block), "Error: SD/MMC start read sector(s)."); test_assert_true(test, SD_MMC_OK == sd_mmc_wait_end_of_read_blocks(false), "Error: SD/MMC wait end of read sector(s)."); } /* Check buffer restored */ for (i = 0; i < (SD_MMC_BLOCK_SIZE * nb_block / sizeof(uint32_t)); i++) { test_assert_true(test, ((uint32_t*)buf_test)[i] == ((uint32_t*)buf_save)[i], "Error: SD/MMC verify restore operation."); } if (nb_block == 1) { /* Launch second test */ nb_block = NB_MULTI_BLOCKS; goto run_sd_mmc_rw_test_next; } if (!split_tansfer) { /* Launch third test */ split_tansfer = true; goto run_sd_mmc_rw_test_next; } }
Ctrl_status sd_mmc_usb_write_10(uint8_t slot, uint32_t addr, uint16_t nb_sector) { bool b_first_step = true; uint16_t nb_step; #if defined(USE_ENCRYPTION) && !defined(FAKE_RW) aes_encrypt_ctx aes_ctx[1]; MD5_CTX md5_ctx; unsigned char IV[16]; #endif // USE_ENCRYPTION #ifdef CLEAR_ON_WRITE if (!sd_mmc_usb_check_sector(addr, nb_sector)) return CTRL_FAIL; #endif #ifndef FAKE_RW switch (sd_mmc_init_write_blocks(slot, addr, nb_sector)) { case SD_MMC_OK: break; case SD_MMC_ERR_NO_CARD: return CTRL_NO_PRESENT; default: return CTRL_FAIL; } #endif // FAKE_RW // Pipeline the 2 transfer in order to speed-up the performances nb_step = nb_sector + 1; while (nb_step--) { if (!b_first_step) { // Skip first step // RAM -> MCI #ifdef FAKE_RW cached_sectors[next_cached_sector].sector = addr + nb_sector - nb_step - 1; memcpy(cached_sectors[next_cached_sector++].contents, ((nb_step % 2) == 0) ? sector_buf_0 : sector_buf_1, SD_MMC_BLOCK_SIZE); if (cached_sector_count < 20) cached_sector_count++; next_cached_sector %= NUM_CACHED_SECTORS; #else // FAKE_RW if (SD_MMC_OK != sd_mmc_start_write_blocks(((nb_step % 2) == 0) ? sector_buf_0 : sector_buf_1, 1)) { return CTRL_FAIL; } #endif // !FAKE_RW } if (nb_step) { // Skip last step #if defined(USE_ENCRYPTION) && !defined(FAKE_RW) uint32_t sector = addr + nb_sector - nb_step; #endif // USE_ENCRYPTION && !FAKE_RW // USB -> RAM if (!udi_msc_trans_block(false, #if defined(USE_ENCRYPTION) && !defined(FAKE_RW) use_user_page_values() && sector >= CRYPT_START ? aes_buf : #endif // USE_ENCRYPTION && !FAKE_RW (((nb_step % 2) == 0) ? sector_buf_1 : sector_buf_0), SD_MMC_BLOCK_SIZE, NULL)) { return CTRL_FAIL; } #if defined(USE_ENCRYPTION) && !defined(FAKE_RW) // Encrypt if (use_user_page_values() && sector >= CRYPT_START) { MD5_Init (&md5_ctx); MD5_Update (&md5_ctx, §or, sizeof(uint32_t)); MD5_Final (IV, &md5_ctx); aes_encrypt_key128(AES_KEY, aes_ctx); aes_cbc_encrypt(aes_buf, ((nb_step % 2) == 0) ? sector_buf_1 : sector_buf_0, SD_MMC_BLOCK_SIZE, IV, aes_ctx); } #endif // USE_ENCRYPTION && !FAKE_RW } if (!b_first_step) { // Skip first step #ifndef FAKE_RW if (SD_MMC_OK != sd_mmc_wait_end_of_write_blocks()) { return CTRL_FAIL; } #endif // !FAKE_RW } else { b_first_step = false; } } return CTRL_GOOD; }