コンテンツにスキップ

システム管理コントローラ (SMC)

2025/3/9時点のsmcの翻訳


SMCは、温度センサー、電圧/電力計、バッテリーの状態、ファンの状態、LCDバックライトや蓋スイッチなどへのアクセスを制御するハードウェアです。

https://github.com/corellium/linux-m1/blob/master/drivers/hwmon/apple-m1-smc.c に『文書化』されていますが、 これはプロトコルに過ぎず、基本的に次の3つのことを行うことができます。

  1. 4文字のASCII文字で構成される多数の『キー』それぞれのデータを読み取る。MacBook Proには約1,400個のキーが存在

  2. ペイロードを供給しながら、キーのデータを読み取る

  3. キーに対応するデータを書き込む

バイトのデータを受け取るだけでなく、SMCは4つのASCII文字でエンコードされたそのデータのタイプと、フラグバイトを提供します。

今のところ、(2)と(3)を試す勇気はありません。

SMCのキータイプ

4つのASCII文字でエンコードされ、最後の文字がスペースの場合は省略される。

  • flt: 32ビットの単精度IEEE浮動小数点値。少なくとも1つのケースでバイトオーダーが実際は逆
  • SI8, ui8, SI16, ui16, SI32, ui32, SI64, ui64: 8-/16-/32-/64 ビットの符号付き/符号無しの値
  • hex_: ランダムなバイナリデータ
  • flag: 1 または 0
  • ioft: これは64ビットの符号なし固定小数点値(48.16など)のようです。
  • ch8*: ASCII 文字列
  • {jst: 不明。バイナリコード化された構造化文書のようなもの?
SMCフラグ

ほとんど不明です。0xf0 フラグを持つキーはゼロ以外の値を確実に返さないようです (Quirks を参照)。

SMCキー

たくさんあります。https://github.com/torvalds/linux/blob/master/drivers/hwmon/applesmc.c でいくつか文書化 されていますが、ほとんどは4文字の名前から推測する必要があります。MacBook Proには1,400以上のキーがありその多くは 使われていません。

これらの意味するところをいくつか推測してみます。 * T???: 摂氏単位の温度値でfloat。その数は多い。クエスチョンマークはその場所を示していると思われる (そしておそらくより意味のある読み方をするために平均化されているかどうかも示している?) * TB0T: 電池温度 * TCHP: 充電器温度 (充電時にわずかに上昇) * TW0P: 無線機温度 (無線をオンにするとわずかに上昇) * Ts0P: パームレスト温度 * Ts1P: パームレスト温度 * V???: 電圧。おそらくボルト単位 * gP??: 『GPIO』ピン。実際には出力のみで、ピンのレベルを非破壊で読み取ることができないバグがあるようですが、 最初に読み取られるピンの場合はうまくいく * gP0d: WiFi/BT チップを制御。 これを有効にしないと、WiFi と BT のための PCI デバイスは表示されません。 『rfkill』 機能を実装するために使用? * gP12: LCD バックライト。オフにすることで見かけ上の消費電力を減らしたりオンにすることが可能 * gp?? (大文字小文字に注意): おそらく、ある種のGPIOピン? * D1??: 最初のUSB-Cポートに接続されているデバイスの情報 * D1in: 接続されている充電器の名前 * D1is: 接続されている充電器のシリアル番号 * D2??D1??を参照。 * P???: 電力計、単位はおそらくワット * PSTR: システム全体の消費電力(W) * SBA?: システムのバッテリー情報 * SBA1: 電池セル1の電圧 (mV) * SBA2: バッテリーセル 2 の電圧 (mV) * SBA3: バッテリーセル 3 の電圧 (mV) * SBAV: 電池電圧 (mV) (SBA1SBA2SBA3 の合計、B0AV と同じだが flt として表示) * SBAR: 電池残量 (mAh) (B0RM と同じだが、flt として表示) * SBAS: バッテリー充電量 (%) (BRSC と同じだが、flt と呼ばれる) * RPlt: プラットフォーム名、例えば『J293』 * a???: 電力に関連する非常に揮発性の高い測定値であり、おそらくデバイスの様々な部分に流れる電流を測定 * F???: ファン情報。https://github.com/torvalds/linux/blob/master/drivers/hwmon/applesmc.c を参照 * CL??: 製造/RTCリセットから(おそらく)マイクロ秒単位で測定された様々な時間 * CLKU: 継続的に更新される現在時刻 * CLBT: SMCブートタイム(つまりAC電源供給時) * CLSP: おそらくSMCが最後にスリープした時間 * CLWK: おそらく最後にSMCが起動した時間 * MSLD: 蓋のスイッチ、1 は閉、0 は開を表す * bHLD: 現在押されている電源ボタン * MBSe: 最後に読み込んでから押された電源ボタン、読むとクリア * B0CT: 充電サイクル数 * B0AV: 電池電圧 (mV) (SBAV と同じだがsi16) * BRSC: バッテリー充電量 (パーセント) (SBAS と同じだが ui16) * B0DC: 電池設計容量 (mAh) * B0FC: バッテリーフル容量 (mAh) * B0RM: 電池残量 (mAh) (SBAR と同じだがバイトオーダーが逆のui16) * B0TE: 電池が空になるまでの時間(分) * B0TF: 電池が満充電になるまでの時間(分) * ID0R: 入力電流(A) * VD0R: 入力電圧(V) * PDTR: 入力電力(W)

Quirks

あるいは、もしかしたらねじれ(訳注:quirk)があるのかも?

  • #KEY: SMCのキーの数を保持するがバイトオーダーが逆
  • VP3b: 明らかにバイトオーダーが逆
  • gP??: 奇妙な方法でラッチ。これらのキーのいずれかが最初に読まれたとき、データはピンの電源ステータスを示す。 しかし、これらのキーのいずれかに書き込んだ後を除いて、その後どのキーを読んでも 0 が返される。つまり、 Highレベルであることが分かっているピンに1を書き込んでから、他のピンのレベルを1つずつ読み取ることを 繰り返せば、すべてのピンを読み取ることができる。ペイロードが 0xffffff または 0x00000001 のときに 読み出すと、正しい値が返される
  • rLD0: 普通に読めない。0x00000001や0x00ffffのペイロードで読める。たぶん、これは『flags』バイトが 0xf0 であることと関係がある
通知

『NTAP』(たぶん?notify application processor)フラグを1に設定すると、電源の接続や切断、電源ボタンの押下、 蓋の開閉など、特定のシステムイベントが発生したときにSMCから通知が送られるようになります。 通知はmailboxメッセージで、64ビットのペイロードに制限されているようです。

ADC

SMCから『直接』アクセスできるキーに加え、マルチプレックスされたシングルチャンネルADCと思われるものがあり、 さらに111の値にアクセスできます。これは『aDC#』 (キーの数を提供)や『aDC?』(数値ペイロードを用いたキー名を 検索) や『aDCR』(実際の結果値)を介してアクセスされます。