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

#if defined(__FreeBSD__)
#include <fcntl.h>
#include <unistd.h>
#endif

#include "common.h"
#include "cmos_lowlevel.h"

/* Hardware Abstraction Layer: lowlevel byte-wise write access */

extern cmos_access_t cmos_hal, memory_hal;
static cmos_access_t *current_access =
#ifdef CMOS_HAL
	&cmos_hal;
#else
	&memory_hal;
#endif

void select_hal(hal_t hal, void *data)
{
	switch(hal) {
#ifdef CMOS_HAL
		case HAL_CMOS:
			current_access = &cmos_hal;
			break;
#endif
		case HAL_MEMORY:
		default:
			current_access = &memory_hal;
			break;
	}
	current_access->init(data);
}

/* Bit-level access */
typedef struct {
	unsigned byte_index;
	unsigned bit_offset;
} cmos_bit_op_location_t;

static unsigned cmos_bit_op_strategy(unsigned bit, unsigned bits_left,
				     cmos_bit_op_location_t * where);
static unsigned char cmos_read_bits(const cmos_bit_op_location_t * where,
				    unsigned nr_bits);
static void cmos_write_bits(const cmos_bit_op_location_t * where,
			    unsigned nr_bits, unsigned char value);
static unsigned char get_bits(unsigned long long value, unsigned bit,
			      unsigned nr_bits);
static void put_bits(unsigned char value, unsigned bit, unsigned nr_bits,
		     unsigned long long *result);

/****************************************************************************
 * get_bits
 *
 * Extract a value 'nr_bits' bits wide starting at bit position 'bit' from
 * 'value' and return the result.  It is assumed that 'nr_bits' is at most 8.
 ****************************************************************************/
static inline unsigned char get_bits(unsigned long long value, unsigned bit,
				     unsigned nr_bits)
{
	return (value >> bit) & ((unsigned char)((1 << nr_bits) - 1));
}

/****************************************************************************
 * put_bits
 *
 * Extract the low order 'nr_bits' bits from 'value' and store them in the
 * value pointed to by 'result' starting at bit position 'bit'.  The bit
 * positions in 'result' where the result is stored are assumed to be
 * initially zero.
 ****************************************************************************/
static inline void put_bits(unsigned char value, unsigned bit,
			    unsigned nr_bits, unsigned long long *result)
{
	*result += ((unsigned long long)(value &
				((unsigned char)((1 << nr_bits) - 1)))) << bit;
}

/****************************************************************************
 * cmos_read
 *
 * Read value from nonvolatile RAM at position given by 'bit' and 'length'
 * and return this value.  The I/O privilege level of the currently executing
 * process must be set appropriately.
 *
 * Returned value is either (unsigned long long), or malloc()'d (char *)
 * cast to (unsigned long long)
 ****************************************************************************/
unsigned long long cmos_read(const cmos_entry_t * e)
{
	cmos_bit_op_location_t where;
	unsigned bit = e->bit, length = e->length;
	unsigned next_bit, bits_left, nr_bits;
	unsigned long long result = 0;
	unsigned char value;

	assert(!verify_cmos_op(bit, length, e->config));

	if (e->config == CMOS_ENTRY_STRING) {
		int strsz = (length + 7) / 8 + 1;
		char *newstring = malloc(strsz);
		unsigned usize = (8 * sizeof(unsigned long long));

		if (!newstring) {
			out_of_memory();
		}

		memset(newstring, 0, strsz);

		for (next_bit = 0, bits_left = length;
		     bits_left; next_bit += nr_bits, bits_left -= nr_bits) {
			nr_bits = cmos_bit_op_strategy(bit + next_bit,
				   bits_left > usize ? usize : bits_left, &where);
			value = cmos_read_bits(&where, nr_bits);
			put_bits(value, next_bit % usize, nr_bits,
				 &((unsigned long long *)newstring)[next_bit /
								    usize]);
			result = (unsigned long)newstring;
		}
	} else {
		for (next_bit = 0, bits_left = length;
		     bits_left; next_bit += nr_bits, bits_left -= nr_bits) {
			nr_bits =
			    cmos_bit_op_strategy(bit + next_bit, bits_left,
						 &where);
			value = cmos_read_bits(&where, nr_bits);
			put_bits(value, next_bit, nr_bits, &result);
		}
	}

	return result;
}

/****************************************************************************
 * cmos_write
 *
 * Write 'data' to nonvolatile RAM at position given by 'bit' and 'length'.
 * The I/O privilege level of the currently executing process must be set
 * appropriately.
 ****************************************************************************/
void cmos_write(const cmos_entry_t * e, unsigned long long value)
{
	cmos_bit_op_location_t where;
	unsigned bit = e->bit, length = e->length;
	unsigned next_bit, bits_left, nr_bits;

	assert(!verify_cmos_op(bit, length, e->config));

	if (e->config == CMOS_ENTRY_STRING) {
		unsigned long long *data =
		    (unsigned long long *)(unsigned long)value;
		unsigned usize = (8 * sizeof(unsigned long long));

		for (next_bit = 0, bits_left = length;
		     bits_left; next_bit += nr_bits, bits_left -= nr_bits) {
			nr_bits = cmos_bit_op_strategy(bit + next_bit,
					bits_left > usize ? usize : bits_left,
					&where);
			value = data[next_bit / usize];
			cmos_write_bits(&where, nr_bits,
				get_bits(value, next_bit % usize, nr_bits));
		}
	} else {
		for (next_bit = 0, bits_left = length;
		     bits_left; next_bit += nr_bits, bits_left -= nr_bits) {
			nr_bits = cmos_bit_op_strategy(bit + next_bit,
					bits_left, &where);
			cmos_write_bits(&where, nr_bits,
					get_bits(value, next_bit, nr_bits));
		}
	}
}

