martedì 10 dicembre 2013

Delirii e BSD - Secondo Episodio

Riepilogo delle puntate precedenti: il nostro eroe si trova davanti un compito apparentemente impossibile: rimettere in vita una workstation SUN Ultra 1 ed adibirla a gateway internet con DHCP e DNS aggiornato dinamicamente dal DHCP stesso. Ovviamente tutto questo dopo essere stato svegliato in piena notte dal suo capo che non riesce a lavorare. Esclusa l'ipotesi Linux il nostro eroe decide di optare per OpenBSD: un Sistema Operativo scritto da estremisti per estremisti...

Secondo Episodio: Il Processo di Boot.

Se avete letto la puntata precedente saprete già alcune cose su OpenBSD, quello che probabilmente non sapete è che errori nella documentazione sono trattati allo stesso modo degli errori nel codice: sono bug da eliminare il più in fretta possibile.

La comunità che sta dietro ad OpenBSD è principalmente una comunità di sviluppatori che scrivono software a loro uso e consumo. "Quindi sarà tutto aggiornato all'ultimissima versione, giusto?". Sbagliato. Per fare un esempio: nell'installazione base è compreso il web server Apache 1.3 a cui gli sviluppatori di OpenBSD hanno applicato una serie di patch di sicurezza, solo l'anno scorso ad Apache è stato affiancato nginx.

Gli sviluppatori di OpenBSD hanno la fissa delle cose fatte bene. Se serve del tempo per farle non è un problema, se servono dei test si fanno, se serve della documentazione la si cerca finché non la si trova o non si è costretti a scriverla. Questa è anche una delle ragioni per cui il supporto hardware è così limitato: gli sviluppatori di OpenBSD si rifiutano di inserire nel kernel porzioni di firmware binari al solo scopo di far funzionare una periferica. I produttori di hardware non sono molto contenti di esporre al Mondo i loro segreti e per questo Linus Torvalds ha fatto buon viso a cattivo gioco e ha accettato l'inclusione di BLOB (Binary Large OBjects) nei sorgenti del kernel in deroga alla GPL.

Tutto l'hardware supportato da OpenBSD è supportato grazie a contributi del produttore nel fornire la documentazione oppure mediante opera di reverse-engineering sull'hardware stesso.

Il che ci riporta alla nostra Ultra 1: una (allora costosa) workstation degli anni '90 che adesso è buona al massimo per fare piccoli compiti come quelli richiesti ad un gateway internet per una piccola rete. Se mai vi capiterà di mettere le mani sopra ad una di queste macchine completa di manuali capirete cosa intendo quando dico che con l'acquisizione di SUN da parte di Oracle il mondo dell'Information Technology ha perso moltissimo.

Il nostro non ha a disposizione un monitor e ciò è MALE perché le Ultra 1 hanno un connettore proprietario per l'uscita video e solamente alcuni vecchi monitor SUN a tubo catodico sono compatibili. Ma, per amor di semplicità, supporremo che OpenFirmware (il corrispondente del BIOS per le macchine SUN: non fatevi ingannare dal nome perché si tratta di software proprietario) sia già stato configurato per effettuare il boot da rete e per replicare i messaggi di boot sulla console seriale. Quello che occorre fare è impostare una seconda macchina affinché fornisca alla Ultra 1 un IP, un kernel e l'immagine del ramdisk di avvio.

Se avete letto la puntata precedente sapete già cos'è un kernel (e avete capito perché "Debian GNU/Linux" si chiama così e non sia solamente "Debian Linux") quindi provvederò a spiegare che cos'è questo benedetto file initrd (abbreviazione di "initial ramdisk").

Cominciamo dalla fine: ramdisk. Un ramdisk è un'idea bizzarra ma funzionale: invece di salvare i dati in una memoria di massa perché non creare un disco nella RAM con un suo filesystem e buttarci dentro tutto quello che non vogliamo sopravviva al prossimo riavvio ma che necessariamente dobbiamo trattare come se fosse un file?

Perplessi? Vediamo se questo esempio vi schiarisce le idee. Supponete di voler scaricare un file di setup di un'applicazione e di non voler salvare questo file una volta installata l'applicazione per risparmiare spazio o perché avete una connessione veloce e impieghereste meno tempo a scaricare di nuovo il file di setup che a cercarlo sul vostro disco rigido. Se avete impostato un ramdisk potete scaricare il file direttamente nel ramdisk, avviare l'installazione e sarete sicuri che al riavvio della macchina quel file non resterà dimenticato da qualche parte nel vostro disco rigido.

I ramdisk (come molte altre cose) non sono un'idea nuova, ma circolano da decenni nell'informatica: gli utenti di AmigaOS (quelli che ancora rimangono) sicuramente si ricorderanno dell'icona a forma di chip sul Workbench in cui si potevano salvare file temporaneamente prima di decidere se spostarli in un disco o cancellarli.

