blob: d4b0e0476a94a1f5590e3b0c63cf47dd672d1d5e [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2016, ZIXC Corporation.
*
* File Name:cmd_load_nand.c
* File Mark:
* Description:
* Others:
* Version: 1.0
* Author: zangxiaofeng
* Date: 2013-3-13
* 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 partition_table_t * g_partition_table_dl;
extern int downloader_readline (char * buffer);
extern char *tsp_console_buffer;
extern int crc_switch_flag;
extern unsigned int null_slice_flag;
/*******************************************************************************
* Function:do_nand_write
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_nand_write(partition_entry_t *part, char *par ,
unsigned int offset, unsigned int size )
{
char *ack = tsp_console_buffer;
unsigned int offset_par = offset;
unsigned int leftWriteLength = 0;
unsigned int curWriteLength = 0;
unsigned int read_buf_offset = 0;
unsigned long crc = 0;
int ret = 0;
//part = downloader_get_part(par);
if(part==NULL)
{
sprintf(ack,"FAIL INVALID PARTITION");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
if((size==0)||(size>part->part_size))
{
sprintf(ack,"FAIL INVALID LENGTH");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
leftWriteLength = size;
ret = downloader_nand_erase(part,part->part_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);
sprintf(ack,"DATA %08x",curWriteLength);
downloader_serial_write(ack, strlen(ack)+1);
downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
if(memcmp(par,"zloader",7) == 0) /* ÏÂÔØzloader·ÖÇø£¬Í¬Ê±ÏÂÔØ·ÖÇø±í */
{
memcpy((char *)(DOWNLOADER_BUFFER_BASE+8192),g_partition_table_dl,4096);
ret = downloader_nand_write(part, offset_par, 0x3000,
(unsigned char *)DOWNLOADER_BUFFER_BASE);
}
else
{
ret = downloader_nand_write(part, offset_par, curWriteLength,
(unsigned char *)DOWNLOADER_BUFFER_BASE);
}
if(ret)
{
sprintf(ack,"FAIL NAND WRITE %d,%d,ret = %d",offset_par,curWriteLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
leftWriteLength -= curWriteLength;
offset_par += curWriteLength;
}
if(crc_switch_flag == 0)
{
sprintf(ack,"OKAY");
downloader_serial_write(ack, strlen(ack)+1);
}
else
{
leftWriteLength = size;
offset_par = offset;
while(leftWriteLength>0)
{
curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
ret = downloader_nand_read(part, offset_par, curWriteLength,
(unsigned char *)(DOWNLOADER_BUFFER_BASE + read_buf_offset));
if(ret)
{
sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curWriteLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
leftWriteLength -= curWriteLength;
offset_par += curWriteLength;
read_buf_offset += curWriteLength;
}
crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,size);
downloader_serial_write_actuallen((const char *)(&crc), 4);
}
return 0;
}
/*******************************************************************************
* Function:do_nand_read
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_nand_read(partition_entry_t *part, char *par ,
unsigned int offset, unsigned int size )
{
char *rx_buffer = tsp_console_buffer;
char *ack = tsp_console_buffer;
unsigned int offset_par=offset;
unsigned int leftReadLength = 0;
unsigned int curReadLength = 0;
int ret = 0;
//part = downloader_get_part(par);
if(part == NULL)
{
sprintf(ack,"FAIL INVALID PARTITION");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
if((size == 0)||(size>part->part_size))
{
sprintf(ack,"FAIL INVALID LENGTH");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
leftReadLength = size;
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 = downloader_nand_read(part, offset_par,
curReadLength,
(unsigned char *)DOWNLOADER_BUFFER_BASE);
if(ret)
{
sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curReadLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
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_par += 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;
}
}
/*******************************************************************************
* Function:do_nor_write
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_nor_write(partition_entry_t *part, char *par ,
unsigned int offset, unsigned int size )
{
char *ack = tsp_console_buffer;
unsigned int offset_par = offset;
unsigned int leftWriteLength = 0;
unsigned int curWriteLength = 0;
unsigned int read_buf_offset = 0;
unsigned long crc = 0;
int ret = 0;
//part = downloader_get_part(par);
if(part==NULL)
{
sprintf(ack,"FAIL INVALID PARTITION");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
if((size==0)||(size>part->part_size))
{
sprintf(ack,"FAIL INVALID LENGTH");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
leftWriteLength = size;
if(null_slice_flag == 1)
{
ret = downloader_nor_erase(part,part->part_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);
sprintf(ack,"DATA %08x",curWriteLength);
downloader_serial_write(ack, strlen(ack)+1);
downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
if(memcmp(par,"zloader",7) == 0) /* ÏÂÔØzloader·ÖÇø£¬Í¬Ê±ÏÂÔØ·ÖÇø±í */
{
memcpy((char *)(DOWNLOADER_BUFFER_BASE+8192),g_partition_table_dl,4096);
ret = downloader_nor_write( part, offset_par, 0x3000, (unsigned char *)DOWNLOADER_BUFFER_BASE);
}
else
{
ret = downloader_nor_write( part, offset_par, curWriteLength, (unsigned char *)DOWNLOADER_BUFFER_BASE);
}
if(ret)
{
sprintf(ack,"FAIL NAND WRITE %d,%d,ret = %d",offset_par,curWriteLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
leftWriteLength -= curWriteLength;
offset_par += curWriteLength;
}
if(crc_switch_flag == 0)
{
sprintf(ack,"OKAY");
downloader_serial_write(ack, strlen(ack)+1);
}
else
{
leftWriteLength = size;
offset_par = offset;
while(leftWriteLength>0)
{
curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
ret = downloader_nor_read(part,
offset_par,
curWriteLength,
(unsigned char *)(DOWNLOADER_BUFFER_BASE + read_buf_offset));
if(ret)
{
sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curWriteLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
leftWriteLength -= curWriteLength;
offset_par += curWriteLength;
read_buf_offset += curWriteLength;
}
crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,size);
downloader_serial_write_actuallen((const char *)(&crc), 4);
}
return 0;
}
/*******************************************************************************
* Function:do_nor_read
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_nor_read(partition_entry_t *part, char *par ,
unsigned int offset, unsigned int size )
{
char *rx_buffer = tsp_console_buffer;
char *ack = tsp_console_buffer;
unsigned int offset_par=offset;
unsigned int leftReadLength = 0;
unsigned int curReadLength = 0;
int ret = 0;
//part = downloader_get_part(par);
if(part == NULL)
{
sprintf(ack,"FAIL INVALID PARTITION");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
if((size == 0)||(size>part->part_size))
{
sprintf(ack,"FAIL INVALID LENGTH");
downloader_serial_write(ack, strlen(ack)+1);
return EINVAL; /* Invalid argument */
}
leftReadLength = size;
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 = downloader_nor_read( part, offset_par, curReadLength, (unsigned char *)DOWNLOADER_BUFFER_BASE);
if(ret)
{
sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curReadLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
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_par += 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;
}
}