UBOOT之源码分析(X4412)——SD卡烧录之sdfuse命令分析

11 篇文章 0 订阅
11 篇文章 0 订阅

cmd_fastboot.c文件中
命令格式:
sdfuseflash kernel zImage
sdfuse flash systemsystem.ext3
=========================================
int do_sdfuse (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int ret = 1;
int enable_reset = 0;
struct mmc *mmc =find_mmc_device(CFG_FASTBOOT_SDFUSE_MMCDEV);interface.nand_block_size = CFG_FASTBOOT_PAGESIZE *64;
interface.transfer_buffer = (unsigned char *)CFG_FASTBOOT_TRANSFER_BUFFER;
interface.transfer_buffer_size =CFG_FASTBOOT_TRANSFER_BUFFER_SIZE;

if(mmc_init(mmc)) {
printf("do_sdfuse:MMC init isfailed.\n");
return0;
}
//
emmc为空片时,可以支持sd卡直接格式化emmc,并分区。
printf("[FusingImage from SD Card.]\n");
if (set_partition_table())
return 1;

if((argc == 2) && !strcmp(argv[1],"info"))
{//
打印信息
printf("sdfusewill read images from the followings:\n");
printf("sd/mmc device : mmc %d:%d\n",
CFG_FASTBOOT_SDFUSE_MMCDEV,CFG_FASTBOOT_SDFUSE_MMCPART);

printf("directory : %s\n", CFG_FASTBOOT_SDFUSE_DIR);
printf("booting device : %s\n",

#ifdefined(CFG_FASTBOOT_ONENANDBSP)
"OneNAND"

#elifdefined(CFG_FASTBOOT_NANDBSP)
"NAND"
#elifdefined(CFG_FASTBOOT_SDMMCBSP)

"MoviNAND"
#else
#error "Unknown booting device!"
#endif

#ifdefined(CONFIG_FUSED)
" (on eFusedChip)"
#endif
);
return 0;
}
else if((argc == 2) && !strcmp(argv[1],"flashall"))
{
LCD_turnon();//
打开LCD
//run_command("fdisk-c 0", 0);//SD
卡分区。此处注消
set_partition_table_sdmmc();//
设置SD卡分区表

//支持SD卡烧写
update_from_sd("ubootpak","ubootpak.bin");
ret=update_from_sd("boot","boot.img");

if(ret==1)//linuxos
{//
烧写LINUX+QT环境变量及内核镜像.这里SD卡烧写自动设置好默认的环境变量
setenv("bootcmd", CONFIG_BOOTCOMMAND_QT);
setenv("bootargs",CONFIG_BOOTARGS_QT);
saveenv();
update_from_sd("kernel","zImage");
}
else//android os
{//
设置android系统环境变量
setenv("bootcmd", CONFIG_BOOTCOMMAND);
setenv ("bootargs",CONFIG_BOOTARGS);
saveenv();
}

ret=update_from_sd("system","system.img");
if(ret==1)//
如果烧写的不是android系统,则烧写QT文件系统
update_from_sd("system","qt-rootfs.img");

update_from_sd("userdata",NULL);
update_from_sd("cache",NULL);
update_from_sd("fat", NULL);

enable_reset= 1;
ret = 0;
}
else if ((argc == 4) &&!strcmp(argv[1], "flash"))
{

LCD_turnon();
if(update_from_sd(argv[2], argv[3]))
goto err_sdfuse;
ret= 0;
}
else if ((argc == 3) &&!strcmp(argv[1], "erase"))
{
LCD_turnon();
if(update_from_sd(argv[2], NULL))
goto err_sdfuse;
ret =0;
}
else
{
printf("Usage:\n%s\n",cmdtp->usage);
return 1;
}

err_sdfuse:

LCD_setfgcolor(0x000010);
LCD_setleftcolor(0x000010);
LCD_setprogress(100);

if(enable_reset)
do_reset (NULL, 0, 0, NULL);
return ret;
}



