Novena/Embedian Build

From Studio Kousagi Wiki
Revision as of 11:40, 23 January 2013 by Bnewbold (talk | contribs) (whew!)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

NOTE: these instructions are probably not complete?

Use the embedian cross-compilation toolchain to generate binaries that will run on armhf hardware using an x86/amd64 build host.

These directions require a physical micro SD card; partitioning happens "in place" instead of using loop-mounted .img files.

These directions assume you basically know what you are doing; eg, be careful dd'ing directly to the micro SD card and that you don't accidentally dd to an important disk, resulting in a loss of all data.

Prepare Cross-Compile Toolchain on Build Host

There aren't toolchain packages in wheezy yet, so if your build host is wheezy add squeeze to your /etc/apt/sources.list (don't replace any wheezy lines, just copy the wheezy deb line and replace "wheezy" with "squeeze"), then apt-get update. This shouldn't clobber your system too bad as the wheezy packages will almost always be prefered to squeeze packages.

Install (at least) these debian packages:

build-essential multistrap qemu-user-static gparted device-tree-compiler 
u-boot-tools

Note that 'gparted' is a GUI and will pull in X dependancies; if you build on a remote server you could do the partitioning steps on a different machine.

Check out these repositories from github (don't have links b/c github is blocked in china):

The linux-stable git checkout could take ages (and is huge), so you might want to just grab a tarball of 3.7.4.

Build u-boot

Checkout the custom u-boot-imx6: https://github.com/sutajiokousagi/u-boot-imx6

As of Jan 2013, use ddrsetup branch (else *-staging?).

Enter top directory and build:

   export CROSS_COMPILE=arm-linux-gnueabi-
   make novena_config
   make

Grab the resulting 'u-boot.imx' for later.

Build Kernel

Install whatever general build tools. Might in particular need 'lzop' for building uImages.

Grab linux-stable upstream: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

As of Jan 2013, testing with 3.8-rc (not linux-stable).

Copy in meta-kosagi/recipes-kernel/linux/linux-novena/defconfig as .config

Create this script as cross_build.sh; note the UIMAGE_LOADADDR=10008000 on penultimate line (i.mx6-specific?), and change "custom1" to whatever you want:

   #!/usr/bin/env bash
   export ARCH=arm
   export DEB_HOST_ARCH=armhf
   export CONCURRENCY_LEVEL=`grep -m1 cpu\ cores /proc/cpuinfo | cut -d : -f 2`
   fakeroot make-kpkg --arch arm --cross-compile arm-linux-gnueabi- --initrd --append-to-version=-custom1 kernel_image kernel_headers
   make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- EXTRAVERSION=-custom1 UIMAGE_LOADADDR=10008000 uImage
   cp arch/arm/boot/uImage uImage

If you are using a newer -stable kernel than the one use to generate the .config, the first compile will prompt you to select a whole boatload of NEW configuration options (new optional features in the kernel sources). If you run in to this, keep hitting enter to accept all the defaults.

Run the cross_build.sh script to build.

Grab the resulting uImage file and rename it uImage-novena.bin.

Build a Basic Debian armhf wheezy rootfs with multistrap and qemu

These are crude, manual, slow directions, included for completeness. Pretty much nobody should do things this way, any targeted application of the novena board would have images generated by a script or better build process. Perhaps even the Debian installer will be sufficient.

You might also be able to use a generic debian wheezy armhf rootfs tarball if you have one sitting around.

We'll use multistrap, configure the packages with qemu, then edit the configuration by hand. This follows http://wiki.debian.org/Multistrap#Steps_for_Squeeze_and_later.

Install the qemu-user-static and multistrap packages.

In a new directory, create a multistrap configuration file like the below, called novena.conf. Add any extra packages you want to the long list:

   [General]
   arch=armhf
   cleanup=true
   noauth=false
   aptsources=Debian
   bootstrap=Debian
   
   [Debian]
   packages=file i2c-tools screen build-essential base-files openssh-server wget iproute net-tools hostname udev isc-dhcp-client parted dosfstools apt iputils-ping dialog iptables less traceroute apt-utils dnsutils lsof vim-tiny sudo locales ethtool pciutils git-core kmod ifupdown
   keyring=debian-archive-keyring
   suite=wheezy
   source=http://http.debian.net/debian/

To build the first (unconfigured) stage of the rootfs, run:

   sudo multistrap -f novena.conf -d armhf

Rename the resulting 'armhf' directory to 'rootfs', and tar it up as a backup copy. Then make the following basic changes *AS ROOT* in the rootfs directory (you don't need to chroot) before configuring the packages. These are just the minimal requirements; package configuration and udev will help, but this won't be a polished OS:

   # sudo-s omitted
   echo "novena" > etc/hostname
   touch etc/fstab
   touch etc/resolv.conf
   mkdir dev/pts
   mknod dev/console c 5 1
   mknod dev/random c 1 8
   mknod dev/urandom c 1 9
   mknod dev/null c 1 3
   mknod dev/ptmx c 5 2

Copy the build host's /usr/bin/qemu-arm-static to rootfs/usr/bin/qemu-static-arm.

Create a config.sh script in top level of the rootfs:

   # config.sh script
   export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
   export LC_ALL=C LANGUAGE=C LANG=C
   /var/lib/dpkg/info/dash.preinst install
   dpkg --configure -a
   mount proc -t proc /proc
   dpkg --configure -a
   umount /proc

Run it:

   sudo chroot rootfs /config.sh

Remove unnecessary files:

   sudo rm /usr/bin/qemu-static-arm
   sudo rm /config.sh

Add a minimal rootfs/etc/hosts:

   127.0.0.1       localhost.localdomain localhost novena
   # The following lines are desirable for IPv6 capable hosts
   ::1     ip6-localhost ip6-loopback
   fe00::0 ip6-localnet
   ff00::0 ip6-mcastprefix
   ff02::1 ip6-allnodes
   ff02::2 ip6-allrouters

Add a crude rootfs/etc/network/interfaces:

   auto lo
   iface lo inet loopback
   auto eth0
   iface eth0 inet dhcp
           hwaddress ether 00:11:22:33:44:55

Edit rootfs/etc/inittab and allow logins on serial console (modify the similar tty1 line):

   1:2345:respawn:/sbin/getty 115200 ttymxc1

Edit rootfs/etc/shadow and remove the '*' character after root (to set a null password). NOTE: only root will be able to login, with blank password (!!!).

Ensure that all files in the rootfs are owned by root:root, not a user:

   sudo chown -R root:root rootfs/*

Then double check the "tweaks" below.

rootfs Tweaks (even for recycled images)

Set some serial login on ttymxc1 (edit etc/inittab):

   1:2345:respawn:/sbin/getty 115200 ttymxc1

Set MAC address in etc/network/interfaces to:

   hwaddress 00:11:22:33:44:55

Partition a blank SD card

Use the gparted GUI.

Delete all existing partitions on the micro SD card.

Create a ~32MB FAT32 partition labeled 'boot' with at least 512KB of padding in front of it (by default there is 1MB of padding), call it 'boot'.

Create a ~500MB ext3 partition.

Commit changes.

Build device tree file

You need the 'device-tree-compiler' package for the next bit.

Grab novena.dts and imx6q.dtsi from the meta-kosagi repo:

   meta-kosagi/recipes-kernel/linux/linux-novena/novena.dts
   meta-kosagi/recipes-kernel/linux/linux-novena/imx6q.dtsi

Grab skelton.dtsi from the linux-stable sources (checked out previously):

   linux-stable/arch/arm/boot/dts/skeleton.dtsi

Compile the device tree file:

   dtc -I dts -O dtb -R 8 -p 0x3000 -o uImage-novena.dtb novena.dts

Grab the resulting uImage-novena.dtb file for later.

Compile the u-boot boot script

You need 'u-boot-tools' for the next bit.

Grab boot.script from the meta-kosagi repo:

   meta-kosagi/recipes-bsp/u-boot/u-boot-imx/boot.script

Compile the boot script (careful, confusing file names!):

   mkimage -A arm -O linux -a 0 -e 0 -T script -C none -n "Boot script" -d boot.script boot.scr

Grab the resulting boot.src file for later.

Assemble Everything

Copy the u-boot.imx file built above to the padded space at the begining of the card:

   $ dd if=u-boot.imx of=/dev/sdb bs=512 conv=notrunc seek=2

Mount the FAT boot partition to /mnt.

Copy boot.src and uImage-novena.dtb over to /mnt, keeping their names. Copy the uImage kernel file to /mnt/uImage-novena.bin.

unmount the FAT boot patition and mount the ext partition to /mnt.

Delete any old rootfs files (if you didn't just re-partition the disk), and copy over the whole rootfs:

   $ sudo rsync -arv ./rootfs/ /mnt/

unmount the disk, it's ready to go!

Result!

 root@novena:~# uname -a
 Linux novena 3.8.0-custom1 #2 SMP Tue Jan 22 04:20:12 UTC 2013 armv7l GNU/Linux
 root@novena:~# cat /etc/os-release     
 PRETTY_NAME="Debian GNU/Linux 7.0 (wheezy)"
 NAME="Debian GNU/Linux"
 VERSION_ID="7.0"
 VERSION="7.0 (wheezy)"
 ID=debian
 ANSI_COLOR="1;31"
 HOME_URL="http://www.debian.org/"
 SUPPORT_URL="http://www.debian.org/support/"
 BUG_REPORT_URL="http://bugs.debian.org/"

reboot time: about 13 seconds shutdown time: 3-4 seconds

Hacks

To try and steal a u-boot header from existing disk:

   dd if=/dev/sdb of=snag.bin bs=512 skip=2 count=500

and write:

   dd if=snag.bin of=/dev/sdb bs=512 seek=2 count=500

If a MAC address isn't assigned for eth0 at boot (eg, if ifupdown package isn't installed), you will get:

   root@novena:~# ifconfig eth0 up
   SIOCSIFFLAGS: Cannot assign requested address

Workaround:

   ifconfig eth0 hw ether 00:11:22:33:44:55
   ifconfig eth0 up

TODO

  • add i2c thing to rc.local: "i2cset -y 1 0x08 0x66 0x48 || true"