1. android目录下的mkimage.sh
-
#!/bin/bash
-
set -e
-
-
. build/envsetup.sh >/dev/null && setpaths
-
-
export PATH=$ANDROID_BUILD_PATHS:$PATH
-
-
TARGET="withoutkernel"
-
if [ "$1"x != ""x ]; then
-
TARGET=$1
-
fi
-
rm -rf rockdev/Image
-
mkdir -p rockdev/Image
//在init.rk30board.rc中搜索字符串mtd@system,发现其分区类型为ext4
-
FSTYPE=`grep 'mtd@system' $OUT/root/init.rk30board.rc | head -n 1 | awk '{ print $2 }'`
-
if [ "$FSTYPE" = "" ]; then
-
FSTYPE=`grep 'mtd@system' $OUT/root/init.rc | head -n 1 | awk '{ print $2 }'`
-
fi
-
echo system filesysystem is $FSTYPE
-
-
BOARD_CONFIG=device/rockchip/rk30sdk/device.mk
-
//KERNLE_SRC_PATH为空
-
KERNEL_SRC_PATH=`grep TARGET_PREBUILT_KERNEL ${BOARD_CONFIG} |grep "^\s*TARGET_PREBUILT_KERNEL *:= *[\w]*\s" |awk '{print $3}'`
-
[ $(id -u) -eq 0 ] || FAKEROOT=fakeroot
-
-
BOOT_OTA="ota"
-
echo "TARGET=$TARGET"
-
[ $TARGET != $BOOT_OTA -a $TARGET != "withoutkernel" ] && echo "unknow target[${TARGET}],exit!" && exit 0
-
-
if [ ! -f $OUT/kernel ] //这个文件存在不执行以下
-
then
-
echo "kernel image not fount![$OUT/kernel] "
-
read -p "copy kernel from TARGET_PREBUILT_KERNEL[$KERNEL_SRC_PATH] (y/n) n to exit?"
-
if [ "$REPLY" == "y" ]
-
then
-
[ -f $KERNEL_SRC_PATH ] || \
-
echo -n "fatal! TARGET_PREBUILT_KERNEL not eixit! " || \
-
echo -n "check you configuration in [${BOARD_CONFIG}] " || exit 0
-
-
cp ${KERNEL_SRC_PATH} $OUT/kernel
-
-
else
-
exit 0
-
fi
-
fi
//1.boot.img的生成过程
-
if [ $TARGET == $BOOT_OTA ] //TARGET=withoutkernel, BOOT_OTA=ota不相等,执行else
-
then
-
echo "make ota images... "
-
echo -n "create boot.img with kernel... "
-
[ -d $OUT/root ] && \
-
mkbootfs $OUT/root | minigzip > $OUT/ramdisk.img && \
-
mkbootimg --kernel $OUT/kernel --ramdisk $OUT/ramdisk.img --output $OUT/boot.img && \
-
cp -a $OUT/boot.img rockdev/Image/
-
echo "done."
-
else
-
echo -n "create boot.img without kernel... "
-
[ -d $OUT/root ] && \ //目录out/target/product/rk30sdk/root存在
-
mkbootfs $OUT/root | minigzip > $OUT/ramdisk.img && \ //1.将root下的每个文件加上cpio头+每个文件的内容,打包成cpios格式
-
rkst/mkkrnlimg $OUT/ramdisk.img rockdev/Image/boot.img //2. 将这个cpio文件用gzip压缩后写到文件ramdisk.img中
-
echo "done." //3. mkkrnlimg会对ramdisk.img加上8个字节的头标志,尾部加上4个字字
-
fi
-
//2.recovery.img的生成过程
-
echo -n "create recovery.img with kernel... "
-
[ -d $OUT/recovery/root ] && \
-
mkbootfs $OUT/recovery/root | minigzip > $OUT/ramdisk-recovery.img && \
-
mkbootimg --kernel $OUT/kernel --ramdisk $OUT/ramdisk-recovery.img --output $OUT/recovery.img && \
-
cp -a $OUT/recovery.img rockdev/Image/
-
echo "done."
-
-
echo -n "create misc.img.... "
-
cp -a rkst/Image/misc.img rockdev/Image/misc.img
-
cp -a rkst/Image/pcba_small_misc.img rockdev/Image/pcba_small_misc.img
-
cp -a rkst/Image/pcba_whole_misc.img rockdev/Image/pcba_whole_misc.img
-
echo "done."
-
-
//3.system.img的生成过程
-
if [ -d $OUT/system ]
-
then
-
echo -n "create system.img... "
-
if [ "$FSTYPE" = "cramfs" ]
-
then
-
chmod -R 777 $OUT/system
-
$FAKEROOT mkfs.cramfs $OUT/system rockdev/Image/system.img
-
elif [ "$FSTYPE" = "squashfs" ]
-
then
-
chmod -R 777 $OUT/system
-
mksquashfs $OUT/system rockdev/Image/system.img -all-root >/dev/null
-
elif [ "$FSTYPE" = "ext3" ] || [ "$FSTYPE" = "ext4" ]
-
then //ext3或ext4的生成过程
-
delta=5120
-
num_blocks=`du -sk $OUT/system | tail -n1 | awk '{print $1;}'`
-
num_blocks=$(($num_blocks + $delta))
-
-
num_inodes=`find $OUT/system | wc -l`
-
num_inodes=$(($num_inodes + 500))
-
-
ok=0
-
while [ "$ok" = "0" ]; do
-
genext2fs -a -d $OUT/system -b $num_blocks -N $num_inodes -m 0 rockdev/Image/system.img >/dev/null 2>&1 && \
-
tune2fs -j -L system -c -1 -i 0 rockdev/Image/system.img >/dev/null 2>&1 && \
-
ok=1 || num_blocks=$(($num_blocks + $delta))
-
done
-
e2fsck -fy rockdev/Image/system.img >/dev/null 2>&1 || true
-
-
delta=1024
-
num_blocks=`resize2fs -P rockdev/Image/system.img 2>&1 | tail -n1 | awk '{print $7;}'`
-
rm -f rockdev/Image/system.img
-
ok=0
-
while [ "$ok" = "0" ]; do
-
genext2fs -a -d $OUT/system -b $num_blocks -N $num_inodes -m 0 rockdev/Image/system.img >/dev/null 2>&1 && \
-
tune2fs -O dir_index,filetype,sparse_super -j -L system -c -1 -i 0 rockdev/Image/system.img >/dev/null 2>&1 && \
-
ok=1 || num_blocks=$(($num_blocks + $delta))
-
done
-
e2fsck -fyD rockdev/Image/system.img >/dev/null 2>&1 || true
-
else
-
mkdir -p rockdev/Image/2k rockdev/Image/4k
-
mkyaffs2image -c 2032 -s 16 -f $OUT/system rockdev/Image/2k/system.img
-
mkyaffs2image -c 4080 -s 16 -f $OUT/system rockdev/Image/4k/system.img
-
fi
-
echo "done."
-
fi
-
- chmod a+r -R rockdev/Image/
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是打包后的文件路径
-
static void _archive_dir(char *in, char *out, int ilen, int olen)
-
{
-
int i, t;
-
DIR *d;
- struct dirent *de;
-
DIR* d = opendir(in); //打开目录
-
-
int size = 32;
-
int entries = 0;
- char** names = malloc(size * sizeof(char*)); //每次分配32个文件名的内存
-
//将./out/target/product/rk30sdk/root目录下所有的文件名存在name数组中
-
while((de = readdir(d)) != 0){
- if(de->d_name[0] == '.') continue; //跳过.目录
- if(!strcmp(de->d_name, "root")) continue; //排除root,这是为了什么?
-
if (entries >= size) {
-
size *= 2; //如果超出32个文件名,则再多分配32*2个,依次类推
-
names = realloc(names, size * sizeof(char*)); //realloc,又学习了一招
-
}
-
names[entries] = strdup(de->d_name); //strdup可以分配内存并复制
-
++entries;
-
}
-
//对name数组中的文件名进行排序
-
qsort(names, entries, sizeof(char*), compare);
-
-
for (i = 0; i < entries; ++i) {
-
t = strlen(names[i]);
-
in[ilen] = '/';
-
memcpy(in + ilen + 1, names[i], t + 1);
-
-
if(olen > 0) { //out为空
-
out[olen] = '/';
-
memcpy(out + olen + 1, names[i], t + 1);
-
_archive(in, out, ilen + t + 1, olen + t + 1);
-
} else {
-
memcpy(out, names[i], t + 1); //将文件名复制到out中
-
_archive(in, out, ilen + t + 1, t); //将这个文件打包到ramdisk.img中
-
}
-
-
in[ilen] = 0;
-
out[olen] = 0;
-
-
free(names[i]);
-
}
-
free(names);
- }
main
--> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
--> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
--> _archive //对普通文件 目录 链接分开处理
-
static void _archive(char *in, char *out, int ilen, int olen)
-
{
- struct stat s;
-
if(S_ISREG(s.st_mode)){ //1.对普通文件的处理
-
int fd = open(in, O_RDONLY);
- char* tmp = (char*) malloc(s.st_size);
- read(fd, tmp, s.st_size);
- _eject(&s, out, olen, tmp, s.st_size);
-
free(tmp);
-
close(fd);
-
} else if(S_ISDIR(s.st_mode)) { //2.对目录的处理
-
_eject(&s, out, olen, 0, 0);
-
_archive_dir(in, out, ilen, olen);
-
} else if(S_ISLNK(s.st_mode)) { //3.对链接文件的处理
-
char buf[1024];
-
int size;
-
size = readlink(in, buf, 1024); //调用readlink读符号链接的大小及内容
-
_eject(&s, out, olen, buf, size);
-
} else {
-
die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
-
}
- }
假设有这样的符号连接
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中去
-
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
-
{
-
static unsigned next_inode = 300000;
-
-
while(total_size & 3) {
-
total_size++;
-
putchar(0);
-
}
-
- fix_stat(out, s);
-
//这儿的printf实际上是要写入到ramdisk.img中去的
-
printf("%06x%08x%08x%08x%08x%08x%08x"
-
"%08x%08x%08x%08x%08x%08x%08x%s%c",
-
0x070701, <<<<--- 标志
-
next_inode++, // s.st_ino, //inode_number
-
s->st_mode, //mode
-
0, // s.st_uid, //uid
-
0, // s.st_gid, //gid
-
1, // s.st_nlink, //链接数
-
0, // s.st_mtime, //最后修改时间
-
datasize, //文件长度
-
0, // volmajor //主号
-
0, // volminor //次号
-
0, // devmajor //主设备号
-
0, // devminor, //次设备号
-
olen + 1, //name_len名字长度
-
0, --->>>>
-
out,
-
0
-
);
-
-
total_size += 6 + 8*13 + olen + 1;
-
-
-
while(total_size & 3) {
-
total_size++;
-
putchar(0);
-
}
-
-
if(datasize) {
-
fwrite(data, datasize, 1, stdout); //这是文件的内容
-
total_size += datasize;
-
}
- }
-
static void _eject_trailer()
-
{
-
struct stat s;
-
memset(&s, 0, sizeof(s));
-
_eject(&s, "TRAILER!!!", 10, 0, 0);
-
-
while(total_size & 0xff) {
-
total_size++;
-
putchar(0);
-
}
- }
110字节的Head(6 + 8*13)
不定长的文件名(文件名的长度是olen)
结束字符 \0
文件的内容
.... //重复上面4个
最后的文件名是一个 TRAILER!!!
附1. ramdisk.img的解压过程
-
cong@ubuntu:/tmp/test$ file ./bak/ramdisk.img
-
./bak/ramdisk.img: gzip compressed data, from Unix
-
cong@ubuntu:/tmp/test$ cp ./bak/ramdisk.img ./bak/ramdisk.img_bak.gz //重新copy一份
-
cong@ubuntu:/tmp/test$ gunzip ./bak/ramdisk.img_bak.gz //gunzip解压缩
-
cong@ubuntu:/tmp/test$ ls ./bak/
-
ramdisk.img ramdisk.img_bak ramdisk.img.gz
-
cong@ubuntu:/tmp/test$ file ./bak/ramdisk.img_bak //解压后的文件就是cpio格式的
-
./bak/ramdisk.img_bak: ASCII cpio archive (SVR4 with no CRC)
-
cong@ubuntu:/tmp/test$ cpio -i -F ./bak/ramdisk.img_bak //解压cpio格式
-
463 blocks
-
cong@ubuntu:/tmp/test$ ls //这就能看到所有文件了
-
bak data default.prop dev forlinx.rc init init.goldfish.rc init.rc linuxrc proc sbin sys system ueventd.goldfish.rc ueventd.rc
- cong@ubuntu:/tmp/test$