BitVisorのcore/acpi_dsdt.cに実装されている各種回避策について簡単に紹介します。
ACPI specについてはUEFIのサイトにあります。
Specifications | Unified Extensible Firmware Interface Forum
http://www.uefi.org/specifications
Preexisting ACPI Specifications | Unified Extensible Firmware Interface Forum
http://www.uefi.org/acpi/specs
旧対策
DefDevice
DefDeviceのObjectListの部分にIf()やZeroOpが含まれるケースがよくあり、仕様に合致していないものとして特別にObjectList2を作って対処していました。ACPI spec 6.1 (Errata A) で、ObjectListではなくTermListになったことで、仕様に合致したものとなり、特別扱いは不要になりました。
この旧実装については、以下の記事のDSDT/SSDTの項目にも一部説明があります。
BitVisorとACPI - Qiita
https://qiita.com/hdk_2/items/941699d40d9a5905639b#dsdtssdt
ACPI specの不思議
NamedObj
ACPI spec 5.0から、AMLのNamedObjの定義がなぜかずいぶんと減り、明らかに必要なものが足りていない状態となっています。ACPI spec 6.2 (Errata A) においても同じですが、古いspecと見比べると、以下のものが編集ミスで脱落したとしか思えない状態なので、この部分は古いspecに合わせています。
- DefDevice
- DefEvent
- DefField
- DefIndexField
- DefMethod
- DefMutex
Type6Opcode
ACPI spec 5.0で、UserTermObjの定義が消え、代わりにMethodInvocationに置き換えられたように見えますが、なぜか、Type6Opcodeには、未定義となったUserTermObjが残されています。ACPI spec 6.2 (Errata A) においても同じですが、おそらく、目視による置換ミスでMethodInvocationに置き換えられなかっただけだと思われるので、MethodInvocationとして入れています。
ExtendedAccessField
ACPI spec 5.0で、ExtendedAccessFieldというのが追加されましたが、不思議なことに、その定義が参照するAccessLengthが未定義です。ACPI spec 6.2 (Errata A) においても同じですが、おそらく単なる書き忘れで、雰囲気からしてByteDataで解釈できるだろうということで、ByteDataとしてあります。
ConnectField
ACPI spec 5.0で、ConnectFieldというのが追加されましたが、不思議なことに、その定義が参照するBufferDataが未定義です。ACPI spec 6.2 (Errata A) においても同じですが、おそらく単なる書き間違いで、雰囲気からしてBufDataが正解だろうということで、BufDataとしてあります。
解釈ルーチンの都合によるもの
MethodInvocation
ACPI spec 6.1 (Errata A) で、ObjectListが削除され、既存のTermListに置き換わりました。ObjectListには含まれなかったものがTermListには含まれていることにより、BitVisorのちゃちな解釈ルーチンでは問題が発生するようになってしまいました。
ObjectListは0個以上のObjectで、ObjectとはNameSpaceModifierObjまたはNamedObjで、これらはMethodInvocationを含みませんでした。しかし、TermListになったことで、0個以上のTermObjとなったため、Type1OpcodeとType2Opcodeが使えるようになり、Type2OpcodeとしてMethodInvocationが使えるようになりました。これによって、これまで特別扱いのZeroOpとして解釈されていた部分が、NullNameのMethodInvocationに引数がZeroOpとして解釈できるようになってしまいました。しかし、引数のZeroOpもまた、NullNameのMethodInvocationとして解釈できてしまうことから、ZeroOpが続く部分で解釈パターンが収束しなくなりました。
そもそも、NullNameのMethodInvocationなんてものがおかしな話なわけですが、AMLの仕様上は許されていそうですので、単純に切り捨てるわけにはいかないでしょう。そこで、特別扱いでNullNameのMethodInvocationの引数等にはNullNameのMethodInvocationが来ないという制限をかけてあります。この実現のために、NameStringからNullNameを除いたNameString2を定義し、NameString2の場合は通常通りの定義としています。そして、NullNameのためのMethodInvocation2を定義し、その中でMethodInvocationが来る場合は解釈しないようにしてあります。
機種依存問題
AMLCode
AMLCodeというとものすごく根本的なところですが、ThinkPad L570というPCで、なぜか、AMLCodeのTermListにOneOpが含まれるというケースが見つかりました。謎のZeroOpが並ぶケースはいろいろありましたが、それらはなんでNoopOpを使わないのかという疑問は残るものの、単純に使わない領域をゼロクリアしちゃったんだなと思えば、擁護できる面はありました。OneOpというのはさらに謎です。回避策としてTermList2を用意し、謎のOneOpが来ても解釈エラーにならないようにしてあります。
一言
iaslコマンドはこのような謎のコードを読んでも全くエラーを出さないのも面白いところです。上述の編集ミスらしき内容を見ても、実はAMLの本当の仕様書はACPICAのソースコードで、ACPI specは誰も見ていないのかも知れませんね。