[AT&T Samsung Galaxy Note II] garyd9:
It would be a great idea to get familiar with the "adb" tool; particularly the "shell", "pull" and "push" commands. (Use Google to search for "how to use adb.") Over the next several sections, we make use of these adb commands to copy files to and from the Android device and to interact with the device's operating system. This document also assumes that the device has already been rooted.

To get a "rooted adb shell" on a Samsung TouchWiz device, you'll have to have your device attached to and seen by your linux build machine, and use the command "adb shell" in a terminal window. Now, turn on the display for your android device and unlock it (if required.) Finally, back in the terminal window on the linux build machine, type the command "su". You Android device might pop up a prompt asking to give permission for the root access. If it does, grant the access. After the su command, the prompt should have a "#" symbol (instead of a "$" symbol.)​

As you might already have realized, just having a linux kernel is interesting, but not extremely useful. The kernel can boot, but once it does, it needs a filesystem to load programs from, to store data, etc. In the UN*X world (which linux is derived from), there's a single root to all filesystems, and other filesystems mount (attach) to that single root. Android (and many other embedded systems) use a root filesystem that isn't real - instead it's a virtual filesystem called a RAM Disk. Briefly, a RAM Disk is a portion of the devices RAM that's put aside and make to look like a persistent storage device. Unlike a real storage device, the RAM Disk (usually typed as "ramdisk") is completely erased each time the device is rebooted.

Linux allows taking that concept to a higher level by allowing a kernel to specify an initial ramdisk image. The image is a snapshot of a portion of an actual filesystem which is used to create the ramdisk. That, in turn, is specified in the kernel configuration to be the "initramfs" - which means that it becomes the root filesystem for the entire device. ("initramfs" is short for "Initial RAM FileSystem.") The initramfs image is embedded within the kernel image, and each time the kernel boots up, it uses that image as a root filesystem. Being it's a ramdisk, we can even make changes within the root filesystem after the device boots, but those changes will be wiped out the next time the device reboots.

Some other initramfs features supported by linux, but that don't seem to be used in Android, include the ability to switch root filesystems from within the initramfs, and the ability to store the initramfs as a seperate file (instead of embedding it in the kernel image.)​

