Steam DeckでWindowsとのデュアルブート環境を構築してる方も多いだろうけど、SDカードを挿し替えるのが面倒だし、なによりSDカードを買い足す費用がかかるから、なんとかできないかともがいてみた。
WindowsでExt4パーティションを扱う方法を色々調べたところ、専用のドライバーはありそうだけど、有償だったり、メンテナンスされてなかったり、怪しい所だったり…で使う気がしなかった。そんな中、WSL2を経由すればext4がWindowsでも扱えるという情報を発見。
極力オープンソース技術を使い、かつ比較的安全と思われる方法が見つかったので記録しておく。
先に書いておくと手順が結構くどい。あとLinuxのカーネルモジュールをビルドする関係で時間がかかる。上級者向けかも。オープンソースアプリをソースからビルドした経験があると楽かも。
Steam Deckに搭載されているSDカードリーダーは、SCSI接続の模様。検証始めるまでUSBだと思ってた。
- 簡単に言うと、WindowsからiSCSIを経由してWSLにマウントして、WSL上に立てたSambaサーバーからまたWindowsへ戻す、というループバックを行う。
- Windows 11 Home (22H2)で検証。多分Windows 10でもできる。
- WSL2 / Ubuntu 22.04.1 LTSを利用
- Windows 11(10) ProだとクライアントHyper-Vが使えるので、うまくデバイスのパススルーができれば、もう少し手順が簡単になる可能性があるかも。
- Steam Deckの内蔵カードリーダー以外にも応用可能。PCのUSBメモリ等のマスストレージデバイスでも使える。
- USBだけ使えればいいやという方は、usbipd-winで検索すると幸せになれるかも。
- 手順はUSB Storage Device Access on WSL2をベースに、パッケージや選択項目の不足をなど細部手順を補完したもの。
前提条件
- Valveから配布されているWindows用ドライバーのインストールが完了していること
- Windows環境上にWSL2がインストールされていること
[WSL側]カーネルモジュールのビルドとインストール
$sudo apt update
ビルドに必要なパッケージをインストール
$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses5-dev git bc dwarves
$ mkdir src
$ cd src
WSL2用のLinuxカーネルソースをダウンロードする
$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
$ cd WSL2-Linux-Kernel
$ export KCONFIG_CONFIG=Microsoft/config-wsl
$ make menuconfig
コンフィグ画面が出るので、下記の項目にチェックを入れる。
[*] Enable loadable module support
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
Device Drivers --->
[*] Multiple devices driver support (RAID and LVM) --->
<*> Device mapper support
[*] Block Devices --->
<*> Loopback device support
SCSI device support --->
<*> SCSI disk support
<*> SCSI generic support
SCSI Transports --->
<M> iSCSI Transport Attributes
[*] SCSI low-level drivers --->
<M> iSCSI Initiator over TCP/IP
File systems --->
<*> FUSE (Filesystem in Userspace) support
[*] UTF-8 nomalization and casefolding support
↑忘れずに!この機能が無いとマウントの所でエラーになる
[*] Networking support --->
Networking options --->
[*] TCP/IP networking
ビルド開始。Steam Deckで30~40分程度かかる。もしエラーになった場合は、不足しているパッケージが無いか再確認する。
$ sudo make KCONFIG_CONFIG=Microsoft/config-wsl
できたモジュールをインストールする
$ sudo make modules_install
新しく作ったカーネルイメージをWindowsのユーザーディレクトリに配置
$ cp ./arch/x86_64/boot/bzImage /mnt/c/Users/(Windowsのユーザー名)/
nano /mnt/c/Users/(ユーザー名)/.wslconfig
/mnt/c/Users/(ユーザー名)/.wslconfig
[wsl2]
kernel=C:\\Users\\(ユーザー名)\\bzImage
swap=0
localhostForwarding=true
Ctrl+oで書き込みメニューを開き、Alt+dでDos Formatを選択、Enterで保存。Ctrl+xで閉じる。
PowerShellからWSLを再起動
PS > wsl --shutdown
再びWSLのコンソールを開き、モジュールをロード
$ sudo modprobe -v libiscsi
$ sudo modprobe -v scsi_transport_iscsi
$ sudo modprobe -v iscsi_tcp
$ sudo modprobe -v libiscsi_tcp
[WSL側]Systemd有効化
$ sudo nano /etc/wsl.conf
/etc/wsl.conf
[boot]
systemd=true
Ctrl+oで書き込みメニューを開き、Enterで保存。Ctrl+xで閉じる。
PowerShellからWSLを再起動。
PS > wsl --shutdown
再びWSLのコンソールを開いて起動しておく。
[Windows側]iSCSIターゲットのセットアップ
iSCSI Consoleを用いる。
https://github.com/TalAloni/iSCSIConsole
画面右側のReleasesからバイナリーのzipをダウンロードする。
zipを展開すると3つフォルダーがあるが、多分どれを選んでも同じ。(対応している.netのバージョンの違いだと思われる)
管理者権限でiSCSIConsole.exeを起動する。
SmartScreenの警告画面が出た場合は、詳細情報→実行をクリック
起動したらAdd Targetをクリック。
Add Physical Diskをクリック。
一覧にSDXCが表示されるので、それを選択してOKをクリック
ドライブをオフラインにする旨の確認画面が出るのでOKをクリック
Disksの欄にSDカードドライブが追加されるので、OKを押して閉じる
StartをクリックしてiSCSIターゲットを起動する。
ファイアーウォールの確認画面が出た場合は許可する。
[WSL側]iSCSIイニシエーターの設定
open-iscsiのインストール
$ sudo apt install open-iscsi
iSCSIターゲットとの疎通確認をする。
$ export WSLHOSTIP=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
$ sudo iscsiadm -m discovery -t st -p $WSLHOSTIP
172.26.240.1:3260,-1 iqn.1991-05.com.microsoft:target1
$ sudo iscsiadm -m node
172.26.240.1:3260,-1 iqn.1991-05.com.microsoft:target1
この時点で相手が表示されない場合は、iSCSI ConsoleのStartボタンの押し忘れがないか、ファイアーウォールなどでトラフィックが遮断されていないか確認する。
iSCSIターゲットへ接続。successfulが出ていれば成功
$ sudo iscsiadm -m node --targetname "iqn.1991-05.com.microsoft:target1" --portal "$WSLHOSTIP:3260" --login
Logging in to [iface: default, target: iqn.1991-05.com.microsoft:target1, portal: 172.26.240.1,3260] (multiple)
Login to [iface: default, target: iqn.1991-05.com.microsoft:target1, portal: 172.26.240.1,3260] successful.
新しくブロックデバイスが出現していることを確認
$ lsblk
SDカードのマウントを行う
$ sudo mkdir -p /mnt/sdcard/SteamLibrary
$ sudo mount /dev/sdc1 /mnt/sdcard/SteamLibrary
(↑/dev/sdc1の部分はlsblkを確認して適宜変更する)
[WSL側]Sambaサーバーのセットアップ
$ sudo apt install samba
$ sudo nano /etc/samba/smb.conf
/etc/samba/smb.confの最下行に下記を追加
[sdcard]
path = /mnt/sdcard
read only = no
sudo systemctl restart smbd
Samba用のパスワードを設定。
ここではSambaログイン時に利用するLinuxユーザーアカウント名を指定する。ここではdeckとしている。
必要に応じてsudo smbpasswd -a の部分は変更する
パスワードは空白でも怒られなかった。
sudo smbpasswd -a deck
New SMB Password:(そのままEnter)
Retype new SMB password:(そのままEnter)
WSLのIPアドレスを確認しておく
$ ip addr
[Windows側]ネットワークドライブとして接続
エクスプローラーを開き、PCの所で「・・・」をクリックし、「ネットワークドライブの割り当て」をクリック
ドライブはお好みで。
フォルダーは、\\(WSLのIPアドレス)\sdcard
とする
サインイン時に再接続にチェック、別の資格情報を使用して接続するにチェック。
完了をクリック。
アカウントを尋ねられるので、ユーザー:deck、パスワード:(smbpasswdで設定したパスワード)を入力
SDカードの中身が表示されていれば成功。
Steamライブラリフォルダーに追加
設定→ダウンロード→Steamライブラリフォルダーを開く。
ドライブ一覧の右にある(+)ボタンをクリック
「新しいSTEAMライブラリフォルダーを追加」のダイアログが出るので、先程追加したネットワークドライブを選択
※ネットワークドライブが一覧にない場合は、「別の場所を選択」を選び、「追加」をクリックした後、フォルダ選択画面でネットワークドライブを選択し、その配下にある「SteamLibrary」を選択した状態でOKをクリック。
最後に
これによってSteamOSでインストールしたライブラリーの共有ができると思うけど、心配なのは、Windows/Linuxの両方に対応したゲームで、かつ各プラットフォームによって配信されるファイルの内容が分かれているもの。ファイルが上書きされてうまくゲームが動かなくなったりするかも。
安全にライブラリーを共有したいという方は、フォルダを分ける(といっても歪な構造になりそう)か、事前にSDカードのバックアップをとっておくとよいでしょう。
参考
- USB Storage Device Access on WSL2
https://github.com/jovton/USB-Storage-on-WSL2 - 「Windows Subsystem for Linux」が「systemd」に対応へ
https://forest.watch.impress.co.jp/docs/news/1441775.html
最近のコメント