162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) Paul Mackerras 1997.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <stdarg.h>
662306a36Sopenharmony_ci#include <stddef.h>
762306a36Sopenharmony_ci#include "types.h"
862306a36Sopenharmony_ci#include "elf.h"
962306a36Sopenharmony_ci#include "string.h"
1062306a36Sopenharmony_ci#include "stdio.h"
1162306a36Sopenharmony_ci#include "page.h"
1262306a36Sopenharmony_ci#include "ops.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "of.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* Value picked to match that used by yaboot */
1762306a36Sopenharmony_ci#define PROG_START	0x01400000	/* only used on 64-bit systems */
1862306a36Sopenharmony_ci#define RAM_END		(512<<20)	/* Fixme: use OF */
1962306a36Sopenharmony_ci#define	ONE_MB		0x100000
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic unsigned long claim_base;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_civoid epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
2662306a36Sopenharmony_ci			 unsigned long r6, unsigned long r7);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic void *of_try_claim(unsigned long size)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	unsigned long addr = 0;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (claim_base == 0)
3362306a36Sopenharmony_ci		claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	for(; claim_base < RAM_END; claim_base += ONE_MB) {
3662306a36Sopenharmony_ci#ifdef DEBUG
3762306a36Sopenharmony_ci		printf("    trying: 0x%08lx\n\r", claim_base);
3862306a36Sopenharmony_ci#endif
3962306a36Sopenharmony_ci		addr = (unsigned long) of_claim(claim_base, size, 0);
4062306a36Sopenharmony_ci		if (addr != PROM_ERROR)
4162306a36Sopenharmony_ci			break;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci	if (addr == 0)
4462306a36Sopenharmony_ci		return NULL;
4562306a36Sopenharmony_ci	claim_base = PAGE_ALIGN(claim_base + size);
4662306a36Sopenharmony_ci	return (void *)addr;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic void of_image_hdr(const void *hdr)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	const Elf64_Ehdr *elf64 = hdr;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	if (elf64->e_ident[EI_CLASS] == ELFCLASS64) {
5462306a36Sopenharmony_ci		/*
5562306a36Sopenharmony_ci		 * Maintain a "magic" minimum address. This keeps some older
5662306a36Sopenharmony_ci		 * firmware platforms running.
5762306a36Sopenharmony_ci		 */
5862306a36Sopenharmony_ci		if (claim_base < PROG_START)
5962306a36Sopenharmony_ci			claim_base = PROG_START;
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic void of_platform_init(unsigned long a1, unsigned long a2, void *promptr)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	platform_ops.image_hdr = of_image_hdr;
6662306a36Sopenharmony_ci	platform_ops.malloc = of_try_claim;
6762306a36Sopenharmony_ci	platform_ops.exit = of_exit;
6862306a36Sopenharmony_ci	platform_ops.vmlinux_alloc = of_vmlinux_alloc;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	dt_ops.finddevice = of_finddevice;
7162306a36Sopenharmony_ci	dt_ops.getprop = of_getprop;
7262306a36Sopenharmony_ci	dt_ops.setprop = of_setprop;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	of_console_init();
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	of_init(promptr);
7762306a36Sopenharmony_ci	loader_info.promptr = promptr;
7862306a36Sopenharmony_ci	if (a1 && a2 && a2 != 0xdeadbeef) {
7962306a36Sopenharmony_ci		loader_info.initrd_addr = a1;
8062306a36Sopenharmony_ci		loader_info.initrd_size = a2;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_civoid platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
8562306a36Sopenharmony_ci		   unsigned long r6, unsigned long r7)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	/* Detect OF vs. ePAPR boot */
8862306a36Sopenharmony_ci	if (r5)
8962306a36Sopenharmony_ci		of_platform_init(r3, r4, (void *)r5);
9062306a36Sopenharmony_ci	else
9162306a36Sopenharmony_ci		epapr_platform_init(r3, r4, r5, r6, r7);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
94