xref: /openbmc/linux/arch/alpha/boot/bootpz.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * arch/alpha/boot/bootpz.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (C) 1997 Jay Estabrook
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * This file is used for creating a compressed BOOTP file for the
81da177e4SLinus Torvalds  * Linux/AXP kernel
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * based significantly on the arch/alpha/boot/main.c of Linus Torvalds
111da177e4SLinus Torvalds  * and the decompression code from MILO.
121da177e4SLinus Torvalds  */
131da177e4SLinus Torvalds #include <linux/kernel.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
151da177e4SLinus Torvalds #include <linux/string.h>
16273b281fSSam Ravnborg #include <generated/utsrelease.h>
171da177e4SLinus Torvalds #include <linux/mm.h>
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds #include <asm/console.h>
201da177e4SLinus Torvalds #include <asm/hwrpb.h>
211da177e4SLinus Torvalds #include <asm/io.h>
221da177e4SLinus Torvalds 
23*e07f68d5SAl Viro #include <linux/stdarg.h>
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #include "kzsize.h"
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds /* FIXME FIXME FIXME */
281da177e4SLinus Torvalds #define MALLOC_AREA_SIZE 0x200000 /* 2MB for now */
291da177e4SLinus Torvalds /* FIXME FIXME FIXME */
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds /*
331da177e4SLinus Torvalds   WARNING NOTE
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds   It is very possible that turning on additional messages may cause
361da177e4SLinus Torvalds   kernel image corruption due to stack usage to do the printing.
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds */
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds #undef DEBUG_CHECK_RANGE
411da177e4SLinus Torvalds #undef DEBUG_ADDRESSES
421da177e4SLinus Torvalds #undef DEBUG_LAST_STEPS
431da177e4SLinus Torvalds 
441da177e4SLinus Torvalds extern unsigned long switch_to_osf_pal(unsigned long nr,
451da177e4SLinus Torvalds 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
461da177e4SLinus Torvalds 	unsigned long *vptb);
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds extern int decompress_kernel(void* destination, void *source,
491da177e4SLinus Torvalds 			     size_t ksize, size_t kzsize);
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds extern void move_stack(unsigned long new_stack);
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds struct hwrpb_struct *hwrpb = INIT_HWRPB;
541da177e4SLinus Torvalds static struct pcb_struct pcb_va[1];
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds /*
571da177e4SLinus Torvalds  * Find a physical address of a virtual object..
581da177e4SLinus Torvalds  *
591da177e4SLinus Torvalds  * This is easy using the virtual page table address.
601da177e4SLinus Torvalds  */
611da177e4SLinus Torvalds #define VPTB	((unsigned long *) 0x200000000)
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds static inline unsigned long
find_pa(unsigned long address)641da177e4SLinus Torvalds find_pa(unsigned long address)
651da177e4SLinus Torvalds {
661da177e4SLinus Torvalds 	unsigned long result;
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds 	result = VPTB[address >> 13];
691da177e4SLinus Torvalds 	result >>= 32;
701da177e4SLinus Torvalds 	result <<= 13;
711da177e4SLinus Torvalds 	result |= address & 0x1fff;
721da177e4SLinus Torvalds 	return result;
731da177e4SLinus Torvalds }
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds int
check_range(unsigned long vstart,unsigned long vend,unsigned long kstart,unsigned long kend)761da177e4SLinus Torvalds check_range(unsigned long vstart, unsigned long vend,
771da177e4SLinus Torvalds 	    unsigned long kstart, unsigned long kend)
781da177e4SLinus Torvalds {
791da177e4SLinus Torvalds 	unsigned long vaddr, kaddr;
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds #ifdef DEBUG_CHECK_RANGE
821da177e4SLinus Torvalds 	srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n",
831da177e4SLinus Torvalds 		   vstart, vend, kstart, kend);
841da177e4SLinus Torvalds #endif
851da177e4SLinus Torvalds 	/* do some range checking for detecting an overlap... */
861da177e4SLinus Torvalds 	for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE)
871da177e4SLinus Torvalds 	{
881da177e4SLinus Torvalds 		kaddr = (find_pa(vaddr) | PAGE_OFFSET);
891da177e4SLinus Torvalds 		if (kaddr >= kstart && kaddr <= kend)
901da177e4SLinus Torvalds 		{
911da177e4SLinus Torvalds #ifdef DEBUG_CHECK_RANGE
921da177e4SLinus Torvalds 			srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx"
931da177e4SLinus Torvalds 				   " [0x%lx:0x%lx]\n",
941da177e4SLinus Torvalds 				   vaddr, kaddr, kstart, kend);
951da177e4SLinus Torvalds #endif
961da177e4SLinus Torvalds 			return 1;
971da177e4SLinus Torvalds 		}
981da177e4SLinus Torvalds 	}
991da177e4SLinus Torvalds 	return 0;
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds /*
1031da177e4SLinus Torvalds  * This function moves into OSF/1 pal-code, and has a temporary
1041da177e4SLinus Torvalds  * PCB for that. The kernel proper should replace this PCB with
1051da177e4SLinus Torvalds  * the real one as soon as possible.
1061da177e4SLinus Torvalds  *
1071da177e4SLinus Torvalds  * The page table muckery in here depends on the fact that the boot
1081da177e4SLinus Torvalds  * code has the L1 page table identity-map itself in the second PTE
1091da177e4SLinus Torvalds  * in the L1 page table. Thus the L1-page is virtually addressable
1101da177e4SLinus Torvalds  * itself (through three levels) at virtual address 0x200802000.
1111da177e4SLinus Torvalds  */
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds #define L1	((unsigned long *) 0x200802000)
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds void
pal_init(void)1161da177e4SLinus Torvalds pal_init(void)
1171da177e4SLinus Torvalds {
1181da177e4SLinus Torvalds 	unsigned long i, rev;
1191da177e4SLinus Torvalds 	struct percpu_struct * percpu;
1201da177e4SLinus Torvalds 	struct pcb_struct * pcb_pa;
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	/* Create the dummy PCB.  */
1231da177e4SLinus Torvalds 	pcb_va->ksp = 0;
1241da177e4SLinus Torvalds 	pcb_va->usp = 0;
1251da177e4SLinus Torvalds 	pcb_va->ptbr = L1[1] >> 32;
1261da177e4SLinus Torvalds 	pcb_va->asn = 0;
1271da177e4SLinus Torvalds 	pcb_va->pcc = 0;
1281da177e4SLinus Torvalds 	pcb_va->unique = 0;
1291da177e4SLinus Torvalds 	pcb_va->flags = 1;
1301da177e4SLinus Torvalds 	pcb_va->res1 = 0;
1311da177e4SLinus Torvalds 	pcb_va->res2 = 0;
1321da177e4SLinus Torvalds 	pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va);
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	/*
1351da177e4SLinus Torvalds 	 * a0 = 2 (OSF)
1361da177e4SLinus Torvalds 	 * a1 = return address, but we give the asm the vaddr of the PCB
1371da177e4SLinus Torvalds 	 * a2 = physical addr of PCB
1381da177e4SLinus Torvalds 	 * a3 = new virtual page table pointer
1391da177e4SLinus Torvalds 	 * a4 = KSP (but the asm sets it)
1401da177e4SLinus Torvalds 	 */
1411da177e4SLinus Torvalds 	srm_printk("Switching to OSF PAL-code... ");
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds 	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
1441da177e4SLinus Torvalds 	if (i) {
1451da177e4SLinus Torvalds 		srm_printk("failed, code %ld\n", i);
1461da177e4SLinus Torvalds 		__halt();
1471da177e4SLinus Torvalds 	}
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	percpu = (struct percpu_struct *)
1501da177e4SLinus Torvalds 		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
1511da177e4SLinus Torvalds 	rev = percpu->pal_revision = percpu->palcode_avail[2];
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds 	srm_printk("OK (rev %lx)\n", rev);
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 	tbia(); /* do it directly in case we are SMP */
1561da177e4SLinus Torvalds }
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds /*
1591da177e4SLinus Torvalds  * Start the kernel.
1601da177e4SLinus Torvalds  */
1611da177e4SLinus Torvalds static inline void
runkernel(void)1621da177e4SLinus Torvalds runkernel(void)
1631da177e4SLinus Torvalds {
1641da177e4SLinus Torvalds 	__asm__ __volatile__(
1651da177e4SLinus Torvalds 		"bis %0,%0,$27\n\t"
1661da177e4SLinus Torvalds 		"jmp ($27)"
1671da177e4SLinus Torvalds 		: /* no outputs: it doesn't even return */
1681da177e4SLinus Torvalds 		: "r" (START_ADDR));
1691da177e4SLinus Torvalds }
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds /* Must record the SP (it is virtual) on entry, so we can make sure
1721da177e4SLinus Torvalds    not to overwrite it during movement or decompression. */
1731da177e4SLinus Torvalds unsigned long SP_on_entry;
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds /* Calculate the kernel image address based on the end of the BOOTP
1761da177e4SLinus Torvalds    bootstrapper (ie this program).
1771da177e4SLinus Torvalds */
1781da177e4SLinus Torvalds extern char _end;
1791da177e4SLinus Torvalds #define KERNEL_ORIGIN \
1801da177e4SLinus Torvalds 	((((unsigned long)&_end) + 511) & ~511)
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds /* Round address to next higher page boundary. */
1831da177e4SLinus Torvalds #define NEXT_PAGE(a)	(((a) | (PAGE_SIZE - 1)) + 1)
1841da177e4SLinus Torvalds 
1851da177e4SLinus Torvalds #ifdef INITRD_IMAGE_SIZE
1861da177e4SLinus Torvalds # define REAL_INITRD_SIZE INITRD_IMAGE_SIZE
1871da177e4SLinus Torvalds #else
1881da177e4SLinus Torvalds # define REAL_INITRD_SIZE 0
1891da177e4SLinus Torvalds #endif
1901da177e4SLinus Torvalds 
1911da177e4SLinus Torvalds /* Defines from include/asm-alpha/system.h
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 	BOOT_ADDR	Virtual address at which the consoles loads
1941da177e4SLinus Torvalds 			the BOOTP image.
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds 	KERNEL_START    KSEG address at which the kernel is built to run,
1971da177e4SLinus Torvalds 			which includes some initial data pages before the
1981da177e4SLinus Torvalds 			code.
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 	START_ADDR	KSEG address of the entry point of kernel code.
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	ZERO_PGE	KSEG address of page full of zeroes, but
2038f34ed9dStangchunyou 			upon entry to kernel, it can be expected
2041da177e4SLinus Torvalds 			to hold the parameter list and possible
2051da177e4SLinus Torvalds 			INTRD information.
2061da177e4SLinus Torvalds 
2071da177e4SLinus Torvalds    These are used in the local defines below.
2081da177e4SLinus Torvalds */
2091da177e4SLinus Torvalds 
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds /* Virtual addresses for the BOOTP image. Note that this includes the
2121da177e4SLinus Torvalds    bootstrapper code as well as the compressed kernel image, and
2131da177e4SLinus Torvalds    possibly the INITRD image.
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds    Oh, and do NOT forget the STACK, which appears to be placed virtually
2161da177e4SLinus Torvalds    beyond the end of the loaded image.
2171da177e4SLinus Torvalds */
2181da177e4SLinus Torvalds #define V_BOOT_IMAGE_START	BOOT_ADDR
2191da177e4SLinus Torvalds #define V_BOOT_IMAGE_END	SP_on_entry
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds /* Virtual addresses for just the bootstrapper part of the BOOTP image. */
2221da177e4SLinus Torvalds #define V_BOOTSTRAPPER_START	BOOT_ADDR
2231da177e4SLinus Torvalds #define V_BOOTSTRAPPER_END	KERNEL_ORIGIN
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds /* Virtual addresses for just the data part of the BOOTP
2261da177e4SLinus Torvalds    image. This may also include the INITRD image, but always
2271da177e4SLinus Torvalds    includes the STACK.
2281da177e4SLinus Torvalds */
2291da177e4SLinus Torvalds #define V_DATA_START		KERNEL_ORIGIN
2301da177e4SLinus Torvalds #define V_INITRD_START		(KERNEL_ORIGIN + KERNEL_Z_SIZE)
2311da177e4SLinus Torvalds #define V_INTRD_END		(V_INITRD_START + REAL_INITRD_SIZE)
2321da177e4SLinus Torvalds #define V_DATA_END	 	V_BOOT_IMAGE_END
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds /* KSEG addresses for the uncompressed kernel.
2351da177e4SLinus Torvalds 
2361da177e4SLinus Torvalds    Note that the end address includes workspace for the decompression.
2371da177e4SLinus Torvalds    Note also that the DATA_START address is ZERO_PGE, to which we write
2381da177e4SLinus Torvalds    just before jumping to the kernel image at START_ADDR.
2391da177e4SLinus Torvalds  */
2401da177e4SLinus Torvalds #define K_KERNEL_DATA_START	ZERO_PGE
2411da177e4SLinus Torvalds #define K_KERNEL_IMAGE_START	START_ADDR
2421da177e4SLinus Torvalds #define K_KERNEL_IMAGE_END	(START_ADDR + KERNEL_SIZE)
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds /* Define to where we may have to decompress the kernel image, before
2451da177e4SLinus Torvalds    we move it to the final position, in case of overlap. This will be
2461da177e4SLinus Torvalds    above the final position of the kernel.
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds    Regardless of overlap, we move the INITRD image to the end of this
2491da177e4SLinus Torvalds    copy area, because there needs to be a buffer area after the kernel
2501da177e4SLinus Torvalds    for "bootmem" anyway.
2511da177e4SLinus Torvalds */
2521da177e4SLinus Torvalds #define K_COPY_IMAGE_START	NEXT_PAGE(K_KERNEL_IMAGE_END)
2531da177e4SLinus Torvalds /* Reserve one page below INITRD for the new stack. */
2541da177e4SLinus Torvalds #define K_INITRD_START \
2551da177e4SLinus Torvalds     NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
2561da177e4SLinus Torvalds #define K_COPY_IMAGE_END \
2571da177e4SLinus Torvalds     (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
2581da177e4SLinus Torvalds #define K_COPY_IMAGE_SIZE \
2591da177e4SLinus Torvalds     NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds void
start_kernel(void)2621da177e4SLinus Torvalds start_kernel(void)
2631da177e4SLinus Torvalds {
2641da177e4SLinus Torvalds 	int must_move = 0;
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds 	/* Initialize these for the decompression-in-place situation,
2671da177e4SLinus Torvalds 	   which is the smallest amount of work and most likely to
2681da177e4SLinus Torvalds 	   occur when using the normal START_ADDR of the kernel
2691da177e4SLinus Torvalds 	   (currently set to 16MB, to clear all console code.
2701da177e4SLinus Torvalds 	*/
2711da177e4SLinus Torvalds 	unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
2721da177e4SLinus Torvalds 	unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	unsigned long initrd_image_start = K_INITRD_START;
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds 	/*
2771da177e4SLinus Torvalds 	 * Note that this crufty stuff with static and envval
2781da177e4SLinus Torvalds 	 * and envbuf is because:
2791da177e4SLinus Torvalds 	 *
2801da177e4SLinus Torvalds 	 * 1. Frequently, the stack is short, and we don't want to overrun;
2811da177e4SLinus Torvalds 	 * 2. Frequently the stack is where we are going to copy the kernel to;
2821da177e4SLinus Torvalds 	 * 3. A certain SRM console required the GET_ENV output to stack.
2831da177e4SLinus Torvalds 	 *    ??? A comment in the aboot sources indicates that the GET_ENV
2841da177e4SLinus Torvalds 	 *    destination must be quadword aligned.  Might this explain the
2851da177e4SLinus Torvalds 	 *    behaviour, rather than requiring output to the stack, which
2861da177e4SLinus Torvalds 	 *    seems rather far-fetched.
2871da177e4SLinus Torvalds 	 */
2881da177e4SLinus Torvalds 	static long nbytes;
2891da177e4SLinus Torvalds 	static char envval[256] __attribute__((aligned(8)));
2901da177e4SLinus Torvalds 	register unsigned long asm_sp asm("30");
2911da177e4SLinus Torvalds 
2921da177e4SLinus Torvalds 	SP_on_entry = asm_sp;
2931da177e4SLinus Torvalds 
2941da177e4SLinus Torvalds 	srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
2951da177e4SLinus Torvalds 
2961da177e4SLinus Torvalds 	/* Validity check the HWRPB. */
2971da177e4SLinus Torvalds 	if (INIT_HWRPB->pagesize != 8192) {
2981da177e4SLinus Torvalds 		srm_printk("Expected 8kB pages, got %ldkB\n",
2991da177e4SLinus Torvalds 		           INIT_HWRPB->pagesize >> 10);
3001da177e4SLinus Torvalds 		return;
3011da177e4SLinus Torvalds 	}
3021da177e4SLinus Torvalds 	if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
3031da177e4SLinus Torvalds 		srm_printk("Expected vptb at %p, got %p\n",
3041da177e4SLinus Torvalds 			   VPTB, (void *)INIT_HWRPB->vptb);
3051da177e4SLinus Torvalds 		return;
3061da177e4SLinus Torvalds 	}
3071da177e4SLinus Torvalds 
3081da177e4SLinus Torvalds 	/* PALcode (re)initialization. */
3091da177e4SLinus Torvalds 	pal_init();
3101da177e4SLinus Torvalds 
3111da177e4SLinus Torvalds 	/* Get the parameter list from the console environment variable. */
3121da177e4SLinus Torvalds 	nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
3131da177e4SLinus Torvalds 	if (nbytes < 0 || nbytes >= sizeof(envval)) {
3141da177e4SLinus Torvalds 		nbytes = 0;
3151da177e4SLinus Torvalds 	}
3161da177e4SLinus Torvalds 	envval[nbytes] = '\0';
3171da177e4SLinus Torvalds 
3181da177e4SLinus Torvalds #ifdef DEBUG_ADDRESSES
3191da177e4SLinus Torvalds 	srm_printk("START_ADDR 0x%lx\n", START_ADDR);
3201da177e4SLinus Torvalds 	srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
3211da177e4SLinus Torvalds 	srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
3221da177e4SLinus Torvalds 	srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
3231da177e4SLinus Torvalds #endif
3241da177e4SLinus Torvalds 
3251da177e4SLinus Torvalds 	/* Since all the SRM consoles load the BOOTP image at virtual
3261da177e4SLinus Torvalds 	 * 0x20000000, we have to ensure that the physical memory
3271da177e4SLinus Torvalds 	 * pages occupied by that image do NOT overlap the physical
3281da177e4SLinus Torvalds 	 * address range where the kernel wants to be run.  This
3291da177e4SLinus Torvalds 	 * causes real problems when attempting to cdecompress the
3301da177e4SLinus Torvalds 	 * former into the latter... :-(
3311da177e4SLinus Torvalds 	 *
3321da177e4SLinus Torvalds 	 * So, we may have to decompress/move the kernel/INITRD image
3331da177e4SLinus Torvalds 	 * virtual-to-physical someplace else first before moving
3341da177e4SLinus Torvalds 	 * kernel /INITRD to their final resting places... ;-}
3351da177e4SLinus Torvalds 	 *
3361da177e4SLinus Torvalds 	 * Sigh...
3371da177e4SLinus Torvalds 	 */
3381da177e4SLinus Torvalds 
3391da177e4SLinus Torvalds 	/* First, check to see if the range of addresses occupied by
3401da177e4SLinus Torvalds 	   the bootstrapper part of the BOOTP image include any of the
3411da177e4SLinus Torvalds 	   physical pages into which the kernel will be placed for
3421da177e4SLinus Torvalds 	   execution.
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	   We only need check on the final kernel image range, since we
3451da177e4SLinus Torvalds 	   will put the INITRD someplace that we can be sure is not
3461da177e4SLinus Torvalds 	   in conflict.
3471da177e4SLinus Torvalds 	 */
3481da177e4SLinus Torvalds 	if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
3491da177e4SLinus Torvalds 			K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
3501da177e4SLinus Torvalds 	{
3511da177e4SLinus Torvalds 		srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
3521da177e4SLinus Torvalds 		__halt();
3531da177e4SLinus Torvalds 	}
3541da177e4SLinus Torvalds 
3551da177e4SLinus Torvalds 	/* Next, check to see if the range of addresses occupied by
3561da177e4SLinus Torvalds 	   the compressed kernel/INITRD/stack portion of the BOOTP
3571da177e4SLinus Torvalds 	   image include any of the physical pages into which the
3581da177e4SLinus Torvalds 	   decompressed kernel or the INITRD will be placed for
3591da177e4SLinus Torvalds 	   execution.
3601da177e4SLinus Torvalds 	 */
3611da177e4SLinus Torvalds 	if (check_range(V_DATA_START, V_DATA_END,
3621da177e4SLinus Torvalds 			K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
3631da177e4SLinus Torvalds 	{
3641da177e4SLinus Torvalds #ifdef DEBUG_ADDRESSES
3651da177e4SLinus Torvalds 		srm_printk("OVERLAP: cannot decompress in place\n");
3661da177e4SLinus Torvalds #endif
3671da177e4SLinus Torvalds 		uncompressed_image_start = K_COPY_IMAGE_START;
3681da177e4SLinus Torvalds 		uncompressed_image_end = K_COPY_IMAGE_END;
3691da177e4SLinus Torvalds 		must_move = 1;
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds 		/* Finally, check to see if the range of addresses
3721da177e4SLinus Torvalds 		   occupied by the compressed kernel/INITRD part of
3731da177e4SLinus Torvalds 		   the BOOTP image include any of the physical pages
3741da177e4SLinus Torvalds 		   into which that part is to be copied for
3751da177e4SLinus Torvalds 		   decompression.
3761da177e4SLinus Torvalds 		*/
3771da177e4SLinus Torvalds 		while (check_range(V_DATA_START, V_DATA_END,
3781da177e4SLinus Torvalds 				   uncompressed_image_start,
3791da177e4SLinus Torvalds 				   uncompressed_image_end))
3801da177e4SLinus Torvalds 		{
3811da177e4SLinus Torvalds #if 0
3821da177e4SLinus Torvalds 			uncompressed_image_start += K_COPY_IMAGE_SIZE;
3831da177e4SLinus Torvalds 			uncompressed_image_end += K_COPY_IMAGE_SIZE;
3841da177e4SLinus Torvalds 			initrd_image_start += K_COPY_IMAGE_SIZE;
3851da177e4SLinus Torvalds #else
3861da177e4SLinus Torvalds 			/* Keep as close as possible to end of BOOTP image. */
3871da177e4SLinus Torvalds 			uncompressed_image_start += PAGE_SIZE;
3881da177e4SLinus Torvalds 			uncompressed_image_end += PAGE_SIZE;
3891da177e4SLinus Torvalds 			initrd_image_start += PAGE_SIZE;
3901da177e4SLinus Torvalds #endif
3911da177e4SLinus Torvalds 		}
3921da177e4SLinus Torvalds 	}
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds 	srm_printk("Starting to load the kernel with args '%s'\n", envval);
3951da177e4SLinus Torvalds 
3961da177e4SLinus Torvalds #ifdef DEBUG_ADDRESSES
3971da177e4SLinus Torvalds 	srm_printk("Decompressing the kernel...\n"
3981da177e4SLinus Torvalds 		   "...from 0x%lx to 0x%lx size 0x%x\n",
3991da177e4SLinus Torvalds 		   V_DATA_START,
4001da177e4SLinus Torvalds 		   uncompressed_image_start,
4011da177e4SLinus Torvalds 		   KERNEL_SIZE);
4021da177e4SLinus Torvalds #endif
4031da177e4SLinus Torvalds         decompress_kernel((void *)uncompressed_image_start,
4041da177e4SLinus Torvalds 			  (void *)V_DATA_START,
4051da177e4SLinus Torvalds 			  KERNEL_SIZE, KERNEL_Z_SIZE);
4061da177e4SLinus Torvalds 
4071da177e4SLinus Torvalds 	/*
4081da177e4SLinus Torvalds 	 * Now, move things to their final positions, if/as required.
4091da177e4SLinus Torvalds 	 */
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds #ifdef INITRD_IMAGE_SIZE
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds 	/* First, we always move the INITRD image, if present. */
4141da177e4SLinus Torvalds #ifdef DEBUG_ADDRESSES
4151da177e4SLinus Torvalds 	srm_printk("Moving the INITRD image...\n"
4161da177e4SLinus Torvalds 		   " from 0x%lx to 0x%lx size 0x%x\n",
4171da177e4SLinus Torvalds 		   V_INITRD_START,
4181da177e4SLinus Torvalds 		   initrd_image_start,
4191da177e4SLinus Torvalds 		   INITRD_IMAGE_SIZE);
4201da177e4SLinus Torvalds #endif
4211da177e4SLinus Torvalds 	memcpy((void *)initrd_image_start, (void *)V_INITRD_START,
4221da177e4SLinus Torvalds 	       INITRD_IMAGE_SIZE);
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds #endif /* INITRD_IMAGE_SIZE */
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds 	/* Next, we may have to move the uncompressed kernel to the
4271da177e4SLinus Torvalds 	   final destination.
4281da177e4SLinus Torvalds 	 */
4291da177e4SLinus Torvalds 	if (must_move) {
4301da177e4SLinus Torvalds #ifdef DEBUG_ADDRESSES
4311da177e4SLinus Torvalds 		srm_printk("Moving the uncompressed kernel...\n"
4321da177e4SLinus Torvalds 			   "...from 0x%lx to 0x%lx size 0x%x\n",
4331da177e4SLinus Torvalds 			   uncompressed_image_start,
4341da177e4SLinus Torvalds 			   K_KERNEL_IMAGE_START,
4351da177e4SLinus Torvalds 			   (unsigned)KERNEL_SIZE);
4361da177e4SLinus Torvalds #endif
4371da177e4SLinus Torvalds 		/*
4381da177e4SLinus Torvalds 		 * Move the stack to a safe place to ensure it won't be
4391da177e4SLinus Torvalds 		 * overwritten by kernel image.
4401da177e4SLinus Torvalds 		 */
4411da177e4SLinus Torvalds 		move_stack(initrd_image_start - PAGE_SIZE);
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds 		memcpy((void *)K_KERNEL_IMAGE_START,
4441da177e4SLinus Torvalds 		       (void *)uncompressed_image_start, KERNEL_SIZE);
4451da177e4SLinus Torvalds 	}
4461da177e4SLinus Torvalds 
4471da177e4SLinus Torvalds 	/* Clear the zero page, then move the argument list in. */
4481da177e4SLinus Torvalds #ifdef DEBUG_LAST_STEPS
4491da177e4SLinus Torvalds 	srm_printk("Preparing ZERO_PGE...\n");
4501da177e4SLinus Torvalds #endif
4511da177e4SLinus Torvalds 	memset((char*)ZERO_PGE, 0, PAGE_SIZE);
4521da177e4SLinus Torvalds 	strcpy((char*)ZERO_PGE, envval);
4531da177e4SLinus Torvalds 
4541da177e4SLinus Torvalds #ifdef INITRD_IMAGE_SIZE
4551da177e4SLinus Torvalds 
4561da177e4SLinus Torvalds #ifdef DEBUG_LAST_STEPS
4571da177e4SLinus Torvalds 	srm_printk("Preparing INITRD info...\n");
4581da177e4SLinus Torvalds #endif
4591da177e4SLinus Torvalds 	/* Finally, set the INITRD paramenters for the kernel. */
4601da177e4SLinus Torvalds 	((long *)(ZERO_PGE+256))[0] = initrd_image_start;
4611da177e4SLinus Torvalds 	((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
4621da177e4SLinus Torvalds 
4631da177e4SLinus Torvalds #endif /* INITRD_IMAGE_SIZE */
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds #ifdef DEBUG_LAST_STEPS
4661da177e4SLinus Torvalds 	srm_printk("Doing 'runkernel()'...\n");
4671da177e4SLinus Torvalds #endif
4681da177e4SLinus Torvalds 	runkernel();
4691da177e4SLinus Torvalds }
470eb2bce7fSIvan Kokshaysky 
471eb2bce7fSIvan Kokshaysky  /* dummy function, should never be called. */
__kmalloc(size_t size,gfp_t flags)472eb2bce7fSIvan Kokshaysky void *__kmalloc(size_t size, gfp_t flags)
473eb2bce7fSIvan Kokshaysky {
474eb2bce7fSIvan Kokshaysky 	return (void *)NULL;
475eb2bce7fSIvan Kokshaysky }
476