HOWTO Corriger les problèmes courants liés à l'ACPI

Un article de Gentoo Linux Wiki.

Cet article est une ébauche. Vous pouvez l'aider à s'enrichir en le complétant.

Cet article n'a pas été complètement traduit.

Cet article fait partie des HOWTOs.
Méthodes d'installation CD Live Noyau et matériel Portables et Notebooks Portage Système Réseaux et Services Serveur X Logiciels fréquemment utilisés Autres

Sommaire

[modifier] Introduction

Pendant plusieurs semaines, je me suis battu avec l'ACPI de mon portable (Gateway 200X). Le problème : un DSDT buggé et un ECDT inexistant. Quelques recherches sur le web m'ont vite montré que ce n'était pas nouveau, bien au contraire. Malheureusement, certains systèmes d'exploitation sont plus tolérants qu'ils ne devraient vis-à-vis des spécifications ACPI, ce qui pose des problèmes à tous les autres. La seule solution viable est donc de fournir un DSDT et un ECDT corrects au noyau.

La première fois que j'ai lu ça, j'ai pris peur. Mais finalement, corriger le problème n'a pas été si difficile. Le plus dur est finalement de le diagnostiquer; ensuite (dans mon cas) le reste coule de source. Voici comment faire, si vous aussi vous rencontrez des problèmes avec l'ACPI sur votre machine. Much of this is taken from this post, but I've weeded out some other stuff that was more specific to my machine.

NOTE: Suivre ce HOWTO vous conduira à patcher votre noyau, et éventuellement à écraser le initrd existant. N'oubliez pas de sauvegarder les fichiers les plus importants !

[modifier] Definitions

ACPI Machine Language (AML)

D'après les spécifications ACPI (Page 13):

Pseudocode for a virtual machine supported by an ACPI-compatible
OS and in which ACPI control methods and objects are written.

C'est ce qui résulte de la compilation du DSDT. Un système d'exploitation compatible ACPI se doit de comprendre l'AML. Pas vous.

ACPI Source Language (ASL)

Egalement d'après les spécifications (Page 13):

The programming language equivalent for AML. ASL is compiled into AML images.

C'est le langage utilisé pour écrire le DSDT. Pour corriger celui-ci, vous aurez à utiliser au moins un petit peu d'ASL.

Differentiated System Description Table (DSDT)

D'après les spécifications ACPI (Page 14) :

An OEM must supply a DSDT to an ACPI-compatible OS.
The DSDT contains the Differentiated Definition Block,
which supplies the implementation and configuration
information about the base system.
The OS always inserts the DSDT information into the
ACPI Namespace at system boot time and never removes it.

En clair, le DSDT décrit la configuration de votre système. Il définit l'ensemble des élements supportés par l'ACPI et leurs caractéristiques. C'est le cas par exemple pour la batterie, l'adaptateur secteur, le controlleur embarqué, les ventilateurs et les sondes thermiques. Ces informations sont hiérarchisées, de sorte que l'ACPI (et donc le système d'exploitation) puisse être informé des dépendances au sein du système matériel. Le DSDT est chargé au moment du boot. Il renseigne l'ACPI sur les pilotes à surveiller.

[modifier] Description du problème

