Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Readers > Amazon Kindle > Kindle Developer's Corner

Notices

Reply
 
Thread Tools Search this Thread
Old 11-28-2021, 10:23 AM   #1
katadelos
rm -rf /
katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.katadelos ought to be getting tired of karma fortunes by now.
 
Posts: 219
Karma: 3333683
Join Date: Nov 2019
Location: United Kingdom
Device: K5, KT, KT2, KT3, KT4, KV, PW2, PW3, PW4, PW5
How-to: Building a custom initramfs for fun and profit

Description
This how-to covers the process of creating and flashing a custom kernel initramfs.

Creating a custom initramfs allows a developer to implement additional functionality early in the boot process.

Compatibility
This how-to should be applicable to Kindle devices that allow the end user to flash and boot an unsigned, self built kernel (i.e anything earlier than KT4/PW4).

Process
Context
All Kindle kernels contain a small initramfs that contains a utility known as recovery-util. The main function implemented by recovery-util that most users will be familiar with is the additional updater that is capable of installing a firmware update, even if the main update mechanism within the rootfs has been disabled. However, when accessing the device using the serial connection, there are a number of other features which, as the name suggests, are useful for recovering bricked devices:

Code:
Menu
====
3. Load MMC over USB storage
4. Erase MMC
I. Initialize Partition Table (fdisk) and format FAT
O. Format and overwrite FAT partition
E. Export FAT partition
U. Update using update*.bin file on FAT partition
M. Update using update*.bin file on FAT partition of second MMC port
D. dmesg / kernel printk ring buffer.
Q. quit
Choose:   9 -U
Most of the features listed in the menu above are always present and functional within recovery-util - generally, this includes the ability to erase the MMC storage, initialise the partition table, format the FAT partition, update using a firmware update on the FAT partition and printing the kernel ring buffer using dmesg.

However, some options (such as loading the entire MMC storage over USB) are either missing entirely or do not work when selected.

Probing deeper
We can understand how this is implemented in more detail by examining the contents of a stock initramfs.
Extracting a stock initramfs
First, we need to download and extract the contents of an update image:
Code:
kindletool extract update_kindle_voyage_5.13.6.bin /tmp/kv
We now need to extract the contents of the initramfs from the kernel contained within the update image:

