Pubblicato da: LukenShiro | 25 aprile 2009

Come correggere la tabella acpi DSDT di un BIOS bacato

    § How to edit acpi DSDT table when you have a defective BIOS

(Versione italiana * English version)

Data l’immonda quantità di BIOS pietosi che i produttori di schede madri producono e distribuiscono, capita spesso che usando GNU/Linux (o anche un sistema operativo del genere *BSD o MacOS) su un elaboratore elettronico piuttosto recente le funzionalità ACPI del sistema non siano proprio ottimali.

    § Out there we have an awfully big quantity of defective BIOS assembled and distribuited by mainboards’ makers, and if we are using GNU/Linux (or other operating systems as MacOS or *BSD-like ones) on a new computer maybe ACPI functions are not so excellent, indeed.

Purtroppo ciò è essenzialmente dovuto al fatto che:

    § There are some reasons:

1) esiste uno standard industriale ACPI (standard di un consorzio di aziende che vede come capofila Intel Corporation), ma, come spesso succede, non viene sempre seguito da tutti;

    § ACPI is an industrial standard (there is a consortium with Intel Corp. as head), but not all firms follow ACPI specifications throughly.

2) i produttori delle schede madri e del relativo BIOS sono spesso superficiali o ignoranti di sistemi operativi alternativi/liberi e quindi tutti è pensato ed implementato con riferimento a sistemi MS Windows;

    § Several mainboards’ and BIOS makers are not really interested in alternative and free-as-in-freedom operating system, and they blindly see MS Windows as a unique operating system to devote all of their effort to.

3) il BIOS è il programma per definizione chiuso e proprietario, non documentato, non è facilmente sostituibile in un’ottica opensource (come dimostra a tutt’oggi il bellissimo ma purtroppo limitato progetto Coreboot, un tempo chiamato linuxbios);

    § BIOS is a real closed-source program, not publicly documented, and it cannot be replaced by an opensource alternative (actually there is a really good but limited project Coreboot, some years ago it was known as linuxbios)

4) il BIOS spesso non è di fatto aggiornabile in ambiente diverso da Windows (perché in tempi recenti molti produttori hanno messo a disposizione programmi di aggiornamento solo per MS Windows; anche se un tentativo con FreeDOS in certi casi è possibile). Fare l’upgrade da GNU/Linux è al momento impossibile (tranne per i sistemi supportati dal progetto Coreboot, vedi sopra); inoltre, dato il suo ruolo critico nel sistema, a meno di avere un meccanismo di protezione (dual BIOS di alcune schede madri, chip BIOS di riserva, o dispositivi di tipo BIOS Savior che consentono una riprogrammazione serena), è assolutamente una pratica non alla portata di tutti;

    § BIOS is not always upgradeable in a operating system different from Windows (in fact recently several mainboard makers made available bios upgrade utilities only for MS Windows; nonetheless you maybe can try to use FreeDOS). At the moment you can’t absolutely perform a BIOS upgrade using GNU/Linux (except for Coreboot supported systems, see point 3); moreover, being such a critical program, you should have a protection tool (dual BIOS fro some mainboards, a spare BIOS chip, o devices like BIOS Savior, in order to guarantee a smoothly BIOS re-programming), as it is not for everybody.

5) Dopo qualche anno dall’uscita della scheda madre il produttore generalmente si disinteressa allo sviluppo di una versione aggiornata del BIOS, per cui l’utente si tiene il suo prodotto con tutti i bachi e le limitazioni;

    § After not so many years since market launch mainboard makers normally aren’t anymore interested in releasing updated versions of their BIOS, so user is abandoned with all his product’s defects.

6) le tabelle acpi del BIOS sono di solito compilate con un programma compilatore di Microsoft (contrassegnato dal codice ‘MSFT’), notoriamente troppo tollerante agli errori e poco restrittivo nel far rispettare le specifiche tecniche ACPI.

    § ACPI tables are usually built using a Microsoft compiler (identified by ‘MSFT’ code), who is too much tolerant and disrespectful towards ACPI technical specifications.

Alla luce di tutto ciò è assai probabile che il proprio fiammante computer non funzioni come deve (p.es. per la sospensione in ram o su disco, per il controllo delle ventole e della temperatura del processore, nonché per ogni altra questione di configurazione che dipende dal sottosistema ACPI).

    § So, as I said previously, it may happen you cannot use your new cool computer as you should (e.g. suspend-to-ram, suspend-to-disk, fan control, cpu temperature control, and any other configuration questions relating to ACPI subsystem)

In prima battuta, ove possibile, è consigliabile aggiornare il kernel almeno all’ultima versione stabile; è probabile infatti che gli sviluppatori del kernel e del sottosistema acpi abbiano già introdotto dei meccanismi per risolvere o aggirare questi problemi.

    First, you might want to upgrade your kernel to last stable version at least, if possible; maybe kernel and acpi subsystem developers has already made available fixes or workarounds for these problems

