diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c index e9a04e6073..365a551327 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c @@ -104,16 +104,43 @@ int rb_iwl_mvm_parse_firmware(const uint8_t *data, size_t len, magic = (uint32_t)data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24); - if (magic != RB_IWL_TLV_UCODE_MAGIC) + + if (magic == RB_IWL_TLV_UCODE_MAGIC) { + /* Simple format: "IWO\n" at offset 0, version at 4, build at 8 */ + out->version = (uint32_t)data[4] | ((uint32_t)data[5] << 8) | + ((uint32_t)data[6] << 16) | ((uint32_t)data[7] << 24); + out->build = (uint32_t)data[8] | ((uint32_t)data[9] << 8) | + ((uint32_t)data[10] << 16) | ((uint32_t)data[11] << 24); + out->api = (uint8_t)((out->version >> 8) & 0xFFU); + p = data + RB_IWL_TLV_HDR_SIZE; + } else if (magic == 0 && len >= 8) { + /* Linux TLV format: zero at offset 0, "IWL\n" at offset 4 */ + uint32_t tlv_magic; + tlv_magic = (uint32_t)data[4] | ((uint32_t)data[5] << 8) | + ((uint32_t)data[6] << 16) | ((uint32_t)data[7] << 24); + if (tlv_magic != 0x0a4c5749U) /* "IWL\n" */ + return -1; + /* Extract version string from offset 8 (64 bytes) */ + if (len >= 72) { + size_t copy = RB_IWL_FW_VER_HUMAN_READABLE_SZ - 1; + if (len - 8 < copy) + copy = len - 8; + if (copy > 0) { + memcpy(out->version_str, data + 8, copy); + out->version_str[copy] = '\0'; + } + /* Major version at offset 72 */ + if (len >= 76) { + out->version = (uint32_t)data[72] | + ((uint32_t)data[73] << 8) | + ((uint32_t)data[74] << 16) | + ((uint32_t)data[75] << 24); + } + } + p = data + 88; /* skip TLV header */ + } else { return -1; - - out->version = (uint32_t)data[4] | ((uint32_t)data[5] << 8) | - ((uint32_t)data[6] << 16) | ((uint32_t)data[7] << 24); - out->build = (uint32_t)data[8] | ((uint32_t)data[9] << 8) | - ((uint32_t)data[10] << 16) | ((uint32_t)data[11] << 24); - out->api = (uint8_t)((out->version >> 8) & 0xFFU); - - p = data + RB_IWL_TLV_HDR_SIZE; + } end = data + len; while (p + 8 <= end) { @@ -138,11 +165,18 @@ int rb_iwl_mvm_parse_firmware(const uint8_t *data, size_t len, switch (tlv_type) { case RB_IWL_UCODE_TLV_ENABLED_CAPABILITIES: - if (tlv_len >= 4) - out->capabilities = (uint32_t)tlv_data[0] | + if (tlv_len >= 8) { + uint32_t api_index, bitmap; + api_index = (uint32_t)tlv_data[0] | ((uint32_t)tlv_data[1] << 8) | ((uint32_t)tlv_data[2] << 16) | ((uint32_t)tlv_data[3] << 24); + bitmap = (uint32_t)tlv_data[4] | + ((uint32_t)tlv_data[5] << 8) | + ((uint32_t)tlv_data[6] << 16) | + ((uint32_t)tlv_data[7] << 24); + out->capabilities |= (bitmap << (api_index * 16)); + } break; case RB_IWL_UCODE_TLV_N_SCAN_CHANNELS: