Open21

MacBook (Retina, 12-inch, 2017) にArchLinuxを導入する過程

enchanenchan

Overview

つまづきメモ, 基本的なインストラクション, etc.

enchanenchan

インストール前にやっておくといいこと

enchanenchan
  • 必要なら起動時のサウンド(ドゥーーーーーーン)をミュートにする
    (Arch側でこれをdisableする方法がわかっていない)
  • ディスプレイのEDIDを取得し、バイナリに起こしておく
    ioreg -lw0 -r -c "IODisplayConnect" -d 2 | grep IODisplayEDID で取得できるので、適当に切り出してバイナリ化する (参考: stackoverflow)
    ちゃんと抜き出せているか確認したいなら、timvideos/edid-decodeをビルドしてファイルごと渡せばOK
enchanenchan

インストール時に困ったこと

enchanenchan
  • インストール
    • 基本的に公式のインストラクションに則れば問題ないと思う, 今回は躊躇なくmacOSごと吹き飛ばしてインストールした(ブートローダにはGRUBを採用)
    • macOSを吹き飛ばした後にmacの環境が欲しくなってしまった場合は、起動時に ⌘+R してネットワーク復元を実行すれば(めちゃくちゃ限られた範囲で)使える
      今回はディスプレイのEDIDを取ってこられなかったのでここで ioreg を叩いた
    • ターミナルの右と下が切れる(ディスプレイの表示領域をはみ出てしまう) ←後述
      応急処置: stty cols 144 rows 45
  • ネットワーク周り
    • iwctlarch-chroot環境だと動かせないので、インストール時にiwdを入れてから再起動して設定すればよい
    • 設定後 systemd-resolved をenableするのを忘れないこと (名前解決ができなくてハマる)
  • パッケージ周り
    • インストールメディアが古いと (package) is corrupted みたいなエラーでコケることがある(インストール中何度か遭遇)
      署名鍵の問題っぽい? pacman -Syu archlinux-keyring してあげれば通った
enchanenchan

解決できていないこと

enchanenchan
  • ディスプレイの解像度がおかしい
    • 公式の仕様を見る限り、ディスプレイの物理的な解像度は 2304x1440
      スケーリング可能な解像度として 1440x900, 1280x800, 1024x640 が提示されている
    • しかし fbset を叩くと 2560x1600 が返る
    • edid-decode に通すとこんなことを言い出す:
      % cat macbook_edid.bin | ./edid-decode/edid-decode
      EDID version: 1.4
      Manufacturer: APP Model a027 Serial Number 0
      Made in week 27 of 2015
      Digital display
      8 bits per primary color channel
      DisplayPort interface
      Maximum image size: 26 cm x 16 cm
      Gamma: 2.20
      Supported color formats: RGB 4:4:4
      Display x,y Chromaticity:
        Red:   0.6533, 0.3339
        Green: 0.2998, 0.6201
        Blue:  0.1464, 0.0498
        White: 0.3125, 0.3291
      Established timings supported:
      Standard timings supported:
      Detailed mode: Clock 262.500 MHz, 259 mm x 162 mm
                   2560 2592 2624 2659 hborder 0
                   1600 1603 1609 1646 vborder 0
                   +hsync -vsync 
                   VertFreq: 59 Hz, HorFreq: 98721 Hz
      Detailed mode: Clock 218.750 MHz, 259 mm x 162 mm
                   2304 2352 2384 2464 hborder 0
                   1440 1443 1449 1481 vborder 0
                   +hsync -vsync 
                   VertFreq: 59 Hz, HorFreq: 88778 Hz
      Detailed mode: Clock 328.000 MHz, 259 mm x 162 mm
                   2880 2908 2936 2964 hborder 0
                   1800 1803 1809 1845 vborder 0
                   +hsync -vsync 
                   VertFreq: 59 Hz, HorFreq: 110661 Hz
      Monitor name: Color LCD
      Checksum: 0x34 (valid)
      
      曰く 2560x1440, 2304x1440, 2880x1800 をサポートしてまっせ!とのこと
      いやでもキミHW的に2304px以上表示できなくない?
enchanenchan

何も考えずにインストールすると全てが狂い出す

  • fbset2560x1600
  • neofetch2304x1440

もう全てがめちゃくちゃ

enchanenchan

tput cols lines160x50 が返るけど、ディスプレイをはみ出さないギリギリのコンソールサイズは 144x45 くらい

デフォルトフォント(多分default8x16.psfu.gz)の縦横比が2:1であることを考えると、160x50160x100144x45144x90 となり、アス比はいずれも 16:10
gcd(160, 144) = 16, 16×144 = 2304 であることから、単純にフレームバッファの左上から表示できる部分を描画しているだけになっている可能性が高い

enchanenchan

例えば dmesg --color=always | less -R してしばらくだーっと流してから、cat /dev/fb0 > fb.bin してフレームバッファの画像を見るとこんな感じ:

表示範囲外にもちゃんと書き込まれてるけど、実際にディスプレイに表示されるのは赤枠の領域だけ!

enchanenchan

整理

  • 物理的な解像度は 2304x1440 である (参考: MacBook(Retina,12-inch,2017) 技術仕様)
    • OS的に対応できる解像度は1440x900, 1280x800(デフォルト), 1024x640 の三種類
  • macOSのioregで取得すると、2560x1600, 2304x1440, 2800x1800 が返る
    • HWの解像度より大きな値, 最初のものはMacBook Proと同じサイズ
    • Retinaの横幅1280pxは実際には2560pxなので、横幅2304pxの液晶にそのまま表示することは物理的に不可能なはず
    • 余談だが、2304x1440 = 2560x1600 × 0.9
  • パッケージread-edidget-edidの出力をparse-edidに通すと、2304x1440 のみが返る
    • ioregで渡した時のものとは異なるバイナリが返ってくるようす (参考: 実際の実行結果)
    • macOS側でEDIDをオーバライドしている可能性がある?
  • 起動時にGRUB Terminalに入りvideoinfoすると、2560x1600が返る
    • なんで?
  • fbsetのvxres, vyresはそれぞれ2560, 1600となっている
    • 上書きできない (fbset -vxres 2304とかやっても効かない)
    • xres, yres は上書きできる
enchanenchan

皮肉にも nomodesetをカーネルパラメータに追加すると全てがうまくいくんだよな…

enchanenchan

解像度問題

ttyの右と下が見切れてしまう現象が発生する。これは(直接的には)フレームバッファの解像度とディスプレイの解像度が合っていないためと考えられる。
インストール後の(特段の設定をしていない)状態では、フレームバッファ/dev/fb0の解像度は 2560x1600 となっている:

フレームバッファの大きさ
# fbset

mode "2560x1600"
    geometry 2560 1600 2560 1600 32
    timings 0 0 0 0 0 0 0
    rgba 8/16,8/8,8/0,0/0
endmode

一方、接続されているディスプレイのモードを読み出すと2304x1440が返る(余談だが、 neofetch はこちらの値を参照している):

ディスプレイモード
# cat /sys/class/drm/*/modes
2304x1440

MacBook Retina 12inch, 2017に搭載されているディスプレイの(物理的な)解像度は 2304x1440 である[1]ため、後者の値が正確(?)だと思われる。
しかしフレームバッファのサイズはディスプレイのそれよりも大きくなってしまっている。これが原因で上記のような現象が発生する。

macOSだとどうなのか

このモデルでは、macOSは 1440x900, 1280x800(デフォルト), 1024x640 の三種類の解像度に対応している。Retinaディスプレイなので実際の解像度はそれぞれ4倍となり、例えば 1280x800 は実際には2560x1600となる…はずである。しかし実際のディスプレイの横幅は2304pxであり、2560pxを表示できる領域はどこにもない。

素人の勝手な妄想だが、2560x1600でレンダリングしたものを90%に縮小しているのかもしれない(2560×0.9=2304, 1600×0.9=1440)…? 実際の描画としては1280x800を180%に拡大している(1280×1.8=2304, 800×1.8=1440)ことになるのだろうか?

応急処置

ターミナルのサイズ(行数/列数)は stty で変更できる[2]ため、stty cols 144 rows 45 とすればとりあえず見切れることはなくなる。しかしフレームバッファ自体のサイズは変わっていないため、/dev/fb0から画像データを起こすと画面右部および下部に余白が生じる。