Prima di continuare la lettura, valgono come al solito le consuete condizioni d’uso.

    § Before continue, please read and accept following disclaimer: Beware! I am absolutely NOT responsible for any direct or indirect damage you might have following these instructions, this guide is made free and published as-is, without implied or explicit warranty of any kind.

In ragione del potenziale rischio insito nelle modifiche proposte consiglio di seguire questa guida solo a chi ha una buona conoscenza dell’argomento ed è in grado di far fronte ad eventuali bizzarrie del proprio sistema. E’ sempre buona norma avere un kernel di riserva (senza caricamento di una tabella DSDT modificata) da cui effettuare l’avvio nel caso in cui vi siano dei problemi.

    § As proposed modifications are potentially harmful, I advise you not to read this guide, unless you are somewhat clever on this topic and are prepared to face all problems it could cause. It is better to have a separate and spare kernel (without a custom DSDT table loaded-in) from which you can boot your system if problems should arise.

A tal fine presuppongo che l’utente conosca già:

    § Here are essential requirements you should already know:

1) che cosa rappresenta la tabella DSDT (Differentiated System Description Table);

    § what does DSDT table consist of;

2) come si può creare su disco una copia della DSDT in uso;

    § how can you create a copy of DSDt on your disk;

es./ e.g.: cat /sys/firmware/acpi/tables/DSDT > DSDT.dat
3) come si disassembla la DSDT per avere un listato in formato AML;

    § how to disassemble DSDT to obtain an AML-format listing;

es./ e.g.: iasl -d DSDT.dat
4) come si ricompila la DSDT per ottenere il formato binario (.aml) o testuale (.hex) necessario;

    § how to re-compile DSDT to obtain binary (.aml) o textual (.hex) format;

es./ e.g.: iasl -ta DSDT.dsl o/or iasl -tc DSDT.dsl
5) come si ricompila il kernel per ricomprendere la tabella DSDT modificata, o come si ricomprende la tabella nel file initrd/initramfs.

    § how to re-compile kernel, including modified DSDT table, o to include your table in initrd/initramfs file.

Per capire meglio possono essere utili le specifiche tecniche ACPI ver. 3.0b di Intel Corporation sul sito ACPI, nonché il sito ACPI CA.

    § To better understand this topic you may read Intel ACPI technical specifications version 3.0b on this
    ACPI website; you can read also ACPI CA website

Ringrazio inoltre gli autori di guide e messaggi sui forum in rete che, anche se a spizzichi e a bocconi, mi hanno dato interessanti idee (essenzialmente tutti quelli in inglese ed in italiano che si ottengono con una ricerca su google dei termini “linux acpi dsdt”), in particolare:

    I owe a huge thanks to online guides and forums messages’ authors, who had given me somehow interesting ideas, such as:

Intel LessWatts (eng)
Gentoo how-to (eng)
Opensuse howto (eng)
ACPI How-to, the sequel (eng)
Guide debianizzati (ita)
Antenore blogspot (ita)

Passo ora in rassegna una serie di errori, avvertimenti e note che si possono incontrare laddove si voglia sostituire la tabella DSDT originale con una modificata (con il compilatore di Intel “iasl”)

    § Now I will examine a serie of errors, warnings and remarks whom you can find when you want replace original BIOS DSDT table with your own (modified and compiled with Intel compiler “iasl”)

—————————————————————————-
DSDT.dsl 349: Method (\_WAK, 1, NotSerialized)
Warning 1080 – ^ Reserved method must return a value (_WAK)

—————————————————————————-

Questo avvertimento è dovuto al fatto che il metodo \_WAK non restituisce un valore, contrariamente a quanto dovrebbe.
Il blocco relativo è strutturato, infatti, in questo modo:

    § This warning is caused by \_WAK method doesn’t return a value, while it should do it; the correlative chunk of code is:

Method (\_WAK, 1, NotSerialized)
{
[..] serie di istruzioni/some statements [..]
}

Soluzione: prima della chiusa parentesi graffa è necessario inserire un’istruzione di Return. Le fonti in rete sembrano concordi sul fatto che il valore corretto sia:

    § Hint: before “}” you must insert a Return statement. According to various online sources this value seems to be:

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

Pertanto il testo del metodo in questione, dopo la modifica sarà:

    § So method’s final text will become:

Method (\_WAK, 1, NotSerialized)
{
[..] serie di istruzioni/some statements [..]
Return(Package(0x02){0x00, 0x00})
}

—————————————————————————-
DSDT.dsl 2356: Name (_HID, “*pnp0c14″)
Error 4001 – String must be entirely alphanumeric ^ (*pnp0c14)

—————————————————————————-

Questo errore è dovuto al fatto che il valore in questione non può essere diverso da una lettera e/o da un numero, l’asterisco prima di pnp0c14 non è consentito e deve essere perciò rimosso.

    § This error is caused by a forbidden not alphabetic and/or numerical value, in this case “*”

Il blocco:

    § this chunk of code:

Name (_HID, "*pnp0c14")

dovrà diventare:

    § will become:

Name (_HID, "pnp0c14")

—————————————————————————-
DSDT.dsl 4382: Name (_T_0, 0×00)
Remark 5110 – Use of compiler reserved name ^ (_T_0)

—————————————————————————-

La tabella sta usando un nome che per il compilatore costituisce una parola riservata, come da specifiche ACPI (_T_x)
Le fonti sembrano concordare sul fatto che basti cambiare nome, semplicemente la rimozione del carattere “_” prima del nome.

    § This table is using a reserved word as name (it can’t be used as a name according to ACPI spec.). Following some online sources you can simply remove “_” before the name.

Il blocco

    § this chunk of code:

Name (_T_0, 0x00)

diventerà:

    § will become:

Name (T_0, 0x00)

—————————————————————————-
DSDT.dsl 576: And (CTRL, 0x0C)
Warning 1105 – ^ Result is not used, operator has no effect

—————————————————————————-

L’istruzione sembra mancare di un argomento. La sintassi dell’operatore And, secondo le specifiche ACPI 3.0b è la seguente:

    § This statement lacks of a parameter. In fact And operator’s syntax, according to ACPI spec. vers. 3.0b, is:

And(Source1, Source2, Result)

Mancando l’argomento Result, l’istruzione non fa alcunché. E’ necessario andare per logica: l’istruzione in teoria dovrebbe eseguire l’AND bit per bit tra due interi, pertanto e’ ragionevole ritenere che manchi come argomento quello della variabile CTRL, che rappresenterà il risultato.

    § Parameter Result is missing, so this statement is unuseful and unexecuted. Logically thinking, this statement teoretically should execute a bitwise AND between 2 integers, so we will consider CTRL parameter as missing: this parameter will be the Result

Il blocco

    § this chunk of code:

And (CTRL, 0x0C)

dovrà diventare:

    § will become:

And (CTRL, 0x0C, CTRL)

—————————————————————————-
DSDT.dsl 2370: Method (WMNV, 3, NotSerialized)
Warning 1087 – ^ Not all control paths return a value (WMNV)

—————————————————————————-

Questo avvertimento è dovuto al fatto che nel metodo in questione dovrebbe restituire un risultato ma non in tutte le condizioni ciò avviene.

    § This warning is caused by lack of return statements in some non-checked conditions

Esemplificando:

    § e.g.

Method (WMNV, 3, NotSerialized)
{
Store ("WMNV: ", Debug)
If (LGreaterEqual (SizeOf (Arg2), 0x08))
{
CreateDWordField (Arg2, 0x00, FUNC)
CreateDWordField (Arg2, 0x04, SUBF)
If (LGreater (SizeOf (Arg2), 0x08))
{
Subtract (SizeOf (Arg2), 0x08, Local2)
ShiftLeft (Local2, 0x03, Local2)
}
CreateField (Arg2, 0x40, Local2, ARGS)
Store (FUNC, Debug)
Store (SUBF, Debug)
Store (ARGS, Debug)
Return (\_SB.PCI0.IXVE.IGPU.NVIF (FUNC, SUBF, ARGS))
}
}

Come si può vedere, il metodo restituisce un valore (con Return) SOLO nel caso in cui la condizione proposta con il primo “if” sia vera, altrimenti il metodo non restituisce alcun valore.

    § As you can see, this method return a value ONLY if first-if condition is true, else nothing is returned.

Il problema serio è che sappiamo che ci va un altro return ma non sappiamo con che valore. Le specifiche non sono di aiuto e il valore di Debug non è esplicitato da nessuna parte, ma a buon senso possiamo ritenere che sia un valore superiore a 0 (di riflesso con Debug non utilizzato, il valore potrebbe essere 0)

    § It’s a serious problem, because we know we need another return to catch an unchecked condition, but we do not know which one. ACPI spec. are not useful in this matter; Debug value is not specified anywhere alse, but you can predict it is a value greater than 0 (so our value could be = 0)

Pertanto proviamo a inserire questa istruzione:

    § So we can insert this statement:

Return (\_SB.PCI0.IXVE.IGPU.NVIF (0, 0, 0))

Quindi il metodo in oggetto terminera’ cosi’:

    § This method finally ends as such:

Method (WMNV, 3, NotSerialized)
{
[..] serie di istruzioni [..]
Return (\_SB.PCI0.IXVE.IGPU.NVIF (0, 0, 0))
}

