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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [alpha/] [boot/] [bootp.c] - Blame information for rev 1765

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

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

powered by: WebSVN 2.1.0

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