| 
					
				 | 
			
			
				@@ -0,0 +1,157 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * arch/alpha/boot/bootpz.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright (C) 1997 Jay Estabrook 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This file is used for creating a compressed BOOTP file for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Linux/AXP kernel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * based significantly on the arch/alpha/boot/main.c of Linus Torvalds 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * and the decompression code from MILO. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/kernel.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/slab.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <generated/utsrelease.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/mm.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/console.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/hwrpb.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/pgtable.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/io.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdarg.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "kzsize.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* FIXME FIXME FIXME */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define MALLOC_AREA_SIZE 0x200000 /* 2MB for now */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* FIXME FIXME FIXME */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  WARNING NOTE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  It is very possible that turning on additional messages may cause 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  kernel image corruption due to stack usage to do the printing. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#undef DEBUG_CHECK_RANGE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#undef DEBUG_ADDRESSES 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#undef DEBUG_LAST_STEPS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern unsigned long switch_to_osf_pal(unsigned long nr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long *vptb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern int decompress_kernel(void* destination, void *source, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			     size_t ksize, size_t kzsize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extern void move_stack(unsigned long new_stack); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct hwrpb_struct *hwrpb = INIT_HWRPB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct pcb_struct pcb_va[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Find a physical address of a virtual object.. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This is easy using the virtual page table address. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define VPTB	((unsigned long *) 0x200000000) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static inline unsigned long 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+find_pa(unsigned long address) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	result = VPTB[address >> 13]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	result >>= 32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	result <<= 13; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	result |= address & 0x1fff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+check_range(unsigned long vstart, unsigned long vend, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    unsigned long kstart, unsigned long kend) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long vaddr, kaddr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef DEBUG_CHECK_RANGE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		   vstart, vend, kstart, kend); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* do some range checking for detecting an overlap... */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		kaddr = (find_pa(vaddr) | PAGE_OFFSET); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (kaddr >= kstart && kaddr <= kend) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef DEBUG_CHECK_RANGE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				   " [0x%lx:0x%lx]\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				   vaddr, kaddr, kstart, kend); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This function moves into OSF/1 pal-code, and has a temporary 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * PCB for that. The kernel proper should replace this PCB with 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * the real one as soon as possible. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * The page table muckery in here depends on the fact that the boot 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * code has the L1 page table identity-map itself in the second PTE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * in the L1 page table. Thus the L1-page is virtually addressable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * itself (through three levels) at virtual address 0x200802000. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define L1	((unsigned long *) 0x200802000) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pal_init(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long i, rev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct percpu_struct * percpu; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct pcb_struct * pcb_pa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Create the dummy PCB.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->ksp = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->usp = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->ptbr = L1[1] >> 32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->asn = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->pcc = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->unique = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->flags = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->res1 = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_va->res2 = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * a0 = 2 (OSF) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * a1 = return address, but we give the asm the vaddr of the PCB 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * a2 = physical addr of PCB 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * a3 = new virtual page table pointer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * a4 = KSP (but the asm sets it) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	srm_printk("Switching to OSF PAL-code... "); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		srm_printk("failed, code %ld\n", i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		__halt(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	percpu = (struct percpu_struct *) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	rev = percpu->pal_revision = percpu->palcode_avail[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	srm_printk("OK (rev %lx)\n", rev); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	tbia(); /* do it directly in case we are SMP */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 |