Les spécifications ACPI définissent assez explicitement les exigences de DSDT (et de tout le reste d'ailleurs). Le compilateur ASL d'Intel (iasl), utilisé pour compiler le DSDT depuis l'ASL vers l'AML, renverra des erreurs si l'ASL est buggué. Malheureusement, le compilateur ASL Microsoft autorise quant à lui de nombreuses erreurs. Au final, beaucoup d'OEM utilisent des DSDT buggués, et il s'avère que Windows est assez tolérant avec les erreurs dans le DSDT issues du compilateur Microsoft.

Cela signifie qu'un DSDT non conforme avec les spécifications ACPI peut tout de même fonctionner sous Windows. En revanche, si vous essayez de l'utiliser sous Linux, les sections bugguées du DSDT ne seront pas supportées. Dans ce cas, l'ACPI peut ne pas reconnaître certains éléments de votre configuration. Ou encore, s'il les reconnaît, il peut ne pas supporter toutes leurs fonctionnalités. Si vous rencontrez ce genre de problème (fonctionnalités manquantes ou incomplètes dans /proc/acpi), cela peut être dû à un DSDT buggué.

Vous pouvez vérifier si votre DSDT est issu du compilateur Microsoft en recherchant la chaîne de caractère "MSFT" dans la ligne DSDT de dmesg :

ACPI: RSDP (v000 GBT ) @ 0x000f6d20
ACPI: RSDT (v001 GBT AWRDACPI 0x42302e31 AWRD 0x01010101) @ 0x3fff3000
ACPI: FADT (v001 GBT AWRDACPI 0x42302e31 AWRD 0x01010101) @ 0x3fff3040
ACPI: MADT (v001 GBT AWRDACPI 0x42302e31 AWRD 0x01010101) @ 0x3fff7080
ACPI: DSDT (v001 GBT AWRDACPI 0x00001000 MSFT 0x0100000c) @ 0x00000000

Dans un monde parfait, on se rendraient tous chez notre constructeur de portable préféré pour lui demander de corriger ses DSDT. Ceci dit, en attendant qu'il neige en enfer, on va se débrouiller pour corriger ça nous-même.

En plus du DSDT, les ordinateurs portables répondant aux spécifications de la norme ACPI 2.0 peuvent également posséder un ECDT. Il s'agit d'une table permettant aux pilotes ACPI d'obtenir les informations minimales relatives au contrôleur embarqué avant que la section correspondante du DSDT ne soit lue. Cela se révèle nécessaire afin d'éviter tout problème (du type poule et oeuf) lors de l'initialisation des différents éléments dépendant du contrôleur embarqué de certains systèmes, comme la batterie ou l'adaptateur secteur. Malheureusement, certains portables ne possèdent pas d'ECDT, alors qu'ils le devraient. Nous allons donc également patcher le noyau afin de lire les informations nécessaires dans le DSDT.

[modifier] Disclaimer

La méthode développée ici devrait vous aider à résoudre de nombreux problèmes courants avec le support ACPI sous Linux, mais peut-être pas tous. En effet, les problèmes liés à l'ACPI peuvent avoir de nombreuses origines. Si après avoir suivi ce HOWTO, vos problèmes persistent, vous avez peut-être découvert un bug dans les pilotes ACPI, encore en plein développement. Vous pouvez également avoir mis le doigt sur un problème relatif au système. Dans tous les cas, la meilleure option est alors d'envoyer un mail à la mailing list acpi-devel ou de déclarer le bug sur bugzilla. Parfois, il faut savoir laisser faire les professionnels.

[modifier] Liste des noyaux testés (remplacement du DSDT)

La procédure de remplacement du DSDT exposée dans les sections suivantes a été testée avec succès avec les noyaux suivants :

  • 2.4.23 vanilla avec le patch ACPI de acpi.sourceforge.net (static DSDT)
  • 2.4.24 vanilla (static DSDT, initrd DSDT)
  • 2.6.0 vanilla (initrd DSDT)
  • 2.6.0-gentoo (initrd DSDT + bootsplash)
  • 2.6.1-rc1 vanilla (static DSDT)
  • 2.6.1 vanilla (initrd DSDT)
  • 2.6.8-gentoo (initrd DSDT)

[modifier] Les outils nécessaires pour corriger le DSDT

Avant de se lancer dans la correction du DSDT, sachez que vous aurez besoin de :

  1. support ACPI compilé dans le noyau (statique ou en modules). Un répertoire /proc/acpi sera alors créé.
  2. Pour les sources vanilla, le dernier patch ACPI de acpi.sourceforge.net.
  3. Le compilateur ASL Intel, disponible .
  4. Le patch du DSDT (testé sur les noyaux 2.4.23 et supérieurs), disponible ici.
  5. Le patch de l'initrd correspondant à votre version de noyau, disponible .

[modifier] Comment diagnostiquer un DSDT buggué

Evidemment, il ne sert à rien de corriger le DSDT s'il n'est pas buggué. On va donc commencer par vérifier ça. Le plus simple est de recompiler le DSDT et de voir si on obtient des erreurs de compilation. Pour cela, nous aurons besoin du compilateur iasl et du DSDT. Intéressons-nous d'abord au compilateur :

  • Installer le compilateur iasl (présent dans portage) :

En root

# emerge iasl

On va maintenant récupérer le DSDT, le désassembler et le recompiler.

  • Extraire le DSDT compilé actuellement utilisé dans un fichier :
# cat /proc/acpi/dsdt > dsdt.dat
  • Désassembler le DSDT en utilisant IASL :
# iasl -d dsdt.dat
  • Recompiler le DSDT, toujours avec IASL :
# iasl -tc dsdt.dsl

Et voilà ! Si votre DSDT est buggué, vous verrez apparaître des messages d'erreur ou de warning à la compilation. Par exemple, sur mon portable, j'ai eu les messages suivants :

Intel ACPI Component Architecture
ASL Optimizing Compiler / AML Disassembler version 20030228 [Feb 28 2003]
Copyright (C) 2000 - 2003 Intel Corporation
Supports ACPI Specification Revision 2.0b
dsdt.dsl   163:   Method (_WAK, 1, NotSerialized)
Warning  2026 -   ^ Reserved method must return a value (_WAK)
dsdt.dsl  2626:   Field (ECR, DWordAcc, Lock, Preserve)
Error    1048 -   ^ Host Operation Region requires ByteAcc access
dsdt.dsl  2672:   Method (_GLK, 1, NotSerialized)
Warning  2024 -   ^ Reserved method has too many arguments ( _GLK requires 0)
ASL Input:  dsdt.dsl - 3759 lines, 123154 bytes, 1862 keywords
Compilation complete. 1 Errors, 2 Warnings, 0 Remarks, 390 Optimizations

Une erreur, deux warnings. Le diagnostic est clair : le DSDT est buggué. Maintenant, il faut le corriger.

[modifier] Corriger le DSDT

La première chose à faire est de vérifier ici s'il n'existe pas déjà un DSDT corrigé pour votre portable. Si c'est le cas, téléchargez-le et après l'avoir extrait, recompilez-le en utilisant IASL comme précédemment. Vous pouvez alors vous rendre à la Section 9. Dans le cas contraire, il vous faudra le corriger vous-même comme dans l'exemple qui suit. Malheureusement, cette étape peut différer suivant le système. Dans mon cas, la solution était simple et évidente. Ce ne sera peut-être pas le cas pour vous. Vous pourrez trouver des solutions à la plupart des erreurs de compilation du DSDT ici. De plus, j'ai ajouté une liste de liens utiles à la fin de ce document au cas où vous seriez bloqué.

Afin de corriger le DSDT, il faut éditer le fichier dsdt.dsl créé pendant la phase de diagnostic. Utilisons le mien pour l'exemple. A moins que vous ne possédiez vous aussi un Gateway 200X, la suite diffèrera pour vous, mais cela devrait au moins donner une idée de la démarche à suivre. Et si vous avez un Gateway 200X, vous ne devriez pas lire ces lignes : le DSDT déjà corrigé est ici).

Vous vous en rappelez peut-être, j'ai eu une erreur lors de la compilation de mon DSDT :

dsdt.dsl  2626:     Field (ECR, DWordAcc, Lock, Preserve)
Error    1048 -     ^ Host Operation Region requires ByteAcc access

On en conclue que : - l'erreur est à la ligne 2626 - la Region en question nécessite un accès de type ByteAcc

Dans la mesure où, à cette ligne du fichier, on voit apparaitre un DWordAcc, je suppose que le problème vient de là :

  • Editer dsdt.dsl
vi dsdt.dsl
  • Modifier toutes les lignes provoquant des erreurs. Conformément à ce que donnait le message d'erreur, j'ai changé la ligne 2626 de
Field (ECR, DWordAcc, Lock, Preserve)

en

Field (ECR, ByteAcc, Lock, Preserve)

Sauvez et quittez. Maintenant que les changements sont faits, il faut recompiler pour voir si les erreurs ont disparu.

  • Recompiler dsdt.dsl
./iasl -tc dsdt.dsl

Le message de compilation est devenu :

Intel ACPI Component Architecture
ASL Optimizing Compiler / AML Disassembler version 20030228 [Feb 28 2003]
Copyright (C) 2000 - 2003 Intel Corporation
Supports ACPI Specification Revision 2.0b
dsdt.dsl   163:   Method (_WAK, 1, NotSerialized)
Warning  2026 -   ^ Reserved method must return a value (_WAK)
dsdt.dsl  2672:   Method (_GLK, 1, NotSerialized)
Warning  2024 -   ^ Reserved method has too many arguments ( _GLK requires 0)
ASL Input:  dsdt.dsl - 3759 lines, 123153 bytes, 1862 keywords
AML Output: DSDT.aml - 14600 bytes 499 named objects 1363 executable opcodes
Compilation complete. 0 Errors, 2 Warnings, 0 Remarks, 390 Optimizations

Bien ! Plus d'erreur. Les warnings sont toujours là, ceci dit. On va donc les supprimer.

  • Répéter les étapes 1-3 pour les warnings

Le deuxième warning est le plus simple à résoudre :

dsdt.dsl  2672:    Method (_GLK, 1, NotSerialized)
Warning  2024 -    ^ Reserved method has too many arguments ( _GLK requires 0)

Donc, la méthode _GLK method a trop d'arguments. On va résoudre ça en modifiant la ligne 2672 de :

Method (_GLK, 1, NotSerialized)

à :

Method (_GLK)

La compilation renvoie alors un seul message :

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

D'après un HOWTO existant, il faut visiblement ajouter ce qui suit à la fin de la méthode _WAK method :

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

Qu'est-ce que cela signifie ? Voici ce que donnent les spécifications ACPI (Section 7.3.5) sur la méthode _WAK :

Arguments:
0  The value of the sleeping state (1 for S1, 2 for S2, and so on).
Result Code (2 DWORD package):
Status   Bit field of defined conditions that occurred during sleep.
0x00000000   Wake was signaled and was successful
0x00000001   Wake was signaled but failed due to lack of power.
0x00000002   Wake was signaled but failed due to thermal condition.
Other   Reserved
PSS  If non-zero, the effective S-state the power supply really entered.

This value is used to detect when the targeted S-state was not entered
because of too much current being drawn from the power supply.
For example, this might occur when some active device’s current consumption
pushes the system’s power requirements over the low power supply mark,
thus preventing the lower power mode from being entered as desired.

Bien. Donc, la méthode _WAK accepte un seul argument, à savoir le nombre d'états de veille. Elle retourne un résultat sous la forme de deux DWORDs. En cas de succès du retour à l'activité, les deux valeurs sont nulles. Dans le cas contraire, le premier précise les raisons de l'échec tandis que le second renvoie la valeur de l'état de veille précédant le retour à l'activité.

Dans le Chapitre 16, Nous pouvons retrouver comment définir un "Package".

PackageTerm   := Package(
              NumElements  //Nothing |
              //ByteConstExpr |
              //TermArg=>Integer
              ) {PackageList} => Package

Le premier argument de la définition du package spécifie le nombre d'éléments à fournir, et le deuxième est la package lui-même. Donc, la définition ci-dessus précise seulement un package à deux éléments, où chacun d'eux vaut zéro. Cela est necessaire car les spécifications necessitent que la méthode _WAK renvoie deux valeurs.

Ainsi, ce qui a vraiment besoin d'être fait, c'est de renvoyer une valeur qui comble les spécifications. (d'où l'élimination des warnings), mais ne faisant pas vraiment grand chose. Cela renvoie juste en permanence une condition validée : "Success".

Voilà, maintenant que cela est résolu, j'ai rajouté cette ligne, recompilé, et ..... (roulement de tambour s'il vous plaît)

