Copy Link
Add to Bookmark
Report
BFi numero 12 file 05
==============================================================================
--------------------[ BFi12-dev - file 05 - 03/05/2003 ]----------------------
==============================================================================
-[ DiSCLAiMER ]---------------------------------------------------------------
Tutto il materiale contenuto in BFi ha fini eslusivamente informativi
ed educativi. Gli autori di BFi non si riterranno in alcun modo
responsabili per danni perpetrati a cose o persone causati dall'uso
di codice, programmi, informazioni, tecniche contenuti all'interno
della rivista.
BFi e' libero e autonomo mezzo di espressione; come noi autori siamo
liberi di scrivere BFi, tu sei libero di continuare a leggere oppure
di fermarti qui. Pertanto, se ti ritieni offeso dai temi trattati
e/o dal modo in cui lo sono, * interrompi immediatamente la lettura
e cancella questi file dal tuo computer * . Proseguendo tu, lettore,
ti assumi ogni genere di responsabilita per l'uso che farai delle
informazioni contenute in BFi.
Si vieta il posting di BFi in newsgroup e la diffusione di *parti*
della rivista: distribuite BFi nella sua forma integrale ed originale.
------------------------------------------------------------------------------
-[ HACKiNG ]------------------------------------------------------------------
---[ GRUB FALLBACK PATCH
-----[ ORK <orkmail@katamail.com>
<---------------------------------------------------------------------------->
<- __ ___ _ -->>------------- GRUB FallBack Patch ------------<<-->
<- / \ | \ | | /\ ------------------------------------------------------>
<- / /\ \| |\ \| |/ / --- Autore: --------------- ORK ---------------------->
<- / /__\ \ /| / --- Contatti: ------------- orkmail@katamail.com ----->
<- \______/ |\ \| | \ ------------------------------------------------------>
<---------|_| \_\_|\_\ ------------------------------------------------------>
<---------------------------------------------------------------------------->
Indice
------
0 - Introduzione
1 - Presentazione del problema
2 - Configurazione HW del sistema Embedded
3 - L'idea
4 - La scelta del Boot Loader
5 - L'implementazione
5.1 - L'attivazione del WatchDog
5.2 - La scelta del kernel
5.3 - Programmi in user-space
6 - Come far funzionare il tutto
6.1 - Modifiche alla distribuzione
6.2 - Installazione di GRUB sulla Compact Flash
6.3 - Aggiornare il kernel
7 - Come adattare la patch ad altri sistemi
8 - Ringraziamenti
0 - Introduzione
----------------
Un po' di tempo fa ho avuto la possibilita` di lavorare alla creazione di
alcune distribuzioni linux da montare su dei sistemi embedded.
Per chi non lo sapesse un sistema embedded e` un elaboratore di dimensioni
ridotte usato per applicazioni particolari.
Siccome questi sistemi sono progettati per andare a svolgere delle funzioni
particolari, molte volte e` necessario adattare certi pacchetti software per
poter andare a coprire certe esigenze che normalmente non sono richieste
dall'uso "normale" di linux su Server o Workstation.
In questo articolo voglio presentare una particolare modifica che ritengo
abbastanza interessante fatta a GRUB.
1 - Presentazione del problema
------------------------------
Una delle cose piu' interessanti dei sistemi su cui ho lavorato e` che una
volta che questi saranno operativi non sara` piu' possibile accedervi
fisicamente (o comunque con molta fatica) e l'unico modo per potervi
interaginre sara` via rete.
Questo vuol dire che si dovranno prevedere delle procedure per la normale
manutenzione della distribuzione linux (come l'aggiornamento dei vari
pacchetti installati) via rete, cercando di limitare al massimo le situazioni
che potrebbero compromettere la stabilita` della macchina. Il crash della
macchina sarebbe una cosa molto grave perche` la renderebbe irraggiungibile.
Come si puo` immaginare in una situazione del genere la parte piu` delicata da
aggiornare e` sicuramente il kernel. Certo, non sara' una cosa che verra`
fatta troppo spesso, ma comunque bisogna prevedere un meccanismo che renda
sicura anche questa procedura.
I passi da seguire per un aggiornamento del kernel su un sistema di questo
tipo sono i seguenti:
1 - Compilare il kernel in locale
2 - Uploadare il kernel sulla macchina
3 - Aggiornare il file di configurazione del Boot-Loader
4 - Riavviare la macchina
Ma cosa succede se dopo aver riavviato la macchina il kernel nuovo fiammante
si blocca per qualche oscuro motivo?
Ovviamente si perde la macchina e questa e` una cosa che non deve succedere
per nessun motivo!!!
Per trovare un meccanismo che renda sicura questa procedua e` interessante
analizzare il comportamento di un utente comune quando aggiorna il kernel
della propria linux box domestica.
In una situazione normale quando si deve aggiornare il kernel di una macchina,
dopo averlo compilato, si aggiungono al file di configurazione del Boot
Loader le righe necessarie per far partire il nuovo kernel lasciando la
possilita` di selezionare quello vecchio nel caso ci siano dei problemi.
Solamente dopo aver testato il nuovo kernel si passa alla cancellazione di
quello vecchio.
Quello che ho cercato di fare e` creare una procedura automatica che faccia la
stessa cosa, ovvero che prima provi il kernel nuovo, ed in caso il boot non
vada a buon fine carichi quello vecchio (ovvero l'ultimo che aveva bootato
correttamente).
In questa procedura il kernel nuovo (ovvero quello di cui non si e` sicuri)
dovrebbe essere impostato come kernel di default, mentre l'altro (quello di
cui si e` sicuri) dovrebbe essere impostato come kernel di fallback (ovvero
una specie di salvataggio nel caso in cui le cose non vadano bene).
Il primo problema che salta in mente e` trovare il posto corretto dove
piazzare una procedura di questo tipo. Dopo una breve analisi si giunge
facilmente alla conclusione che l'unico punto in cui si puo` inserire una cosa
del genere e` all'interno di un boot loader, in quanto e` l'unico "pezzo" di
software controllabile che viene eseguito prima del caricamento del kernel.
Analizzando bene la situazione ci si accorge immediatamente che ci sono 2
problemi fondamentali da risolvere per poter realizzare questa procedura,
ovvero:
- Una volta che il boot loader ha dato il controllo al kernel e questo si
blocca il sistema non puo` essere piu' recuperato via software, ma e`
necessario un reset della macchina.
- Supponendo di riuscire a resettare la macchina, il boot loader dovrebbe
essere in grado di ricordarsi se l'ultimo kernel fatto partire era stato
caricato con successo e nel caso contrario dovrebbe essere in grado di far
partire un kernel alternativo.
2 - Configurazione HW del sistema Embedded
------------------------------------------
Prima di passare alla presentazione delle idee trovate per risolvere i due
problemi introdotti nel paragrafo precedente facciamo una breve panoramica
delle caratteristiche Hardware piu' interessanti del sistema embedded su cui
dovra` poi girare il tutto.
La scheda precisamente si chiama Eurotech CPU-1232 .
Le caratteristiche principali sono le seguenti:
Architettura: PC/AT Compatible
Dimensioni: 91 x 96 mm (PC/104)
Processore: NS Geode GX1 processor (Pentium MMX like) 266MHz
RAM: 64 MB DRAM
Memoria di Massa: Compact Flash da 64 MB
Rete: 3 interfacce 10/100 Mbps Fast Ethernet
BIOS: Standard con estensioni embedded
Sono presenti inoltre:
- Una porta seriale
- Un WatchDog Hardware
- Un Real Time Clock
Tra le caratteristiche Hardware presentate l'unica cosa che forse qualcuno non
conosce e` il WatchDog Hardware.
Cos'e` il WatchDog?
Il WatchDog non e` altro che un dispositivo che una volta inizializzato fa un
conto alla rovescia a partire da un certo numero di secondi. Una volta
arrivato a zero la macchina viene resettata. Durante il conto alla rovescia e`
possibile ricaricare i secondi che mancano per arrivare a zero o fermare del
tutto il conto alla rovescia.
Uno si potrebbe chiedere per cosa puo` tornare utile una cosa del genere.
Immaginiamo un sistema che debba rimanere sempre acceso. Si sa` che dopo
diverso tempo che una macchina e` accesa puo` diventare instabile e puo`
capitare che il sistema si blocchi. A questo punto la macchina restera`
irraggiungibile fino a quando il sistemista non se ne accorge e fa ripartire
il sistema. Questo puo` avvenire anche dopo diverse ore da quando il sistema
si e` bloccato con la conseguenza che per tutto questo tempo i servizi per cui
la macchina era stata progettata non saranno attivi.
In una situazione di questo tipo il WatchDog ci puo` venire incontro per
minimizzare il periodo di fermo-macchina. Supponiamo di impostare il WatchDog
perche` esegua il conto alla rovescia da 60 secondi ed ogni 50 secondi venga
riportato a 60. Fino a quando il sistema e` regolarmente funzionante non
verra` mai raggiunta la fine del conto alla rovescia, ma nel caso il sistema
si bloccasse il WatchDog non verrebbe piu' ricaricato e quindi il sistema
verrebbe riavviato. In questo caso il tempo di fermo-macchina e` al massimo 60
secondi piu' il tempo di reboot.
3 - Le idee
-----------
Passiamo alle soluzioni trovate ai problemi presentati precedentemente.
Per risolvere il problema del reset della macchina ho pensato che la cosa
migliore sarebbe stata quella di usare il WatchDog integrato nella scheda.
L'idea e` quella di inizializzare il WatchDog subito prima di dare il
controllo al kernel. In questo modo se il kernel si blocca il sistema viene
resettato non appena il conto alla rovescia arriva a zero. Se, invece, il boot
va a buon fine ci dovra` essere un programmino lanciato dagli script di
inizializzazione che resetta il WatchDog. Ovviamente il tempo del conto alla
rovescia deve essere abbastanza lungo da permettere al sistema di partire.
Una volta risolto il problema del reset della macchina passiamo al secondo
problema. Come fa il boot loader a sapere se un kernel e` gia` stato fatto
partire e non ha bootato correttamente? In altre parole come fa il boot loader
a decidere quale kernel far partire?
L'unico modo ovviamente e` salvare delle informazioni da qualche parte e poi
al momento della scelta del kernel andarle a rileggere e valutare.
Bisogna quindi decidere che informazioni salvare e dove andarle a scrivere.
Per quanto riguarda il posto in cui scrivere le informazioni, all'inizio avevo
pensato di usare un settore del disco, ma poi ho pensato che sarebbe stato
molto piu' facile scrivere sulla CMOS. Le informazioni da salvare sono poche e
nella CMOS ci sono sempre dei byte non utilizati.
Come seconda cosa bisogna pensare a quali sono le informazioni di cui ha
bisogno il boot loader per fare la scelta del kernel. L'unica informazione
necessaria e` un flag che dica se il kernel di default e` partito con
successo oppure no, quindi e` necessario creare un meccanismo per il test di
questa situazione. L'idea e` semplice, prima di dare il controllo al kernel il
flag verra` messo ad 1 e se il sistema parte senza problemi ci sara` un
programmino che lo reimpostera` a 0. In questo modo per la scelta del kernel
bastera` testare questo flag, se il valore e` 1 significa che il kernel di
default e` gia` stato fatto partire, ma il sistema non e` partito
correttamente. Se il flag e` a 0 significa o che e` la prima volta che si
cerca di far partire il kernel oppure che ha gia` fatto un boot con successo.
4 - La scelta del Boot Loader
-----------------------------
Dovendo implementare questo meccanismo all'interno di un Boot Loader ne ho
visionati alcuni prima di decidere qual era quello piu' adatto allo scopo.
Alla fine la scelta e` caduta su GRUB per varie ragioni, non per ultima la
chiarezza del codice.
Prima di passare all'implementazione e` utile fare una breve presentazione
della struttura interna del GRUB, in modo da capire la logica delle modifiche.
GRUB e` un Boot Loader con molte funzionalita` e quindi come si puo' intuire
e` di dimensioni non troppo ridotte. Siccome il Master Boot Sector (MBR) e`
grande solamente 512 byte ed all'interno, oltre al codice di boot, sono
contenute altre informazioni, e` impensabile far stare l'intero codice
all'interno di questa zona. Per risolvere questo problema il GRUB e` stato
diviso in 3 pezzi distinti in modo che possano essere messi in posizioni
diverse. Questi tre pezzi sono chiamati stage1, stage1.5 e stage2 di cui lo
stage1.5 e` opzionale.
Lo stage1 e` inserito nel MBR in quanto e` molto piccolo. Il suo unico scopo
e` quello di caricare il primo settore di stage1.5 o stage2. Siccome la sua
grandezza doveva restare ridotta non e` stato possibile inserire all'interno
di questo modulo il supporto per i file-system, cosi` l'indirizzo del settore
dello stage successivo da caricare viene calcolato al momento
dell'installazione del GRUB e resta fisso.
Lo stage2 e` il cuore di GRUB e solitamente e` inserito all'interno del
file-system. Il menu` e tutte le funzionalita` di alto livello sono
implementate all'interno di questo modulo.
Lo stage1.5 e` facoltativo ed ha come obiettivo fare da ponte tra stage1 e
stage2. In pratica lo stage1 carica lo stage1.5 che a sua volta carica lo
stage2. La differenza tra lo stage1 e lo stage1.5 e` che il primo non ha il
supporto per i file-system, mentre il secondo si`. Questo e` utile perche`
generalmente lo stage2 e` troppo grande per essere inserito in qualche area
fissa del disco, cosi` viene inserito all'interno del file-system. Lo
stage1.5, invece, e` abbastanza piccolo da essere inserito in una posizione
fissa del disco come il settore immediatamente successivo all'MBR.
Quindi ricapitolando lo stage1 e` memorizzato nell'MBR e carica lo stage1.5
che e` memorizzato in un'altra posizione fissa del disco. Questo a sua volta,
riuscendo a leggere vari file-system, trova lo stage2 lo carica e gli passa
il controllo.
Un'altra cosa interessante del GRUB e` che implementa gia` un rudimentale
meccanismo di fallback. Questo meccanismo si limita ad un test superficiale
di alcune caratteristiche del file che contiene il kernel. La cosa
interessante e` che per la nostra modifica possiamo utilizzare la struttura
interna di GRUB per la gestione di questo rudimentale meccanismo di fallback
(ad esempio GRUB prevede gia` la possibilita` di specificare un kernel di
fallback nel file di configurazione).
5 - L'implementazione
---------------------
Come gia` accennato lo stage2 e` il cuore di GRUB e quindi tutte le modifiche
sono state fatte in questo punto del codice. Nei due paragrafi successivi
presentero` i passaggi piu` interessanti dell'implementazione delle due
soluzioni presentate precedentemente. In allegato potete trovare il file di
patch "grub-0.90-1232.diff" che va applicato alla versione 0.90 del GRUB.
5.1 - L'attivazione del WatchDog
--------------------------------
Siccome al momento in cui viene eseguito GRUB non e` ancora caricato il
sistema operativo non ci si puo` avvalere di drivers o altre facilitazioni per
accedere all'Hardware, ma bisogna per forza accedervi a basso livello ovvero
leggendo e scrivendo su delle porte di I/O.
Per l'attivavione del WatchDog e` necessario scrivere un certo numero di byte
nella giusta sequenza su delle porte di I/O. Per trovare quali sono le porte
e quali sono i byte da scrivere ho fatto riferimento al driver del WatchDog
per la scheda in questione presente nei sorgenti del kernel (tra l'altro
scritto proprio dalla ditta per cui ho sviluppato questa patch). Precisamente
il file del driver si puo` trovare all'interno dei sorgenti del kernel in
questa posizione:
drivers/char/eurotechwdt.c
La funzione per scrivere su una porta di I/O e` cosi` definita:
static inline void
outb (unsigned short port, unsigned char val)
{
__asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
}
dove port indica la porta di I/O su cui si va a scrivere e val e` il valore
che si scrive.
L'inizializzazione del WatchDog, quindi, si limita ad una serie di chiamate
a questa funzione. Non riporto l'elenco dei valori da scrivere (li potete
comunque trovare nel sorgente).
La funzione (che ci servira` dopo) che ci permette di leggere da una porta
di I/O e` cosi` definita:
static inline unsigned char
inb (unsigned short port)
{
unsigned char data;
__asm __volatile ("inb %1,%0" :"=a" (data):"d" (port));
return data;
}
dove port indica la porta da cui leggere.
5.2 - La scelta del kernel
--------------------------
Prima di partire con l'implementazione della procedura per la scelta del
kernel da far partire e` stato necessario:
- trovare un byte libero nella CMOS
- decidere quali informazioni dovevano essere inserite in questo byte
- decidere come dovevano essere disposte le informazioni all'interno del byte
La scelta del byte libero non e` stata molto problematica avendo avuto la
possibilita` di parlare direttamente con il progettista della scheda (ho
dovuto solamente fare un piano di scale :P)
Per quanto riguarda il contenuto del byte e la disposizione delle informazioni
ho deciso per questa soluzione:
bit Contenuto
0 Flag per il Kernel di default
1 Flag per il kernel di fallback
2-3 Numero del kernel di dafault (max 4 possibilita`)
4-5 Numero del kernel di fallback (max 4 possibilita`)
6-7 Numero dell'ultimo kernel fatto partire
dove il bit 0 e` il meno significativo.
I primi 2 bit sono i flag del kernel di default e del kernel di fallback.
Si parte controllando il valore del bit 0. Se ha valore 0 allora si da`
immediatamente il controllo al kernel di default, altrimenti significa che
il boot precedente non ha avuto esito positivo e quindi si passa al controllo
del bit 1. Se questo bit ha valore 0 si lancia il kernel di fallback. Se anche
questo bit ha valore 1 significa che ci si trova in una situazione non buona,
ovvero entrambi i kernel non hanno bootato correttamente e quindi il sistema
e` inevitabilmente bloccato. Non si dovrebbe mai arrivare a questo punto !!!
Il numero del kernel a cui si riferiscono i bit che vanno dal 2 al 7 e` quello
corrispondente al file di configurazione del GRUB (/boot/grub/menu.lst).
Per leggere il valore di un byte dalla CMOS si deve procedere in due tempi:
prima si deve scrivere sulla porta di I/O 0x70 l'indirizzo della CMOS a cui si
e` interessati e poi leggerne il valore dalla porta di I/O 0x71. La funzione
che legge un byte dalla CMOS e` quindi definita cosi`:
static inline unsigned
cmos_read_byte (int loc)
{
outb (0x70, loc);
return inb (0x71);
}
Per scrivere un byte sulla CMOS, invece, si deve procedere in questo modo:
prima si deve scrivere sulla porta di I/O 0x70 l'indirizzo della CMOS a cui si
e` interessati e poi scrivere il byte sulla porta di I/O 0x71. La funzione
che scrive un byte dalla CMOS e` quindi definita cosi`:
static inline void
cmos_write_byte (int loc, int val)
{
outb (0x70, loc);
outb (0x71, val);
}
Una volta definite queste due funzioni vediamo come leggere il byte dalla CMOS
e ricavare i 5 valori spezzando i bit come visto sopra.
cmos_address = 120;
Bcmos = cmos_read_byte (cmos_address);
FB_default= Bcmos & 0x1;
FB_fallback= (int) (Bcmos & 0x2)>>1;
FB_ndefault= (int) (Bcmos & 0xc)>>2;
FB_nfallback= (int) (Bcmos & 0x30)>>4;
FB_nlast= (int) (Bcmos & 0xc0)>>6;
Una volta che si hanno a disposizione le variabili contenenti i valori si puo`
procedere facilmente a calcolare qual e` il kernel da far partire.
if (FB_default==0)
{
grub_printf("ESEGUO IL KERNEL DI DEFAULT !\n");
FB_default=1;
}
else
{
grub_printf("L'ULTIMA VOLTA IL KERNEL DI DEFAULT NON E' PARTITO CORRETTAMENTE !\n");
grub_printf("ESEGUO IL KERNEL DI FALLBACK !\n");
FB_fallback=1;
cur_entry = NULL;
first_entry = 0;
entryno = fallback_entry;
fallback_entry = -1;
}
FB_nlast = first_entry + entryno;
Dopo aver selezionato il kernel da far partire si deve procedere a risalvare i
valori aggiornati sulla CMOS. Per farlo si procede come segue:
Bcmos = (char) FB_default | (char) FB_fallback <<1 | (char) FB_ndefault \
<<2 | (char) FB_nfallback <<4 | (char) FB_nlast <<6;
cmos_write_byte (cmos_address, Bcmos);
5.3 - Programmi in user-space
-----------------------------
Oltre alle modifiche apportate al GRUB, per il corretto funzionamento di tutto
il meccanismo sono necessari alcuni programmi da usare quando il sistema e`
attivo. Precisamente sono necessari:
- Un programma per inizializzare il valore del byte sulla CMOS, da far
partire ogni volta che si fa qualche modifica al file di configurazione
del GRUB.
- Un programma per azzerare il flag che il GRUB ha impostato a 1 al momento
in cui ha dato il controllo al kernel. Questo programma va eseguito a ogni
boot del sistema.
- Un programma per aggiornare il watchdog da far partire ad ogni boot del
sistema.
Partiamo con il primo (cmos-init.c).
Questo programmino non fa altro che leggere il file di configurazione del GRUB
(/boot/grub/menu.lst) e in base alle impostazioni contenute inizializzare il
byte sulla CMOS. Per scrivere sulla CMOS il programma fa uso del device
/dev/nvram quindi deve essere incluso il supporto nel kernel. C'e` da notare
che il device nvram non mappa i primi 14 byte della CMOS che contengono l'ora,
quindi l'indirizzo che si andra` a scrivere e` di 14 byte inferiore rispetto a
quello che si aveva usato all'interno del GRUB.
Il byte sulla CMOS viene inizializzato in questo modo:
bit Contenuto
0 0
1 0
2-3 Numero del kernel di dafault
4-5 Numero del kernel di fallback
6-7 Numero del kernel di dafault
Il device /dev/nvram come gia` acennato mappa il contenuto della CMOS esclusi
i primi 14 byte, quindi con il comando
# od /dev/nvram -t x1
si puo` vedere il contenuto della CMOS in esadecimale.
Il programma cmos-init.c per inizializzare il byte apre il device in modalita`
read/write, si posiziona sul byte corretto e scrive il valore desiderato.
#define DEVICE "/dev/nvram"
x = fopen (DEVICE, "r+");
rewind(x);
fseek(x, CMOS_ADDR,SEEK_CUR);
fwrite (&B, 1, 1, x);
fclose (x);
Passiamo al secondo programma (cmos-update.c).
Questo programma aggiorna il byte dalla CMOS azzerando il flag relativo
all'ultimo kernel fatto partire. Anche cmos-update fa uso del device
/dev/nvram per accedere alla CMOS.
x = fopen (DEVICE, "r+");
rewind(x);
fseek(x, CMOS_ADDR,SEEK_CUR);
fread (&B, 1, 1, x);
FB_default= B & 0x1;
FB_fallback= (int) (B & 0x2)>>1;
FB_ndefault= (int) (B & 0xc)>>2;
FB_nfallback= (int) (B & 0x30)>>4;
FB_nlast= (int) (B & 0xc0)>>6;
if (FB_ndefault == FB_nlast)
{
FB_default = 0;
}
if (FB_nfallback == FB_nlast)
{
FB_fallback = 0;
}
B = (char) FB_default | (char) FB_fallback <<1 | (char) FB_ndefault \
<<2 | (char) FB_nfallback <<4 | (char) FB_nlast <<6;
printf("CMOS Byte Updated: %x\n", B);
rewind(x);
fseek(x, CMOS_ADDR,SEEK_CUR);
fwrite (&B, 1, 1, x);
fclose (x);
Il terzo programma (wdmon.c) e`, invece, quello che ricarica costantemente i
secondi del conto alla rovescia del WatchDog. Per svolgere correttamente il
suo lavoro necessita del device /dev/watchdog, precisamente viene fatto un
ioctl() sul device.
while (1)
{
sleep (WD_RESTART);
if (ioctl(wd_f, WDIOC_KEEPALIVE, &time) < 0)
{
fprintf(stderr, "%s: cannot reset the timer\n", prg_name);
exit(EXIT_FAILURE);
}
}
6 - Come far funzionare il tutto
--------------------------------
Dopo aver presentato tutti i pezzi necessari vediamo brevemente come far
funzionare il tutto.
Come prima cosa bisogna applicare la patch ai sorgenti della versione 0.90
del GRUB e ricompiliare e installare il tutto. Terminata questa operazione si
passa alla compilazione dei programmi contenuti nella directory "GRUB-Utils".
Come mostrato nel paragrafo 2 questo sistema embedded usa come memoria di
massa una Compact Flash da 64 MB che viene vista come un disco IDE dal
sistema. Per tutte le operazioni di modifica della distribuzione linux
contenuta sulla Flash e l'installazione di GRUB faro` uso di un adattatore
PCMCIA per compact Flash.
6.1 - Modifiche alla distribuzione
----------------------------------
Prima di passare all'installazione del GRUB modificato e` necessario
copiare nella directory /sbin della distribuzione linux i programmi contenuti
nella directory "GRUB-Utils" e creare i devices /dev/nvram e /dev/watchdog .
Per creare questi due devices si lanciano i seguenti i comandi:
# mknod /dev/nvram c 10 144
# mknod /dev/watchdog c 10 130
Si dovranno inoltre modificare gli script di boot in modo che facciano partire
i programmi "cmos-update" e "wdmon" ad ogni avvio del sistema e modificare il
file di configurazione di GRUB (/boot/grub/menu.lst) specificando il kernel
di default ed eventualmente quello di Fallback.
Dopo aver compiuto questi passi e` necessario fare il boot del sistema
embedded con la Flash (su cui in precedenza era stato installato un boot
loader "normale"). Una volta che il sistema e` attivo sara` necessario
accedervi tramite ssh e lanciare il comando:
# /sbin/cmos-init
che inizializza il byte sulla CMOS.
6.2 - Installazione GRUB sulla Compact Flash
--------------------------------------------
Usando l'adattatore PCMCIA la Compact Flash viene vista come un disco, nel
mio caso /dev/hde . Al momento in cui viene installato il GRUB nella Flash
la distribuzione linux e` installata nella partizione hde1 che verra` montata
in /mnt/root .
Come prima cosa bisogna andare a modificare i files di configurazione del
GRUB in modo da riuscire ad installarlo sulla Flash.
Cominciamo con l'editare il file /boot/grub/device.map che originariamente
contiene una cosa di questo tipo:
(fd0) /dev/fd0
(hd0) /dev/hda
(hd1) /dev/hde
nel nostro caso il disco /dev/hde dovra` essere visto come primo disco (hd0)
quando fara` il boot, quindi bisogna modificare il file in questo modo:
(fd0) /dev/fd0
(hd1) /dev/hda
(hd0) /dev/hde
questa modifica equivale ad inserire il parametro "bios=0x80" nel file di
configurazione del lilo.
La partizione /dev/hde1 contenente la distribuzione linux dovra` contenere
anche tutti i files necessari a GRUB, quindi provvediamo immediatamente a
copiarli.
# cp /usr/local/share/grub/i386-pc/* mnt/root/boot/grub/
A questo punto si procede lanciando il comando
# grub --device-map /boot/grub/device.map
che avvia la shell di GRUB. Per installare il boot loader sara` sufficiente
lanciare i seguenti comandi:
root (hd0,0)
setup (hd0)
quit
Il primo comando specifica che al boot la partizione radice sara` la prima
partizione del disco hd0 (che corrisponde a /dev/hde). Le partizioni infatti
partono da 0. Il secondo comando installa il boot loader in hd0 (che
corrisponde a /dev/hdb)
A questo punto e` tutto pronto, la Flash puo essere installata sul sistema.
6.3 - Aggiornare il kernel
--------------------------
Supponiamo di aver messo in piedi tutto il meccanismo illustrato nei paragrafi
precedenti e di avere una macchina raggiungibile via rete su cui sia
necessario fare l'upgrade del kernel.
La prima cosa sara` quella di compilare il kernel in locale per poi uploadarlo
sul sistema remoto. A questo punto bastera` modificare il file di
configurazione di GRUB (/boot/grub/menu.lst) specificando come kernel di
default quello nuovo e come kernel di FallBack quello vecchio. Prima di fare
il reboot della macchina non bisogna dimenticarsi di lanciare il comando
"cmos-init" che inizializza il Byte della CMOS con le nuove impostazioni
contenute nel file di configurazione appena modificato.
Dopo il reboot il sistema dara` il controllo al nuovo kernel e se questo
dovesse far bloccare il sistema allora il controllo ritornera` al kernel
precedente.
7 - Come adattare la patch ad altri sistemi
-------------------------------------------
Se volete adattare la patch ad altri sistemi le cose a cui dovete fare
attenzione sono principalmente 2:
- La sequenza dei byte da spedire alle porte di I/O per attivare il WatchDog
sono sicuramente differenti in altre schede e quindi dovrete modificare la
funzione di attivazione del WD.
- Controllate se il byte utilizzato per salvare le informazioni sui kernel
e` gia` usato o se invece e` libero.
8 - Ringraziamenti
------------------
Doverosi sono i ringraziementi al team di sviluppatori dell'Ascensit per
avermi aiutato con preziosi consigli allo sviluppo di questa patch.
<---------------------------------------------------------------------------->
<------------------- ** Information wants to be Free !! ** ------------------>
<---------------------------------------------------------------------------->
<------------------------------------------------------------------ By ORK -->
<---------------------------------------------------------------------------->
-[ WEB ]----------------------------------------------------------------------
http://www.bfi.cx
http://bfi.freaknet.org
http://www.s0ftpj.org/bfi/
-[ E-MAiL ]-------------------------------------------------------------------
bfi@s0ftpj.org
-[ PGP ]----------------------------------------------------------------------
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3i
mQENAzZsSu8AAAEIAM5FrActPz32W1AbxJ/LDG7bB371rhB1aG7/AzDEkXH67nni
DrMRyP+0u4tCTGizOGof0s/YDm2hH4jh+aGO9djJBzIEU8p1dvY677uw6oVCM374
nkjbyDjvBeuJVooKo+J6yGZuUq7jVgBKsR0uklfe5/0TUXsVva9b1pBfxqynK5OO
lQGJuq7g79jTSTqsa0mbFFxAlFq5GZmL+fnZdjWGI0c2pZrz+Tdj2+Ic3dl9dWax
iuy9Bp4Bq+H0mpCmnvwTMVdS2c+99s9unfnbzGvO6KqiwZzIWU9pQeK+v7W6vPa3
TbGHwwH4iaAWQH0mm7v+KdpMzqUPucgvfugfx+kABRO0FUJmSTk4IDxiZmk5OEB1
c2EubmV0PokBFQMFEDZsSu+5yC9+6B/H6QEBb6EIAMRP40T7m4Y1arNkj5enWC/b
a6M4oog42xr9UHOd8X2cOBBNB8qTe+dhBIhPX0fDJnnCr0WuEQ+eiw0YHJKyk5ql
GB/UkRH/hR4IpA0alUUjEYjTqL5HZmW9phMA9xiTAqoNhmXaIh7MVaYmcxhXwoOo
WYOaYoklxxA5qZxOwIXRxlmaN48SKsQuPrSrHwTdKxd+qB7QDU83h8nQ7dB4MAse
gDvMUdspekxAX8XBikXLvVuT0ai4xd8o8owWNR5fQAsNkbrdjOUWrOs0dbFx2K9J
l3XqeKl3XEgLvVG8JyhloKl65h9rUyw6Ek5hvb5ROuyS/lAGGWvxv2YJrN8ABLo=
=o7CG
-----END PGP PUBLIC KEY BLOCK-----
==============================================================================
-----------------------------------[ EOF ]------------------------------------
==============================================================================