Chinaunix首页 | 论坛 | 博客

Go

  • 博客访问: 227632
  • 博文数量: 67
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 783
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-12 16:29
文章分类

全部博文(67)

文章存档

2015年(1)

2014年(47)

2013年(19)

我的朋友

分类: Android平台

2014-07-25 14:08:09

转载:http://blog.chinaunix.net/uid-26009923-id-4068594.html


一.  mkimage.sh

1. android目录下的mkimage.sh
  1. #!/bin/bash
  2. set -e

  3. . build/envsetup.sh >/dev/null && setpaths

  4. export PATH=$ANDROID_BUILD_PATHS:$PATH

  5. TARGET="withoutkernel"
  6. if [ "$1"!= ""]; then
  7.          TARGET=$1
  8. fi
  9. rm -rf rockdev/Image
  10. mkdir -p rockdev/Image

 //在init.rk30board.rc中搜索字符串mtd@system,发现其分区类型为ext4

  1. FSTYPE=`grep 'mtd@system' $OUT/root/init.rk30board.rc | head -n 1 | awk '{ print $2 }'`
  2. if [ "$FSTYPE" = "" ]; then
  3.        FSTYPE=`grep 'mtd@system' $OUT/root/init.rc | head -n 1 | awk '{ print $2 }'`
  4. fi
  5. echo system filesysystem is $FSTYPE

  6. BOARD_CONFIG=device/rockchip/rk30sdk/device.mk
  7. //KERNLE_SRC_PATH为空
  8. KERNEL_SRC_PATH=`grep TARGET_PREBUILT_KERNEL ${BOARD_CONFIG} |grep "^\s*TARGET_PREBUILT_KERNEL *:= *[\w]*\s" |awk '{print $3}'`
  9. [ $(id -u) -eq 0 ] || FAKEROOT=fakeroot

  10. BOOT_OTA="ota"
  11. echo "TARGET=$TARGET"
  12. [ $TARGET != $BOOT_OTA -a $TARGET != "withoutkernel" ] && echo "unknow target[${TARGET}],exit!" && exit 0

  13.     if [ ! -f $OUT/kernel ]   //这个文件存在不执行以下
  14.     then
  15.      echo "kernel image not fount![$OUT/kernel] "
  16.         read -"copy kernel from TARGET_PREBUILT_KERNEL[$KERNEL_SRC_PATH] (y/n) n to exit?"
  17.         if [ "$REPLY" == "y" ]
  18.         then
  19.             [ -f $KERNEL_SRC_PATH ] || \
  20.                 echo -"fatal! TARGET_PREBUILT_KERNEL not eixit! " || \
  21.                 echo -"check you configuration in [${BOARD_CONFIG}] " || exit 0

  22.             cp ${KERNEL_SRC_PATH} $OUT/kernel

  23.         else
  24.             exit 0
  25.         fi
  26.     fi

   //1.boot.img的生成过程

  1. if [ $TARGET == $BOOT_OTA ]   //TARGET=withoutkernel, BOOT_OTA=ota不相等,执行else
  2. then
  3.     echo "make ota images... "
  4.     echo -"create boot.img with kernel... "
  5.     [ -d $OUT/root ] && \
  6.     mkbootfs $OUT/root | minigzip > $OUT/ramdisk.img && \
  7.     mkbootimg --kernel $OUT/kernel --ramdisk $OUT/ramdisk.img --output $OUT/boot.img && \
  8.     cp -a $OUT/boot.img rockdev/Image/
  9.     echo "done."
  10. else
  11.     echo -"create boot.img without kernel... "
  12.     [ -d $OUT/root ] && \                                    //目录out/target/product/rk30sdk/root存在
  13.     mkbootfs $OUT/root | minigzip > $OUT/ramdisk.img && \    //1.将root下的每个文件加上cpio头+每个文件的内容,打包成cpios格式
  14.     rkst/mkkrnlimg $OUT/ramdisk.img rockdev/Image/boot.img   //2. 将这个cpio文件用gzip压缩后写到文件ramdisk.img中, //3. mkkrnlimg会对ramdisk.img加上8个字节的头标志 4b 52 4e 4c e9 96 0f 00 ,尾部加上4个字节 02 6e e6 55。

  15.     echo "done."                                            
  16. fi
 
out/target/..../kernel   多 kernel/kernel.img  首4b 52 4e 4c 24 d0 6c 00  尾:fb 90 e5 ca 
################boot.img = (out/ramdisk.img + mkkrnling加入头尾标)
                            =>out/ramdisk.img = out/root压缩.
                                                 =>out/root =空文件夹(data,dev,proc,sys,system)+res(里面几张电源图片)+sbin(里面带adbd,e2fsck mkdosfs mke2fs resize2fs ueventd,watchdogd等二进制文件) +charger,init可执行文件+一些文件,具体如下:
