root/arch/alpha/boot/main.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. printk
  2. find_pa
  3. pal_init
  4. openboot
  5. close
  6. load
  7. runkernel
  8. start_kernel

   1 /*
   2  * arch/alpha/boot/main.c
   3  *
   4  * Copyright (C) 1994, 1995 Linus Torvalds
   5  *
   6  * This file is the bootloader for the Linux/AXP kernel
   7  */
   8 #include <linux/kernel.h>
   9 #include <linux/string.h>
  10 #include <linux/version.h>
  11 
  12 #include <asm/system.h>
  13 #include <asm/console.h>
  14 #include <asm/hwrpb.h>
  15 #include <asm/page.h>
  16 
  17 #include <stdarg.h>
  18 
  19 extern int vsprintf(char *, const char *, va_list);
  20 extern unsigned long switch_to_osf_pal(unsigned long nr,
  21         struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
  22         unsigned long vptb, unsigned long *kstk);
  23 
  24 int printk(const char * fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26         va_list args;
  27         int i;
  28         static char buf[1024];
  29 
  30         va_start(args, fmt);
  31         i = vsprintf(buf, fmt, args);
  32         va_end(args);
  33         puts(buf,i);
  34         return i;
  35 }
  36 
  37 #define hwrpb (*INIT_HWRPB)
  38 
  39 /*
  40  * Find a physical address of a virtual object..
  41  *
  42  * This is easy using the virtual page table address.
  43  */
  44 struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46         unsigned long address = (unsigned long) pcb;
  47         unsigned long result;
  48 
  49         result = vptb[address >> 13];
  50         result >>= 32;
  51         result <<= 13;
  52         result |= address & 0x1fff;
  53         return (struct pcb_struct *) result;
  54 }       
  55 
  56 /*
  57  * This function moves into OSF/1 pal-code, and has a temporary
  58  * PCB for that. The kernel proper should replace this PCB with
  59  * the real one as soon as possible.
  60  *
  61  * The page table muckery in here depends on the fact that the boot
  62  * code has the L1 page table identity-map itself in the second PTE
  63  * in the L1 page table. Thus the L1-page is virtually addressable
  64  * itself (through three levels) at virtual address 0x200802000.
  65  *
  66  * As we don't want it there anyway, we also move the L1 self-map
  67  * up as high as we can, so that the last entry in the L1 page table
  68  * maps the page tables.
  69  *
  70  * As a result, the OSF/1 pal-code will instead use a virtual page table
  71  * map located at 0xffffffe00000000.
  72  */
  73 #define pcb_va ((struct pcb_struct *) 0x20000000)
  74 #define old_vptb (0x0000000200000000UL)
  75 #define new_vptb (0xfffffffe00000000UL)
  76 void pal_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  77 {
  78         unsigned long i, rev;
  79         unsigned long *L1;
  80         struct percpu_struct * percpu;
  81         struct pcb_struct * pcb_pa;
  82 
  83         /* Find the level 1 page table and duplicate it in high memory */
  84         L1 = (unsigned long *) 0x200802000UL;
  85         L1[1023] = L1[1];
  86 
  87         percpu = (struct percpu_struct *) (hwrpb.processor_offset + (unsigned long) &hwrpb),
  88                 
  89         pcb_va->ksp = 0;
  90         pcb_va->usp = 0;
  91         pcb_va->ptbr = L1[1] >> 32;
  92         pcb_va->asn = 0;
  93         pcb_va->pcc = 0;
  94         pcb_va->unique = 0;
  95         pcb_va->flags = 1;
  96         pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va);
  97         printk("Switching to OSF PAL-code .. ");
  98         /*
  99          * a0 = 2 (OSF)
 100          * a1 = return address, but we give the asm the virtual addr of the PCB
 101          * a2 = physical addr of PCB
 102          * a3 = new virtual page table pointer
 103          * a4 = KSP (but we give it 0, asm sets it)
 104          */
 105         i = switch_to_osf_pal(
 106                 2,
 107                 pcb_va,
 108                 pcb_pa,
 109                 new_vptb,
 110                 0);
 111         if (i) {
 112                 printk("failed, code %ld\n", i);
 113                 halt();
 114         }
 115         rev = percpu->pal_revision = percpu->palcode_avail[2];
 116         hwrpb.vptb = new_vptb;
 117         printk("Ok (rev %lx)\n", rev);
 118         /* remove the old virtual page-table mapping */
 119         L1[1] = 0;
 120         invalidate_all();
 121 }
 122 
 123 extern int _end;
 124 
 125 static inline long openboot(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         char bootdev[256];
 128         long result;
 129 
 130         result = dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
 131         if (result < 0)
 132                 return result;
 133         return dispatch(CCB_OPEN, bootdev, result & 255);
 134 }
 135 
 136 static inline long close(long dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         return dispatch(CCB_CLOSE, dev);
 139 }
 140 
 141 static inline long load(long dev, unsigned long addr, unsigned long count)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         char bootfile[256];
 144         long result;
 145 
 146         result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
 147         if (result < 0)
 148                 return result;
 149         result &= 255;
 150         bootfile[result] = '\0';
 151         if (result)
 152                 printk("Boot file specification (%s) not implemented\n", bootfile);
 153         return dispatch(CCB_READ, dev, count, addr, BOOT_SIZE/512 + 1);
 154 }
 155 
 156 static void runkernel(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         struct pcb_struct * init_pcb = (struct pcb_struct *) INIT_PCB;
 159 
 160         *init_pcb = *pcb_va;
 161         init_pcb->ksp = PAGE_SIZE + INIT_STACK;
 162         
 163         __asm__ __volatile__(
 164                 "bis %0,%0,$26\n\t"
 165                 "bis %1,%1,$16\n\t"
 166                 ".long %2\n\t"
 167                 "ret ($26)"
 168                 : /* no outputs: it doesn't even return */
 169                 : "r" (START_ADDR),
 170                   "r" (init_pcb),
 171                   "i" (PAL_swpctx)
 172                 : "$16","$26");
 173 }
 174 
 175 void start_kernel(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177         long i;
 178         long dev;
 179 
 180         printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
 181         if (hwrpb.pagesize != 8192) {
 182                 printk("Expected 8kB pages, got %ldkB\n", hwrpb.pagesize >> 10);
 183                 return;
 184         }
 185         pal_init();
 186         dev = openboot();
 187         if (dev < 0) {
 188                 printk("Unable to open boot device: %016lx\n", dev);
 189                 return;
 190         }
 191         dev &= 0xffffffff;
 192         printk("Loading vmlinux ...");
 193         i = load(dev, START_ADDR, START_SIZE);
 194         close(dev);
 195         if (i != START_SIZE) {
 196                 printk("Failed (%lx)\n", i);
 197                 return;
 198         }
 199         printk(" Ok\nNow booting the kernel\n");
 200         runkernel();
 201         for (i = 0 ; i < 0x100000000 ; i++)
 202                 /* nothing */;
 203         halt();
 204 }

/* [previous][next][first][last][top][bottom][index][help] */