blob: eb42af5d444a84c7260c63dd195c73b99975cf56 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2016, ZIXC Corporation.
*
* File Name:cmd_dl_raw.c
* File Mark:
* Description:
* Others:
* Version: 1.0
* Author: zangxiaofeng
* Date: 2013-6-9
* History 1:
* Date:
* Version:
* Author:
* Modification:
* History 2:
********************************************************************************/
/****************************************************************************
* Include files
****************************************************************************/
#include <common.h>
#include <command.h>
#include <net.h>
#include <jffs2/load_kernel.h>
#include "downloader_config.h"
#include "downloader_nand.h"
#include "downloader_serial.h"
#include "errno.h"
extern int downloader_readline (char * buffer);
extern char *tsp_console_buffer;
/*******************************************************************************
* Function:do_raw_write
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_raw_write(unsigned int offset, unsigned int size)
{
char *ack = tsp_console_buffer;
unsigned int leftWriteLength = 0;
unsigned int curWriteLength = 0;
#ifdef CONFIG_LOAD_CRC
unsigned long crc = 0;
unsigned long crc1 = 0;
#endif
int ret = 0;
nand_info_t *pNandInfo = NULL;
//struct erase_info instr;
pNandInfo = &nand_info[nand_curr_device];
assert(pNandInfo!=NULL);
leftWriteLength = size;
if((size==0)||(offset+size > pNandInfo->size))
{
sprintf(ack,"FAIL INVALID LENGTH");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
ret = do_raw_erase(offset, size);
if(ret)
{
sprintf(ack,"FAIL ERASE ERROR");
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
while(leftWriteLength>0)
{
curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
#ifdef CONFIG_LOAD_CRC
sprintf(ack,"DATACRC %08x",curWriteLength);
#else
sprintf(ack,"DATA %08x",curWriteLength);
#endif
downloader_serial_write(ack, strlen(ack)+1);
#ifdef CONFIG_LOAD_CRC
downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength+4);
crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,curWriteLength);
memcpy((unsigned char *)(&crc1),(unsigned char*)(DOWNLOADER_BUFFER_BASE+curWriteLength),4);
//printf("CRC_calc= %x,CRC_rec=%x \n",crc,crc1);
if(crc != crc1)
{
sprintf(ack,"FAIL CRC ERROR");
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
#else
downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
#endif
//printf("start to write\n");
ret = nand_write_skip_bad( pNandInfo, offset, &curWriteLength, (unsigned char *)DOWNLOADER_BUFFER_BASE,0);
if(ret)
{
sprintf(ack,"FAIL NAND WRITE %d,%d,ret = %d",offset,curWriteLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
//printf("finish writing\n");
leftWriteLength -= curWriteLength;
offset += curWriteLength;
}
//printf("finish writing, leftlen = %d \n",leftWriteLength);
sprintf(ack,"OKAY");
downloader_serial_write(ack, strlen(ack)+1);
return 0;
}
/*******************************************************************************
* Function:do_raw_read
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_raw_read(unsigned int offset, unsigned int size)
{
char *rx_buffer = tsp_console_buffer;
char *ack = tsp_console_buffer;
unsigned int leftReadLength = 0;
unsigned int curReadLength = 0;
int ret = 0;
nand_info_t *pNandInfo = NULL;
//struct erase_info instr;
pNandInfo = &nand_info[nand_curr_device];
assert(pNandInfo!=NULL);
leftReadLength = size;
if((size==0)||(offset+size > pNandInfo->size))
{
sprintf(ack,"FAIL INVALID LENGTH");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
downloader_serial_write(ack, strlen(ack)+1);
while(leftReadLength>0)
{
curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);
downloader_readline(rx_buffer);
if(memcmp(rx_buffer,"OKAY",4)==0)
{
ret = nand_read_skip_bad( pNandInfo, offset, &curReadLength, (unsigned char *)DOWNLOADER_BUFFER_BASE);
if(ret)
{
sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset,curReadLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
//printf("start to upload LEN=%d \n",curReadLength);
downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength);
}
else
{
sprintf(ack,"FAIL COMMAND ERROR");
downloader_serial_write(ack, strlen(ack)+1);
return EBADRQC; /* Invalid request code */
}
leftReadLength -= curReadLength;
offset += curReadLength;
}
downloader_readline(rx_buffer);
if(memcmp(rx_buffer,"OKAY",4)==0)
{
return 0;
}
else
{
sprintf(ack,"FAIL COMMAND ERROR");
downloader_serial_write(ack, strlen(ack)+1);
return -1;
}
}
int do_raw_erase(unsigned int offset, unsigned int partEraseSize)
{
nand_info_t *pNandInfo = NULL;
struct erase_info instr;
unsigned int size = 0;
unsigned int ret = 0;
pNandInfo = &nand_info[nand_curr_device];
assert(pNandInfo!=NULL);
instr.mtd = pNandInfo;
instr.addr = offset;
assert( (instr.addr & (pNandInfo->erasesize - 1)) == 0);
instr.callback = 0;
while((size < partEraseSize) && (instr.addr < (offset+partEraseSize)))
{
if(nand_block_isbad (pNandInfo, instr.addr))
{
instr.addr += pNandInfo->erasesize;
continue ;
}
instr.len = pNandInfo->erasesize;
instr.state = 0;
ret = pNandInfo->erase(pNandInfo, &instr);
if(ret && instr.state == MTD_ERASE_FAILED)
{
pNandInfo->block_markbad(pNandInfo,instr.addr);
}
else if (ret == 0)
{
size += pNandInfo->erasesize;
}
else
{
printf( "downloader nand: erase error\n");
return 1;
}
instr.addr += pNandInfo->erasesize;
}
return 0;
}