18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) Paul Mackerras 1997.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#include <stdarg.h>
68c2ecf20Sopenharmony_ci#include <stddef.h>
78c2ecf20Sopenharmony_ci#include "types.h"
88c2ecf20Sopenharmony_ci#include "elf.h"
98c2ecf20Sopenharmony_ci#include "string.h"
108c2ecf20Sopenharmony_ci#include "stdio.h"
118c2ecf20Sopenharmony_ci#include "page.h"
128c2ecf20Sopenharmony_ci#include "ops.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "of.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* Value picked to match that used by yaboot */
178c2ecf20Sopenharmony_ci#define PROG_START	0x01400000	/* only used on 64-bit systems */
188c2ecf20Sopenharmony_ci#define RAM_END		(512<<20)	/* Fixme: use OF */
198c2ecf20Sopenharmony_ci#define	ONE_MB		0x100000
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic unsigned long claim_base;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_civoid epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
268c2ecf20Sopenharmony_ci			 unsigned long r6, unsigned long r7);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic void *of_try_claim(unsigned long size)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	unsigned long addr = 0;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	if (claim_base == 0)
338c2ecf20Sopenharmony_ci		claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	for(; claim_base < RAM_END; claim_base += ONE_MB) {
368c2ecf20Sopenharmony_ci#ifdef DEBUG
378c2ecf20Sopenharmony_ci		printf("    trying: 0x%08lx\n\r", claim_base);
388c2ecf20Sopenharmony_ci#endif
398c2ecf20Sopenharmony_ci		addr = (unsigned long) of_claim(claim_base, size, 0);
408c2ecf20Sopenharmony_ci		if (addr != PROM_ERROR)
418c2ecf20Sopenharmony_ci			break;
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci	if (addr == 0)
448c2ecf20Sopenharmony_ci		return NULL;
458c2ecf20Sopenharmony_ci	claim_base = PAGE_ALIGN(claim_base + size);
468c2ecf20Sopenharmony_ci	return (void *)addr;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic void of_image_hdr(const void *hdr)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	const Elf64_Ehdr *elf64 = hdr;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	if (elf64->e_ident[EI_CLASS] == ELFCLASS64) {
548c2ecf20Sopenharmony_ci		/*
558c2ecf20Sopenharmony_ci		 * Maintain a "magic" minimum address. This keeps some older
568c2ecf20Sopenharmony_ci		 * firmware platforms running.
578c2ecf20Sopenharmony_ci		 */
588c2ecf20Sopenharmony_ci		if (claim_base < PROG_START)
598c2ecf20Sopenharmony_ci			claim_base = PROG_START;
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic void of_platform_init(unsigned long a1, unsigned long a2, void *promptr)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	platform_ops.image_hdr = of_image_hdr;
668c2ecf20Sopenharmony_ci	platform_ops.malloc = of_try_claim;
678c2ecf20Sopenharmony_ci	platform_ops.exit = of_exit;
688c2ecf20Sopenharmony_ci	platform_ops.vmlinux_alloc = of_vmlinux_alloc;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	dt_ops.finddevice = of_finddevice;
718c2ecf20Sopenharmony_ci	dt_ops.getprop = of_getprop;
728c2ecf20Sopenharmony_ci	dt_ops.setprop = of_setprop;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	of_console_init();
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	of_init(promptr);
778c2ecf20Sopenharmony_ci	loader_info.promptr = promptr;
788c2ecf20Sopenharmony_ci	if (a1 && a2 && a2 != 0xdeadbeef) {
798c2ecf20Sopenharmony_ci		loader_info.initrd_addr = a1;
808c2ecf20Sopenharmony_ci		loader_info.initrd_size = a2;
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_civoid platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
858c2ecf20Sopenharmony_ci		   unsigned long r6, unsigned long r7)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	/* Detect OF vs. ePAPR boot */
888c2ecf20Sopenharmony_ci	if (r5)
898c2ecf20Sopenharmony_ci		of_platform_init(r3, r4, (void *)r5);
908c2ecf20Sopenharmony_ci	else
918c2ecf20Sopenharmony_ci		epapr_platform_init(r3, r4, r5, r6, r7);
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
94