Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc765bf3 authored by Shahar Levi's avatar Shahar Levi Committed by Luciano Coelho
Browse files

wl12xx: 1281/1283 support - Loading FW & NVS



Take care of FW & NVS with the auto-detection between wl127x and
wl128x.

[Moved some common code outside if statements and added notes about
NVS structure assumptions; Fixed a bug when checking the nvs size: if
the size was incorrect, the local nvs variable was set to NULL, it
should be wl->nvs instead. -- Luca]

[Merged with potential buffer overflow fix -- Luca]

Signed-off-by: default avatarShahar Levi <shahar_levi@ti.com>
Reviewed-by: default avatarLuciano Coelho <coelho@ti.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 49d750ca
Loading
Loading
Loading
Loading
+55 −28
Original line number Diff line number Diff line
@@ -243,16 +243,39 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
	if (wl->nvs == NULL)
		return -ENODEV;

	if (wl->chip.id == CHIP_ID_1283_PG20) {
		struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;

		if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
			if (nvs->general_params.dual_mode_select)
				wl->enable_11a = true;
		} else {
			wl1271_error("nvs size is not as expected: %zu != %zu",
				     wl->nvs_len,
				     sizeof(struct wl128x_nvs_file));
			kfree(wl->nvs);
			wl->nvs = NULL;
			wl->nvs_len = 0;
			return -EILSEQ;
		}

		/* only the first part of the NVS needs to be uploaded */
		nvs_len = sizeof(nvs->nvs);
		nvs_ptr = (u8 *)nvs->nvs;

	} else {
		struct wl1271_nvs_file *nvs =
			(struct wl1271_nvs_file *)wl->nvs;
		/*
	 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
	 * configurations) can be removed when those NVS files stop floating
	 * around.
		 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
		 * band configurations) can be removed when those NVS files stop
		 * floating around.
		 */
		if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
		    wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
			/* for now 11a is unsupported in AP mode */
			if (wl->bss_type != BSS_TYPE_AP_BSS &&
		    wl->nvs->general_params.dual_mode_select)
			    nvs->general_params.dual_mode_select)
				wl->enable_11a = true;
		}

@@ -268,8 +291,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
		}

		/* only the first part of the NVS needs to be uploaded */
	nvs_len = sizeof(wl->nvs->nvs);
	nvs_ptr = (u8 *)wl->nvs->nvs;
		nvs_len = sizeof(nvs->nvs);
		nvs_ptr = (u8 *) nvs->nvs;
	}

	/* update current MAC address to NVS */
	nvs_ptr[11] = wl->mac_addr[0];
@@ -319,10 +343,13 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
	/*
	 * We've reached the first zero length, the first NVS table
	 * is located at an aligned offset which is at least 7 bytes further.
	 * NOTE: The wl->nvs->nvs element must be first, in order to
	 * simplify the casting, we assume it is at the beginning of
	 * the wl->nvs structure.
	 */
	nvs_ptr = (u8 *)wl->nvs->nvs +
			ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
	nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
	nvs_ptr = (u8 *)wl->nvs +
			ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
	nvs_len -= nvs_ptr - (u8 *)wl->nvs;

	/* Now we must set the partition correctly */
	wl1271_set_partition(wl, &part_table[PART_WORK]);
+6 −5
Original line number Diff line number Diff line
@@ -187,8 +187,9 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)

int wl1271_cmd_radio_parms(struct wl1271 *wl)
{
	struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
	struct wl1271_radio_parms_cmd *radio_parms;
	struct wl1271_ini_general_params *gp = &wl->nvs->general_params;
	struct wl1271_ini_general_params *gp = &nvs->general_params;
	int ret;

	if (!wl->nvs)
@@ -201,18 +202,18 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
	radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;

	/* 2.4GHz parameters */
	memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2,
	memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
	       sizeof(struct wl1271_ini_band_params_2));
	memcpy(&radio_parms->dyn_params_2,
	       &wl->nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
	       &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
	       sizeof(struct wl1271_ini_fem_params_2));

	/* 5GHz parameters */
	memcpy(&radio_parms->static_params_5,
	       &wl->nvs->stat_radio_params_5,
	       &nvs->stat_radio_params_5,
	       sizeof(struct wl1271_ini_band_params_5));
	memcpy(&radio_parms->dyn_params_5,
	       &wl->nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
	       &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
	       sizeof(struct wl1271_ini_fem_params_5));

	wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
+2 −2
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ struct wl128x_ini_fem_params_5 {
#define WL1271_INI_LEGACY_NVS_FILE_SIZE              800

struct wl1271_nvs_file {
	/* NVS section */
	/* NVS section - must be first! */
	u8 nvs[WL1271_INI_NVS_SECTION_SIZE];

	/* INI section */
@@ -195,7 +195,7 @@ struct wl1271_nvs_file {
} __packed;

struct wl128x_nvs_file {
	/* NVS section */
	/* NVS section - must be first! */
	u8 nvs[WL1271_INI_NVS_SECTION_SIZE];

	/* INI section */
+10 −3
Original line number Diff line number Diff line
@@ -804,6 +804,9 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
		break;
	case BSS_TYPE_IBSS:
	case BSS_TYPE_STA_BSS:
		if (wl->chip.id == CHIP_ID_1283_PG20)
			fw_name = WL128X_FW_NAME;
		else
			fw_name	= WL1271_FW_NAME;
		break;
	default:
@@ -860,7 +863,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
		return ret;
	}

	wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
	wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);

	if (!wl->nvs) {
		wl1271_error("could not allocate memory for the nvs file");
@@ -3289,7 +3292,11 @@ int wl1271_register_hw(struct wl1271 *wl)

	ret = wl1271_fetch_nvs(wl);
	if (ret == 0) {
		u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
		/* NOTE: The wl->nvs->nvs element must be first, in
		 * order to simplify the casting, we assume it is at
		 * the beginning of the wl->nvs structure.
		 */
		u8 *nvs_ptr = (u8 *)wl->nvs;

		wl->mac_addr[0] = nvs_ptr[11];
		wl->mac_addr[1] = nvs_ptr[10];
+7 −2
Original line number Diff line number Diff line
@@ -189,7 +189,12 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
	const struct firmware *fw;
	int ret;

	ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl));
	if (wl->chip.id == CHIP_ID_1283_PG20)
		ret = request_firmware(&fw, WL128X_FW_NAME,
				       wl1271_wl_to_dev(wl));
	else
		ret = request_firmware(&fw, WL1271_FW_NAME,
				       wl1271_wl_to_dev(wl));

	if (ret < 0) {
		wl1271_error("could not get firmware: %d", ret);
@@ -234,7 +239,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
		return ret;
	}

	wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
	wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);

	if (!wl->nvs) {
		wl1271_error("could not allocate memory for the nvs file");
Loading