// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright IBM Corp. 2019
 */
#include <linux/pgtable.h>
#include <asm/physmem_info.h>
#include <asm/cpacf.h>
#include <asm/timex.h>
#include <asm/sclp.h>
#include <asm/kasan.h>
#include "decompressor.h"
#include "boot.h"

#define PRNG_MODE_TDES	 1
#define PRNG_MODE_SHA512 2
#define PRNG_MODE_TRNG	 3

struct prno_parm {
	u32 res;
	u32 reseed_counter;
	u64 stream_bytes;
	u8  V[112];
	u8  C[112];
};

struct prng_parm {
	u8  parm_block[32];
	u32 reseed_counter;
	u64 byte_counter;
};

static int check_prng(void)
{
	if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) {
		boot_printk("KASLR disabled: CPU has no PRNG\n");
		return 0;
	}
	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
		return PRNG_MODE_TRNG;
	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN))
		return PRNG_MODE_SHA512;
	else
		return PRNG_MODE_TDES;
}

int get_random(unsigned long limit, unsigned long *value)
{
	struct prng_parm prng = {
		/* initial parameter block for tdes mode, copied from libica */
		.parm_block = {
			0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52,
			0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4,
			0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF,
			0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0
		},
	};
	unsigned long seed, random;
	struct prno_parm prno;
	__u64 entropy[4];
	int mode, i;

	mode = check_prng();
	seed = get_tod_clock_fast();
	switch (mode) {
	case PRNG_MODE_TRNG:
		cpacf_trng(NULL, 0, (u8 *) &random, sizeof(random));
		break;
	case PRNG_MODE_SHA512:
		cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, &prno, NULL, 0,
			   (u8 *) &seed, sizeof(seed));
		cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prno, (u8 *) &random,
			   sizeof(random), NULL, 0);
		break;
	case PRNG_MODE_TDES:
		/* add entropy */
		*(unsigned long *) prng.parm_block ^= seed;
		for (i = 0; i < 16; i++) {
			cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block,
				  (u8 *) entropy, (u8 *) entropy,
				  sizeof(entropy));
			memcpy(prng.parm_block, entropy, sizeof(entropy));
		}
		random = seed;
		cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block, (u8 *) &random,
			  (u8 *) &random, sizeof(random));
		break;
	default:
		return -1;
	}
	*value = random % limit;
	return 0;
}

static void sort_reserved_ranges(struct reserved_range *res, unsigned long size)
{
	struct reserved_range tmp;
	int i, j;

	for (i = 1; i < size; i++) {
		tmp = res[i];
		for (j = i - 1; j >= 0 && res[j].start > tmp.start; j--)
			res[j + 1] = res[j];
		res[j + 1] = tmp;
	}
}

static unsigned long iterate_valid_positions(unsigned long size, unsigned long align,
					     unsigned long _min, unsigned long _max,
					     struct reserved_range *res, size_t res_count,
					     bool pos_count, unsigned long find_pos)
{
	unsigned long start, end, tmp_end, range_pos, pos = 0;
	struct reserved_range *res_end = res + res_count;
	struct reserved_range *skip_res;
	int i;

	align = max(align, 8UL);
	_min = round_up(_min, align);
	for_each_physmem_usable_range(i, &start, &end) {
		if (_min >= end)
			continue;
		start = round_up(start, align);
		if (start >= _max)
			break;
		start = max(_min, start);
		end = min(_max, end);

		while (start + size <= end) {
			/* skip reserved ranges below the start */
			while (res && res->end <= start) {
				res++;
				if (res >= res_end)
					res = NULL;
			}
			skip_res = NULL;
			tmp_end = end;
			/* has intersecting reserved range */
			if (res && res->start < end) {
				skip_res = res;
				tmp_end = res->start;
			}
			if (start + size <= tmp_end) {
				range_pos = (tmp_end - start - size) / align + 1;
				if (pos_count) {
					pos += range_pos;
				} else {
					if (range_pos >= find_pos)
						return start + (find_pos - 1) * align;
					find_pos -= range_pos;
				}
			}
			if (!skip_res)
				break;
			start = round_up(skip_res->end, align);
		}
	}

	return pos_count ? pos : 0;
}

/*
 * Two types of decompressor memory allocations/reserves are considered
 * differently.
 *
 * "Static" or "single" allocations are done via physmem_alloc_range() and
 * physmem_reserve(), and they are listed in physmem_info.reserved[]. Each
 * type of "static" allocation can only have one allocation per type and
 * cannot have chains.
 *
 * On the other hand, "dynamic" or "repetitive" allocations are done via
 * physmem_alloc_top_down(). These allocations are tightly packed together
 * top down from the end of online memory. physmem_alloc_pos represents
 * current position where those allocations start.
 *
 * Functions randomize_within_range() and iterate_valid_positions()
 * only consider "dynamic" allocations by never looking above
 * physmem_alloc_pos. "Static" allocations, however, are explicitly
 * considered by checking the "res" (reserves) array. The first
 * reserved_range of a "dynamic" allocation may also be checked along the
 * way, but it will always be above the maximum value anyway.
 */
unsigned long randomize_within_range(unsigned long size, unsigned long align,
				     unsigned long min, unsigned long max)
{
	struct reserved_range res[RR_MAX];
	unsigned long max_pos, pos;

	memcpy(res, physmem_info.reserved, sizeof(res));
	sort_reserved_ranges(res, ARRAY_SIZE(res));
	max = min(max, get_physmem_alloc_pos());

	max_pos = iterate_valid_positions(size, align, min, max, res, ARRAY_SIZE(res), true, 0);
	if (!max_pos)
		return 0;
	if (get_random(max_pos, &pos))
		return 0;
	return iterate_valid_positions(size, align, min, max, res, ARRAY_SIZE(res), false, pos + 1);
}
