Android ROM 刷机脚本 updater-script 的基本流程和初级语句说明

转载自: http://www.verydemo.com/demo_c131_i6403.html

对于很多狂热于刷机爱好的机友们来说最高的追求就是自制刷机包,那么自制刷机包最重要的不是程序的内置收集,也不是美化或者精简,最重要的是对于刷机包的刷机脚本的编写,鉴于很多同学想学却又找不到资料,今天拉拉果断决定给大家分享一份自己收集整理的刷机脚本函数释义教程。

简单说说刷机脚本的相关知识, 以及简单的语句说明.

目的不是让你通过本帖学会如何做刷机脚本,那不是一下子可以做到的事情.
但是至少可以通过本帖子,让你对刷机脚本有一个初步的了解,并且可以初步动手修改相对简单的内容, 例如制作升级包.

以下说明,都以我的Reflex S Data2Ext 2.0.2c 整包ROM为例子说明, 把update的过程流程化,更加有助于理解.

首先说明刷机脚本的路径, 其实很多人,包括部分ROM作者, 都不知道这个文件的存在.位于刷机包的如下路径:

  1. META-INF\com\google\android\updater-script


复制代码

刷机过程其实很简单, 只要你理解了流程, 和相关的语句.
一般来说, 刷机就是如下的步骤:

  1. 开始.
  2. 清理userdata, system, cache, dalvik-cache等 (这是一个可选的步骤,由ROM作者依据ROM的特性去决定是否要采用)
  3. 挂载userdata, system, sdext (其中sdext为可选挂载, 依据ROM特性决定)
  4. 释放对应的文件/文件夹到对应的区域, 例如刷机包内的目录data对应的释放到手机的userdata区域
  5. Symlink,这个是必须的动作, 这个有问题, 会导致ROM出现一些问题, 特别是错误的链接或者不存在的链接,很容易引发问题.
  6. 设置权限,这一个步骤也很重要, 关系到ROM能否正常使用, Android是base在linux基础上的, 对于文件的权限非常重要, 没有权限,一个应用程序是无法被执行或者读写的.
  7. 刷入内核引导文件boot.img
  8. 取消挂载的各个分区, 刷机结束.

复制代码

大概步骤就这样, 这个过程非常明了和直接, 下面我具体举例说明各个步骤的做法.
1. 开始准备刷机.
开始最简单, 实际上就是就是检测硬件, 打印相关信息,提示开始刷机.
其中可能用到的部分函数做个简单介绍:
ui_print: 就是在recovery下打印文字给用户阅览.
getprop: 获取手机对应的属性
assert: 你可以理解为辅助执行多行脚本命令
例如如下我的部分开始代码:

  1. ui_print(” “);
  2. assert(getprop(“ro.product.device”) == “bravo” ||getprop(“ro.build.product”) == “bravo” ||getprop(“ro.product.board”)
  3. ==“bravo”);
  4. ui_print(“. Reflex S Data2Ext Installation .”);
  5. ui_print(” “);
  6. ui_print(“Installing Gingerbread 2.3.3 – Sense 2.1…”);
  7. ui_print(” “);

复制代码

首先开始答应一行空行,编译和之前的文字区别开来.
然后用assert完成对手机的产品设备型号的检测
最后打印, 开始安装该ROM.

2. 清理
这个过程是可选的,有的rom不需要wipe直接升级,就无需这个过程,有的ROM必须完全wipe才可以刷机,否则会出问题,那么rom作者为了担心
你因为没有wipe而导致出了问题, 就在脚本里面处理了,尽量帮助你避免产生问题.
例如我这个data2ext的ROM, 如果不wipe, 会产生一些问题, 例如FC, UID错误等, 就必须wipe,但是为了不让用户的懒惰成为找我问问题的麻烦,我就主动帮他们”wipe”了所有必须wipe的内容.
其中可能用到的部分函数做个简单介绍:
fromat: 格式化相关区域的函数
delete_recursive: 可以直接删除一个目录.
如下我的部分代码摘抄如下:

  1. ui_print(” Clean up cache…”);
  2. format(“MTD”, “cache”);
  3. delete_recursive(“/data/dalvik-cache”);
  4. delete_recursive(“/sdext/dalvik-cache”);

复制代码

首先打印我要开始清理cache了
然后格式化cache, 删除userdata下的dalvik-cache,删除sd卡ext分区的dalvik-cache.
其实我这里代码还是有一些问题的,可能sdext都还没有挂载我就试图删除了.这个就属于脚本的隐患bug了.