対応策: 1. fbsetでフレームバッファのサイズを変更する

fbsetでフレームバッファのサイズを変更しようとしたものの、virtual resolution, 仮想解像度 (vxres, vyres)は変更されなかった。fbset -match も機能せず。

フレームバッファのサイズを変更する
# fbset -g 2304 1440 2304 1440 32
# fbset

mode "2304x1440"
    geometry 2304 1440 2560 1600 32
    timings 0 0 0 0 0 0 0
    rgba 8/16,8/8,8/0,0/0
endmode

実行後に setterm --resize すると stty size144 45 を返すようになったので、「画面に表示できる領域は2304x1440である」と教えることはできていそう。ただし内部的にフレームバッファのサイズが変わったわけではないため、/dev/fb0を画像に変換すると相変わらず右と下に余白が生じてしまう。

対応策: 2. カーネルパラメータに nomodeset を追加する

かなり本末転倒だが、そもそもKMSを使わないという方法がある:

/etc/default/grub
# nomodesetを追加する
GRUB_CMDLINE_LINUX_DEFAULT="nomodeset loglevel=3 quiet"

これを適用して起動すると、まるで最初から2560x1600のディスプレイがつながっているかのような動作を示す。

fbsetの出力
# fbset

mode "2560x1600"
    geometry 2560 1600 2560 1600 32
    timings 0 0 0 0 0 0 0
    rgba 8/16,8/8,8/0,0/0
endmode
ディスプレイモード
# cat /sys/class/drm/*/modes
2560x1600

そもそもディスプレイの認識が異なっている:

nomodesetを適用した場合
# ll /sys/class/drm
total 0
drwxr-xr-x  2 root    0 Mar 22 14:40 .
drwxr-xr-x 71 root    0 Mar 22 14:40 ..
lrwxrwxrwx  1 root    0 Mar 22 14:35 card0 -> ../../devices/platform/simple-framebuffer.0/drm/card0
lrwxrwxrwx  1 root    0 Mar 22 14:35 card0-Unknown-1 -> ../../devices/platform/simple-framebuffer.0/drm/card0/card0-Unknown-1
-r--r--r--  1 root 4.0K Mar 22 14:40 version
nomodesetを適用しない場合
# ll /sys/class/drm
total 0
drwxr-xr-x  2 root    0 Mar 22 14:46 .
drwxr-xr-x 71 root    0 Mar 22 14:46 ..
lrwxrwxrwx  1 root    0 Mar 22 14:46 card1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1
lrwxrwxrwx  1 root    0 Mar 22 14:46 card1-DP-1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-1
lrwxrwxrwx  1 root    0 Mar 22 14:46 card1-eDP-1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1
lrwxrwxrwx  1 root    0 Mar 22 14:46 card1-HDMI-A-1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-HDMI-A-1
lrwxrwxrwx  1 root    0 Mar 22 14:46 renderD128 -> ../../devices/pci0000:00/0000:00:02.0/drm/renderD128
-r--r--r--  1 root 4.0K Mar 22 14:46 version

フレームバッファからスクリーンショットを取得しても余白が生じることはなく、また実際に表示されている内容も見切れることはない。なんとも不可思議な状態を再現できる。

脚注
  1. 参考: MacBook(Retina,12-inch,2017) 技術仕様 ↩︎

  2. 参考: Ubuntu Manpage: stty - 端末の行設定の変更や表示を行う ↩︎

enchanenchan

抜き出してきたEDIDファイルを配置したところ表示が完全に崩れた(同期が狂ってるような感じ、表示が左上に揺れていく)
KMSの早期開始 が有効になってるので、EDIDファイルはinitramfsに組み込んでいる

enchanenchan

KMS自体を遅延させてみるのもひとつアリかもしれない?

enchanenchan

ダメでした 症状変わらず

i915.modeset=0 でGUIセットアップしてみて問題なく動くようならこれでいく i915がRetinaをうまく処理できてないんじゃないかなという仮説

enchanenchan

現状KDE Plasmaが正常に動いています…うーん…これでいいっちゃいいのかなあ…

enchanenchan

Plasmaのパフォーマンスが段違いだ やっぱり無理してたのかあれは