如何制作安卓用的ubuntu制作img镜像 for arm的img镜像

3302人阅读
Android(48)
在国内下载Android可是不太容易,不过从Google断断续续地下载了几天源码后发现清华大学有个TUNA镜像源可以下载Android源码,甚是方便。
参考网站:
/index.html
https://aosp.tuna./
一.环境准备:
现在Android源码的下载和编译在Linux和Mac OS上都可以了,但Mac OS上设置略微复杂点,所以我选择了Ubuntu 14.04 64位的虚拟机。(硬盘建议50G以上,编译的时候给虚拟机加大CPU和内存。)
编译Gingerbread (2.3.x) 及其以上的源码需要64位的系统,以下的可以在32位系统上编译。
1.Java下载和配置
Java 7:适用最新版的源码:
apt-get update
apt-get install
openjdk-7-jdk
如果系统上有多个Java版本,可以设置默认的:
update-alternatives --config java
update-alternatives --config javac
Java 6: 适用于Gingerbread(2.3)~ KitKat(4.4)
Java 5:适用于 Cupcake(1.5)~ Froyo(2.2)
如果Java安装失败可到Java官网下载后自行安装,略去不表。
2.其它依赖包:
apt-get install
bison g++-multilib git gperf libxml2-utils make
zlib1g-dev:i386 zip
如果是Ubuntu 12.04:
apt-get install
git gnupg flex bison gperf build-essential \
curl libc6-dev libncurses5-dev:i386 x11proto-core-dev \
&&libx11-dev:i386
libreadline6-dev:i386 libgl1-mesa-glx:i386 \
&&libgl1-mesa-dev
g++-multilib mingw32 tofrodos \
&&python-markdown
libxml2-utils xsltproc zlib1g-dev:i386
-s /usr/lib/i386-linux-gnu/mesa/libGL.so.1
/usr/lib/i386-linux-gnu/libGL.so
如果是Ubuntu 10.04 — 11.10:
apt-get install
git gnupg flex bison gperf build-essential \
curl zlib1g-dev libc6-dev lib32ncurses5-dev ia32-libs \
&&x11proto-core-dev
libx11-dev lib32readline5-dev lib32z-dev \
&&libgl1-mesa-dev
g++-multilib mingw32 tofrodos python-markdown \
&&libxml2-utils
apt-get install
libx11-dev:i386
-s /usr/lib32/mesa/libGL.so.1
/usr/lib32/mesa/libGL.so
二、下载源码
1.下载repo:
repo是Google基于Git推出的一款版本管理工具,用python写的。
先配置目录:
PATH=~/bin:$PATH
下载repo并赋予其可执行权限:
curl https://storage./git-repo-downloads/repo
& ~/bin/repo
a+x ~/bin/repo
当然由于众所周知的原因,我们往往无法把repo下到本地。这里提供一个我下载并修改好的下载链接:
(wp的限制,只能把repo重命名为repo.txt,下载后改回repo即可)
下载放到~/bin目录下,并修改权限即可:
a+x repo
2.初始化repo
进入放置源码的目录,如:
~/android/android
~/android/android
关键的来了,如果想体验好点,建议国内的从清华大学的镜像源下载:
repo init -u git://aosp.tuna./android/platform/manifest
或者指定要下载的分支:
repo init -u git:
完成后即可和服务器同步了:
该服务器限制了每个IP并发数,也就是你可以使用:
设置并发数为4.,给别人留有余地。
现在应该在从服务器下载源码了,但是如果中途有中断了,继续执行repo sync即可。
如何让repo自动在断开后自动下载:
新建autorepo.sh:
然后执行即可:
sh autorepo.sh
如果你之前已经下载了部分AOSP的代码的话,切换到TUNA服务器也很方便,如官网所示:
如果你之前已经通过某种途径获得了 AOSP 的源码(或者你只是 init 这一步完成后), 你希望以后通过 TUNA 同步 AOSP 部分的代码,只需要将&.repo/manifest.xml&把其中的
aosp 这个 remote 的 fetch 从&&改为 git://aosp.tuna./android/
&manifest&
&&&&remote&
name=&aosp&
-&&&&&&&&&&
+&&&&&&&&&&
fetch=&git://aosp.tuna./android/&
&&&&&&&&&&&&review=&android-&
&&&&remote&
name=&github&
这个方法也可以用来在同步 Cyanogenmod 代码的时候从 TUNA 同步部分代码
&三、编译:
当源码下载后,可以看到目录里多出很多源码文件夹:
[aosp@myserver
android4.1_r1]$ ls
drwxrwxr-x&&
3 aosp aosp 4.0K Apr& 7 11:27 abi
drwxrwxr-x&&
9 aosp aosp 4.0K Apr& 7 11:27 bionic
drwxrwxr-x&&
5 aosp aosp 4.0K Apr& 7 11:27 bootable
drwxrwxr-x&&
7 aosp aosp 4.0K Apr& 7 11:27 build
drwxrwxr-x&
11 aosp aosp 4.0K Apr& 7 11:27 cts
drwxrwxr-x&
18 aosp aosp 4.0K Apr& 7 11:27 dalvik
drwxrwxr-x&
19 aosp aosp 4.0K Apr& 7 11:27 development
drwxrwxr-x&
10 aosp aosp 4.0K Apr& 7 11:27 device
drwxrwxr-x&&
3 aosp aosp 4.0K Apr& 7 11:27 docs
drwxrwxr-x
144 aosp aosp 4.0K Apr& 7 11:29 external
drwxrwxr-x&
14 aosp aosp 4.0K Apr& 7 11:32 frameworks
drwxrwxr-x&
10 aosp aosp 4.0K Apr& 7 11:32 gdk
drwxrwxr-x&
10 aosp aosp 4.0K Apr& 7 11:32 hardware
drwxrwxr-x&
11 aosp aosp 4.0K Apr& 7 11:32 libcore
drwxrwxr-x&&
4 aosp aosp 4.0K Apr& 7 11:32 libnativehelper
-r--r--r--&&
1 aosp aosp&& 87 Apr& 7 11:27 Makefile
drwxrwxr-x&&
8 aosp aosp 4.0K Apr& 7 11:32 ndk
drwxrwxr-x&&
4 aosp aosp 4.0K Apr& 7 14:28 out
drwxrwxr-x&&
7 aosp aosp 4.0K Apr& 7 11:33 packages
drwxrwxr-x&&
4 aosp aosp 4.0K Apr& 7 11:33 pdk
drwxrwxr-x&
12 aosp aosp 4.0K Apr& 7 11:33 prebuilt
drwxrwxr-x&&
9 aosp aosp 4.0K Apr& 7 11:34 prebuilts
drwxrwxr-x&
48 aosp aosp 4.0K Apr& 7 11:34 sdk
drwxrwxr-x&&
9 aosp aosp 4.0K Apr& 7 11:34 system
如果你准备在模拟器里运行,则按照如下步骤编译即可,如果你想刷到手机上则还有一些任务要做(见第四步)。
0.其中由于配置问题,我的代码是放在服务器上编译的:
由于.repo这个隐藏文件夹里的文件占用空间很大,所以在压缩的时候将其排除:
-zcvf android4.3_r1.tar.gz
android4.3_r1/ --exclude .repo
然后利用scp命令将压缩好的文件上传到服务器:
android4.3_r1.tar.gz
username@host:/home/android/
其中username和host是你用户名和服务器地址。
-zxvf android4.3_r1.tar.gz
1.初始化:
build/envsetup.sh
2.使用lunch命令选择编译目标,如:
lunch aosp_arm-eng
或者直接lunch,会让你选择编译目标的。
其中参数说明:
BUILD NAME
ARM emulator
包括所有语言、APP和输入法的配置
aosp_maguro
运行在Galaxy Nexus GSM/HSPA+ (&maguro&)上
aosp_panda
&运行在 PandaBoard (&panda&)上
suited for production(有权限限制,适合产品级)
preferred for debugging(适合调试)
development configuration with additional debugging tools(有额外的调试工具)
-jN表示用N个线程来编译,如果你是配置是2CPU,每个CPU有4核,每核可跑俩线程,那么你可以make -j16乃至-j32,这样速度将大大加快。.
在android4.3_r1/out/target/product/generic目录下可以看到如下文件:
[aosp@myserver
generic]$ ls
-rw-rw-r--&
1 aosp aosp&&& 7 Apr& 7 14:49 android-info.txt
-rw-rw-r--&
1 aosp aosp& 25K Apr& 7 14:48 clean_steps.mk
drwxrwxr-x&
4 aosp aosp 4.0K Apr& 7 15:19 data
drwxrwxr-x&
3 aosp aosp 4.0K Apr& 7 15:18 dex_bootjars
-rw-rw-r--&
1 aosp aosp& 47K Apr& 7 15:27 installed-files.txt
drwxrwxr-x
14 aosp aosp 4.0K Apr& 7 15:27 obj
-rw-rw-r--&
1 aosp aosp& 557 Apr& 7 14:48 previous_build_config.mk
-rw-rw-r--&
1 aosp aosp 163K Apr& 7 15:18 ramdisk.img
drwxrwxr-x&
8 aosp aosp 4.0K Apr& 7 15:18 root
drwxrwxr-x&
5 aosp aosp 4.0K Apr& 7 15:18 symbols
drwxrwxr-x
12 aosp aosp 4.0K Apr& 7 15:27 system
-rw-------&
1 aosp aosp 204M Apr& 7 15:27 system.img
drwxrwxr-x&
3 aosp aosp 4.0K Apr& 7 15:05 test
-rw-------&
1 aosp aosp& 99K Apr& 7 15:19 userdata.img
1.模拟器的话,其实直接运行emulator即可运行:
由于不涉及内核,我的做法是把ramdisk.img、system.img和userdata.img复制到sdk/system-images/android-18/default/armeabi-v7a/目录下替换掉原来的文件。(可以把原来的先备份)
然后新建对应的API虚拟机,运行即可。
真机我是用Google三太子Galaxy Nexus&[maguro] (GSM/HSPA+)做的实验,毕竟亲儿子,驱动方面都很好配置。
a.在第三步编译之前,先把驱动配置好:
然后按照第三步编译即可。
b.连接手机,打开USB调试,进入bootloader模式:
adb reboot bootloader
如果bootloader被锁住的话,先解锁:
fastboot oem unlock
然后进入system.img等文件的目录:
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash userdata userdata.img
然后重启即可。
本文首发地址:/archives/187
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:74841次
积分:1515
积分:1515
排名:第19759名
原创:64篇
转载:17篇
译文:10篇
评论:20条
(2)(1)(2)(3)(1)(2)(4)(2)(2)(17)(6)(2)(5)(4)(3)(7)(3)(7)(8)(1)(2)(3)(4)4040人阅读
android(29)
Android文件系统具有什么样的结构?我们如何才能将这一文件系统分离出来?又能以何种方式挂载文件系统呢?这些问题都会在文中找到具体的解决答案。
用过Linux的朋友可能对开源的系统有一个非常好的印象。那么在日益成熟的手机操作系统中,有没有一款像Linux一样的开源系统呢?谷歌公司就退出了一款基于Linux平台的操作系统来满足人们的需求。在这里大家可以先来了解一下Android文件系统的相关内容。
1、Android文件系统的结构
Android源码编译后得到system.img,ramdisk.img,userdata.img映像文件。其中, ramdisk.img是emulator的文件系统,system.img包括了主要的包、库等文件,userdata.img包括了一些用户数据,emulator加载这3个映像文件后,会把 system和 userdata分别加载到 ramdisk文件系统中的system和 userdata目录下。因此,我们可以把ramdisk.img里的所有文件复制出来,system.img和userdata.img分别解压到
ramdisk文件系统中的system和 userdata目录下。
2、分离Android文件系统出来
system.img,ramdisk.img,userdata.img映像文件是采用cpio打包、gzip压缩的,可以通过file命令验证:
file&ramdisk.img&
ramdisk.img:&gzip&compressed&data,&from&Unix,&
last&modified:&Wed&Mar&18&17:16:10&2009&
Android源码编译后除了生成system.img,userdata.img之外还生成system和 userdata文件夹,因此不需要解压它们。Android源码编译后还生成root文件夹,其实root下的文件与 ramdisk.img 里的文件是一样的,不过这里还是介绍怎样把 ramdisk.img解压出来:
将ramdisk.img复制一份到任何其他目录下,将其名称改为ramdisk.img.gz,并使用命令
gunzip&ramdisk.img.gz&
然后新建一个文件夹,叫ramdisk吧,进入,输入命令
cpio&-i&-F&../ramdisk.img&
这下,你就能看见并操作ramdisk里面的内容了。
然后把Android源码编译后生成的system和 userdata里的文件复制到 ramdisk/system和 ramdisk/userdata下。这样就得到一个文件系统了。
3、使用网络文件系统方式挂载Android文件系统
因此,我们需要建立/nfsroot目录,再建立/nfsroot/Androidfs目录,把刚才的Android文件系统改名为Androidfs,并链接到/nfsroot/Androidfs
4、Android文件系统内核引导文件系统
Android内核挂载/nfsroot/Androidfs之后,根据init.rc,init.goldfish.rc来初始化并装载系统库、程序等直到开机完成。init.rc脚本包括了文件系统初始化、装载的许多过程。init.rc的工作主要是:
1)设置一些环境变量
2)创建system、sdcard、data、cache等目录
3)把一些文件系统mount到一些目录去,如,mount tmpfs tmpfs /sqlite_stmt_journals
4)设置一些文件的用户群组、权限
5)设置一些线程参数
6)设置TCP缓存大小
android文件系统制作:
splash1 :开机画面,Nandroid备份为splash1.img
recovery :设备序列号为mtd1,该分区是恢复模式(即开机按Home+End进入的界面),Nandroid备份为recovery.img
boot :设备序列号为mtd2,底层操作系统内核启动分区,挂载 为/目录,Nandroid备份为boot.img
system :设备序列号为mtd3,G1的Android核心平台,挂 载为/system目录,通常为只读,Nandroid备份为system.img
cache :设备序列号为mtd4,G1的缓存临时文件夹,挂载为 /cache目录,事实上除了T-mobile的OTA更新外,别无用处,Nandroid备份为cache.img
userdata :设备序列号为mtd5,G1中用户安装的软件以及各种 数据,挂载为/data目录,Nandroid备份为data.img
android文件系统制作教程(2) —- 常用的fastboot命令
$ fastboot reboot
刷所有分区并重启手机
$ fastboot flashall 刷指定分区:
$ fastboot flash {partition} {file.img}
如:fastboot flash system /备份/system.img 擦除分区:
$ fastboot erase {partition}
如:fastboot erase system 使用update.zip整体刷新
$ fastboot update {update.zip} 刷自定义开机画面:
$ fasboot flash splash1 mysplash.rgb565
android文件系统制作教程(3) —- 利用Makefile制作update.zip
从update.zip这个刷机包反推的介绍整个android文件系统的制作过程
并编写了一个Makefile文件,利用 Makefile的”依赖检查”机制管理各种文件的生成步骤和依赖关系;
-1.前期准备
将所有的文件都放在/home/xiaoliang/workspace 目录下,目录下有这些文件夹:
auto-sign data system META-INF root
两个环境变量含义和必须的目录:
SRC_HOME : android源代码所在的目录,例如我放在 /home/xiaoliang/android_src 下
JAVA_HOME: JAVA SDK的目录,我的是 /server/jdk1.5.0_21
0.进行一次源代码编译
1.然后看下面的Makefile
#设置环境变量,JAVA_HOME默认就有
SRC_HOME=/home/liangwei/android_src
#它依赖于system,data,META-INF三个目录和一个boot.img镜像,并且它需要签名
update.zip : boot.img $(shell find system data META-INF)
&&& #生成update_unsign.zip
&&& zip -qr update_unsign.zip system data META-INF boot.img
&&& $(JAVA_HOME)/bin/java -jar auto-sign/signapk.jar auto-sign/testkey.x509.pem auto-sign/testkey.pk8 update_unsign.zip update.zip
&&& #删除中间文件
&&& rm -f update_unsign.zip
#依赖于ramdisk.img 和 kernel.img 两个镜像
boot.img:ramdisk.img kernel.img
&&& #使用mkbootimg制作
&&& $(SRC_HOME)/out/host/linux-x86/bin/mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel kernel.img --ramdisk ramdisk.img -o boot.img
#其实它就是源码编译后生成的zImage,拷贝过来改个名字
kernel.img:$(SRC_HOME)/kernel/msm/arch/arm/boot/zImage
&&& cp -f $(SRC_HOME)/kernel/msm/arch/arm/boot/zImage ./kernel.img
#是将root文件夹使用mkbootfs制作的镜像
ramdisk.img:$(shell find root)
&&& $(SRC_HOME)/out/host/linux-x86/bin/mkbootfs ./root |gzip & ramdisk.img
2.总结一下,其实update.zip主要就是三个部分组成:
启动部分: root文件夹 + zImage内核镜像 = boot.img
系统文件部分: system文件夹
用户文件部分: data文件夹
就是:root + system + data + zIamage = update.zip
3.文件的出处
root,system,data文件夹: 来自”$(SRC_HOME)/out/target/product/generic”
zIamage: 来自”$(SRC_HOME)/kernel/msm/arch/arm/boot/zImage”
4.刷机脚本:META-INF文件夹
该需要自己创建,并且里面包含1个文件 : com/google/android/update-script ,内容为:
show_progress 0.
format SYSTEM:
copy_dir PACKAGE:system SYSTEM:
set_perm_recursive 0 0
set_perm_recursive 0 55 SYSTEM:bin
set_perm 0
SYSTEM:bin/netcfg
set_perm 0
SYSTEM:bin/ping
set_perm 0 0 04755 SYSTEM:bin/su
set_perm 40 SYSTEM:etc/dbus.conf
set_perm 50 SYSTEM:etc/dhcpcd/dhcpcd-run-hooks
set_perm 0
SYSTEM:etc/init.goldfish.sh
set_perm_recursive 0 0
SYSTEM:etc/ppp
show_progress 0.
delete_recursive DATA:dalvik-cache
copy_dir PACKAGE:data DATA:
set_perm_recursive 71 0555 DATA:dalvik-cache
write_raw_image PACKAGE:boot.img BOOT:
show_progress 0.
android文件系统制作教程(4) —- makefile脚本,制作各种单独的分区文件ramdisk.img,system.img,boot.img
#***********************************
#&&& build android rom script
#***********************************
SRC_HOME=/home/liangwei/android_src
update.zip : boot.img $(shell find system data META-INF)
&&& rm -rf update_unsign.zip
&&& zip -qr update_unsign.zip system data META-INF boot.img
&&& $(JAVA_HOME)/bin/java -jar auto-sign/signapk.jar auto-sign/testkey.x509.pem auto-sign/testkey.pk8 update_unsign.zip update.zip
&&& rm -f update_unsign.zip
boot.img:ramdisk.img kernel.img
&&& $(SRC_HOME)/out/host/linux-x86/bin/mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel kernel.img --ramdisk ramdisk.img -o boot.img
kernel.img:$(SRC_HOME)/kernel/msm/arch/arm/boot/zImage
&&& cp -f $(SRC_HOME)/kernel/msm/arch/arm/boot/zImage ./kernel.img
kernel-qemu:$(SRC_HOME)/kernel/common/arch/arm/boot/zImage
&&& cp -f $(SRC_HOME)/kernel/common/arch/arm/boot/zImage ./kernel-qemu
ramdisk.img:$(shell find root)
&&& $(SRC_HOME)/out/host/linux-x86/bin/mkbootfs ./root |gzip & ramdisk.img
system.img : $(shell find system)
&&& $(SRC_HOME)/out/host/linux-x86/bin/mkyaffs2image ./system system.img
userdata.img:$(shell find data)
&&& $(SRC_HOME)/out/host/linux-x86/bin/mkyaffs2image ./data userdata.img
userdata-qemu.img:userdata.img
&&& rm -rf userdata-qemu.img
&&& cp userdata.img userdata-qemu.img
initlogo.rle:logo.png
&&& convert -depth 8 logo.png rgb:logo.raw
&&& $(SRC_HOME)/out/host/linux-x86/bin/rgb2565 -rle &logo.raw &initlogo.rle
&&& cp -rf initlogo.rle data/data/com.android.mysplash/
&&& rm -rf logo.raw
.PHONY:run
run:system.img ramdisk.img kernel-qemu userdata-qemu.img
&&& /server/android-sdk-linux_86/tools/emulator -show-kernel -sysdir ./
android文件系统制作教程(5) —- 两行命令从png制作启动界面initlogo.rle
用图片工具编辑好想要的png之后,保存为logo.png
在logo.png所在命令下执行命令:
#使用ImageMagick自带的convert命令,进行raw格式转换
convert -depth 8 logo.png rgb:logo.raw
#android自带的rgb2565工具,对raw文件进行rle565格式转换
$(SRC_HOME)/out/host/linux-x86/bin/rgb2565 -rle &logo.raw &initlogo.rle
#然后将initlogo.rle拷贝到android系统根目录,也就是root目录底下
cp initlogo.rle root/
#删除中间文件
rm -f logo.raw
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:475042次
积分:6509
积分:6509
排名:第2564名
原创:133篇
转载:71篇
译文:12篇
评论:226条
(1)(2)(1)(1)(1)(1)(2)(1)(2)(2)(2)(6)(5)(1)(5)(5)(1)(2)(2)(8)(5)(5)(17)(12)(24)(17)(9)(3)(14)(13)(9)(4)(3)(1)(2)(5)(2)(1)(6)(7)(2)(3)(1)1916人阅读
转载时请注明出处和作者
文章出处:
作者:Xandy
1&&&&&& 总述
为了方便客户日后的固件升级,本周研究了一下android的recovery模式。网上有不少这类的资料,但都比较繁杂,没有一个系统的介绍与认识,在这里将网上所找到的和自己通过查阅代码所掌握的东西整理出来,给大家一个参考!
2&&&&&& Android启动过程
在这里有必要理一下android的启动过程:
图1 android启动过程
系统上电之后,首先是完成一系列的初始化过程,如cpu、串口、中断、timer、DDR等等硬件设备,然后接着加载boot default environmet,为后面内核的加载作好准备。在一些系统启动必要的初始完成之后,将判断是否要进入recovery模式,从图1中可以看出,进入recovery模式有两种情况。一种是检测到有组合按键按下时;另一种是检测到cache/recovery目录下有command这个文件,这个文件有内容有它特定的格式,将在后面讲到。
3&&&&&& Uboot启动
下面来看看uboot中lib_arm/board.c这个文件中的start_armboot这个函数,这个函数在start.s这个汇编文件中完成堆栈等一些基础动作之后被调用,进入到c的代码中,start_armboot部分代码如下:
void start_armboot (void){
for (init_fnc_ptr = init_ *init_fnc_ ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
}#ifdef CONFIG_ANDROID_RECOVERY
check_recovery_mode();#endif
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
&&&&&& init_sequence是一个函数结构体指针,里面存放的是一些必备的初始化函数,其代码如下:
init_fnc_t *init_sequence[] = {#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init,
/* basic arch cpu dependent setup */#endif
board_init,
/* basic board dependent setup */#if defined(CONFIG_USE_IRQ)
interrupt_init,
/* set up exceptions */#endif
timer_init,
/* initialize timer */
/* initialize environment */
init_baudrate,
/* initialze baudrate settings */
serial_init,
/* serial communications setup */
console_init_f,
/* stage 1 init of console */
display_banner,
/* say that we are here */#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,
/* display cpu info (and speed) */#endif#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard,
/* display board info */#endif#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,#endif
dram_init,
/* configure available RAM banks */#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
arm_pci_init,#endif
display_dram_config,
&&&&&& 我们来看看env_init这个函数,其代码如下:
int env_init(void){
/* use default */
gd-&env_addr = (ulong)&default_environment[0];
gd-&env_valid = 1;#ifdef CONFIG_DYNAMIC_MMC_DEVNO
extern int get_mmc_env_devno(void);
mmc_env_devno = get_mmc_env_devno();#else
mmc_env_devno = CONFIG_SYS_MMC_ENV_DEV;#endif
return 0;}
&&&&&& 可以看出在这里将default_environment加载进入系统,default_environment对应的部分代码如下:
uchar default_environment[] = {
CONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS#endif
&&&&&& 而CONFIG_EXTRA_ENV_SETTINGS则是在我们对应的BSP的头文件中定义了,如下:
CONFIG_EXTRA_ENV_SETTINGS
&netdev=eth0\0&
&ethprime=FEC0\0&
&bootfile=uImage\0&
&loadaddr=0x&
&rd_loadaddr=0x70D00000\0&
&bootargs=console=ttymxc0 init=/init & \
&androidboot.console=ttymxc0 video=mxcdi1fb:RGB666,XGA & \
&ldb=di1 di1_primary pmem=32M,64M fbmem=5M gpu_memory=64M\0& \
&bootcmd_SD=mmc read 0 ${loadaddr} 0x800 0x2000;& \
&mmc read 0 ${rd_loadaddr} 0x\0& \
&bootcmd=run bootcmd_SD; bootm ${loadaddr} ${rd_loadaddr}\0& \
&&&&&& 再来看看check_recovery_mode这个函数中的代码,具体代码如下:
/* export to lib_arm/board.c */void check_recovery_mode(void){
if (check_key_pressing())
setup_recovery_env();
else if (check_recovery_cmd_file()) {
puts(&Recovery command file founded!\n&);
setup_recovery_env();
&&&&&& 可以看到在这里通过check_key_pressing这个函数来检测组合按键,当有对应的组合按键按下时,将会进入到recovery模式,这也正是各大android论坛里讲到刷机时都会提到的power+音量加键进入recovery模式的原因。那么check_recovery_cmd_file又是在什么情况下执行的呢?这个也正是这篇文章所要讲的内容之处。
&&&&&& 先来看看check_recovery_cmd_file这个函数中的如下这段代码:
int check_recovery_cmd_file(void){
switch (get_boot_device()) {
case MMC_BOOT:
case SD_BOOT:
for (i = 0; i & 2; i++) {
block_dev_desc_t *dev_desc = NULL;
struct mmc *mmc = find_mmc_device(i);
dev_desc = get_dev(&mmc&, i);
if (NULL == dev_desc) {
printf(&** Block device MMC %d not supported\n&, i);
mmc_init(mmc);
if (get_partition_info(dev_desc, CONFIG_ANDROID_CACHE_PARTITION_MMC,
printf(&** Bad partition %d **\n&,CONFIG_ANDROID_CACHE_PARTITION_MMC);
part_length = ext2fs_set_blk_dev(dev_desc, CONFIG_ANDROID_CACHE_PARTITION_MMC);
if (part_length == 0) {
printf(&** Bad partition - mmc %d:%d **\n&, i, CONFIG_ANDROID_CACHE_PARTITION_MMC);
ext2fs_close();
if (!ext2fs_mount(part_length)) {
printf(&** Bad ext2 partition or &
&disk - mmc %d:%d **\n&,
i, CONFIG_ANDROID_CACHE_PARTITION_MMC);
ext2fs_close();
filelen = ext2fs_open(CONFIG_ANDROID_RECOVERY_CMD_FILE);
ext2fs_close();
&&&&&& 主要来看看下面这个ext2fs_open所打开的内容,CONFIG_ANDROID_RECOVERY_CMD_FILE,这个正是上面所提到的rocovery cmd file的宏定义,内容如下:
#define CONFIG_ANDROID_RECOVERY_CMD_FILE
&/recovery/command&
&&&&&& 当检测到有这个文件存在时,将会进入到setup_recovery_env这个函数中,其相应的代码如下:
void setup_recovery_env(void){
char *env, *boot_args, *boot_
int bootdev = get_boot_device();
boot_cmd = supported_reco_envs[bootdev].
boot_args = supported_reco_envs[bootdev].
if (boot_cmd == NULL) {
printf(&Unsupported bootup device for recovery\n&);
printf(&setup env for recovery..\n&);
env = getenv(&bootargs_android_recovery&);
/* Set env to recovery mode */
/* Only set recovery env when these env not exist, give user a
* chance to change their recovery env */
setenv(&bootargs_android_recovery&, boot_args);
env = getenv(&bootcmd_android_recovery&);
setenv(&bootcmd_android_recovery&, boot_cmd);
setenv(&bootcmd&, &run bootcmd_android_recovery&);}
&&&&&& 在这里主要是将bootcmd_android_recovery这个环境变量加到uboot启动的environment中,这样当系统启动加载完root fs之后将不会进入到android的system中,而是进入到了recovery这个轻量级的小UI系统中。
&&&&&& 下面我们来看看为什么在uboot的启动环境变量中加入bootcmd_android_recovery这些启动参数的时候,系统就会进入到recovery模式下而不是android system,先看看bootcmd_android_recovery相应的参数:
#define CONFIG_ANDROID_RECOVERY_BOOTARGS_MMC \
&setenv bootargs ${bootargs} init=/init root=/dev/mmcblk1p4&
&rootfs=ext4 video=mxcdi1fb:RGB666,XGA ldb=di1 di1_primary&#define CONFIG_ANDROID_RECOVERY_BOOTCMD_MMC
&run bootargs_android_&
&mmc read 0 ${loadaddr} 0x800 0x2000;bootm&
&&&&&& 可以看到在进入recovery模式的时候这里把root的分区设置成了/dev/mmcblk1p4,再来看看在系统烧录的时候对整个SD卡的分区如下:
sudo mkfs.vfat -F 32 ${NODE}${PART}1 -n sdcardssudo mkfs.ext4 ${NODE}${PART}2 -O ^extent -L systemsudo mkfs.ext4 ${NODE}${PART}4 -O ^extent -L recoverysudo mkfs.ext4 ${NODE}${PART}5 -O ^extent -L datasudo mkfs.ext4 ${NODE}${PART}6 -O ^extent -L cache
&&&&&& 这里NODE = /dev/mmcblk1为挂载点,PART = p或者为空,作为分区的检测。可以看出上面在给recovery分区的时候,用的是/dev/mmcblk1p4这个分区,所以当设置了recovery启动模式的时候,root根目录就被挂载到/dev/mmcblk1p4这个recovery分区中来,从而进入recovery模式。
4&&&&&& recovery
关于android的recovery网上有各种版本的定义,这里我总结一下:所谓recovery是android下加入的一种特殊工作模式,有点类似于windows下的gost,系统进入到这种模式下时,可以在这里通过按键选择相应的操作菜单实现相应的功能,比如android系统和数据区的快速格式化(wipe);系统和用户数据的备份和恢复;通过sd卡刷新的rom等等。典型的recovery界面如下:
图2 recovery界面
&&&&&& Recovery的源代码在bootable/recovery这个目录下面,主要来看看recovery.c这个文件中的main函数:
Int main(int argc, char **argv) {
ui_init();
ui_set_background(BACKGROUND_ICON_INSTALLING);
load_volume_table();
while ((arg = getopt_long(argc, argv, &&, OPTIONS, NULL)) != -1) {
switch (arg) {
case 'p': previous_runs = atoi(optarg); break;
case 's': send_intent = break;
case 'u': update_package = break;
case 'w': wipe_data = wipe_cache = 1; break;
case 'c': wipe_cache = 1; break;
case 'e': encrypted_fs_mode = toggle_secure_fs = 1; break;
case 't': ui_show_text(1); break;
LOGE(&Invalid command argument\n&);
device_recovery_start();
if (update_package)
// For backwards compatibility on the cache partition only, if
// we're given an old 'root' path &CACHE:foo&, change it to
// &/cache/foo&.
if (strncmp(update_package, &CACHE:&, 6) == 0)
int len = strlen(update_package) + 10;
char* modified_path = malloc(len);
strlcpy(modified_path, &/cache/&, len);
strlcat(modified_path, update_package+6, len);
printf(&(replacing path \&%s\& with \&%s\&)\n&,
update_package, modified_path);
update_package = modified_
//for update from &/mnt/sdcard/update.zip&,but at recovery system is &/sdcard& so change it to &/sdcard&
//ui_print(&before:[%s]\n&,update_package);
if (strncmp(update_package, &/mnt&, 4) == 0)
//jump the &/mnt&
update_package +=4;
ui_print(&install package from[%s]\n&,update_package);
printf(&\n&);
property_list(print_property, NULL);
printf(&\n&);
int status = INSTALL_SUCCESS;
.// Recovery strategy: if the data partition is damaged, disable encrypted file systems.
// This preventsthe device recycling endlessly in recovery mode.
if (update_package != NULL)
status = install_package(update_package);
if (status != INSTALL_SUCCESS)
ui_print(&Installation aborted.\n&);
erase_volume(&/data&);
erase_volume(&/cache&);
} else if (wipe_data) {
if (device_wipe_data()) status = INSTALL_ERROR;
if (erase_volume(&/data&)) status = INSTALL_ERROR;
if (wipe_cache && erase_volume(&/cache&)) status = INSTALL_ERROR;
if (status != INSTALL_SUCCESS) ui_print(&Data wipe failed.\n&);
} else if (wipe_cache) {
if (wipe_cache && erase_volume(&/cache&)) status = INSTALL_ERROR;
if (status != INSTALL_SUCCESS) ui_print(&Cache wipe failed.\n&);
status = INSTALL_ERROR;
// No command specified
if (status != INSTALL_SUCCESS) ui_set_background(BACKGROUND_ICON_ERROR);
//Xandy modify for view the install infomation
//if (status != INSTALL_SUCCESS || ui_text_visible())
if(status != INSTALL_SUCCESS)
prompt_and_wait();
// Otherwise, get ready to boot the main system...
finish_recovery(send_intent);
ui_print(&Rebooting...\n&);
reboot(RB_AUTOBOOT);
return EXIT_SUCCESS;}
&&&&&& 在这里首先完成recovery模式轻量级的UI系统初始化,设置背景图片,然后对输入的参数格式化,最后根据输入的参数进行相应的操作,如:安装新的ROM、格式化(wipe)data及cache分区等等;值得注意的是刷新ROM的时候,要制作相应的update.zip的安装包,这个在最后一章节讲述,这里遇到的一个问题是在recovery模式下sd卡的挂载点为/sdcard而不是android系统下的/mnt/sdcard,所以我在这里通过:
//for update from &/mnt/sdcard/update.zip&,but at recovery system is &/sdcard& so change it to &/sdcard&
//ui_print(&before:[%s]\n&,update_package);
if (strncmp(update_package, &/mnt&, 4) == 0)
//jump the &/mnt&
update_package +=4;
这样的操作跳过了上层传过来的/mnt这四个字符。另外一个值得一提的是,传入这里的这些参数都是从/cache/recovery/command这个文件中提取。具体对command文件的解析过程这里不再讲述,可能通过查看recovery.c这个文件中的get_args函数。
&&&&&& 那么command这个文件是在什么情况下创建的呢?下面我们就来看看吧!
5&&&&&& 恢复出厂设置和固件升级
在android的系统设备中进入“隐私权-&恢复出厂设置-&重置手机”将为进入到恢复出厂设置的状态,这时将会清除data、cache分区中的所有用户数据,使得系统重启后和刚刷机时一样了。另外为了方便操作我们还可在“隐私权-&固件升级-&刷新ROM”这里加入了固件升级这一项。
在讲述这些内容之前,我们有必要来看看/cache/recovery/command这个文件相应的一些recovery命令,这些命令都由android系统写入。所有的命令如下:
--send_intent=anystring ―― write the text out to recovery.intent*
--update_package=root:path —— verify install an OTA package file*
--wipe_data —— erase user data (and cache), then reboot*
--wipe_cache —— wipe cache (but not user data), then reboot
5.1 恢复出厂设置
在frameworks/base/services/java/com/android/server/masterClearReceiver.java
这个文件中有如下代码:
public class MasterClearReceiver extends BroadcastReceiver {
private static final String TAG = &MasterClear&;
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
if (!&&.equals(intent.getStringExtra(&from&))) {
Slog.w(TAG, &Ignoring master clear request -- not from trusted server.&);
Slog.w(TAG, &!!! FACTORY RESET !!!&);
// The reboot call is blocking, so we need to do it on another thread.
Thread thr = new Thread(&Reboot&) {
public void run() {
if (intent.hasExtra(&enableEFS&)) {
RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra(&enableEFS&, false));
RecoverySystem.rebootWipeUserData(context);
Log.wtf(TAG, &Still running after master clear?!&);
} catch (IOException e) {
Slog.e(TAG, &Can't perform master clear/factory reset&, e);
thr.start();
&&&&&& 当app中操作了“恢复出厂设置”这一项时,将发出广播,这个广播将在这里被监听,然后进入到恢复出厂设置状态,我们来看看rebootWipeUserData这个方法的代码:
public static void rebootWipeUserData(Context context) throws IOException {
final ConditionVariable condition = new ConditionVariable();
Intent intent = new Intent(&android.intent.action.MASTER_CLEAR_NOTIFICATION&);
context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,
new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
condition.open();
}, null, 0, null, null);
// Block until the ordered broadcast has completed.
condition.block();
bootCommand(context, &--wipe_data&);
我们可以看到在这里参入了“--wipe_data”这个参数,并把这条命令写入到command这个文件中去了,在进入recovery模式的时候解析到这条命令时就会清除data和cache中的数据了。
再来看看bootCommand这个方法里的代码:
private static void bootCommand(Context context, String arg) throws IOException {
RECOVERY_DIR.mkdirs();
// In case we need it
COMMAND_FILE.delete();
// In case it's not writable
LOG_FILE.delete();
FileWriter command = new FileWriter(COMMAND_FILE);
command.write(arg);
command.write(&\n&);
} finally {
command.close();
// Having written the command file, go ahead and reboot
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
pm.reboot(&recovery&);
throw new IOException(&Reboot failed (no permissions?)&);
&&&&&& 其中COMMAND_FILE这个成员的定义如下:
/** Used to communicate with recovery.
See bootable/recovery/recovery.c. */private static File RECOVERY_DIR = new File(&/cache/recovery&);private static File COMMAND_FILE = new File(RECOVERY_DIR, &command&);
&&&&&& 至此恢复出厂设置的命令就写入了recovery cmd file中去了,通过pm.reboot(“recovery”);重启系统,系统就自动进入到recovery模式自动清除用户数据后再重启系统。
5.2 固件升级
固件升级的流程和恢复出厂设置差不多,不同之处是入command这个文件中写入的命令不一样,下面是恢复出厂设置时的写命令的代码:
public static void installPackage(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
Log.w(TAG, &!!! REBOOTING TO INSTALL & + filename + & !!!&);
String arg = &--update_package=& +
bootCommand(context, arg);
&&&&&& 这里的packageFile是由上层app传入的,内容如下:
File packageFile = new File(&/sdcard/update.zip&);RecoverySystem.installPackage(context, packageFile);
&&&&&& 这样当系统重启进入到recovery模式时将会自动查找sdcard的根目录下是否有update.zip这个文件,如果有将会进入到update状态,否则会提示无法找到update.zip!
&&&&&& 至此我们已经明白了android的整个recovery流程,下面将讲讲update.zip也就是各大论坛里讲到的ROM的制作过程。
6&&&&&& ROM的制作
我们解压update.zip这个文件,可发现它一般打包了如下这几个文件:&
图3 &ROM包中的内容
或者没有updates而是system这个目录,不同的原因是我这里在updates里放置的是system.img等镜像文件,这些文件都由源码编译而来。而如果是system目录,这里一般放的是android系统的system目录下的内容,可以是整个android系统的system目录,也可以是其中的一部分内容,如一些so库等等,这样为补丁的发布提供了一个很好的解决办法,不需要更新整个系统,只需要更新一部分内容就可以了!
来看看META-INF/com/google/android这个目录下的内容,在这里就两个文件,一个是可执行的exe文件update-binary,这个文件在进入update状态的用于控制ROM的烧入,具体的代码在recovery下的install.c文件中的try_update_binary这个函数中;另一个是updater-script,这个文件里是一些脚本程序,具体的代码如下:
# Mount system for check figurepoint etc.# mount(&ext4&, &EMMC&,&/dev/block/mmcblk0p2&, &/system&);# Make sure Check system image figurepoint first.# uncomment below lines to check# assert(file_getprop(&/system/build.prop&, &ro.build.fingerprint&) == &freescale/imx53_evk/imx53_evk/imx53_evk:2.2/FRF85B/eng.b14.145340:eng/test-keys&);# assert(getprop(&ro.build.platform) == &imx5x&);# unmount(&/system&);show_progress(0.1, 5);package_extract_dir(&updates&, &/tmp&);#Format system/data/cache partitionui_print(&Format disk...&);format(&ext4&,&EMMC&,&/system&);format(&ext4&,&EMMC&,&/data&);format(&ext4&,&EMMC&,&/cache&);show_progress(0.2, 10);# Write u-boot to 1K position.# u-boot binary should be a no padding uboot!# For eMMC(iNand) device, needs to unlock boot partition.ui_print(&writting u-boot...&);sysfs_file_write(& /sys/class/mmc_host/mmc0/mmc0:0001/boot_config&, &1&);package_extract_file(&files/u-boot.bin&, &/tmp/u-boot.bin&);#ui_print(&Clean U-Boot environment...&);show_progress(0.2, 5);#simple_dd(&/dev/zero&,&/dev/block/mmcblk0&,2048);simple_dd(&/tmp/u-boot.bin&, &/dev/block/mmcblk0&, 2048);#access user partition,and enable boot partion1 to bootsysfs_file_write(&/sys/class/mmc_host/mmc0/mmc0:0001/boot_config&, &8&);
#Set boot width is 8bitssysfs_file_write(&/sys/class/mmc_host/mmc0/mmc0:0001/boot_bus_config&, &2&);show_progress(0.2, 5);
ui_print(&extract kernel image...&);package_extract_file(&files/uImage&, &/tmp/uImage&);# Write uImage to 1M position.ui_print(&writting kernel image&);simple_dd(&/tmp/uImage&, &/dev/block/mmcblk0&, 1048576);ui_print(&extract uramdisk image...&);package_extract_file(&files/uramdisk.img&, &/tmp/uramdisk.img&);# Write uImage to 1M position.ui_print(&writting uramdisk image&);simple_dd(&/tmp/uramdisk&, &/dev/block/mmcblk0&, 6291456);show_progress(0.2, 50); # You can use two way to update your system which using ext4 system.# dd hole system.img to your mmcblk0p2 partition.package_extract_file(&files/system.img&, &/tmp/system.img&);ui_print(&upgrading system partition...&);simple_dd(&/tmp/system.img&, &/dev/block/mmcblk0p2&, 0);show_progress(0.1, 5);
相应的脚本指令可在说明可对应源码可在recovery包中的install.c这个文件中找到。
&&&&&& 在bootable/recovery/etc下有原始版的脚本代码update-script,但在recovery下的updater.c这个文件中有如下定义:
// Where in the package we expect to find the edify script to execute.// (Note it's &updateR-script&, not the older &update-script&.)#define SCRIPT_NAME &META-INF/com/google/android/updater-script&
&&&&&& 所在使用这个原版的脚本的时候要将update-script更成updater-script,需要注意!
&&&&&& 我们可以发现在bootable/recovery/etcMETA-INFO/com/google/android目录下少了一个update-binary的执行文件,在out/target/product/YOU_PRODUCT/system/bin下面我们可以找到updater,只要将其重名字为update-binary就可以了!
&&&&&& 有了这些准备工作,我们就可以开始制作一个我们自己的ROM了,具体步骤如下:
Xandy@ubuntu:~$ mkdir recovery*
Xandy@ubuntu:~$ cd recovery 然后将上面提到的bootable/recovery/etc下的所有内容拷贝到当前目录下并删掉init.rc这个文件*
编译./META-INF/com/google/android/updater-script这个文件使达到我们想要的烧写控制,如果是烧写system.img这样的镜像文件,可以直接用我上面提到的updater-script这个脚本代码。*
拷贝相应的需要制作成ROM的android文件到updates目录或者system目录下,这个得根据系统的需要决定。*
Xandy@ubuntu:~/recovery$ mkdir res*
Xandy@ubuntu:~/recovery$ ~/myandroid/out/host/linux-x86/framework/dumpkey.jar ~/myandroid/build/target/product/security/testkey.x509.pem & res/keys 这里创建一个目录用于存储系统的key值*
zip /tmp/recovery.zip -r ./META-INF ./updates ./res 将所有文件打包*
java -jar ./tools/signapk.jar -w ./tools/testkey.x509.pem ./tools/testkey.pk8 /tmp/recovery.zip update.zip 我在recovery目录下创建了一个tools目录,里面放置了sygnapk.jar、testkey.pk8、testkey.x509.pem这几个文件用于java签名时用
经过上面这几步之后就会在recovery目录生成一个update.zip的文件,这个就是我们自己制作的ROM文件,将它拷到sdcard的根目录下,在系统设置里操作进入到“固件升级状态”,等到系统重启时,就会看到已经开始自行格式化data和cache分区,稍后就开始出现进度条向相应分区里烧写uboot、kernel、android system的文件了!
图4 烧入新ROM
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1916535次
积分:18140
积分:18140
排名:第331名
原创:51篇
转载:725篇
评论:241条
(4)(7)(2)(1)(5)(5)(7)(8)(7)(3)(5)(11)(4)(5)(9)(6)(4)(8)(8)(10)(13)(10)(21)(24)(6)(4)(29)(19)(12)(24)(12)(4)(6)(5)(16)(27)(23)(17)(5)(15)(23)(50)(6)(5)(19)(11)(9)(2)(13)(15)(19)(1)(2)(2)(11)(8)(2)(14)(1)(9)(6)(8)(2)(2)(29)(41)(24)(36)

我要回帖

更多关于 arm ubuntu 系统img 的文章

 

随机推荐