root/arch/alpha/boot/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

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

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * arch/alpha/boot/main.c
   4  *
   5  * Copyright (C) 1994, 1995 Linus Torvalds
   6  *
   7  * This file is the bootloader for the Linux/AXP kernel
   8  */
   9 #include <linux/kernel.h>
  10 #include <linux/slab.h>
  11 #include <linux/string.h>
  12 #include <generated/utsrelease.h>
  13 #include <linux/mm.h>
  14 
  15 #include <asm/console.h>
  16 #include <asm/hwrpb.h>
  17 #include <asm/pgtable.h>
  18 
  19 #include <stdarg.h>
  20 
  21 #include "ksize.h"
  22 
  23 extern unsigned long switch_to_osf_pal(unsigned long nr,
  24         struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
  25         unsigned long *vptb);
  26 struct hwrpb_struct *hwrpb = INIT_HWRPB;
  27 static struct pcb_struct pcb_va[1];
  28 
  29 /*
  30  * Find a physical address of a virtual object..
  31  *
  32  * This is easy using the virtual page table address.
  33  */
  34 
  35 static inline void *
  36 find_pa(unsigned long *vptb, void *ptr)
  37 {
  38         unsigned long address = (unsigned long) ptr;
  39         unsigned long result;
  40 
  41         result = vptb[address >> 13];
  42         result >>= 32;
  43         result <<= 13;
  44         result |= address & 0x1fff;
  45         return (void *) result;
  46 }       
  47 
  48 /*
  49  * This function moves into OSF/1 pal-code, and has a temporary
  50  * PCB for that. The kernel proper should replace this PCB with
  51  * the real one as soon as possible.
  52  *
  53  * The page table muckery in here depends on the fact that the boot
  54  * code has the L1 page table identity-map itself in the second PTE
  55  * in the L1 page table. Thus the L1-page is virtually addressable
  56  * itself (through three levels) at virtual address 0x200802000.
  57  */
  58 
  59 #define VPTB    ((unsigned long *) 0x200000000)
  60 #define L1      ((unsigned long *) 0x200802000)
  61 
  62 void
  63 pal_init(void)
  64 {
  65         unsigned long i, rev;
  66         struct percpu_struct * percpu;
  67         struct pcb_struct * pcb_pa;
  68 
  69         /* Create the dummy PCB.  */
  70         pcb_va->ksp = 0;
  71         pcb_va->usp = 0;
  72         pcb_va->ptbr = L1[1] >> 32;
  73         pcb_va->asn = 0;
  74         pcb_va->pcc = 0;
  75         pcb_va->unique = 0;
  76         pcb_va->flags = 1;
  77         pcb_va->res1 = 0;
  78         pcb_va->res2 = 0;
  79         pcb_pa = find_pa(VPTB, pcb_va);
  80 
  81         /*
  82          * a0 = 2 (OSF)
  83          * a1 = return address, but we give the asm the vaddr of the PCB
  84          * a2 = physical addr of PCB
  85          * a3 = new virtual page table pointer
  86          * a4 = KSP (but the asm sets it)
  87          */
  88         srm_printk("Switching to OSF PAL-code .. ");
  89 
  90         i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
  91         if (i) {
  92                 srm_printk("failed, code %ld\n", i);
  93                 __halt();
  94         }
  95 
  96         percpu = (struct percpu_struct *)
  97                 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
  98         rev = percpu->pal_revision = percpu->palcode_avail[2];
  99 
 100         srm_printk("Ok (rev %lx)\n", rev);
 101 
 102         tbia(); /* do it directly in case we are SMP */
 103 }
 104 
 105 static inline long openboot(void)
 106 {
 107         char bootdev[256];
 108         long result;
 109 
 110         result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
 111         if (result < 0)
 112                 return result;
 113         return callback_open(bootdev, result & 255);
 114 }
 115 
 116 static inline long close(long dev)
 117 {
 118         return callback_close(dev);
 119 }
 120 
 121 static inline long load(long dev, unsigned long addr, unsigned long count)
 122 {
 123         char bootfile[256];
 124         extern char _end;
 125         long result, boot_size = &_end - (char *) BOOT_ADDR;
 126 
 127         result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
 128         if (result < 0)
 129                 return result;
 130         result &= 255;
 131         bootfile[result] = '\0';
 132         if (result)
 133                 srm_printk("Boot file specification (%s) not implemented\n",
 134                        bootfile);
 135         return callback_read(dev, count, (void *)addr, boot_size/512 + 1);
 136 }
 137 
 138 /*
 139  * Start the kernel.
 140  */
 141 static void runkernel(void)
 142 {
 143         __asm__ __volatile__(
 144                 "bis %1,%1,$30\n\t"
 145                 "bis %0,%0,$26\n\t"
 146                 "ret ($26)"
 147                 : /* no outputs: it doesn't even return */
 148                 : "r" (START_ADDR),
 149                   "r" (PAGE_SIZE + INIT_STACK));
 150 }
 151 
 152 void start_kernel(void)
 153 {
 154         long i;
 155         long dev;
 156         int nbytes;
 157         char envval[256];
 158 
 159         srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
 160         if (INIT_HWRPB->pagesize != 8192) {
 161                 srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10);
 162                 return;
 163         }
 164         pal_init();
 165         dev = openboot();
 166         if (dev < 0) {
 167                 srm_printk("Unable to open boot device: %016lx\n", dev);
 168                 return;
 169         }
 170         dev &= 0xffffffff;
 171         srm_printk("Loading vmlinux ...");
 172         i = load(dev, START_ADDR, KERNEL_SIZE);
 173         close(dev);
 174         if (i != KERNEL_SIZE) {
 175                 srm_printk("Failed (%lx)\n", i);
 176                 return;
 177         }
 178 
 179         nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
 180         if (nbytes < 0) {
 181                 nbytes = 0;
 182         }
 183         envval[nbytes] = '\0';
 184         strcpy((char*)ZERO_PGE, envval);
 185 
 186         srm_printk(" Ok\nNow booting the kernel\n");
 187         runkernel();
 188         for (i = 0 ; i < 0x100000000 ; i++)
 189                 /* nothing */;
 190         __halt();
 191 }

/* [<][>][^][v][top][bottom][index][help] */