/*
 * Atheros CARL9170 driver
 *
 * firmware parser
 *
 * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, see
 * http://www.gnu.org/licenses/.
 */

#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
#include <linux/module.h>
#include "carl9170.h"
#include "fwcmd.h"
#include "version.h"

static const u8 otus_magic[4] = { OTUS_MAGIC };

static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
	const unsigned int len, const u8 compatible_revision)
{
	const struct carl9170fw_desc_head *iter;

	carl9170fw_for_each_hdr(iter, ar->fw.desc) {
		if (carl9170fw_desc_cmp(iter, descid, len,
					compatible_revision))
			return (void *)iter;
	}

	/* needed to find the LAST desc */
	if (carl9170fw_desc_cmp(iter, descid, len,
				compatible_revision))
		return (void *)iter;

	return NULL;
}

static int carl9170_fw_verify_descs(struct ar9170 *ar,
	const struct carl9170fw_desc_head *head, unsigned int max_len)
{
	const struct carl9170fw_desc_head *pos;
	unsigned long pos_addr, end_addr;
	unsigned int pos_length;

	if (max_len < sizeof(*pos))
		return -ENODATA;

	max_len = min_t(unsigned int, CARL9170FW_DESC_MAX_LENGTH, max_len);

	pos = head;
	pos_addr = (unsigned long) pos;
	end_addr = pos_addr + max_len;

	while (pos_addr < end_addr) {
		if (pos_addr + sizeof(*head) > end_addr)
			return -E2BIG;

		pos_length = le16_to_cpu(pos->length);

		if (pos_length < sizeof(*head))
			return -EBADMSG;

		if (pos_length > max_len)
			return -EOVERFLOW;

		if (pos_addr + pos_length > end_addr)
			return -EMSGSIZE;

		if (carl9170fw_desc_cmp(pos, LAST_MAGIC,
					CARL9170FW_LAST_DESC_SIZE,
					CARL9170FW_LAST_DESC_CUR_VER))
			return 0;

		pos_addr += pos_length;
		pos = (void *)pos_addr;
		max_len -= pos_length;
	}
	return -EINVAL;
}

static void carl9170_fw_info(struct ar9170 *ar)
{
	const struct carl9170fw_motd_desc *motd_desc;
	unsigned int str_ver_len;
	u32 fw_date;

	dev_info(&ar->udev->dev, "driver   API: %s 2%03d-%02d-%02d [%d-%d]\n",
		CARL9170FW_VERSION_GIT, CARL9170FW_VERSION_YEAR,
		CARL9170FW_VERSION_MONTH, CARL9170FW_VERSION_DAY,
		CARL9170FW_API_MIN_VER, CARL9170FW_API_MAX_VER);

	motd_desc = carl9170_fw_find_desc(ar, MOTD_MAGIC,
		sizeof(*motd_desc), CARL9170FW_MOTD_DESC_CUR_VER);

	if (motd_desc) {
		str_ver_len = strnlen(motd_desc->release,
			CARL9170FW_MOTD_RELEASE_LEN);

		fw_date = le32_to_cpu(motd_desc->fw_year_month_day);

		dev_info(&ar->udev->dev, "firmware API: %.*s 2%03d-%02d-%02d\n",
			 str_ver_len, motd_desc->release,
			 CARL9170FW_GET_YEAR(fw_date),
			 CARL9170FW_GET_MONTH(fw_date),
			 CARL9170FW_GET_DAY(fw_date));

		strlcpy(ar->hw->wiphy->fw_version, motd_desc->release,
			sizeof(ar->hw->wiphy->fw_version));
	}
}

static bool valid_dma_addr(const u32 address)
{
	if (address >= AR9170_SRAM_OFFSET &&
	    address < (AR9170_SRAM_OFFSET + AR9170_SRAM_SIZE))
		return true;

	return false;
}

static bool valid_cpu_addr(const u32 address)
{
	if (valid_dma_addr(address) || (address >= AR9170_PRAM_OFFSET &&
	    address < (AR9170_PRAM_OFFSET + AR9170_PRAM_SIZE)))
		return true;

	return false;
}

