Unofficial
このページの内容
  1. 01ワークショップの役割
  2. 02ワークスペースを準備する
  3. 03プロジェクト
  4. 04ドライバーをビルドする
  5. 05動作中のカーネルとの互換性を確認する
  6. 06ロードとその影響

NAS用のカーネルモジュールをビルドする:CH341 USBシリアルドライバー

CH340またはCH341チップを搭載したUSBシリアル変換アダプターの多くは、カーネルのch341ドライバーを必要とします。ここで使用するQTS 6.1搭載NASには、このドライバーが付属していません。Bucket & Code Server IDEのカーネルワークショップは、NASで動作中のカーネルに合わせてモジュールをビルドし、そのカーネルとの互換性を確認してロードします。

  1. プロファイルカーネルの情報
  2. ワークスペース情報に合わせて設定したツリー
  3. ビルドdrivers/usb/serial
  4. 確認vermagic、レイアウト、シンボル
  5. ロード管理者が自己責任で実行

画像はQTS 6.1とカーネル6.6.129-qnapを搭載したNASのものです。各フィールドは、このガイドの説明に従って入力しています。

01ワークショップの役割

QNAPの公開GPLアーカイブに掲載されているカーネルソースはQTS 5.2.3までで、このQTS 6.1搭載NASで動作中のカーネルは含まれていません。そのため、ワークショップは動作中のカーネルが公開する情報を読み取り、kernel.orgのカーネルツリーをそれに合わせて設定します。Kernelsページには、リリース、QNAPが使用したコンパイラー、QNAP製モジュールのvermagicとstruct moduleのレイアウト、モジュールの署名が必須かどうかを含むプロファイルが表示されます。

動作中のカーネル:リリース6.6.129-qnap、x86_64 TS-X74P、コンパイラーx86_64-QNAP_gcc13-linux-gnu-gcc 13.2.0、binutils 2.41、vermagic 6.6.129-qnap SMP preempt mod_unload、struct moduleは1152バイトでinitの位置は312、exitは1064。QNAP製モジュールに署名はなく、情報はQNAP製モジュールから取得
  • Examplesギャラリー(Apps → Examples)のKernel builder環境が必要です。Ubuntu 24.04にGCC 13とカーネルのビルドツールを備えています。ワークショップでは、動作中のカーネルをビルドしたものと同じGCCメジャーバージョンが必要で、ワークスペースの準備前に確認します。
  • 準備、ビルド、ロードには管理者ロール、確認には開発者ロールが必要です。rootで動作するエディターのターミナルでは、同じ手順をbvs kernelコマンドで実行できます。

02ワークスペースを準備する

ワークスペースは動作中のカーネルに正確に対応するカーネルツリーで、データフォルダーのkernels/<release>に置かれます。KernelsページでPrepare the workspaceを押します。

  1. Source:推奨されるソースのままにします。QNAP自身のツリーには古いカーネルしかないため、6.6.129ではkernel.orgのツリーが選ばれます。 カーネルソース:kernel.orgのLinux 6.6.129が推奨、このカーネルを含み、134 MBをダウンロード。QNAPのQTS 5.2.3 GPLソースには5.10.60、4.14.24、4.2.8のカーネルが含まれ、別バージョン、780 MB
  2. Environment:kernel-builder。Extra settingsには、USBシリアルのコアとCH341ドライバーを指定するUSB_SERIAL=mとUSB_SERIAL_CH341=mを1行ずつ入力します。Build the whole kernelはオフのままにして、Prepareを押します。 6.6.129-qnapのワークスペース準備:Sourceは推奨値、Environmentはkernel-builder、Extra settingsはUSB_SERIAL=mとUSB_SERIAL_CH341=m、Build the whole kernelは未選択、Prepareボタン
  3. ジョブがソースを展開し、プロファイルと指定した設定に従って構成し、モジュールをビルドできる状態にします。続いて、ツリーのビルド対象が動作中のリリースと完全に一致することを確認します。Workspaceカードにreadyと表示されます。準備に失敗した場合、以前のツリーは保持されます。 Workspace、状態ready:ソースはkernel.orgのlinux-6.6.129、構成はUSB_SERIAL=mとUSB_SERIAL_CH341=mを含むdefconfig+profile、環境はkernel-builder、Build modulesとDeleteボタン

