
このワークショップセッションでは、EV充電器からファームウェアを抽出し、そのファームウェアを詳しく解析して、最終的にエミュレートすることで、サービスとリアルタイムにやり取りできるようにします。
このハンズオンデモでは、柔軟なファームウェア抽出ツールであるUnblobを体験していただきます。 このワークショップセッションでは、EV充電器からファームウェアを抽出し、ファームウェアを詳しく調べ、最終的にエミュレーションして、サービスとリアルタイムにやり取りできるようにします。Unblobはハードウェア版とダウンロード版の両方のファームウェアに対応しているため、ターゲットとなる環境は豊富です。事前経験は不要で、あらゆるスキルレベルに適したセッションです。皆様のご参加をお待ちしています。
私たちのターゲットは、Phoenix Contact製の電気自動車充電ステーションコントローラです。詳細は こちらをご覧ください。
CHARX control modular、AC充電コントローラ、組み込みLinuxシステム搭載、IEC 61851-1、動作モード: スタンドアロン、クライアント、サーバー
インターフェース:
- イーサネット (2x)
- セルラー通信 (4G/2G)
- CHARX control modular システムバス
- MICRO-USB type C
通信プロトコル:
- OCPP 1.6J
- Modbus/TCP
- MQTT
接続可能な周辺機器:
- エネルギー計
- RFID
- DC残留電流検出
- DINレールマウント
このワークショップで必要ないくつかのツールがあります。次のように install-prerequisites スクリプトを実行してインストールできます。```sh
./install-prerequisites
## ファームウェアの入手
ファームウェアはベンダーのウェブサイトから入手できます。このリポジトリには
`download-firmware` というスクリプトがあり、ブラウザを開くことなく
ファームウェアを取得するために使用します。
今回の焦点は、必要なものがすべて含まれているベンダー提供のファームウェアです。
ただし、同様のワークフローは、実機から抽出したメモリダンプにも適用できます。
ここで興味深いのは、実機を必要とせずに抽出、探索、エミュレーションができることです。
## Unblob による抽出
まず、すべての依存関係が利用可能であることを確認しましょう。```
unblob --show-external-dependencies
The following executables found installed, which are needed by unblob:
7z ✓
debugfs ✓
jefferson ✓
lz4 ✓
lziprecover ✓
lzop ✓
sasquatch ✓
sasquatch-v4be ✓
simg2img ✓
ubireader_extract_files ✓
ubireader_extract_images ✓
unar ✓
zstd ✓
これでunblobを使ってファームウェアを抽出できます:``` unblob CHARXSEC3XXXSoftwareBundleV190.raucb
標準的なノートPCでは、抽出に約3分かかります。プログレスバーが進んでいくのが確認できるはずです:

抽出が完了すると、ディレクトリが表示されるはずです。その名前は
`CHARXSEC3XXXSoftwareBundleV190.raucb_extract` です。移動して
その中に入って、コンテンツを一覧表示できます。
### チャンク、未知のチャンク
Unblobは、ファイル内のデータのチャンクを特定することで動作します。チャンクが
圧縮ストリームであれば解凍されます。ファイルシステムまたはアーカイブであれば、
抽出されます。抽出または解凍が成功した場合、ディスクに切り出されたチャンクは、
スペースを回復するために削除されます。
ここでは、SquashFSバージョン4のリトルエンディアンのチャンクがディスクに切り出され、抽出され、
削除されました。ファイル(したがって抽出ディレクトリも)は、
`{start_offset}-{end_offset}.{type}` という命名規則で名前が付けられます。
squashfsファイルシステムの後に、11KB分の "unknown" チャンクが存在することがわかります。```
./0-132173824.squashfs_v4_le_extract
./132173824-132184833.unknown
それに対して binwalk を実行すると、中に何が含まれているか確認できます:```
binwalk 132173824-132184833.unknown
0 0x0 Object signature in DER format (PKCS header length: 4, sequence length: 10997 58 0x3A Certificate in DER format (x509 v3), header length: 4, sequence length: 4372 4434 0x1152 Certificate in DER format (x509 v3), header length: 4, sequence length: 4387
openssl で証明書を確認できます:```
dd if=132173824-132184833.unknown bs=1 skip=58 | openssl x509 -in /dev/stdin -inform der -noout -text
dd if=132173824-132184833.unknown bs=1 skip=4434 | openssl x509 -in /dev/stdin -inform der -noout -text
つまり、ファームウェアはおそらくベンダーの秘密鍵で署名されており、デバイスはファームウェアが本物であることを確認できるというわけです。
これがunblobの利点のひとつです。未知の未知を、調査可能な既知の未知に変えてくれます。
squashfs ファイルシステムの内容を見てみましょう:``` ls -al 0-132173824.squashfs_v4_le_extract total 460532 drwxrwxr-x 4 kali kali 4096 dec 5 09:51 . drwxrwxr-x 3 kali kali 4096 dec 5 09:51 .. -rw-rw-r-- 1 kali kali 20971520 sep 8 09:59 bootimg.vfat drwxrwxr-x 3 kali kali 4096 dec 5 09:51 bootimg.vfat_extract -rwxrwxr-x 1 kali kali 2654 sep 19 2022 hook -rw-rw-r-- 1 kali kali 442 sep 8 09:59 manifest.raucm -rw-rw-r-- 1 kali kali 450584576 sep 8 09:59 root.ext4 drwxrwxr-x 22 kali kali 4096 sep 8 09:57 root.ext4_extract
プレーンテキストのマニフェスト、シェルスクリプト、1つのMBR、そしてEXT4ファイルシステムが見えます:```
find -maxdepth 1 -type f -exec file {} \;
./manifest.raucm: ASCII text
./hook: a /usr/bin/env sh script, ASCII text executable
./bootimg.vfat: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, reserved sectors 4, root entries 512, sectors 40960 (volumes <=32 MB), Media descriptor 0xf8, sectors/FAT 40, sectors/track 63, heads 255, hidden sectors 163158016, reserved 0x1, serial number 0xd09aad9c, label: "KERNEL ", FAT (16 bit)
./root.ext4: Linux rev 1.0 ext4 filesystem data, UUID=8ed19606-02c4-42e7-9cfb-1a2839f93ec4 (extents) (large files) (huge files)
bootimg.vfat と root.ext4 はどちらも unblob によって処理され、抽出されました。
VFAT パーティションには、ブートと OS に関連するすべてのもの(Linux カーネル、DTB、
TEE)が含まれています:```
oftree: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756
tee.bin: data
zImage: Linux kernel ARM boot executable zImage (little-endian)
zImage-imx6ul-ksp0632.dtb: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756
unblob は少し貪欲で、Linux カーネル(`zImage`)から
ELF ファイルと CPIO アーカイブを抽出します。これらは
最小限のカーネルと RAM ディスクに対応します。
EXT4 ファイルシステムには、Linux カーネルが起動時に
マウントするルートファイルシステムが含まれています。```
ls -alh root.ext4_extract
total 88K
drwxrwxr-x 22 kali kali 4,0K sep 8 09:57 .
drwxrwxr-x 4 kali kali 4,0K dec 5 09:51 ..
drwxrwxr-x 2 kali kali 4,0K dec 5 09:51 bin
drwxrwxr-x 3 kali kali 4,0K dec 5 09:51 boot
drwxrwxr-x 16 kali kali 4,0K sep 8 09:56 data
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 dev
drwxrwxr-x 53 kali kali 4,0K dec 5 09:51 etc
drwxrwxr-x 18 kali kali 4,0K sep 8 09:56 home
drwxrwxr-x 2 kali kali 4,0K jul 18 03:13 identity
drwxrwxr-x 9 kali kali 4,0K dec 5 09:51 lib
drwxrwxr-x 2 kali kali 4,0K jul 18 03:14 log
drwxrwxr-x 2 kali kali 4,0K sep 8 09:57 lost+found
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 media
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 mnt
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 proc
drwxrwxr-x 2 kali kali 4,0K sep 8 09:57 run
drwxrwxr-x 2 kali kali 4,0K dec 5 09:51 sbin
drwxrwxr-x 2 kali kali 4,0K jul 18 03:14 sdcard
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 sys
drwxrwxrwx 2 kali kali 4,0K jul 18 00:09 tmp
drwxrwxr-x 11 kali kali 4,0K sep 8 09:56 usr
drwxrwxr-x 11 kali kali 4,0K dec 5 09:51 var
unblob の別のオプションセットを使って、少し探索してみましょう。```
unblob -e /tmp/out -f -k -d 3 --report /tmp/report.json
--log /tmp/unblob.log CHARXSEC3XXXSoftwareBundleV190.raucb
ここでは (`-e`) で `/tmp/out` への抽出を続けますが、(`-f`) で上書きを強制し、
(`-k`) で切り出したチャンクを保持しつつ、(`-d`) で再帰の深さを
3 に制限しています。詳細レポート (`--report`) は `/tmp/report.json` に、ログファイル
(`--log`) は `/tmp/unblob.log` に書き出します。
ログファイルを見ると、unblob の内部動作がわかります。
レポートファイルには、分析されたファイル (サイズ、ファイル
タイプ、パス、マジック、MIMEタイプ、MD5/SHA1/SHA256 ハッシュ)、チャンク (サイズ、オフセット、
エントロピー分布)、およびタスク (抽出、展開、カービング) に関する詳細情報が含まれています。
少しの Python を使えば、これらのレポートファイルから素敵な可視化を
生成することができます。
このリポジトリにある `diagram.py` Python スクリプトを使用すると、それらを
自分で作成できます:```
python3 diagram.py /tmp/report.json sunburst
python3 diagram.py /tmp/report.json treemap
これらのコマンドを実行すると、ブラウザで以下のような plotly ベースの 可視化を含むページが開きます。


内部の概要が把握できたところで、デバイスを適切にエミュレーションするために 必要な情報を列挙していきましょう。
理想的には、以下の情報を収集する必要があります。
プラットフォーム、CPU、アーキテクチャに関する詳細を確認するには、 ファームウェアに埋め込まれたデバイスツリーブロブを調べるとよいでしょう。
VFATパーティションには、以下のDTBがあります。``` oftree: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756 zImage-imx6ul-ksp0632.dtb: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756
これらのファイルはデバイスツリーのバイナリ表現です。`device-tree-compiler` を使用することで、それらの
プレーンテキストソースを復元できます:```
dtc -I dtb -o zImage-imx6ul-ksp0632.dts zImage-imx6ul-ksp0632.dtb
dtc -I dtb -o oftree.dts oftree
DTS を確認してみてください。すぐにモデルのような興味深い詳細が見つかるでしょう:``` /dts-v1/;
/ { #address-cells = <0x01>; #size-cells = <0x01>; model = "Phytec phyBOARD-Segin i.MX6 UltraLite"; <----- right here compatible = "phytec,imx6ul-pbacd-10\0phytec,imx6ul-pcl063\0fsl,imx6ul";
CPU:```
cpus {
#address-cells = <0x01>;
#size-cells = <0x00>;
cpu@0 {
compatible = "arm,cortex-a7"; <---- here
device_type = "cpu";
reg = <0x00>;
clock-latency = <0xee6c>;
operating-points = <0xa9ec0 0x137478 0x80e80 0x11edd8 0x60ae0 0xfa3e8 0x30570 0xe7ef0>;
fsl,soc-operating-points = <0xa9ec0 0x137478 0x80e80 0x11edd8 0x60ae0 0x11edd8 0x30570 0x11edd8>;
clocks = <0x01 0x5d 0x01 0x1a 0x01 0x26 0x01 0xdb 0x01 0x38 0x01 0x39 0x01 0x19>;
clock-names = "arm\0pll2_bus\0pll2_pfd2_396m\0secondary_sel\0step\0pll1_sw\0pll1_sys";
arm-supply = <0x02>;
soc-supply = <0x03>;
dc-supply = <0x04>;
};
};
あるいは周辺機器さえも:``` --snip-- ethernet@2188000 { compatible = "fsl,imx6ul-fec\0fsl,imx6q-fec"; reg = <0x2188000 0x4000>; interrupts = <0x00 0x76 0x04 0x00 0x77 0x04>; clocks = <0x01 0x90 0x01 0x91 0x01 0x30 0x01 0x2c 0x01 0x2c>; clock-names = "ipg\0ahb\0ptp\0enet_clk_ref\0enet_out"; fsl,num-tx-queues = <0x01>; fsl,num-rx-queues = <0x01>; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <0x23>; phy-mode = "rmii"; phy-handle = <0x24>;
mdio {
#address-cells = <0x01>;
#size-cells = <0x00>;
ethernet-phy@1 {
reg = <0x01>;
interrupt-parent = <0x0b>;
interrupts = <0x02 0x08>;
micrel,led-mode = <0x01>;
clocks = <0x01 0x2c>;
clock-names = "rmii-ref";
status = "okay";
linux,phandle = <0x24>;
phandle = <0x24>;
};
ethernet-phy@2 {
reg = <0x03>;
micrel,led-mode = <0x01>;
clocks = <0x01 0x2d>;
clock-names = "rmii-ref";
status = "okay";
linux,phandle = <0x13>;
phandle = <0x13>;
};
};
};
--snip-- flexcan@2090000 { compatible = "fsl,imx6ul-flexcan\0fsl,imx6q-flexcan"; reg = <0x2090000 0x4000>; interrupts = <0x00 0x6e 0x04>; clocks = <0x01 0x94 0x01 0x95>; clock-names = "ipg\0per"; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <0x0f>; xceiver-supply = <0x10>; };
flexcan@2094000 { compatible = "fsl,imx6ul-flexcan\0fsl,imx6q-flexcan"; reg = <0x2094000 0x4000>; interrupts = <0x00 0x6f 0x04>; clocks = <0x01 0x96 0x01 0x97>; clock-names = "ipg\0per"; status = "disabled"; };
### Linux カーネルのバージョン情報
圧縮されたカーネルを含む VFAT パーティション内を grep することで、Linux カーネルのバージョンを特定できます:```
grep 'Linux version' . -ra
./zImage_extract/7296-6371487.lzo_extract/7296-6371487:
Linux version 5.15.195 (oe-user@oe-host) (gcc version 8.3.0 (GCC)) #1 SMP PREEMPT
./zImage_extract/7296-6371487.lzo_extract/7296-6371487:
Linux version %s (%s)Bluetooth subsystem version %u.%uHCI socket registration failed
別の方法としては、EXT4ルートファイルシステム内のカーネルモジュールを調べることです:```
modinfo ./CHARXSEC3XXXSoftwareBundleV190.raucb_extract/0-138014720.squashfs_v4_le_extract/root.ext4_extract/lib/modules/5.15.195/kernel/net/bluetooth/bnep/bnep.ko.xz
filename: ./CHARXSEC3XXXSoftwareBundleV190.raucb_extract/0-138014720.squashfs_v4_le_extract/root.ext4_extract/lib/modules/5.15.195/kernel/net/bluetooth/bnep/bnep.ko.xz
alias: bt-proto-4
license: GPL
version: 1.3
description: Bluetooth BNEP ver 1.3
author: Marcel Holtmann [email protected]
srcversion: 86266D360814678CE0C94E9
depends:
intree: Y
name: bnep
vermagic: 5.15.195 preempt mod_unload modversions ARMv7 thumb2 p2v8
parm: compress_src:Compress sources headers (bool)
parm: compress_dst:Compress destination headers (bool)
## エミュレーション
ファームウェアパッケージ内にコンパイル済みカーネルが既に含まれている場合もありますが、このカーネルは特定のマシン(Phytec phyBOARD-Segin i.MX6 UltraLite)向けにコンパイルされています。
このカーネルを適切に使用するには、このカーネルがコンパイルされた正確なマシンのエミュレーション上で、このカーネルを実行できる必要があります。それがQEMUのマシンリストにまだ載っていない場合は、かなりの時間がかかります。注:QEMUには評価ボードマシン(`mcimx6ul-evk - Freescale i.MX6UL Evaluation Kit (Cortex-A7)`)が用意されていますが、正確には一致しません。
その代わりに、理論上は、QEMUマシンを選択し、ファームウェアイメージ内で見つかるさまざまなメタデータを使用して、そのマシン向けのカーネルを構成およびビルドできます。そうすれば、ファイルシステム内のすべてを、可能な限りオリジナルに近い形で実行することもできます。
ここから、いくつかの選択肢があります。
- *ユーザー空間エミュレーション*: 独自のカスタムramfs/rootfsでブートし、その後ターゲットファームウェアのrootfsをロードして、そこにchrootしてエミュレートできます。
- *フルシステムエミュレーション*: ターゲットファームウェアのrootfsを直接ブートしてみる(QEMUマシンに直接渡す)こともできます。
ユーザー空間エミュレーションは通常、制限がありますが、特定のバイナリを調査、デバッグ、および悪用するには優れた方法です。ユーザー空間エミュレーションのニーズには、Saumil Shahによる[EMUX](https://github.com/therealsaumil/emux)をぜひご覧になることを強くお勧めします。
いずれにせよ、ターゲットファームウェアが期待しているものにできる限り近い、QEMUマシン内でブートするカーネルが依然として必要です。
### QEMUマシン
柔軟性を備えた汎用マシンの候補は、ほんのわずかしかありません。かなりの試行錯誤の結果、`virt`
(https://qemu.readthedocs.io/en/latest/system/arm/virt.html) は、私たちの目的に対して良好な柔軟性/性能の比率を持つようです。
特定のQEMUマシン用にカーネルをビルドする場合、QEMUがバンドルしている一般的なvirtioデバイスを使用できるようにしておくのがおそらく最善です。設定では、これらは次の1つ以上を意味する場合があります。```
CONFIG_VIRTIO=y
CONFIG_SCSI_VIRTIO=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BLK=y
まだまだあります!このリストは不完全です。
カーネルと同一(または少なくとも非常に似た)vermagic文字列を持つカーネルを使用することは有益です。システム内のあらゆる種類のコンポーネントがカーネルのvermagicをチェックし、期待と異なる場合に失敗する可能性があります。これはカーネルモジュールで最も一般的です。カーネルは通常、自身と一致するvermagicを持たないモジュールのロードを拒否します。カーネルレベルでこれを無視するようにカーネルにパッチを当てることはできますが、文字列の最初の「カーネルリリース」部分がカーネルモジュールのリリース文字列と一致する必要があります。これはmodules.depの検索パスとして使用されるためです。
Phoenix Contactファームウェアでは、vermagicは 5.15.195 preempt mod_unload modversions ARMv7 thumb2 p2v8 です。
vermagic文字列の形式は次のとおりです(include/linux/vermagic.h から):```c
#define VERMAGIC_STRING
UTS_RELEASE " "
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS
MODULE_ARCH_VERMAGIC
- カーネルリリース = カーネルバージョン + `CONFIG_LOCALVERSION` 文字列。
- SMP = `CONFIG_SMP`
- PREEMPT = `CONFIG_PREEMPT`
- mod_unload = `CONFIG_MODULE_UNLOAD`
- modversions = `CONFIG_MODVERSIONS`
- ARMv7 thumb2 p2v8 = `MODULE_ARCH_VERMAGIC` (カーネルがコンパイルされるアーキテクチャに関連しており、したがって渡されるコンパイラ/アーキテクチャオプションに関連しています。)
抽出したカーネルソースを入手したら、vermagic 文字列の比較がそれほど厳しくないようにパッチを適用できます。kernel/module.c で、return -ENOEXEC をコメントアウトするだけです:```diff
} else if (!same_magic(modmagic, vermagic, info->index.vers)) {
pr_err("%s: version magic '%s' should be '%s'\n", info->name, modmagic, vermagic);
- return -ENOEXEC;
+ // return -ENOEXEC;
}
if (!get_modinfo(info, "intree")) {
It may not necessarily be useful in the long run, but it’s good for testing, as long as there’s slight discrepancies between our kernel vermagic and the module vermagic. The modules (will mostly) still load.
NOTE: here we provide an already built kernel that matches the target requirements so you don't need to compile one yourself. It was built with an in-house script that:
multi_v7_defconfig to set initial configkernel/module.cVIRTIO options and specific subsystems like
USB or CANBUSLet's go over the different parameters of our qemu-system-arm command. We provide the kernel this way:```sh
qemu-system-arm -M virt,highmem=off
-m ${AVAILABLE_MEM_GB}G -smp ${CPU_CORES} -cpu cortex-a15
-kernel zImage
EXT4ファイルシステムイメージは、SCSIディスクとして接続されています:```sh
-device virtio-scsi-device \
-device scsi-hd,drive=SystemDisk \
-drive file=${FIRMWARE_IMAGE},format=raw,if=none,id=SystemDisk
適切なコンソール出力は、次のようにして設定します:```sh
-append "${BOOT_PARAMS}"
-no-reboot
-nographic
-serial mon:stdio \
The `BOOT_PARAMS` are set in `config.ini` and corresponds to the actual kernel
bootcmd, with two small adaptations (console path and rootfs path).
`BOOT_PARAMS` は `config.ini` で設定され、実際のカーネルブートコマンドに対応しています。ただし、2つの小さな変更(コンソールパスとrootfsパス)が加えられています。
### Networking
### ネットワーク
Now that we have a working emulated system, it's time to set up networking. The target has the following:
動作するエミュレートシステムができたので、次はネットワークを設定します。ターゲットには以下があります:
- two Ethernet interfaces (`eth0` and `eth1`)
- 2つのイーサネットインターフェース(`eth0` と `eth1`)
- one CANbus interface (`can0`)
- 1つのCANバスインターフェース(`can0`)
- one USB interface that can act as Ethernet over USB (`usb0`)
- USB over Ethernetとして機能する1つのUSBインターフェース(`usb0`)
- a Qualcomm High Sierra cellular modem (`ppp0`)
- Qualcomm High Sierraセルラーモデム(`ppp0`)
Emulating cellular modem and USB interfaces is a pain with QEMU, and not really
required for the device operation since those interfaces are "optional". The
CAN interface is there to allow the controller to talk to other controllers or
charging stations. The `eth0` interface provides upstream connectivity by
requesting a DHCP lease by default while `eth1` is set to 192.168.4.1 and is
there if you want to daisy chain multiple controllers.
セルラーモデムとUSBインターフェースのエミュレーションはQEMUでは厄介であり、これらのインターフェースは「オプション」であるため、デバイスの動作には実際には必要ありません。CANインターフェースは、コントローラが他のコントローラや充電ステーションと通信できるようにするためにあります。`eth0` インターフェースは、デフォルトでDHCPリースを要求して上流への接続を提供します。一方、`eth1` は192.168.4.1に設定されており、複数のコントローラをデイジーチェーン接続したい場合に使用します。
The ethernet interfaces are set as TAP interfaces and attached like this:
イーサネットインターフェースはTAPインターフェースとして設定され、次のように接続されます:```
-netdev tap,id=tap0net,ifname=${ETH_1},script=no,downscript=no \
-device virtio-net-device,netdev=tap0net,mac=${ETH_1_MAC} \
-netdev tap,id=tap1net,ifname=${ETH_0},script=no,downscript=no \
-device virtio-net-device,netdev=tap1net,mac=${ETH_0_MAC} \
CANBUSインターフェースは、単なるPCIインターフェースであり、次のように接続されます:```
-object can-bus,id=canbus0
-device kvaser_pci,canbus=canbus0
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0 \
以下の図は、ネットワーク構成がどのようになるかを示しています:

Phoenix Contact が推奨するように、コントローラー同士をデイジーチェーン接続してコントローラー間通信を試したい場合は、次のような構成を使用できます:

## 準備はいい?セット。起動!
すべてが配置されたので、起動するときが来ました!
まず、すべてのネットワークインターフェースを次のように設定する必要があります:```
sudo ./ifup.sh
上流インターフェースが config.ini で正しく設定されていることを確認してください:```
OUT_IF="eth0"
その後、エミュレータを起動できます:```
sudo ./launch.sh
取得したアドレスがログに表示されます:``` Dec 5 10:07:46 ev3000 daemon.info avahi-daemon[1047]: Registering new address record for 192.168.4.1 on eth1.IPv4. Dec 5 10:07:46 ev3000 daemon.info avahi-daemon[1047]: Registering new address record for 192.168.88.181 on eth0.IPv4.
### SSH経由のアクセス
その後、`user-app` ユーザーを使用して、エミュレートされたデバイスにSSH接続できます:```sh
ssh [email protected]
パスワードは「user」です。初回ログイン時に変更を強制されます:```sh ssh [email protected] The authenticity of host '192.168.88.181 (192.168.88.181)' can't be established. ED25519 key fingerprint is SHA256:qMupzEehNFpx6eaGZ4d3AY5Jlms3Pmxh3/yg9OGA28o. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.88.181' (ED25519) to the list of known hosts. [email protected]'s password: WARNING: Your password has expired. You must change your password now and login again! Changing password for user-app Old password: Enter the new password (minimum of 5 characters) Please use a combination of upper and lower case letters and numbers. New password: Re-enter new password: passwd: password changed. Connection to 192.168.88.181 closed.
### Web インターフェース
Web インターフェースには http://192.168.4.1 からアクセスできます。
デバイスの起動中はエラーメッセージが表示されることがあります。すべてが起動して動作し始めると、
次の画面が表示されます:

以下のアカウントでログインできます:
| username | password |
|----------|----------|
| manufacturer | manufacturer |
| operator | operator |
### CAN トラフィック
すべてが起動して動作しているとき、コントローラーが送信する CAN トラフィックをキャプチャできます:```
candump -i can0
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
注記:QEMU バージョン 8.x は、何らかの理由で CAN コントローラの接続にいくつか問題があるようです。