"Ma cosa c'entra un ramdisk con il boot?". Ci stavo arrivando. All'avvio di un computer la prima cosa che fa la CPU è caricare un indirizzo di memoria nel program counter (un registro della CPU che indica qual è la posizione di memoria in cui si trova la prossima istruzione da eseguire) e cominciare ad eseguire qualsiasi cosa ci sia a quell'indirizzo di memoria. Nella quasi totalità dei casi quell'indirizzo di memoria fa riferimento ad un chip EEPROM sulla scheda madre che ospita il firmware (BIOS nei vecchi PC, EFI nei nuovi PC, OpenFirmware nel caso della nostra Ultra 1).

Vi chiedo umilmente di perdonare eventuali errori ed inesattezze che andrò a scrivere nei paragrafi che seguono: il processo di avvio di un computer è una questione squisitamente tecnica che richiede un'ottima conoscenza di hardware e software e che cambia enormemente tra le numerose architetture che si sono susseguite nel corso della storia. Cercherò di discuterne in termini generali, ma sappiate fin d'ora che le cose sono MOLTO più complicate di come le descriverò.

In linea di massima il firmware fornisce una prima interfaccia tra hardware e software consentendo a chi verrà dopo di avere una certa base su cui poggiarsi: ad esempio mappa gli interrupt hardware della CPU con le relative periferiche, rileva la presenza e il numero delle unità di memoria di massa e di altre periferiche ed infine carica il bootloader in memoria ad un indirizzo ben preciso e imposta il program counter su quell'indirizzo.

Più un firmware è sofisticato e più opzioni avrà a disposizione per reperire e caricare in memoria il bootloader, una di queste opzioni è il precedentemente citato boot da rete, che vedremo tra un attimo.

Una volta caricato in memoria il bootloader questo viene eseguito. Il compito del bootloader nei Sistemi Operativi derivati da UNIX è scoprire dove si trovi il kernel e l'immagine di avvio, ovvero il famigerato initrd. L'immagine di avvio contiene un filesystem temporaneo con i dati necessari al kernel per avviare la macchina e caricare il resto del sistema operativo. All'avvio il bootloader carica in memoria il kernel e lo initrd e quindi avvia il kernel indicandogli gli eventuali parametri di avvio opzionali che l'utente ha voluto impostare.

Ovviamente le cose sono MOLTO più complicate di così: se non mi credete provate a leggere un po' la documentazione di GRUB all'indirizzo http://www.gnu.org/software/grub/manual/html_node/index.html

Ora ragioniamo un attimo: abbiamo un kernel e un initrd da caricare in memoria e da eseguire, per questioni pratiche li abbiamo salvati come file sul disco rigido della macchina, ma nulla ci vieta di complicare le cose aggiungendo al firmware le capacità necessarie a interrogare un server RARP per ottenere un indirizzo IP e scaricare da un TFTP le immagini del kernel e di initrd.

Questo è quello che credo si siano detti gli ingegneri della SUN quando hanno messo mano ad OpenFirmware quando hanno deciso di abilitare il boot da rete. Ovviamente non ho le prove di quanto sostengo, ma conosco abbastanza gli ingegneri da supporre che sia una ricostruzione verosimile.

In teoria (ed anche in pratica) è possibile avere un intero laboratorio pieno di computer privi di disco rigido e poter comunque avviare un Sistema Operativo su ciascuno di essi. Non solo! È anche possibile utilizzare uno share di rete (anche noto come "Cartella Condivisa" nel mondo degli OS di Redmond) per ospitare i programmi e i dati degli utenti di quei computer privi di disco rigido.

L'idea non è affatto nuova, e si rifà a quello che era il modus operandi canonico per gli utenti dei computer degli anni 70: c'era un unico calcolatore centrale e una serie di terminali stupidi che erano poco più che uno schermo, una tastiera e un'interfaccia seriale. Gli utenti operavano in time sharing mediante i terminali sul calcolatore centrale e tutti i loro dati erano salvati su di esso: se avevano bisogno di una copia dei dati chiamavano gli operatori del calcolatore centrale e facevano richiesta per l'invio di una copia su nastro magnetico. Altri tempi, altri informatici, altre rogne...

Fortunatamente per il nostro eroe la documentazione di OpenBSD tratta molto bene il boot da rete nelle pagine di manuale, più precisamente alla voce diskless della sezione 8 del manuale.

Sfortunatamente il procedimento esatto per metter in piedi un server RARP con un TFTP varia notevolmente in base al Sistema Operativo installato sulla macchina che farà da bootstrap per la Ultra 1. Siccome lo spazio è tiranno e io mi sono dilungato anche troppo in considerazioni sui bei vecchi tempi lascerò il nostro eroe a leggere la documentazione e preparare il suo server di bootstrap e lascerò voi lettori con un ultimo suggerimento: cercate con il vostro motore di ricerca preferito i termini "Knoppix Terminal Server" e scoprirete come sia possibile creare facilmente un laboratorio di computer come quello che ho descritto.