—————————————————————————-
DSDT.dsl 2613: }
Error 4095 – syntax error, unexpected ‘}’, expecting ‘(‘ ^

—————————————————————————-
DSDT.dsl 2624: }
Error 4095 – syntax error, unexpected ‘}’, expecting ‘(‘ ^

—————————————————————————-
DSDT.dsl 2635: }
Error 4095 – syntax error, unexpected ‘}’, expecting ‘(‘ ^

—————————————————————————-
DSDT.dsl 11576: [*** iASL: Read error on source code temp file DSDT.src ***]
Error 4095 -^ syntax error, unexpected $end

—————————————————————————-

Questi errori sono tutti correlati; si tratta di una serie di variabili (ARGS, SARG e XARG) che non si capisce che cosa facciano e perché si trovino lì (specialmente dopo un Return)

    § These errors are reciprocally related: you have a number of variables (ARGS, SARG e XARG) whom you don’t understand what they do and why are they there (specially after a Return)

Prendiamo uno stralcio come esempio:

    § e.g.

[..]
CreateDWordField (Arg2, 0x04, ARGS)
If (LEqual (FUNC, 0x4D53445F))
{
If (LNotEqual (Arg1, 0x10))
{
Return (\_SB.PCI0.XVR0.DGPU._DSM)
ARGS
}
}
Else
{
If (LEqual (FUNC, 0x584D584D))
{
If (LGreaterEqual (SizeOf (Arg2), 0x08))
{
CreateDWordField (Arg2, 0x08, SARG)
Return (\_SB.PCI0.IXVE.IGPU.DDVI.MXMX)
SARG
}
}
Else
{
If (LEqual (FUNC, 0x5344584D))
{
If (LGreaterEqual (SizeOf (Arg2), 0x08))
{
CreateDWordField (Arg2, 0x08, XARG)
Return (\_SB.PCI0.IXVE.IGPU.CRT0.MXDS)
XARG
}
[..]

A prima vista si potrebbero ipotizzare due soluzioni al volo:
- potrebbero essere delle funzioni e vanno quindi indicate con le parentesi ovvero: ARGS () SARG () XARG ()
- oppure potrebbero essere “scivolate” dal return precedente e quindi andrebbero indicate come Return (testoblabla, ARGS) ecc..
In realta’ nessuna delle soluzioni funziona ed in diverso modo danno luogo a errori di sintassi

    § On the first hand you can think on 2 possible solutions:
    - they could be functions, so you should call them with “(” and “)”: ARGS () SARG () XARG ()
    - or, the could be “slipped” from previous Return, so they should be indicated as Return (sometext, ARGS) etc..
    But actually both of them DO NOT work and they give some syntax-errors.

Non resta altro quindi che commentare i valori, cosi’:

    § So you will have to comment all values:

/* ARGS */
/* SARG */
/* XARG */

————————————————————————————————
DSDT.dsl 3649: Method (RNKP, 2, NotSerialized)
Warning 1087 – ^ Not all control paths return a value (RNKP)

————————————————————————————————
DSDT.dsl 4512: If (RNKP (0×00, Local1))
Warning 1092 – Called method may not always return a value ^

————————————————————————————————
DSDT.dsl 3790: Method (STAD, 2, NotSerialized)
Warning 1087 – ^ Not all control paths return a value (STAD)

————————————————————————————————
DSDT.dsl 4564: If (LOr (LLess (STAD (Local1, Local2), \_SB.PCI0.RR13), LEqual (\_SB.PCI0.RR10, Zero)))
Warning 1092 – Called method may not always return a value ^

————————————————————————————————
DSDT.dsl 4055: Method (PCS8, 1, NotSerialized)
Warning 1087 – ^ Not all control paths return a value (PCS8)

————————————————————————————————
DSDT.dsl 4791: Store (PCS8 (Local1), Local2)
Warning 1092 – Called method may not always return a value ^

————————————————————————————————
DSDT.dsl 4230: Method (CSE8, 1, NotSerialized)
Warning 1087 – ^ Not all control paths return a value (CSE8)

————————————————————————————————
DSDT.dsl 4783: If (CSE8 (Local1))
Warning 1092 – ^ Called method may not always return a value

————————————————————————————————
DSDT.dsl 4294: Method (BAL8, 1, NotSerialized)
Warning 1087 – ^ Not all control paths return a value (BAL8)

————————————————————————————————
DSDT.dsl 4786: If (LAnd (\_SB.PCI0.K802.MEMW, BAL8 (Local1)))
Warning 1092 – Called method may not always return a value ^

————————————————————————————————

Il secondo di ciascuna di queste coppie di errori è diretta conseguenza del primo di ognuna. Come detto più sopra in presenza di alcune condizioni il metodo non restituisce un valore, come invece dovrebbe.
Tenuto conto che il metodo non è documentato nelle specifiche ACPI e vi sono una serie di condizioni in presenza delle quali si restituisce un valore correlato a \_SB.PCI0.K802.RRxx oppure a \_SB.PCI0.RRxx (dove xx è un numero che varia), anch’essi non documentati, appare ragionevole restituire uno zero, con:

    § For every couple of warning, the second one depends on the first one. As I said before, giving some conditions this method does not return a value
    This method is not documented in ACPI spec. and we have some conditions for which this one returns a value referring to \_SB.PCI0.K802.RRxx or \_SB.PCI0.RRxx (where xx is the changing part), both undocumented, we could return a Zero value:

Return (0x00)

Perciò all’interno del metodo, alla fine di questo e prima dell’ultima chiusa parentesi graffa andrà indicato questo:

    § So in this method, immediately before “}”, we will insert this Return:

Method (RNKP, 2, NotSerialized)
{
[..] serie_di_istruzioni/some statements [..]
Return (0x00)
}

Il tutto ripetuto per tutti i metodi che hanno questo problema.

    § This statement has to be inserted in every similar problematic method.

—————————————————————————————————-
DSDT.dsl 237: Store (Local0, Local0)
Error 4050 – ^ Method local variable is not initialized (Local0)

—————————————————————————————————-
DSDT.dsl 242: Store (Local0, Local0)
Error 4050 – ^ Method local variable is not initialized (Local0)

—————————————————————————————————-

Questo errore appare mentre si ricompila la tabella DSDT. l’istruzione memorizza la variabile in se stessa: molto utile senza dubbio! ;-)

    § This error appears when you re-compile DSDT table. This statement store a variable in itself: really useful, guys! ;-)

Dato un blocco come il seguente:

    § Having this chunk of code:

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

Method (_SST, 1, NotSerialized)
{
Store (Local0, Local0)
If (LEqual (Arg0, 0x03)) {}
If (LEqual (Arg0, 0x01)) {}
}
}