As well as being an anchor for all the persistent (and non-persistent) storage devices in the phone, the Android initramfs also kick-starts the Android OS itself. (Remember that "linux" is a kernel, not the OS!) It usually contains some lower level system utilities (such as the files needed for adb functionality), a few kernel drivers that might not already be compiled into the kernel, a few config files used at the early stage of booting the device, and scripts used to get the rest of the system going. On some Android devices, the initramfs also contains the files needed for booting the phone recovery. (On other phones, including most that have been released since Android 4.0, recovery has it's own private kernel.) Remember, however, that the initramfs uses RAM, so it shouldn't be bloated with things that could be stored in real persistent storage.

Another aspect of using the initramfs that can be useful is that it allows booting at least a minimally functioning linux system in cases when the rest of the Android OS doesn't load properly. That minimal system could even be used to manually flash a different kernel, recovery, or even the entire firmware for the device.

Now that we have an idea what the initramfs is, and why we need one, the question is how to obtain one. In most cases, it's usually better to at least start with a copy of the initramfs already used by our Android device. This way, we know that everything needed in the initramfs already is there. We can (and will) make changes to it later. The best way to get an unmodified copy of the kernel's initramfs is to use a special tool to pull the ramdisk out of the kernel image.

For this HOWTO, we'll start with a "stock" kernel image (instead of a custom image that might have already been modified.) This gives us a known starting place, and ensures that files haven't been modified by a previous kernel developer. There are a few ways to get this kernel image. Often times, the easiest is to find one online in either a "recovery" style zip file, or packaged in a proprietary file such as Samsung's ODIN tar files. If you haven't installed a custom kernel on your device, you can also usually extract the kernel image directly from our phone.

The remainder of this section will be devoted to the information needed to extract a kernel image from the phone. Even if you don't have a stock kernel installed, it would be useful to read the information and go through the steps. The knowledge (and experience) will be useful when we have a kernel to install. However, different types of devices might have different device configurations, so some of this information might not be accurate for every device.

The kernel image (along with the device modem, firmware, data, etc) is stored on a special type of "flash" RAM that doesn't lose it's memory when power is removed. It's very much like any type of removable memory (such as a SDCard, USB thumb drive, etc.) Unlike those examples, however, this special storage is built into the phone or tablet. This guide refers to that flash memory as "persistent storage" which indicates storage that retains data even when power is off or the device resets.

The persistent storage on our devices is treated in linux much as a hard drive is treated on a PC. As with a hard drive, the persistent storage is split into logical "partitions" and each partition can be (and usually is) treated as a separate logical storage device. Our devices might contain 16GB of persistent storage space, but that 16GB is partitioned into a dozen or more smaller chunks providing separate locations for storing the kernel, the bootloaders, the files needed for recovery, the system files, the modem firmware, user data, etc.

In linux, physical (and virtual) devices have drivers in the kernel, and are represented by a special virtual filesystem usually mounted (attached) to a directory called "dev" in the root filesystem. Modern versions of the linux kernel usually separate the devices into sub-directories based on category. Persistent storage devices are almost always "block" devices. Finally, individual block devices are given names based on their driver and other ordering information as determined by the driver. Actual devices being represented are called "nodes" but are often also just called "device files" to keep the description simple. (This is an intentional simplification of how the device nodes are created.)

Based on the above paragraph, we know that the device nodes for the persistent storage can be found in a directory called "/dev/block" on our device. To see this, we'll need a rooted adb shell on your device (or rooted shell via a terminal emulator installed on the phone) and to copy the following command:

ls /dev/block

On most modern Android devices, we'll see a device node for "mmcblk0" which represents the entire built-in persistent storage. There will also be devices for each partition, such as "mmcblk0p1", "mmcblk0p2", and so on. One of those device nodes represents the partition used to store the kernel image (often called the boot image) - and we need to figure out which one. This is an area that can get annoying, as there doesn't seem to be a simple generic way to determine which partition the kernel is stored on.

(NOTE: If someone can give me a good way to determine the boot/kernel partition regardless of platform, please let me know and I'll document it here.)

If we poke around the directory tree in /dev/block/platform, we might be able to find a sub-directory buried in there called "by-name" and, at least on some platforms, we can determine the boot/kernel partition from there. We need to be somewhat careful, as the boot LOADER is most certainly not something we want to mess with - and many platforms can make it confusing when they refer to the kernel partition as the "boot" partition. On the Galaxy Note II, that "by-name" sub-directory is in /dev/block/platform/dw_mmc, and you can see the full list of named partitions by copying the following command to a rooted adb shell running on your device:

ls -l /dev/block/platform/dw_mmc/by-name

The result of running that command will include the following (or something similar)

lrwxrwxrwx 1 root root 20 Nov 18 12:39 BOOT -> /dev/block/mmcblk0p8
lrwxrwxrwx 1 root root 20 Nov 18 12:39 BOTA0 -> /dev/block/mmcblk0p1
lrwxrwxrwx 1 root root 20 Nov 18 12:39 BOTA1 -> /dev/block/mmcblk0p2
lrwxrwxrwx 1 root root 21 Nov 18 12:39 CACHE -> /dev/block/mmcblk0p12
lrwxrwxrwx 1 root root 20 Nov 18 12:39 EFS -> /dev/block/mmcblk0p3
lrwxrwxrwx 1 root root 21 Nov 18 12:39 HIDDEN -> /dev/block/mmcblk0p14
lrwxrwxrwx 1 root root 21 Nov 18 12:39 OTA -> /dev/block/mmcblk0p15
lrwxrwxrwx 1 root root 20 Nov 18 12:39 PARAM -> /dev/block/mmcblk0p7
lrwxrwxrwx 1 root root 21 Nov 18 12:39 RADIO -> /dev/block/mmcblk0p10
lrwxrwxrwx 1 root root 20 Nov 18 12:39 RECOVERY -> /dev/block/mmcblk0p9
lrwxrwxrwx 1 root root 21 Nov 18 12:39 SYSTEM -> /dev/block/mmcblk0p13
lrwxrwxrwx 1 root root 21 Nov 18 12:39 TOMBSTONES -> /dev/block/mmcblk0p11
lrwxrwxrwx 1 root root 21 Nov 18 12:39 USERDATA -> /dev/block/mmcblk0p16

This gives us the information we need to determine the kernel partition. It's called "BOOT" and the actual device node is /dev/block/mmcblk0p8. Similar information can be found for other device types as well. For example, on a Galaxy Nexus running CM10, the sub-directory containing this information is /dev/block/platform/omap/omap_hsmmc.0/by-name and on a Nexus7 running pure AOSP 4.2, a similar (but more crytpic) set of information is at /dev/block/platform/sdhci-tegra.3/by-name. Sometimes, we just need to search to find the proper partition.

Once we have the name of the device node for the partition containing the boot/kernel partition, we can use that to actually convert and copy the entire partition to a normal file. The command for doing this is "dd" and the parameters we use need to be typed carefully. A simple typo here can result in overwriting a valid kernel unintentionally. Be paranoid! The following command, which should be copied to a rooted adb shell, assumes that the "boot" (kernel) partition is mmcblk0p8, and stores a copy of that entire image to a file called orig_boot.img on the internal user storage (/sdcard):

dd if=/dev/block/mmcblk0p8 of=/sdcard/orig_boot.img bs=4096

"if" designates the "input file", "of" designates the "output file" and "bs" is the block size. The block size parameter isn't really needed here, but it tends to speed up the copy by telling "dd" to copy 4096 bytes at a time (instead of 1 byte at a time.)

We now have a boot image (kernel image) that we can use to extract an initramfs from. One last step is needed to get that file transferred to our linux build machine. Open a new terminal window and copy the following commands into it:

cd
cd kernel-howto
adb pull /sdcard/orig_boot.img ./orig_boot.img

This will change into the kernel-howto directory on your build machine, and pull the recently made image to your build machine. (If using the 'Terminal' program in Ubuntu, you can open a new terminal window by right-clicking on an existing terminal window and selecting "Open Terminal." You can also right-click on the 'Terminal' icon in the Launcher bar and select "New Terminal.")

If you are using a different starting image, such as from an ODIN compatible tar file or CWM Recovery compatible zip file, please find the kernel image within that archive, extract it, and place it in the proper directory, renaming it to match. If you can't find a stock image (or don't feel like searching for one) just execute the following commands to get a kernel image that was extracted from a stock LJ2 SGH-i317 (AT&T variant):

cd
cd kernel-howto
wget https://github.com/garyd9/kernel-howto-misc/raw/master/boot_orig.img.gz
gunzip boot_orig.img.gz