Embedded GNU/Linux partendo da zero: test sulla Raspberry Pi

Embedded GNU/Linux partendo da zero: boot sulla Raspberry Pi

Continua la serie di articoli “Embedded GNU/Linux partendo da zero” con una prova pratica di quanto abbiamo visto nelle puntate precedenti: questa volta vedremo come creare una distro minimale e funzionante sulla Raspberry Pi partendo completamente da zero.

Introduzione

La Raspberry Pi [1] (o più brevemente RPi da ora in poi) è un computer vero e proprio realizzato su una singola scheda elettronica sviluppato dalla Raspberry Pi Fundation, un’organizzazione di beneficenza che ha sede nel Regno Unito. Lo scopo di tale progetto è di promuovere lo studio dell’informatica, in particolar modo in ambito accademico. Proprio per questa ragione tale dispositivo è facilmente accessibile a costi molto contenuti (il prezzo va da $25 per la prima versione a $35 per la seconda della versione).

Per maggiori dettagli sulle specifiche della board si rimanda all’articolo seguente: http://it.emcelettronica.com/computer-meno-di-25-dollari-con-arm11-e-hdmi.

In questo nuovo articolo vedremo come ricompilare un kernel e come preparare un root filesystem minimale per la RPi, partendo dai sorgenti e da una SD card vuota.

Per una visione più generica sulla procedura di ricompilazione del kernel si consiglia la lettura degli articoli precedenti della serie “Embedded GNU/Linux partendo da zero”:

http://it.emcelettronica.com/embedded-gnulinux-partendo-da-zero-ricompilare-kernel

http://it.emcelettronica.com/embedded-gnulinux-partendo-da-zero-preparazione-del-root-filesystem

http://it.emcelettronica.com/embedded-gnulinux-partendo-da-zero-integrazione-e-test

Procedura di avvio sulla RPi

La procedura di avvio della RPi utilizza un processo di boot a più stage.

Quando la RPi viene accesa la GPU inizia ad eseguire il primo stage del
boot-loader (bootcode.bin), che è memorizzato nella ROM del SoC Broadcom
BCM2835. Il primo stage reperisce dalla prima partizione dell’SD card esterna il boot-loader di secondo livello (bootloader.bin), che si occupa di leggere tutti gli altri file necessari al boot, compresa l’immagine del kernel (kernel.img), caricando tutto nell’SDRAM. A questo punto il boot-loader ha terminato il suo compito e passa il controllo al kernel.

NOTA: ricompilare un kernel da zero su una board come la RPi può essere visto anche come un’ottima opportunità per realizzare un laboratorio di “kernel development”. La board potrà essere utilizzata in seguito anche per fare esperimenti sul kernel Linux senza aver paura di danneggiare o compromettere il dispositivo stesso. Difatti per ripristinare il kernel originale basta semplicemente sovrascrivere il file kernel.img presente nella partizione di boot della SD card, ad esempio inserendo l’SD card in un PC.

Prerequisiti

  • una RaspBerry Pi
  • una SD card (la nostra sarà una distro ultra-minimale quindi va bene di qualsiasi dimensione)
  • un PC con una distribuzione GNU/Linux
  • una connessione a Internet per scaricare i sorgenti e il cross-compilatore

Preparare l’ambiente di sviluppo

Per prima cosa è necessario reperire il cross compilatore e tutti i sorgenti richiesti a creare da zero la nostra distribuzione per la RPi. Per quanto riguarda il boot-loader si può trovare una versione precompilata nel repository git “ufficiale” della RPi (github.com/raspberrypi).

Per preparare l’ambiente di sviluppo della nostra micro-distribuzione per la RPi è sufficiente lanciare i comandi seguenti:

$ mkdir raspberry
$ cd raspberry
$ git clone git://github.com/raspberrypi/firmware.git
$ git clone git://github.com/raspberrypi/tools.git
$ git clone git://github.com/raspberrypi/linux.git
$ git clone git://busybox.net/busybox.git

Il primo repository git contiene i file binari del boot loader, che andremo a copiare direttamente sull’SD card. Gli altri repository contengono rispettivamente i cross-compilatori (e utility varie per la gestione dei binari), e infine i sorgenti del kernel Linux e BusyBox per la parte user-space, che andremo a ricompilare.

NOTA #1: teoricamente potremo partire dai sorgenti “ufficiali” di Linux
(denominati “vanilla”), disponibili su http://www.kernel.org tuttavia i kernel vanilla non hanno al loro interno i driver e i moduli per gestire il SoC Broadcom BCM2835 presente sulla RPi. Per questo motivo usare un kernel vanilla generico presupporrebbe una lunga e complessa fase di porting di tutte le patch specifiche della RPi sull’eventuale kernel scelto come base di partenza. In questo caso ci affidiamo direttamente al kernel già patchato e messo adisposizione su GitHub alla comunità di utilizzatori.

