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

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