static int update_from_sd (char *part, char *file)
{
int ret =1;

/*Read file */
if (file != NULL)
{
longsize;
unsigned long offset;
unsigned long count;
charfilename[32];

block_dev_desc_t*dev_desc=NULL;


printf("Partition:%s, File: %s/%s\n", part, CFG_FASTBOOT_SDFUSE_DIR,file);
LCD_setfgcolor(0x2E8B57);
LCD_setprogress(100);
dev_desc= get_dev("mmc", CFG_FASTBOOT_SDFUSE_MMCDEV);
if(dev_desc == NULL) {
printf ("** Invalid boot device**\n");
return 1;
}

if(fat_register_device(dev_desc, CFG_FASTBOOT_SDFUSE_MMCPART) != 0){
printf ("** Invalid partition **\n");
return1;
}

sprintf(filename,"%s/%s", CFG_FASTBOOT_SDFUSE_DIR, file);
offset =CFG_FASTBOOT_TRANSFER_BUFFER;
count = 0;
size =file_fat_read (filename, (unsigned char *) offset, count);

if(size == -1) {
printf("Failed to read %s\n",filename);
return 1;
}

download_size= 0; // should be 0
download_bytes = size;

printf("%ld (0x%08x) bytes read\n", size, size);
}
else{
printf("Partition: %s\n", part);
download_size= 0; // should be 0
download_bytes = 0;
}

/*Write image into partition */
/* If file is empty or NULL, justerase the part. */
{
char command[32];
if(download_bytes == 0)
sprintf(command, "%s:%s","erase", part);
else
sprintf(command, "%s:%s","flash", part);
ret = rx_handler(command,sizeof(command));
}

//最后还是调用fastboot的这个接口,来烧写文件。
returnret;
}

SD卡支持自动格式,分区emmc命令:
common/cmd_ext2.c
文件中

U_BOOT_CMD(
ext3format, 3, 0, do_ext3_format,
"ext3format- disk format by ext3\n",
"<interface(only supportmmc)> <dev:partition num>\n"
" - format byext3 on 'interface'\n"
);

int do_ext3_format (cmd_tbl_t *cmdtp, int flag, int argc, char*argv[])
{
return ext_format(argc, argv, FS_TYPE_EXT3);
}


int ext_format (int argc, char *argv[], char filesystem_type)
{

intdev=0;
int part=1;
char *ep;
block_dev_desc_t*dev_desc=NULL;

if(argc < 2) {
printf("usage : ext2format <interface><dev[:part]>\n");
return (0);
}

dev= (int)simple_strtoul (argv[2], &ep,16);
dev_desc=get_dev(argv[1],dev);
if (dev_desc==NULL){
puts ("\n** Invalid boot device **\n");
return1;
}

if(*ep) {
if (*ep != ':') {
puts ("\n** Invalid bootdevice, use 'dev[:part]' **\n");
return 1;
}
part= (int)simple_strtoul(++ep, NULL, 16);
if (part > 4 || part< 1) {
puts ("** Partition Number shuld be 1 ~ 4**\n");
return 1;
}
}
printf("Startformat MMC%d partition%d ....\n", dev, part);

switch(filesystem_type) {
case FS_TYPE_EXT3:
caseFS_TYPE_EXT2:
if (ext2fs_format(dev_desc, part,filesystem_type) != 0)
printf("Formatfailure!!!\n");
break;

default:
printf("FileSystemType Value is not invalidate=%d \n",filesystem_type);
break;
}
return 0;
}

//ext2格式化详细机理以后再慢慢研究

分区部分

include/configs/x4412.h中定义格式化命令宏:

#defineCONFIG_BOOTCOMMAND2 "fdisk -c 0;sdfuse flashall;reset"

board/samsung/x4212/x4212.c文件中添加命令

setenv("bootcmd", CONFIG_BOOTCOMMAND2);

fdisk-c 0命令

common/cmd_mmc_fdisk.c文件中

