[Samsung Galaxy Nexus] Climber Ty:
I know a lot of this has been posted before in other locations, but recently I have found some of that data to be incomplete when I was building a custom kernel for my GNex, so just bear with me.

--The Build Environment--

Operating System: Xubuntu 12.04 x86 (I haven't tested it on the x64 version yet)

Dependencies: (using sudo-apt get install)

git git-core gnupg flex bison gperf build-essential zip hexdump gedit \
curl libc6-dev libncurses5-dev:i386 x11proto-core-dev libx11-dev:i386 gcc \
libreadline6-dev:i386 libgl1-mesa-glx:i386 libgl1-mesa-dev g++-multilib \
mingw32 tofrodos

Other Files Needed:

unpack-mkbootimg - Which I have forked from work4blue@github.

You can grab the modified version from: https://github.com/ClimberTy/unpack-mkbootimg.git

The mkbootimg.c has been modified to fix the default load addresses of the kernel with the GNex (See below for more details).

Android SDK - You just need the Android Debug Bridge (ADB) from the SDK.

Or you can grab a toolkit from here: http://xdaforums.com/showthread.php?t=1848036 for a script that will get you the files you need (Internet connection required).

Needed:

Samsung Galaxy Nexus Prime (I9250)

The GNex Bootloader to be Unlocked (http://www.android.gs/how-to-unlock-galaxy-nexus-bootloader/)

Kernel files (See Kernel Source area for locations)

ADB and Fastboot

ARM Cross Compiler - grab from here.

NOTE:

You'll need the ARM EABI Release. You can also get the ARM Cross Compiler by following the "Downloading a prebuilt gcc" instructions from Google as well.

Place either of these ARM Compilers in the folder you are using to build your KERNELSOURCE.

Linux USB Driver Rules:

Open Terminal and type:

$ vim /etc/udev/rules.d/70-android.rules

You can use gEdit if you prefer.

Paste in (Ensuring that <username> is the name of your Linux profile):

# adb protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e12", MODE="0600", OWNER="<username>"
# fastboot protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0fff", MODE="0600", OWNER="<username>"
# adb protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e22", MODE="0600", OWNER="<username>"
# fastboot protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e20", MODE="0600", OWNER="<username>"
# adb protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a9", MODE="0600", OWNER="<username>"
# fastboot protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="708c", MODE="0600", OWNER="<username>"
# adb protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6860", MODE="0600", OWNER="<username>"
# fastboot protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e30", MODE="0600", OWNER="<username>"
# adb protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d101", MODE="0600", OWNER="<username>"
# fastboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d022", MODE="0600", OWNER="<username>"
# usbboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d00f", MODE="0600", OWNER="<username>"
# usbboot protocol on panda (PandaBoard ES)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d010", MODE="0600", OWNER="<username>"
# adb protocol on grouper/tilapia (Nexus 7)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e42", MODE="0600", OWNER="<username>"
# fastboot protocol on grouper/tilapia (Nexus 7)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e40", MODE="0600", OWNER="<username>"
# adb protocol on manta (Nexus 10)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee2", MODE="0600", OWNER="<username>"
# fastboot protocol on manta (Nexus 10)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee0", MODE="0600", OWNER="<username>"

Kernel Source:

It is important that you make separate folders to put everything in. Keeping the DEV area organized will help out in the long run.

$ mkdir -p ~/Documents/Kernel/Source

CyanogenMod 10.1 Kernel from GitHub

Google's Android Kernel (See Downloading Android Kernel section below for more details)

Downloading the Android Kernel:

To download the kernel directly from Google enter in these commands.

$ git clone https://android.googlesource.com/kernel/omap.git
$ cd omap/
$ git branch -a

What you'll see in response:

* master
remotes/origin/HEAD -> origin/master
remotes/origin/android-omap-3.0
remotes/origin/android-omap-panda-3.0
remotes/origin/android-omap-steelhead-3.0-ics-aah
remotes/origin/android-omap-tuna-3.0
remotes/origin/android-omap-tuna-3.0-ics-mr1
remotes/origin/android-omap-tuna-3.0-jb-mr0
remotes/origin/android-omap-tuna-3.0-jb-mr1
remotes/origin/android-omap-tuna-3.0-jb-mr1.1
remotes/origin/android-omap-tuna-3.0-jb-pre1
remotes/origin/android-omap-tuna-3.0-mr0
remotes/origin/android-omap-tuna-3.0-mr0.1
remotes/origin/linux-omap-3.0
remotes/origin/master
remotes/origin/sph-l700-fh05

To grab the (at this time) latest Jellybean source:

$ git checkout remotes/origin/android-omap-tuna-3.0-jb-mr1.1

Otherwise just use:

$ git clone https://github.com/CyanogenMod/android_kernel_samsung_tuna.git

--Building the Kernel--

In the ~/Documents/Kernel/KERNELSOURCE (varies depending on which kernel you downloaded. For this build I used android_kernel_samsung_tuna-jb as my source directory. The ARM Cross Compiler that I downloaded from the CodeSourcery site is located inside this folder.

In the terminal type:

$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=/home/user/Documents/Kernel/KERNELSOURCE/arm-2011.03/bin/arm-none-eabi-
$ make tuna_defconfig
$ make

NOTE: The [...]/arm-none-eabi- is how it is supposed to be.

Now go grab some lunch or drink a beer or two, it could take about 30-45 mins to compile. You'll know when it is finished when you see:

OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
AS arch/arm/boot/compressed/head.o
GZIP arch/arm/boot/compressed/piggy.gzip
AS arch/arm/boot/compressed/piggy.gzip.o
CC arch/arm/boot/compressed/misc.o
CC arch/arm/boot/compressed/decompress.o
SHIPPED arch/arm/boot/compressed/lib1funcs.S
AS arch/arm/boot/compressed/lib1funcs.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
Building modules, stage 2.
MODPOST 4 modules
CC crypto/ansi_cprng.mod.o
LD [M] crypto/ansi_cprng.ko
CC drivers/rpmsg/rpmsg_client_sample.mod.o
LD [M] drivers/rpmsg/rpmsg_client_sample.ko
CC drivers/rpmsg/rpmsg_server_sample.mod.o
LD [M] drivers/rpmsg/rpmsg_server_sample.ko
CC drivers/scsi/scsi_wait_scan.mod.o
LD [M] drivers/scsi/scsi_wait_scan.ko

The

zImage

is what we need because it is the compressed Linux kernel. Note the path of where the zImage is located. We also need the *.ko files (Kernel Modules). Remember their paths because you'll need to create those same paths later when you rebuild the kernel. Probably best to move these files to a new folder, I have used /home/user/Documents/Kernel/CompiledKernel/.

--Backing Up the Original Kernel--

It is important that we save a backup of the original kernel just in case there are errors in the kernel you are creating and we need to revert. Each device has their images saved in somwhat similar spots but they can change depending on device or OS.

Before these images were located on /proc/mnt location but with this model/OS they are stored elsewhere. Your phone will most likely need to be rooted prior to this operation. So either push the SuperUser app to your phone or grab Koushik Dutta's version from ROM Manager in ClockworkMod (http://download.clockworkmod.com/test/superuser-2.zip).

How to grab the images:

$ adb shell
$ su
$ ls -l /dev/block/platform/omap/omap_hsmmc.0/by-name

Result:

lrwxrwxrwx root root	2013-02-20 06:38 boot -> /dev/block/mmcblk0p7
lrwxrwxrwx root root 2013-02-20 06:38 cache -> /dev/block/mmcblk0p11
lrwxrwxrwx root root 2013-02-20 06:38 dgs -> /dev/block/mmcblk0p6
lrwxrwxrwx root root 2013-02-20 06:38 efs -> /dev/block/mmcblk0p3
lrwxrwxrwx root root 2013-02-20 06:38 metadata -> /dev/block/mmcblk0p13
lrwxrwxrwx root root 2013-02-20 06:38 misc -> /dev/block/mmcblk0p5
lrwxrwxrwx root root 2013-02-20 06:38 param -> /dev/block/mmcblk0p4
lrwxrwxrwx root root 2013-02-20 06:38 radio -> /dev/block/mmcblk0p9
lrwxrwxrwx root root 2013-02-20 06:38 recovery -> /dev/block/mmcblk0p8
lrwxrwxrwx root root 2013-02-20 06:38 sbl -> /dev/block/mmcblk0p2
lrwxrwxrwx root root 2013-02-20 06:38 system -> /dev/block/mmcblk0p10
lrwxrwxrwx root root 2013-02-20 06:38 userdata -> /dev/block/mmcblk0p12
lrwxrwxrwx root root 2013-02-20 06:38 xloader -> /dev/block/mmcblk0p1

We need to backup the boot and recovery images.

Copying the Android Images:

cat /dev/block/mmcblk0p7 > /sdcard/boot
cat /dev/block/mmcblk0p8 > /sdcard/recovery

Pulling the Images Off the Device:

$ dab pull /sdcard/IMAGE_NAME ~/Documents/Kernel/OriginalKernel/

NOTE: This assumes you have this folder already created.

--Unpacking the Kernel--

Splitting the Image:

Using the

unpack-mkbootimg-master

kit you can split the image by using the ./unpackbootimg binary. The command is:

$ ./unpackbootimg -i ~/Documents/Kernel/OriginalKernel/boot

The results should be similar to this:

BOARD_KERNEL_CMDLINE
BOARD_KERNEL_BASE 80000000
BOARD_OAGE_SIZE 2048

The output files in your unpack-mkbootimg-master folder should be similar to this:

drwxrwxr-x 4 user user 4.0K Mar 3 11:22 .
drwxr-xr-x 3 user user 4.0K Mar 3 11:15 ..
-rw-rw-r-- 1 user user 9 Mar 3 11:22 boot-base
-rw-rw-r-- 1 user user 1 Mar 3 11:22 boot-cmdline
-rw-rw-r-- 1 user user 2.9K Feb 28 18:00 bootimg.h
-rw-rw-r-- 1 user user 5 Mar 3 11:22 boot-pagesize
-rw-rw-r-- 1 user user 344K Mar 3 11:22 boot-ramdisk.gz
-rw-rw-r-- 1 user user 4.0M Mar 3 11:22 boot-zImage
drwxrwxr-x 2 user user 4.0K Mar 3 11:15 libmincrypt
-rw-rw-r-- 1 user user 7.3K Mar 3 11:15 libmincrypt.a
-rwxr-xr-x 1 user user 622 Feb 28 18:00 Makefile
drwxrwxr-x 2 user user 4.0K Feb 28 18:00 mincrypt
-rwxrwxr-x 1 user user 789K Mar 3 11:15 mkbootimg
-rw-rw-r-- 1 user user 7.4K Feb 28 18:00 mkbootimg.c
-rw-rw-r-- 1 user user 8.5K Mar 3 11:15 mkbootimg.o
-rw-rw-r-- 1 user user 1.1K Feb 28 18:00 README
-rwxrwxr-x 1 user user 789K Mar 3 11:15 unpackbootimg
-rw-rw-r-- 1 user user 3.9K Feb 28 18:00 unpackbootimg.c
-rw-rw-r-- 1 user user 6.6K Mar 3 11:15 unpackbootimg.o

NOTE: This is for the Samsung Galaxy Nexus (Maguro & Tuna, possibly Toro & Toroplus)

A simple hexdump (using "hex dump -n 40") of the boot image from the GNex phone should give us the results of:

0000000 41 4e 44 52 4f 49 44 21 68 54 3f 00 00 80 00 80
0000010 4d 5c 05 00 00 00 00 81 00 00 00 00 00 00 f0 80
0000020 00 01 00 80 00 08 00 00
0000028

Results may vary between Android versions. These numbers will help us in verifying that your kernel that you're creating is indeed correct.

What is needed to be taken away from this is the so called "Android Magic" which are the first four bytes of data in the hex dump.

Android Magic = 4e41 5244 494f 2144

The next two bytes are the kernel size, in this case (0x5468 0x003f).

The rest of the byes are as follows:

Kernel Base = 8000 8000
Ramdisk Address = 8100 0000
Secondary Address = 80f0 0000
Tags Address = 8000 0100

These values are what I had to change in the mkbootimg application in the unpack-mkbootimg-master. Otherwise the kernel images would be off and they would not load correctly on the device. Look at https://github.com/ClimberTy/unpack-mkbootimg/blob/master/mkbootimg.c for more details.

Splitting the Ramdisk

For organizations sake move the boot-* files to a new folder. From here we need to open the boot-ramdisk.gz.

$ mkdir UnpackedKernel
$ mv boot-* UnpackedKernel/
$ cd UnpackedKernel/
$ gunzip -c boot-ramdisk.gz | cpio -i

This splits open the boot-ramdisk.gz file so we can place our newly created kernel modules (anything listed as .KO) in their appropriate folders or make modifications to any of the other files in the UnpackedKernel/ folder.

Remember these, we'll need them later.

--Rebuilding the Kernel--

After making the modifications and placing the kernel modules in the UnpackedKernel/ folders . Again you may need to create the directories for these kernel module locations. See your compiled kernel printout for the correct paths. Now that everything is in place you need to rebuild the boot-ramdisk.gz:

$ pwd
[…]/UnpackedKernel/
$ find . | cpio -o -H newc | gzip > ../newramdisk.cpio.gz
$ cd ..

Now copy in the /CompiledKernel/zImage into the /unpack-mkbootimg-master/ folder and run this command to build the kernel:

$ ./mkbootimg --kernel zImage --ramdisk newramdisk.cpio.gz --base 80000000 --pagesize 2048 -o newKernel.img

Now to verify that the compiled kernel is right on par with the original kernel you need to do a hexdump.

$ hex dump -n 40 newKernel.img

Should print out results similar to this:

0000000 4e41 5244 494f 2144 cee4 0044 8000 8000
0000010 3e08 004b 0000 8100 0000 0000 0000 80f0
0000020 0100 8000 0800 0000
0000028

And as you can see all the addresses line up as they should, the only thing that should have changed is the kernel size which is expected.

--Test Flashing to the Device--

Move your newKernel.img image file into its own folder (e.g. ~/Documents/Kernel/NewKernel/) then put your device into the recovery mode to test and see if it boots, if it doesn't then "wash, rinse, and repeat".

To put your device into recovery mode, first power it off then power it back on and immediately hold down the POWER, VOLUME UP and VOLUME DOWN buttons. Select RECOVERY from the menu and press POWER to enter.

$ fastboot flash boot ~/Documents/Kernel/NewKernel/newKernel.img

$ fastboot reboot

Wait a few seconds till it boots up. If you don't receive any device response after a minute or so then put your phone back into recovery and flash the original kernel. If it works then,

congratulations!

If not try, try rebuilding it again and verifying you have the correct addresses or all the kernel modules installed properly.