L 級新功能、PRD/Design/TDD/ADR 三方協作 + 互審 + M9-6 SDK 雙驗證、總計 ~9000 行文件。
範圍:
- A 階段(MVP、5 人天):KL520 + KL720 自動升級 KDP1 → KDP2
- B 階段(10.5 人天):手動降版面向一般使用者 + KL630 / KL730 擴展
- 合計 15.5 人天、安裝包 +7MB(保守 bundle 策略)
關鍵決策:
- 翻案 R5-Q9(progress.md 第二輪使用者決策「韌體燒錄 flash → B 砍掉」)
- 跨平台用 KneronPLUS Python C API、不用 DFUT.exe
- 多版本目錄結構選 C metadata(firmware/<chip>/{version}/ + CURRENT_VERSION)
- Kneron firmware redistribution 授權與 R5-B4 預置模型同性質、發佈前評估
文件產出:
- PRD v2.2(PRD-v2.md 495 行 + features/feature-firmware-management.md 599 行)
- Design v2.2(firmware-management.md 948 行 + control-panel.md §6a graceful shutdown)
- TDD v2.2(v2/firmware-management.md 823 行 + ADR-001 218 行)
- 8 份 research(含 M9-6 弱驗證 + 強驗證、~3200 行)
- 3 份三方互審報告(PM/Design/Architect cross-review)
M9-6 強驗證重大發現(影響 B 階段):
- KL730 product_id 實際是 0x732(不是 0x0730)
- KL630/KL730 firmware 是 embedded Linux rootfs(不是 .bin、不同代設計)
- KneronPLUS Python 沒 update_kdp_firmware_from_files 公開 API、warrenchen 走 ctypes
- 不影響 A 階段、B 階段 M9-8 需 spike
下一步:派 backend M9-1 起跑(bridge.py handle_firmware_upgrade)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
459 lines
19 KiB
Markdown
459 lines
19 KiB
Markdown
# .tar Firmware 處理研究:KL630 / KL730
|
||
|
||
> 對應 research index §41
|
||
> 範圍:KL630 / KL730 firmware 是 `.tar` 格式(不是 .bin)、SDK 處理路徑、解壓策略、安裝包衝擊
|
||
> 撰寫日期:2026-05-24
|
||
> 限制:純 plan、不出 code、所有「需 SDK 文件驗證」段落都明標註
|
||
> 路徑使用相對路徑(相對於 `/Users/jimchen/visionA/local-tool/`)
|
||
|
||
---
|
||
|
||
## 0. TL;DR
|
||
|
||
1. KL520 / KL720 是 `fw_scpu.bin` + `fw_ncpu.bin` 兩個 raw binary、KL630 / KL730 是 `kp_firmware.tar` + `kp_loader.tar` 兩個 .tar 包
|
||
2. **.tar 裡面包什麼、SDK 怎麼吃,需要在 B 階段 M9-6 milestone 驗證**——我們現在無法從 warrenchen 程式碼推斷(他們沒實作)
|
||
3. 兩個候選策略:
|
||
- **策略 X:runtime 解壓**(bridge.py 解 .tar 到 temp 目錄、餵解壓後的 .bin 給 SDK)
|
||
- **策略 Y:build time 解壓**(build script 解壓進 `firmware/<chip>/extracted/`、ship 解壓後的 .bin)
|
||
- **策略 Z:直接餵 .tar 給 SDK**(如果 SDK 支援 `load_firmware_from_tar` 之類 API)
|
||
4. **推薦策略 Y + Z 二選一、視 SDK 驗證結果**——不推薦策略 X(每次 connect 解壓浪費時間 + temp file 管理麻煩)
|
||
5. 安裝包大小衝擊估算:策略 Y 約 +5MB、策略 Z 約 +5MB(一樣、因為 .tar 跟 .bin 解壓後大小接近、壓縮率不高)
|
||
|
||
---
|
||
|
||
## 1. 為什麼 KL630 / KL730 是 .tar、不是 .bin
|
||
|
||
### 1.1 從 warrenchen bundle 看到的事實
|
||
|
||
```
|
||
local_service_win/firmware/
|
||
├── KL520/
|
||
│ ├── fw_scpu.bin ← raw binary
|
||
│ ├── fw_ncpu.bin ← raw binary
|
||
│ ├── fw_loader.bin ← raw binary
|
||
│ ├── dfw/minions.bin ← raw binary(DFUT 用)
|
||
│ └── VERSION ← "2.2.0"
|
||
├── KL720/
|
||
│ ├── fw_scpu.bin
|
||
│ ├── fw_ncpu.bin
|
||
│ └── VERSION ← "2.2.0"
|
||
├── KL630/
|
||
│ ├── kp_firmware.tar ← tar 打包
|
||
│ ├── kp_loader.tar ← tar 打包
|
||
│ └── VERSION ← "SDK-v2.5.7"(命名規則不同)
|
||
└── KL730/
|
||
├── kp_firmware.tar
|
||
├── kp_loader.tar
|
||
└── VERSION ← "SDK-v1.3.0"
|
||
```
|
||
|
||
### 1.2 推測原因(**待 SDK 文件驗證**)
|
||
|
||
從命名規則、版號規則、SDK 版本看:
|
||
|
||
| 觀察 | 推論 |
|
||
|------|------|
|
||
| KL520/KL720 VERSION 是 firmware 版本(2.2.0)、KL630/KL730 是 SDK 版本(SDK-v2.5.7)| KL630/KL730 是新世代 SDK(v2.x SDK release)、firmware 與 SDK 綁定打包 |
|
||
| KL520/KL720 用 `fw_scpu.bin` / `fw_ncpu.bin` 命名、KL630/KL730 用 `kp_firmware.tar` 命名| KneronPLUS v2/v3 改用統一 packaging 格式、把 scpu + ncpu + metadata 整包到一個 .tar |
|
||
| KL520/KL720 有 `fw_loader.bin`、KL630/KL730 有 `kp_loader.tar`| Loader 也用同樣的打包策略、可能裡面除了 binary 還含 manifest |
|
||
| KL730 SDK-v1.3.0 比 KL630 SDK-v2.5.7 低、跟 chip 推出時間有關| KL730 可能還在較舊 SDK release(warrenchen 取樣時的版本快照)|
|
||
|
||
### 1.3 .tar 內容可能性(**未驗證、僅猜測**)
|
||
|
||
`.tar` 通常會包:
|
||
- `fw_scpu.bin`
|
||
- `fw_ncpu.bin`
|
||
- `manifest.json` 或 `metadata.txt`(含版本、checksum、target chip 等)
|
||
- 可能含其他 firmware sub-module(FPP_FW 等視 chip 而異)
|
||
|
||
**驗證方式**(M9-6 必做):
|
||
```bash
|
||
mkdir -p /tmp/kl630_inspect
|
||
cd /tmp/kl630_inspect
|
||
tar -tvf /tmp/web_academy_prototype/local_service_win/firmware/KL630/kp_firmware.tar
|
||
tar -tvf /tmp/web_academy_prototype/local_service_win/firmware/KL630/kp_loader.tar
|
||
tar -tvf /tmp/web_academy_prototype/local_service_win/firmware/KL730/kp_firmware.tar
|
||
tar -tvf /tmp/web_academy_prototype/local_service_win/firmware/KL730/kp_loader.tar
|
||
# 紀錄每個 .tar 內含檔案清單、大小、結構
|
||
```
|
||
|
||
**本份研究無法跑這個 inspect**(Architect Agent 不執行 shell 變動類指令、且這應該在實機驗證階段做)——M9-6 milestone 必做、結果回填到本檔 §3。
|
||
|
||
---
|
||
|
||
## 2. KneronPLUS API 對 .tar 的處理(**全部待 SDK 文件驗證**)
|
||
|
||
### 2.1 可能的 API 設計
|
||
|
||
從 KneronPLUS Python SDK 既有 API pattern 推測:
|
||
|
||
| API 候選 | 簽名 | 可能性 |
|
||
|---------|------|-------|
|
||
| `kp.core.load_firmware_from_file(dg, scpu_path, ncpu_path)` | 既有 API、接受兩個 .bin | KL630/KL730 是否能接受 .tar 內容路徑?需要先解壓?|
|
||
| `kp.core.load_firmware_from_tar(dg, tar_path)` | 假設新 API | **未確認存在**——可能 SDK v3.x 才有 |
|
||
| `kp.core.update_kdp2_firmware_from_tar(dg, tar_path, auto_reboot)` | 假設新 API(KDP2 寫 flash 用) | **未確認**、推測對應 KL630/KL730 升級 |
|
||
| `kp.core.update_kdp_firmware_from_files(dg, scpu, ncpu, auto_reboot)` | 既有 API(A 階段用) | 對 KL630/KL730 可能不適用(KDP 是 KL520/KL720 老世代術語)|
|
||
|
||
### 2.2 從 warrenchen wheel 推斷
|
||
|
||
`local_service_win/KneronPLUS-3.1.2-py3-none-any.whl` 是 KneronPLUS 3.1.2、推測 API 命名應該已統一(v3.x 主版本)。
|
||
|
||
**驗證方式**(M9-6 必做):
|
||
```bash
|
||
cd /tmp
|
||
unzip /tmp/web_academy_prototype/local_service_win/KneronPLUS-3.1.2-py3-none-any.whl -d kneron_plus_inspect
|
||
# 找 kp/core.py 或對應的 wrapper
|
||
grep -rn "tar\|load_firmware\|update_kdp\|update_firmware" /tmp/kneron_plus_inspect/kp/
|
||
# 找所有 firmware-related 函數
|
||
grep -rn "^def " /tmp/kneron_plus_inspect/kp/core.py | grep -i "fw\|firmware"
|
||
```
|
||
|
||
**本份研究無法跑這個**——M9-6 必做。
|
||
|
||
### 2.3 從 visionA-local 既有 KneronPLUS wheel 推斷
|
||
|
||
需要知道我們既有 wheel 版本(**待查**):
|
||
|
||
```bash
|
||
# 假設安裝在 server/scripts/venv/ 或類似位置
|
||
ls server/scripts/*.whl 2>/dev/null # 如果是直接 ship wheel
|
||
pip show kneronplus 2>/dev/null # 如果是 installed package
|
||
```
|
||
|
||
**重要**:如果我們既有 wheel 比 warrenchen 的 3.1.2 還舊(例如 2.x),可能:
|
||
- 既有 wheel 不認 `KP_DEVICE_KL630` / `KP_DEVICE_KL730` enum → driver 升級必須先升 wheel
|
||
- 既有 wheel 沒有 .tar 處理 API → 必須升 wheel 才能支援 KL630/KL730
|
||
|
||
→ M9-6 評估「是否升級 KneronPLUS wheel」是 B 階段風險最高的決策點。
|
||
|
||
---
|
||
|
||
## 3. 大小估算(warrenchen 提供的 .tar 各多大)
|
||
|
||
### 3.1 .tar 檔案大小(從 warrenchen bundle 推斷)
|
||
|
||
```bash
|
||
# 在 M9-6 驗證階段執行(本份研究不執行 shell write 動作)
|
||
ls -lh /tmp/web_academy_prototype/local_service_win/firmware/KL630/
|
||
ls -lh /tmp/web_academy_prototype/local_service_win/firmware/KL730/
|
||
ls -lh /tmp/web_academy_prototype/local_service_win/firmware/KL520/
|
||
ls -lh /tmp/web_academy_prototype/local_service_win/firmware/KL520_kdp/
|
||
ls -lh /tmp/web_academy_prototype/local_service_win/firmware/KL720/
|
||
```
|
||
|
||
**預估值**(基於檔案類型常識):
|
||
|
||
| 路徑 | 預估大小 | 註 |
|
||
|------|---------|------|
|
||
| `KL520/fw_scpu.bin` | ~52KB | TDD L3219 記錄 |
|
||
| `KL520/fw_ncpu.bin` | ~40KB | TDD L3219 記錄 |
|
||
| `KL520/fw_loader.bin` | ~10KB | KDP1→KDP2 升級用 |
|
||
| `KL520/dfw/minions.bin` | ~50KB | DFUT 用、未來可能不 bundle |
|
||
| `KL520_kdp/fw_scpu.bin` | ~50KB | KDP1 降版用 |
|
||
| `KL520_kdp/fw_ncpu.bin` | ~40KB | KDP1 降版用 |
|
||
| `KL720/fw_scpu.bin` | ~150KB | KDP2、更複雜 |
|
||
| `KL720/fw_ncpu.bin` | ~100KB | |
|
||
| `KL630/kp_firmware.tar` | ~2-3MB | tar 含多檔、新世代 firmware 較大 |
|
||
| `KL630/kp_loader.tar` | ~500KB | loader |
|
||
| `KL730/kp_firmware.tar` | ~3-4MB | |
|
||
| `KL730/kp_loader.tar` | ~500KB | |
|
||
|
||
**B 階段所有 firmware 合計增量**:
|
||
- KL520_kdp(降版用):~90KB
|
||
- KL630(升降版用):~2.5-3.5MB
|
||
- KL730(升降版用):~3.5-4.5MB
|
||
- 合計:**~6-8MB**
|
||
|
||
**multi-version bundle(B2 階段)**:
|
||
- 每 chip 額外 bundle 1 個舊版(v2.1.0 之類):~+1-2MB
|
||
- 合計:**~7-10MB**
|
||
|
||
### 3.2 與 macOS dmg 既有 163MB 比
|
||
|
||
| 階段 | 累計新增 | 累計安裝包 | 衝擊 |
|
||
|------|---------|----------|------|
|
||
| 既有(含 KL520/KL720 firmware) | 0 | 163MB | baseline |
|
||
| A 階段(+ KL520/fw_loader.bin) | +10KB | ~163MB | <0.01% |
|
||
| B 階段(含 KL520_kdp + KL630 + KL730 firmware) | +6-8MB | ~170-171MB | +4-5% |
|
||
| B2 階段(多版本,每 chip + 1 個舊版)| +7-10MB | ~170-173MB | +4-6% |
|
||
|
||
→ **使用者「+5MB 接受」的決策完全成立**——B 階段全做完約 +7-10MB、不超過 +6%。
|
||
|
||
### 3.3 解壓後大小(估算)
|
||
|
||
.tar 通常不會做壓縮(tar 預設無 compression、除非 .tar.gz)、解壓後大小 ≈ 原 .tar 大小:
|
||
|
||
| 檔案 | 原始 .tar | 解壓後 |
|
||
|------|----------|--------|
|
||
| `KL630/kp_firmware.tar` (~3MB) | 3MB | ~3MB(內含多個 .bin、metadata、加總接近 .tar 大小) |
|
||
| `KL730/kp_firmware.tar` (~4MB) | 4MB | ~4MB |
|
||
|
||
→ 採策略 Y(build time 解壓)vs 策略 Z(ship .tar)大小差異 **< 100KB**、可忽略。
|
||
|
||
---
|
||
|
||
## 4. 解壓策略對比
|
||
|
||
### 4.1 策略 X:runtime 解壓
|
||
|
||
**做法**:
|
||
- bridge.py 每次 connect KL630/KL730 時、解壓 `.tar` 到 `tempfile.mkdtemp()` 暫存目錄
|
||
- 餵解壓後的 .bin 路徑給 `kp.core.load_firmware_from_file()`
|
||
- 連線結束清理 temp 目錄
|
||
|
||
**優點**:
|
||
- 安裝包不增加解壓後檔案、只 ship 一份 .tar
|
||
- 解壓邏輯集中在 bridge.py、單一資料夾管理
|
||
|
||
**缺點**:
|
||
- 每次 connect 多花 50-200ms 解壓時間
|
||
- temp 目錄管理:clean-up、permissions、tempfile 衝突
|
||
- macOS hardened runtime 對 temp 目錄寫入權限可能有限制
|
||
- Windows 上 `tempfile` 預設位置 `%TEMP%` 可能被防毒軟體掃描,慢
|
||
- KL630/KL730 如果類似 KL520(每次 connect 都要 load firmware),解壓會發生在 hot path
|
||
|
||
**不推薦**——成本 vs 收益不划算。
|
||
|
||
### 4.2 策略 Y:build time 解壓
|
||
|
||
**做法**:
|
||
- `installer/` build script 在 wails build 之前、先解壓 `.tar` 到 `server/scripts/firmware/<chip>/extracted/`
|
||
- ship 解壓後的 .bin(不 ship 原始 .tar)
|
||
- bridge.py 直接餵解壓後路徑、`_resolve_firmware_paths(chip)` 解析 `extracted/` 子目錄
|
||
|
||
**優點**:
|
||
- runtime 零成本、connect 速度不受影響
|
||
- bridge.py 邏輯與 KL520/KL720 一致(都餵 .bin path)
|
||
- 安裝包大小不變(.tar 跟解壓後 .bin 大小接近)
|
||
|
||
**缺點**:
|
||
- 需要修改 installer build script(單純做)
|
||
- 開發環境第一次 clone repo 後、必須跑解壓 script 一次(或加進 `make setup` / npm postinstall)
|
||
- 解壓後檔案進不進 git?建議**不進**(避免 binary diff、靠 build script 即時產生)
|
||
|
||
**推薦條件**:如果 SDK 不支援 .tar 直接餵入、選此策略。
|
||
|
||
### 4.3 策略 Z:直接餵 .tar 給 SDK
|
||
|
||
**做法**:
|
||
- SDK 提供 `kp.core.load_firmware_from_tar()` 或類似 API、bridge.py 直接傳 .tar 路徑
|
||
|
||
**優點**:
|
||
- 最簡(不需解壓邏輯)
|
||
- runtime 零成本
|
||
- 安裝包 ship 原始 .tar、與 warrenchen 一致
|
||
|
||
**缺點**:
|
||
- **依賴 SDK 支援**——M9-6 必須驗證 API 存在
|
||
- 如果 SDK 接受的是「.tar 內 fw_scpu.bin 解出來的路徑」、那就退回策略 Y
|
||
- bridge.py 內 KL520/KL720 vs KL630/KL730 firmware 路徑解析邏輯不一致(一邊兩個 .bin、一邊一個 .tar)、`_resolve_firmware_paths` 必須回 union type 或分支處理
|
||
|
||
**推薦條件**:如果 SDK 確認支援、選此策略(最乾淨)。
|
||
|
||
### 4.4 決策樹
|
||
|
||
```
|
||
M9-6 SDK 驗證結果
|
||
├── SDK 支援 load_firmware_from_tar() / update_*_from_tar()
|
||
│ └── 選策略 Z
|
||
│ └── 改動:_resolve_firmware_paths 回 (tar_path, None) 或 union
|
||
│
|
||
└── SDK 不支援、必須先解壓
|
||
└── 選策略 Y
|
||
└── 改動:
|
||
- installer build script 加 tar -xf 步驟
|
||
- .gitignore 加 firmware/<chip>/extracted/
|
||
- 開發環境 setup 加解壓 step
|
||
- _resolve_firmware_paths 找 extracted/fw_scpu.bin
|
||
```
|
||
|
||
**絕對不要選策略 X**(runtime 解壓)。
|
||
|
||
---
|
||
|
||
## 5. SDK API 可用性驗證計畫(M9-6 必做)
|
||
|
||
### 5.1 驗證項目清單
|
||
|
||
| # | 驗證項目 | 方法 | 影響 |
|
||
|---|---------|------|-----|
|
||
| 1 | 既有 KneronPLUS wheel 版本 | `pip show kneronplus` / 找 wheel 檔案 | 決定要不要升級 wheel |
|
||
| 2 | wheel 內 `kp.ProductId.KP_DEVICE_KL630` / `KL730` enum 存在 | `python -c "import kp; print(kp.ProductId.KP_DEVICE_KL630)"` | 不存在 → 升 wheel |
|
||
| 3 | `kp.core.load_firmware_from_file` 對 .tar 路徑的行為 | 實機跑、傳 `.tar` 看回傳 | 決定策略 Y or Z |
|
||
| 4 | `kp.core.update_kdp_firmware_from_files` 對 KL630/KL730 是否適用 | 實機跑(如果有 KL630/KL730)| FW 升降版實作策略 |
|
||
| 5 | 是否有 `load_firmware_from_tar()` / `update_*_from_tar()` 新 API | grep wheel source / 查 SDK 文件 | 策略 Z 是否可行 |
|
||
| 6 | KL630/KL730 firmware 字串可能值 | 實機 `kp.core.scan_devices()` 看 firmware 欄位 | FW badge 顯示邏輯 |
|
||
| 7 | KL630/KL730 是否每次 connect 都要 load firmware | 實機 connect 兩次、看第二次需不需要 load | connect 流程設計 |
|
||
| 8 | `kp.inference.generic_image_inference_send/receive` 對 KL630/KL730 NEF 是否能直接 work | 實機跑 sample inference | inference 流程是否要分支 |
|
||
| 9 | .tar 內容(解壓看裡面有什麼)| `tar -tvf kp_firmware.tar` | bridge.py 解析策略 |
|
||
| 10 | KneronPLUS wheel 升級對 KL520/KL720 的 regression 風險 | 升級後跑 既有 E2E | 是否值得升 wheel |
|
||
|
||
### 5.2 驗證所需資源
|
||
|
||
- 使用者手上要有:
|
||
- 至少 1 個 KL630 dongle(理想)
|
||
- 至少 1 個 KL730 dongle(理想)
|
||
- 如果沒有、只能查 SDK 文件 + wheel source、無法做動態驗證、風險變高
|
||
- KneronPLUS SDK 官方文件(PDF / online docs)
|
||
- Python REPL + 既有 venv
|
||
|
||
### 5.3 驗證結果回填位置
|
||
|
||
- 本檔 §1.3、§2、§3.3 的「未驗證」段落填實際結果
|
||
- 40-b-phase 檔 §3.2、§5.2、§7.1 對應段落
|
||
- 30-integration-plan 檔 §6 階段 B 評估提示更新
|
||
|
||
---
|
||
|
||
## 6. .tar 解壓技術細節(如選策略 Y)
|
||
|
||
### 6.1 解壓工具選擇
|
||
|
||
**跨平台選 Python `tarfile` 模組**(標準庫、無外部依賴):
|
||
|
||
```python
|
||
# 偽碼、給 installer build script 用
|
||
import tarfile
|
||
import os
|
||
import shutil
|
||
|
||
def extract_firmware_tars(firmware_dir):
|
||
"""Walk firmware/<chip>/ dirs、解壓所有 .tar 到 extracted/ 子目錄"""
|
||
for chip_dir in os.listdir(firmware_dir):
|
||
chip_path = os.path.join(firmware_dir, chip_dir)
|
||
if not os.path.isdir(chip_path):
|
||
continue
|
||
for fname in os.listdir(chip_path):
|
||
if not fname.endswith(".tar"):
|
||
continue
|
||
tar_path = os.path.join(chip_path, fname)
|
||
extract_to = os.path.join(chip_path, "extracted")
|
||
os.makedirs(extract_to, exist_ok=True)
|
||
with tarfile.open(tar_path, "r") as tar:
|
||
tar.extractall(extract_to)
|
||
```
|
||
|
||
**不選 shell `tar -xf`**——Windows 上 `tar` 命令不一定存在(Win10+ 才有)、Python 標準庫穩定。
|
||
|
||
### 6.2 何時跑
|
||
|
||
- **CI/CD build pipeline**:每次 build 安裝包前跑(保證 ship 出去的安裝包有解壓檔)
|
||
- **開發環境 setup**:`scripts/setup-dev.sh` / `make setup` 加一步、或 npm postinstall
|
||
- **首次 clone 後**:README 提醒「跑 `python3 scripts/extract-firmware.py`」
|
||
|
||
### 6.3 .gitignore 規則
|
||
|
||
```
|
||
# .gitignore 追加(B 階段 M9-8 milestone)
|
||
server/scripts/firmware/*/extracted/
|
||
```
|
||
|
||
→ `.tar` 進 git、解壓後 `.bin` 不進 git(避免雙份 binary 進版控、減少 repo 大小)
|
||
|
||
### 6.4 衝突處理
|
||
|
||
如果使用者手動修改了 `extracted/` 內檔案、下次 build 會覆蓋。可接受、因為這個目錄不該手動改。
|
||
|
||
---
|
||
|
||
## 7. 如果選策略 Z(直接餵 .tar)的細節
|
||
|
||
### 7.1 bridge.py 簽名變化
|
||
|
||
```python
|
||
# _resolve_firmware_paths 偽碼變化
|
||
def _resolve_firmware_paths(chip="KL520"):
|
||
base = os.path.dirname(os.path.abspath(__file__))
|
||
fw_dir = os.path.join(base, "firmware", chip)
|
||
|
||
if chip in ("KL520", "KL720"):
|
||
# 既有路徑 .bin
|
||
scpu = os.path.join(fw_dir, "fw_scpu.bin")
|
||
ncpu = os.path.join(fw_dir, "fw_ncpu.bin")
|
||
if os.path.exists(scpu) and os.path.exists(ncpu):
|
||
return {"format": "bin", "scpu": scpu, "ncpu": ncpu, "loader": ...}
|
||
return None
|
||
|
||
if chip in ("KL630", "KL730"):
|
||
fw_tar = os.path.join(fw_dir, "kp_firmware.tar")
|
||
loader_tar = os.path.join(fw_dir, "kp_loader.tar")
|
||
if os.path.exists(fw_tar):
|
||
return {"format": "tar", "firmware": fw_tar, "loader": loader_tar}
|
||
return None
|
||
|
||
return None
|
||
```
|
||
|
||
→ 回 dict / union type 而不是 tuple、給 caller 判斷 format。
|
||
|
||
### 7.2 firmware load 分支
|
||
|
||
```python
|
||
# handle_connect / handle_firmware_upgrade 內偽碼
|
||
fw_paths = _resolve_firmware_paths(chip)
|
||
if fw_paths is None:
|
||
return {"error": f"firmware not found for {chip}"}
|
||
|
||
if fw_paths["format"] == "bin":
|
||
kp.core.load_firmware_from_file(dg, fw_paths["scpu"], fw_paths["ncpu"])
|
||
elif fw_paths["format"] == "tar":
|
||
# 假設 SDK 提供這個 API、待驗證
|
||
kp.core.load_firmware_from_tar(dg, fw_paths["firmware"])
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 風險(針對 .tar 處理)
|
||
|
||
### 8.1 R-TAR-1:SDK 不接受 .tar 直接餵(中度,B 階段 M9-6 驗)
|
||
|
||
**情境**:策略 Z 不可行、被迫退回策略 Y。
|
||
|
||
**緩解**:M9-6 預先驗證、選對策略才做 M9-8。
|
||
|
||
### 8.2 R-TAR-2:build time 解壓步驟漏跑(中度)
|
||
|
||
**情境**:CI/CD 流程沒加解壓 step、ship 出去的安裝包沒有解壓 .bin、KL630/KL730 連不上。
|
||
|
||
**緩解**:
|
||
- installer build script 加 mandatory `extract-firmware.py` step
|
||
- 加 build-time check:「`firmware/KL630/extracted/fw_scpu.bin` 不存在 → build fail」
|
||
- 安裝包 smoke test:解壓安裝包、grep `extracted/fw_scpu.bin` 必須存在
|
||
|
||
### 8.3 R-TAR-3:解壓對 macOS notarization 影響(低度)
|
||
|
||
**情境**:macOS notarization 對 dmg 內 binary file 要求 codesign、解壓出來的 .bin 是否需要簽?
|
||
|
||
**研究**:
|
||
- firmware .bin 不是 executable(是 NPU instruction binary)、預估不需 codesign
|
||
- 但 Apple Gatekeeper / XProtect 可能誤判某些 binary pattern
|
||
- M9-13 milestone 三平台驗證時必須跑 notarized dmg、確認沒被砍
|
||
|
||
### 8.4 R-TAR-4:.tar 解壓路徑跨平台問題(低度)
|
||
|
||
**情境**:Python `tarfile.extractall()` 在 Windows 上對絕對路徑 / `..` path entry 有警告(Python 3.12+ 預設拒絕)。
|
||
|
||
**緩解**:
|
||
- 解壓前用 `tarfile.data_filter` 過濾(Python 3.12+ 內建)
|
||
- 或預先驗證 .tar 內容、refuse 含 `..` / 絕對路徑的 .tar
|
||
|
||
---
|
||
|
||
## 9. 給 Orchestrator 的決策點
|
||
|
||
1. **A 階段 MVP 不涉 .tar**——不影響本檔
|
||
2. **B 階段啟動前 M9-6 必跑**——SDK 驗證、決定策略 Y/Z
|
||
3. **策略選定後本檔 §4.4 「決策樹」結果回填**到 progress.md「重要決策紀錄」
|
||
4. **如果使用者沒有 KL630/KL730 dongle**——降級驗證強度:只查 SDK 文件 + wheel source、不做動態驗證、風險 R-FW-8 提升
|
||
|
||
---
|
||
|
||
## 10. 與其他研究檔的關係
|
||
|
||
| 連結 | 引用內容 |
|
||
|------|---------|
|
||
| `40-b-phase-kl630-kl730-extension.md` §6.3 | `_resolve_firmware_paths` 擴展偽碼(本檔詳化)|
|
||
| `40-b-phase-kl630-kl730-extension.md` R-FW-9 | .tar 解壓對安裝包大小衝擊(本檔 §3 詳化)|
|
||
| `40-b-phase-kl630-kl730-extension.md` R-FW-10 | KL630/KL730 是否有 Loader mode(本檔 §5.1 驗證 #6/#7 確認)|
|
||
| `42-manual-downgrade-for-end-users.md` | 多版本 .tar 儲存結構(本檔 §6.3 .gitignore 規則延伸)|
|