3挂载和4释放文件, 我是按照区域来组合做的, 如下分别是userdata的处理和system的处理.
其中可能用到的部分函数做个简单介绍:
umount/mount: 分别是取消挂载和挂载相关的区域函数.
package_extract_dir: 你可以理解为复制刷机包内的指定目录到手机的指定区域.

  1. ui_print(” Unpacking DATA files…”);
  2. unmount(“/data”);
  3. format(“MTD”, “userdata”);
  4. mount(“MTD”, “userdata”, “/data”);
  5. package_extract_dir(“data”, “/data”);
  6. ui_print(” Unpacking SYSTEM files…”);
  7. unmount(“/system”);
  8. format(“MTD”, “system”);
  9. mount(“MTD”, “system”, “/system”);
  10. package_extract_dir(“system”, “/system”);

复制代码

为了避免出问题,首先取消挂载, 然后格式化该区域, 然后再挂载,确保挂载没有问题.
然后复制需要的文件.

5和6相比前面的一些内容,属于比较难懂一点的,需要有linux相关的知识, 不再更多阐述, 贴些代码,简单说下.
其中可能用上的部分函数介绍:
symlink: 所谓的符号链接, 当然, windows的用户不怎么容易了解, 建议多熟悉下Linux相关内容.
set_perm_recursive: 你可以理解为设置目录权限
如下代码, 连接../xbin/su到/system/bin/su这个程序.

  1. ui_print(” Symlinking now…”);
  2. symlink(“../xbin/su”, “/system/bin/su”);

复制代码

如下代码,设置相关的权限.

  1. ui_print(” Setup permissions now…”);
  2. set_perm_recursive(0, 0, 0755, 0644, “/system”);
  3. set_perm_recursive(0, 2000, 0755, 0755, “/system/bin”);
  4. set_perm_recursive(0, 2000, 0755, 0755, “/system/app”);

复制代码

至于刷入内核引导文件boot.img,
如下, 用assert函数实现了, 解压内核到临时区域, 写入内核文件, 删除临时文件的过程.

  1. ui_print(” Writing Boot.img…”);
  2. assert(package_extract_file(“boot.img”, “/tmp/boot.img”),write_raw_image(“/tmp/boot.img”, “boot”),delete(“/tmp/boot.img”));

复制代码

最后,结束, 取消挂载所有区域, 提示结束.
如下代码:

  1. ui_print(” “);
  2. ui_print(” Flash finished…Enjoy it!”);
  3. unmount(“/system”);
  4. unmount(“/data”);

复制代码

可能大家看了还是模模糊糊的, 没关系, 没有相关的知识, 确实不容易一下子看明白, 但是饭一口口吃, 知识也是一点点懂的,抛砖引玉,希望给与大家一点点帮助.


 

下面是用在Edify的Updater-script中的函数例子:

函数名称: mount

函数语法: mount(fs_type, partition_type, location, mount_point)

参数详解:

fs_type-----------------"yaffs2" 或 "ext4"

partition_type----------"MTD" 或 "EMMC"

location-----------------分区(partition) 或 驱动器(device)

mount_poin------------挂载文件系统的目标文件夹(targetfolder to mount FS)

作用解释: 挂载一个文件系统到指定的挂载点

返回值: 挂载成功则返回挂载点,失败返回null

函数示例:

mount("MTD", "system", "/system");挂载system分区,设置返回指针"/system”

mount("vfat", "/dev/block/mmcblk1p2", "/system");挂载/dev/block/mmcblk1p2,返回指针"/system”

函数名称:is_mounted

函数语法: is_mounted(mount_point)

参数详解: mount_point-----------字符串,检查是否已经挂载的挂载点

作用解释: 检查文件系统是否挂载

返回值: 挂载成功则返回挂载点,失败返回null

函数示例:

函数名称:unmount

函数语法: unmount(mount_point)

参数详解: mount_point-----------字符串,要解除挂载的挂载点

作用解释: 解除文件系统挂载

返回值: 解除挂载成功则返回挂载点,失败返回null

函数示例:

unmount("/system"); 卸载/system分区

函数名称:format

函数语法: format(fs_type, partition_type, location)

参数详解:

fs_type-----------------字符串,数据为"yaffs2" 或 "ext4"

partition_type----------字符串, "MTD" 或 "EMMC"

location-----------------字符串, 分区(partition) 或 驱动器(device)

作用解释: 格式化为指定的文件系统

函数示例:

format("MTD", "system");格式化system分区

函数名称:delete

函数语法: delete(file1, file2, ..., fileN)

参数详解: 字符串,要删除的文件

作用解释: 删除一个文件。最少指定一个文件;多个文件可以做为多个参数指定

函数示例:

delete("/data/zipalign.log");删除文件/data/zipalign.log

函数名称:delete_recursive

