@ -22,6 +22,7 @@
# include <common.h>
# include <common.h>
# include <malloc.h>
# include <malloc.h>
# include <errno.h>
# include <errno.h>
# include <div64.h>
# include <dfu.h>
# include <dfu.h>
enum dfu_mmc_op {
enum dfu_mmc_op {
@ -29,32 +30,51 @@ enum dfu_mmc_op {
DFU_OP_WRITE ,
DFU_OP_WRITE ,
} ;
} ;
static unsigned char __aligned ( CONFIG_SYS_CACHELINE_SIZE )
dfu_file_buf [ CONFIG_SYS_DFU_MAX_FILE_SIZE ] ;
static long dfu_file_buf_len ;
static int mmc_block_op ( enum dfu_mmc_op op , struct dfu_entity * dfu ,
static int mmc_block_op ( enum dfu_mmc_op op , struct dfu_entity * dfu ,
void * buf , long * len )
u64 offset , void * buf , long * len )
{
{
char cmd_buf [ DFU_CMD_BUF_SIZE ] ;
char cmd_buf [ DFU_CMD_BUF_SIZE ] ;
u32 blk_start , blk_count ;
/*
* We must ensure that we work in lba_blk_size chunks , so ALIGN
* this value .
*/
* len = ALIGN ( * len , dfu - > data . mmc . lba_blk_size ) ;
blk_start = dfu - > data . mmc . lba_start +
( u32 ) lldiv ( offset , dfu - > data . mmc . lba_blk_size ) ;
blk_count = * len / dfu - > data . mmc . lba_blk_size ;
if ( blk_start + blk_count >
dfu - > data . mmc . lba_start + dfu - > data . mmc . lba_size ) {
puts ( " Request would exceed designated area! \n " ) ;
return - EINVAL ;
}
sprintf ( cmd_buf , " mmc %s 0x%x %x %x " ,
sprintf ( cmd_buf , " mmc %s %p %x %x " ,
op = = DFU_OP_READ ? " read " : " write " ,
op = = DFU_OP_READ ? " read " : " write " ,
( unsigned int ) buf ,
buf , blk_start , blk_count ) ;
dfu - > data . mmc . lba_start ,
dfu - > data . mmc . lba_size ) ;
if ( op = = DFU_OP_READ )
* len = dfu - > data . mmc . lba_blk_size * dfu - > data . mmc . lba_size ;
debug ( " %s: %s 0x%p \n " , __func__ , cmd_buf , cmd_buf ) ;
debug ( " %s: %s 0x%p \n " , __func__ , cmd_buf , cmd_buf ) ;
return run_command ( cmd_buf , 0 ) ;
return run_command ( cmd_buf , 0 ) ;
}
}
static inline int mmc_block_write ( struct dfu_entity * dfu , void * buf , long * len )
static int mmc_file_buffer ( struct dfu_entity * dfu , void * buf , long * len )
{
{
return mmc_block_op ( DFU_OP_WRITE , dfu , buf , len ) ;
if ( dfu_file_buf_len + * len > CONFIG_SYS_DFU_MAX_FILE_SIZE ) {
}
dfu_file_buf_len = 0 ;
return - EINVAL ;
}
static inline int mmc_block_read ( struct dfu_entity * dfu , void * buf , long * len )
/* Add to the current buffer. */
{
memcpy ( dfu_file_buf + dfu_file_buf_len , buf , * len ) ;
return mmc_block_op ( DFU_OP_READ , dfu , buf , len ) ;
dfu_file_buf_len + = * len ;
return 0 ;
}
}
static int mmc_file_op ( enum dfu_mmc_op op , struct dfu_entity * dfu ,
static int mmc_file_op ( enum dfu_mmc_op op , struct dfu_entity * dfu ,
@ -66,20 +86,23 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
switch ( dfu - > layout ) {
switch ( dfu - > layout ) {
case DFU_FS_FAT :
case DFU_FS_FAT :
sprintf ( cmd_buf , " fat%s mmc %d:%d 0x%x %s %lx " ,
sprintf ( cmd_buf , " fat%s mmc %d:%d 0x%x %s " ,
op = = DFU_OP_READ ? " load " : " write " ,
op = = DFU_OP_READ ? " load " : " write " ,
dfu - > data . mmc . dev , dfu - > data . mmc . part ,
dfu - > data . mmc . dev , dfu - > data . mmc . part ,
( unsigned int ) buf , dfu - > name , * len ) ;
( unsigned int ) buf , dfu - > name ) ;
if ( op = = DFU_OP_WRITE )
sprintf ( cmd_buf + strlen ( cmd_buf ) , " %lx " , * len ) ;
break ;
break ;
case DFU_FS_EXT4 :
case DFU_FS_EXT4 :
sprintf ( cmd_buf , " ext4%s mmc %d:%d 0x%x /%s %ld " ,
sprintf ( cmd_buf , " ext4%s mmc %d:%d 0x%x /%s " ,
op = = DFU_OP_READ ? " load " : " write " ,
op = = DFU_OP_READ ? " load " : " write " ,
dfu - > data . mmc . dev , dfu - > data . mmc . part ,
dfu - > data . mmc . dev , dfu - > data . mmc . part ,
( unsigned int ) buf , dfu - > name , * len ) ;
( unsigned int ) buf , dfu - > name ) ;
break ;
break ;
default :
default :
printf ( " %s: Layout (%s) not (yet) supported! \n " , __func__ ,
printf ( " %s: Layout (%s) not (yet) supported! \n " , __func__ ,
dfu_get_layout ( dfu - > layout ) ) ;
dfu_get_layout ( dfu - > layout ) ) ;
return - 1 ;
}
}
debug ( " %s: %s 0x%p \n " , __func__ , cmd_buf , cmd_buf ) ;
debug ( " %s: %s 0x%p \n " , __func__ , cmd_buf , cmd_buf ) ;
@ -102,27 +125,18 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
return ret ;
return ret ;
}
}
static inline int mmc_file_write ( struct dfu_entity * dfu , void * buf , long * len )
int dfu_write_medium_mmc ( struct dfu_entity * dfu ,
{
u64 offset , void * buf , long * len )
return mmc_file_op ( DFU_OP_WRITE , dfu , buf , len ) ;
}
static inline int mmc_file_read ( struct dfu_entity * dfu , void * buf , long * len )
{
return mmc_file_op ( DFU_OP_READ , dfu , buf , len ) ;
}
int dfu_write_medium_mmc ( struct dfu_entity * dfu , void * buf , long * len )
{
{
int ret = - 1 ;
int ret = - 1 ;
switch ( dfu - > layout ) {
switch ( dfu - > layout ) {
case DFU_RAW_ADDR :
case DFU_RAW_ADDR :
ret = mmc_block_write ( dfu , buf , len ) ;
ret = mmc_block_op ( DFU_OP_WRITE , dfu , offset , buf , len ) ;
break ;
break ;
case DFU_FS_FAT :
case DFU_FS_FAT :
case DFU_FS_EXT4 :
case DFU_FS_EXT4 :
ret = mmc_file_write ( dfu , buf , len ) ;
ret = mmc_file_buffer ( dfu , buf , len ) ;
break ;
break ;
default :
default :
printf ( " %s: Layout (%s) not (yet) supported! \n " , __func__ ,
printf ( " %s: Layout (%s) not (yet) supported! \n " , __func__ ,
@ -132,17 +146,34 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
return ret ;
return ret ;
}
}
int dfu_read_medium_mmc ( struct dfu_entity * dfu , void * buf , long * len )
int dfu_flush_medium_mmc ( struct dfu_entity * dfu )
{
int ret = 0 ;
if ( dfu - > layout ! = DFU_RAW_ADDR ) {
/* Do stuff here. */
ret = mmc_file_op ( DFU_OP_WRITE , dfu , & dfu_file_buf ,
& dfu_file_buf_len ) ;
/* Now that we're done */
dfu_file_buf_len = 0 ;
}
return ret ;
}
int dfu_read_medium_mmc ( struct dfu_entity * dfu , u64 offset , void * buf ,
long * len )
{
{
int ret = - 1 ;
int ret = - 1 ;
switch ( dfu - > layout ) {
switch ( dfu - > layout ) {
case DFU_RAW_ADDR :
case DFU_RAW_ADDR :
ret = mmc_block_read ( dfu , buf , len ) ;
ret = mmc_block_op ( DFU_OP_READ , dfu , offset , buf , len ) ;
break ;
break ;
case DFU_FS_FAT :
case DFU_FS_FAT :
case DFU_FS_EXT4 :
case DFU_FS_EXT4 :
ret = mmc_file_read ( dfu , buf , len ) ;
ret = mmc_file_op ( DFU_OP_READ , dfu , buf , len ) ;
break ;
break ;
default :
default :
printf ( " %s: Layout (%s) not (yet) supported! \n " , __func__ ,
printf ( " %s: Layout (%s) not (yet) supported! \n " , __func__ ,
@ -181,14 +212,15 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
mmc = find_mmc_device ( dev ) ;
mmc = find_mmc_device ( dev ) ;
if ( mmc = = NULL | | mmc_init ( mmc ) ) {
if ( mmc = = NULL | | mmc_init ( mmc ) ) {
printf ( " %s: could not find mmc device #%d! \n " , __func__ , dev ) ;
printf ( " %s: could not find mmc device #%d! \n " ,
__func__ , dev ) ;
return - ENODEV ;
return - ENODEV ;
}
}
blk_dev = & mmc - > block_dev ;
blk_dev = & mmc - > block_dev ;
if ( get_partition_info ( blk_dev , part , & partinfo ) ! = 0 ) {
if ( get_partition_info ( blk_dev , part , & partinfo ) ! = 0 ) {
printf ( " %s: could not find partition #%d on mmc device #%d! \n " ,
printf ( " %s: could not find partition #%d on mmc device #%d! \n " ,
__func__ , part , dev ) ;
__func__ , part , dev ) ;
return - ENODEV ;
return - ENODEV ;
}
}
@ -208,6 +240,10 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
dfu - > read_medium = dfu_read_medium_mmc ;
dfu - > read_medium = dfu_read_medium_mmc ;
dfu - > write_medium = dfu_write_medium_mmc ;
dfu - > write_medium = dfu_write_medium_mmc ;
dfu - > flush_medium = dfu_flush_medium_mmc ;
/* initial state */
dfu - > inited = 0 ;
return 0 ;
return 0 ;
}
}