OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [alpha/] [boot/] [main.c] - Blame information for rev 1622

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.