patch-2.1.126 linux/arch/alpha/boot/bootp.c

Next file: linux/arch/alpha/boot/head.S
Previous file: linux/arch/alpha/boot/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.125/linux/arch/alpha/boot/bootp.c linux/arch/alpha/boot/bootp.c
@@ -22,74 +22,30 @@
 
 #include "ksize.h"
 
-extern int vsprintf(char *, const char *, va_list);
 extern unsigned long switch_to_osf_pal(unsigned long nr,
 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
-	unsigned long vptb, unsigned long *kstk);
+	unsigned long *vptb);
 
-extern long dispatch(long code, ...);
-
-static void
-puts(const char *str, int len)
-{
-	long written;
-
-	while (len > 0) {
-		written = dispatch(CCB_PUTS, 0, str, len);
-		if (written < 0)
-			break;
-		len -= (unsigned int) written;
-		str += (unsigned int) written;
-	}
-}
-
-int printk(const char * fmt, ...)
-{
-	va_list args;
-	int i, j, remaining, num_nl;
-	static char buf[1024];
-
-	va_start(args, fmt);
-	i = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	/* expand \n into \r\n: */
-
-	num_nl = 0;
-	for (j = 0; j < i; ++j) {
-	    if (buf[j] == '\n')
-	    	++num_nl;
-	}
-	remaining = i + num_nl;
-	for (j = i - 1; j >= 0; --j) {
-	    buf[j + num_nl] = buf[j];
-	    if (buf[j] == '\n') {
-	    	--num_nl;
-		buf[j + num_nl] = '\r';
-	    }
-	}
-
-	puts(buf, remaining);
-	return i;
-}
-
-#define hwrpb (*INIT_HWRPB)
+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.
  */
-struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
+
+static inline void *
+find_pa(unsigned long *vptb, void *ptr)
 {
-	unsigned long address = (unsigned long) pcb;
+	unsigned long address = (unsigned long) ptr;
 	unsigned long result;
 
 	result = vptb[address >> 13];
 	result >>= 32;
 	result <<= 13;
 	result |= address & 0x1fff;
-	return (struct pcb_struct *) result;
+	return (void *) result;
 }	
 
 /*
@@ -101,31 +57,19 @@
  * 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.
- *
- * As we don't want it there anyway, we also move the L1 self-map
- * up as high as we can, so that the last entry in the L1 page table
- * maps the page tables.
- *
- * As a result, the OSF/1 pal-code will instead use a virtual page table
- * map located at 0xffffffe00000000.
  */
-#define pcb_va ((struct pcb_struct *) 0x20000000)
-#define old_vptb (0x0000000200000000UL)
-#define new_vptb (0xfffffffe00000000UL)
-void pal_init(void)
+
+#define VPTB	((unsigned long *) 0x200000000)
+#define L1	((unsigned long *) 0x200802000)
+
+void
+pal_init(void)
 {
-	unsigned long i, rev, sum;
-	unsigned long *L1, *l;
+	unsigned long i, rev;
 	struct percpu_struct * percpu;
 	struct pcb_struct * pcb_pa;
 
-	/* Find the level 1 page table and duplicate it in high memory */
-	L1 = (unsigned long *) 0x200802000UL; /* (1<<33 | 1<<23 | 1<<13) */
-	L1[1023] = L1[1];
-
-	percpu = (struct percpu_struct *)
-			(hwrpb.processor_offset + (unsigned long) &hwrpb),
-		
+	/* Create the dummy PCB.  */
 	pcb_va->ksp = 0;
 	pcb_va->usp = 0;
 	pcb_va->ptbr = L1[1] >> 32;
@@ -133,58 +77,45 @@
 	pcb_va->pcc = 0;
 	pcb_va->unique = 0;
 	pcb_va->flags = 1;
-	pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va);
-	printk("Switching to OSF PAL-code .. ");
+	pcb_va->res1 = 0;
+	pcb_va->res2 = 0;
+	pcb_pa = find_pa(VPTB, 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 we give it 0, asm sets it)
+	 * a4 = KSP (but the asm sets it)
 	 */
-	i = switch_to_osf_pal(
-		2,
-		pcb_va,
-		pcb_pa,
-		new_vptb,
-		0);
+	srm_printk("Switching to OSF PAL-code .. ");
+
+	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
 	if (i) {
-		printk("failed, code %ld\n", i);
+		srm_printk("failed, code %ld\n", i);
 		halt();
 	}
-	rev = percpu->pal_revision = percpu->palcode_avail[2];
 
-	hwrpb.vptb = new_vptb;
+	percpu = (struct percpu_struct *)
+		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
+	rev = percpu->pal_revision = percpu->palcode_avail[2];
 
-	/* update checksum: */
-	sum = 0;
-	for (l = (unsigned long *) &hwrpb;
-	     l < (unsigned long *) &hwrpb.chksum;
-	     ++l)
-		sum += *l;
-	hwrpb.chksum = sum;
-
-	printk("Ok (rev %lx)\n", rev);
-	/* remove the old virtual page-table mapping */
-	L1[1] = 0;
+	srm_printk("Ok (rev %lx)\n", rev);
 
 	tbia(); /* do it directly in case we are SMP */
 }
 
