// SPDX-License-Identifier: GPL-2.0+
/*
 * EFI efi_selftest
 *
 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
 */

#include <efi_selftest.h>
#include <vsprintf.h>

struct efi_simple_text_output_protocol *con_out;
struct efi_simple_text_input_protocol *con_in;

/*
 * Print a MAC address to an u16 string
 *
 * @pointer: mac address
 * @buf: pointer to buffer address
 * on return position of terminating zero word
 */
static void mac(void *pointer, u16 **buf)
{
	int i, j;
	u16 c;
	u8 *p = (u8 *)pointer;
	u8 byte;
	u16 *pos = *buf;

	for (i = 0; i < ARP_HLEN; ++i) {
		if (i)
			*pos++ = ':';
		byte = p[i];
		for (j = 4; j >= 0; j -= 4) {
			c = (byte >> j) & 0x0f;
			c += '0';
			if (c > '9')
				c += 'a' - '9' - 1;
			*pos++ = c;
		}
	}
	*pos = 0;
	*buf = pos;
}

/*
 * Print a pointer to an u16 string
 *
 * @pointer: pointer
 * @buf: pointer to buffer address
 * on return position of terminating zero word
 */
static void pointer(void *pointer, u16 **buf)
{
	int i;
	u16 c;
	uintptr_t p = (uintptr_t)pointer;
	u16 *pos = *buf;

	for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
		c = (p >> i) & 0x0f;
		c += '0';
		if (c > '9')
			c += 'a' - '9' - 1;
		*pos++ = c;
	}
	*pos = 0;
	*buf = pos;
}

/*
 * Print an unsigned 32bit value as decimal number to an u16 string
 *
 * @value:	value to be printed
 * @prec:	minimum number of digits to display
 * @buf:	pointer to buffer address
 *		on return position of terminating zero word
 */
static void uint2dec(u32 value, int prec, u16 **buf)
{
	u16 *pos = *buf;
	int i;
	u16 c;
	u64 f;

	/*
	 * Increment by .5 and multiply with
	 * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
	 * to move the first digit to bit 60-63.
	 */
	f = 0x225C17D0;
	f += (0x9B5A52DULL * value) >> 28;
	f += 0x44B82FA0ULL * value;

	for (i = 0; i < 10; ++i) {
		/* Write current digit */
		c = f >> 60;
		if (c || pos != *buf || 10 - i <= prec)
			*pos++ = c + '0';
		/* Eliminate current digit */
		f &= 0xfffffffffffffff;
		/* Get next digit */
		f *= 0xaULL;
	}
	if (pos == *buf)
		*pos++ = '0';
	*pos = 0;
	*buf = pos;
}

/*
 * Print a signed 32bit value as decimal number to an u16 string
 *
 * @value:	value to be printed
 * @prec:	minimum number of digits to display
 * @buf:	pointer to buffer address
 * on return position of terminating zero word
 */
static void int2dec(s32 value, int prec, u16 **buf)
{
	u32 u;
	u16 *pos = *buf;

	if (value < 0) {
		*pos++ = '-';
		u = -value;
	} else {
		u = value;
	}
	uint2dec(u, prec, &pos);
	*buf = pos;
}

/*
 * Print a colored formatted string to the EFI console
 *
 * @color	color, see constants in efi_api.h, use -1 for no color
 * @fmt		format string
 * @...		optional arguments
 */
void efi_st_printc(int color, const char *fmt, ...)
{
	va_list args;
	u16 buf[160];
	const char *c;
	u16 *pos = buf;
	const char *s;
	u16 *u;
	int prec;

	va_start(args, fmt);

	if (color >= 0)
		con_out->set_attribute(con_out, (unsigned long)color);
	c = fmt;
	for (; *c; ++c) {
		switch (*c) {
		case '\\':
			++c;
			switch (*c) {
			case '\0':
				--c;
				break;
			case 'n':
				*pos++ = '\n';
				break;
			case 'r':
				*pos++ = '\r';
				break;
			case 't':
				*pos++ = '\t';
				break;
			default:
				*pos++ = *c;
			}
			break;
		case '%':
			++c;
			/* Parse precision */
			if (*c == '.') {
				++c;
				prec = *c - '0';
				++c;
			} else {
				prec = 0;
			}
			switch (*c) {
			case '\0':
				--c;
				break;
			case 'd':
				int2dec(va_arg(args, s32), prec, &pos);
				break;
			case 'p':
				++c;
				switch (*c) {
				/* MAC address */
				case 'm':
					mac(va_arg(args, void*), &pos);
					break;

				/* u16 string */
				case 's':
					u = va_arg(args, u16*);
					if (pos > buf) {
						*pos = 0;
						con_out->output_string(con_out,
								       buf);
					}
					con_out->output_string(con_out, u);
					pos = buf;
					break;
				default:
					--c;
					pointer(va_arg(args, void*), &pos);
				}
				break;
			case 's':
				s = va_arg(args, const char *);
				for (; *s; ++s)
					*pos++ = *s;
				break;
			case 'u':
				uint2dec(va_arg(args, u32), prec, &pos);
				break;
			default:
				break;
			}
			break;
		default:
			*pos++ = *c;
		}
	}
	va_end(args);
	*pos = 0;
	con_out->output_string(con_out, buf);
	if (color >= 0)
		con_out->set_attribute(con_out, EFI_LIGHTGRAY);
}

/*
 * Reads an Unicode character from the input device.
 *
 * @return: Unicode character
 */
u16 efi_st_get_key(void)
{
	struct efi_input_key input_key;
	efi_status_t ret;

	/* Wait for next key */
	do {
		ret = con_in->read_key_stroke(con_in, &input_key);
	} while (ret == EFI_NOT_READY);
	return input_key.unicode_char;
}
