1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) Paul Mackerras 1997. 4 */ 5 #include <stdarg.h> 6 #include <stddef.h> 7 #include "types.h" 8 #include "elf.h" 9 #include "string.h" 10 #include "stdio.h" 11 #include "page.h" 12 #include "ops.h" 13 14 #include "of.h" 15 16 /* Value picked to match that used by yaboot */ 17 #define PROG_START 0x01400000 /* only used on 64-bit systems */ 18 #define RAM_END (512<<20) /* Fixme: use OF */ 19 #define ONE_MB 0x100000 20 21 22 23 static unsigned long claim_base; 24 25 void epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 26 unsigned long r6, unsigned long r7); 27 28 static void *of_try_claim(unsigned long size) 29 { 30 unsigned long addr = 0; 31 32 if (claim_base == 0) 33 claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); 34 35 for(; claim_base < RAM_END; claim_base += ONE_MB) { 36 #ifdef DEBUG 37 printf(" trying: 0x%08lx\n\r", claim_base); 38 #endif 39 addr = (unsigned long) of_claim(claim_base, size, 0); 40 if (addr != PROM_ERROR) 41 break; 42 } 43 if (addr == 0) 44 return NULL; 45 claim_base = PAGE_ALIGN(claim_base + size); 46 return (void *)addr; 47 } 48 49 static void of_image_hdr(const void *hdr) 50 { 51 const Elf64_Ehdr *elf64 = hdr; 52 53 if (elf64->e_ident[EI_CLASS] == ELFCLASS64) { 54 /* 55 * Maintain a "magic" minimum address. This keeps some older 56 * firmware platforms running. 57 */ 58 if (claim_base < PROG_START) 59 claim_base = PROG_START; 60 } 61 } 62 63 static void of_platform_init(unsigned long a1, unsigned long a2, void *promptr) 64 { 65 platform_ops.image_hdr = of_image_hdr; 66 platform_ops.malloc = of_try_claim; 67 platform_ops.exit = of_exit; 68 platform_ops.vmlinux_alloc = of_vmlinux_alloc; 69 70 dt_ops.finddevice = of_finddevice; 71 dt_ops.getprop = of_getprop; 72 dt_ops.setprop = of_setprop; 73 74 of_console_init(); 75 76 of_init(promptr); 77 loader_info.promptr = promptr; 78 if (a1 && a2 && a2 != 0xdeadbeef) { 79 loader_info.initrd_addr = a1; 80 loader_info.initrd_size = a2; 81 } 82 } 83 84 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 85 unsigned long r6, unsigned long r7) 86 { 87 /* Detect OF vs. ePAPR boot */ 88 if (r5) 89 of_platform_init(r3, r4, (void *)r5); 90 else 91 epapr_platform_init(r3, r4, r5, r6, r7); 92 } 93 94