#include "../inc/mtk_device_wrap.h" | |
#if MTK_BOOTDEV_TYPE == BOOTDEV_TYPE_NAND | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "../inc/nand_api.h" | |
#include "../inc/common.h" | |
#include "../inc/xalloc.h" | |
int mtk_device_wrap_m_open(const char *pathname, int flags, mode_t mode) | |
{ | |
return nand_open(pathname, flags); | |
} | |
int mtk_device_wrap_open(const char *pathname, int flags) | |
{ | |
return nand_open(pathname, flags); | |
} | |
off_t mtk_device_wrap_seek(int fd, off_t offset, int whence) | |
{ | |
return nand_seek(fd, offset, whence); | |
} | |
off64_t mtk_device_wrap_seek64(int fd, off64_t offset, int whence) | |
{ | |
return nand_seek64(fd, offset, whence); | |
} | |
ssize_t mtk_device_wrap_read(int fd, void *buf, size_t count) | |
{ | |
return nand_read(fd, buf, count); | |
} | |
ssize_t mtk_device_wrap_write(int fd, void *buf, size_t count) | |
{ | |
return nand_write(fd, buf, count); | |
} | |
#define ALIGN_LOWER(x, a) ((x)&~(a-1)) | |
struct nandx_split32 { | |
off_t head; | |
size_t head_len; | |
off_t body; | |
size_t body_len; | |
off_t tail; | |
size_t tail_len; | |
}; | |
static void nandx_split(struct nandx_split32 *split, off_t offset, size_t len, size_t align) | |
{ | |
size_t val; | |
split->head = offset; | |
val = ALIGN_LOWER(offset, align); | |
val = align - (offset - val); | |
if (val == align) | |
split->head_len = 0; | |
else if (val > len) | |
split->head_len = len; | |
else | |
split->head_len = val; | |
split->body = offset + split->head_len; | |
split->body_len = ALIGN_LOWER(len - split->head_len, align); | |
split->tail = split->body + split->body_len; | |
split->tail_len = len - split->head_len - split->body_len; | |
} | |
ssize_t mtk_device_wrap_write_force(int fd, void *buf, size_t count) | |
{ | |
struct nandx_split32 split = {0}; | |
off_t offset, record_offset; | |
size_t block_size; | |
void* temp_buf; | |
size_t acc_count = 0; | |
size_t result; | |
size_t remain_count = count; | |
char* lbuf = buf; | |
int i=0; | |
offset = nand_query_offset(fd); | |
record_offset = offset + count; | |
block_size = nand_query_blk_size(fd); | |
if (block_size <= 0) { | |
printf("write_force wrong block size\n"); | |
return 0; | |
} | |
//split head, body, and tail | |
nandx_split(&split, offset, count, block_size); | |
//allocate buffer | |
temp_buf = xmalloc(block_size); | |
if (temp_buf == NULL) { | |
printf("write_force alloc fail\n"); | |
return 0; | |
} | |
//handle head | |
if (split.head_len) { | |
off_t head_base = ALIGN_LOWER(split.head, block_size); | |
// read the whole block | |
nand_seek(fd, head_base, SEEK_SET); | |
nand_read(fd, temp_buf, block_size); | |
//update the temp_buf | |
memcpy(temp_buf + offset - head_base, lbuf, split.head_len); | |
//write to flash | |
nand_seek(fd, head_base, SEEK_SET); | |
result = nand_write(fd, temp_buf, block_size); | |
if (result != block_size) { | |
printf("write_force head fail\n"); | |
goto out; | |
} | |
acc_count += split.head_len; | |
//update | |
lbuf += split.head_len; | |
} | |
//handle body | |
if (split.body_len) { | |
nand_seek(fd, split.body, SEEK_SET); | |
result = nand_write(fd, lbuf, split.body_len); | |
if (result != split.body_len) { | |
printf("write_force body fail\n"); | |
goto out; | |
} | |
acc_count += result; | |
//update | |
lbuf += split.body_len; | |
} | |
//handle tail | |
if (split.tail_len) { | |
// read the whole block | |
nand_seek(fd, split.tail, SEEK_SET); | |
nand_read(fd, temp_buf, block_size); | |
//update the temp_buf | |
memcpy(temp_buf, lbuf, split.tail_len); | |
//write to flash | |
nand_seek(fd, split.tail, SEEK_SET); | |
result = nand_write(fd, temp_buf, block_size); | |
if (result != block_size) { | |
printf("write_force tail fail\n"); | |
goto out; | |
} | |
acc_count += split.tail_len; | |
//update | |
lbuf += split.tail_len; | |
} | |
out: | |
nand_seek(fd, record_offset, SEEK_SET); | |
//free buffer | |
free(temp_buf); | |
return acc_count; | |
} | |
int mtk_device_wrap_close(int fd) | |
{ | |
return nand_close(fd); | |
} | |
#else | |
int mtk_device_wrap_m_open(const char *pathname, int flags, mode_t mode) | |
{ | |
return open(pathname, flags, mode); | |
} | |
int mtk_device_wrap_open(const char *pathname, int flags) | |
{ | |
return open(pathname, flags); | |
} | |
off_t mtk_device_wrap_seek(int fd, off_t offset, int whence) | |
{ | |
return lseek(fd, offset, whence); | |
} | |
off64_t mtk_device_wrap_seek64(int fd, off64_t offset, int whence) | |
{ | |
return lseek64(fd, offset, whence); | |
} | |
ssize_t mtk_device_wrap_read(int fd, void *buf, size_t count) | |
{ | |
return read(fd, buf, count); | |
} | |
ssize_t mtk_device_wrap_write(int fd, void *buf, size_t count) | |
{ | |
return write(fd, buf, count); | |
} | |
ssize_t mtk_device_wrap_write_force(int fd, void *buf, size_t count) | |
{ | |
return write(fd, buf, count); | |
} | |
int mtk_device_wrap_close(int fd) | |
{ | |
return close(fd); | |
} | |
#endif |