int do_fdisk(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
if( argc == 3 || argc ==6 )
{
if ( strcmp(argv[1], "-c")== 0 )
return create_mmc_fdisk(argc, argv);//
创建分区

elseif ( strcmp(argv[1], "-p") == 0 )
returnprint_mmc_part_info(argc,argv);//
查看分区
}
else
{
printf("Usage:\nfdisk<-p> <device_num>\n");
printf("fdisk <-c><device_num> [<sys. part size(MB)> <user data partsize> <cache part size>]\n");
}
return 0;
}

//创建分区函数

int create_mmc_fdisk(int argc, char *argv[])
{

int rv;
int total_block_count;
unsignedchar mbr[512];

memset(mbr,0x00, 512);
//
根据指定的0,获取总快数,这里可以知道了fdisk-c 0 ,指的第一个注册的设备。是0节点,

total_block_count= get_mmc_block_count(argv[2]);//获取SD/MMC容量
if(total_block_count < 0)
return -1;

make_mmc_partition(total_block_count,mbr, (argc==6?1:0), argv);//创建分区表

rv= put_mmc_mbr(mbr, argv[2]);
if (rv != 0)
return -1;

printf("fdiskis completed\n");

argv[1][1]= 'p';
print_mmc_part_info(argc, argv);
return 0;
}

//获取SD/MMC容量
int get_mmc_block_count(char *device_name)
{

intrv;
struct mmc *mmc;
int block_count = 0;
intdev_num;

dev_num= simple_strtoul(device_name, NULL, 0);//这里把字符0转换成了整型 0

mmc= find_mmc_device(dev_num);//分区列表MBR写入节点设备中去

if(!mmc)
{
printf("mmc/sd device is NOTfounded.\n");
return -1;
}

//emmc/sd总容量大小,为块大小的倍数.
//
修改此处,因整个分区体系就是以一个块大小为512来分区的。
//BLOCK_SIZE= 512
//
所以对于有的emmc块大小是1024的。应增大它的容量,以免
//
对一个块使用不完全,就跳到下一个块过去了。

block_count= mmc->capacity * (mmc->read_bl_len / BLOCK_SIZE);

// printf("block_count= %d\n", block_count);

returnblock_count;

}



//创建分区列表MBR

int make_mmc_partition(int total_block_count, unsigned char *mbr, intflag, char *argv[])
{

int block_start= 0, block_offset;
SDInfo sdInfo;
PartitionInfo partInfo[4];

///

memset((unsignedchar *)&sdInfo, 0x00, sizeof(SDInfo));

///

//获取sd柱面,磁头,扇区的起始地址和结束地址

get_SDInfo(total_block_count,&sdInfo);

///

block_start= calc_unit(CFG_PARTITION_START, sdInfo);

//跳过前64M,作为系统分区起始地址CFG_PARTITION_STARTinclude/configs/x4412.h中定义,计算从第几块开始,64MB/512

if(flag)

block_offset= calc_unit((unsigned long long)simple_strtoul(argv[3], NULL,0)*1024*1024, sdInfo);

else
block_offset= calc_unit(SYSTEM_PART_SIZE, sdInfo);
//
空间大小为384MBsystem分区。文件开始有定义如下:
//
#define SYSTEM_PART_SIZE (384*1024*1024)
//#define USER_DATA_PART_SIZE (1024*1024*1024)
//#define CACHE_PART_SIZE (384*1024*1024)

partInfo[0].bootable =0x00;
partInfo[0].partitionId =0x83;
//
开始设置分区,赋值partInfo0,会跳过前面64M的空间,用于u-boot,kernelramdisk
make_partitionInfo(block_start, block_offset,sdInfo, &partInfo[0]);

///

block_start+= block_offset;

if(flag)
block_offset = calc_unit((unsigned longlong)simple_strtoul(argv[4], NULL, 0)*1024*1024,sdInfo);
else
block_offset =calc_unit(USER_DATA_PART_SIZE, sdInfo);
//1024Mdatauser
分区

partInfo[1].bootable =0x00;
partInfo[1].partitionId =0x83;
make_partitionInfo(block_start, block_offset, sdInfo,&partInfo[1]);

///

block_start+= block_offset;
if (flag)
block_offset =calc_unit((unsigned long long)simple_strtoul(argv[5], NULL,0)*1024*1024, sdInfo);
else
block_offset =calc_unit(CACHE_PART_SIZE, sdInfo);
//384M
cache分区

partInfo[2].bootable =0x00;
partInfo[2].partitionId =0x83;
make_partitionInfo(block_start, block_offset, sdInfo,&partInfo[2]);

///
//
剩余容量vfat分区,以0cid
block_start+= block_offset;
block_offset = BLOCK_END;

partInfo[3].bootable =0x00;
partInfo[3].partitionId =0x0C;
make_partitionInfo(block_start, block_offset, sdInfo,&partInfo[3]);

///

memset(mbr,0x00, sizeof(mbr));
mbr[510] = 0x55; mbr[511] =0xAA;
//
初始MBR的标志,默认是55AA

//MBR中:1BE-1CD:记录分区表11CE-1DD:记录分区表2
// 1DE-1ED :
分区31EE-1FD : 分区表4分区表 5不能创建,1FE需加55AA
//
每次 +F
//system
分区:分区表2,所以partInfo[0]表示分区表2
//
设置DPT结构
//
把每个分区的起始地址和结束地址写入到MBR
encode_partitionInfo(partInfo[0],&mbr[0x1CE]);
//datause
分区,partInfo[1]:表示分区表3
encode_partitionInfo(partInfo[1],&mbr[0x1DE]);
//cache
分区,partInfo[2]:表示分区表4
encode_partitionInfo(partInfo[2],&mbr[0x1EE]);
//
剩余空间:partInfo[3]表示分区表1
encode_partitionInfo(partInfo[3], &mbr[0x1BE]);

return0;
}

//计算每个分区的起始地址和结束地址

void make_partitionInfo(int LBA_start, int count, SDInfo sdInfo,PartitionInfo *partInfo)
{

int temp = 0;
int _10MB_unit;
partInfo->block_start = LBA_start;

//-----------------------------------------------------
if (sdInfo.addr_mode == CHS_MODE)
{//
块总数=c * H * s SD卡容量=块总数 *512byte
所以,块的起始地址
partInfo->C_start = partInfo->block_start/ (sdInfo.H_end * sdInfo.S_end);
temp = partInfo->block_start % (sdInfo.H_end * sdInfo.S_end);
partInfo->H_start = temp / sdInfo.S_end;
partInfo->S_start = temp % sdInfo.S_end +1;

if(count == BLOCK_END)
{//
剩余所有空间

_10MB_unit= calc_unit(CFG_PARTITION_START, sdInfo);
partInfo->block_end = sdInfo.C_end * sdInfo.H_end *sdInfo.S_end - _10MB_unit – 1;
partInfo->block_count = partInfo->block_end -partInfo->block_start + 1;
partInfo->C_end = partInfo->block_end / sdInfo.unit;
partInfo->H_end = sdInfo.H_end – 1;
partInfo->S_end = sdInfo.S_end;
}
else
{
partInfo->block_count = count;

partInfo->block_end = partInfo->block_start + count – 1;
partInfo->C_end = partInfo->block_end /sdInfo.unit;
temp =partInfo->block_end % sdInfo.unit;
partInfo->H_end = temp / sdInfo.S_end;
partInfo->S_end = temp % sdInfo.S_end + 1;
}
}

//-----------------------------------------------------
else
{

partInfo->C_start = 0;
partInfo->H_start = 1;
partInfo->S_start = 1;

partInfo->C_end = 1023;
partInfo->H_end =254;
partInfo->S_end = 63;

if(count == BLOCK_END)
{

_10MB_unit= calc_unit(CFG_PARTITION_START, sdInfo);
partInfo->block_end = sdInfo.total_block_count - _10MB_unit –1;
partInfo->block_count =partInfo->block_end - partInfo->block_start + 1;

}
else
{
partInfo->block_count = count;
partInfo->block_end = partInfo->block_start + count –1;
}
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值