## Busybox "Embedded Linux from Scratch" Distribution for the Beaglebone ## ### Prepare your Build Sandbox ### $ mkdir -p beaglelfs/{sources,rootfs_install,boot_mnt,rootfs_mnt} ### Acquire an ARM Toolchain ### Download the latest i686 Binary TAR of the ARM GNU/Linux (glibc-based) Lite Toolchain: http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/arm-gnu-linux $ tar xvfj arm-2011.09-70-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 $ export PATH=/path/to/arm-2011.09/bin:$PATH ### Build MLO and U-Boot ### $ cd /path/to/beaglelfs/sources/ $ git clone git://arago-project.org/git/projects/u-boot-am33x.git $ cd u-boot-am33x $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- am335x_evm_config $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- This produces the TI first stage bootloader "MLO", and u-boot bootloader "u-boot.img". ### Build the Linux Kernel ### $ cd /path/to/beaglelfs/sources/ $ git clone git://arago-project.org/git/projects/linux-am33x.git $ cd linux-am33x $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- am335x_evm_defconfig $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- menuconfig Device Drivers -> Generic Driver Options -> Maintain a devtmpfs filesystem to mount at /dev Device Drivers -> Generic Driver Options -> Automount devtmpfs at /dev, after the kernel mounted the rootfs $ make -j4 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- EXTRA_CFLAGS=-mno-unaligned-access uImage (You may need to install the uboot-mkimage package or include u-boot-am33x/tools in your path for the mkimage tool) This produces the Linux kernel image arch/arm/boot/uImage. $ make -j4 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- EXTRA_CFLAGS=-mno-unaligned-access modules $ sudo make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- EXTRA_CFLAGS=-mno-unaligned-access INSTALL_MOD_PATH=/path/to/beaglelfs/rootfs_install modules_install This installs any kernel modules to the root file system temporary installation folder. ### Build Busybox ### $ cd /path/to/beaglelfs/sources/ $ git clone git://busybox.net/busybox.git $ cd busybox $ git checkout remotes/origin/1_19_stable $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- defconfig $ LDFLAGS="--static" make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j4 $ LDFLAGS="--static" make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- install $ rsync -a _install/ /path/to/beaglelfs/rootfs_install/ This produces the statically-linked busybox and all of the symlinks that let it multiplex multiple programs. ### Setup essential root filesystem files ### $ cd /path/to/beaglelfs/rootfs_install Create Core Device files $ mkdir dev $ sudo mknod dev/console c 5 1 $ sudo mknod dev/null c 1 3 Create a basic inittab for init $ mkdir etc $ cat >> etc/inittab null::sysinit:/bin/mount -t proc proc /proc null::sysinit:/bin/hostname -F /etc/hostname null::respawn:/sbin/getty -L ttyO0 115200 vt100 null::shutdown:/sbin/mount -a -r ^D Create the mountpoint for proc $ mkdir proc Create a root user with an empty password $ mkdir root $ cat >> etc/passwd root:x:0:0:root:/root:/bin/sh ^D $ cat >> etc/shadow root::10933:0:99999:7::: ^D Install a basic udhcpc script $ mkdir -p usr/share/udhcpc $ cp /path/to/beaglelfs/sources/busybox/examples/udhcp/simple.script usr/share/udhcpc/default.script Designate a hostname $ cat >> etc/hostname minibeagle ^D ### Create an SD Card Image File ### Create and Partition the Image $ dd if=/dev/zero of=sdcard.img bs=1M count=128 $ echo "Cylinders: " `du -b sdcard.img | awk '{print int($1/255/63/512)}'` $ fdisk sdcard.img x for expert mode h to set heads to 255 s to set sectors to 63 c to set cylinders to value above r to return to normal mode n for new partition: primary, number 1, default first sector, +16M size t to set type of partition with code: c (W95 FAT32 LBA) a to mark bootable partition number 1 n for new partition: primary, number 2, default first sector, default full size w to write the partition table Map block devices to the image $ sudo modprobe loop $ sudo losetup /dev/loop0 sdcard.img $ sudo kpartx -av /dev/loop0 Format the boot and root partitions of the image $ sudo mkfs.vfat -F 16 -n "boot" /dev/mapper/loop0p1 $ sudo mkfs.ext3 -L "rootfs" /dev/mapper/loop0p2 ### Mount the SD Card Image File, Copy Bootloaders, Kernel, Rootfs ### Mount boot (FAT) and rootfs (ext3) partitions $ cd /path/to/beaglelfs/ $ sudo mount /dev/mapper/loop0p1 boot_mnt $ sudo mount /dev/mapper/loop0p2 rootfs_mnt Copy TI bootloader, u-boot bootloader, kernel image to boot partition $ sudo cp /path/to/beaglelfs/sources/u-boot-am33x/MLO boot_mnt/ $ sudo cp /path/to/beaglelfs/sources/u-boot-am33x/u-boot.img boot_mnt/ $ sudo cp /path/to/beaglelfs/sources/linux-am33x/arch/arm/boot/uImage boot_mnt/ $ sudo umount boot_mnt Copy root filesystem and chown it to root $ sudo rsync -a rootfs_install/ rootfs_mnt/ $ sudo chown -R root:root rootfs_mnt/* $ sudo umount rootfs_mnt Unassociate the loopback device $ sudo kpartx -d /dev/loop0 $ sudo losetup -d /dev/loop0 ### Copy the SD Card Image File to a Real SD Card ### $ sudo dd if=sdcard.img of=/dev/sdcardblockdevice bs=1M ### Load the ftdi serial driver ### $ sudo rmmod ftdi_sio usbserial $ sudo modprobe ftdi_sio vendor=0x0403 product=0xa6d0 ### Boot up the Beaglebone! ### Observe the boot output in your favorite serial port terminal on /dev/ttyUSB0 (typically). U-Boot SPL 2011.09-00002-gd0e52e5 (Apr 14 2012 - 22:13:07) Texas Instruments Revision detection unimplemented No AC power, disabling frequency switch OMAP SD/MMC: 0 reading u-boot.img reading u-boot.img U-Boot 2011.09-00002-gd0e52e5 (Apr 14 2012 - 22:13:07) I2C: ready DRAM: 256 MiB WARNING: Caches not enabled No daughter card present NAND: HW ECC Hamming Code selected No NAND device found!!! 0 MiB MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1 *** Warning - readenv() failed, using default environment Net: cpsw Hit any key to stop autoboot: 3  2  1  0 SD/MMC found on device 0 reading uEnv.txt ** Unable to read "uEnv.txt" from mmc 0:1 ** reading uImage 3132976 bytes read ## Booting kernel from Legacy Image at 80007fc0 ... Image Name: Linux-3.1.0-00010-g66bfbd2 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3132912 Bytes = 3 MiB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK XIP Kernel Image ... OK OK Starting kernel ... Uncompressing Linux... done, booting the kernel. [ 0.000000] Linux version 3.1.0-00010-g66bfbd2 (anteater@anteater-laptop) (gcc version 4.6.1 (Sourcery CodeBench Lite 2011.09-70) ) #3 Sun Apr 15 03:47:19 EDT 2012 [ 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c53c7f [ 0.000000] CPU: VIPT nonaliasing data cache, VIPT aliasing instruction cache [ 0.000000] Machine: am335xevm [ 0.000000] Memory policy: ECC disabled, Data cache writeback [ 0.000000] AM335X ES1.0 (neon ) [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024 [ 0.000000] Kernel command line: console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait ip=none [ 0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes) [ 0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes) [ 0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes) [ 0.000000] Memory: 256MB = 256MB total [ 0.000000] Memory: 253516k/253516k available, 8628k reserved, 0K highmem [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) [ 0.000000] DMA : 0xffa00000 - 0xffe00000 ( 4 MB) [ 0.000000] vmalloc : 0xd0800000 - 0xf8000000 ( 632 MB) [ 0.000000] lowmem : 0xc0000000 - 0xd0000000 ( 256 MB) [ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB) [ 0.000000] .text : 0xc0008000 - 0xc0569000 (5508 kB) [ 0.000000] .init : 0xc0569000 - 0xc05a2000 ( 228 kB) [ 0.000000] .data : 0xc05a2000 - 0xc05f7380 ( 341 kB) [ 0.000000] .bss : 0xc05f73a4 - 0xc0631920 ( 234 kB) [ 0.000000] NR_IRQS:396 [ 0.000000] IRQ: Found an INTC at 0xfa200000 (revision 5.0) with 128 interrupts [ 0.000000] Total of 128 interrupts on 1 active controller [ 0.000000] OMAP clockevent source: GPTIMER1 at 24000000 Hz [ 0.000000] OMAP clocksource: GPTIMER2 at 24000000 Hz [ 0.000000] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956ms [ 0.000000] Console: colour dummy device 80x30 [ 0.000248] Calibrating delay loop... 498.89 BogoMIPS (lpj=2494464) [ 0.058636] pid_max: default: 32768 minimum: 301 [ 0.058804] Security Framework initialized [ 0.058931] Mount-cache hash table entries: 512 [ 0.059386] CPU: Testing write buffer coherency: ok [ 0.060496] devtmpfs: initialized [ 0.065357] print_constraints: dummy: [ 0.065822] NET: Registered protocol family 16 [ 0.066246] GPMC revision 6.0 [ 0.069136] OMAP GPIO hardware version 0.1 [ 0.071965] omap_l3_smx omap_l3_smx.0: couldn't find resource [ 0.072625] omap_mux_init: Add partition: #1: core, flags: 0 [ 0.076608] omap_i2c.1: alias fck already exists [ 0.078638] omap2_mcspi.1: alias fck already exists [ 0.079352] omap2_mcspi.2: alias fck already exists [ 0.110257] bio: create slab at 0 [ 0.112549] SCSI subsystem initialized [ 0.114673] usbcore: registered new interface driver usbfs [ 0.115116] usbcore: registered new interface driver hub [ 0.115398] usbcore: registered new device driver usb [ 0.115825] registerd cppi-dma Intr @ IRQ 17 [ 0.115844] Cppi41 Init Done Qmgr-base(d083a000) dma-base(d0838000) [ 0.115856] Cppi41 Init Done [ 0.117806] omap_i2c omap_i2c.1: bus 1 rev4.0 at 100 kHz [ 0.121099] Advanced Linux Sound Architecture Driver Version 1.0.24. [ 0.122604] Switching to clocksource gp timer [ 0.128714] Switched to NOHz mode on CPU #0 [ 0.147961] musb-hdrc: version 6.0, ?dma?, otg (peripheral+host) [ 0.148184] musb-hdrc musb-hdrc.0: dma type: dma-cppi41 [ 0.149640] musb-hdrc musb-hdrc.0: USB OTG mode controller at d080a000 using DMA, IRQ 18 [ 0.149855] musb-hdrc musb-hdrc.1: dma type: dma-cppi41 [ 0.151151] musb-hdrc musb-hdrc.1: USB OTG mode controller at d080c800 using DMA, IRQ 19 [ 0.151659] NET: Registered protocol family 2 [ 0.151904] IP route cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.152274] TCP established hash table entries: 8192 (order: 4, 65536 bytes) [ 0.152499] TCP bind hash table entries: 8192 (order: 3, 32768 bytes) [ 0.152728] TCP: Hash tables configured (established 8192 bind 8192) [ 0.152745] TCP reno registered [ 0.152764] UDP hash table entries: 256 (order: 0, 4096 bytes) [ 0.152796] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) [ 0.153089] NET: Registered protocol family 1 [ 0.153769] RPC: Registered named UNIX socket transport module. [ 0.153793] RPC: Registered udp transport module. [ 0.153804] RPC: Registered tcp transport module. [ 0.153816] RPC: Registered tcp NFSv4.1 backchannel transport module. [ 0.154092] NetWinder Floating Point Emulator V0.97 (double precision) [ 0.167605] VFS: Disk quotas dquot_6.5.2 [ 0.167693] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes) [ 0.168407] msgmni has been set to 495 [ 0.169412] io scheduler noop registered [ 0.169428] io scheduler deadline registered [ 0.169512] io scheduler cfq registered (default) [ 0.170656] Could not set LED4 to fully on [ 0.173080] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled [ 0.175542] omap_uart.0: ttyO0 at MMIO 0x44e09000 (irq = 72) is a OMAP UART0 [ 0.668999] console [ttyO0] enabled [ 0.673414] omap_uart.1: ttyO1 at MMIO 0x48022000 (irq = 73) is a OMAP UART1 [ 0.681311] omap_uart.2: ttyO2 at MMIO 0x48024000 (irq = 74) is a OMAP UART2 [ 0.689344] omap_uart.3: ttyO3 at MMIO 0x481a6000 (irq = 44) is a OMAP UART3 [ 0.697310] omap_uart.4: ttyO4 at MMIO 0x481a8000 (irq = 45) is a OMAP UART4 [ 0.705250] omap_uart.5: ttyO5 at MMIO 0x481aa000 (irq = 46) is a OMAP UART5 [ 0.726113] brd: module loaded [ 0.736568] loop: module loaded [ 0.740097] i2c-core: driver [tsl2550] using legacy suspend method [ 0.746651] i2c-core: driver [tsl2550] using legacy resume method [ 0.753148] at24 1-0051: 32768 byte 24c256 EEPROM, writable, 64 bytes/write [ 0.812658] No daughter card found [ 0.816289] at24 1-0050: 32768 byte 24c256 EEPROM, writable, 64 bytes/write [ 0.831584] Board name: A335BONE [ 0.834997] Board version: 00A3 [ 0.838295] The board is a AM335x Beaglebone. [ 0.843361] omap_hsmmc.0: alias fck already exists [ 0.851729] mtdoops: mtd device (mtddev=name/number) must be supplied [ 0.858922] omap2-nand driver initializing [ 0.863622] OneNAND driver initializing [ 0.912675] davinci_mdio davinci_mdio.0: davinci mdio revision 1.6 [ 0.919181] davinci_mdio davinci_mdio.0: detected phy mask fffffffe [ 0.926567] davinci_mdio.0: probed [ 0.930150] davinci_mdio davinci_mdio.0: phy[0]: device 0:00, driver SMSC LAN8710/LAN8720 [ 0.938999] CAN device driver interface [ 0.943056] CAN bus driver for Bosch D_CAN controller 1.0 [ 0.949690] usbcore: registered new interface driver cdc_ether [ 0.956107] usbcore: registered new interface driver cdc_subset [ 0.962384] Initializing USB Mass Storage driver... [ 0.967794] usbcore: registered new interface driver usb-storage [ 0.974135] USB Mass Storage support registered. [ 0.979051] musb-hdrc musb-hdrc.1: MUSB HDRC host driver [ 0.984773] musb-hdrc musb-hdrc.1: new USB bus registered, assigned bus number 1 [ 0.992721] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002 [ 0.999860] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [ 1.007479] usb usb1: Product: MUSB HDRC host driver [ 1.012711] usb usb1: Manufacturer: Linux 3.1.0-00010-g66bfbd2 musb-hcd [ 1.019664] usb usb1: SerialNumber: musb-hdrc.1 [ 1.025620] hub 1-0:1.0: USB hub found [ 1.029587] hub 1-0:1.0: 1 port detected [ 1.035337] mousedev: PS/2 mouse device common for all mice [ 1.042763] omap_rtc omap_rtc: rtc core: registered omap_rtc as rtc0 [ 1.049481] omap_rtc: already running [ 1.053818] i2c /dev entries driver [ 1.060556] OMAP Watchdog Timer Rev 0x01: initial timeout 60 sec [ 1.067621] cpuidle: using governor ladder [ 1.072584] cpuidle: using governor menu [ 1.081471] usbcore: registered new interface driver usbhid [ 1.087411] usbhid: USB HID core driver [ 1.092564] usbcore: registered new interface driver snd-usb-audio [ 1.101564] ALSA device list: [ 1.104747] No soundcards found. [ 1.108320] oprofile: hardware counters not available [ 1.113644] oprofile: using timer interrupt. [ 1.118164] nf_conntrack version 0.5.0 (3961 buckets, 15844 max) [ 1.125088] ip_tables: (C) 2000-2006 Netfilter Core Team [ 1.130831] TCP cubic registered [ 1.134275] NET: Registered protocol family 17 [ 1.138959] can: controller area network core (rev 20090105 abi 8) [ 1.145592] NET: Registered protocol family 29 [ 1.150264] can: raw protocol (rev 20090105) [ 1.154770] can: broadcast manager protocol (rev 20090105 t) [ 1.160774] Registering the dns_resolver key type [ 1.165831] VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 3 [ 1.173916] ThumbEE CPU extension supported. [ 1.179327] _regulator_get: mpu.0 supply mpu not found, using dummy regulator [ 1.186978] omap2_set_init_voltage: Fail set voltage-dpll_mpu_ck(f=500000000 v=1100000)on vddmpu [ 1.196236] omap2_set_init_voltage: unable to set vdd_mpu [ 1.207896] Detected MACID=40:5f:c2:76:77:2b [ 1.215524] omap_rtc omap_rtc: setting system clock to 2000-01-01 00:12:14 UTC (946685534) [ 1.224900] Waiting for root device /dev/mmcblk0p2... [ 1.264022] mmc0: host does not support reading read-only switch. assuming write-enable. [ 1.274498] mmc0: new high speed SDHC card at address 1234 [ 1.281098] mmcblk0: mmc0:1234 SA04G 3.70 GiB [ 1.288802] mmcblk0: p1 p2 [ 2.954651] kjournald starting. Commit interval 5 seconds [ 3.074509] EXT3-fs (mmcblk0p2): using internal journal [ 3.080015] EXT3-fs (mmcblk0p2): recovery complete [ 3.092581] EXT3-fs (mmcblk0p2): mounted filesystem with ordered data mode [ 3.099909] VFS: Mounted root (ext3 filesystem) on device 179:2. [ 3.109798] devtmpfs: mounted [ 3.113310] Freeing init memory: 228K minibeagle login: root login[541]: root login on 'ttyO0' ~ # uname -a Linux minibeagle 3.1.0-00010-g66bfbd2 #3 Sun Apr 15 03:47:19 EDT 2012 armv7l GNU/Linux ~ # whoami root ~ # ps PID USER TIME COMMAND 1 root 0:00 init 2 root 0:00 [kthreadd] 3 root 0:00 [ksoftirqd/0] 4 root 0:00 [kworker/0:0] 5 root 0:00 [kworker/u:0] 6 root 0:00 [rcu_kthread] 7 root 0:00 [khelper] 8 root 0:00 [kdevtmpfs] 9 root 0:00 [netns] 10 root 0:00 [kworker/u:1] 42 root 0:00 [irq/72-serial i] 44 root 0:00 [irq/73-serial i] 46 root 0:00 [irq/74-serial i] 48 root 0:00 [irq/44-serial i] 50 root 0:00 [irq/45-serial i] 52 root 0:00 [irq/46-serial i] 214 root 0:00 [sync_supers] 216 root 0:00 [bdi-default] 218 root 0:00 [kblockd] 226 root 0:00 [omap2_mcspi] 237 root 0:00 [khubd] 346 root 0:00 [musb-hdrc.0] 349 root 0:00 [musb-hdrc.1] 351 root 0:00 [rpciod] 353 root 0:00 [kworker/0:1] 361 root 0:00 [kswapd0] 362 root 0:00 [fsnotify_mark] 363 root 0:00 [nfsiod] 364 root 0:00 [crypto] 481 root 0:00 [kpsmoused] 500 root 0:00 [kworker/u:2] 533 root 0:00 [mmcqd/0] 538 root 0:00 [kjournald] 541 root 0:00 -sh 543 root 0:00 [flush-179:0] 545 root 0:00 ps ~ # ### Note ### There are known issues with DNS functionality in statically-linked glibc programs (like busybox in this case), because libnss must be dynamically loaded. Building a uClibc toolchain and linking busybox against that would resolve this. ### References ### http://pakesson.se/b/2012/01/arch-linux-on-the-beaglebone/ http://dev.gentoo.org/~armin76/arm/beaglebone/install.xml http://blog.galemin.com/2011/05/linux-kernel-2-6-39-codesourcery-2011-03-41-alignment-exception/ http://free-electrons.com/docs/elfs/