static int carl9170_fw_checksum(struct ar9170 *ar, const __u8 *data,
				size_t len)
{
	const struct carl9170fw_otus_desc *otus_desc;
	const struct carl9170fw_last_desc *last_desc;
	const struct carl9170fw_chk_desc *chk_desc;
	unsigned long fin, diff;
	unsigned int dsc_len;
	u32 crc32;

	last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
		sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
	if (!last_desc)
		return -EINVAL;

	otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
		sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
	if (!otus_desc) {
		dev_err(&ar->udev->dev, "failed to find compatible firmware "
			"descriptor.\n");
		return -ENODATA;
	}

	chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC,
		sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER);

	if (!chk_desc) {
		dev_warn(&ar->udev->dev, "Unprotected firmware image.\n");
		return 0;
	}

	dsc_len = min_t(unsigned int, len,
			(unsigned long)chk_desc - (unsigned long)otus_desc);

	fin = (unsigned long) last_desc + sizeof(*last_desc);
	diff = fin - (unsigned long) otus_desc;

	if (diff < len)
		len -= diff;

	if (len < 256)
		return -EIO;

	crc32 = crc32_le(~0, data, len);
	if (cpu_to_le32(crc32) != chk_desc->fw_crc32) {
		dev_err(&ar->udev->dev, "fw checksum test failed.\n");
		return -ENOEXEC;
	}

	crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len);
	if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) {
		dev_err(&ar->udev->dev, "descriptor check failed.\n");
		return -EINVAL;
	}
	return 0;
}

static int carl9170_fw_tx_sequence(struct ar9170 *ar)
{
	const struct carl9170fw_txsq_desc *txsq_desc;

	txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, sizeof(*txsq_desc),
					  CARL9170FW_TXSQ_DESC_CUR_VER);
	if (txsq_desc) {
		ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
		if (!valid_cpu_addr(ar->fw.tx_seq_table))
			return -EINVAL;
	} else {
		ar->fw.tx_seq_table = 0;
	}

	return 0;
}

static void carl9170_fw_set_if_combinations(struct ar9170 *ar,
					    u16 if_comb_types)
{
	if (ar->fw.vif_num < 2)
		return;

	ar->if_comb_limits[0].max = ar->fw.vif_num;
	ar->if_comb_limits[0].types = if_comb_types;

	ar->if_combs[0].num_different_channels = 1;
	ar->if_combs[0].max_interfaces = ar->fw.vif_num;
	ar->if_combs[0].limits = ar->if_comb_limits;
	ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);

	ar->hw->wiphy->iface_combinations = ar->if_combs;
	ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
}

static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
{
	const struct carl9170fw_otus_desc *otus_desc;
	int err;
	u16 if_comb_types;

	err = carl9170_fw_checksum(ar, data, len);
	if (err)
		return err;

	otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
		sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
	if (!otus_desc) {
		return -ENODATA;
	}

#define SUPP(feat)						\
	(carl9170fw_supports(otus_desc->feature_set, feat))

	if (!SUPP(CARL9170FW_DUMMY_FEATURE)) {
		dev_err(&ar->udev->dev, "invalid firmware descriptor "
			"format detected.\n");
		return -EINVAL;
	}

	ar->fw.api_version = otus_desc->api_ver;

	if (ar->fw.api_version < CARL9170FW_API_MIN_VER ||
	    ar->fw.api_version > CARL9170FW_API_MAX_VER) {
		dev_err(&ar->udev->dev, "unsupported firmware api version.\n");
		return -EINVAL;
	}

	if (!SUPP(CARL9170FW_COMMAND_PHY) || SUPP(CARL9170FW_UNUSABLE) ||
	    !SUPP(CARL9170FW_HANDLE_BACK_REQ)) {
		dev_err(&ar->udev->dev, "firmware does support "
			"mandatory features.\n");
		return -ECANCELED;
	}

	if (ilog2(le32_to_cpu(otus_desc->feature_set)) >=
		__CARL9170FW_FEATURE_NUM) {
		dev_warn(&ar->udev->dev, "driver does not support all "
			 "firmware features.\n");
	}

	if (!SUPP(CARL9170FW_COMMAND_CAM)) {
		dev_info(&ar->udev->dev, "crypto offloading is disabled "
			 "by firmware.\n");
		ar->fw.disable_offload_fw = true;
	}

	if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
		ieee80211_hw_set(ar->hw, SUPPORTS_PS);

	if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
		dev_err(&ar->udev->dev, "firmware does not provide "
			"mandatory interfaces.\n");
		return -EINVAL;
	}

	if (SUPP(CARL9170FW_MINIBOOT))
		ar->fw.offset = le16_to_cpu(otus_desc->miniboot_size);
	else
		ar->fw.offset = 0;

	if (SUPP(CARL9170FW_USB_DOWN_STREAM)) {
		ar->hw->extra_tx_headroom += sizeof(struct ar9170_stream);
		ar->fw.tx_stream = true;
	}

	if (SUPP(CARL9170FW_USB_UP_STREAM))
		ar->fw.rx_stream = true;

	if (SUPP(CARL9170FW_RX_FILTER)) {
		ar->fw.rx_filter = true;
		ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL |
			FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS;
	}

	if (SUPP(CARL9170FW_HW_COUNTERS))
		ar->fw.hw_counters = true;

	if (SUPP(CARL9170FW_WOL))
		device_set_wakeup_enable(&ar->udev->dev, true);

	if (SUPP(CARL9170FW_RX_BA_FILTER))
		ar->fw.ba_filter = true;

	if_comb_types = BIT(NL80211_IFTYPE_STATION) |
			BIT(NL80211_IFTYPE_P2P_CLIENT);

	ar->fw.vif_num = otus_desc->vif_num;
	ar->fw.cmd_bufs = otus_desc->cmd_bufs;
	ar->fw.address = le32_to_cpu(otus_desc->fw_address);
	ar->fw.rx_size = le16_to_cpu(otus_desc->rx_max_frame_len);
	ar->fw.mem_blocks = min_t(unsigned int, otus_desc->tx_descs, 0xfe);
	atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
	ar->fw.mem_block_size = le16_to_cpu(otus_desc->tx_frag_len);

	if (ar->fw.vif_num >= AR9170_MAX_VIRTUAL_MAC || !ar->fw.vif_num ||
	    ar->fw.mem_blocks < 16 || !ar->fw.cmd_bufs ||
	    ar->fw.mem_block_size < 64 || ar->fw.mem_block_size > 512 ||
	    ar->fw.rx_size > 32768 || ar->fw.rx_size < 4096 ||
	    !valid_cpu_addr(ar->fw.address)) {
		dev_err(&ar->udev->dev, "firmware shows obvious signs of "
			"malicious tampering.\n");
		return -EINVAL;
	}

	ar->fw.beacon_addr = le32_to_cpu(otus_desc->bcn_addr);
	ar->fw.beacon_max_len = le16_to_cpu(otus_desc->bcn_len);

	if (valid_dma_addr(ar->fw.beacon_addr) && ar->fw.beacon_max_len >=
	    AR9170_MAC_BCN_LENGTH_MAX) {
		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);

		if (SUPP(CARL9170FW_WLANTX_CAB)) {
			if_comb_types |=
				BIT(NL80211_IFTYPE_AP) |
				BIT(NL80211_IFTYPE_P2P_GO);

#ifdef CPTCFG_MAC80211_MESH
			if_comb_types |=
				BIT(NL80211_IFTYPE_MESH_POINT);
#endif /* CPTCFG_MAC80211_MESH */
		}
	}

	carl9170_fw_set_if_combinations(ar, if_comb_types);

	ar->hw->wiphy->interface_modes |= if_comb_types;

	ar->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;

	/* As IBSS Encryption is software-based, IBSS RSN is supported. */
	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
		 WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_SUPPORTS_TDLS;

#undef SUPPORTED
	return carl9170_fw_tx_sequence(ar);
}

static struct carl9170fw_desc_head *
carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len)

{
	int scan = 0, found = 0;

	if (!carl9170fw_size_check(len)) {
		dev_err(&ar->udev->dev, "firmware size is out of bound.\n");
		return NULL;
	}

	while (scan < len - sizeof(struct carl9170fw_desc_head)) {
		if (fw_data[scan++] == otus_magic[found])
			found++;
		else
			found = 0;

		if (scan >= len)
			break;

		if (found == sizeof(otus_magic))
			break;
	}

	if (found != sizeof(otus_magic))
		return NULL;

	return (void *)&fw_data[scan - found];
}

int carl9170_parse_firmware(struct ar9170 *ar)
{
	const struct carl9170fw_desc_head *fw_desc = NULL;
	const struct firmware *fw = ar->fw.fw;
	unsigned long header_offset = 0;
	int err;

	if (WARN_ON(!fw))
		return -EINVAL;

	fw_desc = carl9170_find_fw_desc(ar, fw->data, fw->size);

	if (!fw_desc) {
		dev_err(&ar->udev->dev, "unsupported firmware.\n");
		return -ENODATA;
	}

	header_offset = (unsigned long)fw_desc - (unsigned long)fw->data;

	err = carl9170_fw_verify_descs(ar, fw_desc, fw->size - header_offset);
	if (err) {
		dev_err(&ar->udev->dev, "damaged firmware (%d).\n", err);
		return err;
	}

	ar->fw.desc = fw_desc;

	carl9170_fw_info(ar);

	err = carl9170_fw(ar, fw->data, fw->size);
	if (err) {
		dev_err(&ar->udev->dev, "failed to parse firmware (%d).\n",
			err);
		return err;
	}

	return 0;
}
