summaryrefslogtreecommitdiffstats
path: root/arch/alpha/boot/bootp.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-03 17:49:53 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-03 17:49:53 +0000
commiteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (patch)
tree5746fea1605ff013be9b78a1556aaad7615d664a /arch/alpha/boot/bootp.c
parent80ea5b1e15398277650e1197957053b5a71c08bc (diff)
Merge with Linux 2.1.131 plus some more MIPS goodies.
Diffstat (limited to 'arch/alpha/boot/bootp.c')
-rw-r--r--arch/alpha/boot/bootp.c216
1 files changed, 82 insertions, 134 deletions
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
index 2dc8b6a4d..34645a643 100644
--- a/arch/alpha/boot/bootp.c
+++ b/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 @@ struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
* 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 @@ void pal_init(void)
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;
-
- /* update checksum: */
- sum = 0;
- for (l = (unsigned long *) &hwrpb;
- l < (unsigned long *) &hwrpb.chksum;
- ++l)
- sum += *l;
- hwrpb.chksum = sum;
+ percpu = (struct percpu_struct *)
+ (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
+ rev = percpu->pal_revision = percpu->palcode_avail[2];
- 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 @@ extern char _end;
#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();
}