fastboot命令分析

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

uboot源码学习过程中从网上找到文章,转摘与此。文章出处忘了,见谅!

 fastboot分析:

int do_fastboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{//设置u-boot,kernel,ramdisk ,system,userdata,cache空间地址

if (set_partition_table())



----------------------------------------> // set_partition_table
//主要设置bootloader ramdisk kernel 和fdisk所分的区的起始地址和大小,保存在ptable里面。

/* Bootloader */

strcpy(ptable[pcount].name, "bootloader");

ptable[pcount].start = 0;

ptable[pcount].length = 0;

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;

pcount++;

/* Kernel */

strcpy(ptable[pcount].name, "kernel");

ptable[pcount].start = 0;

ptable[pcount].length = 0;

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;

pcount++;

/* Ramdisk 3M */

strcpy(ptable[pcount].name, "ramdisk");

ptable[pcount].start = 0;

ptable[pcount].length = 0x300000; //3MB,初始值,如果文件大于3M,则会使用文件大小

//写ramdisk的命令类型标志,这里用movi命令来写

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;

pcount++;

-----------------------

/* System */

get_mmc_part_info("0", 2, &start, &count, &pid);

-------------------------

if (pid != 0x83)

goto part_type_error;

strcpy(ptable[pcount].name, "system");

/*

decode_partitionInfo(&mbr[0x1CE], &partInfo);

*block_start = partInfo.block_start;

*block_count = partInfo.block_count;

*part_Id = partInfo.partitionId;

*/ //system 开始的地址

ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

//大小,256M

ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

//写system数据类型的标志,这里用MMC命令来写

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;

pcount++;

/* Data 350M*/

get_mmc_part_info("0", 3, &start, &count, &pid);

if (pid != 0x83)

goto part_type_error;

strcpy(ptable[pcount].name, "userdata");

ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;

pcount++;


/* Cache 100 M */

get_mmc_part_info("0", 4, &start, &count, &pid);

if (pid != 0x83)

goto part_type_error;

strcpy(ptable[pcount].name, "cache");

ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;

pcount++;


/* fat 剩余空间分区,剩余空间分区格式fat?标志为 0c*/

get_mmc_part_info("0", 1, &start, &count, &pid);

if (pid != 0xc)

goto part_type_error;

strcpy(ptable[pcount].name, "fat");

ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;

pcount++;


-------------->
<pre class="cpp" name="code">---------------------------->
//获取fdisk 对system userdata cache分区的大小
int get_mmc_part_info(char *device_name, int part_num, int *block_start, int *block_count, unsigned char *part_Id)
{
int rv;
PartitionInfo partInfo;
unsigned char mbr[512];
//从设备0中读取MBR主分区目录,里面定义了各个分区的信息,和起始,结束扇区
rv = get_mmc_mbr(device_name, mbr);

if(rv !=0)
return -1;

switch(part_num)
{
//剩余容量空间
case 1:
decode_partitionInfo(&mbr[0x1BE], &partInfo);
*block_start = partInfo.block_start;
*block_count = partInfo.block_count;
*part_Id = partInfo.partitionId;
break;
//system 分区表2。fdisk给system分了256M大小
case 2:
decode_partitionInfo(&mbr[0x1CE], &partInfo);
*block_start = partInfo.block_start;
*block_count = partInfo.block_count;
*part_Id = partInfo.partitionId; //83
break;
//userdata 分区
case 3:
decode_partitionInfo(&mbr[0x1DE], &partInfo);
*block_start = partInfo.block_start;
*block_count = partInfo.block_count;
*part_Id = partInfo.partitionId;
break;
//cache分区
case 4:
decode_partitionInfo(&mbr[0x1EE], &partInfo);
*block_start = partInfo.block_start;
*block_count = partInfo.block_count;
*part_Id = partInfo.partitionId;
break;
default:
return -1;
}

return 0;
}
---------------------------->


=================================================================

设置完分区地址空间后,继续

=================================================================

主要初始化usb接口,来等待数据传输。

fastboot_init(&interface)

fastboot_interface = interface;

fastboot_interface->product_name = device_strings[DEVICE_STRING_PRODUCT_INDEX];

fastboot_interface->serial_no = device_strings[DEVICE_STRING_SERIAL_NUMBER_INDEX];

fastboot_interface->nand_block_size = CFG_FASTBOOT_PAGESIZE * 64; //2046*64

fastboot_interface->transfer_buffer = (unsigned char *) CFG_FASTBOOT_TRANSFER_BUFFER;//0x40000000

fastboot_interface->transfer_buffer_size = CFG_FASTBOOT_TRANSFER_BUFFER_SIZE; //272MB

/* Fastboot variables */

#define CFG_FASTBOOT_TRANSFER_BUFFER (0x40000000) //

#define CFG_FASTBOOT_TRANSFER_BUFFER_SIZE (0x11000000) /* 272MB,大于烧录文件就行*/

#define CFG_FASTBOOT_ADDR_KERNEL (0xC0008000)

#define CFG_FASTBOOT_ADDR_RAMDISK (0x30A00000)

#define CFG_FASTBOOT_PAGESIZE (2048) // Page size of booting device

#define CFG_FASTBOOT_SDMMC_BLOCKSIZE (512) // Block size of sdmmc

==================================

static struct cmd_fastboot_interface interface =

{

.rx_handler = rx_handler, //通过此接口烧写

.reset_handler = reset_handler,

.product_name = NULL,

.serial_no = NULL,

.nand_block_size = 0,

.transfer_buffer = (unsigned char *)0xffffffff,

.transfer_buffer_size = 0,

};

---------------------------------------------
cmd_fastboot.c
-----------------------------
//擦除接口 fastboot erase
if (memcmp(cmdbuf, "erase:", 6) == 0)
{
struct fastboot_ptentry *ptn;

ptn = fastboot_flash_find_ptn(cmdbuf + 6);
if (ptn == 0)

------------------------------------------------------------
//获取fat system userdata cache 分区名字
fastboot_ptentry *fastboot_flash_find_ptn(const char *name)
{
unsigned int n;

for (n = 0; n < pcount; n++)
{
/* Make sure a substring is not accepted */
if (strlen(name) == strlen(ptable[n].name))
{
if (0 == strcmp(ptable[n].name, name))
return ptable + n;
}
}
return 0;
}
-------------------------------------------------------

//只有擦除userdata cache fat 这几个功能,kernel u-boot ramdisk 不能擦除
//其实就是调用ext3format fatmot等格式命令 ,需要添加system 擦除命令
char run_cmd[80];
status = 1;
if (!strcmp(ptn->name, "sytem"))
{
sprintf(run_cmd, "ext3format mmc 0:2");
status = run_command(run_cmd, 0);
}
Else if (!strcmp(ptn->name, "userdata"))
{
sprintf(run_cmd, "ext3format mmc 0:3");
status = run_command(run_cmd, 0);
}
else if (!strcmp(ptn->name, "cache"))
{
sprintf(run_cmd, "ext3format mmc 0:4");
status = run_command(run_cmd, 0);
}
else if (!strcmp(ptn->name, "fat"))
{
sprintf(run_cmd, "fatformat mmc 0:1");
status = run_command(run_cmd, 0);
}
=======================================================

Flash what was downloaded */
if (memcmp(cmdbuf, "flash:", 6) == 0)
{
if (download_bytes == 0)
{
sprintf(response, "FAILno image downloaded");
ret = 0;
goto send_tx_status;
}
//从此句开始判断 kernel。 ramdisk system,获取ptable
ptn = fastboot_flash_find_ptn(cmdbuf + 6);
----------------------
if ((download_bytes > ptn->length) && (ptn->length != 0) &&
!(ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV))
{ //注意。system写,会出现这个信息。注意检查
//分析,只有当system文件大小小于分区大小时,是不会进入的
sprintf(response, "FAILimage too large for partition");
/* TODO : Improve check for yaffs write */
}
else
{
/* Normal case */
if (write_to_ptn(ptn, (unsigned int)interface.transfer_buffer, download_bytes))
{
printf("flashing '%s' failed\n", ptn->name);
sprintf(response, "FAILfailed to flash partition");
}
else
{
printf("partition '%s' flashed\n", ptn->name);
sprintf(response, "OKAY");
}
}
-------------------------------------------

/* Kernel */

strcpy(ptable[pcount].name, "kernel");

ptable[pcount].start = 0;

ptable[pcount].length = 0;

ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;

pcount++;


#######################################################################
static int write_to_ptn(struct fastboot_ptentry *ptn, unsigned int addr, unsigned int size)
{

#elif defined(CFG_FASTBOOT_SDMMCBSP)
{
int ret = 1;
char device[32], part[32];
char start[32], length[32], buffer[32];

char *argv[6] = { NULL, "write", NULL, NULL, NULL, NULL, };
int argc = 0;
//区别出kernel u-boot ,当ramdisk,system等文件大于分区大小时。
if ((ptn->length != 0) && (size > ptn->length))
{
printf("Error: Image size is larger than partition size!\n");
return 1;
}

//add by <a href="mailto:xiao@2012-04-16">xiao@2012-04-16</a> : 只获取实际文件大小,因下面烧写文件时,是根据分区大小来烧写文件。对于几百MB的空间来说实在是太大和耗时间。
real_len = (size /CFG_FASTBOOT_SDMMC_BLOCKSIZE + 1);

//写system userdata cache fat 接口
if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD)
{
argv[2] = device;
argv[3] = buffer;
argv[4] = start;
argv[5] = length;
sprintf(device, "mmc %d", 1);
sprintf(buffer, "0x%x", addr);
sprintf(start, "0x%x", (ptn->start / CFG_FASTBOOT_SDMMC_BLOCKSIZE));
//sprintf(length, "0x%x", (ptn->length / CFG_FASTBOOT_SDMMC_BLOCKSIZE));
//add by <a href="mailto:xiao@2012-04-16">xiao@2012-04-16</a> :
#ifndef CONFIG_EMMC_INAND
sprintf(length, "0x%x", (ptn->length / CFG_FASTBOOT_SDMMC_BLOCKSIZE));
#else
sprintf(length, "0x%x", real_len);
#endif
//mmc 命令
ret = do_mmcops(NULL, 0, 6, argv);
}//写u-boot kernel ramdisk接口
else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD)
{
argv[2] = part; //指向part
argv[3] = buffer; //指向buffer

argc = 4;

/* use the partition name that can be understood by a command, movi */
if (!strcmp(ptn->name, "bootloader"))
{
// part 改为 u-boot 名称 ,为movi 读写作区别
strncpy(part, "u-boot", 7);
}
else if (!strcmp(ptn->name, "ramdisk"))
{
//改为rootfs 名称,为movi 读写作区别
strncpy(part, "rootfs", 7);
//指向length,
argv[4] = length;
//此时,ramdisk 大小为下载的文件实际大小。 download_bytes
sprintf(length, "0x%x",
((size + CFG_FASTBOOT_SDMMC_BLOCKSIZE - 1)
/ CFG_FASTBOOT_SDMMC_BLOCKSIZE ) * CFG_FASTBOOT_SDMMC_BLOCKSIZE);
argc++;
}
else /* kernel, fwbl1 */
{ //kernel 名称
argv[2] = ptn->name;
}
//把DRAM1 = 0x40000000 地址给buffer
sprintf(buffer, "0x%x", addr);
//用movi命令写kernel ,ramdisk u-boot数据
ret = do_movi(NULL, 0, argc, argv);

/* the return value of do_movi is different from usual commands. Hence the followings. */
ret = 1 - ret;
}

return ret;
}

===========================

cmd_mmc.c

====================

注意:此命令 movi也会调用,mmc也调用。所以u-boot

kernel ramdisk system等多是调用此接口

也就是do_movi调用 do_mmcops命令来读写

int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int rc = 0;

switch (argc) {


default: /* at least 5 args */

if (strcmp(argv[1], "write") == 0) {
int dev = simple_strtoul(argv[2], NULL, 10);
void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
u32 cnt = simple_strtoul(argv[5], NULL, 10);
int blk = simple_strtoul(argv[4], NULL, 10);
u32 n;
u32 written_cnt;
u32 cnt_to_write;
void *addr_to_write = addr;
struct mmc *mmc = find_mmc_device(dev);


if (!mmc)
return 1;

//重新初始化设备。
rc = mmc_init(mmc);
if(rc)
return rc;

n = 0;
addr_to_write = addr;
do {
if (cnt - n > MAXIMUM_BLOCK_COUNT)
cnt_to_write = MAXIMUM_BLOCK_COUNT;
else
cnt_to_write = cnt - n;

written_cnt = mmc->block_dev.block_write(dev, blk, cnt_to_write, addr_to_write);
n += written_cnt;
blk += written_cnt;
addr_to_write += written_cnt * 512;
if(cnt_to_write != written_cnt) {
printf("%d blocks written: %s\n",
n, "ERROR");
return -1;
}
} while(cnt > n);

printf("%d blocks written: %s\n",
n, "OK");
return 0;
} else {
printf("Usage:\n%s\n", cmdtp->usage);
rc = 1;
}

return rc;
}
}

---------------------------------------------


---------------------------------------------
分析 ret = do_movi(NULL, 0, argc, argv);

分析 u-boot kernel ramdisk烧写!!!

int do_movi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
char *cmd;
ulong addr, start_blk, blkcnt;
uint rfs_size;
char run_cmd[100];
uint rw = 0, attribute = 0;
int i;
member_t *image;
struct mmc *mmc;
//此处节点为 0
int dev_num = 0;

cmd = argv[1];
switch (cmd[0]) {

case 'r':
rw = 0; /* read case */
break;
case 'w':
rw = 1; /* write case */
break;
default:
goto usage;
}
//获取,文件名称
cmd = argv[2];


switch (cmd[0]) {
//u-boot
case 'u':
if (argc != 4)
goto usage;
attribute = 0x2;
//地址为DRAM1 = 0x40000000 此处的地址
addr = simple_strtoul(argv[3], NULL, 16);
break;
//kernel
case 'k':
if (argc != 4)
goto usage;
attribute = 0x4;
//地址为DRAM1 = 0x40000000 此处的地址
addr = simple_strtoul(argv[3], NULL, 16);
break;
//rootfs
case 'r':
if (argc != 5)
goto usage;
attribute = 0x8;
//地址为DRAM1 = 0x40000000 此处的地址
addr = simple_strtoul(argv[3], NULL, 16);
break;
default:
goto usage;
}
//此处查找节点 0
mmc = find_mmc_device(dev_num);
//重新注册
mmc_init(mmc);
/* u-boot r/w */
//bl2 后半部分区域: u-boot 大小 512K
if (attribute == 0x2) {
//rw =1 表示写。0:表示读
if (rw) {
//先去写BL1部分
start_blk = raw_area_control.image[1].start_blk;
blkcnt = raw_area_control.image[1].used_blk;
printf("Writing BL1 to sector %ld (%ld sectors).. ",
start_blk, blkcnt);
//16M + 1K -- 16M + 1K + 8K
//从dram1 上吧数据写入BL1 区域
movi_write_bl1(addr);
}
//找到BL2后半部分位置。
for (i=0, image = raw_area_control.image; i<15; i++) {
if (image[i].attribute == attribute)
break;
}
//image[3] 大小512k
start_blk = image[i].start_blk;
blkcnt = image[i].used_blk;
printf("%s bootloader.. %ld, %ld ", rw ? "writing":"reading",
start_blk, blkcnt);

//使用mmc 命令来烧写 bl2 后半部分
sprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",
rw ? "write":"read",
addr, start_blk, blkcnt);
//mmc write 0 0x40000000 star len
//do_mmcops 写的时候,会根据argv[2]来获取设备号。
//这里 mmc write 0 指定了设备号了。
//16M + 9K +16K -- 16M + 25K +512K
run_command(run_cmd, 0);
printf("completed\n");
return 1;
}
//烧写内核 16M + 25K +512K -- 16M + 25K +512K + 4MB
/* kernel r/w */
if (attribute == 0x4) {
//找到内核区域 image[4]
for (i=0, image = raw_area_control.image; i<15; i++) {
if (image[i].attribute == attribute)
break;
}
//
start_blk = image[i].start_blk;
//大小为4MB
blkcnt = image[i].used_blk;

printf("%s kernel.. %ld, %ld ", rw ? "writing" : "reading",
start_blk, blkcnt);
//命令 mmc write 0 0x40000000 star len
sprintf(run_cmd, "mmc %s 0 0x%lx 0x%lx 0x%lx",
rw ? "write" : "read", addr, start_blk, blkcnt);
//写入到设备 0中
run_command(run_cmd, 0);

printf("completed\n");
return 1;
}
//根文件系统烧写 16M + 25K +512K + 4MB - 16M + 25K +512K + 4MB +26MB
/* root file system r/w */
if (attribute == 0x8) {
//获取rootfs的实际文件大小 download_bytes
rfs_size = simple_strtoul(argv[4], NULL, 16);
//获取rootfs 区域 image[5]
for (i=0, image = raw_area_control.image; i<15; i++) {
if (image[i].attribute == attribute)
break;
}

start_blk = image[i].start_blk;
//一个块512的大小对齐
blkcnt = rfs_size/MOVI_BLKSIZE +
((rfs_size&(MOVI_BLKSIZE-1)) ? 1 : 0);
image[i].used_blk = blkcnt;
printf("%s RFS.. %ld, %ld ", rw ? "writing":"reading",
start_blk, blkcnt);
//写rootfs 16M + 25K +512K + 4MB - 16M + 25K +512K + 4MB +26MB
sprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",
rw ? "write":"read",
addr, start_blk, blkcnt);
run_command(run_cmd, 0);
printf("completed\n");
return 1;
}

return 1;

usage:
printf("Usage:\n%s\n", cmdtp->usage);
return -1;
}


#########################################################

分析:cmd_movi.c

#ifdef CONFIG_CMD_MOVINAND
init_raw_area_table(&host->block_dev);

#endif

#########################################################
int init_raw_area_table (block_dev_desc_t * dev_desc)
{
//找到设备
struct mmc *host = find_mmc_device(dev_desc->dev);
//第一次确实不相等
if (raw_area_control.magic_number != MAGIC_NUMBER_MOVI) {
int i = 0;
member_t *image;
u32 capacity;

if (host->high_capacity) {
capacity = host->capacity;
#ifdef CONFIG_S3C6410
if(IS_SD(host))
capacity -= 1024;
#endif
} else {
//注意此处,块大小 > 512时
capacity = host->capacity * (host->read_bl_len / MOVI_BLKSIZE);
}

//读取是否有raw分区表。
dev_desc->block_read(dev_desc->dev,
capacity - (eFUSE_SIZE/MOVI_BLKSIZE) - 1,
1, &raw_area_control);
if (raw_area_control.magic_number == MAGIC_NUMBER_MOVI) {
return 0;
}
//没有raw分区表就增加一个
/* add magic number */
raw_area_control.magic_number = MAGIC_NUMBER_MOVI;
//从bl1 开始放
/* init raw_area will be 16MB */
//一个块大小512,的倍数表示起始的块地址,也就是偏移16M?
raw_area_control.start_blk = 16*1024*1024/MOVI_BLKSIZE;
//0.5k 的efuse 和 0.5k的recvers 总大小块
raw_area_control.total_blk = capacity;

raw_area_control.next_raw_area = 0;
strcpy(raw_area_control.description, "initial raw table");
//指向image
image = raw_area_control.image;
/* image 0 should be fwbl1 */
//image【0】 我们没必要有。
#######################################
/* image 1 should be bl2 */
//第一次写完了efuse后,在它后面写bl2.所以使用efuse作为起始块地址。
image[1].start_blk = (eFUSE_SIZE/MOVI_BLKSIZE);
//8K 的块大小个数
image[1].used_blk = MOVI_BL1_BLKCNT;
//大小8K
image[1].size = SS_SIZE;

image[1].attribute = 0x1;
//标注此区为u-boot parted
strcpy(image[1].description, "u-boot parted");
#######################################################
//接下来保存环境参数
/* image 2 should be environment */
//上一个的结束块地址
image[2].start_blk = image[1].start_blk + MOVI_BL1_BLKCNT;
//使用了16k的块大小个数
image[2].used_blk = MOVI_ENV_BLKCNT;
//大小16K
image[2].size = CFG_ENV_SIZE;

image[2].attribute = 0x10;
//标注此区为 environment
strcpy(image[2].description, "environment");
dbg("env: %d\n", image[2].start_blk);
###########################################################
/* image 3 should be bl2 */
//开始放BL2
image[3].start_blk = image[2].start_blk + MOVI_ENV_BLKCNT;
//512KB的块大小个数
image[3].used_blk = MOVI_BL2_BLKCNT;
//512KB
image[3].size = PART_SIZE_BL;
image[3].attribute = 0x2;
//标注此区为u-boot
strcpy(image[3].description, "u-boot");
dbg("bl2: %d\n", image[3].start_blk);
####################################################
/* image 4 should be kernel */
//这里接下来存放内核信息
image[4].start_blk = image[3].start_blk + MOVI_BL2_BLKCNT;
//4M的块大小个数
image[4].used_blk = MOVI_ZIMAGE_BLKCNT;
//大小4M
image[4].size = PART_SIZE_KERNEL;

image[4].attribute = 0x4;
//标注此区为kernel
strcpy(image[4].description, "kernel");
dbg("knl: %d\n", image[4].start_blk);
######################################################
/* image 5 should be RFS */
//接下来放rootfs
image[5].start_blk = image[4].start_blk + MOVI_ZIMAGE_BLKCNT;
//26M的块大小
image[5].used_blk = MOVI_ROOTFS_BLKCNT;
//26M大小
image[5].size = PART_SIZE_ROOTFS;
image[5].attribute = 0x8;
strcpy(image[5].description, "rfs");
dbg("rfs: %d\n", image[5].start_blk);

for (i=6; i<15; i++) {
raw_area_control.image[i].start_blk = 0;
raw_area_control.image[i].used_blk = 0;
}

------------------------------

总结一下:

raw分区:

16M -- 16M + 1K: efuse区域 标示:initial raw table

image[1] , 0x1

16M + 1K -- 16M + 1K + 8K:bl2前半部分区域标示: u-boot parted

image[2] , 0x10

16M + 9K -- 16M + 9K +16K :环境参数保存区域:environment

image[3], 0x2

16M + 9K +16K -- 16M + 25K +512K :bl2后半部分区域: u-boot

image[4[, 0x4

16M + 25K +512K -- 16M + 25K +512K + 4MB : kernel区域: kernel

image[5],0x8

16M + 25K +512K + 4MB - 16M + 25K +512K + 4MB +26MB

rootfs区域,表示: rfs

image[5].attribute = 0x8;

方便烧写对应:

case 'r':

if (argc != 5)

goto usage;

attribute = 0x8;

###############################################################

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
运行 清除fastboot进磁盘操作.bat 接着电脑自动安装驱动(不会自动安装的驱动路径在MiFlash安装目录下) 这时就进入磁盘模式了,接着就可以用DiskGenius,分区助手专业版和MiFlash进行操作了(还可以用DiskGenius做数据备份) 用MiFlash刷机(目的是为了还原删除的aboot也可以用我提供的备份还原)刷完后关MiFlash,可别拔掉手机哦 呵呵 补充:没用miflash刷机的一定要要还原aboot分区要不后面改好了启动不来(一定要刷机要不你自己备份的也是清除的分区里面没数据是没用的) 3. 打开DiskGenius要操作的磁盘是QualcommMMCStorage(里面有27个分区的就是) 认为有必要的备份好整个分区表和分区(极力推荐备份)。 也可以用我提供的备份(有些分区是各手机私有的不能用我的备份分别是ssd dbi bk1 bk2 modemst1 modemst2 fsc bk3 fsg bk4 bk5 这11个分区同时也是不可动的)。 以下是两种分区方法 选其中一种即可 1。 用分区助手无损移动分区 2。 用DiskGenius删分区再重建 第一种: 方法删除 system1 boot1 modem1 userdata四个分区就可以了。(认为有必要的懂得可以删其他分区) 用分区助手移动分区把未分配空间集合在右边也就是userdata分区那一边保存修改(提交)然后用DiskGenius新建分区userdata把剩下的空间都给它 文件系统类型linux data partion 勾上对齐到下列扇区数的整数倍数值是8 详细里面的分区名userdata 再点上无盘符。 分区建好保存更改(分区名一定要是userdata)。 换到分区助手格式化userdata分区 格式ext3其他默认(可以开机后进fastboot命令格式化此分区命令fastboot format userdata)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值