NOTA #2: è possibile utilizzare lo stesso cross-compilatore visto nelle
puntate Embedded GNU/Linux partendo da zero, in fin dei conti siamo sempre su architetture ARM. In questo caso, però, visto che nei repository di sorgenti della RPi troviamo già un cross-compilatore pronto all’uso, optiamo per quest’ultimo. L’uso di altri cross-compilatori é lasciato come esercizio per il lettore.

Inizializzare l’SD card

Dopo aver reperito tutti i sorgenti e gli strumenti per lo sviluppo possiamo formattare l’SD card utilizzando un layout compatibile al boot della RPi.

Possiamo quindi inserire l’SD card nel PC e (da Linux) partizionarla usando il comando seguente:

$ sudo sfdisk /dev/mmcblk0 << EOF
unit: sectors

/dev/mmcblk0p1 : start= 16, size= 97648, Id= c, bootable
/dev/mmcblk0p2 : start= 97664, size= 97648, Id=83
/dev/mmcblk0p3 : start= 0, size= 0, Id= 0
/dev/mmcblk0p4 : start= 0, size= 0, Id= 0
EOF

ATTENZIONE! Questo comando causa la perdita di tutti i contenuti che erano presenti sull’SD card, quindi verificate di utilizzare una SD card vuota o contenente informazioni che volete cancellare.

Con questo comando abbiamo creato una partizione primaria FAT (/dev/mmcblk0p1) che verrà usata per il boot (cioè dove copieremo i file del boot-loader e l’immagine del kernel che cross-compileremo nei passi successivi) e una partizione per il root filesystem (/dev/mmcblk0p2), dove copieremo i binari user-space (BusyBox).

NOTA: le dimensioni delle due partizioni sono entrambe di 50MB. Il resto dell’SD card va ovviamente sprecato; tuttavia in questo caso tale spazio risulta addirittura sovradimensionato per ospitare la nostra micro-distribuzione, ma in questo modo siamo sicuri di rientrarci con le dimensioni e di poter supportare SD card di qualsiasi taglio.

Una volta partizionata l’SD card con uno schema compatibile per il boot-loader andremo a creare i filesystem su entrambe le partizioni:

$ sudo mkfs.vfat /dev/mmcblk0p1
$ sudo mkfs.ext4 /dev/mmcblk0p2

La partizione primaria deve essere necessariamente VFAT. Per la secondaria
(root filesystem) possiamo scegliere un qualsiasi filesystem supportato da
Linux. In questo caso abbiamo scelto ext4.

Ricompilare il kernel