Code:
user@ubuntu:/tmp/kv$ binwalk -e imx60_wario/uImage

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x3F3219, created: 2021-04-08 09:40:01, image size: 3143456 bytes, Data Address: 0x80008000, Entry Point: 0x80008000, data CRC: 0xA02A9C91, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-3.0.35-lab126"
64            0x40            Linux kernel ARM boot executable zImage (little-endian)
18028         0x466C          gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
This will leave us with a mangled copy of the zImage contained within the uImage:
Code:
user@ubuntu:/tmp/kv$ file imx60_wario/_uImage.extracted/466C 
imx60_wario/_uImage.ex
tracted/466C: data
Use binwalk to extract the initramfs contents from the mangled zImage:
Code:
user@ubuntu:/tmp/kv$ binwalk -e imx60_wario/_uImage.extracted/466C 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
6773          0x1A75          End of Zip archive, footer length: -24474
129080        0x1F838         ASCII cpio archive (SVR4 with no CRC), file name: ".", file name length: "0x00000002", file size: "0x00000000"
129192        0x1F8A8         ASCII cpio archive (SVR4 with no CRC), file name: "lib", file name length: "0x00000004", file size: "0x00000000"
129308        0x1F91C         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules", file name length: "0x0000000C", file size: "0x00000000"
129432        0x1F998         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/arcotg_udc.ko", file name length: "0x0000001A", file size: "0x00000035"
129624        0x1FA58         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/ehci-hcd.ko", file name length: "0x00000018", file size: "0x00000031"
129812        0x1FB14         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/g_file_storage.ko", file name length: "0x0000001E", file size: "0x00000039"
130012        0x1FBDC         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/fsl_otg_arc.ko", file name length: "0x0000001B", file size: "0x00000033"
130204        0x1FC9C         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126", file name length: "0x0000001A", file size: "0x00000000"
130340        0x1FD24         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.alias", file name length: "0x00000028", file size: "0x0000004E"
130572        0x1FE0C         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.dep", file name length: "0x00000026", file size: "0x00000148"
131048        0x1FFE8         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.builtin.bin", file name length: "0x0000002E", file size: "0x00000000"
131204        0x20084         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.softdep", file name length: "0x0000002A", file size: "0x00000037"
131412        0x20154         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.symbols", file name length: "0x0000002A", file size: "0x00000532"
132896        0x20720         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.dep.bin", file name length: "0x0000002A", file size: "0x000001FE"
133560        0x209B8         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.alias.bin", file name length: "0x0000002C", file size: "0x00000034"
133768        0x20A88         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.symbols.bin", file name length: "0x0000002E", file size: "0x000006BA"
135648        0x211E0         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel", file name length: "0x00000021", file size: "0x00000000"
135792        0x21270         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers", file name length: "0x00000029", file size: "0x00000000"
135944        0x21308         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb", file name length: "0x0000002D", file size: "0x00000000"
136100        0x213A4         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/host", file name length: "0x00000032", file size: "0x00000000"
136260        0x21444         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/host/ehci-hcd.ko", file name length: "0x0000003E", file size: "0x00013418"
215304        0x34908         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget", file name length: "0x00000034", file size: "0x00000000"
215468        0x349AC         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/arcotg_udc.ko", file name length: "0x00000042", file size: "0x0000A4C8"
257828        0x3EF24         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/g_file_storage.ko", file name length: "0x00000046", file size: "0x0000EC48"
318496        0x4DC20         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/otg", file name length: "0x00000031", file size: "0x00000000"
318656        0x4DCC0         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/usb/otg/fsl_otg_arc.ko", file name length: "0x00000040", file size: "0x000067E4"
345428        0x54554         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/video", file name length: "0x0000002F", file size: "0x00000000"
345588        0x545F4         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/video/mxc", file name length: "0x00000033", file size: "0x00000000"
345752        0x54698         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/kernel/drivers/video/mxc/mxc_epdc_fb.ko", file name length: "0x00000042", file size: "0x00022FA8"
489200        0x776F0         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/modules.devname", file name length: "0x0000002A", file size: "0x00000034"
489404        0x777BC         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/extra", file name length: "0x00000020", file size: "0x00000000"
489548        0x7784C         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/3.0.35-lab126/extra/mxc_epdc_eink.ko", file name length: "0x00000031", file size: "0x00002E94"
501632        0x7A780         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/mxc_epdc_eink.ko", file name length: "0x0000001D", file size: "0x00000024"
501808        0x7A830         ASCII cpio archive (SVR4 with no CRC), file name: "lib/modules/mxc_epdc_fb.ko", file name length: "0x0000001B", file size: "0x00000035"
502004        0x7A8F4         ASCII cpio archive (SVR4 with no CRC), file name: "bin", file name length: "0x00000004", file size: "0x00000000"
502120        0x7A968         ASCII cpio archive (SVR4 with no CRC), file name: "bin/cat", file name length: "0x00000008", file size: "0x00000AF0"
505040        0x7B4D0         ASCII cpio archive (SVR4 with no CRC), file name: "bin/nfsmount", file name length: "0x0000000D", file size: "0x00001D20"
512620        0x7D26C         ASCII cpio archive (SVR4 with no CRC), file name: "bin/sh", file name length: "0x00000007", file size: "0x00000009"
512752        0x7D2F0         ASCII cpio archive (SVR4 with no CRC), file name: "bin/sleep", file name length: "0x0000000A", file size: "0x000002D8"
513600        0x7D640         ASCII cpio archive (SVR4 with no CRC), file name: "bin/hotplug", file name length: "0x0000000C", file size: "0x00001DBC"
521336        0x7F478         ASCII cpio archive (SVR4 with no CRC), file name: "bin/load_waveform.sh", file name length: "0x00000015", file size: "0x0000027C"
522104        0x7F778         ASCII cpio archive (SVR4 with no CRC), file name: "bin/ipconfig", file name length: "0x0000000D", file size: "0x0000368C"
536192        0x82E80         ASCII cpio archive (SVR4 with no CRC), file name: "bin/mkdosfs", file name length: "0x0000000C", file size: "0x00007438"
566068        0x8A334         ASCII cpio archive (SVR4 with no CRC), file name: "bin/run-init", file name length: "0x0000000D", file size: "0x000010DC"
570508        0x8B48C         ASCII cpio archive (SVR4 with no CRC), file name: "bin/kinit", file name length: "0x0000000A", file size: "0x0001320C"
648976        0x9E710         ASCII cpio archive (SVR4 with no CRC), file name: "bin/recovery-util", file name length: "0x00000012", file size: "0x00080968"
1175800       0x11F0F8        ASCII cpio archive (SVR4 with no CRC), file name: "bin/sh.shared", file name length: "0x0000000E", file size: "0x0000F900"
1239668       0x12EA74        ASCII cpio archive (SVR4 with no CRC), file name: "etc", file name length: "0x00000004", file size: "0x00000000"
......
binwalk output truncated for brevity
......
The contents of the initramfs can now be examined:
Code:
user@ubuntu:/tmp/kv$ ls imx60_wario/_uImage.extracted/_466C.extracted/cpio-root/
bin  dev  etc  init  lib  mnt  proc  root  sys  usr  var
Examining a stock initramfs
Now that we have a copy of the contents of the initramfs, we can begin to understand how its functionality is implemented.

Init process
When the kernel loads the initramfs, it checks a number of predefined paths for a script that it should attempt to run. In this case, the file is a symlink located at the initramfs root directory that points to /bin/init:
Code:
lrwxrwxrwx 1 user user   17 Nov 28 11:21 init -> bin/recovery-util
If we look within /bin/, we can find a bunch of additional scripts and binaries:
Code:
user@ubuntu:/tmp/kv/cpio-root$ ls -l bin/
total 744
-rwxr-xr-x 1 user user   2800 Nov 28 11:21 cat
-rwxr-xr-x 1 user user   7612 Nov 28 11:21 hotplug
-rwxr-xr-x 1 user user  13964 Nov 28 11:21 ipconfig
-rwxr-xr-x 1 user user  78348 Nov 28 11:21 kinit
-rwxr-xr-x 1 user user    636 Nov 28 11:21 load_waveform.sh
-rwxr-xr-x 1 user user  29752 Nov 28 11:21 mkdosfs
-rwxr-xr-x 1 user user   7456 Nov 28 11:21 nfsmount
-rwxr-xr-x 1 user user 526696 Nov 28 11:21 recovery-util
-rwxr-xr-x 1 user user   4316 Nov 28 11:21 run-init
lrwxrwxrwx 1 user user      9 Nov 28 11:21 sh -> sh.shared
-rwxr-xr-x 1 user user  63744 Nov 28 11:21 sh.shared
-rwxr-xr-x 1 user user    728 Nov 28 11:21 sleep
NFS Boot
The inclusion of the nfsmount binary is particularly interesting. Despite the lack of any menu option allowing the user to boot from an NFS share, there are a number of strings within the recovery-util binary that imply that this is possible using the g_ether kernel module:
Code:
nfs_boot_default
ipconfig -d nfsaddrs=%s:%s:%s:%s:%s:%s
nfsmount -o v3,tcp %s:%s /root
nfsmount: retval = %d
Attempt #%d to NFS mount...
%s: Failed to mount NFS on /root: retval=%d
gadget_load_ethernet
/lib/modules/g_ether.ko
%s: Could not load Ethernet gadget module: %s (%d)
This kernel module is not included within the stock initramfs, meaning that it is likely an internal feature used by Lab126 during development. It is possible to create an initramfs that can mount and boot from an NFS share, which we will cover separately in a later post.

Diags firmware update
Another interesting feature of recovery-util relates to a type of firmware update that I was not previously aware of and have not encountered in the wild. The recovery-util binary contains strings that imply that it is capable of installing a diags kernel and rootfs:
Code:
diagsfs_gz_file_data
imx60_wario/diag-uImage.sig
diagrootfs.img.gz.sig
imx60_wario/diag-uImage
diagrootfs.img.gz
ERROR:%s: error getting diagsfs size: %d. Skipping diagsfs size check.
Public key location
As with the main updater within the rootfs, the recovery-util updater will only accept a signed firmware image that contains files signed with the same public key. These keys are stored within the binary itself; their existence can be verified by searching for the first 8 bytes of each of the production public keys:
Code:
user@ubuntu:/tmp/kv/cpio-root$ xxd -ps bin/recovery-util | grep 00b17e98
00000000000000000000000000000000650000000000000000b17e9899d5
user@ubuntu:/tmp/kv/cpio-root$ xxd -ps bin/recovery-util | grep 00b0f74b
8afc3100000000000000010001000000000000b0f74b8e062739f169108a
It is possible to replace these keys and repack the initramfs to create an update mechanism that will accept both Lab126 and user-signed firmware updates. This will be covered separately in a later post.

Summing it up
By examining the both the behaviour of recovery-util over the serial port and the contents of the initramfs, we have been able to broadly understand how this utility fits into the boot process:
  • On boot, the kernel will search for a file to execute
  • Upon finding the /init symlink, the kernel will follow it and execute recovery-util
  • recovery-util will present an option that allows the user to halt the boot process and access the various menu options over the serial port
  • If this option is not selected, recovery-util will search for an update file to install, handle that update, then reboot into the updated rootfs
  • recovery-util achieves this using a combination of native code within the binary itself and exec calls to the included klibc utilities.

Context
With this understanding, we can begin to plan out how to create an initramfs of our own. This raises a couple of important questions:
  • How do we structure the files that we want to include within the initramfs?
  • How do we implement our desired functionality within the initramfs?

In this how-to, we will structure our initramfs by creating a directory containing scripts and kernel modules that we wish to include and create an initramfs list to specify the required device nodes. To provide a simple starting point for further experimentation, we will create a simple ash script that will mount and switch to the root partition, rather than creating a more complex executable using C.

Structuring initramfs files
Although it is not particularly obvious without reading the help for the kernel configuration menu item, it is possible to include a directory or list of directories containing the files that we want to include within the initramfs.

This might seem like a good strategy, but presents us with a problem: when creating an initramfs, we need to include not only the binaries that we want to run, but also the device nodes that are required for these tasks. If we use a directory-based approach, these would need to be created manually using mknod - a tedious, error prone task that involves the need to escalate to root.

We can avoid this by defining the files and device nodes that we want to include within a list file.

This is the same approach used by Lab126 and an example of the format that this list should take can be found within the linux-2.6.31-lab126 kernel sources:
Code:
dir /dev 0755 0 0
nod /dev/tty 0660 0 0 c 5 0
nod /dev/console 0600 0 0 c 5 1
nod /dev/null 0666 0 0 c 1 3
nod /dev/zero 0660 0 0 c 1 5
nod /dev/random 0660 0 0 c 1 8
nod /dev/mem 0660 0 0 c 1 1

nod /dev/pmic 0660 0 0 c 250 0
nod /dev/usb1 0660 0 0 c 189 0
nod /dev/watchdog 0660 0 0 c 10 130

nod /dev/ttymxc0 0660 0 0 c 207 16
nod /dev/ttymxc1 0660 0 0 c 207 17
nod /dev/ttymxc2 0660 0 0 c 207 18
nod /dev/ttymxc3 0660 0 0 c 207 19
nod /dev/ttymxc4 0660 0 0 c 207 20

dir /dev/fb 0755 0 0
nod /dev/fb/0 0660 0 0 c 29 0
slink /dev/fb0 /dev/fb/0 0660 0 0

nod /dev/mmcblk0 0660 0 0 b 179 0
nod /dev/mmcblk0p1 0660 0 0 b 179 1
nod /dev/mmcblk0p2 0660 0 0 b 179 2
nod /dev/mmcblk0p3 0660 0 0 b 179 3
nod /dev/mmcblk0p4 0660 0 0 b 179 4

nod /dev/mmcblk1 0660 0 0 b 179 8
nod /dev/mmcblk1p1 0660 0 0 b 179 9
nod /dev/mmcblk1p2 0660 0 0 b 179 10
nod /dev/mmcblk1p3 0660 0 0 b 179 11
nod /dev/mmcblk1p4 0660 0 0 b 179 12

dir /dev/mtd 0755 0 0
nod /dev/mtd/0 0660 0 0 c 90 0
nod /dev/mtd/1 0660 0 0 c 90 2
nod /dev/mtd/2 0660 0 0 c 90 4
nod /dev/mtd/3 0660 0 0 c 90 6
nod /dev/mtd/4 0660 0 0 c 90 8
nod /dev/mtd/5 0660 0 0 c 90 10

dir /dev/mtdblock 0755 0 0
nod /dev/mtdblock/0 0660 0 0 b 31 0
nod /dev/mtdblock/1 0660 0 0 b 31 1
nod /dev/mtdblock/2 0660 0 0 b 31 2
nod /dev/mtdblock/3 0660 0 0 b 31 3
nod /dev/mtdblock/4 0660 0 0 b 31 4
nod /dev/mtdblock/5 0660 0 0 b 31 5

nod /dev/loop0 0660 0 0 b 7 0
nod /dev/loop1 0660 0 0 b 7 1
nod /dev/loop2 0660 0 0 b 7 2
nod /dev/loop3 0660 0 0 b 7 3

dir /dev/i2c 0755 0 0
nod /dev/i2c/0 0660 0 0 c 89 0
nod /dev/i2c/1 0660 0 0 c 89 1
nod /dev/i2c/2 0660 0 0 c 89 2

dir /dev/input 0755 0 0
nod /dev/input/event0 0660 0 0 c 13 64
nod /dev/input/event1 0660 0 0 c 13 65
nod /dev/input/event2 0660 0 0 c 13 66

dir /proc 0755 0 0

dir /sys 0755 0 0

dir /root 0700 0 0

dir /lib 0755 0 0

# klibc lib
file /lib/klibc-XXXXXXXXXXXXXXXXXXXXXXXXXXX.so /initrd/lib/klibc/lib/klibc-XXXXXXXXXXXXXXXXXXXXXXXXXXX.so 0755 0 0

dir /lib/modules 0755 0 0

dir /mnt 0755 0 0
dir /mnt/wfm 0755 0 0

# usb gadget drivers
file /lib/modules/arcotg_udc.ko /initrd/initramfs/lib/arcotg_udc.ko 0755 0 0
file /lib/modules/g_file_storage.ko /initrd/initramfs/lib/g_file_storage.ko 0755 0 0

# eink drivers
file /lib/modules/eink_fb_waveform.ko /initrd/initramfs/lib/eink_fb_waveform.ko 0755 0 0
file /lib/modules/mxc_epdc_fb.ko /initrd/initramfs/lib/mxc_epdc_fb.ko 0755 0 0

# keypad driver
file /lib/modules/mxc_keyb.ko /initrd/initramfs/lib/mxc_keyb.ko 0755 0 0
file /lib/modules/tequila_keypad.ko /initrd/initramfs/lib/tequila_keypad.ko 0755 0 0
file /lib/modules/whitney_button.ko /initrd/initramfs/lib/whitney_button.ko 0755 0 0

# klibc utilities
dir /bin 0755 0 0
file /bin/ipconfig /initrd/lib/klibc/bin/ipconfig 0755 0 0
file /bin/nfsmount /initrd/lib/klibc/bin/nfsmount 0755 0 0
file /bin/run-init /initrd/lib/klibc/bin/run-init 0755 0 0
file /bin/recovery-util /initrd/sbin/recovery-util 0755 0 0
file /bin/hotplug /initrd/sbin/hotplug 0755 0 0
file /bin/kinit /initrd/lib/klibc/bin/kinit 0755 0 0
file /bin/sh /initrd/lib/klibc/bin/sh.shared 0755 0 0
file /bin/mkdosfs /initrd/initramfs/bin/mkdosfs 0755 0 0

# link init
slink /init /bin/recovery-util 0755 0 0
Although initially confusing, we can break down what each of the item types and parameters refer to like so:
Code:
dir <PATH_TO_CREATE> <PERMISSIONS> <UID> <GID>
slink <SYMLINK_TO_CREATE> <PERMISSIONS> <UID> <GID>
file <INITRAMFS_PATH> <HOST_PATH> <PERMISSIONS> <UID> <GID>
nod <NODE_TO_CREATE> <PERMISSIONS> <UID> <GID> <DEVICE_TYPE> <MAJOR> <MINOR>
We will follow the way that Lab126 have structured their initramfs list and create a directory at the root of our build host to contain the files that we want to include:
Code:
sudo mkdir -p /initrd/bin
sudo chown -R user:user /initrd
Implementing initramfs functionality
Building Busybox
In this how-to, we will forgo the traditional approach of including the small set of utilities included with klibc and use a statically linked version of Busybox instead. Doing so allows us to implement more complex functionality than is otherwise possible by utilising the various applets that Busybox provides.

Download and extract a copy of the Busybox source code:
Code:
wget https://www.busybox.net/downloads/busybox-1.34.1.tar.bz2 && tar xf busybox-1.34.1.tar.bz2
Enter the directory containing the Busybox source code and start the configuration menu:
Code:
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make menuconfig
Navigate to the Settings submenu and select the Build static binary (no shared libs) option under Build Options

Depending on your toolchain, you may encounter build errors. When using NiLuJe's PW2 toolchain, I needed to make these changes using the configuration menu:
  • Disable nsenter
  • Disable Enable -d and -f flags (requires syncfs(2) in libc) for sync

Copy the statically linked Busybox binary to our staging directory:
Code:
cp busybox /initrd/bin/busybox
Creating an init script
Save the contents of the file below to /initrd/bin/custom_boot.sh:

Code:
#!/bin/busybox ash
/bin/busybox --install -s
mount /dev/mmcblk0p1 /mnt/rootfs
exec switch_root -c /dev/console /mnt/rootfs /sbin/init
There's a few things going on here:
  • Busybox detects which applet needs to be run by checking the first parameter that is is called with. We want to use the stripped down version of the ash shell included with Busybox, so we specify this within the shebang
  • To avoid having to specify the full path to Busybox each time we call an applet, we can install symlinks to each applet within the initramfs by running /bin/busybox --install -s. Note that this command expects a number of directories to exist and will fail if they are not specified within our initramfs list
  • We're mounting the rootfs partition to /mnt/rootfs. Note that this directory also needs to be specified within our initramfs list
  • Finally, we use switch_root to switch to /mnt/rootfs and start the main Upstart init process by calling /sbin/init. We use exec to run switch_root as we want to replace the shell that is running this script with this process (the default behaviour would be to run switch_root as a new process, which causes problems as Upstart expects /sbin/init to be PID 1)

Creating an initramfs list
Save the contents of the file below to /initrd/initramfs-custom.list:

Code:
# Root directories
dir /bin 755 0 0
dir /dev 755 0 0
dir /lib 755 0 0
dir /root 700 0 0
dir /mnt 755 0 0
dir /proc 755 0 0
dir /sys 755 0 0

# Busybox applet directories
dir /sbin 755 0 0
dir /usr 755 0 0
dir /usr/bin 755 0 0
dir /usr/sbin 755 0 0

# Second level
dir /mnt/wfm 777 0 0
dir /mnt/rootfs 777 0 0
dir /lib/modules 777 0 0

# Kernel module (example, we're not using this)
file /lib/modules/arcotg_udc.ko  /initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/arcotg_udc.ko

# Binaries + scripts
file /bin/busybox /initrd/bin/busybox 755 0 0
file /bin/custom_boot.sh /initrd/bin/custom_boot.sh 755 0 0

# Devices
nod /dev/console 600 0 0 c 5 1
nod /dev/frontlight 660 0 0 c 10 162
nod /dev/kmsg 660 0 0 c 1 11
nod /dev/loop0 660 0 0 b 7 0
nod /dev/loop1 660 0 0 b 7 1
nod /dev/loop2 660 0 0 b 7 2
nod /dev/loop3 660 0 0 b 7 3
nod /dev/mem 660 0 0 c 1 1
nod /dev/mmcblk0 660 0 0 b 179 0
nod /dev/mmcblk0boot1 660 0 0 b 179 16
nod /dev/mmcblk0boot0 660 0 0 b 179 8
nod /dev/mmcblk0p1 660 0 0 b 179 1
nod /dev/mmcblk0p2 660 0 0 b 179 2
nod /dev/mmcblk0p3 660 0 0 b 179 3
nod /dev/mmcblk0p4 660 0 0 b 179 4
nod /dev/null 666 0 0 c 1 3
nod /dev/pmic 660 0 0 c 250 0
nod /dev/random 660 0 0 c 1 8
nod /dev/tty 660 0 0 c 5 0
nod /dev/tty1 660 0 0 c 5 1
nod /dev/tty2 660 0 0 c 5 2
nod /dev/tty3 660 0 0 c 5 3
nod /dev/tty4 660 0 0 c 5 4
nod /dev/tty5 660 0 0 c 5 5
nod /dev/tty6 660 0 0 c 5 6
nod /dev/ttyGS0 660 0 0 c 253 0
nod /dev/ttymxc0 660 0 0 c 207 16
nod /dev/ttymxc1 660 0 0 c 207 17
nod /dev/ttymxc2 660 0 0 c 207 18
nod /dev/ttymxc4 660 0 0 c 207 20
nod /dev/ttymxc3 660 0 0 c 207 19
nod /dev/usb1 660 0 0 c 189 0
nod /dev/watchdog 660 0 0 c 10 130
nod /dev/zero 660 0 0 c 1 5
dir /dev/fb 755 0 0
nod /dev/fb/0 660 0 0 c 29 0
dir /dev/input 755 0 0
nod /dev/input/event0 660 0 0 c 13 64
nod /dev/input/event1 660 0 0 c 13 65
dir /dev/i2c 755 0 0
nod /dev/i2c/0 660 0 0 c 89 0
nod /dev/i2c/1 660 0 0 c 89 1
nod /dev/i2c/2 660 0 0 c 89 2

slink /dev/fb0 /dev/fb/0 777 0 0
slink /init /bin/custom_boot.sh 777 0 0
There are a few things to note with this simple example:
  • We are including the custom_boot.sh script that we created at /bin/custom_boot.sh
  • We then create a symlink to this file using a path relative to the file structure of the initramfs

Creating an initramfs list
Before we can build the kernel, we need to build any kernel modules that we might need - note that the example kernel module in the initramfs list that we just created points to a file that does not exist yet.

