Old:ACPI e DSDT: differenze tra le versioni

Da Guide@Debianizzati.Org.
Vai alla navigazione Vai alla ricerca
m (ha spostato ACPI e DSDT a Old:ACPI e DSDT)
 
(26 versioni intermedie di 8 utenti non mostrate)
Riga 1: Riga 1:
{{stub}}
{{Old}}
== Introduzione ==
== Introduzione ==


Gli '''Hard Disk''' sono una delle parti pi� delicate degli odierni pc, ed infatti sono tra le periferiche che pi� facilmente soggette a rompersi.
ACPI ('''Advanced Configuration and Power Interface''') è uno standard industriale aperto che definisce l'interfaccia tra S.O. e BIOS per l'amministrazione e la configurazione delle risorse di un PC. ACPI prevede che le informazioni a basso livello sul sistema (batteria, luminosità LCD, pulsanti Fn, ecc.) siano contenute nella DSDT ('''Differentiated System Description Table''').  


Fortunantamente ci sono degli strumenti che permettono diagnosticare i malfunzionamenti (sperabilmente) prima ancora che possano creare danno. Ma ricordate che un backup periodico dei dati importanti � sempre la scelta migliore.
Il problema principale del supporto ad ACPI in Linux risiede nella presenza di errori (ma anche di controlli espliciti su alcune caratteristiche peculiari del S.O. soprastante) nella tabella DSDT: purtroppo, molti fornitori di hardware non sono in grado, o non vogliono fornire tabelle DSDT completamente funzionali secondo gli standard ACPI.


In questa guida vedremo come usare alcuni strumenti come '''smartmontools''' e '''badblocks''' per monitorare lo stato di salute di un hard disk, vedremo come effettuare le basilari operazioni di backup di emergenza ed eventualmente come affrontare il ripristino dei dati.  
Per questo motivo, per utilizzare appieno le possibilità offerte da alcuni PC, soprattutto laptop, è necessario correggere la DSDT e istruire il kernel affinché nel processo di boot carichi la tabella fornita da noi invece di quella fornita dal BIOS.


== DISCLAIMER ==
== Aggiornamento del BIOS ==


Per quanto io faccia del mio meglio per verificare l'attendibilit� delle informazioni, non posso garantire che alcune delle tecniche illustrate di seguito possano danneggire i vostri dati, bruciare la vostra casa o uccidere il vostro gatto.
Per cominciare è indispensabile aggiornare il BIOS con l’ultima versione disponibile, sperando che la nuova versione contenga una tabella DSDT con meno errori della precedente :P.


Faccio notare, inoltre, che il ripristino dei dati da una partizione corrotta sia pi� una magia nera che una scienza e richiede oltre che doti da chiromante anche una buona dose di fortuna. Quindi, e non lo ripeto pi�, fate backup sistematici dei vostri dati o non lamentatevi se doveste perderli accidentalmente e non riuscire pi� a recuperarli!
== Installazione nel kernel del supporto ACPI ==


== Controllare lo stato di salute di un HD: smartmontools ==
Per poter utilizzare ACPI è necessario disporre di un kernel in cui sia stato abilitato il supporto ACPI. Praticamente tutte le distribuzioni forniscono kernel precompilati con il supporto ACPI attivato. Nel caso, però, vi trovaste a dover (o voler) compilare autonomamente un kernel con il supporto ACPI, le voci necessarie sono le seguenti:


