/*
 * Copyright (c) 2016-2017 Satlab Aps <satlab@satlab.com>
 * All rights reserved. Do not distribute without permission.
 */

#include <satlab/polaris_boot.h>

#include <errno.h>

#include <csp/csp.h>
#include <csp/csp_endian.h>

#include <satlab/polaris.h>

int sl_polaris_bootloader_set_alternate(uint8_t node, uint32_t timeout, uint8_t boots)
{
	int ret;
	sl_polaris_bootloader_set_req_t request;
	sl_polaris_bootloader_set_rep_t reply;

	request.type = SL_POLARIS_BOOTLOADER_SET_REQ;
	request.flags = 0;
	request.boots = boots;
	request.key = csp_hton32(SL_POLARIS_BOOTLOADER_SET_KEY);

	ret = csp_transaction(CSP_PRIO_NORM, node, SL_POLARIS_PORT_BOOTLOADER, timeout,
			      &request, sizeof(request), &reply, sizeof(reply));
	if (ret != sizeof(reply))
		return -ECONNREFUSED;

	if (reply.type != SL_POLARIS_BOOTLOADER_SET_REP)
		return -EINVAL;

	if (reply.error != SL_POLARIS_ERR_NONE)
		return -reply.error;

	return 0;
}

int sl_polaris_bootloader_flash_alternate(uint8_t node, uint32_t timeout, const char *filename, uint32_t *crc)
{
	int ret;
	sl_polaris_bootloader_flash_req_t request;
	sl_polaris_bootloader_flash_rep_t reply;

	request.type = SL_POLARIS_BOOTLOADER_FLASH_REQ;
	request.flags = 0;
	request.key = csp_hton32(SL_POLARIS_BOOTLOADER_FLASH_KEY);

	strncpy((char *)request.filename, filename, sizeof(request.filename));
	if (request.filename[sizeof(request.filename) - 1] != '\0')
		return -ENOSPC;

	ret = csp_transaction(CSP_PRIO_NORM, node, SL_POLARIS_PORT_BOOTLOADER, timeout,
			      &request, sizeof(request), &reply, sizeof(reply));
	if (ret != sizeof(reply))
		return -ECONNREFUSED;

	if (reply.type != SL_POLARIS_BOOTLOADER_FLASH_REP)
		return -EINVAL;

	if (reply.error != SL_POLARIS_ERR_NONE)
		return -reply.error;

	if (crc != NULL)
		*crc = csp_ntoh32(reply.checksum);

	return 0;
}

int sl_polaris_bootloader_erase_alternate(uint8_t node, uint32_t timeout)
{
	int ret;
	sl_polaris_bootloader_erase_req_t request;
	sl_polaris_bootloader_erase_rep_t reply;

	request.type = SL_POLARIS_BOOTLOADER_ERASE_REQ;
	request.flags = 0;
	request.key = csp_hton32(SL_POLARIS_BOOTLOADER_ERASE_KEY);

	ret = csp_transaction(CSP_PRIO_NORM, node, SL_POLARIS_PORT_BOOTLOADER, timeout,
			      &request, sizeof(request), &reply, sizeof(reply));
	if (ret != sizeof(reply))
		return -ECONNREFUSED;

	if (reply.type != SL_POLARIS_BOOTLOADER_ERASE_REP)
		return -EINVAL;

	if (reply.error != SL_POLARIS_ERR_NONE)
		return -reply.error;

	return 0;
}

int sl_polaris_bootloader_checksum_alternate(uint8_t node, uint32_t timeout, uint32_t size, uint32_t *crc)
{
	int ret;
	sl_polaris_bootloader_checksum_req_t request;
	sl_polaris_bootloader_checksum_rep_t reply;

	request.type = SL_POLARIS_BOOTLOADER_CHECKSUM_REQ;
	request.flags = 0;
	request.size = csp_hton32(size);

	ret = csp_transaction(CSP_PRIO_NORM, node, SL_POLARIS_PORT_BOOTLOADER, timeout,
			      &request, sizeof(request), &reply, sizeof(reply));
	if (ret != sizeof(reply))
		return -ECONNREFUSED;

	if (reply.type != SL_POLARIS_BOOTLOADER_CHECKSUM_REP)
		return -EINVAL;

	if (reply.error != SL_POLARIS_ERR_NONE)
		return -reply.error;

	if (crc != NULL)
		*crc = csp_ntoh32(reply.checksum);

	return 0;
}
