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;
}
}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: u-boot是一个开源的引导加载程序,用于嵌入式系统的启动。它通常嵌入在芯片的ROM或闪存中,是系统的第一个执行程序,负责初始化硬件、加载操作系统和其他应用程序。 u-boot源码是以C语言编写的,具有高度可移植性。它提供了一系列的驱动程序和命令行工具,可以在开发板上进行硬件初始化和测试。 源码的结构分为几个重要的部分:启动代码、中断向量表、初始化代码以及其他功能模块。启动代码是u-boot执行的入口点,在这个阶段,它会初始化一些必要的硬件设备,例如串口、存储器等,同时也会设置中断向量表。 中断向量表是一个由硬件中断信号触发的函数指针数组,u-boot将中断信号与相应的函数关联起来,以便在发生中断时进行相应的处理。 初始化代码是u-boot执行的核心部分,它会通过配置文件或环境变量来读取系统设置,并进行相应的初始化。例如,它会加载并运行操作系统内核镜像,设置内存映射表,配置设备和网络接口等。 此外,u-boot还提供了一些功能模块,例如命令行解析器、文件系统支持、网络协议栈等。这些功能模块可以通过命令行进行操作,以便用户对嵌入式系统进行配置、调试和测试。 对于研究和分析u-boot源码,可以从以下几个方面入手: 1. 启动流程:了解u-boot是如何从ROM或闪存中加载到内存并执行的,包括启动代码和中断向量表的设置。 2. 硬件初始化:了解u-boot是如何初始化硬件设备的,包括串口、存储器、网络接口等。 3. 配置文件和环境变量:了解u-boot是如何通过配置文件或环境变量来读取系统设置的,以及如何进行相应的初始化。 4. 功能模块:了解u-boot提供的功能模块,例如命令行解析器、文件系统支持、网络协议栈等,以及它们的实现方式和使用方法。 通过对u-boot源码的详细分析,可以深入了解嵌入式系统的引导过程、硬件初始化和驱动程序的编写,从而提高嵌入式系统的开发和调试能力。 ### 回答2: Uboot是一种开源的引导加载程序,用于嵌入式系统的启动。它是一个简单而灵活的软件,可以在各种硬件平台上使用,并提供了许多功能和驱动程序。 首先,Uboot的主要功能是加载和运行操作系统。它通过读取存储介质上的引导扇区,将操作系统加载到内存中并启动。此外,Uboot还提供了命令行界面,用户可以在启动过程中进行配置和控制。 Uboot的源代码由若干模块组成,包括引导代码、设备驱动程序、命令行解析器等。其中,引导代码是最关键的部分,负责在硬件启动时初始化系统和设备,并在引导过程中进行加载和启动操作系统。设备驱动程序用于访问硬件设备,例如存储介质、串口等。命令行解析器则负责解析用户输入的命令,并执行相应的操作。 在Uboot的源代码中,可以找到各种初始化和设置函数,以及与硬件平台相关的代码。这些代码通常是与硬件设备的寄存器交互,进行硬件初始化和配置。此外,还有一些与引导过程和加载操作系统相关的代码,用于读取、解析和加载引导扇区以及操作系统镜像。 总的来说,Uboot源码详细分析涉及到引导代码、设备驱动程序和命令行解析器等多个模块。在分析过程中,需要理解硬件平台的相关知识和操作系统的启动流程,并深入了解Uboot的代码实现和功能。只有这样,才能对Uboot源码有一个全面的理解,并能根据需求进行相应的修改和定制。 ### 回答3: U-Boot是一款开源的引导加载程序,用于嵌入式系统中启动操作系统。它是最常用的引导加载程序之一,具有广泛的应用。下面,我将对U-Boot源码进行详细分析。 U-Boot源码位于一个git仓库中,可以通过clone仓库获取源码源码的结构清晰,主要分为三个部分:板级支持包(board support package,BSP),引导和命令。 BSP包含了与硬件相关的代码和配置文件,用于支持不同的硬件平台。其中,包括设备初始化、设备驱动程序和硬件设置等。这些代码主要包括处理器启动代码、时钟初始化、内存初始化以及设备和外设的配置等。 引导部分是U-Boot的核心,其中包括引导过程的各个阶段。首先,它加载引导扇区和主引导程序,其中包括引导加载器。引导加载器根据设备的启动模式选择适当的引导方式。然后,它会加载内核映像和根文件系统,并将控制权转移到内核。 最后,命令部分包含了一系列的命令,用于与用户进行交互。这些命令可以用于启动操作系统、进行系统设置和调试等。U-Boot提供了丰富的命令集,包括boot、setenv、saveenv、printenv等等。 在分析U-Boot源码时,需要了解硬件平台的特性和配置文件。可以根据目标硬件平台的手册和数据手册,对源码进行逐步分析和调试。在分析过程中,可以使用调试工具进行跟踪、断点和单步调试,以便更好地理解源码的执行过程。 总的来说,U-Boot源码的详细分析需要涉及到硬件平台的特性和配置文件,并对引导加载过程和命令解析进行深入研究。通过对U-Boot源码的理解和分析,可以为嵌入式系统的启动和操作提供更好的支持和定制化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值