03プロジェクト

New projectのKernelには、自作のHelloモジュールとch341ドライバーの2つのテンプレートがあります。USB serial driver ch341を選びます。

New projectのKernelテンプレート:Kernel moduleはKbuildとMakefileを含むHelloカーネルモジュール。選択中のUSB serial driver ch341はCH340およびCH341 USBシリアル変換アダプター用のカーネル標準ch341ドライバー

プロジェクトには、ワークショップのコマンドを各ターゲットで実行するMakefileと、NASのランナー用ワークフローが含まれます。

# プロジェクトのMakefile。エディターのターミナルでrootとして実行
make prepare   # bvs kernel prepare --option USB_SERIAL=m --option USB_SERIAL_CH341=m
make           # bvs kernel make --dir drivers/usb/serial
make check     # bvs kernel check ch341
make load      # bvs kernel load ch341
make unload    # bvs kernel unload ch341

ワークフローはpushのたびに--build-onlyでドライバーをビルドし、確認します。そのビルドのch341.koは実行結果のアーティファクトmodulesに保存され、ワークスペースのmodules/フォルダーには入りません。そのため、make loadは自分でビルドしたモジュールを引き続きロードします。

04ドライバーをビルドする

KernelsページのBuild modulesは、プロジェクトのフォルダーまたはカーネルツリー内のディレクトリをビルドします。ch341ドライバーはツリーの一部なので、A directory of the kernel treeを選び、drivers/usb/serialと入力します。プロジェクト内でのmakeも同じ処理を行います。

6.6.129-qnapのBuild modules:What to buildはA directory of the kernel tree、Directoryはdrivers/usb/serial、Targetsは空欄、Buildボタン

ビルドによってch341.koとusbserial.koが生成されます。ワークスペースはch341.koをmodules/に保持します。usbserial.koはQNAPが提供しており、ロードにはQNAPのコピーを使用するため、保持しません。

ワークスペースのモジュール:bvs_helloとch341はいずれも未ロード。サイズ、ビルド日、CheckとLoadボタンを表示

05動作中のカーネルとの互換性を確認する

Checkはモジュールを動作中のカーネルと比較します。対象はvermagic、struct moduleのサイズとinitおよびexitの位置、署名の必要性、依存するモジュール、必要なすべてのシンボルです。各検出結果には、不一致の内容と対処方法が示されます。

ch341の確認結果:ロード可能。このカーネルはデータシンボルを列挙しないため、2つのシンボルjiffiesとkmalloc_cachesを照合できず、どちらかが欠けていればロード時にカーネルがモジュールを拒否するという警告

QNAPのカーネルはデータシンボルを列挙しないため、確認ではjiffiesなどのシンボルを警告として表示します。コマンドラインのbvs kernel check ch341は、モジュールをロードしてはいけない場合、終了ステータス3で終了します。

06ロードとその影響

モジュールはカーネル内部で、カーネルと同じすべての権限を持って動作します。不具合のあるモジュールはNASを停止させるおそれがあります。明確な目的で自分がビルドしたものだけを、再起動できるNASでロードしてください。

  • Load(管理者)またはmake loadは再度確認を実行し、依存するモジュールから順にロードします。この例ではQNAPのusbserialが先です。確認でエラーが出たモジュールはロードされません。Unloadはモジュールを取り除きますが、使用中のモジュールはロードされたままです。ロードとアンロードはすべてlog/kernel-modules.logに記録されます。
  • 手動でロードしたモジュールは再起動後にはなくなります。毎回の起動時にロードするには、App Builderアプリのカーネルモジュールにその名前を指定します。アプリの有効化時にロードされ、その後もパッケージの起動ごとに再ロードされます。
  • パッケージがモジュールをロードした起動中に、パッケージの正常な停止を経ずにNASが停止した場合(クラッシュ、停電、ハードリセット)、次の起動ではそのモジュール群を読み込みません。いずれかのモジュールがクラッシュの原因だった可能性があるためで、通知に名前が表示されます。モジュールを手動でロードするか、そのアプリを再度有効にすると、起動時に再びロードできるようになります。
  • QTSの更新でカーネルが変わったら、新しいカーネルのワークスペースを準備してモジュールを再ビルドします。バックアップにはkernels/は含まれません。