This commit is contained in:
刘可亮
2024-06-04 19:00:30 +08:00
parent 990c72f5be
commit 0a13af6a1d
1668 changed files with 342810 additions and 37726 deletions

View File

@@ -27,6 +27,8 @@ if GetDepend('AIC_BOOTLOADER_FATFS_SUPPORT'):
src += Glob('upg_fat_direct_mmc.c')
src += Glob('upg_fat_direct_nor.c')
src += Glob('upg_fat_direct_nand.c')
if GetDepend('AICUPG_LOG_BUFFER_SUPPORT'):
src += Glob('log_buf.c')
CPPPATH = [cwd]
ASFLAGS = ''

View File

@@ -12,7 +12,9 @@
#include <console.h>
#include <aic_common.h>
#include "upg_internal.h"
#ifdef AICUPG_LOG_BUFFER_SUPPORT
#include <log_buf.h>
#endif
#define BOOT_STAGE_UBOOT 1
/*
* UPG_PROTO_CMD_GET_HWINFO at BROM stage is use to provide hardware data
@@ -482,8 +484,8 @@ static s32 CMD_RUN_SHELL_STR_write_input_data(struct upg_cmd *cmd, u8 *buf,
if (cmd->state == CMD_STATE_ARG) {
/*
* Enter recv argument state
*/
* Enter recv argument state
*/
if (len < 4)
return 0;
memcpy(&shinfo->cmdlen, buf, 4);
@@ -496,9 +498,9 @@ static s32 CMD_RUN_SHELL_STR_write_input_data(struct upg_cmd *cmd, u8 *buf,
if (cmd->state == CMD_STATE_DATA_IN) {
/*
* Enter recv data state, all command string should be sent in
* one packet.
*/
* Enter recv data state, all command string should be sent in
* one packet.
*/
if (((len - clen) != shinfo->cmdlen) ||
(shinfo->cmdlen >= MAX_SHELL_CMD_STR_LEN)) {
@@ -531,9 +533,9 @@ static s32 CMD_RUN_SHELL_STR_read_output_data(struct upg_cmd *cmd, u8 *buf,
if (cmd->state == CMD_STATE_RESP) {
/*
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
aicupg_gen_resp(&resp, cmd->cmd, shinfo->result, 0);
siz = sizeof(struct resp_header);
memcpy(buf, &resp, siz);
@@ -859,6 +861,157 @@ static void CMD_SET_UPG_END_end(struct upg_cmd *cmd)
}
}
static void CMD_GET_LOG_SIZE_start(struct upg_cmd *cmd, s32 cmd_data_len)
{
cmd_state_init(cmd, CMD_STATE_START);
}
static s32 CMD_GET_LOG_SIZE_write_input_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
/* No input data for this command */
return 0;
}
static s32 CMD_GET_LOG_SIZE_read_output_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
struct resp_header resp;
u32 siz = 0, val = 0;
if (cmd->state == CMD_STATE_START)
cmd_state_set_next(cmd, CMD_STATE_RESP);
if (cmd->state == CMD_STATE_RESP) {
/*
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
aicupg_gen_resp(&resp, cmd->cmd, 0, 4);
siz = sizeof(struct resp_header);
memcpy(buf, &resp, siz);
cmd_state_set_next(cmd, CMD_STATE_DATA_OUT);
}
if (siz == len)
return siz;
if (cmd->state == CMD_STATE_DATA_OUT) {
#ifdef AICUPG_LOG_BUFFER_SUPPORT
val = log_buf_get_len();
#else
val = 0;
#endif
memcpy(buf, &val, 4);
siz += 4;
cmd_state_set_next(cmd, CMD_STATE_END);
}
return siz;
}
static void CMD_GET_LOG_SIZE_end(struct upg_cmd *cmd)
{
cmd_state_set_next(cmd, CMD_STATE_IDLE);
}
static void CMD_GET_LOG_DATA_start(struct upg_cmd *cmd, s32 cmd_data_len)
{
static struct cmd_rw_priv read_log;
read_log.addr = 0;
read_log.len = 0;
read_log.index = 0;
cmd->priv = &read_log;
cmd_state_init(cmd, CMD_STATE_START);
}
static s32 CMD_GET_LOG_DATA_write_input_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
struct cmd_rw_priv *priv;
u32 val, clen = 0;
priv = (struct cmd_rw_priv *)cmd->priv;
if (!priv)
return 0;
if (cmd->state == CMD_STATE_START)
cmd_state_set_next(cmd, CMD_STATE_ARG);
if (cmd->state == CMD_STATE_ARG) {
/*
* Enter recv argument state
*/
if (len < 4)
return 0;
memcpy(&val, buf, 4);
#ifdef AICUPG_LOG_BUFFER_SUPPORT
if (val > log_buf_get_len())
val = log_buf_get_len();
#endif
priv->len = val;
clen += 4;
cmd_state_set_next(cmd, CMD_STATE_RESP);
}
return clen;
}
static s32 CMD_GET_LOG_DATA_read_output_data(struct upg_cmd *cmd, u8 *buf,
s32 len)
{
struct cmd_rw_priv *priv;
struct resp_header resp;
u32 siz = 0;
#ifdef AICUPG_LOG_BUFFER_SUPPORT
char *p;
#endif
priv = (struct cmd_rw_priv *)cmd->priv;
if (!priv)
return 0;
if (cmd->state == CMD_STATE_RESP) {
/*
* Enter read RESP state, to make it simple, HOST should read
* RESP in one read operation.
*/
siz = priv->len;
aicupg_gen_resp(&resp, cmd->cmd, 0, siz);
siz = sizeof(struct resp_header);
memcpy(buf, &resp, siz);
cmd_state_set_next(cmd, CMD_STATE_DATA_OUT);
}
if (siz == len)
return siz;
if (cmd->state == CMD_STATE_DATA_OUT) {
/* Enter read DATA state */
p = (char *)buf;
#ifdef AICUPG_LOG_BUFFER_SUPPORT
log_buf_read(p, len - siz);
#endif
priv->index += (len - siz);
siz += (len - siz);
if (priv->index >= priv->len)
cmd_state_set_next(cmd, CMD_STATE_END);
}
return siz;
}
static void CMD_GET_LOG_DATA_end(struct upg_cmd *cmd)
{
struct cmd_rw_priv *priv;
priv = (struct cmd_rw_priv *)cmd->priv;
if (!priv)
return;
if (cmd->state == CMD_STATE_END) {
priv->addr = 0;
priv->len = 0;
priv->index = 0;
cmd->priv = 0;
cmd_state_set_next(cmd, CMD_STATE_IDLE);
}
}
static struct upg_cmd basic_cmd_list[] = {
{
UPG_PROTO_CMD_GET_HWINFO,
@@ -930,6 +1083,20 @@ static struct upg_cmd basic_cmd_list[] = {
CMD_FREE_MEM_BUF_read_output_data,
CMD_FREE_MEM_BUF_end,
},
{
UPG_PROTO_CMD_GET_LOG_SIZE,
CMD_GET_LOG_SIZE_start,
CMD_GET_LOG_SIZE_write_input_data,
CMD_GET_LOG_SIZE_read_output_data,
CMD_GET_LOG_SIZE_end,
},
{
UPG_PROTO_CMD_GET_LOG_DATA,
CMD_GET_LOG_DATA_start,
CMD_GET_LOG_DATA_write_input_data,
CMD_GET_LOG_DATA_read_output_data,
CMD_GET_LOG_DATA_end,
},
};
struct upg_cmd *find_basic_command(struct cmd_header *h)

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2023, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Wu Dehuang <dehuang.wu@artinchip.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <aic_core.h>
#include <aic_common.h>
#include <aic_errno.h>
#include <log_buf.h>
#define AIC_LOG_MAGIC 0x4C434941
struct log_buffer {
int magic;
int istart;
int icurr;
int buf_size;
char buf[];
};
#ifdef AICUPG_LOG_BUFFER_SUPPORT
#define LOG_BUF_ADDR AICUPG_LOG_BUFFER_ADDR
#define LOG_BUF_SIZE AICUPG_LOG_BUFFER_SIZE
#else
#define LOG_BUF_ADDR 0
#define LOG_BUF_SIZE 0
#endif
int log_buf_init(void)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log;
void *buff;
int size;
buff = (void *)LOG_BUF_ADDR;
size = (int)LOG_BUF_SIZE;
if (!buff || (size < sizeof(*log)))
return -1;
log = buff;
if (log->magic == AIC_LOG_MAGIC)
return 0;
log->istart = 0;
log->icurr = 0;
log->buf_size = size - sizeof(*log);
log->magic = AIC_LOG_MAGIC;
#endif
return 0;
}
int log_buf_get_len(void)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log = (void *)LOG_BUF_ADDR;
if (!log)
return 0;
return (log->icurr + log->buf_size - log->istart) % log->buf_size;
#endif
return 0;
}
int log_buf_write(char *in, int len)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log = (void *)LOG_BUF_ADDR;
int dolen, freelen;
char *ps;
if (!log)
return 0;
if (log->magic != AIC_LOG_MAGIC)
return 0;
dolen = len;
freelen = log->buf_size - 1 - log_buf_get_len();
if (freelen == 0)
return 0;
if (dolen > freelen)
dolen = freelen;
len = dolen;
ps = in;
while (dolen) {
log->buf[log->icurr % log->buf_size] = *ps;
log->icurr = (log->icurr + 1) % log->buf_size;
dolen--;
ps++;
}
return len;
#endif
return 0;
}
int log_buf_read(char *out, int len)
{
#ifdef AICUPG_LOG_BUFFER_SUPPORT
struct log_buffer *log = (void *)LOG_BUF_ADDR;
int dolen, loglen;
char *pd;
if (!log)
return 0;
if (log->magic != AIC_LOG_MAGIC)
return 0;
dolen = len;
loglen = log_buf_get_len();
if (dolen > loglen)
dolen = loglen;
len = dolen;
pd = out;
while (dolen) {
*pd = log->buf[log->istart % log->buf_size];
log->istart = (log->istart + 1) % log->buf_size;
dolen--;
pd++;
}
return len;
#endif
return 0;
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2023, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Wu Dehuang <dehuang.wu@artinchip.com>
*/
#ifndef _LOG_BUF_H_
#define _LOG_BUF_H_
int log_buf_init(void);
int log_buf_get_len(void);
int log_buf_write(char *in, int len);
int log_buf_read(char *out, int len);
#endif

View File

@@ -50,6 +50,23 @@ s32 mmc_fwc_prepare(struct fwc_info *fwc, u32 mmc_id)
return ret;
}
struct aic_partition *mmc_fwc_get_part_by_name(struct fwc_info *fwc, char *name)
{
struct aicupg_mmc_priv *priv;
struct aic_partition *parts = NULL;
priv = (struct aicupg_mmc_priv *)fwc->priv;
parts = priv->parts;
while (parts) {
if (!strcmp(parts->name, name))
return parts;
parts = parts->next;
}
return NULL;
}
static unsigned long mmc_write(struct blk_desc *block_dev, u64 start,
u64 blkcnt, void *buffer)
{
@@ -115,6 +132,71 @@ out:
free(priv);
}
s32 mmc_fwc_sparse_fill(struct aicupg_mmc_priv *priv, struct aic_partition *parts, u64 chunk_blkcnt, uint32_t fill_val)
{
u32 blks, remain_blks, redund_blks, erase_group;
u32 *fill_buf, fill_buf_num_blks, fill_blks = 0;
int i, j;
fill_buf = (u32 *)aicos_malloc_align(0, ROUNDUP(SPARSE_FILLBUF_SIZE, CACHE_LINE_SIZE), CACHE_LINE_SIZE);
if (!fill_buf) {
pr_err("Malloc failed for: CHUNK_TYPE_FILL\n");
return 0;
}
for (i = 0; i < (SPARSE_FILLBUF_SIZE / sizeof(fill_val)); i++)
fill_buf[i] = fill_val;
// When using 0 fill, it is faster to use erase than write
if (chunk_blkcnt >= 0x400 && fill_val == 0x0) { // 512K
// 1. Fill part start blocks to align by group. 1 group = 1024 blocks
remain_blks = ROUNDUP((parts->start / MMC_BLOCK_SIZE) + priv->blkstart, 0x400) - ((parts->start / MMC_BLOCK_SIZE) + priv->blkstart);
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, remain_blks, (u8 *)fill_buf);
if (blks < remain_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, remain_blks);
goto out;
}
fill_blks += blks;
// 2. Erase by group for faster speed,
erase_group = (chunk_blkcnt - remain_blks) / 0x400;
blks = mmc_berase(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, erase_group * 0x400);
if (blks != (erase_group * 0x400)) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Erase failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, erase_group * 0x400);
goto out;
}
fill_blks += blks;
// 3. Fill of remaining blocks
redund_blks = chunk_blkcnt - remain_blks - (erase_group * 0x400);
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, redund_blks, (u8 *)fill_buf);
if (blks < redund_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, redund_blks);
goto out;
}
fill_blks += blks;
} else {
fill_buf_num_blks = SPARSE_FILLBUF_SIZE / MMC_BLOCK_SIZE;
for (i = 0; i < chunk_blkcnt;) {
j = chunk_blkcnt - i;
if (j > fill_buf_num_blks)
j = fill_buf_num_blks;
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, j, (u8 *)fill_buf);
if (blks < j) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, j);
goto out;
}
fill_blks += blks;
i += j;
}
}
out:
aicos_free_align(0, fill_buf);
return fill_blks;
}
s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
{
struct aicupg_mmc_priv *priv;
@@ -126,9 +208,7 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
u32 chunk;
u64 chunk_data_sz, chunk_blkcnt, remain_blkcnt;
u32 total_blocks = 0, blks;
u32 remain_blks, redund_blks, erase_group;
u32 *fill_buf, fill_val, fill_buf_num_blks;
int i, j, break_flag = 0;
u32 fill_val;
wbuf = malloc(ROUNDUP(len + MMC_BLOCK_SIZE, fwc->block_size));
if (!wbuf) {
@@ -153,16 +233,11 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
total_len = (priv->remain_len + len);
remain = total_len;
parts = priv->parts;
while (parts) {
if (!strcmp(parts->name, fwc->meta.partition))
break;
parts = parts->next;
}
if (!parts)
parts = mmc_fwc_get_part_by_name(fwc, fwc->meta.partition);
if (!parts) {
pr_err("not find %s part info.\n", fwc->meta.partition);
goto out;
}
sheader = &(priv->sparse_header);
if (is_sparse_image(wbuf)) {
@@ -171,11 +246,6 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
wbuf += sheader->file_hdr_sz;
clen += sheader->file_hdr_sz;
remain -= sheader->file_hdr_sz;
if (sheader->file_hdr_sz > sizeof(sparse_header_t)) {
wbuf += (sheader->file_hdr_sz - sizeof(sparse_header_t));
clen += (sheader->file_hdr_sz - sizeof(sparse_header_t));
remain -= (sheader->file_hdr_sz - sizeof(sparse_header_t));
}
pr_info("=== Sparse Image Header ===\n");
pr_info("magic: 0x%x\n", sheader->magic);
pr_info("major_version: 0x%x\n", sheader->major_version);
@@ -194,17 +264,11 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
/* Read and skip over chunk header */
cheader = (chunk_header_t *)wbuf;
if (cheader->chunk_type != CHUNK_TYPE_RAW) {
pr_debug("=== Chunk Header ===\n");
pr_debug("chunk_type: 0x%x\n", cheader->chunk_type);
pr_debug("chunk_data_sz: 0x%x\n", cheader->chunk_sz);
pr_debug("total_size: 0x%x\n", cheader->total_sz);
}
if (cheader->chunk_type != CHUNK_TYPE_RAW &&
cheader->chunk_type != CHUNK_TYPE_FILL &&
cheader->chunk_type != CHUNK_TYPE_DONT_CARE &&
cheader->chunk_type != CHUNK_TYPE_CRC32) {
cheader->chunk_type != CHUNK_TYPE_CRC32 &&
priv->cur_chunk_remain_data_sz) {
cheader = &(priv->chunk_header);
chunk_data_sz = priv->cur_chunk_remain_data_sz;
} else {
@@ -212,69 +276,50 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
clen += sheader->chunk_hdr_sz;
remain -= sheader->chunk_hdr_sz;
memcpy(&(priv->chunk_header), cheader, sizeof(chunk_header_t));
if (sheader->chunk_hdr_sz > sizeof(chunk_header_t)) {
/*
* Skip the remaining bytes in a header that is longer
* than we expected.
*/
wbuf += (sheader->chunk_hdr_sz - sizeof(chunk_header_t));
clen += (sheader->chunk_hdr_sz - sizeof(chunk_header_t));
remain -= (sheader->chunk_hdr_sz - sizeof(chunk_header_t));
}
chunk_data_sz = ((u64)sheader->blk_sz) * cheader->chunk_sz;
priv->cur_chunk_remain_data_sz = chunk_data_sz;
priv->cur_chunk_burned_data_sz = 0;
pr_debug("=== Chunk Header ===\n");
pr_debug("chunk_type: 0x%x\n", cheader->chunk_type);
pr_debug("chunk_size: 0x%x\n", cheader->chunk_sz);
pr_debug("total_size: 0x%x\n", cheader->total_sz);
pr_debug("=== Chunk DEBUG ===\n");
pr_debug("chunk_id: %u\t", chunk);
pr_debug("chunk_offset: %u\t", fwc->trans_size + clen);
pr_debug("chunk_number: %u\n", cheader->total_sz - sheader->chunk_hdr_sz);
}
chunk_blkcnt = DIV_ROUND_UP(chunk_data_sz, MMC_BLOCK_SIZE);
if (priv->blkstart + chunk_blkcnt > (parts->size / MMC_BLOCK_SIZE)) {
pr_err("Request would exceed partition size!\n");
goto out;
}
remain_blkcnt = remain / MMC_BLOCK_SIZE;
switch (cheader->chunk_type) {
case CHUNK_TYPE_RAW:
if (cheader->total_sz !=
(sheader->chunk_hdr_sz + chunk_data_sz +
priv->cur_chunk_burned_data_sz)) {
if (cheader->total_sz != (sheader->chunk_hdr_sz + chunk_data_sz + priv->cur_chunk_burned_data_sz)) {
pr_err("Bogus chunk size for chunk type Raw\n");
goto out;
}
if (priv->blkstart + chunk_blkcnt >
(parts->size / MMC_BLOCK_SIZE)) {
pr_err("Request would exceed partition size!\n");
goto out;
}
if (remain_blkcnt > chunk_blkcnt &&
(remain - chunk_data_sz) >= 16) {
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
chunk_blkcnt, wbuf);
if (blks <
chunk_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
blks);
if (remain_blkcnt > chunk_blkcnt && (remain - chunk_data_sz) >= 16) {
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, chunk_blkcnt, wbuf);
if (blks < chunk_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, blks);
goto out;
}
remain = remain - chunk_data_sz;
priv->cur_chunk_remain_data_sz = 0;
priv->cur_chunk_burned_data_sz += chunk_data_sz;
} else {
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
remain_blkcnt, wbuf);
if (blks <
remain_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
blks);
blks = mmc_bwrite(priv->host, (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, remain_blkcnt, wbuf);
if (blks < remain_blkcnt) { /* blks might be > blkcnt (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%u]\n", (parts->start / MMC_BLOCK_SIZE) + priv->blkstart, blks);
goto out;
}
priv->cur_chunk_remain_data_sz -=
remain_blkcnt * MMC_BLOCK_SIZE;
priv->cur_chunk_burned_data_sz +=
remain_blkcnt * MMC_BLOCK_SIZE;
priv->cur_chunk_remain_data_sz -= remain_blkcnt * MMC_BLOCK_SIZE;
priv->cur_chunk_burned_data_sz += remain_blkcnt * MMC_BLOCK_SIZE;
remain = remain % MMC_BLOCK_SIZE;
}
@@ -282,122 +327,31 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
total_blocks += blks;
wbuf += blks * MMC_BLOCK_SIZE;
clen += blks * MMC_BLOCK_SIZE;
if ((priv->cur_chunk_remain_data_sz > 0 &&
(remain > 0 && remain < MMC_BLOCK_SIZE)) ||
remain < sizeof(chunk_header_t))
break_flag = 1;
break;
case CHUNK_TYPE_FILL:
if (cheader->total_sz !=
(sheader->chunk_hdr_sz + sizeof(uint32_t))) {
if (cheader->total_sz != (sheader->chunk_hdr_sz + sizeof(uint32_t))) {
pr_err("Bogus chunk size for chunk type FILL\n");
goto out;
}
fill_buf = (u32 *)aicos_malloc_align(
0, ROUNDUP(SPARSE_FILLBUF_SIZE, CACHE_LINE_SIZE),
CACHE_LINE_SIZE);
if (!fill_buf) {
pr_err("Malloc failed for: CHUNK_TYPE_FILL\n");
goto out;
}
fill_val = *(uint32_t *)wbuf;
wbuf = (u8 *)wbuf + sizeof(u32);
clen += sizeof(uint32_t);
remain -= sizeof(uint32_t);
if (remain < sizeof(chunk_header_t))
break_flag = 1;
if (priv->blkstart + chunk_blkcnt >
(parts->size / MMC_BLOCK_SIZE)) {
pr_err("Request would exceed partition size!\n");
pr_debug("FILL with \t 0x%08x\n", fill_val);
blks = mmc_fwc_sparse_fill(priv, parts, chunk_blkcnt, fill_val);
if (blks != chunk_blkcnt) {
pr_err("CHUNK_TYPE_FILL FILL failed.\n");
goto out;
}
for (i = 0; i < (SPARSE_FILLBUF_SIZE / sizeof(fill_val)); i++)
fill_buf[i] = fill_val;
remain_blks =
ROUNDUP((parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
0x400) -
((parts->start / MMC_BLOCK_SIZE) + priv->blkstart);
if (chunk_blkcnt >= (remain_blks + 0x400) &&
fill_val == 0x0) { // 512K
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
remain_blks, (u8 *)fill_buf);
if (blks <
remain_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
remain_blks);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
erase_group = (chunk_blkcnt - remain_blks) / 0x400;
blks = mmc_berase(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
erase_group * 0x400);
if (blks !=
(erase_group *
0x400)) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Erase failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
erase_group * 0x400);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
redund_blks =
chunk_blkcnt - remain_blks - (erase_group * 0x400);
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
redund_blks, (u8 *)fill_buf);
if (blks <
redund_blks) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) + priv->blkstart,
redund_blks);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
} else {
fill_buf_num_blks = SPARSE_FILLBUF_SIZE / MMC_BLOCK_SIZE;
for (i = 0; i < chunk_blkcnt;) {
j = chunk_blkcnt - i;
if (j > fill_buf_num_blks)
j = fill_buf_num_blks;
blks = mmc_bwrite(priv->host,
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
j, (u8 *)fill_buf);
if (blks <
j) { /* blks might be > j (eg. NAND bad-blocks) */
pr_err("Write failed, block %llu[%d]\n",
(parts->start / MMC_BLOCK_SIZE) +
priv->blkstart,
j);
free(fill_buf);
goto out;
}
priv->blkstart += blks;
i += j;
}
}
priv->blkstart += blks;
total_blocks += DIV_ROUND_UP(chunk_data_sz, sheader->blk_sz);
free(fill_buf);
break;
case CHUNK_TYPE_DONT_CARE:
@@ -421,13 +375,13 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
cheader = &(priv->chunk_header);
}
if (break_flag)
if ((priv->cur_chunk_remain_data_sz > 0 && (remain > 0 && remain < MMC_BLOCK_SIZE)) || remain < sizeof(chunk_header_t))
break;
}
priv->remain_len = remain;
priv->cur_chunk = chunk;
if (priv->remain_len) {
priv->cur_chunk = chunk;
memcpy(priv->remain_data, wbuf, priv->remain_len);
}
@@ -436,8 +390,7 @@ s32 mmc_fwc_sparse_write(struct fwc_info *fwc, u8 *buf, s32 len)
pr_debug("%s, data len %d, trans len %d\n", __func__, len, fwc->trans_size);
out:
if (p)
free(p);
free(p);
return len;
}
@@ -455,14 +408,7 @@ s32 mmc_fwc_raw_write(struct fwc_info *fwc, u8 *buf, s32 len)
goto out;
}
parts = priv->parts;
while (parts) {
if (!strcmp(parts->name, fwc->meta.partition))
break;
parts = parts->next;
}
parts = mmc_fwc_get_part_by_name(fwc, fwc->meta.partition);
if (!parts)
pr_err("not find %s part info.\n", fwc->meta.partition);

View File

@@ -204,7 +204,7 @@ s32 nand_fwc_uffs_write(struct fwc_info *fwc, u8 *buf, s32 len)
int total_len = 0, remain_offset = 0;
u8 *wbuf = NULL, *pbuf = NULL;
wbuf = malloc(ROUNDUP(len, fwc->block_size));
wbuf = aicos_malloc_align(0, ROUNDUP(len, fwc->block_size), CACHE_LINE_SIZE);
if (!wbuf) {
pr_err("malloc failed.\n");
return 0;
@@ -291,13 +291,13 @@ s32 nand_fwc_uffs_write(struct fwc_info *fwc, u8 *buf, s32 len)
pr_debug("%s, data len %d, trans len %d\n", __func__, len, fwc->trans_size);
free(wbuf);
aicos_free_align(0, wbuf);
return len;
out:
if (wbuf)
free(wbuf);
aicos_free_align(0, wbuf);
return ret;
}

View File

@@ -256,9 +256,7 @@ static s32 spl_build_page_table(struct aicupg_nand_spl *spl,
pr_debug("%s, going to generate page table.\n", __func__);
slice_size = spl->mtd->writesize;
pt->head.page_size = PAGE_SIZE_2KB;
if (spl->mtd->writesize == 4096)
pt->head.page_size = PAGE_SIZE_4KB;
pt->head.page_size = spl->mtd->writesize;
page_per_blk = spl->mtd->erasesize / spl->mtd->writesize;
page_data = malloc(PAGE_MAX_SIZE);
@@ -455,7 +453,7 @@ out:
static s32 verify_page_table(struct aicupg_nand_spl *spl, u32 blkidx,
struct nand_page_table *pt, u32 len)
{
u8 page_data[PAGE_TABLE_USE_SIZE] = { 0 };
u8 page_data[PAGE_MAX_SIZE] = { 0 };
ulong offset;
u32 sumval;
s32 ret;
@@ -639,3 +637,15 @@ s32 nand_fwc_spl_write(u32 totalsiz, u8 *buf, s32 len)
return len;
}
int nand_spl_get_candidate_blocks(u32 *blks, u32 size)
{
if (!blks || size < SPL_CANDIDATE_BLOCK_NUM) {
pr_err("Invalid parameter.\n");
return -1;
}
memcpy(blks, spl_candidate_block_table,
sizeof(u32) * SPL_CANDIDATE_BLOCK_NUM);
return 0;
}

View File

@@ -27,10 +27,6 @@ extern "C" {
#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))
#define PAGE_SIZE_1KB 1
#define PAGE_SIZE_2KB 2
#define PAGE_SIZE_4KB 4
#define MAX_DUPLICATED_PART 4
#ifdef AIC_NFTL_SUPPORT
@@ -51,8 +47,8 @@ struct aicupg_nand_priv {
struct nand_page_table_head {
char magic[4]; /* AICP: AIC Page table */
u32 entry_cnt;
u8 page_size; /* 0: No page size info; 1: 1KB; 2: 2KB; 4: 4KB */
u8 pad[11]; /* Padding it to fit size 20 bytes */
u16 page_size;
u8 pad[10]; /* Padding it to fit size 20 bytes */
};
/*
@@ -90,6 +86,7 @@ s32 nand_fwc_spl_reserve_blocks(struct aicupg_nand_priv *priv);
s32 nand_fwc_spl_prepare(struct aicupg_nand_priv *priv, u32 datasiz,
u32 blksiz);
s32 nand_fwc_spl_write(u32 totalsiz, u8 *buf, s32 len);
int nand_spl_get_candidate_blocks(u32 *blks, u32 size);
#ifdef __cplusplus
}

View File

@@ -26,8 +26,10 @@
#endif
#define RECV_SIZE_USE_DMA 512
#define TRANS_DATA_BUFF_SIZE (64 * 1024)
#define TRANS_DATA_BUFF_MAX_SIZE (64 * 1024)
#define TRANS_DATA_BUFF_MIN_SIZE (20 * 1024)
static u8 *trans_pkt_buf = NULL;
static u32 trans_pkt_siz = 0;
static void trans_send_csw(struct phy_data_rw *rw, u32 tag, u8 status, u32 rest)
{
@@ -56,10 +58,15 @@ s32 trans_layer_rw_proc(struct phy_data_rw *rw, u8 *buffer, u32 len)
}
if (!trans_pkt_buf) {
trans_pkt_buf = aicos_malloc_align(0, TRANS_DATA_BUFF_SIZE, CACHE_LINE_SIZE);
trans_pkt_siz = TRANS_DATA_BUFF_MAX_SIZE;
trans_pkt_buf = aicos_malloc_align(0, trans_pkt_siz, CACHE_LINE_SIZE);
if (!trans_pkt_buf) {
pr_err("malloc trans pkt buf failed.\n");
return -1;
trans_pkt_siz = TRANS_DATA_BUFF_MIN_SIZE;
trans_pkt_buf = aicos_malloc_align(0, trans_pkt_siz, CACHE_LINE_SIZE);
if (!trans_pkt_buf) {
pr_err("malloc trans pkt buf(%u) failed.\n", trans_pkt_siz);
return -1;
}
}
}
@@ -87,8 +94,8 @@ s32 trans_layer_rw_proc(struct phy_data_rw *rw, u8 *buffer, u32 len)
rest = data_len;
total = 0;
while (rest > 0) {
if (rest >= TRANS_DATA_BUFF_SIZE)
slice = TRANS_DATA_BUFF_SIZE;
if (rest >= trans_pkt_siz)
slice = trans_pkt_siz;
else
slice = rest;
@@ -121,8 +128,8 @@ s32 trans_layer_rw_proc(struct phy_data_rw *rw, u8 *buffer, u32 len)
rest = data_len;
total = 0;
while (rest > 0) {
if (rest >= TRANS_DATA_BUFF_SIZE)
slice = TRANS_DATA_BUFF_SIZE;
if (rest >= trans_pkt_siz)
slice = trans_pkt_siz;
else
slice = rest;

View File

@@ -19,11 +19,45 @@
static u32 image_size = 0;
static u64 write_size = 0;
static void *upg_fat_malloc_align(struct fwc_info *fwc, u32 *size, size_t align)
{
void *ptr = NULL;
switch (*size) {
case DATA_WRITE_ONCE_MAX_SIZE:
*size = ALIGN_DOWN(DATA_WRITE_ONCE_MAX_SIZE, fwc->block_size);
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
case DATA_WRITE_ONCE_MID_SIZE:
*size = ALIGN_DOWN(DATA_WRITE_ONCE_MID_SIZE, fwc->block_size);
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
case DATA_WRITE_ONCE_MIN_SIZE:
*size = ALIGN_DOWN(DATA_WRITE_ONCE_MIN_SIZE, fwc->block_size);
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
default:
ptr = aicos_malloc_align(0, *size, align);
if (ptr)
break;
}
return ptr;
}
static void upg_fat_free_align(void *mem)
{
aicos_free_align(0, mem);
}
#define FRAME_LIST_SIZE 4096
static s32 media_device_write(char *image_name, struct fwc_meta *pmeta)
{
struct fwc_info *fwc;
int offset, write_once_size, len, remaining_size;
u32 offset, write_once_size, len, remaining_size;
u8 *buf;
s32 ret;
ulong actread, total_len = 0;
@@ -48,18 +82,18 @@ static s32 media_device_write(char *image_name, struct fwc_meta *pmeta)
/*start write data*/
start_us = aic_get_time_us();
media_data_write_start(fwc);
/*config write size once*/
write_once_size = DATA_WRITE_ONCE_SIZE;
if (write_once_size % fwc->block_size)
write_once_size = (write_once_size / fwc->block_size) * fwc->block_size;
write_once_size = DATA_WRITE_ONCE_MAX_SIZE;
/*malloc buf memory*/
buf = aicos_malloc_align(0, write_once_size, FRAME_LIST_SIZE);
buf = upg_fat_malloc_align(fwc, &write_once_size, FRAME_LIST_SIZE);
if (!buf) {
pr_err("Error: malloc buf failed.\n");
ret = -1;
goto err;
}
memset((void *)buf, 0, write_once_size);
offset = 0;
@@ -99,13 +133,13 @@ static s32 media_device_write(char *image_name, struct fwc_meta *pmeta)
(total_len * 1000000 / start_us) / 1024 / 1024,
(total_len * 1000000 / start_us) / 1024 % 1024);
aicos_free_align(0, buf);
upg_fat_free_align(buf);
aicos_free_align(0, fwc);
return total_len;
err:
if (buf)
aicos_free_align(0, buf);
upg_fat_free_align(buf);
if (fwc)
aicos_free_align(0, fwc);
return 0;