【Emuelec】emmc刷写工具ceemmc原理分析

ceemmc是emuelec官方闭源的刷入emmc的工具,但在4.3以后就官方不提供了,好在旧版本的ceemmc是二进制程序,放到新系统上也能用,于是乎分析其工作原理,自己折腾,自己将4.5游戏系统刷入emmc的一点经验总结(单系统模式)

1.根据emmc中现有的分区表分析现有分区状态和可用空间,并且迁移cache、data、code等分区,并计算出创建CE_FLASH、CE_STORAGE分区所需的偏移量(4.3版本的ceemmc下,bootloader占用4M、 env占用8M、 misc占用8M、  logo占用8M、dtbo占用8M、 reserved占用64MB、CE_FLASH占用2GB,CE_STORAGE占用剩余的所有空间

2.在emmc中创建包含CE_FLASH、CE_STORAGE的新的分区表

因为ceemmc是不开源的,看不到源码,所以以上2步是通过二进制逆向分析了解的(可能理解不全面)

这里的关键是创建一张新的分区表以替换/dev/reserved中旧的分区表信息(可能还有别的辅助步骤,比如修改dtb信息),使设备开机时就会在/dev目录虚拟出CE_FLASH、CE_STORAGE两个disk设备,然后在开机配置选项文件(cfg_load)中指定启动disk设备为CE_FLASH、CE_STORAGE就可以实现emmc开机了,参考代码如下:

 v6 = fopen(a2, "rb+");
  if ( v6 )
  {
    v5 = calloc(1LL, 0x40000LL);
    if ( v5 )
    {
      for ( i = 0; i <= 1; ++i )
      {
        if ( (unsigned int)fseek(v6, (i + 16LL) << 18, 0LL) )
        {
          puts("Error seek file!");
          free(v5);
          fclose();
          return 0xFFFFFFFFLL;
        }
        if ( fread(v5, 0x40000LL, 1LL, v6) != 1 )
        {
          puts("Error reading file!");
          free(v5);
          fclose();
          return 0xFFFFFFFFLL;
        }
        if ( (signed int)sub_402520(v5, (__int64)"/partitions") < 0 )
        {
          printf("Could not remove node '%s' from dtb%d!\n", "/partitions", i);
          free(v5);
          fclose();
          return 0xFFFFFFFFLL;
        }
        if ( (unsigned int)fseek(v6, (i + 16LL) << 18, 0LL) )
        {
          puts("Error seek file!");
          free(v5);
          fclose();
          return 0xFFFFFFFFLL;
        }
        if ( fwrite(v5, 0x40000LL, 1LL, v6) != 1 )
        {
          puts("Error writing file!");
          free(v5);
          fclose();
          return 0xFFFFFFFFLL;
        }
      }
 v15 = *(_DWORD *)a1;
  if ( (unsigned int)strcmp((const char *)(a1 + 262128), "A~D") )
  {
    printf("Error dtb magic: %s!\n", v4 + 262128);
    return 0xFFFFFFFFLL;
  }
  if ( (unsigned __int16)v15 == 35615 )
  {
    v17 = (int *)calloc(1LL, 5242880LL);
    if ( !v17 )
    {
      puts("malloc failed for gzip_buf!");
      return 0xFFFFFFFFLL;
    }
    v11 = sub_4097A8(v17, 5242880LL, v16, &v5);
    if ( (v11 & 0x80000000) != 0 )
    {
      printf("Failed to decompress gzipped dtb: %d!\n", v11);
      free(v17);
      return 0xFFFFFFFFLL;
    }
    v16 = (__int64)v17;
    v15 = *v17;
  }
  if ( v15 == -302117424 )
  {
    sub_401DE0(v16, v3);
    sub_40B95C(v16);
    *(_DWORD *)(v4 + 262140) = sub_401E48(v4);
  }
  else if ( v15 == 1598836033 )
  {
    v13 = 0;
    v10 = *(_DWORD *)(v16 + 4);
    if ( v10 == 1 )
    {
      v13 = 4;
    }
    else if ( v10 == 2 )
    {
      v13 = 16;
    }
    v9 = 3 * v13;
    v8 = 3 * v13 + 8;
    v12 = *(_DWORD *)(v16 + 8);
    for ( i = 0; v12 > i; ++i )
    {
      v7 = *(_DWORD *)(v16 + i * v8 + (unsigned __int64)v9 + 12);
      if ( *(_DWORD *)(v16 + v7) == -302117424 )
      {
        sub_401DE0(v16 + v7, v3);
        sub_40B95C(v16 + v7);
      }
    }
    *(_DWORD *)(v4 + 262140) = sub_401E48(v4);
  }
  if ( v17 )
  {
    v11 = sub_40976C(v4, (__int64)&v6, (__int64)v17, v5);
    if ( (v11 & 0x80000000) != 0 )
    {
      printf("Failed to compress data to dtb: %d!\n", v11);

3.挂载CE_FLASH、CE_STORAGE分区,并复制相应的数据:

以下以创建挂载CE_FLASH为例子

losetup --find 找出可用loop设备,比如loop1

将分区挂载成loop设备:

 losetup /dev/loop1 /dev/mmcblk0 --offset <偏移量>

格式化分区

mkfs.vfat -n "CE_FLASH" /dev/loop1; sync

 参考代码

 memset(&v11, 0LL, 10240LL);
  printf("\nStarting to format the new '%s' partition...\n", v10);
  if ( v7 && v6 )
    snprintf(
      &v11,
      10240LL,
      "mke2fs -F -L \"%s\" -t ext4 -m 0 \"%s\" -O %s -E offset=%lld %lldm; sync",
      v10,
      v9,
      v8,
      v7,
      v6 >> 20);
  else
    snprintf(&v11, 10240LL, "mke2fs -F -L \"%s\" -t ext4 -m 0 \"%s\" -O %s; sync", v10, v9, v8);
  if ( (signed int)sub_402C3C(&v11, 0LL, stdout) >= 0 )
    return 0LL;
  printf("Error executing cmd '%s'\n", &v11);
  return 0xFFFFFFFFLL;
}

创建挂载目标目录 

mkdir -p /media/CE_FLASH

 挂载

mount -o rw,loop /dev/loop1 /media/CE_FLASH

拷贝数据

rsync -ah --info=progress2 /flash/ /media/CE_FLASH

这样就完成了从外置设备/flash中拷贝数据到emmc中的CE_FLASH的工程

你可能感兴趣的:(linux,emuelec,arm逆向,arm,c语言)