# Update System Code (Firmware Update) 實現分析 ## 流程架構 ``` ┌─────────────────────────────────────────────────────────────┐ │ jmUpdateFirmware_actionPerformed() │ │ (密碼驗證) │ └──────────────────────────┬──────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ UpdateFirmware(iCmdCode, microcode, enclosureID, type) │ ├─────────────────────────────────────────────────────────────┤ │ 1. 開啟檔案選擇器 (JFileChooser) │ │ 2. 檢查檔案有效性 │ │ 3. 建立 CmdQueue 命令 │ │ 4. 讀取 FW 檔案 │ │ 5. 顯示進度對話框 (dlgProgressCheck) │ │ 6. 發送 FW 到控制器 │ └──────────────────────────┬──────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 進度監控 (dlgProgressCheck) │ └─────────────────────────────────────────────────────────────┘ ``` ## Firmware 類型 | iCmdCode | microcode | enclosureID | 類型 | 說明 | |----------|-----------|-------------|------|------| | 0x94 | 0xFF | 0xFF | System Code | 主系統韌體更新 | | 0x95 | 0xFF | 0xFF | Boot Code | 啟動韌體更新 | | 0x96 | 0x00 | 0xFF | BIOS/EFI | BIOS/EFI 更新 | | 0x96 | 0x01 | [ID] | Expander Code | Expander 韌體更新 | ## 通訊協定 ### Command Queue (CmdQueue) ```java // 建立命令 int iRow = CmdQueue.NewCommand( IP, // 控制器 IP SN, // 序號 4200, // Command Len (min fw size) 1, // Reply Len 0x01 // Req Type: InBand Command ); // CDB 結構 bCmds[0] = 0x00; // Phase Code bCmds[1] = 0x00; // Request Code bCmds[2] = 0x00; // Controller No bCmds[3] = (byte) iCmdCode; // 0x94/0x95/0x96 bCmds[4] = 0x04; // Length (default) bCmds[5-8] = FW Length (4 bytes, little-endian) bCmds[9] = microcode; bCmds[10] = enclosureID (if microcode == 0x01) // FW 資料 (從偏移量 9 或 10 開始) bCmds[9/10+] = firmware data ``` ### CDB 參數說明 | Offset | 值 | 說明 | |--------|-----|------| | 0 | 0x00 | Phase Code | | 1 | 0x00 | Request Code | | 2 | 0x00 | Controller No | | 3 | 0x94/0x95/0x96 | Command Code | | 4 | 0x04-0x06 | Length | | 5-8 | FW Length | 韌體大小 (4 bytes) | | 9 | microcode | 微碼類型 | | 10 | enclosureID | Enclosure ID (選用) | | 11+ | firmware data | 韌體內容 | ## 檔案驗證 ```java // 檢查 1: 檔案存在 if (!f.exists()) { showError("File does not exist"); return; } // 檢查 2: 檔案大小 (< 4MB) if (f.length() > 4048000) { showWarning("File too large (>4MB)"); return; } // 檢查 3: 主機狀態 (必須在線) if (GetHostStatus(sSN) != 0x01) { showWarning("Controller not online"); return; } ``` ## Code Flow ### 1. Menu 點擊 ``` jmUpdateFirmware (MenuItem) → jmUpdateFirmware_actionPerformed() → PwdCheck() 密碼驗證 → UpdateFirmware(0x94, 0xff, 0xff, "System Code") ``` ### 2. Firmware 選擇 ``` UpdateFirmware() → JFileChooser.showOpenDialog() 選擇 .bin 檔 → 檢查檔案存在、大小限制 → 讀取檔案到 byte array → CmdQueue.NewCommand() 建立命令 ``` ### 3. 發送 FW ``` → dlgProgressCheck 顯示進度 → 設定主機狀態為 updating (0x10) → 透過 In-Band API 發送到控制器 → UpdateFirmwareSlave() 更新備援控制器 (如有) ``` ## 關鍵類 | 類別 | 檔案 | 功能 | |------|------|------| | `frmMain` | frmMain.java:4077 | 入口,密碼驗證 | | `UpdateFirmware` | frmMain.java:3663 | 主 FW 更新邏輯 | | `UpdateFirmwareSlave` | frmMain.java:3866 | 備援 FW 更新 | | `dlgProgressCheck` | dlgProgressCheck.java | 進度顯示對話框 | | `CmdQueue` | CmdQueue.java | 命令排程 | | `SendCmd` | InBandAPI/SendCmd.java | TCP 通訊底層 | ## 錯誤訊息 (Langs) | Key | 訊息 | |-----|------| | Main_UpdateFirmwareMsg1 | No file selected | | Main_UpdateFirmwareMsg2 | Please connect to controller first | | Main_UpdateFirmwareMsg3_1 | File not found: | | Main_UpdateFirmwareMsg3_2 | | | Main_UpdateFirmwareMsg4 | File size over 4M, cannot update! | ## 狀態更新 ```java // 更新前 PageDataDB.SetHostStatus(sSN, 0x10); // 0x10 = Updating // UI 顯示 jtHostList.setValueAt("System Code updating.", row, StatusColumn); ```