Load the device configuration for your target device:
Code:
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make imx60_wario_defconfig
Prepare and build the kernel modules:
Code:
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make modules_prepare
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make modules -j8
Install the kernel modules to the staging directory:
Code:
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make modules_install INSTALL_MOD_PATH=/initrd
The full set of standard kernel modules can now be found within the staging directory:
Code:
user@ubuntu:~/Git/linux-3.0.35-lab126$ find /initrd/lib/ -name *.ko
/initrd/lib/modules/3.0.35-lab126/kernel/compat-wireless/net/wireless/cfg80211.ko
/initrd/lib/modules/3.0.35-lab126/kernel/compat-wireless/drivers/net/wireless/ath/ath.ko
/initrd/lib/modules/3.0.35-lab126/kernel/compat-wireless/drivers/net/wireless/ath/ath6kl/ath6kl_sdio.ko
/initrd/lib/modules/3.0.35-lab126/kernel/crypto/tcrypt.ko
/initrd/lib/modules/3.0.35-lab126/kernel/fs/fuse/fuse.ko
/initrd/lib/modules/3.0.35-lab126/kernel/fs/nls/nls_ascii.ko
/initrd/lib/modules/3.0.35-lab126/kernel/fs/nls/nls_utf8.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/cyttsp4_core.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/cyttsp4_i2c.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/zforce2.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/cyttsp4_loader.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/cyttsp4_device_access.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/cyttsp4_debug.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/touchscreen/cyttsp4_mt_b.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/misc/als_max44009.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/misc/prox_pic12lf1822.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/keyboard/fsr_keypad.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/input/keyboard/drv26xx_haptics.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/net/ppp_async.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/net/slhc.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/net/wan/mwan.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/net/wan/pkt_monitor.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/net/ppp_generic.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/host/ehci-hcd.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/otg/fsl_otg_arc.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/g_ether.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/arcotg_udc.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/g_file_storage.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/gadget/g_serial.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/serial/usb_wwan.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/serial/option.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/usb/serial/usbserial.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/misc/mxs-perfmon.ko
/initrd/lib/modules/3.0.35-lab126/kernel/drivers/video/mxc/mxc_epdc_fb.ko
/initrd/lib/modules/3.0.35-lab126/kernel/lib/crc-ccitt.ko
If you need a kernel module that isn't available by default, select it and any kernel modules that it depends upon using the configuration menu and rebuild the kernel modules.

Tying it all together
We now have all of the components that we need to create an initramfs.

Using the kernel configuration menu, navigate to General Setup and set the parameter Initramfs source file(s) to /initrd/initramfs-custom.list, then save and exit:
Code:
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make menuconfig
Build the uImage variant of the kernel:
Code:
ARCH=arm CROSS_COMPILE=arm-kindlepw2-linux-gnueabi- make uImage -j8
The finished kernel can be found under arch/arm/boot/uImage:
Code:
user@ubuntu:~/Git/linux-3.0.35-lab126$ ls -l arch/arm/boot/uImage 
-rw-rw-r-- 1 user user 3435104 Nov 28 14:29 arch/arm/boot/uImage
Flashing the kernel
At this point, we have a kernel containing a initramfs containing the files that we specified within our initramfs list. Before flashing this kernel to the device, you should test that it works as expected; a how-to on loading custom kernels can be found here.

Once you are confident that the kernel works as expected, we can transfer it to the device and flash it using this command:
Code:
dd if=/mnt/us/uImage of=/dev/mmcblk0 bs=4096 seek=65
katadelos is offline   Reply With Quote
Old 01-23-2022, 10:52 PM   #2
cwalls
Member
cwalls can extract oil from cheesecwalls can extract oil from cheesecwalls can extract oil from cheesecwalls can extract oil from cheesecwalls can extract oil from cheesecwalls can extract oil from cheesecwalls can extract oil from cheesecwalls can extract oil from cheese
 
Posts: 10
Karma: 1010
Join Date: Jan 2022
Device: Kindle Voyage 3G + WiFi (Europe)
This was very helpful to me, thank you!

I had to add this to custom_boot.sh:

Code:
[ -d /mnt/rootfs ] || mkdir /mnt/rootfs
mount -t proc proc /proc
sleep 0.1
I also tried to use `CONFIG_INITRAMFS_SOURCE="/path/to/orig.cpio"`, but it resulted in `Kernel panic - not syncing: broken padding`, not sure why.
cwalls is offline   Reply With Quote
Advert
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
building a genre custom column from tags meghane_e Library Management 3 03-09-2019 09:39 PM
Literary Fun! Fun! Fun! • October 2018 sun surfer Book Clubs 22 10-12-2018 08:12 PM
Getting Started in ePUB For Fun & Profit SeaCanary Workshop 2 01-28-2014 08:35 PM
extract initramfs from kindle dx kernel image chinaet Kindle Developer's Corner 16 04-19-2013 12:16 PM
Touch building custom dictionaries, especially Japanese-English tshering Kobo Reader 0 07-12-2012 06:00 PM


All times are GMT -4. The time now is 07:59 AM.


MobileRead.com is a privately owned, operated and funded community.