#include #include #include #include #include #include #include #include #include #include #include #include #include #include "libmmc.h" #define DEFAULT_PATH_FOR_RCA "/sys/block/%s/device/rca" #define MEMCARD_DIR "/retain" #define FILE_PATH "/retain/file" #define IMAGE_SIZE_B 1*1024*1024 // 1MB #define SEC_TO_USEC 1000*1000 #define NSEC_TO_USEC 1000 static char *image_write = NULL; static int image_size = 0; unsigned int sdFindRca(char* filename) { unsigned int rca_temp = 0; char devname[16]; char rca_file[50]; char read_rca[8]; FILE *fp; int i; for(i=strlen(filename)-1; (i>0) && filename[i-1]!='/'; i--); strncpy(devname,filename+i,sizeof(devname)); sprintf(rca_file, DEFAULT_PATH_FOR_RCA, devname); fp = fopen(rca_file, "r"); if(fp != NULL){ fread(read_rca, 1, 8, fp); rca_temp = (int)strtol(read_rca, NULL, 0); fclose(fp); } return rca_temp; } void* ThreadFunc(void *arg) { int fd = -1; int dev = -1; struct mmc_ioc_cmd sts_cmd; struct mmc_ioc_cmd ina_cmd; unsigned int rca; unsigned int status = 0; char *devname = "/dev/mmcblk1"; struct timespec tstr; struct timespec tend; struct timespec t1; struct timespec t2; unsigned long diff_unmount = 0; unsigned long diff_wait_busy = 0; unsigned long diff_go_inactive = 0; unsigned long diff_overall = 0; unsigned long diff_open = 0; unsigned long diff_write = 0; unsigned long diff_fsync = 0; unsigned long diff_close = 0; /* Get RCA and Device descriptor */ rca = sdFindRca(devname); dev = open(devname, O_RDWR); /* Prepare status command */ memset(&sts_cmd, 0, sizeof(sts_cmd)); sts_cmd.opcode = MMC_SEND_STATUS; sts_cmd.arg = (rca << 16); sts_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; mmc_ioc_cmd_set_data(sts_cmd, &status); /* Preprare inactivate command */ memset(&ina_cmd, 0, sizeof(ina_cmd)); ina_cmd.opcode = MMC_GO_INACTIVE_STATE; ina_cmd.arg = (rca << 16); ina_cmd.flags = MMC_CMD_AC; clock_gettime(CLOCK_MONOTONIC, &tstr); if(rca > 0 && dev >= 0){ /* Write data to the file */ printf("Opening file...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); fd = open(FILE_PATH, O_WRONLY | O_CREAT); clock_gettime(CLOCK_MONOTONIC, &t2); diff_open = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); if(fd >= 0){ printf("Writing file...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); write(fd, image_write, image_size); clock_gettime(CLOCK_MONOTONIC, &t2); diff_write = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); printf("Synchronizing file...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); fsync(fd); clock_gettime(CLOCK_MONOTONIC, &t2); diff_fsync = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); printf("Closing file...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); close(fd); clock_gettime(CLOCK_MONOTONIC, &t2); diff_close = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); } printf("Unmounting filesystem...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); if(umount2(MEMCARD_DIR, MNT_DETACH) < 0){ printf("Error in unmount (errorno %d: %s)!\n", errno, strerror(errno)); } clock_gettime(CLOCK_MONOTONIC, &t2); diff_unmount = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); /* Wait to be in Transfer State (not busy) */ printf("Waiting MMC busy...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); do{ if(ioctl(dev, MMC_IOC_CMD, &sts_cmd) < 0){ printf("Error in CMD %d (errorno %d: %s)!\n", sts_cmd.opcode, errno, strerror(errno)); } }while(R1_CURRENT_STATE(status) != R1_STATE_TRAN && R1_CURRENT_STATE(status) != R1_STATE_STBY && R1_CURRENT_STATE(status) != R1_STATE_IDLE); clock_gettime(CLOCK_MONOTONIC, &t2); diff_wait_busy = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); /* Set MMC to inactive */ printf("Going to inactive...\n"); clock_gettime(CLOCK_MONOTONIC, &t1); if(ioctl(dev, MMC_IOC_CMD, &ina_cmd) < 0){ printf("Error in CMD %d (errorno %d: %s)!\n", ina_cmd.opcode, errno, strerror(errno)); } clock_gettime(CLOCK_MONOTONIC, &t2); diff_go_inactive = (unsigned long)(t2.tv_sec*SEC_TO_USEC + t2.tv_nsec/NSEC_TO_USEC - (t1.tv_sec*SEC_TO_USEC + t1.tv_nsec/NSEC_TO_USEC)); } else{ printf("Wrong RCA value -> %d\n", rca); } clock_gettime(CLOCK_MONOTONIC, &tend); diff_overall = (unsigned long)(tend.tv_sec*SEC_TO_USEC + tend.tv_nsec/NSEC_TO_USEC - (tstr.tv_sec*SEC_TO_USEC + tstr.tv_nsec/NSEC_TO_USEC)); printf("Thread Time Logs:\n\tOpen: %lu us\n\tWrite: %lu us\n\tFsync: %lu us\n\tClose: %lu us\n\t" \ "Unmount: %lu us\n\tWait Busy: %lu us\n\tInactivate: %lu us\nOverall: %lu us\n", diff_open, diff_write, diff_fsync, diff_close, diff_unmount, diff_wait_busy, diff_go_inactive, diff_overall); /* Close device */ if(dev >= 0){ close(dev); } } /* * First argument = number of MBytes of the buffer * Second argument = file source that will be copied */ int main(int argc, char **argv) { int file = -1; int ret = -1; pthread_t thread; struct sched_param param; printf("Secure Unmount v4.1\n"); if(argc < 2) { printf("Missing argument!\n"); return -1; } /* * Receive the number of MBytes of the file * e.g.: sd_test 8 -> 8MBytes */ image_size = atoi(argv[1]) * IMAGE_SIZE_B; if(image_size == 0){ printf("Wrong argument!\n"); return -1; } /* Allocate the buffer */ image_write = calloc(image_size, sizeof(char)); if(image_write == NULL){ printf("Unable to allocate %d bytes\n", image_size); return -1; } printf("Init Code!\n"); /* Open file to be copied */ file = open(argv[2], O_RDONLY); if(file >= 0){ if(read(file, image_write, image_size) != image_size){ printf("File size is different from %d bytes\n", image_size); } close(file); } else{ printf("Error opening the file %s!\n", argv[2]); free(image_write); return -1; } /* Remove a existent file */ if(remove(FILE_PATH) == 0){ printf("File removed!\n"); } printf("Init thread...\n"); pthread_create(&thread, NULL, ThreadFunc, NULL); param.__sched_priority = 90; pthread_setschedparam(thread, SCHED_FIFO, ¶m); printf("Wait thread...\n"); ret = pthread_join(thread, NULL); if(ret != 0){ printf("Join received error: %d\n", ret); } free(image_write); return 0; }