1 760
contributi
mNessun oggetto della modifica |
|||
Riga 1: | Riga 1: | ||
==Introduzione== | ==Introduzione== | ||
ACPI ('''Advanced Configuration and Power Interface''') | 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 DSTD ('''Differentiated System Description Table'''). | ||
Il problema principale del supporto ad ACPI in linux risiede nella 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. | Il problema principale del supporto ad ACPI in linux risiede nella 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 | 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== | ==Aggiornamento del BIOS== | ||
Per cominciare | 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== | ==Installazione nel kernel del supporto ACPI== | ||
Per poter utilizzare 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: | ||
<pre>ACPI (Advanced Configuration and Power Interface) Support ---> | <pre>ACPI (Advanced Configuration and Power Interface) Support ---> | ||
Riga 21: | Riga 21: | ||
==Strumenti per lavorare con le DSDT== | ==Strumenti per lavorare con le DSDT== | ||
Per poter leggere e compilare una DSDT | Per poter leggere e compilare una DSDT è necessario il compilatore ASL di Intel, che in debian esiste già precompilato a partire da etch (attuale testing), altrimenti è liberamente disponibile per il download all'indirizzo: | ||
<pre>http://developer.intel.com/technology/iapc/acpi/downloads.htm</pre> | <pre>http://developer.intel.com/technology/iapc/acpi/downloads.htm</pre> | ||
Per utilizzare la DSDT corretta sono disponibili due metodi: 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 | Per utilizzare la DSDT corretta sono disponibili due metodi: 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 | 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). | ||
===Installare il compilatore ASL=== | ===Installare il compilatore ASL=== | ||
Uno dei motivi per cui le DSDT sono spesso difettose | 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 | Per installare il compilatore Intel è sufficiente avere nel <tt>sources.list</tt> un repository per etch, e impartire, da root, il comando | ||
<pre> | <pre> | ||
# aptitude install iasl | # aptitude install iasl | ||
</pre> | </pre> | ||
Se invece avete scaricato i sorgenti, per avere il compilatore ASL funzionante | Se invece avete scaricato i sorgenti, per avere il compilatore ASL funzionante è necessario compilarlo: | ||
<pre>$ tar -zxvf acpica-unix-20050624.tar.gz | <pre>$ tar -zxvf acpica-unix-20050624.tar.gz | ||
$ cd acpica-unix-20050624/compiler | $ cd acpica-unix-20050624/compiler | ||
Riga 42: | Riga 42: | ||
===Ottenere una DSDT=== | ===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 /proc: | |||
<pre>$ cat /proc/acpi/dsdt > dsdt.dat</pre> | <pre>$ cat /proc/acpi/dsdt > dsdt.dat</pre> | ||
Ciò creerà un file '''dsdt.dat''' che contiene la DSDT compilata. | |||
Per poterne leggere il contenuto | Per poterne leggere il contenuto è necessario decompilarla con il compilatore ASL appena installato: | ||
<pre>$ iasl -d dsdt.dat</pre> | <pre>$ iasl -d dsdt.dat</pre> | ||
Verrà generato un file di testo denominato '''dsdt.dsl''', che contiene la DSDT. Questo file può essere modificato con un normale editor di testi e modificato a seconda delle esigenze e dei problemi riscontrati. | |||
Per vedere quali sono i problemi spesso | 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 | 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 | 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'''. | Una volta corretti gli errori ricompilare il file '''dsdt.dsl'''. | ||
Riga 66: | Riga 66: | ||
*: DSDT.aml | *: DSDT.aml | ||
{{ Warningbox | | {{ Warningbox | È 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=== | ===Un esempio: la mia DSDT=== | ||
Riga 98: | Riga 98: | ||
</pre> | </pre> | ||
in sostanza, c' | in sostanza, c'è un errore ripetuto identico tre volte (<tt>Error 1048</tt>), oltre ad un warning. Andiamo a vedere le sezioni incriminate. La prima è: | ||
<pre> | <pre> | ||
Scope (\_SI) | Scope (\_SI) | ||
Riga 115: | Riga 115: | ||
Vediamo di capire almeno un minimo il significato di questo pezzo di codice. | Vediamo di capire almeno un minimo il significato di questo pezzo di codice. | ||
La funzione <tt>Store</tt> | La funzione <tt>Store</tt> è 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, | In questo caso, però, è evidente che questa assegnazione è del tutto inutile, perchè viene assegnato alla variabile <tt>Local0</tt> il valore che ha già, quindi per correggere l'errore non faccio altro che cancellare l'istruzione commentandola: | ||
<pre> | <pre> | ||
Scope (\_SI) | Scope (\_SI) | ||
Riga 133: | Riga 133: | ||
Come si vede i commenti sono marcati come in C. | 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 | Facendo questa correzione anche nelle altre posizioni segnalate vengono eliminati tutti gli errori, quindi passiamo al warning. Il codice è questo: | ||
<pre> | <pre> | ||
Method (\_WAK, 1, NotSerialized) | Method (\_WAK, 1, NotSerialized) | ||
Riga 158: | Riga 158: | ||
} | } | ||
</pre> | </pre> | ||
Le ultime righe mi danno la prova che l'errore ha a che fare con le porte USB, come avevo | 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 <tt>\_WAK</tt>, che | Cercando in rete scopro che il metodo <tt>\_WAK</tt>, 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, | 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 | 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 | 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> | <pre> | ||
Return(Package(0x02){0x00, 0x00}) | Return(Package(0x02){0x00, 0x00}) | ||
Riga 172: | Riga 172: | ||
Dopo le correzioni il codice viene ricompilato senza errori ne' warning :D | Dopo le correzioni il codice viene ricompilato senza errori ne' warning :D | ||
Ora | Ora però mi viene una curiosità, e mi metto a cercare nel codice la scritta "Microsoft". Questo è quello che ne viene fuori: | ||
<pre> | <pre> | ||
Method (\_SB.PCI0._INI, 0, NotSerialized) | Method (\_SB.PCI0._INI, 0, NotSerialized) | ||
Riga 196: | Riga 196: | ||
} | } | ||
</pre> | </pre> | ||
Anche senza conoscere il linguaggio, il codice | Anche senza conoscere il linguaggio, il codice è facilmente interpretabile: "se il Sistema Operativo si chiama 'Microsoft Windows' assegna il valore (esadecimale) <tt>0x56</tt> alla variabile <tt>SMIP</tt>, se invece si chiama 'Microsoft Windows NT' assegna <tt>0x58</tt> alla variabile <tt>SMIP</tt> e zero alle variabili <tt>OSFX</tt> e <tt>OSFL</tt>; se il S.O. è diverso da quelli elencati assegna alle tre variabili, rispettivamente, <tt>0x57</tt>, <tt>0x02</tt> e <tt>0x02</tt>". | ||
Per qualche motivo a me ignoto chi ha impostato questa DSDT ha fatto in modo di cambiare le | 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> | <pre> | ||
Method (\_SB.PCI0._INI, 0, NotSerialized) | Method (\_SB.PCI0._INI, 0, NotSerialized) | ||
Riga 225: | Riga 225: | ||
Ora il mio sistema funziona un pochino meglio :-) | Ora il mio sistema funziona un pochino meglio :-) | ||
Aggiornamento: ricontrollando il codice ho notato che le tre variabili <tt>SMIP</tt>, <tt>OSFX</tt> e <tt>OSFL</tt> vengono inizializzate altrove, e quindi, in sostanza, il presente codice | Aggiornamento: ricontrollando il codice ho notato che le tre variabili <tt>SMIP</tt>, <tt>OSFX</tt> e <tt>OSFL</tt> 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 <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. | 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. | ||
Purtroppo la correzione <b>vera</b> di questi errori | 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. | ||
==Aggiornare il Kernel== | ==Aggiornare il Kernel== | ||
Come abbiamo | 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 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'''. | ||
Riga 240: | Riga 240: | ||
Il metodo initrd | Il metodo initrd è probabilmente preferibile, particolarmente se dovete fare diversi cambiamenti alla vostra DSDT, perché non richiede la ricompilazione del kernel per ogni nuova DSDT generata. | ||
===Installazione Metodo statico=== | ===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: | Per fare questo ci spostiamo nella directory dove sono presenti i sorgenti: | ||
<pre> | <pre> | ||
Riga 250: | Riga 250: | ||
</pre> | </pre> | ||
Se non appaiono errori, significa che 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: | Copiamo il file dsdt.hex, rinominandolo in dsdt_table.h, nella directory dei sorgenti del kernel: | ||
Riga 257: | Riga 257: | ||
</pre> | </pre> | ||
Infine ricompiliamo il kernel. Se non ci sono errori al prossimo avvio del PC il supporto ACPI | 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=== | ===Installazione Metodo initrd=== | ||
Se usate un kernel standard Debian non | 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 | 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 <tt>file</tt>. | |||
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. | |||
Distro diverse da Debian non usano il cramfs, e può darsi che a questa prima analisi si trovi comunque un file compresso con <tt>gzip</tt>: per indagare oltre è sufficiente decomprimere una copia del file (notate l'aggiunta del suffisso .gz, senza il quale <tt>gunzip</tt> rifiuta di decomprimere il file): l'initramfs è un archivio <tt>cpio</tt>. | |||
<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> | |||
Se usate l'initrd (da root): | Se usate l'initrd (da root): | ||
<pre> | <pre> | ||
# cp | # cp DSDT.aml /etc/mkinitrd/DSDT | ||
# mkinitrd -o initrd-<versione> <versione> | # mkinitrd -o initrd-<versione> <versione> | ||
</pre> | </pre> | ||
in cui <tt><versione</tt> | in cui <tt><versione></tt> è il nome della directory che contiene i moduli, e che trovate in <tt>/lib/modules/</tt>. | ||
Se usate l'initramfs (sempre da root): | Se usate l'initramfs (sempre da root): | ||
<pre> | <pre> | ||
# cp | # cp DSDT.aml /etc/mkinitramfs/DSDT.aml | ||
# | # mkinitramfs -o initrd-<versione> <versione> | ||
</pre> | </pre> | ||
con le stesse avvertenze di prima. | 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 | 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 | <pre>$ cd /usr/src/linux-2.6.8 | ||
$ patch -p1 < / percorso_dove_avete_salvato_la_patch</pre> | $ patch -p1 < / percorso_dove_avete_salvato_la_patch</pre> | ||
Riga 283: | Riga 305: | ||
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). | 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 | Prima di compilare è necessario assicurarsi che i seguenti moduli (ramdisk e initrd) siano compilati staticamente nel kernel: | ||
<pre> | <pre> | ||
Device Drivers ---> | Device Drivers ---> | ||
Riga 291: | Riga 313: | ||
</pre> | </pre> | ||
Inoltre | Inoltre è necessario controllare che l’opzione '''Read DSDT from initrd''' sia selezionata nel menu delle opzioni ACPI: | ||
<pre> | <pre> | ||
Power management options (ACPI, APM) ---> | Power management options (ACPI, APM) ---> | ||
Riga 298: | Riga 320: | ||
</pre> | </pre> | ||
Se queste opzioni non sono abilitate, abilitarle e ricompilare il kernel. Se sono | Se queste opzioni non sono abilitate, abilitarle e ricompilare il kernel. Se sono già abilitate non è necessario ricompilare il kernel ;-). | ||
Ora 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 | 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> | <pre> | ||
# cp /boot/initrd-kernel-2.6.8.img /boot/initrd-kernel-2.6.8.img.bak | # cp /boot/initrd-kernel-2.6.8.img /boot/initrd-kernel-2.6.8.img.bak | ||
Riga 318: | Riga 340: | ||
Rivisto e corretto: [[Utente:Tindal|Tindal]] 17:37, Gen 27, 2006 (EST) | Rivisto e corretto: [[Utente:Tindal|Tindal]] 17:37, Gen 27, 2006 (EST) | ||
[[Categoria:Laptop]] |
contributi