^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) Paul Mackerras 1997.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Updates for PPC64 by Todd Inglett, Dave Engebretsen & Peter Bergner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "elf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "page.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "string.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "stdio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct addr_range {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static struct addr_range prep_kernel(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) char elfheader[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned char *vmlinuz_addr = (unsigned char *)_vmlinux_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void *addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct elf_info ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) long len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int uncompressed_image = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) len = partial_decompress(vmlinuz_addr, vmlinuz_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) elfheader, sizeof(elfheader), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* assume uncompressed data if -1 is returned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (len == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) uncompressed_image = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) memcpy(elfheader, vmlinuz_addr, sizeof(elfheader));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) printf("No valid compressed data found, assume uncompressed data\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (platform_ops.image_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) platform_ops.image_hdr(elfheader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* We need to alloc the memsize: gzip will expand the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * text/data, then possible rubbish we don't care about. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * the kernel bss must be claimed (it will be zero'd by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * kernel itself)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) printf("Allocating 0x%lx bytes for kernel...\n\r", ei.memsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (platform_ops.vmlinux_alloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) addr = platform_ops.vmlinux_alloc(ei.memsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * Check if the kernel image (without bss) would overwrite the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * bootwrapper. The device tree has been moved in fdt_init()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * to an area allocated with malloc() (somewhere past _end).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if ((unsigned long)_start < ei.loadsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) fatal("Insufficient memory for kernel at address 0!"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) " (_start=%p, uncompressed size=%08lx)\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) _start, ei.loadsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if ((unsigned long)_end < ei.memsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) fatal("The final kernel image would overwrite the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) "device tree\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (uncompressed_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) memcpy(addr, vmlinuz_addr + ei.elfoffset, ei.loadsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) printf("0x%lx bytes of uncompressed data copied\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ei.loadsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Finally, decompress the kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) len = partial_decompress(vmlinuz_addr, vmlinuz_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) addr, ei.loadsize, ei.elfoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) fatal("Decompression failed with error code %ld\n\r", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (len != ei.loadsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) fatal("Decompression error: got 0x%lx bytes, expected 0x%lx.\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) len, ei.loadsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) printf("Done! Decompressed 0x%lx bytes\n\r", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) flush_cache(addr, ei.loadsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return (struct addr_range){addr, ei.memsize};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned long initrd_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned long initrd_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* If we have an image attached to us, it overrides anything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * supplied by the loader. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (&_initrd_end > &_initrd_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) printf("Attached initrd image at 0x%p-0x%p\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) _initrd_start, _initrd_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) initrd_addr = (unsigned long)_initrd_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) initrd_size = _initrd_end - _initrd_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else if (initrd_size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) printf("Using loader supplied ramdisk at 0x%lx-0x%lx\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) initrd_addr, initrd_addr + initrd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* If there's no initrd at all, we're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (! initrd_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return (struct addr_range){0, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * If the initrd is too low it will be clobbered when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * kernel relocates to its final location. In this case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * allocate a safer place and move it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (initrd_addr < vmlinux.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void *old_addr = (void *)initrd_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) printf("Allocating 0x%lx bytes for initrd ...\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) initrd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) initrd_addr = (unsigned long)malloc(initrd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (! initrd_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) fatal("Can't allocate memory for initial "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) "ramdisk !\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) initrd_addr, old_addr, initrd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) memmove((void *)initrd_addr, old_addr, initrd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Tell the kernel initrd address via device tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return (struct addr_range){(void *)initrd_addr, initrd_size};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #ifdef __powerpc64__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void prep_esm_blob(struct addr_range vmlinux, void *chosen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned long esm_blob_addr, esm_blob_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* Do we have an ESM (Enter Secure Mode) blob? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (&_esm_blob_end <= &_esm_blob_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) printf("Attached ESM blob at 0x%p-0x%p\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) _esm_blob_start, _esm_blob_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) esm_blob_addr = (unsigned long)_esm_blob_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) esm_blob_size = _esm_blob_end - _esm_blob_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * If the ESM blob is too low it will be clobbered when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * kernel relocates to its final location. In this case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * allocate a safer place and move it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (esm_blob_addr < vmlinux.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) void *old_addr = (void *)esm_blob_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) printf("Allocating 0x%lx bytes for esm_blob ...\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) esm_blob_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) esm_blob_addr = (unsigned long)malloc(esm_blob_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (!esm_blob_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) fatal("Can't allocate memory for ESM blob !\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) printf("Relocating ESM blob 0x%lx <- 0x%p (0x%lx bytes)\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) esm_blob_addr, old_addr, esm_blob_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) memmove((void *)esm_blob_addr, old_addr, esm_blob_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* Tell the kernel ESM blob address via device tree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) setprop_val(chosen, "linux,esm-blob-start", (u32)(esm_blob_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) setprop_val(chosen, "linux,esm-blob-end", (u32)(esm_blob_addr + esm_blob_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static inline void prep_esm_blob(struct addr_range vmlinux, void *chosen) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* A buffer that may be edited by tools operating on a zImage binary so as to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * edit the command line passed to vmlinux (by setting /chosen/bootargs).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * The buffer is put in it's own section so that tools may locate it easier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static char cmdline[BOOT_COMMAND_LINE_SIZE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) __attribute__((__section__("__builtin_cmdline")));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void prep_cmdline(void *chosen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned int getline_timeout = 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Wait-for-input time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) n = getprop(chosen, "linux,cmdline-timeout", &v, sizeof(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (n == sizeof(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) getline_timeout = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (cmdline[0] == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) getprop(chosen, "bootargs", cmdline, BOOT_COMMAND_LINE_SIZE-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) printf("\n\rLinux/PowerPC load: %s", cmdline);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* If possible, edit the command line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (console_ops.edit_cmdline && getline_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) console_ops.edit_cmdline(cmdline, BOOT_COMMAND_LINE_SIZE, getline_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) printf("\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* Put the command line back into the devtree for the kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) setprop_str(chosen, "bootargs", cmdline);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct platform_ops platform_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct dt_ops dt_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct console_ops console_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct loader_info loader_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) void start(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct addr_range vmlinux, initrd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) kernel_entry_t kentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned long ft_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void *chosen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* Do this first, because malloc() could clobber the loader's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * command line. Only use the loader command line if a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * built-in command line wasn't set by an external tool */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) memmove(cmdline, loader_info.cmdline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) min(loader_info.cmdline_len, BOOT_COMMAND_LINE_SIZE-1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (console_ops.open && (console_ops.open() < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (platform_ops.fixups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) platform_ops.fixups();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) _start, get_sp());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Ensure that the device tree has a /chosen node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) chosen = finddevice("/chosen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!chosen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) chosen = create_node(NULL, "chosen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) vmlinux = prep_kernel();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) initrd = prep_initrd(vmlinux, chosen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) loader_info.initrd_addr, loader_info.initrd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) prep_esm_blob(vmlinux, chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) prep_cmdline(chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) printf("Finalizing device tree...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (dt_ops.finalize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ft_addr = dt_ops.finalize();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (ft_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) printf(" flat tree at 0x%lx\n\r", ft_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (console_ops.close)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) console_ops.close();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) kentry = (kernel_entry_t) vmlinux.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (ft_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if(platform_ops.kentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) platform_ops.kentry(ft_addr, vmlinux.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) kentry(ft_addr, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) kentry((unsigned long)initrd.addr, initrd.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) loader_info.promptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* console closed so printf in fatal below may not work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }