How to create initrd/initramfs for use with tftp

Hi,

Can anybody explain me how can i create a kernel with initrd (modules inside) for use with tftp (netboot)?

I know i can boot from tftp via uboot, have not tried it, because i can only boot the kernel itself (uimage) and modules are missing. This imho can be solved by an inird build into uimage.

If the initrd with modules (modules currently ~60mb) is too much maybe i can put them in separate file and mount inside initrd or load via nfs or similar but this is more work everytime i change kernel.

Regards Frank

Hi Frank,

I’m not sure what your end goal is, but if you just want to bootstrap network boot with an initramfs you could look into booting directly to a rootfs on nfs. Since you exactly know the (only) platform you support this should not involve a lot of kernel configuration. See here and here.

If you just want to use the initrd as your filesystem, you’d have to create a rootfs in a folder somewhere. (a stripped down version of) The sysroot of your toolchain + busybox could serve as the bare minimum. You most likely also need an overlay (with your specific application and config files) and of course the linux modules.

I run the following script (in fakeroot!) to generate the cpio archive:

cd [your rootfs folder (sysroot+busybox)]

# Image requirements that busybox doesn't typically generate for you
ln -sf bin/busybox init
mkdir -p dev sys proc run boot
mknod -m 622 dev/console c 5 1
mknod -m 755 dev/null c 1 3
chown root:root bin/busybox init dev/console dev/null

# Some optional cleanup steps
rm -rf usr/include usr/lib/gconv usr/share
${CROSS_COMPILE}strip lib/*.so 2>/dev/null
${CROSS_COMPILE}strip sbin/ldconfig sbin/sln 2>/dev/null

find . | cpio -H newc -o > ../initramfs.cpio # You could pipe this through gzip as well if you want to compress it

I would advise you to keep the image as small as possible, because it all gets loaded into memory. Mine is about 18M uncompressed. You can try it if you want, but I haven’t touched this file since april, no guarantees. Maybe it’s helpful to see the list of files in the initrd.

Edit: of course the modules in my initrd will not be compatible with your kernel. You could use it as a reference for your own.

1 Like

My goal is to load a full system nlt only kernel-image via network to avoid permananetly writing kernel to sd…

Can you describe install of busybox amd the overlay? Are there any memory limitations (~100 mb)?

Hi Frank. If you want to boot everything over network - it is possible. You need to have uboot with support for networking. I had the same problem - I didn’t want to write every kernel I compiled to SD card. Now I’m able to boot kernel from uboot via tftp but I don’t use any initrd/initramfs (initrd is not necessary). At the moment I’m mounting filesystem from SD card but it is possible to share some filesystem via nfs-root - so everything can be accessed via network. The question is - if you have properly compiled uboot with support for networking and tftp?

I currently collect infos how-to-do :slight_smile: have not tested it yet…i found infos how i can boot uimage but then i miss the modules…so i search a (easy) way to load them also over network.

I use my modified uboot…do i meed to enable anyrhing to get network working? I expected that this is working…

In case of uboot you need as I wrote before support for network (Ethernet) and tftp commands. Then you can use for example: tftfpboot 0x41000000 zImage; tftpboot 0x43000000 sun8i-something.dtb; bootz 0x41000000 - 0x43000000. And your kernel should be loaded via tftp and launched. Of course before you need to setup environment variables like ipaddress and serverip (tftpserver) and tftp server configured properly on your server.

I use this uboot (official r2 from bsp) with some modifications: https://github.com/frank-w/bpi-r2-uboot

Do i need additional settings in code and recompile or simply uboot-commands?

This is my current preparation:

setenv ipaddr 192.168.0.11
setenv netmask 255.255.255.0
setenv serverip 192.168.0.10
setenv bootfile uImage
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait ip=dhcp

tftp 0x80200000 uImage
bootm 0x80200000

alternative

tftpboot uImage
bootm

Ok, I see you don’t use DTB file with kernel, but if it is working for you - it’s fine. Regarding uboot - if this setup is working - it is also ok and you don’t need to add anything - I think. There is possibility to mount even filesystem via network - but it needs to enable a few features in kernel (nfs-root).

My kernel has appended dtb like official kernel so i guess i don’t need to load it separately,right?

Yes, I guessed that your kernel already contains DTB :slight_smile:

tftp-boot seems to work fine:

uboot-config (uenv.txt; after reloadbootmenu):

ipaddr=192.168.0.11
netmask=255.255.255.0
serverip=192.168.0.10

bootfile=uImage_4.14.73
netbootargs=console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait ip=dhcp

bootmenu_1=2. Boot kernel from TFTP.=run bootnet
bootnet=printenv; setenv bootargs ${netbootargs};tftp 0x80200000 ${bootfile};bootm

first lines from bootlog for kernel-loading:

Enter mt7623_ethifsys_init()
[mt7623_pinmux_set]start
[mt7623_pinmux_set]end

 Waitting for RX_DMA_BUSY status Start... done

Enter setup_internal_gsw()
MT7530 Reset Completed!!
change HW-TRAP to 0x1015edf
 Release MT7623 RXC Reset
set LAN/WAN LLLLW
Using mtk_eth device
TFTP from server 192.168.0.10; our IP address is 192.168.0.11
Filename 'uImage_4.14.73'.
Load address: 0x80200000
Loading: T T #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##T #######################################
         175.8 KiB/s
done
Bytes transferred = 7267918 (6ee64e hex)
bootm flag=0, states=70f
## Booting kernel from Legacy Image at 80200000 ...
   Image Name:   Linux Kernel 4.14.73-main
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    7267854 Bytes = 6.9 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.14.73-bpi-r2-main (frank@frank-N56VZ) (gcc version 7.3.0 (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04)) #151 SMP Mon Oct 1 15:26:15 CEST 2018
[    0.000000] CPU: ARMv7 Processor [410fc073] revision 3 (ARMv7), cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: Bananapi BPI-R2
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] [WMT-CONSYS-HW][W]reserve_memory_consys_fn: name: consys-reserve-memory, base: 0xffe00000, size: 0x100000

full log: netboot.log (72,3 KB)

currently without modules/initramfs/NFS

@Adam_B can you guide me to get a bootable NFS-Root-dir or a initramfs with my modules?

So for an initramfs, you are putting together a filesystem from different sources (sysroot, busybox, kernel modules and overlay).

Busybox is the package (also used by buildroot) that compiles all the common system utilities (like sh, grep, mount, tar, etc.) into a single binary. Like this you can include a lot of tools while still keeping a minimal footprint. If you want a more advanced filesystem you could also use buildroot, which includes build scripts for more high-level utilities like wpa_supplicant, hostapd, etc. The output of both busybox and buildroot is a folder with the basic filesystem. You need to add the libraries from your toolchain (sysroot) and the kernel modules.

The overlay is just a folder with files you need to add or edit. As last step in the compilation process, you copy this folder over the filesystem and overwrite the existing files with the changes you’ve made.

As a reference, my overlay has the following files:

./etc/init.d/rcS
./etc/fstab
./etc/inittab
./etc/profile

Did you try to boot my initramfs? It should work for you, only the device drivers are not loading.

To run linux with nfs-root you need:

  1. kernel compiled with support for nfs and nfs-root and kernel level IP autoconfiguration
  2. properly configured and running nfs-server (/etc/exports file)
  3. the whole rootfs of your rootfs (for example from your SD card) copied into nfs-server
  4. properly configured kernel commandline. Tak a look at: https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt

The kernel must be given its IP address, netmask, your nfs server, etc. There are plenty other examples in the net how to boot linux with nfs-root.

How does kernel-cmdline have to look to make eth0 up and give ip-address to lan0?

Documentation is your friend - have you taken a look at: https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt?

example:

ip=10.0.0.2:10.0.0.1::255.255.255.0::eth0 root=/dev/nfs nfsroot=10.0.0.1:/nfs_qemu

I looked at it but eth0 should only be set to up without ip and the ip have to be set to lan0…I guess i need to add 2 ip-entries…one without ips for eth0 and one for lan0, is this possible?

@bitmaster i try your initramfs today if get near my r2 :slight_smile: how large can be a init ramfs (any limitation?)

I’m not sure what do you mean as “lan0”, and why do you want to set its ip addr…

I gave you working example from my configuration. 10.0.0.2 is your ip address of eth0 (banana pi), and 10.0.0.1 is your server ip. On this server 10.0.0.1 there is nfs server. So - your banana pi will have 10.0.0.2 address and will try to connect to 10.0.0.1 (nfs-server).

Try to change those ip addresses to be appropriate your network (192.168.x.y ?)

in kernel 4.14 (4.9+) you have a dsa-driver for r2 where eth0/eth1 the cpu-ports and lan0-3+wan are the physical-ports on the switch

the cpu-ports have to be set to up and the ip should be configured to the user-ports (lanx,wan)

see https://www.fw-web.de/dokuwiki/doku.php?id=en/bpi-r2/network/start (introduction and IP-permanent)

i guess you have no r2 or using the old 4.4-kernel?

Yes, you are right - I have banana pi m2 ultra, not r2. There is no ethernet switch on M2 ultra. In such (your) case of configuration with eth-switch I’m not sure which interface you should set - or even both. Sorry. I tried to help. I’m only guessing you need to set eth0 and maybe one of the lanX interfaces from kernel command line.

thank you for helping :slight_smile: do you know if i can put 2 IP-options in cmdline?

@bitmaster i had run your initrd successfully, and here i see, that eth0/1 are already up (maybe debian/ubuntu put them down if they not configured). my wan-port got dhcp-response from my other r2 (main-router) and i can reach my r2 over ipv4

tried with this ip-config:

ip=192.168.0.11:192.168.0.10::255.255.255.0::wan

ip-adress is set to wan, but i think i need to set 3rd param because the default-gateway is missing, i had to set it manually via “ip route add default via 192.168.0.10”

now it works so far with your initramfs…but i have not figured out how to set dns-server…oh it’s also in documentation

ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>:<ntp0-ip>

but seems not working (with @bitmaster s initramfs)…i have only 127.0.0.1 as dns…

tried with this:

ip=192.168.0.11:192.168.0.10:192.168.0.10:255.255.255.0::wan::192.168.0.10:8.8.8.8

boot.log.gz (51,1 KB)

btw. setting mac in uboot seems not working…i see dhcp-request from another mac as i configured using ethaddr