デバイスが正常に機能するには、デバイスのファームウェアとデバイスドライバの互換性がなければなりません。デバイスドライバをインストールまたはアップグレードする前に、ファームウェアとの互換性をチェックする必要があります。互換性のあるファームウェアが見つからない場合は、デバイスドライバの実装によって、デバイスドライバがインストールまたはアップグレードされないように保証する必要があります。
好ましいデバイスドライバの設計では、1 つ以上の ELF (実行可能リンク形式) モジュール内にファームウェアをカプセル化し、attach() 関数を使用してファームウェアのバージョンを管理します。ELF モジュール内にファームウェアをカプセル化するには、elfwrap(1) コマンドを使用します。ファームウェア ELF モジュールは、misc モジュールとしてモジュールリンケージスタブとリンクされます。ファームウェアモジュールは /kernel/misc ディレクトリに存在します。
次のフローチャートに、デバイスドライバの attach() 関数でファームウェアのバージョンを管理する方法を示します。
図 1-1 attach() 関数でのファームウェアのバージョン管理
詳細は、 attach (9E) 、 ddi_modopen (9F) 、 ddi_modsym (9F) 、および ddi_modclose (9F) のマニュアルページを参照してください。
ファームウェアのバージョンをチェックする attach() 関数の一般的な疑似コードは次のとおりです。
static int xxxx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { ..... ddi_modhandle_t modfn; int errno; uint32_t *fwvp; ..... long fw_version; ..... /* Check if firmware update is disabled. * If firmware update is disabled, return. * The setting is stored in a config file. */ if(dip->firmware_disable_update){ return (0); } /* Get the current firmware version. */ fw_version = xxxx_get_firmware_version(dip,...); /* Check if the firmware version is correct and if force update is disabled. */ if(fw_version == REQUIRED_FIRMWARE_VERSION){ if(dip->firmware_force_update == 0){ return (0); } /* Even though the firmware version matches, update is forced. */ } /* Open the firmware file by using ddi_modopen. */ modfn = ddi_modopen(FIRMWARE_FILENAME, KRTLD_MODE_FIRST, &errno); if (errno){ /* handle error */ } /* locate the firmware */ fwvp = ddi_modsym(modfn, FIRMWARE_VERSION_NAME, &errno); if (errno){ /* handle error */ (void) ddi_modclose(modfn); } /* Check if the firmware version in the module is correct. */ if (*fwvp != REQUIRED_FIRMWARE_VERSION){ if(dip->firmware_force_update == 0){ /* close the firmware module file */ (void) ddi_modclose(modfn); return (0); } /* Even tough the firmware version in the module does not match, * update is forced. */ } /* Update the firmware. */ xxx_update_firmware(dip,....); /* Close the FIRMWARE file */ (void) ddi_modclose(modfn); ..... // resume attach }