Gli ''smartmontools'' permettono di usare la funzionalit� [http://en.wikipedia.org/wiki/Self-Monitoring%2C_Analysis_and_Reporting_Technology SMART] di tutti i moderni HD grazie alla quale � possibile prevedere con 24 ore di anticipo la rottura di un HD.
<pre>ACPI (Advanced Configuration and Power Interface) Support --->
    ACPI Support --->
        <*> AC Adapter
        <*> Battery
        <*> Button
        <*> Processor</pre>


In debian basta installare il pacchetto smartmontools:
== Strumenti per lavorare con le DSDT ==


# aptitude install smartmontools
Per poter leggere e compilare una DSDT è necessario il compilatore ASL di Intel, che in Debian esiste già precompilato a partire da Etch; altrimenti è liberamente disponibile per il download a [http://developer.intel.com/technology/iapc/acpi/downloads.htm questo] indirizzo.


=== Analizzare lo stato dell'HD ===
Per utilizzare la DSDT corretta sono disponibili due metodi:
Possiamo usare l'utility <tt>'''smartctl'''</tt> per analizzare lo stato dell'HD.  
* il primo prevede l'applicazione di una [ftp://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/patches/release/ patch per il kernel] e l'inserimento della nuova DSDT direttamente nel kernel, che quindi  sarà da ricompilare ogni volta che si fanno cambiamenti alla DSDT;
* il secondo inserisce la nuova DSDT all'interno dell'initrd, e quindi non necessita la ricompilazione del kernel, a patto che nel vostro kernel sia stata inclusa una [http://gaugusch.at/kernel.shtml patch apposita]. Al momento la patch menzionata è inclusa nei kernel delle maggiori distribuzioni (sicuramente in Debian, Ubuntu, Suse, e Mandriva).  


Innazi tutto vediamo alcune informazioni generiche sul nostro HD:
=== Installare il compilatore ASL ===


Uno dei motivi per cui le DSDT sono spesso difettose è che vengono compilate con il compilatore fornito da Microsoft, invece che con quello fornito da Intel. Curiosamente i sistemi Microsoft riescono ad evitare gli errori commessi dal compilatore della stessa società, mentre, come si può immaginare, la stessa cosa non succede per Linux.
Per installare il compilatore Intel è sufficiente avere nel <code>sources.list</code> un repository per Etch, ed impartire, da root, il comando
<pre>
<pre>
# smartctl -i /dev/hda
# aptitude install iasl
smartctl version 5.34 [i686-pc-linux-gnu] Copyright (C) 2002-5 Bruce Allen
</pre>
Home page is http://smartmontools.sourceforge.net/


=== START OF INFORMATION SECTION ===
Se invece avete scaricato i sorgenti, per avere il compilatore ASL funzionante è necessario compilarlo:
Model Family:     Western Digital Caviar family
<pre>$ tar -zxvf acpica-unix-20050624.tar.gz
Device Model:    WDC WD600BB-00CAA1
$ cd acpica-unix-20050624/compiler
Serial Number:    WD-WMA8F1747570
$ make</pre>
Firmware Version: 17.07W17
User Capacity:    60,022,480,896 bytes
Device is:        In smartctl database [for details use: -P show]
ATA Version is:  5
ATA Standard is:  Exact ATA specification draft version not indicated
Local Time is:    Tue Jan 31 17:36:07 2006 CET
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
</pre>


oltre alle informazioni generiche generiche, dalle ultime due righe, si capisce che l'HD supporta la tecnologia SMART e che il supporto � attivato. Se non fosse attivato basterebbe questo comando:
=== Ottenere una DSDT ===


# smatmontools -s on /dev/hda
È possibile ottenere la DSDT attualmente installata per poi correggere gli eventuali errori e problemi, copiandola da un file reso appositamente disponibile dal filesystem virtuale <code>/sys</code>:
<pre># cat /sys/firmware/acpi/tables/DSDT > dsdt.dat</pre>


per attivare il supporto SMART.
Ciò creerà un file '''dsdt.dat''' che contiene la DSDT compilata.
Per poterne leggere il contenuto è necessario decompilarla con il compilatore ASL appena installato:
<pre>$ iasl -d dsdt.dat</pre>


Per controllare lo stato di salute attuale:
Verrà generato un file di testo denominato '''dsdt.dsl''', che contiene la DSDT. Questo file può essere aperto con un normale editor di testi e modificato a seconda delle esigenze e dei problemi riscontrati.


<pre>
Per vedere quali sono i problemi spesso è sufficiente ricompilare il file ottenuto: il compilatore ASL fornirà una serie di warning sulle ottimizzazioni che è possibile fare (e le farà automaticamente) ed, eventualmente, segnalerà degli errori, la cui soluzione può essere, ad esempio, ricercata su Internet.
# smartctl -H /dev/hda
smartctl version 5.34 [i686-pc-linux-gnu] Copyright (C) 2002-5 Bruce Allen
Home page is http://smartmontools.sourceforge.net/


=== START OF READ SMART DATA SECTION ===
Ad ogni modo una lettura del codice della DSDT può essere istruttiva. Il linguaggio è abbastanza simile al C e con qualche minima conoscenza è possibile comprendere i principali costrutti logici.
SMART overall-health self-assessment test result: PASSED
</pre>


L'ultima riga ci dice che la salute sembra buona e nessuno dei parametri interni controllati da SMART ha superato il livello di guardia.
Nel codice di alcune DSDT è stato trovato un controllo (if .. then) sulla lunghezza del nome del S.O. soprastante (17 lettere, proprio come "Microsoft Windows") come requisito per l'attivazione di alcune funzioni dell'ACPI.


{{Warningbox| Se il precendente comando non riporta '''PASSED''' smontate immediatamente tutte le partizioni presenti su quell'HD ed effettuate un backup dei dati: la rottura definiti del diso � prevista nelle successive 24 ore!}}
Una volta corretti gli errori ricompilare il file '''dsdt.dsl'''.
       
<pre>$ iasl -tc dsdt.dsl</pre>


Per avere tutte le informazioni possibili sul nostro HD diamo:
Verranno generati due file dalla compilazione:
*: dsdt.hex
# smartmontools -a /dev/hda


L'output, abbastanza lungo, � diviso in quattro sezioni. Il primo blocco rappresenta le informazioni generiche sull'HD (le stesse ottenute prima con <tt>-i</tt>), la seconda sezione riporta le informazioni sul supporto SMART. La terza sezione elenca i parametri interni monitorati da SMART e se hanno mai superato il livello di guardia, nel mio caso:
*: DSDT.aml


<pre>
{{ Warningbox | È possibile scaricare una custom DSDT già pronta e corretta da Internet per molti portatili in commercio: http://acpi.sourceforge.net/dsdt/tables }}
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG    VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate    0x000b  200  200  051    Pre-fail  Always      -      0
  3 Spin_Up_Time            0x0007  099  091  021    Pre-fail  Always      -      4108
  4 Start_Stop_Count        0x0032  098  098  040    Old_age  Always      -      2590
  5 Reallocated_Sector_Ct  0x0033  200  200  140    Pre-fail  Always      -      0
  7 Seek_Error_Rate        0x000b  200  200  051    Pre-fail  Always      -      0
  9 Power_On_Hours          0x0032  092  092  000    Old_age  Always      -      6494
10 Spin_Retry_Count        0x0013  100  100  051    Pre-fail  Always      -      0
11 Calibration_Retry_Count 0x0013  100  100  051    Pre-fail  Always      -      0
12 Power_Cycle_Count      0x0032  098  098  000    Old_age  Always      -      2435
196 Reallocated_Event_Count 0x0032  200  200  000    Old_age  Always      -      0
197 Current_Pending_Sector  0x0012  200  200  000    Old_age  Always      -      0
198 Offline_Uncorrectable  0x0012  200  200  000    Old_age  Always      -      0
199 UDMA_CRC_Error_Count    0x000a  200  200  000    Old_age  Always      -      19
200 Multi_Zone_Error_Rate  0x0009  200  200  051    Pre-fail  Offline      -      0
</pre>


I parametri indicati come ''Pre-fail'' sono quelli che superano la soglia di guardia nelle 24 ore che precedono la rottura dell'HD, mentre quelli ''Old_age'' sono i parametri che superano la soglia di guardia quando ormai l'HD � vecchio e non � considerato pi� affidabile dal costruttore. Nel mio esempio si vede nessun parametro ha mai superato la soglia di guardia.
==== Un esempio: la mia DSDT ====


L'ultima sezione del comando <tt>smartctl -a /dev/hda</tt> riguarda il log dei test manualmente effettuati sull'HD:
Nel mio sistema (PC desktop, scheda madre Chaintech) ho da qualche tempo un problema con l'inizializzazione delle porte USB, tale che circa nel 40% dei casi (ma mai due volte di seguito) il PC si blocca durante il boot, e devo riavviare forzatamente.


Per cercare di risolvere la cosa ho analizzato la mia tabella DSDT.
L'ho estratta, e quando ho provato a ricompilarla ho avuto il seguente output:
<pre>
<pre>
SMART Error Log Version: 1
$ iasl -tc dsdt.dsl
No Errors Logged


SMART Self-test log structure revision number 1
Intel ACPI Component Architecture
Num  Test_Description    Status                  Remaining  LifeTime(hours) LBA_of_first_error
ASL Optimizing Compiler version 20060113 [Jan 22 2006]
# 1  Short offline      Completed without error      00%      952        -
Copyright (C) 2000 - 2006 Intel Corporation
# 2  Conveyance offline  Completed without error      00%      951        -
Supports ACPI Specification Revision 3.0a
# 3 Short offline      Completed without error      00%      951        -
# 4  Short offline      Completed without error      00%      875        -
</pre>


Nell'esempio si pu� vedere che sono stati effettuati 4 test di cui tre di tipo ''short'' e uno di tipo ''conveyance''. Nessuno di loro ha dato esito negativo.
dsdt.dsl  290:    Method (\_WAK, 1, NotSerialized)
Warning  2078 -                ^ Reserved method must return a value (_WAK)


=== Effettuare manualmente i test ===
dsdt.dsl  318:            Store (Local0, Local0)
Error    1048 -                        ^ Method local variable is not initialized (Local0)


E' possibile effettuare dei test pi� o meno approfonditi sul disco. Alcuni test si possono effettuare con l'HD montato e funzionate, ed il test stesso avr� un impatto minimo o nullo sulle prestazioni del sistema.
dsdt.dsl  323:            Store (Local0, Local0)
Error    1048 -                        ^ Method local variable is not initialized (Local0)


Per effettuare un test:
dsdt.dsl  2368:             Store (Local0, Local0)
Error    1048 -                        ^ Method local variable is not initialized (Local0)


  # smartctl -t tipo_test /dev/hda
ASL Input: dsdt.dsl - 4804 lines, 160190 bytes, 1781 keywords
Compilation complete. 3 Errors, 1 Warnings, 0 Remarks, 465 Optimizations
</pre>


dove ''<tt>tipo_test</tt>'' pu� essere:
in sostanza, c'è un errore ripetuto identico tre volte (<code>Error 1048</code>), oltre ad un warning. Andiamo a vedere le sezioni incriminate. La prima è:
<pre>
Scope (\_SI)
{
    Method (_MSG, 1, NotSerialized)
    {
        Store (Local0, Local0)
    }
    Method (_SST, 1, NotSerialized)
    {
        Store (Local0, Local0)
    }
}
</pre>
Come si vede viene utilizzata due volte la variabile <code>Local0</code>, ma non viene mai dichiarata.


;<tt>short</tt>: effettua un test sul disco di durata inferiore a 10 minuti, pu� essere eseguito durante il normale funzionamento e non impatta le prestazioni. Questo test controlla le performace meccaniche ed elettriche del disco, oltre che le performance in lettura.
Vediamo di capire almeno un minimo il significato di questo pezzo di codice.
La funzione <code>Store</code> è una funzione di assegnazione verso destra: alla variabile a destra viene assegnato il valore (o il valore della variabile) che si trova a sinistra.  


;<tt>long</tt>: effettua un test di durata da 40 minuti ad un ora (a seconda del disco). Pu� essere effettuato durante il normale funzionamento del disco e non ha impatto sulle prestazioni. Questo test � una versione pi� estesa dello ''short test''.
In questo caso, però, è evidente che questa assegnazione è del tutto inutile, perché viene assegnato alla variabile <code>Local0</code> il valore che ha già, quindi per correggere l'errore non faccio altro che cancellare l'istruzione commentandola:
<pre>
Scope (\_SI)
{
    Method (_MSG, 1, NotSerialized)
    {
//        Store (Local0, Local0)
    }
    Method (_SST, 1, NotSerialized)
    {
//        Store (Local0, Local0)
    }
}
</pre>
Come si vede i commenti sono marcati come in C.
 
Facendo questa correzione anche nelle altre posizioni segnalate vengono eliminati tutti gli errori, quindi passiamo al warning. Il codice è questo:
<pre>
Method (\_WAK, 1, NotSerialized)
{
    Store (0xFF, DBG1)
    SALD (0x00)
    SFAN (0xFF)
    Notify (\_SB.PCI0.PX40.UAR1, 0x00)
    If (OSFL)
    {
        Notify (\_SB.PWRB, 0x02)
    }
    Else
    {
        If (LEqual (RTCW, 0x00))
        {
            Notify (\_SB.PWRB, 0x02)
        }
    }
    Notify (\_SB.PCI0.USB0, 0x00)
    Notify (\_SB.PCI0.USB1, 0x00)
    Notify (\_SB.PCI0.USB2, 0x00)
    Notify (\_SB.PCI0.USB3, 0x00)
}
</pre>
Le ultime righe mi danno la prova che l'errore ha a che fare con le porte USB, come avevo già notato.  


;<tt>conveyance</tt>: effettua un test di alcuni minuti atto a scoprire difetti dovuti ad incurie nel trasporto dell'HD. Pu� essere eseguito durante il normale funzionamento dell'HD.
Cercando in rete scopro che il metodo <code>\_WAK</code>, che è una funzione utilizzata al risveglio da uno stato di risparmio energetico (o di spegnimento), deve restituire un valore, che indichi se l'operazione di risveglio è riuscita o meno.


Esistono anche altri tipi di test per i quali si rimanda alla simpatica pagina di manuale: '''<tt>man smartctl</tt>'''.
Una possibile diagnosi del mio problema, a questo punto, è che in certi casi durante il boot viene richiamato questo metodo, e il sistema si blocca in attesa di un risultato, che però non viene mai restituito. (N.d.A.: la diagnosi è evidentemente sbagliata, perché il problema persiste :()


I risultati di questi test vengono riportati nella parte finale dell'output di <code>smartctl -a /dev/hda</code>, come notato in precedenza.
Io non ho idea di come reperire, nel codice, l'informazione sull'esito dell'inizializzazione delle porte USB, quindi non mi è possibile correggere il codice in modo che assolva alla funzione per cui è stato scritto, ma posso usare un workaround, e fare in modo che restituisca comunque un esito positivo.  


=== Controllo automatizzato ===
Per fare questo si trova (in rete), senza entrare nei dettagli, che è sufficiente aggiungere alla fine del metodo, subito prima dell'ultima parentesi graffa, la riga
<pre>
Return(Package(0x02){0x00, 0x00})
</pre>
Dopo le correzioni il codice viene ricompilato senza errori né warning :D


E' possibile attivare il demone '''<tt>smartd</tt>''' fornito dal pacchetto <tt>smartmontools</tt> per monitorare in continuazione lo stato di saluto dell'HD e notificare ogni anomalia immediatamente tramite syslog.
Ora però mi viene una curiosità, e mi metto a cercare nel codice la scritta "Microsoft". Questo è quello che ne viene fuori:
<pre>
Method (\_SB.PCI0._INI, 0, NotSerialized)
{
    If (STRC (\_OS, "Microsoft Windows"))
    {
        Store (0x56, SMIP)
    }
    Else
    {
        If (STRC (\_OS, "Microsoft Windows NT"))
    {
        Store (0x58, SMIP)
        Store (0x00, OSFX)
        Store (0x00, OSFL)
    }
    Else
    {
    Store (0x57, SMIP)
    Store (0x02, OSFX)
    Store (0x02, OSFL)
    }
}
</pre>
Anche senza conoscere il linguaggio, il codice è facilmente interpretabile: "se il Sistema Operativo si chiama 'Microsoft Windows' assegna il valore (esadecimale) <code>0x56</code> alla variabile <code>SMIP</code>, se invece si chiama 'Microsoft Windows NT' assegna <code>0x58</code> alla variabile <code>SMIP</code> e zero alle variabili <code>OSFX</code> e <code>OSFL</code>; se il S.O. è diverso da quelli elencati assegna alle tre variabili, rispettivamente, <code>0x57</code>, <code>0x02</code> e <code>0x02</code>".


Normalmente il demone � disabilitato. Per abilitarlo bisogna editare il file <tt>/etc/default/smartmontools</tt> e decommentare la riga:
Per qualche motivo a me ignoto chi ha impostato questa DSDT ha fatto in modo di cambiare le funzionalità del sottosistema ACPI a seconda del S.O. che si usa. Poiché questo non mi rende particolarmente felice, ho modificato il codice in questo modo, eliminando di fatto il controllo:
<pre>
Method (\_SB.PCI0._INI, 0, NotSerialized)
{
//   If (STRC (\_OS, "Microsoft Windows"))
//    {
//        Store (0x56, SMIP)
//    }
//    Else
//    {
//        If (STRC (\_OS, "Microsoft Windows NT"))
//    {
        Store (0x58, SMIP)
        Store (0x00, OSFX)
        Store (0x00, OSFL)
//    }
//    Else
//    {
//    Store (0x57, SMIP)
//    Store (0x02, OSFX)
//    Store (0x02, OSFL)
//    }
}
</pre>


start_smartd=yes
Ora il mio sistema funziona un pochino meglio :-)


Dobbiamo inoltre configurare smartd per deciderne il suo comportamento. A tal scopo editiamo il file <tt>/etc/smartd.conf</tt>. Leggendo i commenti nel file e l'amichevole pagina di manuale (<tt>man smartd.conf</tt>) � possibile scegliere quali parametri <tt>smartd</tt> debba monitorare, programmare dei test automatici, e decidere quali azioni intraprendere in caso di errore.
Aggiornamento: ricontrollando il codice ho notato che le tre variabili <code>SMIP</code>, <code>OSFX</code> e <code>OSFL</code> vengono inizializzate altrove, e quindi, in sostanza, il presente codice è inutile (se non dannoso ;-)), quindi l'ho semplicemente eliminato.


Nel mio caso ho inserito solo la seguente linea:


/dev/hda -a -o on -S on
Vorrei far notare che le correzioni che sono state fatte <b>non sono</b> delle <b>vere</b> correzioni, ma dei workaround: non ci si assicura che il codice faccia quel che deve fare, ma solo che non ci siano errori formali.


che attiva il monitoraggio di tutti (<tt>-a</tt>) i parametri, abilitia l' ''automatic online data collection'' (<tt>-o on</tt>), e abilita il salvataggio degli attributi (<tt>-S on</tt>) in modo che le informazioni di log di SMART vengano memorizzare nella FLASH del disco e siano disponibili anche dopo il riavvio.
Purtroppo la correzione <b>vera</b> di questi errori è al di là delle nostre possibilità, perché richiede, oltre alla conoscenza del linguaggio di programmazione, una conoscenza approfondita di come si comporta il nostro hardware, e nella grande maggioranza dei casi queste informazioni sono tenute segrete.
== Verifica di settori corrotti ==


L'utility <tt>'''badblocks'''</tt> permette di fare un controllo di basso livello per vedere se su una partizione sono presenti dei settori danneggiati.
== Aggiornare il Kernel ==


I moderni HD IDE fanno un controllo automatico degli errori e sono in grado di segnare dei settori corrotti che di conseguenza non verranno pi� usati. Questo rende in parte inutile <tt>badblocks</tt>, ma se si effettua un controllo e dei settori risultano danneggiati vuol dire che probabilmente la superficie del disco contiene cos� tanti settori danneggiati che la circuiteria di controllo non � pi� in gradio di gestirli.
Come abbiamo già detto, è possibile inserire la tabella DSDT generata in modo statico nel kernel, oppure renderla disponibili tramite initrd.


Per effettuare un controllo con <tt>badblocks</tt> smontiamo la partizione ed eseguiamo:
*:Il primo metodo prevede di includere la DSDT nel kernel. Questo comporta la ricompilazione del kernel al termine della procedura. Se usate questo metodo avete bisogno del file '''dsdt.hex'''.


# badblocks -b dimensione_blocco /dev/hdaX
*:Il secondo metodo prevede di passare la DSDT al kernel durante il caricamento nella fase di boot tramite initrd. Se usate questo metodo avete bisogno del file '''DSDT.aml'''.


dove <tt>/dev/hdaX</tt> la partizione da controllare. Il parametro <tt>dimensione_blocco</tt> la dimensione del blocco usata dal filesytem espresso in byte. Di solito 4096 (ovvero 4KB), per controllare potete usare:


# disktype /dev/hda
Il metodo initrd è probabilmente preferibile, soprattutto se dovete fare diversi cambiamenti alla vostra DSDT, perché non richiede la ricompilazione del kernel per ogni nuova DSDT generata.


Per le ulteriori opzioni di <tt>badblocks</tt> si rimanda all'amichevole pagina di manuale, ma '''attenzione: l'opzione <tt>-w</tt> distrugger� tutti i dati sulla vostra partizione'''. Non usatela se non volete che ci� accada.
=== Installazione Metodo statico ===


Se trovate dei settori danneggiati conviene cambiare immediatamente HD. Sebbene ci sia una piccola probabilit� che l'errore sia isolato (dovuto ad esempio ad uno sbalzo di tensione) � molto pi� probabile che l'HD si stia progressivamente danneggiando e presto ci saranno dei nuovi settori danneggiati. Comunque se volete giocare alla roulette russa con i vostri dati siete liberi di farlo :-P.
È necessario applicare una patch al kernel per far sì che sia in grado di leggere la nuova DSDT.
Per fare questo ci spostiamo nella directory dove sono presenti i sorgenti:
<pre>
$ cd /usr/src/linux-2.6.8
$ patch -p1 < /percorso_dove_avete_salvato_la_patch
</pre>


== Backup di emergenza ==
Se non appaiono errori, significa che la patch è stata applicata correttamente.


Per effettuare un backup di emergenza di una partizione corrotta il tool pi� efficace � '''[http://www.gnu.org/software/ddrescue/ddrescue.html GNU ddrescue]''' (da non confondere con il simile ma meno potente <tt>[http://www.garloff.de/kurt/linux/ddrescue/ dd_rescue]</tt>). Per installare GNU ddrescue in debian basta installare il pacchetto <tt>gddrecue</tt>.
Copiamo il file dsdt.hex, rinominandolo in dsdt_table.h, nella directory dei sorgenti del kernel:
<pre>
$ cp dsdt.hex /usr/src/linux-2.6.8/include/acpi/dsdt_table.h
</pre>


GNU ddrescue pu� effettuare backup di singoli file o di intere partizioni, riconoscendo ad aggirando i settori danneggiati. Pu� essere interrotto in qualsiasi momento, riprendere la copia da punto in cui � stato interrrotto e pu� fare il ''merge'' dei file se si hanno pi� copie degli stessi file corrotti.
Infine ricompiliamo il kernel. Se non ci sono errori al prossimo avvio del PC il supporto ACPI è caricato correttamente senza alcun problema.


Il suo uso � vagamente simile al classico '''<tt>dd</tt>''':
=== Installazione Metodo initrd ===


# ddrescue ddrescue [OPTIONS] INFILE OUTFILE [LOGFILE]
Se usate un kernel standard Debian non è necessario ricompilare il kernel: è sufficiente posizionare la tabella DSDT nel posto giusto e ricreare l'initrd o l'initramfs.
Per fare questo dovete prima verificare se il vostro kernel usa l'initrd o l'initramfs.
I kernel Debian standard usano l'initramfs a partire dalla versione 2.6.14 compresa, ma per essere sicuri è sufficiente usare il comando <code>file</code>.
Per esempio nel mio sistema ho:
<pre>
$ file /boot/initrd.img-2.6.12-1-686-smp
/boot/initrd.img-2.6.12-1-686-smp: Linux Compressed ROM File System data, little endian \
size 5046272 version #2 sorted_dirs CRC 0x5c015a8f, edition 0, 2920 blocks, 338 files
</pre>
che è un tipico initrd Debian e usa il cramfs, e anche
<pre>
$ file /boot/initrd.img-2.6.15-1-686-smp
/boot/initrd.img-2.6.15-1-686-smp: gzip compressed data, from Unix, max compression
</pre>
che invece è un initramfs.


Per una lista completa delle opzioni si rimanda al manuale: <tt>info ddrescue</tt>.
Distro diverse da Debian non usano il cramfs, e può darsi che a questa prima analisi si trovi comunque un file compresso con <code>gzip</code>: per indagare oltre è sufficiente decomprimere una copia del file (notate l'aggiunta del suffisso .gz, senza il quale <code>gunzip</code> rifiuta di decomprimere il file): l'initramfs è un archivio <code>cpio</code>.


Riporto un semplice esempio di utilizzo:
<pre>
$ cp /boot/initrd.img-2.6.15-1-686-smp initramfs.gz
$ gunzip initramfs.gz
$ file initramfs
initramfs: ASCII cpio archive (SVR4 with no CRC)
</pre>


# ddrescue -r3 /dev/hda3 /dev/hdb2 logfile
Se usate l'initrd (da root):
<pre>
# cp DSDT.aml /etc/mkinitrd/DSDT
# mkinitrd -o initrd-<versione>  <versione>
</pre>
in cui <code><versione></code> è il nome della directory che contiene i moduli, e che trovate in <code>/lib/modules/</code>.


il precedente comando copier� la partizione hda3 in hdb2 (distruggengo gli eventuali dati ivi presenti) provando a leggere tre volte i settori danneggiati e usando <tt>logfile</tt> come file di log.
Se usate l'initramfs (sempre da root):
<pre>
# cp DSDT.aml /etc/mkinitramfs/DSDT.aml
# mkinitramfs -o initrd-<versione>  <versione>
</pre>
con le stesse avvertenze di prima.


Ora possiamo eseguire sulla copia i normali tool di ripristino del nostro filesystem (<tt>fsck.*</tt>).
Se il vostro kernel non comprende la patch che gli permette di leggere la DSDT nell'initrd, dovete ricompilarlo. Prima però applicate la patch, spostandovi nella directory dove sono presenti i sorgenti:
<pre>$ cd /usr/src/linux-2.6.8
$ patch -p1 < / percorso_dove_avete_salvato_la_patch</pre>


== Strumenti per il ripristino dei dati ==
Al momento in cui si scrive, se usate l'initramfs vi serve anche una seconda patch che trovate allo stesso indirizzo della prima (in futuro verranno probabilmente unificate).
''In questa sezione verr� solo accennato il problema di ripristino dati. Lo scopo � quello di dare solo un panoramica iniziale del problema che possa servire come orientamento per ulteriori approfondimenti''.


Prima di ogni operazione di ripristino dati � fortemente consigliato effettuare una copia della partizione (vedi sezione precedednte) e operare sulla copia.
Prima di compilare è necessario assicurarsi che i seguenti moduli (ramdisk e initrd) siano compilati staticamente nel kernel:
<pre>
Device Drivers --->
    Block Devices --->
        <*> RAM disk support
        [*] Initial RAM disk (initrd) support
</pre>


Il ripristino dei dati pu� variare a seconda del filesytem utilizzato e di come si sono perduti i dati. Ad esempio se si vogliono recuperare dei file cancellati accidentalmente da una partizione ext2 ci sono delle buone possibilit� di usare il tool <tt>[http://recover.sourceforge.net/linux/recover/ recover]</tt> (presente nell'omonimo pacchetto debian). Il tool <tt>recover</tt> non pu� essere usato su partizione ext3. Purtroppo, oltre a <tt>recover</tt> per ext2, non conosco nessun altro tool free e automatico per il recupero dei file accidentamente cancellati.
Inoltre è necessario controllare che l’opzione '''Read DSDT from initrd''' sia selezionata nel menu delle opzioni ACPI:
<pre>
Power management options (ACPI, APM) --->  
    ACPI (Advanced Configuration and Power Interface) Support --->  
        [*] Read DSDT from initrd
</pre>


In mancaza di strumenti automatici si usa la cos� detta ''Unix Way''. Ovvero si usano i tradizionali strumenti unix per accedere direttamente al device ed estrarre i dati utili. Ad esempio se si devono recuperare file di testo o documenti non binari (per intenderci non foto o musica o programmi compilati) si possono usare <tt>egrep</tt> e <tt>strings</tt>.
Se queste opzioni non sono abilitate, abilitarle e ricompilare il kernel. Se sono già abilitate non è necessario ricompilare il kernel ;-).  


Se si vogliono recuperare foto jpeg � possibile usare <tt>'''recoverjpeg'''</tt> che cerca di identificare gli header jepeg in una immagine di file system.
Ora il kernel è pronto ad accettare la DSDT con initrd.
Se non avete a disposizione i tool mkinitrd e/o mkinitramfs che Debian mette a disposizione è necessario modificare l'initrd che avete, ma prima di farlo è fortemente consigliato di farne una copia di backup:
<pre>
# cp /boot/initrd-kernel-2.6.8.img /boot/initrd-kernel-2.6.8.img.bak
# echo -n "INITRDDSDT123DSDT123" >> /boot/initrd-kernel-2.6.8.img
# cat DSDT.aml >> /boot/initrd-kernel-2.6.8.img
</pre>


E' fortemente cosigliata la lettura dei documenti elencati di seguito nella sezione ''Links->Articoli'' per degli esempi pratici sul recupero dati su filesystem ext2 e reiserfs (ma le informazioni possono servire di spunto per operare anche su altri file system).
Riavviare e controllare se il supporto ACPI funziona. Ricordarsi di aggiornare i bootloader!
== Links ==
=== Articoli ===
* [http://www.linuxquestions.org/linux/answers/Hardware/ReiserFS_Data_Recovery_Tips ReiserFS Data Recovery Tips]


* [http://ildp.pluto.it/HOWTO/Ext2fs-Undeletion.html Linux Ext2fs Undeletion mini-HOWTO]
== Siti ufficiali dei progetti ==
* [http://www.linuxjournal.com/article/8366 How a Corrupted USB Drive Was Saved by GNU/Linux]


=== Strumenti Utili ===
* http://acpi.sourceforge.net
* [http://smartmontools.sourceforge.net/ smartmontools Home Page]
* http://www.acpi.info/
* [http://www.gnu.org/software/ddrescue/ddrescue.html GNU ddrescue]
* [http://www.partimage.org/index.en.html Partimage]
* [http://www.cgsecurity.org/index.html?testdisk.html TestDisk]

Versione attuale delle 09:43, 8 mag 2016

Emblem-important.png Attenzione. Questa guida è obsoleta. Viene mantenuta sul Wiki solo per motivi di natura storica e didattica.


Introduzione

ACPI (Advanced Configuration and Power Interface) è uno standard industriale aperto che definisce l'interfaccia tra S.O. e BIOS per l'amministrazione e la configurazione delle risorse di un PC. ACPI prevede che le informazioni a basso livello sul sistema (batteria, luminosità LCD, pulsanti Fn, ecc.) siano contenute nella DSDT (Differentiated System Description Table).

Il problema principale del supporto ad ACPI in Linux risiede nella presenza di errori (ma anche di controlli espliciti su alcune caratteristiche peculiari del S.O. soprastante) nella tabella DSDT: purtroppo, molti fornitori di hardware non sono in grado, o non vogliono fornire tabelle DSDT completamente funzionali secondo gli standard ACPI.

Per questo motivo, per utilizzare appieno le possibilità offerte da alcuni PC, soprattutto laptop, è necessario correggere la DSDT e istruire il kernel affinché nel processo di boot carichi la tabella fornita da noi invece di quella fornita dal BIOS.

Aggiornamento del BIOS

Per cominciare è indispensabile aggiornare il BIOS con l’ultima versione disponibile, sperando che la nuova versione contenga una tabella DSDT con meno errori della precedente :P.

Installazione nel kernel del supporto ACPI

Per poter utilizzare ACPI è necessario disporre di un kernel in cui sia stato abilitato il supporto ACPI. Praticamente tutte le distribuzioni forniscono kernel precompilati con il supporto ACPI attivato. Nel caso, però, vi trovaste a dover (o voler) compilare autonomamente un kernel con il supporto ACPI, le voci necessarie sono le seguenti:

ACPI (Advanced Configuration and Power Interface) Support ---> 
    ACPI Support ---> 
        <*> AC Adapter
        <*> Battery
        <*> Button
        <*> Processor

Strumenti per lavorare con le DSDT

Per poter leggere e compilare una DSDT è necessario il compilatore ASL di Intel, che in Debian esiste già precompilato a partire da Etch; altrimenti è liberamente disponibile per il download a questo indirizzo.

Per utilizzare la DSDT corretta sono disponibili due metodi:

  • il primo prevede l'applicazione di una patch per il kernel e l'inserimento della nuova DSDT direttamente nel kernel, che quindi sarà da ricompilare ogni volta che si fanno cambiamenti alla DSDT;
  • il secondo inserisce la nuova DSDT all'interno dell'initrd, e quindi non necessita la ricompilazione del kernel, a patto che nel vostro kernel sia stata inclusa una patch apposita. Al momento la patch menzionata è inclusa nei kernel delle maggiori distribuzioni (sicuramente in Debian, Ubuntu, Suse, e Mandriva).

Installare il compilatore ASL

Uno dei motivi per cui le DSDT sono spesso difettose è che vengono compilate con il compilatore fornito da Microsoft, invece che con quello fornito da Intel. Curiosamente i sistemi Microsoft riescono ad evitare gli errori commessi dal compilatore della stessa società, mentre, come si può immaginare, la stessa cosa non succede per Linux.

Per installare il compilatore Intel è sufficiente avere nel sources.list un repository per Etch, ed impartire, da root, il comando

# aptitude install iasl

Se invece avete scaricato i sorgenti, per avere il compilatore ASL funzionante è necessario compilarlo:

$ tar -zxvf acpica-unix-20050624.tar.gz
$ cd acpica-unix-20050624/compiler
$ make

Ottenere una DSDT

È possibile ottenere la DSDT attualmente installata per poi correggere gli eventuali errori e problemi, copiandola da un file reso appositamente disponibile dal filesystem virtuale /sys:

# cat /sys/firmware/acpi/tables/DSDT > dsdt.dat

Ciò creerà un file dsdt.dat che contiene la DSDT compilata. Per poterne leggere il contenuto è necessario decompilarla con il compilatore ASL appena installato:

$ iasl -d dsdt.dat

Verrà generato un file di testo denominato dsdt.dsl, che contiene la DSDT. Questo file può essere aperto con un normale editor di testi e modificato a seconda delle esigenze e dei problemi riscontrati.

Per vedere quali sono i problemi spesso è sufficiente ricompilare il file ottenuto: il compilatore ASL fornirà una serie di warning sulle ottimizzazioni che è possibile fare (e le farà automaticamente) ed, eventualmente, segnalerà degli errori, la cui soluzione può essere, ad esempio, ricercata su Internet.

Ad ogni modo una lettura del codice della DSDT può essere istruttiva. Il linguaggio è abbastanza simile al C e con qualche minima conoscenza è possibile comprendere i principali costrutti logici.

Nel codice di alcune DSDT è stato trovato un controllo (if .. then) sulla lunghezza del nome del S.O. soprastante (17 lettere, proprio come "Microsoft Windows") come requisito per l'attivazione di alcune funzioni dell'ACPI.

Una volta corretti gli errori ricompilare il file dsdt.dsl.

$ iasl -tc dsdt.dsl

Verranno generati due file dalla compilazione:

  • dsdt.hex
  • DSDT.aml
Warning.png ATTENZIONE
È possibile scaricare una custom DSDT già pronta e corretta da Internet per molti portatili in commercio: http://acpi.sourceforge.net/dsdt/tables


Un esempio: la mia DSDT

Nel mio sistema (PC desktop, scheda madre Chaintech) ho da qualche tempo un problema con l'inizializzazione delle porte USB, tale che circa nel 40% dei casi (ma mai due volte di seguito) il PC si blocca durante il boot, e devo riavviare forzatamente.

Per cercare di risolvere la cosa ho analizzato la mia tabella DSDT. L'ho estratta, e quando ho provato a ricompilarla ho avuto il seguente output:

$ iasl -tc dsdt.dsl

Intel ACPI Component Architecture
ASL Optimizing Compiler version 20060113 [Jan 22 2006]
Copyright (C) 2000 - 2006 Intel Corporation
Supports ACPI Specification Revision 3.0a

dsdt.dsl   290:     Method (\_WAK, 1, NotSerialized)
Warning  2078 -                 ^ Reserved method must return a value (_WAK)

dsdt.dsl   318:             Store (Local0, Local0)
Error    1048 -                         ^ Method local variable is not initialized (Local0)

dsdt.dsl   323:             Store (Local0, Local0)
Error    1048 -                         ^ Method local variable is not initialized (Local0)

dsdt.dsl  2368:             Store (Local0, Local0)
Error    1048 -                         ^ Method local variable is not initialized (Local0)

ASL Input:  dsdt.dsl - 4804 lines, 160190 bytes, 1781 keywords
Compilation complete. 3 Errors, 1 Warnings, 0 Remarks, 465 Optimizations

in sostanza, c'è un errore ripetuto identico tre volte (Error 1048), oltre ad un warning. Andiamo a vedere le sezioni incriminate. La prima è:

Scope (\_SI)
{
    Method (_MSG, 1, NotSerialized)
    {
        Store (Local0, Local0)
    }
    Method (_SST, 1, NotSerialized)
    {
        Store (Local0, Local0)
    }
}

Come si vede viene utilizzata due volte la variabile Local0, ma non viene mai dichiarata.

Vediamo di capire almeno un minimo il significato di questo pezzo di codice. La funzione Store è una funzione di assegnazione verso destra: alla variabile a destra viene assegnato il valore (o il valore della variabile) che si trova a sinistra.

In questo caso, però, è evidente che questa assegnazione è del tutto inutile, perché viene assegnato alla variabile Local0 il valore che ha già, quindi per correggere l'errore non faccio altro che cancellare l'istruzione commentandola:

Scope (\_SI)
{
    Method (_MSG, 1, NotSerialized)
    {
//        Store (Local0, Local0)
    }
    Method (_SST, 1, NotSerialized)
    {
//        Store (Local0, Local0)
    }
}

Come si vede i commenti sono marcati come in C.

Facendo questa correzione anche nelle altre posizioni segnalate vengono eliminati tutti gli errori, quindi passiamo al warning. Il codice è questo:

Method (\_WAK, 1, NotSerialized)
{
    Store (0xFF, DBG1)
    SALD (0x00)
    SFAN (0xFF)
    Notify (\_SB.PCI0.PX40.UAR1, 0x00)
    If (OSFL)
    {
        Notify (\_SB.PWRB, 0x02)
    }
    Else
    {
        If (LEqual (RTCW, 0x00))
        {
            Notify (\_SB.PWRB, 0x02)
        }
    }
    Notify (\_SB.PCI0.USB0, 0x00)
    Notify (\_SB.PCI0.USB1, 0x00)
    Notify (\_SB.PCI0.USB2, 0x00)
    Notify (\_SB.PCI0.USB3, 0x00)
}

Le ultime righe mi danno la prova che l'errore ha a che fare con le porte USB, come avevo già notato.

Cercando in rete scopro che il metodo \_WAK, che è una funzione utilizzata al risveglio da uno stato di risparmio energetico (o di spegnimento), deve restituire un valore, che indichi se l'operazione di risveglio è riuscita o meno.

Una possibile diagnosi del mio problema, a questo punto, è che in certi casi durante il boot viene richiamato questo metodo, e il sistema si blocca in attesa di un risultato, che però non viene mai restituito. (N.d.A.: la diagnosi è evidentemente sbagliata, perché il problema persiste :()

Io non ho idea di come reperire, nel codice, l'informazione sull'esito dell'inizializzazione delle porte USB, quindi non mi è possibile correggere il codice in modo che assolva alla funzione per cui è stato scritto, ma posso usare un workaround, e fare in modo che restituisca comunque un esito positivo.

Per fare questo si trova (in rete), senza entrare nei dettagli, che è sufficiente aggiungere alla fine del metodo, subito prima dell'ultima parentesi graffa, la riga

Return(Package(0x02){0x00, 0x00})

Dopo le correzioni il codice viene ricompilato senza errori né warning :D

Ora però mi viene una curiosità, e mi metto a cercare nel codice la scritta "Microsoft". Questo è quello che ne viene fuori:

Method (\_SB.PCI0._INI, 0, NotSerialized)
{
    If (STRC (\_OS, "Microsoft Windows"))
    {
        Store (0x56, SMIP)
    }
    Else
    {
        If (STRC (\_OS, "Microsoft Windows NT"))
    {
        Store (0x58, SMIP)
        Store (0x00, OSFX)
        Store (0x00, OSFL)
    }
    Else
    {
    Store (0x57, SMIP)
    Store (0x02, OSFX)
    Store (0x02, OSFL)
    }
}

Anche senza conoscere il linguaggio, il codice è facilmente interpretabile: "se il Sistema Operativo si chiama 'Microsoft Windows' assegna il valore (esadecimale) 0x56 alla variabile SMIP, se invece si chiama 'Microsoft Windows NT' assegna 0x58 alla variabile SMIP e zero alle variabili OSFX e OSFL; se il S.O. è diverso da quelli elencati assegna alle tre variabili, rispettivamente, 0x57, 0x02 e 0x02".

Per qualche motivo a me ignoto chi ha impostato questa DSDT ha fatto in modo di cambiare le funzionalità del sottosistema ACPI a seconda del S.O. che si usa. Poiché questo non mi rende particolarmente felice, ho modificato il codice in questo modo, eliminando di fatto il controllo:

Method (\_SB.PCI0._INI, 0, NotSerialized)
{
//    If (STRC (\_OS, "Microsoft Windows"))
//    {
//        Store (0x56, SMIP)
//    }
//    Else
//    {
//        If (STRC (\_OS, "Microsoft Windows NT"))
//    {
        Store (0x58, SMIP)
        Store (0x00, OSFX)
        Store (0x00, OSFL)
//    }
//    Else
//    {
//    Store (0x57, SMIP)
//    Store (0x02, OSFX)
//    Store (0x02, OSFL)
//    }
}

Ora il mio sistema funziona un pochino meglio :-)

Aggiornamento: ricontrollando il codice ho notato che le tre variabili SMIP, OSFX e OSFL vengono inizializzate altrove, e quindi, in sostanza, il presente codice è inutile (se non dannoso ;-)), quindi l'ho semplicemente eliminato.


Vorrei far notare che le correzioni che sono state fatte non sono delle vere correzioni, ma dei workaround: non ci si assicura che il codice faccia quel che deve fare, ma solo che non ci siano errori formali.

Purtroppo la correzione vera di questi errori è al di là delle nostre possibilità, perché richiede, oltre alla conoscenza del linguaggio di programmazione, una conoscenza approfondita di come si comporta il nostro hardware, e nella grande maggioranza dei casi queste informazioni sono tenute segrete.

Aggiornare il Kernel

Come abbiamo già detto, è possibile inserire la tabella DSDT generata in modo statico nel kernel, oppure renderla disponibili tramite initrd.

  • Il primo metodo prevede di includere la DSDT nel kernel. Questo comporta la ricompilazione del kernel al termine della procedura. Se usate questo metodo avete bisogno del file dsdt.hex.
  • Il secondo metodo prevede di passare la DSDT al kernel durante il caricamento nella fase di boot tramite initrd. Se usate questo metodo avete bisogno del file DSDT.aml.


Il metodo initrd è probabilmente preferibile, soprattutto se dovete fare diversi cambiamenti alla vostra DSDT, perché non richiede la ricompilazione del kernel per ogni nuova DSDT generata.

Installazione Metodo statico

È necessario applicare una patch al kernel per far sì che sia in grado di leggere la nuova DSDT. Per fare questo ci spostiamo nella directory dove sono presenti i sorgenti:

$ cd /usr/src/linux-2.6.8
$ patch -p1 < /percorso_dove_avete_salvato_la_patch

Se non appaiono errori, significa che la patch è stata applicata correttamente.

Copiamo il file dsdt.hex, rinominandolo in dsdt_table.h, nella directory dei sorgenti del kernel:

$ cp dsdt.hex /usr/src/linux-2.6.8/include/acpi/dsdt_table.h

Infine ricompiliamo il kernel. Se non ci sono errori al prossimo avvio del PC il supporto ACPI è caricato correttamente senza alcun problema.

Installazione Metodo initrd

Se usate un kernel standard Debian non è necessario ricompilare il kernel: è sufficiente posizionare la tabella DSDT nel posto giusto e ricreare l'initrd o l'initramfs. Per fare questo dovete prima verificare se il vostro kernel usa l'initrd o l'initramfs. I kernel Debian standard usano l'initramfs a partire dalla versione 2.6.14 compresa, ma per essere sicuri è sufficiente usare il comando file. Per esempio nel mio sistema ho:

$ file /boot/initrd.img-2.6.12-1-686-smp
/boot/initrd.img-2.6.12-1-686-smp: Linux Compressed ROM File System data, little endian \
size 5046272 version #2 sorted_dirs CRC 0x5c015a8f, edition 0, 2920 blocks, 338 files

che è un tipico initrd Debian e usa il cramfs, e anche

$ file /boot/initrd.img-2.6.15-1-686-smp
/boot/initrd.img-2.6.15-1-686-smp: gzip compressed data, from Unix, max compression

che invece è un initramfs.

Distro diverse da Debian non usano il cramfs, e può darsi che a questa prima analisi si trovi comunque un file compresso con gzip: per indagare oltre è sufficiente decomprimere una copia del file (notate l'aggiunta del suffisso .gz, senza il quale gunzip rifiuta di decomprimere il file): l'initramfs è un archivio cpio.

$ cp /boot/initrd.img-2.6.15-1-686-smp initramfs.gz
$ gunzip initramfs.gz
$ file initramfs
initramfs: ASCII cpio archive (SVR4 with no CRC)

Se usate l'initrd (da root):

# cp DSDT.aml /etc/mkinitrd/DSDT
# mkinitrd -o initrd-<versione>  <versione> 

in cui <versione> è il nome della directory che contiene i moduli, e che trovate in /lib/modules/.

Se usate l'initramfs (sempre da root):

# cp DSDT.aml /etc/mkinitramfs/DSDT.aml
# mkinitramfs -o initrd-<versione>  <versione> 

con le stesse avvertenze di prima.

Se il vostro kernel non comprende la patch che gli permette di leggere la DSDT nell'initrd, dovete ricompilarlo. Prima però applicate la patch, spostandovi nella directory dove sono presenti i sorgenti:

$ cd /usr/src/linux-2.6.8
$ patch -p1 < / percorso_dove_avete_salvato_la_patch

Al momento in cui si scrive, se usate l'initramfs vi serve anche una seconda patch che trovate allo stesso indirizzo della prima (in futuro verranno probabilmente unificate).

Prima di compilare è necessario assicurarsi che i seguenti moduli (ramdisk e initrd) siano compilati staticamente nel kernel:

Device Drivers ---> 
    Block Devices ---> 
        <*> RAM disk support 
        [*] Initial RAM disk (initrd) support

Inoltre è necessario controllare che l’opzione Read DSDT from initrd sia selezionata nel menu delle opzioni ACPI:

Power management options (ACPI, APM) ---> 
    ACPI (Advanced Configuration and Power Interface) Support ---> 
        [*] Read DSDT from initrd

Se queste opzioni non sono abilitate, abilitarle e ricompilare il kernel. Se sono già abilitate non è necessario ricompilare il kernel ;-).

Ora il kernel è pronto ad accettare la DSDT con initrd. Se non avete a disposizione i tool mkinitrd e/o mkinitramfs che Debian mette a disposizione è necessario modificare l'initrd che avete, ma prima di farlo è fortemente consigliato di farne una copia di backup:

# cp /boot/initrd-kernel-2.6.8.img /boot/initrd-kernel-2.6.8.img.bak
# echo -n "INITRDDSDT123DSDT123" >> /boot/initrd-kernel-2.6.8.img
# cat DSDT.aml >> /boot/initrd-kernel-2.6.8.img

Riavviare e controllare se il supporto ACPI funziona. Ricordarsi di aggiornare i bootloader!

Siti ufficiali dei progetti