blob: 1950ef26aab11498d812ec7c6079bc6a55cc212f [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2016, ZIXC Corporation.
*
* File Name:cmd_dl_mmc.c
* File Mark:
* Description: download or upload bin from eMMC,compat with SD
* Others:
* Version: 1.0
* Author: zangxiaofeng
* Date: 2014-1-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"
#include <mmc.h>
extern partition_table_t * g_partition_table_dl;
extern int downloader_readline (char * buffer);
extern int downloader_mmc_erase(partition_entry_t * part, uint partEraseSize);
extern char *tsp_console_buffer;
/*******************************************************************************
* Function:do_mmc_write
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_mmc_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;
#ifdef CONFIG_LOAD_CRC
unsigned long crc = 0;
unsigned long crc1 = 0;
#endif
int ret = 0;
int zload_len = 8192;
nand_info_t *nand = NULL;
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_mmc_erase( part, part->part_size);
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
if(memcmp(par,"zloader",7) == 0) /* ÏÂÔØzloader·ÖÇø£¬Í¬Ê±ÏÂÔØ·ÖÇø±í */
{
memcpy((char *)(DOWNLOADER_BUFFER_BASE+4096),g_partition_table_dl,4096);
ret = mmc_write( nand,(loff_t)(part->part_offset + offset_par) , &zload_len, (unsigned char *)DOWNLOADER_BUFFER_BASE, 0);
}
else
{
ret = mmc_write( nand,(loff_t)(part->part_offset + offset_par) , &curWriteLength, (unsigned char *)DOWNLOADER_BUFFER_BASE, 0);
}
if(ret)
{
sprintf(ack,"FAIL MMC 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;
}
sprintf(ack,"OKAY");
downloader_serial_write(ack, strlen(ack)+1);
return 0;
}
/*******************************************************************************
* Function:do_mmc_read
* Description:
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int do_mmc_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;
#ifdef CONFIG_LOAD_CRC
unsigned long crc = 0;
#endif
int ret = 0;
nand_info_t *nand = NULL;
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;
#ifdef CONFIG_LOAD_CRC
sprintf(ack,"DATACRC %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
#else
sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
#endif
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 = mmc_read( nand,(loff_t)(part->part_offset+offset_par), &curReadLength, (unsigned char *)DOWNLOADER_BUFFER_BASE);
if(ret)
{
sprintf(ack,"FAIL MMC READ %d,%d, ret = %d",offset_par,curReadLength,ret);
downloader_serial_write(ack, strlen(ack)+1);
return ENOSYS; /* Function not implemented */
}
//printf("start to upload LEN=%d \n",curReadLength);
#ifdef CONFIG_LOAD_CRC
crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,curReadLength);
memcpy((unsigned char*)(DOWNLOADER_BUFFER_BASE+curReadLength),(unsigned char *)(&crc),4);
downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength+4);
#else
downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength);
#endif
//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:downloader_mmc_erase
* Description:erase mmc partition
* Parameters:
* Input:partEraseSize: must be multiple of 512KBytes
* part:part information,offset and size must be multiple of 512KBytes
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int downloader_mmc_erase(partition_entry_t * part, uint partEraseSize)
{
unsigned int blksize = 512;
int ret = 0;
if(part == NULL )
{
return -1;
}
ret = mmc_erase( (u64)part->part_offset, (lbaint_t)partEraseSize/blksize);
return ret;
}
/*******************************************************************************
* Function:do_mmc_eraseall
* Description:erase all mmc partitions
* Parameters:
* Input:
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int downloader_mmc_eraseall(void)
{
int ret = 0;
partition_entry_t *entry = &g_partition_table->table[0];
uint32_t entry_nums = g_partition_table->entrys;
while( entry_nums-- )
{
if ( strcmp((const char *)entry->part_name, "ddr") == 0 \
||strcmp((const char *)entry->part_name, "raw") == 0)
{
entry++;
continue;
}
ret = downloader_mmc_erase(entry,entry->part_size);
entry++;
}
return ret;
}
/*******************************************************************************
* Function:do_mmc_eraseauto
* Description:erase mmc except nvr
* Parameters:
* Input:
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int downloader_mmc_eraseauto(void)
{
int ret = 0;
partition_entry_t *entry = &g_partition_table->table[0];
uint32_t entry_nums = g_partition_table->entrys;
while( entry_nums-- )
{
if (strcmp((const char *)entry->part_name, "nvro") == 0||\
strcmp((const char *)entry->part_name, "ddr") == 0 \
||strcmp((const char *)entry->part_name, "raw") == 0)
{
entry++;
continue;
}
ret = downloader_mmc_erase(entry,entry->part_size);
entry++;
}
return ret;
}
/*
******************************************************************************
* Function:set_mmc_dlflag
* Description: open or close USB DL PORT, based on mmc
* dl on :open DL port ; dl off :close DL port
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
*******************************************************************************
*/
int set_mmc_dlflag( char * sign)
{
int ret = 0;
char value = 0;
int bootflag = 0;
int size = 8192;
u_char *buffer = kzalloc(0x3000,GFP_KERNEL);
if( buffer == NULL )
return -1;
if (strcmp((const char *)sign,"on") == 0)
{
bootflag = 0x00;
memset(&value, bootflag, 1);
}
else if (strcmp((const char *)sign,"off") == 0)
{
bootflag = 0x5a;
memset(&value, bootflag, 1);
}
memcpy(buffer+2, &value, 1);
ret = mmc_write( 0, 0, &size,buffer, 0);
sprintf(tsp_console_buffer,"DL OKAY");
downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
kfree(buffer);
return 0;
}