-static inline long load(unsigned long dst,
-			unsigned long src,
-			unsigned long count)
+static inline void
+load(unsigned long dst, unsigned long src, unsigned long count)
 {
-	extern void * memcpy(void *, const void *, size_t);
-
 	memcpy((void *)dst, (void *)src, count);
-	return count;
 }
 
 /*
  * Start the kernel.
  */
-static void runkernel(void)
+static inline void
+runkernel(void)
 {
 	__asm__ __volatile__(
 		"bis %1,%1,$30\n\t"
@@ -199,65 +130,82 @@
 #define KERNEL_ORIGIN \
 	((((unsigned long)&_end) + 511) & ~511)
 
-void start_kernel(void)
+void
+start_kernel(void)
 {
-	static long i;
-	static int nbytes;
 	/*
-	 * note that this crufty stuff with static and envval and envbuf
-	 * is because:
+	 * Note that this crufty stuff with static and envval
+	 * and envbuf is because:
 	 *
-	 * 1. frequently, the stack is is short, and we don't want to overrun;
-	 * 2. frequently the stack is where we are going to copy the kernel to;
-	 * 3. a certain SRM console required the GET_ENV output to stack.
+	 * 1. Frequently, the stack is short, and we don't want to overrun;
+	 * 2. Frequently the stack is where we are going to copy the kernel to;
+	 * 3. A certain SRM console required the GET_ENV output to stack.
+	 *    ??? A comment in the aboot sources indicates that the GET_ENV
+	 *    destination must be quadword aligned.  Might this explain the
+	 *    behaviour, rather than requiring output to the stack, which
+	 *    seems rather far-fetched.
 	 */
-	static char envval[256];
-	char envbuf[256];
+	static long nbytes;
+	static char envval[256] __attribute__((aligned(8)));
+#ifdef INITRD_SIZE
+	static unsigned long initrd_start;
+#endif
 
-	printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
-	if (hwrpb.pagesize != 8192) {
-		printk("Expected 8kB pages, got %ldkB\n",
-		       hwrpb.pagesize >> 10);
+	srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
+	if (INIT_HWRPB->pagesize != 8192) {
+		srm_printk("Expected 8kB pages, got %ldkB\n",
+		           INIT_HWRPB->pagesize >> 10);
+		return;
+	}
+	if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
+		srm_printk("Expected vptb at %p, got %p\n",
+			   VPTB, (void *)INIT_HWRPB->vptb);
 		return;
 	}
 	pal_init();
 
-	nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
-			  envbuf, sizeof(envbuf));
-	if (nbytes < 0 || nbytes >= sizeof(envbuf)) {
+#ifdef INITRD_SIZE
+	/* The initrd must be page-aligned.  See below for the 
+	   cause of the magic number 5.  */
+	initrd_start = ((START_ADDR + 5*KERNEL_SIZE) | (PAGE_SIZE-1)) + 1;
+	srm_printk("Initrd positioned at %#lx\n", initrd_start);
+#endif
+
+	nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
+			      envval, sizeof(envval));
+	if (nbytes < 0 || nbytes >= sizeof(envval)) {
 		nbytes = 0;
 	}
-	envbuf[nbytes] = '\0';
-	memcpy(envval, envbuf, nbytes+1);
-	printk("Loading the kernel...'%s'\n", envval);
+	envval[nbytes] = '\0';
+	srm_printk("Loading the kernel...'%s'\n", envval);
 
 	/* NOTE: *no* callbacks or printouts from here on out!!! */
 
-#if 1
 	/*
-	 * this is a hack, as some consoles seem to get virtual 20000000
+	 * This is a hack, as some consoles seem to get virtual 20000000
 	 * (ie where the SRM console puts the kernel bootp image) memory
 	 * overlapping physical 310000 memory, which causes real problems
 	 * when attempting to copy the former to the latter... :-(
 	 *
-	 * so, we first move the kernel virtual-to-physical way above where
+	 * So, we first move the kernel virtual-to-physical way above where
 	 * we physically want the kernel to end up, then copy it from there
 	 * to its final resting place... ;-}
 	 *
-	 * sigh...
+	 * Sigh...
 	 */
 
-        i = load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
-        i = load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
-#else
-	i = load(START_ADDR, KERNEL_ORIGIN, KERNEL_SIZE);
+#ifdef INITRD_SIZE
+	load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_SIZE);
 #endif
+        load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
+        load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
 
+	memset((char*)ZERO_PAGE, 0, PAGE_SIZE);
 	strcpy((char*)ZERO_PAGE, envval);
+#ifdef INITRD_SIZE
+	((long *)(ZERO_PAGE+256))[0] = initrd_start;
+	((long *)(ZERO_PAGE+256))[1] = INITRD_SIZE;
+#endif
 
 	runkernel();
-
-	for (i = 0 ; i < 0x100000000 ; i++)
-		/* nothing */;
-	halt();
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov