/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <string.h>
#include <cbfs.h>
#include <option.h>
#include <pc80/mc146818rtc.h>
#include <types.h>

/* option_table.h is autogenerated */
#include "option_table.h"

/* Don't warn for checking >= LB_CKS_RANGE_START even though it may be 0. */
#pragma GCC diagnostic ignored "-Wtype-limits"

/*
 * This routine returns the value of the requested bits.
 * input bit = bit count from the beginning of the CMOS image
 * length = number of bits to include in the value
 * ret = a character pointer to where the value is to be returned
 * returns CB_SUCCESS = successful, cb_err code if an error occurred
 */
static enum cb_err get_cmos_value(unsigned long bit, unsigned long length,
				  void *vret)
{
	unsigned char *ret;
	unsigned long byte, byte_bit;
	unsigned long i;
	unsigned char uchar;

	/*
	 * The table is checked when it is built to ensure all
	 * values are valid.
	 */
	ret = vret;
	byte = bit / 8;	/* find the byte where the data starts */
	byte_bit = bit % 8; /* find the bit in the byte where the data starts */
	if (length < 9) {	/* one byte or less */
		uchar = cmos_read(byte); /* load the byte */
		uchar >>= byte_bit;	/* shift the bits to byte align */
		/* clear unspecified bits */
		ret[0] = uchar & ((1 << length) - 1);
	} else {	/* more than one byte so transfer the whole bytes */
		for (i = 0; length; i++, length -= 8, byte++) {
			/* load the byte */
			ret[i] = cmos_read(byte);
		}
	}
	return CB_SUCCESS;
}

static enum cb_err locate_cmos_layout(struct region_device *rdev)
{
	uint32_t cbfs_type = CBFS_COMPONENT_CMOS_LAYOUT;
	static struct cbfsf fh;

	/*
	 * In case VBOOT is enabled and this function is called from SMM,
	 * we have multiple CMOS layout files and to locate them we'd need to
	 * include VBOOT into SMM...
	 *
	 * Support only one CMOS layout in the 'COREBOOT' region for now.
	 */
	if (!region_device_sz(&(fh.data))) {
		if (cbfs_locate_file_in_region(&fh, "COREBOOT", "cmos_layout.bin",
					       &cbfs_type)) {
			printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
						"Options are disabled\n");
			return CB_CMOS_LAYOUT_NOT_FOUND;
		}
	}

	cbfs_file_data(rdev, &fh);

	return CB_SUCCESS;
}

enum cb_err cmos_get_option(void *dest, const char *name)
{
	struct cmos_option_table *ct;
	struct region_device rdev;
	struct cmos_entries *ce;
	size_t namelen;
	int found = 0;

	/* Figure out how long name is */
	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);

	if (locate_cmos_layout(&rdev) != CB_SUCCESS) {
		return CB_CMOS_LAYOUT_NOT_FOUND;
	}
	ct = rdev_mmap_full(&rdev);
	if (!ct) {
		printk(BIOS_ERR, "RTC: cmos_layout.bin could not be mapped. "
		       "Options are disabled\n");

		return CB_CMOS_LAYOUT_NOT_FOUND;
	}

	/* find the requested entry record */
	ce = (struct cmos_entries *)((unsigned char *)ct + ct->header_length);
	for (; ce->tag == LB_TAG_OPTION;
		ce = (struct cmos_entries *)((unsigned char *)ce + ce->size)) {
		if (memcmp(ce->name, name, namelen) == 0) {
			found = 1;
			break;
		}
	}
	if (!found) {
		printk(BIOS_DEBUG, "No CMOS option '%s'.\n", name);
		rdev_munmap(&rdev, ct);
		return CB_CMOS_OPTION_NOT_FOUND;
	}

	if (!cmos_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END, LB_CKS_LOC)) {
		rdev_munmap(&rdev, ct);
		return CB_CMOS_CHECKSUM_INVALID;
	}
	if (get_cmos_value(ce->bit, ce->length, dest) != CB_SUCCESS) {
		rdev_munmap(&rdev, ct);
		return CB_CMOS_ACCESS_ERROR;
	}
	rdev_munmap(&rdev, ct);
	return CB_SUCCESS;
}

static enum cb_err set_cmos_value(unsigned long bit, unsigned long length,
				  void *vret)
{
	unsigned char *ret;
	unsigned long byte, byte_bit;
	unsigned long i;
	unsigned char uchar, mask;
	unsigned int chksum_update_needed = 0;

	ret = vret;
	byte = bit / 8;		/* find the byte where the data starts */
	byte_bit = bit % 8;	/* find the bit where the data starts */
	if (length <= 8) {	/* one byte or less */
		mask = (1 << length) - 1;
		mask <<= byte_bit;

		uchar = cmos_read(byte);
		uchar &= ~mask;
		uchar |= (ret[0] << byte_bit);
		cmos_write(uchar, byte);
		if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END)
			chksum_update_needed = 1;
	} else { /* more that one byte so transfer the whole bytes */
		if (byte_bit || length % 8)
			return CB_ERR_ARG;

		for (i = 0; length; i++, length -= 8, byte++) {
			cmos_write(ret[i], byte);
			if (byte >= LB_CKS_RANGE_START &&
			    byte <= LB_CKS_RANGE_END)
				chksum_update_needed = 1;
		}
	}

	if (chksum_update_needed) {
		cmos_set_checksum(LB_CKS_RANGE_START, LB_CKS_RANGE_END,
				  LB_CKS_LOC);
	}
	return CB_SUCCESS;
}

enum cb_err cmos_set_option(const char *name, void *value)
{
	struct cmos_option_table *ct;
	struct region_device rdev;
	struct cmos_entries *ce;
	unsigned long length;
	size_t namelen;
	int found = 0;

	/* Figure out how long name is */
	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);

	if (locate_cmos_layout(&rdev) != CB_SUCCESS) {
		return CB_CMOS_LAYOUT_NOT_FOUND;
	}
	ct = rdev_mmap_full(&rdev);
	if (!ct) {
		printk(BIOS_ERR, "RTC: cmos_layout.bin could not be mapped. "
		       "Options are disabled\n");

		return CB_CMOS_LAYOUT_NOT_FOUND;
	}

	/* find the requested entry record */
	ce = (struct cmos_entries *)((unsigned char *)ct + ct->header_length);
	for (; ce->tag == LB_TAG_OPTION;
		ce = (struct cmos_entries *)((unsigned char *)ce + ce->size)) {
		if (memcmp(ce->name, name, namelen) == 0) {
			found = 1;
			break;
		}
	}
	if (!found) {
		printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name);
		rdev_munmap(&rdev, ct);
		return CB_CMOS_OPTION_NOT_FOUND;
	}

	length = ce->length;
	if (ce->config == 's') {
		length = MAX(strlen((const char *)value) * 8, ce->length - 8);
		/* make sure the string is null terminated */
		if (set_cmos_value(ce->bit + ce->length - 8, 8, &(u8[]){0})
		    != CB_SUCCESS) {
			rdev_munmap(&rdev, ct);
			return CB_CMOS_ACCESS_ERROR;
		}
	}

	if (set_cmos_value(ce->bit, length, value) != CB_SUCCESS) {
		rdev_munmap(&rdev, ct);
		return CB_CMOS_ACCESS_ERROR;
	}

	rdev_munmap(&rdev, ct);
	return CB_SUCCESS;
}

int cmos_lb_cks_valid(void)
{
	return cmos_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END, LB_CKS_LOC);
}

void sanitize_cmos(void)
{
	const unsigned char *cmos_default;
	const bool cmos_need_reset =
		CONFIG(STATIC_OPTION_TABLE) || cmos_error() || !cmos_lb_cks_valid();
	size_t length = 128;
	size_t i;

	if (CONFIG(TPM_MEASURED_BOOT) || cmos_need_reset) {
		cmos_default = cbfs_map("cmos.default", &length);

		if (!cmos_default || !cmos_need_reset)
			return;

		u8 control_state = cmos_disable_rtc();
		for (i = 14; i < MIN(128, length); i++)
			cmos_write_inner(cmos_default[i], i);
		cmos_restore_rtc(control_state);
	}
}
