Esistono però dei bootloader generici, che possono essere adattati a varie configurazioni hardware e CPU
Il bootloader spesso è scritto dal produttore del chip o della scheda ed a volte è software proprietario
Normalmente questi boot-loader fanno parte di progetti più grandi orientati allo sviluppo embedded
Uboot o RedBoot
http://www.denx.de/wiki/U-Boot fa parte del Embedded Linux Development Kit della DENX, che è un sistema di sviluppo open per sistemi embedded
Particolarità dell'embedded
Per questo motivo difficilmente si può utilizzare una distribuzione normale "off the shelf" come la Debian che è disponibile per la maggior parte delle architetture
Normalmente una scheda embedded ha poca RAM e poco "disco" (in realtà normalmente della ROM)
Anche ammettendo di utilizzare una distribuzione "normale", occorrerà ottimizzarla per ridurne l'imnpegno di disco e di memoria
Ma probabilmente anche questo non basta. Occorre usare dei trucchi, come delle applicazioni semplificate, per ridurre l'uso di RAM e disco.
Particolarità dell'embedded
Inoltre normalmente il sistema operativo viene eseguito su di un supporto in sola lettura (in genere una ROM), quindi occorrerà un'installazione simile a quella delle distribuzioni live
μClibc
Potremmo quindi risparmiare molto spazio se invece di usare la libreria completa usassimo una libreria ridotta, che contenesse solo le funzioni realmente necessarie per il nostro sistema
Una grossa parte delle funzioni contenute nella libreria glibc standard vengono usate molto di rado e praticamente mai nei sistemi embedded
Una libreria C che appunto non contiene tutte le funzioni della libreria standard è μClib (http://www.uclibc.org/)
μClibc
Questa è una versione ridotta ed adattata della libreria glibc standard, adtta per sistemi embedded con poca RAM e poco disco
Naturalmente per poter utilizzare µClibc occorre compilare i programmi per µClibc utilizzando versioni adatte di compilatore e linker
Cross-compilazione
Abbiamo visto che per utilizzare µClibc occorre utilizzare compilatori e linker diversi dai normali
Le soluzioni sono due: o installiamo un compilatore sulla nostra scheda oppure installiamo sul nostro sistema un compilatore che produca codice per la nostra scheda che chiameremo sistema target
Il compilatore ed il linker del nostro sistema producono eseguibili contenenti istruzioni per un processore IA32 o AMD64, vale a dire quello del nostro PC
Cross-compilazione
C'è un motivo ben più importante che ci costringe ad utilizzare compilatori e linker diversi da quelli del nostro sistema per compiare i programmi che andranno sul nostro sistema
Se installiamo un compilatore per un diverso microprocessore rispetto a quello del nostro sistema, si dice che stiamo eseguendo una cross-compilazione o del cross-sviluppo
La nostra scheda embedded però non monta un processore IA32 o AMD64. Nel nostro caso il processore è della famiglia MIPSel
Differenze Hardware
Essendo basati sullo stesso chip di base (o su chip simili - esistono varie versioni simili del processore video, con caratteristiche leggermente diverse) anche le caratteristiche hardware sono in gran parte simili
Entrambi gli apparati presentano un'interfaccia Ethernet e connettori USB sia periferica che host
La differenza fondamentale è che l'hard disk è opzionale nell'unità 4Geek mentre è fissa (da 500G nel mio caso) nell'unità Iomega
Differenze Hardware
Questo comporta il fatto che il sistema operativo sia completamente in FLASH nell'uinità 4Geek mentre sia sul disco fisso nell'unità Iomega, lasciando solo il boot loader in flash.
Gli apparati differiscono nelle interfacce video: l'unità 4Geek è più ricca; l'unità Iomega manca dell'interfaccia SCART e dell'uscita audio ottica
Dispositivo MTD
Linux può utilizzare una FLASH come dispositivo a blocchi (come fisse un hard disk)
Tornando ai nostri sistemi, Iomega ha il sistema completamente basato su disco fisso, utilizzando un filesystem ext3
Per quanto riguarda invece il sistema 4Geek, può anche funzionare senza hard disk, quindi tutto il sistema è contenuto nella FLASH da 32M
Questa driver implementa la lettura e scrittura nei dispositivi Flash.
Dispositivo MTD
Per usare una flash come disco occorre la driver MTD (Memory Type Device).
Un dispositivo può essere suddiviso in partizioni (indivisuate come /dev/mtd0 /dev/mtd1 ...) in vari modi:
Tramite una tabella di partizioni RedBoot
Tramite parametri passati alla riga di comando del kernel
Bootloader
Nei normali computer, per caricare il sistema operativo si utilizza un boot manager come ad esempio Grub o Lilo.
Il boot manager è un piccolo programma che, oltre a presentare un menù d'avvio, si occupa di leggere il file con il sistema operativo (vmlinuz) in memoria, caricare eventualmente un'immagine d'avvio initrd ed invocare il kernel passandogli una serie di parametri.
Nei sistemi embedded c'è qualcosa di simile, ma non è sul disco come Lilo o Grub. E' registrato in una rom o nella stessa flash dove ci sono le partizioni MTD.
Bootloader
Questo bootloader in genere è molto più potente di Grub o Lipo perché normalmente consente anche di programmare la flash con una nuova immagine di file system, di configurare l'interfaccia di rete e di fare altre operazioni.
Per fare queste operazioni si deve collegare un'interfaccia seriale alla scheda, per poter impartire comandi al bootloader ed eventualmente per scaricare nella scheda il file system da registrare in flash.
Nel nostro caso (come in molti altri) la seriale è implementata direttamente nel micro, ma occorre aggiungere esternamente un transceiver che adatti le tensioni a quelle di una normale RS232
Compilazione residente
Avendo un sistema con una buona disponibilità di disco fisso, sebbene in genere lento, possiamo anche pensare di compilare i programmi direttamente sul dispositivo
In questo caso sarebbe utile avere un sistema operativo "full featured".
Visto che in genere non è possibile avere un sistema dual boot, possiamo pensare di avere il nostro sistema in una sottodirectory ed eseguirlo con il comando chroot
Compilazione residente
In questo modo potremo caricare tutti i pacchetti che ci servono, anche se potranno girare solo nell'ambiente chroot Debian.
Se usiamo un sistema Debian, che è disponibile per le principali architetture usate nei sistemi embedded, possiamo usare il pacchetto debootstrap per creare la directory con il sistema
Ancora avremo bisogno di procurarci una toolchain, visto che dovremo compilare eseguibili per librerie diverse da quelle di Debian (µClibc invece che glibc)
Toolchain
Occorre poi avere i file di intestazione (header file) e le librerie di sviluppo per la libreria µClibc e le sue librerie correlate
Se ci riferiamo ad un sistema GNU (Linux) ci serviranno le GNU binutils, la GNU Compiler Collection GCC, e uClibc
In realtà per produrre un eseguibile, che faccia riferimento a delle librerie dinamiche non basta il compilatore
L'insieme degli eseguibili e delle librerie, compilati per produrre codice per l'architettura target, prende il nome di toolchain
Toolchain
Occorre almeno un linker, che colleghi tra loro i vari file compilati in un singolo eseguibile
Le librerie di sviluppo sono librerie statiche che non contengono di fatto il codice delle funzioni che contengono, ma solo un riferimento alle librerie dinamiche che lo contengono.
Quale Embedded
Oppure possiamo rivolgerci ai box multimediali, che spesso montano già un Linux di serie
Oppure possiamo procurarci un access point wireles, come il WRT54GL della Linksys e caricarvi Linux usando OpenWRT
Normalmente quando si parla di embedded si pensa ad una bella scheda a microprocessore, collegata con una serie di interfacce a chissà che cosa
Insomma, si pensa a realizzare qualcosa di più elettronico che informatico, di costruire un controllo
Quale Embedded
In realtà noi possiamo comprare un sacco di embeddedgià pronto da programmare
Per esempio possiamo comprare un telefonino e scrivere applicazioni Java da scaricarvi
Caratteristiche Hardware
Nel mio caso, ho rivolto la mia attenzione a due box multimediali: il Medley+ della 4geek ed lo ScreenPlay Pro HD di Iomega
Entrambi sono box multimediali in grado di registrare un segnale TV analogico dall'esterno e di riprodurre un'ampia serie di formati video, prelevati da varie sorgenti, su di un TV tramite varie uscite tra cui l'HDMI
Per questo processore Realtek stessa distribuisce un sistema operativo Linux preconfigurato, purtroppo non Open Source
Caratteristiche Hardware
Entrambi gli apparati sono basati sul processore video Realtek RTD1281 che contiene un encoder/decoder MPEG hardware ed un core MIPS
Libreria C standard - glibc
Una grossa parte della memoria e del disco sono utilizzati dalla libreria standard del C glibc
Quando noi compiliamo un programma, le funzioni standard che noi richiamiamo, come ad esempio la printf, non vengono aggiunte in coda all'eseguibile, ma viene messo nell'eseguibile un riferimento alla libreria standard dinamica del C
In questo modo, quando lancio più programmi, non devo ricaricare ogni volta il codice delle funzioni standard ma invece carico una volta sola la libreria dinamica con un grande risparmio di memoria.
Libreria C standard - glibc
Il problema è che la libreria standard contiene centinaia di funzioni che svolgono i compiti più diversi.
Shell e comandi fondamentali
A ben guardare, i vari piccoli programmi condividono una serie di funzioni di servizio con la shell, come ad esempio quelle che analizzano i parametri a riga di comando o leggono e interpretano la riga immessa dall'utente
Normalmente nei sistemi Linux tradizionali la shell è un programma abbastanza impegnativo e complesso, in genere è bash
Inoltre c'è sempre un comando fondamentale chiamato shell, che serve per dare comandi da riga di comando o eseguire gli script di configurazione all'avvio.
Shell e comandi fondamentali
Per prima cosa, Linux ha una lunga serie di piccoli comandi che eseguono operazioni fondamentali come creare e cancellare directory o montare volumi.
Lavorare con JFFS2
Per creare un'immagine di file system JFFS2 da scaricare in una partizione del target esiste il comando mkfs.jffs2 appartenente al pacchetto Debian mtd-utils
Questo comando prende un'albero di directory e crea un'immagine di file system jffs2 che contiene l'albero stesso.
Purtroppo non esiste un comando che estragga dal file immagine l'albero di directory contenuto
Di più, il file system jffs2 pretende un dispositivo di tipo mtd per funzionare, quindi non funziona nemmeno col il dispositivo loop per montare direttamente il file immagine, come si fa con i CD-ROM
File System Squashfs
Per poter fare stare un sistema operativo in una memoria così piccola, occorre usare un file system compresso.
Abbiamo visto che il sistema 4Geek deve fare stare l'intero sistema nella è FLASH da 32M
Squashfs è un file system compresso in sola lettura, ottimizzato per essere scritto in una ROM
La maggior parte del file system non va normalmente scritta in un sistema che si comporta di fatto come una distribuzione live
Lavorare con Squashfs
Il sistema target dovrà montare il file system Squashfs per poterlo usare, quindi dovrà possedere un modulo adeguato nel suo kernel
Se vogliamo modificare il file system del nostro sistema target non ci servirà montare il file system nel sistema host (tanto è in sola lettura e non potremmo modificarlo)
La soluzione migliore è quella di scompattarlo in una directory (un albero di directory), modificare i file nella directory e poi ricompattarlo.
I programmi per fare questo sono contenuti nel pacchetto Debian squashfs-tools
Lavorare con Squashfs
Con il programma unsquashfs potremo scompattare la nostra immagine.
Con il programma mksquashfs potremo prendere il contenuto della nostra directory e ricostruire l'immagine del file system
Montare e copiare un file system JFFS2
Per operare con un file system JFFS2 occorre prima di tutto creare un dispositivo di tipo MTD in memoria
Occorre poi copiare l'immagine del file system JFFS2 nel dispositivo
A questo punto potremo montare il dispositivo ed accedere ai file
Un'idea per risparmiare spazio su disco e memoria è quello di creare una shell semplificata che contenga anche il codice di una serie di piccoli comandi (magari semplificati anch'essi)
Dato che molti script di shell fanno riferimento direttamente al nome del file dei vari comandi come rm mkdir ecc, tutti i nomi di questi comandi sono collegati (in genere con hard link) a busybox
Busybox
Dato che in Linux un programma può conoscere con che nome è stato invocato, busybox sa se, ad esempio, è stato invocato con il nome "mount" ed in questo caso esegue solo le operazioni di mount e termina.
Loader
Nel nostro caso invece, almeno in un primo momento, possiamo fare uso dell'hard disk del sistema e della sua connessione di rete
Utilizzando i programmi sul dispositivo (ad esempio wget), la condivisione del disco (l'Iomega funziona come NAS con un server SAMBA) oppure collegandolo come disco USB al PC possiamo copiare il programma compilato sull'hard disk del dispositivo
Una volta spostato il programma sul dispositivo, possiamo eseguirlo come più ci piace e copiarlo dove vogliamo.
Loader
Nei sistemi embedded "classici" si utilizzano dei "rom emulator" oppure si programma la flash di sistema tramite una connessione seriale ed un software adeguato, generalmente il bootloader
Nei sistemi embedded, una volta compilato il programma che ci interessa si pone il problema di trasferirlo sul nostro sistema target
Filesystem JFFS2
In genere il nostro sistema avrà bisogno di memorizzare nella flash dei dati (la configurazione).
Il file system Squashfs è in sola lettura, quindi non ci consente di registrare dati
Potremmo formattare una "partizione" della flash con un file system tradizionale, ma avrebbe prestazioni scarse e soprattutto scarsa durata (la flash ha un numero limitato di scritture disponibili)
La soluzione è quella di usare JFFS2 (Journal Flash File System 2).
Filesystem JFFS2
JFFS2 è un file system journaled (come ext3) ottimizzato per usare una FLASH come supporto.
Le sue principali caratteristiche sono di comprimere i dati e di usare a rotazione i blocchi della flash, in modo da spargere le scritture sull'intero dispositivo, minimizzandone il numero
[any material that should appear in print but not on the slide]