0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/slab.h>
0011 #include <linux/string.h>
0012 #include <generated/utsrelease.h>
0013 #include <linux/mm.h>
0014
0015 #include <asm/console.h>
0016 #include <asm/hwrpb.h>
0017
0018 #include <stdarg.h>
0019
0020 #include "ksize.h"
0021
0022 extern unsigned long switch_to_osf_pal(unsigned long nr,
0023 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
0024 unsigned long *vptb);
0025 struct hwrpb_struct *hwrpb = INIT_HWRPB;
0026 static struct pcb_struct pcb_va[1];
0027
0028
0029
0030
0031
0032
0033
0034 static inline void *
0035 find_pa(unsigned long *vptb, void *ptr)
0036 {
0037 unsigned long address = (unsigned long) ptr;
0038 unsigned long result;
0039
0040 result = vptb[address >> 13];
0041 result >>= 32;
0042 result <<= 13;
0043 result |= address & 0x1fff;
0044 return (void *) result;
0045 }
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 #define VPTB ((unsigned long *) 0x200000000)
0059 #define L1 ((unsigned long *) 0x200802000)
0060
0061 void
0062 pal_init(void)
0063 {
0064 unsigned long i, rev;
0065 struct percpu_struct * percpu;
0066 struct pcb_struct * pcb_pa;
0067
0068
0069 pcb_va->ksp = 0;
0070 pcb_va->usp = 0;
0071 pcb_va->ptbr = L1[1] >> 32;
0072 pcb_va->asn = 0;
0073 pcb_va->pcc = 0;
0074 pcb_va->unique = 0;
0075 pcb_va->flags = 1;
0076 pcb_va->res1 = 0;
0077 pcb_va->res2 = 0;
0078 pcb_pa = find_pa(VPTB, pcb_va);
0079
0080
0081
0082
0083
0084
0085
0086
0087 srm_printk("Switching to OSF PAL-code .. ");
0088
0089 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
0090 if (i) {
0091 srm_printk("failed, code %ld\n", i);
0092 __halt();
0093 }
0094
0095 percpu = (struct percpu_struct *)
0096 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
0097 rev = percpu->pal_revision = percpu->palcode_avail[2];
0098
0099 srm_printk("Ok (rev %lx)\n", rev);
0100
0101 tbia();
0102 }
0103
0104 static inline long openboot(void)
0105 {
0106 char bootdev[256];
0107 long result;
0108
0109 result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
0110 if (result < 0)
0111 return result;
0112 return callback_open(bootdev, result & 255);
0113 }
0114
0115 static inline long close(long dev)
0116 {
0117 return callback_close(dev);
0118 }
0119
0120 static inline long load(long dev, unsigned long addr, unsigned long count)
0121 {
0122 char bootfile[256];
0123 extern char _end;
0124 long result, boot_size = &_end - (char *) BOOT_ADDR;
0125
0126 result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
0127 if (result < 0)
0128 return result;
0129 result &= 255;
0130 bootfile[result] = '\0';
0131 if (result)
0132 srm_printk("Boot file specification (%s) not implemented\n",
0133 bootfile);
0134 return callback_read(dev, count, (void *)addr, boot_size/512 + 1);
0135 }
0136
0137
0138
0139
0140 static void runkernel(void)
0141 {
0142 __asm__ __volatile__(
0143 "bis %1,%1,$30\n\t"
0144 "bis %0,%0,$26\n\t"
0145 "ret ($26)"
0146 :
0147 : "r" (START_ADDR),
0148 "r" (PAGE_SIZE + INIT_STACK));
0149 }
0150
0151 void start_kernel(void)
0152 {
0153 long i;
0154 long dev;
0155 int nbytes;
0156 char envval[256];
0157
0158 srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
0159 if (INIT_HWRPB->pagesize != 8192) {
0160 srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10);
0161 return;
0162 }
0163 pal_init();
0164 dev = openboot();
0165 if (dev < 0) {
0166 srm_printk("Unable to open boot device: %016lx\n", dev);
0167 return;
0168 }
0169 dev &= 0xffffffff;
0170 srm_printk("Loading vmlinux ...");
0171 i = load(dev, START_ADDR, KERNEL_SIZE);
0172 close(dev);
0173 if (i != KERNEL_SIZE) {
0174 srm_printk("Failed (%lx)\n", i);
0175 return;
0176 }
0177
0178 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
0179 if (nbytes < 0) {
0180 nbytes = 0;
0181 }
0182 envval[nbytes] = '\0';
0183 strcpy((char*)ZERO_PGE, envval);
0184
0185 srm_printk(" Ok\nNow booting the kernel\n");
0186 runkernel();
0187 for (i = 0 ; i < 0x100000000 ; i++)
0188 ;
0189 __halt();
0190 }