Intel ACPI Component Architecture
ASL Optimizing Compiler / AML Disassembler version 20030228 [Feb 28 2003]
Copyright (C) 2000 - 2003 Intel Corporation
Supports ACPI Specification Revision 2.0b
ASL Input:  dsdt.dsl - 3760 lines, 123177 bytes, 1863 keywords
AML Output: DSDT.aml - 14606 bytes 499 named objects 1364 executable opcodes
Compilation complete. 0 Errors, 0 Warnings, 0 Remarks, 392 Optimizations

Parfait ! Pas d'erreur, pas de warning. Nous avons maintenant une DSDT "fixée" (souvenez-vous, la méthode _WAK n'est pas vraiment fixée, nous avons seulement coupé court au warning lors de la compilation). Plusieurs des suggestions dans les HOWTOs sur les DSDT que j'ai trouvés ne sont que des indications, pas des solutions. Si vous vouliez une analyse plus approfondie de votre DSDT, vous pouvez interroger les foules sur la liste de diffusion d'acpi-devel. Dans le cas où vous réussissez à fixer vôtre DSDT, n'oubliez pas d'envoyer le résultat dans le dépot DSDT, ainsi d'autres pourront bénéficier de vôtre travail.


Tout ce qui reste à faire maintenant c'est de convaincre notre noyau d'utiliser cet DSDT.

Comme rappelé plus tôt, cela va créer deux fichiers, dsdt.hex et DSDT.aml. Vous aurez besoin d'utiliser l'un des deux dans l'étape à venir, tout dépend de la méthode que vous utiliserez pour écraser votre DSDT. Si vous utilisez la méthode de remplacement statique, alors vous aurez besoin de dsdt.hex. Sinon, dans la méthode utilisant un initrd, utilisez DSDT.aml.

[modifier] Intégrer la correction dans le noyau

[modifier] 3. Méthode pour les noyaux 2.6.9 et plus

  • Les noyaux récents permettent de spécifier un fichier DSDT personnalisé. Tout d'abord copiez la table dsdt au format hex à l'endroit qui convient :
cp /path/to/dsdt.hex /usr/src/linux/include/acpi/dsdt_table.h
  • La première chose à faire au moment de la configuration du noyau est de décocher "Select only drivers that don't need compile-time external firmware"
Configuration du noyau Linux : Disable "Select only drivers that don't need compile-time external firmware"
Device Drivers --->
  Generic Driver Options --->
    [ ] Select only drivers that don't need compile-time external firmware
    [ ] Prevent firmware from being built
  • Ensuite activez l'option de DSDT personnalisée dans le noyau, et définissez en dessous le chemin vers la table dsdt que vous avez compilé.
