blob: 66280b5475b4fa1c3d29b07f829209eb6a73b437 [file] [log] [blame]
#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