-rwxr-xr-x  1 android android 264100 2014-07-22 18:01 charger*
drwxr-xr-x  2 android android   4096 2014-07-22 16:10 data/
-rw-r--r--  1 android android    905 2014-07-22 16:13 default.prop
drwxr-xr-x  2 android android   4096 2014-07-22 16:10 dev/
-rwxr-xr-x  1 android android   7667 2014-07-22 17:05 drmboot.ko*
-rwxr-xr-x  1 android android 113644 2014-07-22 18:01 init*
-rw-r--r--  1 android android   2487 2014-07-22 17:05 init.goldfish.rc
-rwxr-xr-x  1 android android  20012 2014-07-24 17:27 init.rc*
-rw-r--r--  1 android android    394 2014-07-22 17:05 init.rk30board.bootmode.emmc.rc
-rw-r--r--  1 android android    327 2014-07-22 17:05 init.rk30board.bootmode.unknown.rc
-rwxr-xr-x  1 android android  11770 2014-07-22 17:05 init.rk30board.rc*
-rwxr-xr-x  1 android android   6122 2014-07-22 17:05 init.rk30board.usb.rc*
-rw-r--r--  1 android android   1795 2014-07-22 17:05 init.trace.rc
-rw-r--r--  1 android android   2562 2014-07-22 17:05 init.usb.rc
drwxr-xr-x  2 android android   4096 2014-07-22 16:10 proc/
drwxr-xr-x  3 android android   4096 2014-07-22 17:06 res/
-rwxr-xr-x  1 android android 150405 2014-07-22 17:05 rk30xxnand_ko.ko.3.0.36+*
-rwxr-xr-x  1 android android 145284 2014-07-22 17:05 rk30xxnand_ko.ko.3.0.8+*
drwxr-xr-x  2 android android   4096 2014-07-22 18:01 sbin/
drwxr-xr-x  2 android android   4096 2014-07-22 16:10 sys/
drwxr-xr-x  2 android android   4096 2014-07-22 16:10 system/
-rw-r--r--  1 android android    272 2014-07-22 17:05 ueventd.goldfish.rc
-rwxr-xr-x  1 android android   4547 2014-07-22 17:05 ueventd.rc*
-rwxr-xr-x  1 android android   3106 2014-07-22 17:05 ueventd.rk30board.rc*

总结:boot.img由 out/.../root/里面的文件通过minizip压缩后,在经过rkkrnlimg 加入头尾标志而生成的。
   boot_ota.img则多一个out/../kernel 文件。


  1.     //2.recovery.img的生成过程
  2.     echo -"create recovery.img with kernel... "
  3.     [ -d $OUT/recovery/root ] && \
  4.     mkbootfs $OUT/recovery/root | minigzip > $OUT/ramdisk-recovery.img && \
  5.     mkbootimg --kernel $OUT/kernel --ramdisk $OUT/ramdisk-recovery.img --output $OUT/recovery.img && \
  6.     cp -a $OUT/recovery.img rockdev/Image/
  7.     echo "done."

    总结:recovery.img 由out/.../recovery/root 压缩并加入 out/.../kernel 得到的。 而recovery/root和 上面的root/里面对比多了几个文件而已。



     // misc.img 的生成过程
  1.     echo -"create misc.img.... "
  2.     cp -a rkst/Image/misc.img rockdev/Image/misc.img
  3.     cp -a rkst/Image/pcba_small_misc.img rockdev/Image/pcba_small_misc.img
  4.     cp -a rkst/Image/pcba_whole_misc.img rockdev/Image/pcba_whole_misc.img
  5.     echo "done."
  6.  misc.img 一般用来游戏或软件的图像文件

  7.    
  8.    //3.system.img的生成过程

  9. if [ -d $OUT/system ]
  10. then
  11.     echo -"create system.img... "
  12.     if [ "$FSTYPE" = "cramfs" ]
  13.     then
  14.         chmod -R 777 $OUT/system
  15.         $FAKEROOT mkfs.cramfs $OUT/system rockdev/Image/system.img
  16.     elif [ "$FSTYPE" = "squashfs" ]
  17.     then
  18.         chmod -R 777 $OUT/system
  19.         mksquashfs $OUT/system rockdev/Image/system.img -all-root >/dev/null
  20.     elif [ "$FSTYPE" = "ext3" ] || [ "$FSTYPE" = "ext4" ]
  21.     then                                                      //ext3或ext4的生成过程
  22.         delta=5120
  23.         num_blocks=`du -sk $OUT/system | tail -n1 | awk '{print $1;}'`
  24.         num_blocks=$(($num_blocks + $delta))

  25.         num_inodes=`find $OUT/system | wc -l`
  26.         num_inodes=$(($num_inodes + 500))

  27.         ok=0
  28.         while [ "$ok" = "0" ]; do
  29.             genext2fs --d $OUT/system -b $num_blocks -N $num_inodes -m 0 rockdev/Image/system.img >/dev/null 2>&&& \
  30.             tune2fs --L system ---i 0 rockdev/Image/system.img >/dev/null 2>&&& \
  31.             ok=|| num_blocks=$(($num_blocks + $delta))
  32.         done
  33.         e2fsck -fy rockdev/Image/system.img >/dev/null 2>&|| true

  34.         delta=1024
  35.         num_blocks=`resize2fs -P rockdev/Image/system.img 2>&| tail -n1 | awk '{print $7;}'`
  36.         rm -f rockdev/Image/system.img
  37.         ok=0
  38.         while [ "$ok" = "0" ]; do
  39.             genext2fs --d $OUT/system -b $num_blocks -N $num_inodes -m 0 rockdev/Image/system.img >/dev/null 2>&&& \
  40.             tune2fs -O dir_index,filetype,sparse_super --L system ---i 0 rockdev/Image/system.img >/dev/null 2>&&& \
  41.             ok=|| num_blocks=$(($num_blocks + $delta))
  42.         done
  43.         e2fsck -fyD rockdev/Image/system.img >/dev/null 2>&|| true
  44.     else
  45.         mkdir -p rockdev/Image/2k rockdev/Image/4k
  46.         mkyaffs2image -c 2032 -s 16 -f $OUT/system rockdev/Image/2k/system.img
  47.         mkyaffs2image -c 4080 -s 16 -f $OUT/system rockdev/Image/4k/system.img
  48.     fi
  49.     echo "done."
  50. fi

  51. chmod a+-R rockdev/Image/