/****************************************************************************
 * cmos_read_byte
 *
 * Read a byte from nonvolatile RAM at a position given by 'index' and return
 * the result.  An 'index' value of 0 represents the first byte of
 * nonvolatile RAM.
 *
 * Note: the first 14 bytes of nonvolatile RAM provide an interface to the
 *       real time clock.
 ****************************************************************************/
unsigned char cmos_read_byte(unsigned index)
{
	return current_access->read(index);
}

/****************************************************************************
 * cmos_write_byte
 *
 * Write 'value' to nonvolatile RAM at a position given by 'index'.  An
 * 'index' of 0 represents the first byte of nonvolatile RAM.
 *
 * Note: the first 14 bytes of nonvolatile RAM provide an interface to the
 *       real time clock.  Writing to any of these bytes will therefore
 *       affect its functioning.
 ****************************************************************************/
void cmos_write_byte(unsigned index, unsigned char value)
{
	current_access->write(index, value);
}

/****************************************************************************
 * cmos_read_all
 *
 * Read all contents of CMOS memory into array 'data'.  The first 14 bytes of
 * 'data' are set to zero since this corresponds to the real time clock area.
 ****************************************************************************/
void cmos_read_all(unsigned char data[])
{
	unsigned i;

	for (i = 0; i < CMOS_RTC_AREA_SIZE; i++)
		data[i] = 0;

	for (; i < CMOS_SIZE; i++)
		data[i] = cmos_read_byte(i);
}

/****************************************************************************
 * cmos_write_all
 *
 * Update all of CMOS memory with the contents of array 'data'.  The first 14
 * bytes of 'data' are ignored since this corresponds to the real time clock
 * area.
 ****************************************************************************/
void cmos_write_all(unsigned char data[])
{
	unsigned i;

	for (i = CMOS_RTC_AREA_SIZE; i < CMOS_SIZE; i++)
		cmos_write_byte(i, data[i]);
}

/****************************************************************************
 * set_iopl
 *
 * Set the I/O privilege level of the executing process.  Root privileges are
 * required for performing this action.  A sufficient I/O privilege level
 * allows the process to access x86 I/O address space and to disable/reenable
 * interrupts while executing in user space.  Messing with the I/O privilege
 * level is therefore somewhat dangerous.
 ****************************************************************************/
void set_iopl(int level)
{
	current_access->set_iopl(level);
}

/****************************************************************************
 * verify_cmos_op
 *
 * 'bit' represents a bit position in the nonvolatile RAM.  The first bit
 * (i.e. the lowest order bit of the first byte) of nonvolatile RAM is
 * labeled as bit 0.  'length' represents the width in bits of a value we
 * wish to read or write.  Perform sanity checking on 'bit' and 'length'.  If
 * no problems were encountered, return OK.  Else return an error code.
 ****************************************************************************/
int verify_cmos_op(unsigned bit, unsigned length, cmos_entry_config_t config)
{
	if ((bit >= (8 * CMOS_SIZE)) || ((bit + length) > (8 * CMOS_SIZE)))
		return CMOS_AREA_OUT_OF_RANGE;

	if (bit < (8 * CMOS_RTC_AREA_SIZE))
		return CMOS_AREA_OVERLAPS_RTC;

	if (config == CMOS_ENTRY_STRING)
		return OK;

	if (length > (8 * sizeof(unsigned long long)))
		return CMOS_AREA_TOO_WIDE;

	return OK;
}

/****************************************************************************
 * cmos_bit_op_strategy
 *
 * Helper function used by cmos_read() and cmos_write() to determine which
 * bits to read or write next.
 ****************************************************************************/
static unsigned cmos_bit_op_strategy(unsigned bit, unsigned bits_left,
				     cmos_bit_op_location_t * where)
{
	unsigned max_bits;

	where->byte_index = bit >> 3;
	where->bit_offset = bit & 0x07;
	max_bits = 8 - where->bit_offset;
	return (bits_left > max_bits) ? max_bits : bits_left;
}

/****************************************************************************
 * cmos_read_bits
 *
 * Read a chunk of bits from a byte location within CMOS memory.  Return the
 * value represented by the chunk of bits.
 ****************************************************************************/
static unsigned char cmos_read_bits(const cmos_bit_op_location_t * where,
				    unsigned nr_bits)
{
	return (cmos_read_byte(where->byte_index) >> where->bit_offset) &
	    ((unsigned char)((1 << nr_bits) - 1));
}

/****************************************************************************
 * cmos_write_bits
 *
 * Write a chunk of bits (the low order 'nr_bits' bits of 'value') to an area
 * within a particular byte of CMOS memory.
 ****************************************************************************/
static void cmos_write_bits(const cmos_bit_op_location_t * where,
			    unsigned nr_bits, unsigned char value)
{
	unsigned char n, mask;

	if (nr_bits == 8) {
		cmos_write_byte(where->byte_index, value);
		return;
	}

	n = cmos_read_byte(where->byte_index);
	mask = ((unsigned char)((1 << nr_bits) - 1)) << where->bit_offset;
	n = (n & ~mask) + ((value << where->bit_offset) & mask);
	cmos_write_byte(where->byte_index, n);
}
