Vamos a instalar Gentoo en nuestra Raspberrypi, es solo una prueba de concepto ya que la compilación de los binarios lleva demasiado tiempo en este hardware. En próximos artículos explicaremos como compilar mediante distcc y cross-dev ;)
Generamos las particiones necesarias:
Disposit. Inicio Comienzo Fin Bloques Id Sistema
/dev/mmcblk0p1 * 2048 1050623 524288 c W95 FAT32 (LBA)
/dev/mmcblk0p2 1050624 2099199 524288 82 Linux swap / Solaris
/dev/mmcblk0p3 2099200 61497343 29699072 83 Linux
NOTA: El mínimo tamaño de una partición FAT32 es de 512Mb
Creamos el sistema de ficheros boot, swap y raíz:
mkswap /dev/mmcblk0p2
swapon /dev/mmcblk0p2
mkfs.ext4 /dev/mmcblk0p3
Montamos las particiones:
mkdir -p /mnt/rpigentoo/boot
mount /dev/mmcblk0p1 /mnt/rpigentoo/boot
cd /mnt/rpigentoo
Nos bajamos el stage:
tar xvjpf stage3-armv6j_hardfp-20140605.tar.bz2
rm stage3-armv6j_hardfp-20140605.tar.bz2
Nos bajamos el portage:
tar xvjf portage-latest.tar.bz2 -C /mnt/rpigentoo/usr/
rm portage-latest.tar.bz2
Nos bajamos los ficheros de firmware de la Rasp:
git clone –depth 1 git://github.com/raspberrypi/firmware/
cd firmware/boot
cp * /mnt/rpigentoo/boot/
cp -r ../modules /mnt/rpigentoo/lib/
cd /mnt/rpigentoo/
rm -rf /mnt/rpigentoo/tmp/firmware
Chrooteamos:
Ahora debemos hacer el chroot a nuestro dir root de la Rasp pero no es posible hacer chroot desde una arquitectura distinta a la final, AMD64 –> ARM
Por lo tanto vamos a hacer un workaround mediante qemu, este ejecutará los comandos dentro del chroot emulando la arquitectura ARM.
Para que esto funcione debemos tener habilitado en el kernel:
Executable file formats / Emulations ---> [*] Kernel support for MISC binaries
Una vez realizado el chroot el SO ya no sabe nada del sistema anterior, en realidad se está ejecutando un binario del exterior, en este caso qemu dentro de un chroot con arquitectura ARM, al ejecutar los comandos q-emu buscará librerías AMD64 de q-emu en el chroot(ARM), para evitar esto compilaremos q-emu de forma estática. Compilar qemu de forma estática en gentoo puede ser complicado así que vamos a bajarnos la versión de Debian y sacar el binario de qemu compilado estáticamente mediante alien:
http://http.us.debian.org/debian/pool/main/q/qemu/
wget http://http.us.debian.org/debian/pool/main/q/qemu/qemu-user-static_1.6.0+dfsg-2_amd64.deb
emerge -av alien
Destripamos el deb:
mkdir qemu-user-static
cd qemu-user-static
mv ../qemu-user-static-1.6.0+dfsg.tgz ./
tar xvzf qemu-user-static-1.6.0+dfsg.tgz
Vamos a configurar nuestro SO para que cuando detecte que se está ejecutando algún binario compilado para la arquitectura ARM lo haga a través de qemu, nosotros vamos a ejecutar un wrapper que a su vez ejecutará /opt/qemu-arm-rpi/qemu-arm.
Los pasos que se ejecutarán son:
chroot /bin/bash -- Este bash es ARM --> /opt/qemu-arm-rpi/qemu-wrapper --> /opt/qemu-arm-rpi/qemu-arm
Copiamos el interprete de ARM:
cp ./usr/bin/qemu-arm-static /mnt/rpigentoo/opt/qemu-arm-rpi/qemu-arm
Compilamos el wrapper:
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv, char **envp) {
char *newargv[argc + 3];
newargv[0] = argv[0];
newargv[1] = "-cpu";
newargv[2] = "arm1176";
memcpy(&newargv[3], &argv[1], sizeof(*argv) * (argc - 1));
newargv[argc + 2] = NULL;
return execve("/opt/qemu-arm-rpi/qemu-arm", newargv, envp);
}
gcc -static qemu-wrapper.c -o qemu-wrapper
Configuramos el SO para que ejecute el wrapper en caso de ser ARM:
En caso de tener Kernel support for MISC binaries como módulo:
[ -f /proc/sys/fs/binfmt_misc/register ] || mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
echo ‘:arm_rpi:M::x7fELFx01x01x01x00x00x00x00x00x00x00x00x00x02x00x28x00:xffxffxffxffxffxffxffx00xffxffxffxffxffxffxffxffxfexffxffxff:/opt/qemu-arm-rpi/qemu-wrapper:’ > /proc/sys/fs/binfmt_misc/register
Preparamos el entorno chroot:
mount -t proc proc /mnt/rpigentoo/proc
mount -t sysfs sysfs /mnt/rpigentoo/sys
mount -o bind /dev /mnt/rpigentoo/dev
mount –rbind /sys /mnt/rpigentoo/sys
mount –rbind /dev /mnt/rpigentoo/dev
Entramos:
env-update
source /etc/profile
export PS1="(Im_IN) $PS1"
NOTA: Si experimentamos problemas de memoria deberemos definir la variable: QEMU_RESERVED_VA
Configuramos la gentoo de forma normal:
eselect profile list
eselect profile set 23
default/linux/arm/13.0/armv6j
USE="-X -gnome -kde -ipv6 -mono -doc -java -fortran -openmp"
Definimos los parámetros de config de arranque:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
Continuamos con la config del sistema:
/dev/mmcblk0p1 /boot vfat auto,noatime 1 2
/dev/mmcblk0p3 / ext4 noatime 0 1
/dev/mmcblk0p2 none swap sw 0 0
nano -w /etc/conf.d/net
config_eth0=( "dhcp" )
ln -s net.lo net.eth0
rc-update add net.eth0 default
nano -w /etc/hosts
nano -w /etc/rc.conf
nano -w /etc/conf.d/keymaps
rc-update add swclock boot
rc-update del hwclock boot
nano -w /etc/locale.gen
es_ES.utf8 UTF-8
es_ES@euro ISO-8859-15
nano -w /etc/env.d/02locale
LANG="es_ES.utf8"
LC_COLLATE="C"
export PS1="(Im_IN) $PS1"
grep -v rootfs /proc/mounts > /etc/mtab
echo “# Dummy comment to disable new udev naming schema, by Kr0m;)” > /etc/udev/rules.d/80-net-name-slot.rules
emerge syslog-ng
rc-update add syslog-ng default
emerge vixie-cron
rc-update add vixie-cron default
emerge dhcpcd vim
useradd -m -G users,wheel,audio -s /bin/bash USER_NAME
rc-update add sshd default
nano -w /etc/inittab
# SERIAL CONSOLES
#s0:12345:respawn:/sbin/agetty 9600 ttyS0 vt100
#s1:12345:respawn:/sbin/agetty 9600 ttyS1 vt100
rc-update add gpm default
emerge -av gentoolkit portage-utils
/usr/bin/equery list ‘*’ > /etc/portage/package.list
passwd
emerge –update –newuse –deep –ask @world
NOTA: Si se actualiza la versión de gcc
gcc-config 1
env-update && source /etc/profile
export PS1="(Im_IN) $PS1"
emerge –oneshot libtool
etc-update
export PS1="(Im_IN) $PS1"
exit
cd
umount /mnt/rpigentoo/dev
umount /mnt/rpigentoo/sys
umount /mnt/rpigentoo/proc
umount /mnt/rpigentoo/boot
umount /mnt/rpigentoo/
umount binfmt_misc
Con esto ya tendremos la SD lista para enchufar a la Rasp y funcionar, en próximos artículos explicaremos como compilar mediante distcc y cross-dev ;)