E` infine giunto il momento di cross-compilare il kernel. Percorreremo
velocemente questi passi, perché sono esattamente gli stessi visti nei
precedenti articoli di questa serie.

Le uniche differenze consistono in:

1) aggiungere al PATH della shell il cross-compilatore giusto (lanciare il
comando dalla directory “raspberry” dove abbiamo scaricato i repository git):

export PATH=$PWD/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin:$PATH

2) selezionare il branch rpi-3.2.27 (il ramo del kernel stabile che si trova nel repository git del kernel della RPi)

$ git checkout rpi-3.2.27

3) configurare il kernel per abilitare i settaggi di default per la RPi
(la configurazione di default per questa board è chiamata bcmrpi_defconfig).

Spostiamoci quindi nella directory dei sorgenti del kernel e lanciamo la
configurazione con i comandi seguenti:

$ cd linux
$ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- bcmrpi_defconfig

Per rendere la cosa un po’ più interessante possiamo cambiare la versione del kernel, appendendo alla fine della stringa originale una stringa personalizzata: es. “-eos”. Questa stringa comparirà nella nostra distribuzione personalizzata, ogni volta che verrà stampata la versione del kernel.

Per fare ciò possiamo lanciare:

$ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- menuconfig

E dall’interfaccia andare a modificare il parametro:

General setup —> Local version – append to kernel release

Aggiungendo la stringa “-eos” (o quella che più ci piace).

A questo punto è giunto il momento di lanciare il passo di compilazione
effettiva del kernel:

$ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi-

Per generare un file immagine del kernel compatibile con il boot-loader della RPi dobbiamo anche “pacchettizzarlo” in modo opportuno. Questo passaggio non è sempre richiesto; in questo caso può essere effettuato lanciando lo script imagetool-uncompressed.py (che si trova nel repository “tools” insieme al cross-compilatore):

$ cd ../tools/mkimage
$ ./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
$ cd -

Infine installiamo i moduli esterni nella directory temporanea /tmp/rootfs
(copieremo tutto nell’SD card successivamente, insieme ai binari dello
user-space):

$ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- \
INSTALL_MOD_PATH=/tmp/rootfs/ modules_install

Installazione di BusyBox

Anche per installare BusyBox i passi sono gli stessi visti nell’articolo
http://it.emcelettronica.com/embedded-gnulinux-partendo-da-zero-integrazione-e-test (si può anche utilizzare lo stesso file di configurazione, disponibile come allegato dell’articolo stesso).

Spostiamoci nella directory di BusyBox e lanciamo il passo di configurazione (prendendo il file di configurazione dall’articolo precedente):

$ cd ../busybox
$ wget http://it.emcelettronica.com/files/busybox-config_0.txt
$ cp busybox-config.txt busybox/.config

Infine lanciamo la cross-compilazione di BusyBox:

$ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- \
CONFIG_PREFIX=/tmp/rootfs install

Se tutto è andato per il verso giusto troveremo i binari del nostro user-space minimale in /tmp/rootfs, insieme ai moduli esterni del kernel installati al passo precedente.

L’ultimo passaggio consiste nel creare nel rootfs i file speciali sotto /dev:

$ mkdir /tmp/rootfs/dev
$ cd /tmp/rootfs/dev
$ cat << EOF | sudo sh
mknod tty1 c 4 1
mknod tty2 c 4 2
mknod tty3 c 4 3
mknod tty4 c 4 4
mknod tty5 c 4 5
mknod tty6 c 4 6
mknod console c 5 1
mknod null c 1 3
mknod zero c 1 5
EOF
$ cd –

Trasferire i binari sull’SD card

Il passaggio finale consiste nel copiare tutto sull’SD card e vedere se il
sistema parte veramente. ;-)

Montiamo quindi le due partizioni dell’SD card (boot e rootfs):

$ mkdir -p /tmp/sdcard/boot
$ mkdir -p /tmp/sdcard/rootfs
$ sudo mount /dev/mmcblk0p1 /tmp/sdcard/boot
$ sudo mount /dev/mmcblk0p2 /tmp/sdcard/rootfs

Copiamo i file del boot loader e la nostra immagine del kernel nella partizione di boot:

$ cd ..
$ sudo cp firmware/boot/* /tmp/sdcard/boot/
$ sudo cp tools/mkimage/kernel.img /tmp/sdcard/boot

E infine trasferiamo anche il root filesystem nell’altra partizione ext4
dell’SD card:

$ sudo rsync -avHS /tmp/rootfs/ /tmp/sdcard/rootfs/

NOTA: per quest’ultima copia utilizziamo il comando rsync che permette di preservare sia i link simbolici creati durante l’installazione di BusyBox, sia i file speciali creati nella /dev del nostro root filesystem.

Perfetto! Possiamo smontare i filesystem dell’SD card e ammirare la nostra
micro-distribuzione all’opera:

$ sudo umount /tmp/sdcard/boot
$ sudo umount /tmp/sdcard/rootfs

Test finale

Per testare la distribuzione è sufficiente inserire l’SD card nello slot
presente sulla RPi e riavviare la scheda, collegandola ad un monitor o a un televisore HDMI e vedere cosa compare a video.

Embedded GNU/Linux partendo da zero: boot sulla Raspberry Pi

Se colleghiamo una tastiera possiamo interagire con l’ambiente della shell e lanciare comandi come su una qualsiasi distribuzione GNU/Linux.

Ad esempio possiamo stampare a video la versione del kernel che sta girando sulla board con il comando “uname -r”.

Embedded GNU/Linux partendo da zero: boot sulla Raspberry Pi

Come possiamo vedere il kernel risulta essere proprio la nostra versione: 3.2.27-eos+.

Riferimenti

[1] http://www.raspberrypi.org/
[2] http://it.emcelettronica.com/computer-meno-di-25-dollari-con-arm11-e-hdmi
[3] http://it.emcelettronica.com/raspberry-pi-tutorial-installazione-distro-configurazione-e-stampa

 

Quello che hai appena letto è un Articolo Premium reso disponibile affinché potessi valutare la qualità dei nostri contenuti!

Gli Articoli Tecnici Premium sono infatti riservati agli abbonati e vengono raccolti mensilmente nella nostra rivista digitale EOS-Book in PDF, ePub e mobi.

volantino eos-book1

Vorresti accedere a tutti gli altri Articoli Premium e fare il download degli EOS-Book?
Allora valuta la possibilità di sottoscrivere un abbonamento a partire da € 2,95!

Scopri di più

14 Comments

  1. Piero Boccadoro Piero Boccadoro 22 gennaio 2013
  2. Emanuele Emanuele 22 gennaio 2013
  3. Emanuele Emanuele 22 gennaio 2013
  4. Andrea Righi 22 gennaio 2013
  5. ufo.naviar 22 gennaio 2013
  6. Piero Boccadoro Piero Boccadoro 25 gennaio 2013
  7. fgiava 26 gennaio 2013
  8. Andrea Righi 28 gennaio 2013
  9. willygroup willygroup 2 febbraio 2013
  10. wil 8 febbraio 2013
  11. Andrea Righi 8 febbraio 2013
  12. wil 8 febbraio 2013
  13. willygroup willygroup 9 febbraio 2013
  14. willygroup willygroup 12 febbraio 2013

Leave a Reply