函数语法: delete_recursive(dir1, dir2,...,dirN)

参数详解: 字符串,要递归删除的目录

作用解释: 删除文件夹及其包含的所有内容。最少指定1个目录;多个目录可以做为多个参数指定

函数示例:

delete_recursive("/data/dalvik-cache");删除文件夹/data/dalvik-cache

函数名称:show_progress

函数语法: show_progress(frac, sec)

参数详解:

frac----------------------进度完成数值

Sec----------------------总秒数

作用解释: 显示在Recovery系统中进度

函数示例:

show_progress(0.1,10);show_progress下面的操作可能进行10s,完成后进度条前进0.1(也就是10%)

函数名称:set_progress

函数语法: set_prograss(frac)

参数详解:

frac---------------------进度数值

函数示例:

函数名称: package_extract_dir

函数语法: package_extract_dir(package_path, destination_path)

参数详解: package_path----------字符串,升级包内要提取的目录

destination_path--------字符串,提取文件的目标目录

作用解释: 提取升级包内目录中的所有文件到指定的目标目录

函数示例:

package_extract_dir("system","/system");释放ROM包里system文件夹下所有文件和子文件夹至/system

函数名称:package_extract_file

函数语法: package_extract_file(package_path) 或package_extract_file(package_path, destination_path)

参数详解: package_path----------字符串,升级包内要提取的文件

destination_path-------字符串,提取文件的目标目录

作用解释: 提取升级包内的单个文件到指定的目标目录

函数示例:

package_extract_file("my.zip", "/system");解压ROM包里的my.zip文件至/system

函数名称:file_getprop

函数语法: file_getprop(file, key)

参数详解:

file----------------------字符串,要检查的文件名

Key----------------------字符串,返回数据中的文件的键名字

作用解释: 在格式"key"="value"的文件中取得文件属性值

函数示例:

函数名称:symlink

函数语法: symlink(target, src1, src2, ..., srcN)

参数详解:

target-------------------字符串,符号链接的目标

srcX      ---------------------字符串,要创建的符号链接的目标点

作用解释: 在创建新的符号链接之前,要断开已经存在的符号链接

函数示例:

symlink("toolbox","/system/bin/ps");建立指向toolbox的符号链接/system/bin/ps

函数名称:set_perm

函数语法: set_perm(uid, gid, mode, file1, file2, ..., fileN)

参数详解:

uid----------------------用户ID(user id)

Gid----------------------用户组ID(group id)

Mode--------------------权限模式(permission mode)

fileX---------------------要设置许可的文件(file to set permission on)

作用解释: 设置单个文件或一系列文件的权限,最少指定1个文件,前4个参数是必须的

函数示例:

set_perm(0,2000,0550,"system/etc/init.goldfish.sh");设置手机system中的etc/init.goldfish.sh的用户为root,用户组为shell,所有者以及所属用户组成员可以进行读取和执行操作,其他用户无操作权限)这里0代表用户为root2000代表用户组为shell我们来说明0550这组数据,这组数据的最后三位550,分别代表“所有者\组用户\其他用户”的权限,也就是我们在RE管理中“用户\群组\其他”三行。我们以XXX来表示这三组权限,其中:

×=4 读的权限
×=2 写的权限
×=1 执行的权限

我们必须首先了解用数字表示的属性的含义:0表示没有权限,1表示可执行权限,2表示可写权限,4表示可读权限,然后将其相加。所以数字属性的格式应为3个从0到7的八进制数。例如,如果想让某个文件的属主有"读/写"二种权限,需要把4(可读)+2(可写)=6(读/写)。若要rwx属性则4+2+1=7;若要rw-属性则4+2=6;若要r-x属性则4+1=5。常用修改权限的命令:

Set_perm 0 0 0600 ××× (只有所有者有读和写的权限)
Set_perm 0 0 0644 ××× (所有者有读和写的权限,组用户只有读的权限)
Set_perm 0 0 0700 ××× (只有所有者有读和写以及执行的权限)
Set_perm 0 0 0666 ××× (每个人都有读和写的权限)
Set_perm 0 0 0777 ××× (每个人都有读和写以及执行的权限)

函数名称:set_perm_recursive

函数语法: set_perm_recursive(uid, gid, dirmode, filemode, dir1, dir2,...dirN)

参数详解:

uid----------------------用户ID(user id)

Gid----------------------用户组ID(group id)

Dirmode----------------指定目录内的目录的权限

Filemode---------------指定目录内的文件的权限

dirX---------------------要设置权限的目标

作用解释: 设置单个目录或一系列目录的里面的所有文件的权限,最少指定1个目录,5个参数都是必须的

函数示例:

