Building your own TFTP-bootable kernel

I’ve mentioned earlier that (if you have a serial cable connected) you can interrupt u-boot’s startup and tell it to TFTP-boot your own kernel (allows you to write your own passwd and shadow files, for example).

Here, I’ll document how to build your own openwrt-based kernel (with embedded “initramfs” root filesystem).

NOTE: If you don’t want to bother building your own kernel, I’ve uploaded a pre-built binary image here.

Configure/build the kernel

First, download the openwrt source code (I’m assuming you are using Linux):

git clone git://git.openwrt.org/15.05/openwrt.git openwrt
cd openwrt

Next, you need to edit the file “target/linux/ar71xx/generic/config-default”.  It should contain the following:

CONFIG_CMDLINE="console=ttyS0,115200 loglevel=7 root=/dev/ram0 rootfstype=ramfs board=TL-MR3420-v2"
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_EHCI_ATH79=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_EHCI_PCI=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_STORAGE=y
CONFIG_EXT4_FS=y

The “CONFIG_CMDLINE=” is important (in order to get serial console access, and to boot from the initramfs instead of the image in the Circle’s flash).  The remaining items are required to enable access to the eMMC flash (a USB mass storage device).

Then, you need to configure the build for the correct chipset/target.  Use the command “make menuconfig” to build/run the configuration utility.

make menuconfig

Under “Target System”, choose “Atheros AR7xxx/AR9xxx”, and under “Subtarget”, choose “Generic” (these should be the defaults).

Under “Target Profile”, scroll down and select the “TP-LINK TL-WR841N/ND” profile.

Under “Target Images”, select “ramdisk” (should default to “lzma” compression) and de-select “squashfs”.

Save your configuration.

Then, type “make” (or “make -j12” for faster parallel build) and wait (it’ll take a while).

When you are finished, there will be a lot of images in the “bin/ar71xx” subdirectory.  Copy the file named “openwrt-ar71xx-generic-vmlinux-initramfs.bin” to your TFTP server’s root directory (call it “tftp-kernel.bin”):

cp bin/ar71xx/openwrt-ar71xx-generic-vmlinux-initramfs.bin /var/lib/tftpboot/tftp-kernel.bin
TFTP-booting your new kernel image

I am assuming that you know how to configure a TFTP server on your machine, and that it is all setup.  My TFTP server’s IP address is 172.16.0.1, so I am using that subnet in my example below.

Connect to your Circle device using the serial port (minicom, for example).  It defaults to 115,200bps 8/n/1.  Connect an ethernet cable from your Circle device to the TFTP server.

Power-ON the Circle.  Be prepared to interrupt the u-boot startup on your serial console (by pressing a key when u-boot says “Hit any key to stop autobooting”):

********************************************* 
* U-Boot 1.1.4 (Sep 26 2015, 08:47:34) * 
********************************************* 
 
AP123 (AR9341) U-Boot for TL-MR3420 v2 
 
DRAM: 64 MB DDR 32-bit 
FLASH: Macronix MX25L64 (8 MB) 
CLOCKS: 535/400/200/25 MHz (CPU/RAM/AHB/SPI)

LED on during eth initialization...

Hit any key to stop autobooting: 0

uboot>

As I said, my TFTP server is at 172.16.0.1.  I’ll set “serverip” to that, and set the Circle’s IP address (“ipaddr”) to 172.16.0.5:

uboot> setenv serverip 172.16.0.1
uboot> setenv ipaddr 172.16.0.5

Now, load the kernel using the “tftpboot” command:

uboot> tftpboot 0x80060000 tftp-kernel.bin
Link down: eth0
Ethernet mode (duplex/speed): 1/1000 Mbps
TFTP from IP: 172.16.0.1
 Our IP: 172.16.0.5
 Filename: 'tftp-kernel.bin'
Load address: 0x80060000
 Using: eth1

Loading: ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ########################################
 ###################

TFTP transfer complete!

Bytes transferred: 5212820 (0x4f8a94)

uboot>

Now, start the kernel with the “go” command (start address is 0x0400 bytes after the load address used for the “tftpboot” command):

uboot> go 0x80060400
## Starting application at 0x80060400...
[ 0.000000] Linux version 3.18.29 (paulbart@localhost.localdomain) (gcc version 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 r49294) ) #2 Tue May 3 21:59:28 EDT 2016
[ 0.000000] bootconsole [early0] enabled
[ 0.000000] CPU0 revision is: 0001974c (MIPS 74Kc)
[ 0.000000] SoC: Atheros AR9341 rev 3
[ 0.000000] Determined physical RAM map:
[ 0.000000] memory: 04000000 @ 00000000 (usable)
[ 0.000000] Initrd not found or empty - disabling initrd
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x00000000-0x03ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x00000000-0x03ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x00000000-0x03ffffff]
[ 0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[ 0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
[ 0.000000] Kernel command line: 0x80060400 console=ttyS0,115200 loglevel=7 root=/dev/ram0 rootfstype=ramfs board=TL-MR3420-v2
[ 0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.000000] Writing ErrCtl register=00000000
[ 0.000000] Readback ErrCtl register=00000000
[ 0.000000] Memory: 58576K/65536K available (3008K kernel code, 146K rwdata, 636K rodata, 1960K init, 191K bss, 6960K reserved)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS:51
[ 0.000000] Clocks: CPU:535.000MHz, DDR:400.000MHz, AHB:200.000MHz, Ref:25.000MHz
[ 0.000000] Calibrating delay loop... 266.64 BogoMIPS (lpj=1333248)
[ 0.080000] pid_max: default: 32768 minimum: 301
[ 0.080000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.090000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.100000] NET: Registered protocol family 16
[ 0.100000] MIPS: machine is TP-LINK TL-MR3420 v2
[ 0.570000] SCSI subsystem initialized
[ 0.570000] usbcore: registered new interface driver usbfs
[ 0.580000] usbcore: registered new interface driver hub
[ 0.580000] usbcore: registered new device driver usb
[ 0.590000] Switched to clocksource MIPS
[ 0.590000] NET: Registered protocol family 2
[ 0.600000] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.600000] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.610000] TCP: Hash tables configured (established 1024 bind 1024)
[ 0.620000] TCP: reno registered
[ 0.620000] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.630000] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.640000] NET: Registered protocol family 1
[ 3.010000] futex hash table entries: 256 (order: -1, 3072 bytes)
[ 3.020000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 3.030000] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[ 3.040000] msgmni has been set to 114
[ 3.060000] io scheduler noop registered
[ 3.060000] io scheduler deadline registered (default)
[ 3.070000] Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled
[ 3.080000] console [ttyS0] disabled
· 3.100000] serial8250.0: ttyS0 at MMIO 0x18020000 (irq = 11, base_baud = 1562500) is a 16550A
[ 3.110000] console [ttyS0] enabled
[ 3.110000] console [ttyS0] enabled
[ 3.120000] bootconsole [early0] disabled
[ 3.120000] bootconsole [early0] disabled
[ 3.130000] m25p80 spi0.0: found mx25l6405d, expected m25p80
[ 3.130000] m25p80 spi0.0: mx25l6405d (8192 Kbytes)
[ 3.140000] 5 tp-link partitions found on MTD device spi0.0
[ 3.150000] Creating 5 MTD partitions on "spi0.0":
[ 3.150000] 0x000000000000-0x000000020000 : "u-boot"
[ 3.160000] 0x000000020000-0x00000012e5fc : "kernel"
[ 3.160000] 0x00000012e5fc-0x0000007f0000 : "rootfs"
[ 3.170000] mtd: device 2 (rootfs) set to be root filesystem
[ 3.170000] 1 squashfs-split partitions found on MTD device rootfs
[ 3.180000] 0x0000004d0000-0x0000007f0000 : "rootfs_data"
[ 3.190000] 0x0000007f0000-0x000000800000 : "art"
[ 3.190000] 0x000000020000-0x0000007f0000 : "firmware"
[ 3.220000] libphy: ag71xx_mdio: probed
[ 3.820000] ag71xx ag71xx.0: connected to PHY at ag71xx-mdio.1:00 [uid=004dd042, driver=Generic PHY]
[ 3.830000] eth0: Atheros AG71xx at 0xb9000000, irq 4, mode:MII
[ 4.420000] ag71xx-mdio.1: Found an AR934X built-in switch
[ 4.460000] eth1: Atheros AG71xx at 0xba000000, irq 5, mode:GMII
[ 4.470000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[ 4.470000] ehci-pci: EHCI PCI platform driver
[ 4.480000] ehci-platform: EHCI generic platform driver
[ 4.480000] ehci-platform ehci-platform: EHCI Host Controller
[ 4.490000] ehci-platform ehci-platform: new USB bus registered, assigned bus number 1
[ 4.500000] ehci-platform ehci-platform: TX-TX IDP fix enabled
[ 4.500000] ehci-platform ehci-platform: irq 3, io mem 0x1b000000
[ 4.530000] ehci-platform ehci-platform: USB 2.0 started, EHCI 1.00
[ 4.530000] hub 1-0:1.0: USB hub found
[ 4.540000] hub 1-0:1.0: 1 port detected
[ 4.540000] usbcore: registered new interface driver usb-storage
[ 4.550000] TCP: cubic registered
[ 4.550000] NET: Registered protocol family 17
[ 4.560000] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
[ 4.570000] 8021q: 802.1Q VLAN Support v1.8
[ 4.590000] Freeing unused kernel memory: 1960K (80416000 - 80600000)
[ 4.610000] init: Console is alive
[ 4.620000] init: - watchdog -
[ 4.860000] usb 1-1: new high-speed USB device number 2 using ehci-platform
[ 5.010000] usb-storage 1-1:1.0: USB Mass Storage device detected
[ 5.020000] scsi host0: usb-storage 1-1:1.0
[ 5.620000] init: - preinit -
[ 5.920000] random: procd urandom read with 9 bits of entropy available
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
[ 6.020000] scsi 0:0:0:0: Direct-Access Generic STORAGE DEVICE 0250 PQ: 0 ANSI: 0
[ 6.160000] sd 0:0:0:0: [sda] 15269888 512-byte logical blocks: (7.81 GB/7.28 GiB)
[ 6.160000] sd 0:0:0:0: [sda] Write Protect is off
[ 6.170000] sd 0:0:0:0: [sda] No Caching mode page found
[ 6.180000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 6.190000] sda: sda1 sda2 sda3
[ 6.200000] sd 0:0:0:0: [sda] Attached SCSI removable disk
[ 9.090000] procd: - early -
[ 9.090000] procd: - watchdog -
[ 9.680000] procd: - ubus -
[ 10.690000] procd: - init -
Please press Enter to activate this console.
[ 11.390000] NET: Registered protocol family 10
[ 11.400000] ip6_tables: (C) 2000-2006 Netfilter Core Team
[ 11.420000] Loading modules backported from Linux version v4.4-rc5-1913-gc8fdf68
[ 11.430000] Backport generated by backports.git backports-20151218-0-g2f58d9d
[ 11.440000] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 11.450000] nf_conntrack version 0.5.0 (945 buckets, 3780 max)
[ 11.500000] xt_time: kernel timezone is -0000
[ 11.580000] PPP generic driver version 2.4.2
[ 11.590000] NET: Registered protocol family 24
[ 11.670000] ieee80211 phy0: Atheros AR9340 Rev:3 mem=0xb8100000, irq=47
[ 19.720000] device eth1 entered promiscuous mode
[ 19.740000] IPv6: ADDRCONF(NETDEV_UP): br-lan: link is not ready
[ 19.780000] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[ 21.820000] eth0: link up (100Mbps/Full duplex)
[ 21.820000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

Press ENTER to get to the Linux prompt:

BusyBox v1.23.2 (2016-05-03 21:54:25 EDT) built-in shell (ash)

 _______ ________ __
 | |.-----.-----.-----.| | | |.----.| |_
 | - || _ | -__| || | | || _|| _|
 |_______|| __|_____|__|__||________||__| |____|
 |__| W I R E L E S S F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Chaos Calmer, r49294)
 -----------------------------------------------------
 * 1 1/2 oz Gin Shake with a glassful
 * 1/4 oz Triple Sec of broken ice and pour
 * 3/4 oz Lime Juice unstrained into a goblet.
 * 1 1/2 oz Orange Juice
 * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
root@OpenWrt:/#

Leave a Reply