/*
 * Copyright 2016 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "futility.h"

enum {
	OPT_HELP = 1000,
	OPT_OFFSET,
};

static const struct option long_opts[] = {
	{"help", 0, 0, OPT_HELP},
	{"offset", 1, 0, OPT_OFFSET},
	{NULL, 0, NULL, 0},
};

static void print_help(int argc, char *argv[])
{
	printf("\nUsage:  " MYNAME " %s FILE [OPTIONS]\n", argv[0]);
	printf("\nOptions:\n");
	printf(" --offset <offset>          Offset of cache within FILE\n");
	printf("\n");
}

struct mrc_metadata {
	uint32_t signature;
	uint32_t data_size;
	uint16_t data_checksum;
	uint16_t header_checksum;
	uint32_t version;
} __attribute__((packed));

#define MRC_DATA_SIGNATURE		(('M'<<0)|('R'<<8)|('C'<<16)|('D'<<24))
#define REGF_BLOCK_SHIFT		4
#define REGF_BLOCK_GRANULARITY		(1 << REGF_BLOCK_SHIFT)
#define REGF_METADATA_BLOCK_SIZE	REGF_BLOCK_GRANULARITY
#define REGF_UNALLOCATED_BLOCK		0xffff

unsigned long compute_ip_checksum(const void *addr, unsigned long length)
{
	const uint8_t *ptr;
	volatile union {
		uint8_t  byte[2];
		uint16_t word;
	} value;
	unsigned long sum;
	unsigned long i;
	/* In the most straight forward way possible,
	 * compute an ip style checksum.
	 */
	sum = 0;
	ptr = addr;
	for(i = 0; i < length; i++) {
		unsigned long v;
		v = ptr[i];
		if (i & 1) {
			v <<= 8;
		}
		/* Add the new value */
		sum += v;
		/* Wrap around the carry */
		if (sum > 0xFFFF) {
			sum = (sum + (sum >> 16)) & 0xFFFF;
		}
	}
	value.byte[0] = sum & 0xff;
	value.byte[1] = (sum >> 8) & 0xff;
	return (~value.word) & 0xFFFF;
}

static int verify_mrc_slot(struct mrc_metadata *md, unsigned long slot_len)
{
	uint32_t header_checksum;

	if (slot_len < sizeof(*md)) {
		fprintf(stderr, "Slot too small!\n");
		return 1;
	}

	if (md->signature != MRC_DATA_SIGNATURE) {
		fprintf(stderr, "MRC signature mismatch\n");
		return 1;
	}

	fprintf(stderr, "MRC signature match.. successful\n");

	if (md->data_size > slot_len) {
		fprintf(stderr, "MRC cache size overflow\n");
		return 1;
	}

	header_checksum = md->header_checksum;
	md->header_checksum = 0;

	if (header_checksum != compute_ip_checksum(md, sizeof(*md))) {
		fprintf(stderr, "MRC metadata header checksum mismatch\n");
		return 1;
	}

	md->header_checksum = header_checksum;

	fprintf(stderr, "MRC metadata header checksum.. verified!\n");

	if (md->data_checksum != compute_ip_checksum(&md[1], md->data_size)) {
		fprintf(stderr, "MRC data checksum mismatch\n");
		return 1;
	}

	fprintf(stderr, "MRC data checksum.. verified!\n");
	return 0;
}

static int block_offset_unallocated(uint16_t offset)
{
	return offset == REGF_UNALLOCATED_BLOCK;
}

static uint8_t *get_next_mb(uint8_t *curr_mb)
{
	return curr_mb + REGF_METADATA_BLOCK_SIZE;
}

static int get_mrc_data_slot(uint16_t *mb, uint32_t *data_offset,
			     uint32_t *data_size)
{
	uint16_t num_metadata_blocks = *mb;

	if (block_offset_unallocated(*mb)) {
		fprintf(stderr, "MRC cache is empty!!\n");
		return 1;
	}

	/*
	 * First block offset in metadata block tells the total number of
	 * metadata blocks.
	 * Currently, we expect only 1 metadata block to be used.
	 */
	if (num_metadata_blocks != 1) {
		uint16_t *next_mb = (uint16_t *)get_next_mb((uint8_t *)mb);
		if (!block_offset_unallocated(*next_mb)) {
			fprintf(stderr, "More than 1 valid metadata block!!");
			return 1;
		}
	}

	/*
	 * RECOVERY_MRC_CACHE is expected to contain only one slot. Thus, there
	 * should be only one block offset present, indicating size of the MRC
	 * cache slot.
	 */
	mb++;
	*data_offset = (1 << REGF_BLOCK_SHIFT) * num_metadata_blocks;
	*data_size = (*mb - num_metadata_blocks) << REGF_BLOCK_SHIFT;

	mb++;
	if (!block_offset_unallocated(*mb)) {
		fprintf(stderr, "More than 1 slot in recovery mrc cache.\n");
		return 1;
	}

	return 0;
}

static int do_validate_rec_mrc(int argc, char *argv[])
{
	char *infile = NULL;
	int parse_error = 0;
	int fd, i, ret = 1;
	uint32_t file_size;
	uint8_t *buff;
	uint32_t offset = 0;
	uint32_t data_offset;
	uint32_t data_size;
	char *e;

	while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
	       !parse_error) {
		switch (i) {
		case OPT_HELP:
			print_help(argc, argv);
			return 0;
		case OPT_OFFSET:
			offset = strtoul(optarg, &e, 0);
			if (!*optarg || (e && *e)) {
				fprintf(stderr, "Invalid --offset\n");
				parse_error = 1;
			}
			break;
		default:
		case '?':
			parse_error = 1;
			break;
		}
	}

	if (parse_error) {
		print_help(argc, argv);
		return 1;
	}

	if ((argc - optind) < 1) {
		fprintf(stderr, "You must specify an input FILE!\n");
		print_help(argc, argv);
		return 1;
	} else if ((argc - optind) != 1) {
		fprintf(stderr, "Unexpected arguments!\n");
		print_help(argc, argv);
		return 1;
	}

	infile = argv[optind++];

	fd = open(infile, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "Cannot open %s:%s\n", infile, strerror(errno));
		return 1;
	}

	if (futil_map_file(fd, MAP_RO, &buff, &file_size) != FILE_ERR_NONE) {
		fprintf(stderr, "Cannot map file %s\n", infile);
		close(fd);
		return 1;
	}

	if (offset > file_size) {
		fprintf(stderr, "File size(0x%x) smaller than offset(0x%x)\n",
			file_size, offset);
		futil_unmap_file(fd, MAP_RO, buff, file_size);
		close(fd);
		return 1;
	}

	if (get_mrc_data_slot((uint16_t *)(buff + offset), &data_offset,
			      &data_size)) {
		fprintf(stderr, "Metadata block error\n");
		futil_unmap_file(fd, MAP_RO, buff, file_size);
		close(fd);
		return 1;
	}
	offset += data_offset;

	if ((file_size > offset) && ((file_size - offset) >= data_size))
		ret = verify_mrc_slot((struct mrc_metadata *)(buff + offset),
				      data_size);
	else
		fprintf(stderr, "Offset or data size greater than file size: "
			"offset=0x%x, file size=0x%x, data_size=0x%x\n",
			offset, file_size, data_size);

	if (futil_unmap_file(fd, MAP_RO, buff, file_size) != FILE_ERR_NONE) {
		fprintf(stderr, "Failed to unmap file %s\n", infile);
		ret = 1;
	}

	close(fd);
	return ret;
}

DECLARE_FUTIL_COMMAND(validate_rec_mrc, do_validate_rec_mrc, VBOOT_VERSION_ALL,
		      "Validates content of Recovery MRC cache");