La soluzione è rimuovere o commentare le due istruzioni incriminate. Il blocco precedente diventerà quindi:

    § Solution: you will have to remove or comment related statements. Previous chunk of code will become:

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

Method (_SST, 1, NotSerialized)
{
/* Store (Local0, Local0) */
If (LEqual (Arg0, 0x03)) {}
If (LEqual (Arg0, 0x01)) {}
}
}

—————————————————————————————————-
ACPI Warning (nspredef-0940): \_TZ_.THRM._PSL: Return Package type mismatch at index 0 – found [NULL Object Descriptor], expected Reference [20081204]
ACPI: Expecting a [Reference] package element, found type 0
ACPI: Invalid passive threshold

—————————————————————————————————-

Questo è un avvertimento che appare nel file /var/log/dmesg e all’avvio del sistema operativo (a differenza dei precedenti che invece sono relativi alla ricompilazione della tabella DSDT originale).

    § This is a warning you can see in /var/log/dmesg while booting the o.s. (previous ones relate to DSDT re-compilation, instead)

Il messaggio è molto criptico e non facilmente intelleggibile da un comune utente. Ricercando in rete ho trovato un riferimento ad una segnalazione di bug su bugzilla.kernel.org, a cui sono arrivato tramite linuxquestions.org

    § Indeed this is a cryptic and not an easy to understand message. Searching online, I’ve found a filed bug on bugzilla.kernel.org, from a forum post on linuxquestions.org

Le righe che ci interessano, estrapolate dal listato della tabella DSDT, sono le seguenti:

    § Taken from DSDT table listing, we can see interesting lines, such as:

External (\_PR_.CPU0)
[..] serie di istruzioni/some statements [..]
Scope (\_PR)
{
Processor (\_PR.C000, 0x00, 0x00000000, 0x00) {}
Processor (\_PR.C001, 0x01, 0x00000000, 0x00) {}
Processor (\_PR.C002, 0x02, 0x00000000, 0x00) {}
Processor (\_PR.C003, 0x03, 0x00000000, 0x00) {}
}
[..] serie di istruzioni/some statements [..]
Name (_PSL, Package (0x01)
{
\_PR.CPU0
})

Il problema sta nel fatto che il dispositivo \_PR.CPU0 (che è dichiarato come esistente all’esterno della tabella DSDT) non esiste: il processore in realtà è identificato come \_PR.C00x (dove x è il numero progressivo del processore, partendo dallo 0, in questo caso sono 4 quelli supportati).
P.S. Faccio notare che questo riguarda la tabella DSDT in esame (il dispositivo \_PR.CPU0 può esistere benissimo in altri BIOS, quindi, ove non sia alcun errore, NON modificatelo)

    § The problem is simple: \_PR.CPU0 device doesn’t exist (even if it is declared to be existent as External): the CPU is identified as \_PR.C00x (where x is the incremental CPU number, starting from 0, in this case we have 4 supported CPUs)
    P.S. Please notice: this one concerns ONLY this DSDT table (\_PR.CPU0 device can be really existent in another BIOS or mainboard, so you MUST NOT modify it if you have not any similar errors)

La riga

    § this line:

External (\_PR_.CPU0)

può essere commentata:

    § can be commented:

/* External (\_PR_.CPU0) */

il blocco

    § this chunk of code:

Name (_PSL, Package (0x01)
{
\_PR.CPU0
})

invece diventerà:

    § will become:

Name (_PSL, Package (0x04)
{
\_PR.C000,
\_PR.C001,
\_PR.C002,
\_PR.C003
})

—————————————————————————————————-
[Firmware Bug]: powernow-k8: Your BIOS does not provide
ACPI _PSS objects in a way that Linux understands. Please report this to
the Linux ACPI maintainers and complain to your BIOS vendor.

—————————————————————————————————-

Questo è un errore che appare nel file /var/log/dmesg nel momento in cui l’utente carica il modulo powernow-k8, che serve a gestire la frequenza della CPU (cpu frequency scaling), consentendo di regolarla in aumento o in diminuzione secondo le esigenze.

    § This is an error appearing in /var/log/dmesg when user loads powernow-k8 kernel module: this one is needed to allow CPU frequency scaling, downwards or upwards, as you wish.

In questo caso la variazione di frequenza non è consentita, poiché il blocco _PSS non è definito nella tabella DSDT. Per quanto capisco vi possono essere due casi:

    § Now we can’t scale CPU frequency, because _PSS chunk of code is not defined in DSDT table. AFAIK there are 2 possible reasons:

1) il blocco _PSS non è neanche definito in alcuna delle tabelle SSDT (possono essere anche più di una): in tal caso non credo che ci sia alcunché da fare, tranne sperare in un aggiornamento del BIOS da parte del produttore.

    § _PSS chunk of code is not defined in a SSDT table (you can have more of one of them), either: so I don’t think you can resolve this problem at all, unless you can hope in a BIOS upgrade, by your mainboard’s maker;

2) il blocco _PSS è definito in una delle tabelle SSDT: è questo il caso che possiamo risolvere!

    § _PSS chunk of code is defined in a SSDT table: we can help you!

Ringrazio l’autore di questo sito, per una pagina sull’uso di speedstep per un processore Intel del notebook Fujitsu Amilo: ciò è servito come spunto per la soluzione di questo problema.

    § Thank you very much to this website’s author, for a page concerning speedstep’s use for notebook Fujitsu Amilo’s Intel processor: this has been represented a useful hint to resolve my problem.

La tabella DSDT e la tabella SSDT sono strutturate come segue:

    § Here is a template used for DSDT and SSDT tables:

DefinitionBlock ([..] serie di dati [..])
{
[..] serie di istruzioni/some statements [..]
}

Pare che il kernel Linux non riesca a vedere e caricare la tabella SSDT: la soluzione è aggiungere in coda alla tabella DSDT i dati della tabella SSDT, avendo l’accortezza di rimuovere o commentare:
- l’ultima chiusa parentesi graffa del DefinitionBlock della tabella DSDT;
- l’intestazione del DefinitionBlock della tabella SSDT, compresa la aperta parentesi graffa immediatamente successiva;
- le definizioni come External di dispositivi referenziati in SSDT che siano definiti nella tabella DSDT.

    § It seems Linux kernel can’t see SSDT table: the solution is to add SSDT table’s data to DSDT table; before doing that you will have to remove or comment:
    - last “}” in DSDT table’s DefinitionBlock;
    - SSDT table’s DefinitionBlock header, including “{” who follows;
    - device declarations as “External” who appear in SSDT table, when these devices are defined in DSDT table

In pratica, una volta copiata la tabella SSDT nella DSDT, avremo:

    § So, after copying SSDT table into DSDT one, we will have:

DefinitionBlock ("DSDT.aml", "DSDT", [..] serie di dati/some data [..])
{
[..] serie di istruzioni/some statements [..]
}
DefinitionBlock ("SSDT.aml", "SSDT" [..] serie di dati/some data [..])
{
External (\_PR_.C000, DeviceObj)
[..] serie di istruzioni/some statements [..]
}

Tale blocco dovrà diventare:

    § This chunk of code will become:

DefinitionBlock ("DSDT.aml", "DSDT", [..] serie di dati/some data [..])
{
[..] serie di istruzioni/some statements [..]
// }
// DefinitionBlock ("SSDT.aml", "SSDT", [..] serie di dati/some data [..])
// {
// External (\_PR_.C000, DeviceObj)
[..] serie di istruzioni/some statements [..]
}

Il nuovo file DSDT.dsl andrà compilato come di solito e incorporato nel kernel (e poi ricompilato) o nell’initrd/initramfs.
Nel file di configurazione del boot-loader (/etc/lilo.conf o /boot/grub/menu.lst o /boot/grub/grub.conf) andrà aggiunta l’opzione “acpi_no_auto_ssdt”).

    § New file DSDT.dsl has to be re-compiled and built-in in the kernel (then re-compiled itself) or included in initrd/initramfs. In the boot-loader configuration file (/etc/lilo.conf or /boot/grub/menu.lst or /boot/grub/grub.conf) you will have to add “acpi_no_auto_ssdt” option.

