diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-03 17:49:53 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-03 17:49:53 +0000 |
commit | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (patch) | |
tree | 5746fea1605ff013be9b78a1556aaad7615d664a /arch/alpha/boot/bootp.c | |
parent | 80ea5b1e15398277650e1197957053b5a71c08bc (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.c | 216 |
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(); } |