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 #include <linux/mm.h>
  12 
  13 #include <asm/system.h>
  14 #include <asm/console.h>
  15 #include <asm/hwrpb.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, sum;
  79         unsigned long *L1, *l;
  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; /* (1<<33 | 1<<23 | 1<<13) */
  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 
 117         hwrpb.vptb = new_vptb;
 118 
 119         /* update checksum: */
 120         sum = 0;
 121         for (l = (unsigned long *) &hwrpb; l < (unsigned long *) &hwrpb.chksum; ++l)
 122                 sum += *l;
 123         hwrpb.chksum = sum;
 124 
 125         printk("Ok (rev %lx)\n", rev);
 126         /* remove the old virtual page-table mapping */
 127         L1[1] = 0;
 128         invalidate_all();
 129 }
 130 
 131 extern int _end;
 132 
 133 static inline long openboot(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135         char bootdev[256];
 136         long result;
 137 
 138         result = dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
 139         if (result < 0)
 140                 return result;
 141         return dispatch(CCB_OPEN, bootdev, result & 255);
 142 }
 143 
 144 static inline long close(long dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         return dispatch(CCB_CLOSE, dev);
 147 }
 148 
 149 static inline long load(long dev, unsigned long addr, unsigned long count)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         char bootfile[256];
 152         long result;
 153 
 154         result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
 155         if (result < 0)
 156                 return result;
 157         result &= 255;
 158         bootfile[result] = '\0';
 159         if (result)
 160                 printk("Boot file specification (%s) not implemented\n", bootfile);
 161         return dispatch(CCB_READ, dev, count, addr, BOOT_SIZE/512 + 1);
 162 }
 163 
 164 /*
 165  * Start the kernel.
 166  */
 167 static void runkernel(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         __asm__ __volatile__(
 170                 "bis %1,%1,$30\n\t"
 171                 "bis %0,%0,$26\n\t"
 172                 "ret ($26)"
 173                 : /* no outputs: it doesn't even return */
 174                 : "r" (START_ADDR),
 175                   "r" (PAGE_SIZE + INIT_STACK));
 176 }
 177 
 178 void start_kernel(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180         long i;
 181         long dev;
 182         int nbytes;
 183         char envval[256];
 184 
 185         printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
 186         if (hwrpb.pagesize != 8192) {
 187                 printk("Expected 8kB pages, got %ldkB\n", hwrpb.pagesize >> 10);
 188                 return;
 189         }
 190         pal_init();
 191         dev = openboot();
 192         if (dev < 0) {
 193                 printk("Unable to open boot device: %016lx\n", dev);
 194                 return;
 195         }
 196         dev &= 0xffffffff;
 197         printk("Loading vmlinux ...");
 198         i = load(dev, START_ADDR, START_SIZE);
 199         close(dev);
 200         if (i != START_SIZE) {
 201                 printk("Failed (%lx)\n", i);
 202                 return;
 203         }
 204 
 205         nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
 206                           envval, sizeof(envval));
 207         if (nbytes > 0) {
 208                 envval[nbytes] = '\0';
 209                 strcpy((char*)ZERO_PGE, envval);
 210         }
 211 
 212         printk(" Ok\nNow booting the kernel\n");
 213         runkernel();
 214         for (i = 0 ; i < 0x100000000 ; i++)
 215                 /* nothing */;
 216         halt();
 217 }

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