总结:system.img 用的就是out/..../system/ 里面的的。1、先用genext2fs 将out/.../system/文件夹制作成一个ext2文件系统镜像。2、tune2fs是调整和查看ext2/ext3文件系统的文件系统参数,Windows下面如果出现意外断电死机情况,下次开机一般都会出现系统自检。Linux系统下面也有文件系统自检,而且是可以通过tune2fs命令,自行定义自检周期及方式。
3、
e2fsck检查ext2、ext3、ext4等文件系统的正确性
2. mkbootfs分析
mkbootfs在system/core/cpio/mkbootfs.c中
mkbootfs $OUT/root
    main 
       --> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
        --> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
  1. static void _archive_dir(char *in, char *out, int ilen, int olen)
  2. {
  3.     int i, t;
  4.     DIR *d;
  5.     struct dirent *de;
  6.     DIR* d = opendir(in);  //打开目录

  7.     int size = 32;
  8.     int entries = 0;
  9.     char** names = malloc(size * sizeof(char*)); //每次分配32个文件名的内存
  10.     //将./out/target/product/rk30sdk/root目录下所有的文件名存在name数组中
  11.     while((de = readdir(d)) != 0){
  12.         if(de->d_name[0] == '.') continue;       //跳过.目录
  13.         if(!strcmp(de->d_name, "root")) continue; //排除root,这是为了什么?
  14.         if (entries >= size) {
  15.           size *= 2;                 //如果超出32个文件名,则再多分配32*2个,依次类推        
  16.           names = realloc(names, size * sizeof(char*));  //realloc,又学习了一招
  17.         }
  18.         names[entries] = strdup(de->d_name);   //strdup可以分配内存并复制
  19.         ++entries;
  20.     }
  21.     //对name数组中的文件名进行排序
  22.     qsort(names, entries, sizeof(char*), compare);   

  23.     for (= 0; i < entries; ++i) {
  24.         t = strlen(names[i]);
  25.         in[ilen] = '/';
  26.         memcpy(in + ilen + 1, names[i], t + 1);

  27.         if(olen > 0) {                  //out
  28.             out[olen] = '/';
  29.             memcpy(out + olen + 1, names[i], t + 1);
  30.             _archive(in, out, ilen + t + 1, olen + t + 1);
  31.         } else {
  32.             memcpy(out, names[i], t + 1);       //将文件名复制到out中
  33.             _archive(in, out, ilen + t + 1, t)//将这个文件打包到ramdisk.img中
  34.         }

  35.         in[ilen] = 0;
  36.         out[olen] = 0;

  37.         free(names[i]);
  38.     }
  39.     free(names);
  40. }
mkbootfs $OUT/root
    main 
       --> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
        --> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
        --> _archive    //对普通文件 目录  链接分开处理
  1. static void _archive(char *in, char *out, int ilen, int olen)
  2. {
  3.     struct stat s;
  4.     if(S_ISREG(s.st_mode)){       //1.对普通文件的处理
  5.         int fd = open(in, O_RDONLY);
  6.         char* tmp = (char*) malloc(s.st_size);
  7.         read(fd, tmp, s.st_size);
  8.         _eject(&s, out, olen, tmp, s.st_size);
  9.         free(tmp);
  10.         close(fd);
  11.     } else if(S_ISDIR(s.st_mode)) {  //2.对目录的处理
  12.         _eject(&s, out, olen, 0, 0);
  13.         _archive_dir(in, out, ilen, olen);
  14.     } else if(S_ISLNK(s.st_mode)) {  //3.对链接文件的处理
  15.         char buf[1024];
  16.         int size;
  17.         size = readlink(in, buf, 1024);    //调用readlink读符号链接的大小及内容
  18.         _eject(&s, out, olen, buf, size);   
  19.     } else {
  20.         die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
  21.     }
  22. }
注: 符号链接
假设有这样的符号连接
ln -s /home/cong/Desktop/record.txt link 
则调用readlink后,buf="/home/cong/Desktop/record.txt", size=sizeof("/home/cong/Desktop/record.txt");
即realink所读到的就是link所指向的路径的内容及长度

函数的作用是:把文件的信息与文件的内容写到ramdisk.img中去
mkbootfs $OUT/root
    main 
       --> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
        --> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
        --> _archive    //对普通文件 目录  链接分开处理
            --> _eject   //将文件信息与内容写入到ramdisk.img中去
  1. static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
  2. {
  3.     static unsigned next_inode = 300000;

  4.     while(total_size & 3) {
  5.         total_size++;
  6.         putchar(0);
  7.     }

  8.     fix_stat(out, s);
  9.     //这儿的printf实际上是要写入到ramdisk.img中去的  
  10.     printf("%06x%08x%08x%08x%08x%08x%08x"
  11.            "%08x%08x%08x%08x%08x%08x%08x%s%c",
  12.            0x070701,                   <<<<---   标志 
  13.            next_inode++, // s.st_ino,    //inode_number
  14.            s->st_mode,                   //mode
  15.            0, // s.st_uid,               //uid
  16.            0, // s.st_gid,               //gid
  17.            1, // s.st_nlink,             //链接数
  18.            0, // s.st_mtime,             //最后修改时间
  19.            datasize,                     //文件长度
  20.            0, // volmajor                //主号
  21.            0, // volminor                //次号
  22.            0, // devmajor                //主设备号
  23.            0, // devminor,               //次设备号
  24.            olen + 1,                     //name_len名字长度
  25.            0,                         --->>>>
  26.            out,
  27.            0
  28.            );

  29.     total_size += 6 + 8*13 + olen + 1;


  30.     while(total_size & 3) {
  31.         total_size++;
  32.         putchar(0);
  33.     }

  34.     if(datasize) {
  35.         fwrite(data, datasize, 1, stdout);   //这是文件的内容
  36.         total_size += datasize;
  37.     }
  38. }
 最后写入一个结束标志:
  1. static void _eject_trailer()
  2. {
  3.     struct stat s;
  4.     memset(&s, 0, sizeof(s));
  5.     _eject(&s, "TRAILER!!!", 10, 0, 0);

  6.     while(total_size & 0xff) {
  7.         total_size++;
  8.         putchar(0);
  9.     }
  10. }
注: CPIO 的结构包括:
                   110字节的Head(6 + 8*13) 
                     不定长的文件名(文件名的长度是olen)
                     结束字符 \0
                     文件的内容
                     .... //重复上面4个
                   最后的文件名是一个 TRAILER!!!

附1. ramdisk.img的解压过程
  1. cong@ubuntu:/tmp/test$ file ./bak/ramdisk.img 
  2. ./bak/ramdisk.img: gzip compressed data, from Unix
  3. cong@ubuntu:/tmp/test$ cp ./bak/ramdisk.img ./bak/ramdisk.img_bak.gz  //新copy一份
  4. cong@ubuntu:/tmp/test$ gunzip ./bak/ramdisk.img_bak.gz                //gunzip解压缩
  5. cong@ubuntu:/tmp/test$ ls ./bak/
  6. ramdisk.img ramdisk.img_bak ramdisk.img.gz
  7. cong@ubuntu:/tmp/test$ file ./bak/ramdisk.img_bak                     //解压后的文件就是cpio格式的
  8. ./bak/ramdisk.img_bak: ASCII cpio archive (SVR4 with no CRC)
  9. cong@ubuntu:/tmp/test$ cpio --./bak/ramdisk.img_bak               //解压cpio格式
  10. 463 blocks
  11. cong@ubuntu:/tmp/test$ ls                                             //这就能看到所有文件了
  12. bak data default.prop dev forlinx.rc init init.goldfish.rc init.rc linuxrc proc sbin sys system ueventd.goldfish.rc ueventd.rc
  13. cong@ubuntu:/tmp/test$
阅读(3563) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~