set_perm_recursive 0 0 0755 0644SYSTEM:app;设置手机system/app文件夹及其中文件的用户为root,用户组为root,app文件夹权限为所有者可以进行读、写、执行操作,其他用户可以进行读取和执行操作,其中的文件的权限为所有者可以进行读写操作,其他用户可以进行读取操作

函数名称:getprop

函数语法: getprop(key)

参数详解: key---------------------字符串,想要系统返回的属性

作用解释: 这个函数是用来返指定的属性的值。它是用来从build.props文件中查询手机的信息的。

函数示例:

函数名称:write_raw_image

函数语法: write_raw_image(file, partition)

参数详解:

file----------------------字符串,要读取的Img源文件

Partition-----------------字符串,要写入Img文件的目标分区

作用解释: 这个函数是用来写Img文件到分区

函数示例:

write_raw_image("/tmp/boot.img","boot")将yaffs2格式的boot包直接写入boot分区

函数名称:apply_patch

函数语法: apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1_1,patch_1, ..., sha1_x, patch1_x)

参数详解:

srcfile-------------------字符串,要打补丁的源文件(要读入的文件)

Tgtfile-------------------字符串,补丁文件要写入的目标文件

tgtsha1-----------------字符串,写入补丁文件的目标文件的sha1哈希值

sha1_x------------------字符串,要写入目标文件的补丁数据的sha1哈希值

patch1_x----------------字符串,实际上应用到目标文件的补丁

作用解释: 这个函数是用来打补丁到文件。

函数示例:

函数名称:apply_patch_check

函数语法: apply_patch_check(file, sha1_1, ..., sha1_x)

参数详解:

file----------------------字符串,要检查的文件

sha1_x------------------要检查的哈希值

作用解释: 检查文件是否已经被打补丁,或者能不能被打补丁。需要检查“applypatch_check”函数调用的源代码

函数示例:

函数名称:apply_patch_space

函数语法: apply_patch_space(bytes)

参数详解: bytes-------------------检查的字节的数字

作用解释: 检查缓存来确定是否有足够的空间来写入补丁文件并返回一些数据。

函数示例:

函数名称:read_file

函数语法: read_file(filename)

参数详解: filename----------------字符串,要读取内容的文件名

作用解释: 这个函数返回文件的内容

函数示例:

函数名称:sha1_check

函数语法: sha1_check(data) 或 sha1_check(data, sha1_hex, ...,sha1_hexN)

参数详解:

data---------------------要计算sha1哈希值的文件的内容-必须是只读文件格式

sha1_hexN--------------文件数据要匹配的特定的十六进制sha1_hex哈希值字符串

作用解释:如果只指定data参数,这个函数返回data参数的十六进制sha1_hex哈希值字符串。其他参数用来确认你检查的文件是不是列表中的哈希值的一个。它返回匹配的哈希值,或者在没有匹配任何哈希值时返回空。

函数示例:

函数名称:ui_print

函数语法: ui_print(msg1, ..., msgN)

参数详解: msg----------------------字符串,要处理过程中输出给用户的信息

作用解释: 在脚本运行的时候,在控制台显示的信息。最少要指定1个参数,你可以指定额外的msg参数,并且它们会连接起来输了

函数示例: ui_print("It's ready!");屏幕打印It's ready!

函数名称:run_program

函数语法: run_program(prog, arg1, .., argN)

参数详解:

prog--------------------字符串,要执行的程序

argN--------------------字符串,要执行的程序的运行参数

作用解释: 以指定的参执行程序

函数示例:

run_program("/system/xbin/installbusybox.sh");运行installbusybox.sh脚本文件

函数名称:ifelse

函数语法: ifelse(condition, truecondition, falsecondition)

参数详解:

condition----------------要运算的表达式

Truecondition-----------当值为True时执行的 Edify脚本

Falsecodnition-----------当值为False时执行的 Edify脚本

作用解释: 这是If-then结构的Edify脚本语言。在真条件或非条件下语句可以是单条Edify命令或者脚本块。脚本块可以用圆括号来界定,用分号来隔开。

函数示例:

函数名称: abort

函数语法: abort()

参数详解: 没有参数

作用解释: 中止脚本执行

函数示例:

函数名称:assert

函数语法: assert(condition)

参数详解: condition---------------boolean

作用解释: 如果condition参数的计算结果为False,则停止脚本执行,否则继续执行脚本

函数示例:

assert(package_extract_file("boot.img","/tmp/boot.img"),write_raw_image("/tmp/boot.img","boot"),delete("/tmp/boot.img"))

执行package_extract_file,如果不返回错误则执行write_raw_image,如果write_raw_image不出错则执行delete

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值