Al riavvio la gestione della frequenza sarà funzionante, una volta caricati i moduli del kernel interessati.

    § When you reboot, after loading related kernel modules, you will have a working CPU frequency scaling.

Risposte

  1. Ciao,
    sai da quanto non postavi qui??

  2. Eh, lo so, purtroppo … ;-)
    Sarebbe bello avere giornate di 48 ore, ma credo che neanche così basterebbero, con tutto quello che c’è da fare :-P

  3. ciao ho letto un pò il tuo articolo e ho visto che tratti un problemache ho riscontrato nel mio pc che monta una scheda madre della asus m2n32 sli deluxe wireless ed con cpu amd2 6000 x2; ho ubuntu 9.04 come sistema operativo e all avvio del pc subito dopo grub mi compare questo messaggio
    0.918865 ACPI: expecting a [reference] package element, found type 0;
    sono un utente amatore di linux e non riesco a capire come poter risolvere il problema e se questo è un problema grave

  4. Il messaggio che segnali non è completo: dovrebbero esserci altre righe prima e dopo che inquadrano meglio il problema.

    Questo articolo è pensato per chi abbia una buona esperienza sul campo ed una buona conoscenza del sistema (trafficare con le tabelle ACPI del bios da GNU/Linux o da qualsiasi altro sistema operativo è estremamente rischioso e quindi sconsiglio di farlo se non si sa bene quali sono le implicazioni di ciò che si va a modificare).
    I siti a cui faccio riferimento nell’articolo dovrebbero spiegare meglio come far fronte alle operazioni che io considero come presupposte e che quindi non affronto qui.

    In ogni caso se il PC non ti dà problemi nell’uso comune (es. surriscaldamento), è meglio lasciare tutto com’è. Normalmente, a meno di casi particolari, i PC desktop non necessitano di modifiche (il PC è molto più areato di un notebook, quindi difficilmente si surriscalda, e non si fa di solito il suspend-to-ram o su disco).

  5. a dire il vero il surriscaldamento è un problema … abilitanto il cool and quiet dal bios si stabilizza meglio e non si surriscalda troppo… ma non toglie l errore grazie comunque per la risposta, ne sto discutendo qui con la comunità di ubuntu:
    http://forum.ubuntu-it.org/index.php/topic,294094.0.html

  6. Gran bel post. Non sono MAI riuscito ad avere un ACPI funzionante decentemente con Linux. Ricordo che il primo articolo che parlava di correzione e ricompilazione della tabella DSDT comparve proprio sul wiki di gentoo.
    Ho sempre cercato hardware senza OS preinstallati, almeno da sei anni sto particolarmente attento nel scegliere una scheda madre o una scheda video. C’è poco da fare, il resume dopo lo sleep o l’hibernate non funziona decentemente o perché hai tabelle DSDT bacate o perché fglrx.ko o nvidia.ko è scritto coi piedi.
    Fino a qualche anno fa usavo gentoo, mi compilavo a manina tutto quanto e avevo dei package.use lunghi kilometri per avere l’applicativo X con la feature Y. La compilazione del kernel era un rito, la scelta delle patch giuste, eliminare tutte le caratteristiche che non mi servivano e valutare cosa compilare staticamente o cosa come modulo. Mi son rotto le palle, e ora uso Ubuntu.
    Dopo questo prolisso incipit vengo al punto:
    I post e gli howto di linux che ho visto sul DSDT si limitano SEMPRE alla correzione di eventuali errori di compilazione e di warnings, disassemblando, correggendo, ricompilando ed iniettando nel kernel. Nient’altro.
    Un utente linux è già considerato coraggioso se inserisce nel kernel un dsdt compilato con iasl senza errori e warnings.
    Della questione (per motivi non troppo diversi) se ne è occupata anche la comunità OSX86. Occorre dire però che loro sono andati oltre.
    Al fine di simulare certe caratteristiche apple in pc che non le possiedono si sono messi ad aggiungere/sostituire al sorgente dsdt pezzi interi di codice.
    Non ho mai trovato howto a tale pratica su post riguardanti Linux.
    I risultati che molti possessori di hackintosh ottengono sono talvolta eccellenti: al di la’ del riconoscimento dell’HW, riescono a correggere power, sleep e anche i P-states.
    Aggiungiamo a questo il fatto che Linus Torvalds abbia fatto marcia indietro e sia contrario all’inserimento di un DSDT personale all’interno del kernel. Dalla 2.6.31 almeno nei vanilla non è più possibile farlo.
    A questo punto i casi sono due: o uno si compila a manina per ogni aggiornamento un kernel con la patch per inserire il DSDT (ammesso e concesso che tale patch esista sempre e funzioni!) oppure.. si patcha il suo bios una volta per tutte con la nuova tabella e evita problemi per sempre.
    Non sono un programmatore, ma esistono in rete applicativi in grado di patchare il bios per inserire una tabella diversa (I modded bios per installare macos non fanno altro che questo!) ed esisteranno anche guide su come aggiungere pezzi di codice al sorgente DSDT per colmare le lacune del produttore.
    Ti sei mai interessato della cosa? Hai qualche guida/sito/link da suggerire?
    grazie
    davide

    • Non me ne sono mai occupato direttamente, ma ci sono diversi siti che si occupano di BIOS modificati, tipo wimsbios ecc…. L’idea di modificare il BIOS sembra molto interessante, il problema è che il BIOS è quanto di più proprietario e chiuso possa esistere (questo tra l’altro porta ad incognite sulla liceità di un reverse-engineering partendo dall’originale).
      E’ vero, esistono delle utility (peraltro msdos o windows) per modificare il binario, ma in molti casi riguardano perlopiù elementi tipo i loghi EPA ad inizio avvio (non particolarmente utili) e non necessariamente affidabili per BIOS come i Phoenix di nuovo tipo (diversi anche in termini dimensionali dai vecchi Award e AMI); il problema poi di fidarsi di una modifica amatoriale alla cieca e magari non testata a fondo…
      Oltretutto le tabelle ACPI a volte hanno delle funzioni e delle variabili non documentate e che non sono spiegate nelle specifiche ufficiali del consorzio ACPI.
      Soprattutto il BIOS è molto critico, ha una dimensione minima e prefissata: se qualcosa andasse storto, foss’anche un byte di troppo o nel posto sbagliato, il PC diventerebbe un bel soprammobile ;-)

      Per modificare in modo più ampio le tabelle DSDT bisogna poi avere una buona conoscenza del linguaggio AML (ACPI machine language) e non è neanche detto che basti, non avendo la comunità a disposizione gli schemi e le specifiche tecniche di ciascun BIOS e scheda madre.

      Da questo punto di vista credo che sia più utile, per chi può, dare una mano al progetto Coreboot (ex LinuxBIOS) per testare le piattaforme per cui è già previsto un supporto almeno iniziale o per sistemi dalle caratteristiche e dai componenti simili a quelli già supportati.
      Ma anche per questo c’è un ma: non sempre si ha a disposizione un chip di rimpiazzo (assolutamente consigliato), non sempre si riesce a staccare e riattaccare più volte il fragilissimo zoccolino del chip senza rompere o incrinare i piedini, e, specialmente nei nuovi PC, non tutte le funzionalità del BIOS originario possono essere sostituite o emulate da Coreboot. Senza parlare di chip integrati con la scheda madre tipo TSOP (es. in schede come quella delle Xbox recenti o in PC super-integrati/all-in-one), che sono saldati e che quindi non possono essere staccati facilmente (serve una buona manualità e una capacità tecnica con attrezzi specifici, saldatore ecc… non indifferente).

      Ma sicuramente è un punto di partenza che merita stima e attenzione (molti problemi che si hanno con sistemi operativi alternativi sono dovuti quasi esclusivamente ad un bios schifoso e windows-dipendente, più che alle periferiche in sè, se si fa il flash di un BIOS libero con flashrom molti dei problemi di base dovuto alla non-standardizzazione dovrebbero eclissarsi o almeno ridimensionarsi). In ogni caso se il chip è fisicamente sostituibile, ci sono aziende anche in Italia che vendono chip BIOS e dispositivi ri-programmabili di salvataggio (mi pare anche a poche decine di euro) che permettono di resettare il chip in uso e alternarlo con il chip di riserva; se quello programmato non funziona bene lo si riprogramma con l’altro, avendo l’accortezza di tenerne uno con la versione originale o con l’ultima funzionante.

      Per gli errori di progettazione del firmware della CPU, esiste da un certo numero di anni un modulo del kernel linux “microcode”, che aggiorna il firmware temporaneamente caricando in memoria una patch del microcodice; una parte degli errori del bios (quelli relativi al microprocessore) sono risolti cosi, almeno da AMD e da Intel.

      P.S. riguardo al compilare la tabella DSDT: a me risulta ancora presente nel kernel (parlo del vanilla/linus) la voce “Custom DSDT Table file to include” (CONFIG_ACPI_CUSTOM_DSDT)”, senza bisogno di una patch ulteriore; chiaramente va sempre ricompilato il kernel e viene inglobata nel cuore del kernel vmlinuz (non nell’initrd/initramfs).

  7. [...] [...]


Lascia un Commento

Fill in your details below or click an icon to log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Log Out / Modifica )

Foto Twitter

You are commenting using your Twitter account. Log Out / Modifica )

Foto di Facebook

You are commenting using your Facebook account. Log Out / Modifica )

Connecting to %s

Categorie

Iscriviti

Get every new post delivered to your Inbox.