这又是一篇补录的博客。此工作早在两个半月之前业已完成,只是因为当时很忙所以没有整理后放上来,而且还有一个小小的尾巴没有处理干净。今天,此处已然通过,故而一并合成完整记录。
主要按照 http://whiteboard.ping.se/Android/Debian 文中步骤,在 Ubuntu 14.04 下操作。详细步骤如下。
一、制作新的 boot.img
1、把上述链接页面内如下文本存为 init 文件,其中的 mmcblk1p2 要相应改成自己手机的 root 所在分区(W2013 正好不需修改),此文件将被应用于新的 boot.img 中;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#!/sbin/busybox sh # initramfs pre-boot init script # Mount the /proc and /sys filesystems /sbin/busybox mount -t proc none /proc /sbin/busybox mount -t sysfs none /sys /sbin/busybox mount -t tmpfs none /dev # Something (what?) needs a few cycles here /sbin/busybox sleep 1 # Populate /dev /sbin/busybox mdev -s # Mount the root filesystem, second partition on micro SDcard /sbin/busybox mount -t ext4 -o noatime,nodiratime,errors=panic /dev/mmcblk1p2 /mnt/root # Clean up /sbin/busybox umount /proc /sbin/busybox umount /sys /sbin/busybox umount /dev # Transfer root to SDcard exec /sbin/busybox switch_root /mnt/root /etc/init |
2、下载 http://busybox.net/downloads/binaries/latest/busybox-armv4tl;
3、寻找 SCH-W2013 的 PHYS_OFFSET,为 0x40000000(根据 /proc/iomem 里的 System RAM 项);有佐证 http://android.stackexchange.com/questions/44329/how-to-find-phys-offset-value-for-mkbootimg;
4、下载 mkbootimg:https://code.google.com/p/zen-droid/downloads/detail?name=mkbootimg;据说可以自己编译,见 https://gist.github.com/jberkel/1087757;
5、下载 unmkbootimg:http://whiteboard.ping.se/Android/Unmkbootimg;
6、找到 SCH-W2013 的 ROM,从中提取出 boot.img,再从后者中提取出 zImage;
7、执行以下命令,其中的 0x40000000 即步骤 3 里的数值:
1 2 3 4 5 6 7 8 9 10 |
# mkdir de-initramfs # cd de-initramfs # mkdir -p proc sys dev mnt/root sbin # cp ~/[Downloads]/busybox-armv4tl sbin/busybox # cp ~/[Saved Above]/init init # chmod a+x init sbin/busybox # find . | cpio --quiet -H newc -o | gzip > ../de-initramfs.cpio.gz # cd .. # mkbootimg --base 0x40000000 --kernel zImage --ramdisk de-initramfs.cpio.gz -o de-boot.img |
8、执行到 mkbootimg 时,发现报错 error while loading shared libraries: libstdc++.so.6;又找到了一个版本(64 位的):https://github.com/XT701/Tools/blob/1.0/mkbootimg.64bit;后来执行 adb 时又有相同问题,sudo apt-get install lib32stdc++6 彻底解决;
二、制作 Debian 环境
9、按照 Creating the Debian root file system 一节进行操作,两个阶段。
第一阶段在桌面 Linux 下:
1 2 3 4 5 |
# apt-get install debootstrap # mkdir /mnt/debian # mount -t ext4 /dev/sdc2 /mnt/debian # debootstrap --verbose --arch armel --foreign squeeze /mnt/debian http://ftp.nl.debian.org/debian # umount /mnt/debian |
没有问题。
第二阶段在手机上(adb shell 连通),原作者选择的加载点是 /root,实际操作不成功,因此在 /sdcard 下新建了 de-root 目录,而且 mount 时必须加 -t ext4 参数,否则不成功;原作者将 TMPDIR 指向 /tmp(手机中无此目录,第一次用 /data/local/tmp 代替了一下,后来想到这个应该是用于 chroot 之后的 apt,chroot 环境下是有此路径的,所以仍然应该用 /tmp):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# mount -t ext4 /dev/block/mmcblk1p2 /sdcard/de-root # export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/system/bin # busybox chroot /sdcard/de-root /debootstrap/debootstrap --second-stage # echo 'deb http://ftp.nl.debian.org/debian squeeze main' > /sdcard/de-root/etc/apt/sources.list # mount -t proc none /sdcard/de-root/proc # mount -t sysfs none /sdcard/de-root/sys # mount -o bind /dev /sdcard/de-root/dev # mount -t devpts none /sdcard/de-root/dev/pts # export TMPDIR=/tmp # busybox chroot /sdcard/de-root /bin/bash # apt-get update # apt-get install openssh-server # passwd root # exit # sync |
过程中其实有一个问题费了一些劲,apt-get update 不能正常工作,原作者在文中提到了这点,他的建议是要配置 /etc/named.conf,这应该是一个误导,使用:
1 2 |
# echo -e "domain local\nsearch local\n" >> /etc/resolv.conf # echo -e "# DNS Google\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n" >> /etc/resolv.conf |
对 /etc/resolv.conf 进行配置后就好了(参见 http://forum.xda-developers.com/showthread.php?t=2312013);
接下来是编辑 SD 卡上的 /etc/init 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/sbin/busybox sh # # Debian environment boot init script # # Leave all the initialization process to the Android init to handle # # Launch delayed init script /etc/init.stage2 >/android/log/boot.log 2>&1 & # Transfer control to Android init - never returns exec /sbin/busybox chroot /android /init |
上述脚本里引入了的 /etc/init.stage2 文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#!/sbin/busybox sh # # Delayed Debian environment boot init script # Not really init (not pid 1) but a fork of it. # The real init is right now executing in Android chroot # /sbin/busybox echo "`/sbin/busybox date` Debian init stage2 started" # Wait for Android init to set up everything # wait for dev to be mounted by Android init /sbin/busybox echo "`/sbin/busybox date` Waiting on Android to mount /dev" while [ ! -e /android/dev/.coldboot_done ]; do /sbin/busybox sleep 1 done # wait for Android init to signal all done /sbin/busybox echo "`/sbin/busybox date` Waiting on Android init to finish" while [ -e /android/dev/.booting ]; do /sbin/busybox sleep 1 done # Mount the /proc, /sys etc filesystems /sbin/busybox echo "`/sbin/busybox date` Mounting /proc /sys and /dev" /sbin/busybox mount -t proc none /proc /sbin/busybox mount -t sysfs none /sys # Mount /dev from the Android world /sbin/busybox mount -o bind /android/dev /dev /sbin/busybox mount -o bind /android/dev/pts /dev/pts /sbin/busybox mount -o bind /android/dev/socket /dev/socket # All done, now we can start stuff export PATH=/sbin:/usr/sbin:/bin:/usr/bin /sbin/busybox echo "`/sbin/busybox date` Running /etc/rc.local" # Start selected servers /etc/init.d/rc.local start /sbin/busybox echo "`/sbin/busybox date` All done" exit 0 |
必要的工作完成后,在最后又调用到了 /etc/rc.local,因为要用到 ssh,所以其内容类似于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. /etc/init.d/hostname.sh start /etc/init.d/ssh start exit 0 |
注意将 init 和 init.stage2 的文件属性设置为 755。
把 busybox 放到 Debian 系统的 /sbin 里面(/sdcard/de-root/sbin),属性设置为 755。
三、把 Android 的引导部分迁移到 SD 卡上来
在 SD 卡上,新建 /android 和 /android/log 目录,755。
把原生 boot.img 里的 initramfs(在桌面,用 unmkbootimg 工具把 boot.img 解开,得到 zImage 和 initramfs.cpio.gz 两个文件,再用 gunzip 工具解开后者得到 initramfs.cpio)展开到 /android 里(先用 adb 把 initramfs.cpio 推到手机上):
1 2 |
# cd /sdcard/de-root/android # busybox cpio -idmv < /data/local/tmp/initramfs.cpio |
把 busybox 放到 Android 系统的 /sbin 里面(/sdcard/de-root/android/sbin),755。
至此 SD 卡的工作告一段落,最后要 umount /sdcard/de-root。
四、把新的 boot.img 写到手机
用 Odin 刷入试验没成功(突然想到,有可能是 tar 文件里忘记把 de-boot.img 改成 boot.img 了),后来直接 dd 成功了(寻找合适的分区费了点劲):
1 |
# dd if=/data/local/tmp/de-boot.img of=/dev/block/mmcblk0p5 |
重启手机。
此时,在 Android 中使用 ConnectBot 通过 SSH 连接 localhost 即可,用户名和密码如果在以上步骤中没有修改的话就是 root。
在命令行下安装好 tightvncserver(会要求设定连接口令),然后使用 vncserver -geometry 1024×768 -displayID :1 命令把 VNC 的服务器运行起来。从另外的设备上就可以通过 VNC 客户端来连接了,例如在三太爷的 Ubuntu 下,连接的命令就是 gvncviewer 192.168.1.111:1。只是连接之后,X server 显示了一个对话框,说窗口管理器之类的程序一概没有安装等等(Xsession: unable to start X session — no “/root/.xsession” file, no “/root/.Xsession” file, no session managers, no window managers, and no terminal emulators found; aborting.)。感觉这其实就已经好办了,安装就是。
五、备忘
查看某文件的前多少字节,并格式化输出:
1 |
head -c byteCount fileName | hexdump -C |