Configuration du noyau Linux : Enable the custom DSDT
Power management options (ACPI, APM) --->
  ACPI (Advanced Configuration and Power Interface) Support --->
    [*] Include Custom DSDT
    (dsdt_table.h) Custom DSDT Table file to include
  • Recompilez votre noyau, copiez le bzImage, et adaptez le fichier grub.conf pour cibler le nouveau noyau.
  • Si une erreur du type "dsdt_table.h: No such file or directory" survient au moment de la compilation, placez le fichier dans usr/src/linux/drivers/acpi/dsdt_table.h, ou définissez le chemin complet jusqu'à la table dsdt (par ex. /usr/src/linux/include/acpi/dsdt_table.h) au moment de la configuration du noyau.

[modifier] 4. Méthode pour les noyaux sans option d'inclusion de DSDT personnalisé

Sur certains noyaux, il n'est pas possible de spécifier un DSDT personnalisé directement via la configuration du noyau. Pas de panique! Il est possible d'inclure tout de même notre DSDT tout propre à notre noyau.

  • Placez d'abord la table dsdt au format hex dans /usr/src/linux/drivers/acpi/dsdt_table.h
cp /path/to/dsdt.hex /usr/src/linux/drivers/acpi/dsdt_table.h
  • Editez le fichier /usr/src/linux/drivers/acpi/osl.h:
vi /usr/src/linux/drivers/acpi/osl.h

Il suffit d'ajouter en début de fichier (du moins avant le #ifdef CONFIG_ACPI_CUSTOM_DSDT):

#define CONFIG_ACPI_CUSTOM_DSDT
#define CONFIG_ACPI_CUSTOM_DSDT_FILE "dsdt_table.h"
  • Recompilez votre noyau, copiez le bzImage, et adaptez le fichier grub.conf pour cibler le nouveau noyau.

[modifier] Erreur TIP : Asus ACPI: Error reading LCD status

Lorsque vous avez de nombreuses lignes de cette forme dans /var/log/messages quand vous lancez KDE Vous pouvez positionner 'Kded-autoload' à 'false' :

  1. locate kmilod.desktop
  2. edit /usr/kde/3.4/share/services/kded/kmilod.desktop
  3. set X-KDE-Kded-autoload=false

(AFAIRE : Traduire les explications à partir de src ou de la page de bug KDE :)