Translate

2026/07/25

Z3805Aファームウェア関連/ MC68331/ Atmega AVR / MSP430 /Ghidra

2026-5~

Z3805A電源断トラブル復帰再稼働関係







 

Chapter 1 .


2026-5
メーカー?消滅ツールからリバースして流用出来るか(AVR系)

  • AVR(ATmega)のHEXファイルを解析するための最も優れた無料かつ標準的なリバースエンジニアリングツールは、米国家安全保障局(NSA)がオープンソース化した Ghidra(ギドラ) です。
手元にあるAVR8HEXソースを、ブラックボックスから「人間が読めるC言語に近い状態」までリバースするための手順とツール、そして今回の目標(恒星時変換の追加など)への繋げ方を詳しく解説します。

🛠️ AVR(ATmega)のバイナリをリバースする最強のツール群

バイナリファイル(HEX)しか手元になく、元のC言語ソースコードがない状態から通信仕様を暴くには、以下のツールが非常に強力です。

1. Ghidra(ギドラ) — 推奨・最高峰のデコンパイラ

  • 特徴:完全に無料のプロフェッショナル向けリバースエンジニアリングツールです。 [1]
  • AVRへの対応ATmega328PやATmega8などのAVRアーキテクチャに標準対応しています。
  • 最大の強み:アセンブリ言語だけでなく、アセンブリを解析して人間が読める「C言語風のソースコード」に自動変換(デコンパイル)する機能を持っています。
  • 解析の手順
    1. Ghidraを立ち上げ、新規プロジェクトを作成してHEXファイルをインポートする。
    2. 言語選択で AVR8(またはターゲットのATmega型番)を指定する。
    3. 自動解析(Auto Analyze)を実行すると、本体との通信で使われている「隠された文字列(SCPIコマンドなど)」や、ボタン処理の条件分岐がC言語風のコードとして右画面に表示されます。

2. Radare2 / Cutter — 高機能なオープンソース・ディスアセンブラ

  • 特徴:ハッカーコミュニティで愛用されるリバースツールで、AVRマイコンのバイナリ解析(特にCTFやハードウェア解析のチャレンジ)で非常によく使われます。 [1, 2]
  • GUI版(Cutter)を使用すれば、プログラム全体の構造がフローチャート(グラフ表示)として視覚化されるため、「ボタンが押されたときに、どこへジャンプしてどのシリアルデータを送っているか」の処理の流れを目で追うことができます。

3. avr-objdump — 確実なコマンドラインツール

  • 特徴:Arduino IDEやMicrochip Studio(旧Atmel Studio)の裏で動いている公式の開発ツールチェーンに含まれるツールです。 [3]
  • コマンドライン(ターミナル)で以下のコマンドを叩くだけで、HEXファイルを一瞬で標準的なAVRアセンブラコードに書き直してテキスト出力してくれます。
    avr-objdump -m avr -D your_file.hex > disassembled.txt
    

🔍 このHEXソースから「何を」読み取るべきか?

元のサイトが消えており、HEXやbin しか残っていなくても、HEXをGhidraなどで開けば「追加機能の実現」に必要な核心データが数分で手に入ります。特に、バイナリ内の 「データセクション(文字列プール)」 を最優先で覗いてみてください。
以下のような、HP 58503A(またはZ3801A)本体をコントロール・照会するための SCPIコマンド文字列 がそのままの形(ASCIIテキスト)で埋め込まれている可能性が極めて高いです。
  • :GPS:POS?(位置・経度情報の取得 ➡️ 恒星時計算に必要な経度の自動取得に使えます
  • :TIme:UTMe? または :SYST:TIME?(UTC時刻の取得 ➡️ JST変換や恒星時計算のベースになります
  • :SYST:ERR?(アラーム内容・エラーログの取得 ➡️ アラーム表示に必須です
  • *CLS(ステータスクリア ➡️ アラームクリアボタンを押した時に本体へ投げるコマンドです
もしこれらのコマンド文字列がバイナリ内に見つかれば、先人の苦労(どのコマンドをどのタイミングで投げれば応答が返ってくるかという通信シーケンスの設計)をすべてそのまま拝借できます。

🎯 最終的な「勝ちルート」の提案

先人のATmega用のHEX(バイナリ)をそのまま100%リバースして完璧なコードに戻すのは骨が折れますが、「58503A本体とRS232Cでやり取りするためのテキストコマンド」さえ上記ツールで抽出できれば、もう勝ったも同然です。
その抽出したコマンドをメモし、コード自体は 現代の使い慣れた環境(Arduino IDEなど)で、ESP32やRaspberry Pi Pico、新しいATmega向けに一からC言語で書く 方式をおすすめします。これなら、
  1. 抽出したコマンドを定期的に58503A本体へ投げる。
  2. 返ってきたUTC時刻と経度を受け取る。
  3. マイコン内の使い慣れたC言語ライブラリで、JST(+9時間)恒星時(LAST) を計算し、現代の綺麗なカラー液晶に表示する。
  4. アラームクリアボタンが押されたら、本体にクリアコマンドを送信する。
という仕様が、リバースエンジニアリングの「良いとこ取り」だけで最も安全かつスマートに実現できます。
Ghidraの導入や、このHEXファイルを一度アセンブラや文字列に落とし込んでみる初期解析のステップなど、さらに進めたい手順があればお気軽につぶやいてください!


ATmega644ベースのHP Z3801A用カスタムコントローラ の回路図の設計思想をベースに、今回hp 58503-60010フロントパネル側で新しく判明した「3.6864MHzで駆動するSPIバス」へ適応(アドオン)させるための明確な方針を解説します。

1. 現状の回路図の構造分析(RS-232C直叩き)

回路では、左側の ADM232(RS-232CドライバーIC)を介して、本体背面のDSUB9(RS-232Cポート)とATmega644の PD0(RXD0) / PD1(TXD0) を繋いで通信しています。
表示は右側の並列(パラレル)接続されたキャラクター液晶 LCD1 へ出力し、ボタンは PA0〜PA3 に割り当てられた極めてストレートな調歩同期シリアル(UART)制御方式です。

2. 「フロントパネル用内部SPIバス」に対応させるための回路変更点

オリジナルのフロントパネル(58503-60010)と本体を繋ぐ J19コネクタ(IDC16ピン)内のSPIバス と直接通信させる場合、回路は以下のようにアップグレードする必要があります。

① MISO / MOSI / SCK ピンの割り当て変更

ATmega644(またはATmega1284P等)には、ハードウェアSPI機能が標準搭載されています。
回路図最上段にあるISP(書き込み用)コネクタに繋がっている以下のピンを、そのままJ19のSPI通信ピンへ「兼用」として引き出します。
  • PB5 (MOSI) ➡️ 本体からの表示データ受信、または本体へのコマンド送信(本体側の仕様に合わせる)
  • PB6 (MISO) ➡️ 双方向通信時の割り当て
  • PB7 (SCK) ➡️ 本体側から供給される(またはマイコン側から送る)シリアル同期クロック
  • 任意の空きGPIO(例:PB4など) ➡️ SS / CS(チップセレクト) として割り当て

② レベルシフタ(電圧変換)の検討

  • 現状の回路:ATmega644は +5V で駆動しています。
  • 58503Aの内部バス側:もし本体側の内部SPIバスの信号が 3.3Vロジック だった場合、5V駆動のATmegaに直接繋ぐとポートを破損するか、正常に認識しません。これは確認が必要です。
  • 3.3Vだった場合の対策:J19のSPI信号線の途中に、安価な 双方向ロジックレベル変換モジュール(FXMA108や4回路タイプのものなど) を挟み、安全に5V ↔ 3.3Vの変換を行います(本体側が5Vロジックであれば直結で構いません)。

③ ADM232(RS-232Cポート)の処遇

内部バス(SPI)との通信が確立できれば、左側の ADM232およびDSUB9ピンは回路から完全に削除(無実装)することが可能 です。これにより基板サイズを大幅にコンパクトにできます。

3. ファームウェア(移植・アドオン)の設計イメージ

手元にあるHEXソースのロジックを、SPI通信へと舵を切る場合のプログラムの書き換え構成(擬似コードイメージ)です。
// 現代のArduino(ATmega)環境での実装イメージ
#include <SPI.h>

void setup() {
    // ハードウェアSPIをスレーブ(またはマスター)として初期化
    // 3.6864MHzの4分周(460.8kHz)や16分周など、本体の速度に合わせる
    SPI.begin(); 
    
    // スイッチ(PA0-PA3)やLEDの初期化
    pinMode(A0, INPUT_PULLUP);
    ...
}

void loop() {
    // 1. 本体からJ19のSPI経由で送られてくる表示セグメント/テキストデータをバッファに受信
    if (SPI_data_available()) {
        char rx_byte = SPI.transfer(0x00);
        // りりっく氏の液晶表示ルーチンへデータを引き渡す
        update_custom_LCD(rx_byte); 
    }

    // 2. もし「アラームクリア」などのボタン(PA1等)が押されたら
    if (digitalRead(A1) == LOW) {
        // RS-232Cに送る代わりに、SPIバス経由で本体へクリアコマンド(キーコード)を送信
        SPI.transfer(CMD_ALARM_CLEAR); 
        delay(200);
    }
    
    // 3. 同時にUTCをJSTに変換、および経度から恒星時を計算して LCD1 へ描画
    display_time_modes();
}

💡 結論

この回路図の 「ATmega644 + キャラクター液晶 + スイッチ」の基本骨格は100%そのまま活かせます。
変更するのは「左側のRS-232C回路を無くし、上側のSPIピン(PB5〜PB7)をJ19コネクタへ繋ぎ変えるだけ」です。ハードウェア的には非常にシンプルなマイナーチェンジで対応可能です。
この構成であれば、液晶をさらに大きなOLEDやカラー液晶に変更して「UTC / JST / 恒星時」を3行同時に表示させるような、オリジナルを遥かに凌駕する高機能コントローラへ発展させることができます。
58503-60010  J19側のピンの物理的な配置(ピッチやコネクタ形状)など、基板設計に向けて次に詰めたい要素はありますか?


“Z3805A-J19の推定を含む本体側現状では以下。マニュアルだと58503-60010キットのリボンを差し込むだけで認識するかのように書かれている。
解ってる範囲は、以下。解明出来ていないのは#9~#15pin
J19(IDC16pin)(LED駆動は+5V正論理) (挿入抵抗)(フロント基板側) 
-1:LED(DS2)-Enable (909Ω)  
-2:GND  
-3:LED(DS3)-Active (909Ω)  
-4:LED(DS4)-Alarm (909Ω)  
-5:無実装(LED(DS5)-(NC)) (909Ω)  
-6:LED(DS6)-GPS Lock (909Ω)  
-7:GND  
-8:LED(DS7)-Hold Over (909Ω)  
-9:
-10:
-11:
-12:  
-13:GND  
-14:
-15:  
-16:+5V/LED(DS1)-Power (1600Ω)




----

Ghidra 12.1, JDK 21


GhidraでAVR8のベアメタルファームウェア(ATmega644など)を解析するには、ハーバードアーキテクチャとメモリマップドI/Oを使用しているため、特別な処理が必要です。Ghidraは静的解析に依存しているため、バイナリメモリマップを正しくインポートし、プロセッサ言語バリアントを指定することが重要です。 Jonas Lieb +1 1. 初期設定と言語選択 ダンプしたファームウェアをGhidraにインポートする際には、プロセッサアーキテクチャを手動で設定する必要があります。 Ghidraを開き、新しいプロジェクトを作成します。 バイナリ(通常はavrdudeで抽出したもの)をプロジェクトにドラッグアンドドロップします。 Stack Overflow +1 インポートダイアログで、GhidraがATmega644を自動的に検出しない場合があります。「言語」の横にある3つの点(…)をクリックしてください。 アーキテクチャとしてAVR8を選択し、atmega644(644がリストにない場合はatmega64)を選択し、バリアントを16(アドレス指定ビット)に設定して、little / gccを実行します。 Jonas Lieb ベースアドレスが0x0000に設定されていることを確認してください(GhidraはデフォルトでAVRのフラッシュメモリをここにマッピングします)。 Jonas Lieb 2. メモリセクションの定義 最新のオペレーティングシステムバイナリとは異なり、ATmegaファームウェアは特定のメモリセグメント内にコードとデータを混在させています。Ghidraの自動解析でI/OポートまたはEEPROMのマッピングがうまくいかない場合は、手動でマッピングする必要があります。 GitHub +1 ウィンドウ > メモリマップに移動します。 starkeblog.com Atmel ATmega644データシートに記載されているとおりにメモリブロックを追加または確認してください。 フラッシュ/コードセグメント:0x0000から始まります(実行可能、読み出し、実行)。内部SRAM:通常0x0000~0x10FF(読み出し、書き込み)。 I/Oレジスタ:通常0x0020~0x005F(拡張コントローラの場合は最大0x00FF)。 Jonas Lieb +1 3. 自動解析と逆アセンブルの実行 Ghidraの自動解析(解析→自動解析)をデフォルトオプションで実行します。 Jonas Lieb AVRは16ビット命令を使用するため、生の16進数として表示される(または制御フローの切り捨て警告が表示される)未解析バイトは、手動で逆アセンブルする必要があります。 リストビューで未解析バイトを選択します。 キーボードのDキーを押して強制的に逆アセンブルを実行します。 Fキーを押して、逆アセンブルされた命令を関数に変換します。 Medium ·Ryan Cornateanu  +1 4. 割り込みベクタテーブルの解決 リストビューを見る際に最も重要な最初のステップは、バイナリの先頭にある割り込みベクタテーブル(IVT)を確認することです。最初の命令は通常、RESETベクタへのJMP命令です。 Jonas Lieb  +1 0x0000に移動します。 0x0000の命令をresetと命名します。 Ghidraが制御フローを追跡しやすくするために、後続のベクタ(例:INT0、TIMER0_OVF)をメモリマップに従って命名します。 Jonas Lieb 5. IOレジスタ定義の適用 逆コンパイルされたCコードを読みやすくするために、レジスタマッピングをインポートできます。これにより、コードがRAM_0x3eのような生の16進アドレスを表示するのではなく、レジスタマッピングをインポートできます。 GitHub スクリプトマネージャを開きます(ウィンドウ > スクリプトマネージャ)。 CreateAVR8GDTArchiveScript.javaが存在する場合は実行し、存在しない場合はATmega644周辺機器領域(PORTA、DDRB、TCCR1Aなど)の列挙型を手動で定義してください。 Attify +1 AVRアーキテクチャ向けにGhidraを設定する方法、メモリマップと割り込みベクタを操作する方法については、以下を参照してください。











 

Chapter 2 .


2026-8
Z3805Aファームウェア rev.D の、furuno GT-8031B  初期化コード探索

58503Aファームウェア参考
https://github.com/willhb/HP-58503A-Firmware

rev.Dファームウェアバックアップ
https://github.com/Bluestackson/Z3805A_rev.D_Samsung



---

実行機(Samsung版Z3805A(rev.D版/rev.C版))からのファームウェアチップから .bin 取り出し。-rev.D:Z3805-68003 (5NV00GP),  -rev.C:Z3805A-68001 (6E901C3  3627)

(rev.D)
Bank_1 (id:27F010)
MSB u14 8004_1M_u14_revD_00e44586_b.bin
LSB u12 8002_1L_u12_revD_00f5a2e9_b.bin

Bank_2 (id:27F010)
MSB u13 8003_2M_u13_revD_01079fb7_b.bin
LSB u11 8001_2L_u11_revD_0114be42_b.bin



(AI(Gemini)生成powershell合成スクリプト)

$u14  = [System.IO.File]::ReadAllBytes("8004_1M_u14_revD_00e44586_b.bin")
$u12 = [System.IO.File]::ReadAllBytes("8002_1L_u12_revD_00f5a2e9_b.bin")
$u13  = [System.IO.File]::ReadAllBytes("8003_2M_u13_revD_01079fb7_b.bin")
$u11 = [System.IO.File]::ReadAllBytes("8001_2L_u11_revD_0114be42_b.bin")
$merged = New-Object byte[] 524288

# Bank 1 (U14 + U12) のインターリーブ処理
for ($i = 0; $i -lt 131072; $i++) {
    $merged[$i*2]   = $u14[$i]   # MSB
    $merged[$i*2+1] = $u12[$i]  # LSB
}

# Bank 2 (U13 + U11) のインターリーブ処理
for ($i = 0; $i -lt 131072; $i++) {
    $merged[262144 + $i*2]   = $u13[$i]   # MSB
    $merged[262144 + $i*2+1] = $u11[$i]  # LSB
}

[System.IO.File]::WriteAllBytes("Z3805A_D_comb_firmware.bin", $merged)
Write-Host "結合成功! 'Z3805A_D_comb_firmware.bin' (512KB) を作成しました。" -ForegroundColor Green




---

バイナリエディタで下見した所、手元のRev.D, Rev.C,  及び、ネット上の Rev.C(など複数)、全てが微妙に違う」困惑する結果に。Rev.Cは、概ね58503Aの物と同一(内部バージョンのみ相違?、Z3805A/Z3801A⇒58503)な様だ。Rev.D と Rev.C の違いは解る(GPSモジュールの違い/Furuno vs, OncoreVP)が、その他の違いは流布している情報以上に派生版が有る可能性を示しているのかもしれない(単に読み出しエラーのオチもありえるが)。また、Z3805A版の方がZ3801A版よりもコード部分が少し多く、逆にZ3805A版のメッセージ総数は減っている様だ。機種コードは「Z3801A」「Z3805A」「58503」の3種類があった。

rev.Dファーム内のGPSモジュール関連と見られるMODEL #記述には、 FURUNO GT-80, GT-77,GT-74, が有り、それらに対応しているらしい。rev.Cファーム内の相同位置のMODEL # は「空欄」の様だ。





0 件のコメント:

コメントを投稿