Monday, November 21, 2011

[轉錄]如何客製化 Google Nexus S 的 Kernel

轉自http://www.ur-solution.com/?p=26


Google Nexus S 使用的是原生的 android 作業系統,不像各家廠商的手機,經過大量的客製化,所以這個手機可以說環境最單純、乾淨、簡潔的系統了,我們在進行 Android 驅動程式 Porting 時,都會先拿這隻手機來測試,所以我們會要重新編譯這個手機的 Linux Kernel,在開始之前,首先我們事先準備一些環境,先下載 Android NDK,如下:

wget http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2
tar -jxf android-ndk-r6b-linux-x86.tar.bz2
export ARCH=arm
export CROSS_COMPILE=$(pwd)/android-ndk-r6b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-

接者我們要安裝 SDK:

wget http://dl.google.com/android/android-sdk_r12-linux_x86.tgz
tar -zxf android-sdk_r12-linux_x86.tgz
android-sdk-linux_x86/tools/android update sdk -u -t platform-tool
export PATH=$PATH:$(pwd)/android-sdk-linux_x86/platform-tools

現在我們可以開始進行編譯的工作,要編譯 Nexus S 的 kernel, 首先我們要取得 Samsung Nexus S 的 Kernel tree , 請執行:
git clone -b devrom-2.6.35 https://github.com/cgjones/samsung-android-kernel
cd samsung-android-kernel

接下來我們要設定 Kernel ,請執行:

make herring_defconfig

在開始編譯之前,我們先來看看手機上的 Kernel 版本資訊,請執行:

adb shell cat /proc/version
—–會得到以下的資訊
Linux version 2.6.35.7-ge382d80 (android-build@apa28.mtv.corp.google.com) (gcc v
ersion 4.4.3 (GCC) ) #1 PREEMPT Mon Feb 7 18:29:34 PST 2011

其中有一項很重要的資訊:2.6.35.7 ,這是我們 Kernel 的 版本。你要先確定使用的 kernel 版本是否正確,請執行:

shanchieh@ubuntu:~/nexus_s/samsung-android-kernel$ make kernelversion
2.6.35.7

很好,我們現在使用的也是 2.6.35.7。在版本後面有一個資訊:-ge382d80(2.3.4) (如果你的 OS 是 2.3.3 ,則會是:-g1d030a7 ),請將這個資訊寫入到 .scmversion 檔案中,請執行:

echo -ge382d80 > .scmversion
現在我們可以來開始編譯 kernel ,請執行:

make -j$(($(grep -c processor /proc/cpuinfo) * 3 / 2))

-j 這個參數後要接一個數字,例如 -j2 , -j4,等… 意思是說你同時要使用幾個核心來編譯。根據每一個人的環境不同,當然會不一樣,所以我們用一個參數來取得你目前硬體的核心數目。

編譯的過程中,我們先來看看 Nexus S 中的 boot 是在哪一個分割區中,請執行:

shanchieh@ubuntu:~$ adb shell cat /proc/mtd | awk -F’[:"]‘ ‘$3 == "boot" {print $1}’
mtd2
現在我們知道是放在 mtd2 的分割區中。在更換之前,我們先將手機上的 boot 保存下來,請執行:

shanchieh@ubuntu:~$ adb shell
# su
# dd if=/dev/mtd/mtd2 of=/sdcard/boot.img bs=4096
2048+0 records in
2048+0 records out
8388608 bytes transferred in 1.232 secs (6808935 bytes/sec)
# exit
# exit
這時在 /sdcard 之中。就會有一個 boot.img 的檔案。

請執行: adb pull /sdcard/boot.img 將這個檔案保存到我們的電腦中。

好。現在我們要來產生新的 boot.img 了,請執行:

git clone https://github.com/glandium/unbootimg.git
git clone git://git.linaro.org/android/platform/system/core.git
gcc -o unbootimg/unbootimg unbootimg/unbootimg.c core/libmincrypt/sha.c -Icore/include -Icore/mkbootimg
gcc -o mkbootimg core/mkbootimg/mkbootimg.c core/libmincrypt/sha.c -Icore/include
gcc -o fastboot core/fastboot/{protocol,engine,bootimg,fastboot,usb_linux,util_linux}.c core/libzipfile/{centraldir,zipfile}.c -Icore/mkbootimg -Icore/include –lz

這個時候就會產生 fastboot 跟 mkbootimg 兩個執行檔。

還記得剛剛我們備份下載的 boot.img 嗎?現在我們將這個檔案解開,請執行:

unbootimg/unbootimg boot.img

過程中會告訴你error ,沒關係,不用理會,還是可以順利解開,如下:
section sizes incorrect
kernel 1000 2b1b84
ramdisk 2b3000 22d55
second 2d6000 0
total 2d6000 800000
…but we can still continue

解開之後,會有三個檔案。

boot.img-mk, containing the mkbootimg options required to produce a working boot image,
boot.img-kernel, containing the kernel image,
boot.img-ramdisk.cpio.gz, containing the gzipped ramdisk, which we will reuse as-is.

好,現在我們要替換我們自己編譯的 kernek 了。請執行:

eval ./mkbootimg $(sed s,boot.img-kernel,samsung-android-kernel/arch/arm/boot/zImage, boot.img-mk)

現在我們使用 adb 來進行 fastboot

adb reboot bootloader

這個時候,你的手機應該進入到 fastbook 模式,如下圖:
IMG_0066

請執行: ./fastboot boot boot.img
或出現如下的訊息:

downloading ‘boot.img’…
OKAY [ 0.xxxs]
booting…
OKAY [ 0.xxxs]
finished. total time: 0.xxxs
這個時候手機會重新開機,開機就是使用我們剛剛編譯好的 kernel ,我們要如何驗證手機的 kernel 真的是我們自己編譯的呢?很簡單,在手機中執行:選單->設定->關於手機,就可以看到 kernel 的資訊,如下圖:

IMG_0067
但是手機下次你重新開機時, kernel 還是舊的,因為我們沒有燒入到手機的 ROM 中。如果要永久替換,請執行:
adb reboot bootloader
./fastboot flash boot boot.img
會出現如下的訊息:

sending ‘boot’ (2904 KB)…
OKAY [ 0.xxxs]
writing ‘boot’…
OKAY [ 0.xxxs]
finished. total time: 0.xxxs

再執行 ./fastboot reboot 進行重新開機 ,這樣就將手機中的 Kernel 換成我們自己編譯的了

No comments: