/*
 * This file is part of the coreboot project.
 *
 * Copyright 2014 Google Inc.
 *
 * 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; version 2 of the License.
 *
 * 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.
 */

#include <b64_decode.h>
#include <cbmem.h>
#include <console/console.h>
#include <string.h>

#include <vendorcode/google/chromeos/chromeos.h>
#include <vendorcode/google/chromeos/cros_vpd.h>

/*
 * This file provides functions looking in the VPD for WiFi calibration data,
 * and if found, copying the calibration blobs into CBMEM.
 *
 * Per interface calibration data is stored in the VPD in opaque blobs. The
 * keys of the blobs follow one of two possible patterns:
 * "wifi_base64_calibration<N>" or "wifi_calibration<N>", where <N> is the
 * interface number.
 *
 * This function accommodates up to 4 interfaces. All calibration blobs found
 * in the VPD are packed into a single CBMEM entry as describe by the
 * structures below:
 */

/* This structure describes a single calibration data blob */
struct calibration_blob {
	uint32_t blob_size;  /* Total size. rounded up to fall on a 4 byte
				   boundary. */
	uint32_t key_size;   /* Size of the name of this entry, \0 included. */
	uint32_t value_size; /* Size of the value of this entry */
	/* Zero terminated name(key) goes here, immediately followed by value */
};

/*
 * This is the structure of the CBMEM entry containing WiFi calibration blobs.
 * It starts with the total size (header size included) followed by an
 * arbitrary number of concatenated 4 byte aligned calibration blobs.
 */
struct calibration_entry {
	uint32_t size;
	struct calibration_blob entries[0];  /* A varialble size container. */
};


#define MAX_WIFI_INTERFACE_COUNT 4

/*
 * Structure of the cache to keep information about calibration blobs present
 * in the VPD, one cache entry per VPD blob.
 *
 * Maintaing the cache allows to scan the VPD once, determine the CBMEM entry
 * memory requirements, then allocate as much room as necessary and fill it
 * up.
 */
struct vpd_blob_cache_t {
	/* The longest name template must fit with an extra character. */
	char key_name[40];
	void  *value_pointer;
	unsigned blob_size;
	unsigned key_size;
	unsigned value_size;
};

static const char * const templates[] = {
	"wifi_base64_calibrationX",
	"wifi_calibrationX"
};

/*
 * Scan the VPD for WiFi calibration data, checking for all possible key names
 * and caching discovered blobs.
 *
 * Return the sum of sizes of all blobs, as stored in CBMEM.
 */
static size_t fill_up_entries_cache(struct vpd_blob_cache_t *cache,
				    size_t max_entries, size_t *filled_entries)
{
	int i;
	int cbmem_entry_size = 0;
	size_t used_entries = 0;


	for (i = 0;
	     (i < ARRAY_SIZE(templates)) && (used_entries < max_entries);
	     i++) {
		int j;
		const int index_location = strlen(templates[i]) - 1;
		const int key_length = index_location + 2;

		if (key_length > sizeof(cache->key_name))
			continue;

		for (j = 0; j < MAX_WIFI_INTERFACE_COUNT; j++) {
			const void *payload;
			void *decoded_payload;
			int payload_size;
			size_t decoded_size;

			strcpy(cache->key_name, templates[i]);
			cache->key_name[index_location] = j + '0';

			payload = cros_vpd_find(cache->key_name, &payload_size);
			if (!payload)
				continue;

			decoded_size = B64_DECODED_SIZE(payload_size);
			decoded_payload = malloc(decoded_size);
			if (!decoded_payload) {
				printk(BIOS_ERR,
				       "%s: failed allocating %zd bytes\n",
				       __func__, decoded_size);
				continue;
			}

			decoded_size = b64_decode(payload, payload_size,
						  decoded_payload);
			if (!decoded_size) {
				free(decoded_payload);
				printk(BIOS_ERR, "%s: failed decoding %s\n",
				       __func__, cache->key_name);
				continue;
			}

			cache->value_pointer = decoded_payload;
			cache->key_size = key_length;
			cache->value_size = decoded_size;
			cache->blob_size =
				ALIGN(sizeof(struct calibration_blob) +
				      cache->key_size +
				      cache->value_size, 4);
			cbmem_entry_size += cache->blob_size;

			used_entries++;
			if (used_entries == max_entries)
				break;

			cache++;
		}
	}

	*filled_entries = used_entries;
	return cbmem_entry_size;
}

void cbmem_add_vpd_calibration_data(void)
{
	size_t cbmem_entry_size, filled_entries;
	struct calibration_entry *cbmem_entry;
	struct calibration_blob *cal_blob;
	int i;
	/*
	 * Allocate one more cache entry than max required, to make sure that
	 * the last entry can be identified by the key size of zero.
	 */
	struct vpd_blob_cache_t vpd_blob_cache[ARRAY_SIZE(templates) *
					       MAX_WIFI_INTERFACE_COUNT];

	cbmem_entry_size = fill_up_entries_cache(vpd_blob_cache,
						 ARRAY_SIZE(vpd_blob_cache),
						 &filled_entries);

	if (!cbmem_entry_size)
		return; /* No calibration data found in the VPD. */

	cbmem_entry_size += sizeof(struct calibration_entry);
	cbmem_entry = cbmem_add(CBMEM_ID_WIFI_CALIBRATION, cbmem_entry_size);
	if (!cbmem_entry) {
		printk(BIOS_ERR, "%s: no room in cbmem to add %zd bytes\n",
		       __func__, cbmem_entry_size);
		return;
	}

	cbmem_entry->size = cbmem_entry_size;

	/* Copy cached data into the CBMEM entry. */
	cal_blob = cbmem_entry->entries;

	for (i = 0; i < filled_entries; i++) {
		/* Use this as a pointer to the current cache entry. */
		struct vpd_blob_cache_t *cache = vpd_blob_cache + i;
		char *pointer;

		cal_blob->blob_size = cache->blob_size;
		cal_blob->key_size = cache->key_size;
		cal_blob->value_size = cache->value_size;

		/* copy the key */
		pointer = (char *)(cal_blob + 1);
		memcpy(pointer, cache->key_name, cache->key_size);

		/* and the value */
		pointer += cache->key_size;
		memcpy(pointer, cache->value_pointer, cache->value_size);
		free(cache->value_pointer);

		printk(BIOS_INFO, "%s: added %s to CBMEM\n",
		       __func__, cache->key_name);

		cal_blob = (struct calibration_blob *)
			((char *)cal_blob + cal_blob->blob_size);
	}
}
