1
2
3
4
5
6
7
8
9
10
11
12#include <linux/kernel.h>
13#include <linux/slab.h>
14#include <linux/string.h>
15#include <generated/utsrelease.h>
16#include <linux/mm.h>
17
18#include <asm/console.h>
19#include <asm/hwrpb.h>
20#include <asm/pgtable.h>
21#include <asm/io.h>
22
23#include <stdarg.h>
24
25#include "kzsize.h"
26
27
28#define MALLOC_AREA_SIZE 0x200000
29
30
31
32
33
34
35
36
37
38
39
40#undef DEBUG_CHECK_RANGE
41#undef DEBUG_ADDRESSES
42#undef DEBUG_LAST_STEPS
43
44extern unsigned long switch_to_osf_pal(unsigned long nr,
45 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
46 unsigned long *vptb);
47
48extern int decompress_kernel(void* destination, void *source,
49 size_t ksize, size_t kzsize);
50
51extern void move_stack(unsigned long new_stack);
52
53struct hwrpb_struct *hwrpb = INIT_HWRPB;
54static struct pcb_struct pcb_va[1];
55
56
57
58
59
60
61#define VPTB ((unsigned long *) 0x200000000)
62
63static inline unsigned long
64find_pa(unsigned long address)
65{
66 unsigned long result;
67
68 result = VPTB[address >> 13];
69 result >>= 32;
70 result <<= 13;
71 result |= address & 0x1fff;
72 return result;
73}
74
75int
76check_range(unsigned long vstart, unsigned long vend,
77 unsigned long kstart, unsigned long kend)
78{
79 unsigned long vaddr, kaddr;
80
81#ifdef DEBUG_CHECK_RANGE
82 srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n",
83 vstart, vend, kstart, kend);
84#endif
85
86 for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE)
87 {
88 kaddr = (find_pa(vaddr) | PAGE_OFFSET);
89 if (kaddr >= kstart && kaddr <= kend)
90 {
91#ifdef DEBUG_CHECK_RANGE
92 srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx"
93 " [0x%lx:0x%lx]\n",
94 vaddr, kaddr, kstart, kend);
95#endif
96 return 1;
97 }
98 }
99 return 0;
100}
101
102
103
104
105
106
107
108
109
110
111
112
113#define L1 ((unsigned long *) 0x200802000)
114
115void
116pal_init(void)
117{
118 unsigned long i, rev;
119 struct percpu_struct * percpu;
120 struct pcb_struct * pcb_pa;
121
122
123 pcb_va->ksp = 0;
124 pcb_va->usp = 0;
125 pcb_va->ptbr = L1[1] >> 32;
126 pcb_va->asn = 0;
127 pcb_va->pcc = 0;
128 pcb_va->unique = 0;
129 pcb_va->flags = 1;
130 pcb_va->res1 = 0;
131 pcb_va->res2 = 0;
132 pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va);
133
134
135
136
137
138
139
140
141 srm_printk("Switching to OSF PAL-code... ");
142
143 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
144 if (i) {
145 srm_printk("failed, code %ld\n", i);
146 __halt();
147 }
148
149 percpu = (struct percpu_struct *)
150 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
151 rev = percpu->pal_revision = percpu->palcode_avail[2];
152
153 srm_printk("OK (rev %lx)\n", rev);
154
155 tbia();
156}
157
158
159
160
161static inline void
162runkernel(void)
163{
164 __asm__ __volatile__(
165 "bis %0,%0,$27\n\t"
166 "jmp ($27)"
167 :
168 : "r" (START_ADDR));
169}
170
171
172
173unsigned long SP_on_entry;
174
175
176
177
178extern char _end;
179#define KERNEL_ORIGIN \
180 ((((unsigned long)&_end) + 511) & ~511)
181
182
183#define NEXT_PAGE(a) (((a) | (PAGE_SIZE - 1)) + 1)
184
185#ifdef INITRD_IMAGE_SIZE
186# define REAL_INITRD_SIZE INITRD_IMAGE_SIZE
187#else
188# define REAL_INITRD_SIZE 0
189#endif
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218#define V_BOOT_IMAGE_START BOOT_ADDR
219#define V_BOOT_IMAGE_END SP_on_entry
220
221
222#define V_BOOTSTRAPPER_START BOOT_ADDR
223#define V_BOOTSTRAPPER_END KERNEL_ORIGIN
224
225
226
227
228
229#define V_DATA_START KERNEL_ORIGIN
230#define V_INITRD_START (KERNEL_ORIGIN + KERNEL_Z_SIZE)
231#define V_INTRD_END (V_INITRD_START + REAL_INITRD_SIZE)
232#define V_DATA_END V_BOOT_IMAGE_END
233
234
235
236
237
238
239
240#define K_KERNEL_DATA_START ZERO_PGE
241#define K_KERNEL_IMAGE_START START_ADDR
242#define K_KERNEL_IMAGE_END (START_ADDR + KERNEL_SIZE)
243
244
245
246
247
248
249
250
251
252#define K_COPY_IMAGE_START NEXT_PAGE(K_KERNEL_IMAGE_END)
253
254#define K_INITRD_START \
255 NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
256#define K_COPY_IMAGE_END \
257 (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
258#define K_COPY_IMAGE_SIZE \
259 NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
260
261void
262start_kernel(void)
263{
264 int must_move = 0;
265
266
267
268
269
270
271 unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
272 unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
273
274 unsigned long initrd_image_start = K_INITRD_START;
275
276
277
278
279
280
281
282
283
284
285
286
287
288 static long nbytes;
289 static char envval[256] __attribute__((aligned(8)));
290 register unsigned long asm_sp asm("30");
291
292 SP_on_entry = asm_sp;
293
294 srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
295
296
297 if (INIT_HWRPB->pagesize != 8192) {
298 srm_printk("Expected 8kB pages, got %ldkB\n",
299 INIT_HWRPB->pagesize >> 10);
300 return;
301 }
302 if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
303 srm_printk("Expected vptb at %p, got %p\n",
304 VPTB, (void *)INIT_HWRPB->vptb);
305 return;
306 }
307
308
309 pal_init();
310
311
312 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
313 if (nbytes < 0 || nbytes >= sizeof(envval)) {
314 nbytes = 0;
315 }
316 envval[nbytes] = '\0';
317
318#ifdef DEBUG_ADDRESSES
319 srm_printk("START_ADDR 0x%lx\n", START_ADDR);
320 srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
321 srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
322 srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
323#endif
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348 if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
349 K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
350 {
351 srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
352 __halt();
353 }
354
355
356
357
358
359
360
361 if (check_range(V_DATA_START, V_DATA_END,
362 K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
363 {
364#ifdef DEBUG_ADDRESSES
365 srm_printk("OVERLAP: cannot decompress in place\n");
366#endif
367 uncompressed_image_start = K_COPY_IMAGE_START;
368 uncompressed_image_end = K_COPY_IMAGE_END;
369 must_move = 1;
370
371
372
373
374
375
376
377 while (check_range(V_DATA_START, V_DATA_END,
378 uncompressed_image_start,
379 uncompressed_image_end))
380 {
381#if 0
382 uncompressed_image_start += K_COPY_IMAGE_SIZE;
383 uncompressed_image_end += K_COPY_IMAGE_SIZE;
384 initrd_image_start += K_COPY_IMAGE_SIZE;
385#else
386
387 uncompressed_image_start += PAGE_SIZE;
388 uncompressed_image_end += PAGE_SIZE;
389 initrd_image_start += PAGE_SIZE;
390#endif
391 }
392 }
393
394 srm_printk("Starting to load the kernel with args '%s'\n", envval);
395
396#ifdef DEBUG_ADDRESSES
397 srm_printk("Decompressing the kernel...\n"
398 "...from 0x%lx to 0x%lx size 0x%x\n",
399 V_DATA_START,
400 uncompressed_image_start,
401 KERNEL_SIZE);
402#endif
403 decompress_kernel((void *)uncompressed_image_start,
404 (void *)V_DATA_START,
405 KERNEL_SIZE, KERNEL_Z_SIZE);
406
407
408
409
410
411#ifdef INITRD_IMAGE_SIZE
412
413
414#ifdef DEBUG_ADDRESSES
415 srm_printk("Moving the INITRD image...\n"
416 " from 0x%lx to 0x%lx size 0x%x\n",
417 V_INITRD_START,
418 initrd_image_start,
419 INITRD_IMAGE_SIZE);
420#endif
421 memcpy((void *)initrd_image_start, (void *)V_INITRD_START,
422 INITRD_IMAGE_SIZE);
423
424#endif
425
426
427
428
429 if (must_move) {
430#ifdef DEBUG_ADDRESSES
431 srm_printk("Moving the uncompressed kernel...\n"
432 "...from 0x%lx to 0x%lx size 0x%x\n",
433 uncompressed_image_start,
434 K_KERNEL_IMAGE_START,
435 (unsigned)KERNEL_SIZE);
436#endif
437
438
439
440
441 move_stack(initrd_image_start - PAGE_SIZE);
442
443 memcpy((void *)K_KERNEL_IMAGE_START,
444 (void *)uncompressed_image_start, KERNEL_SIZE);
445 }
446
447
448#ifdef DEBUG_LAST_STEPS
449 srm_printk("Preparing ZERO_PGE...\n");
450#endif
451 memset((char*)ZERO_PGE, 0, PAGE_SIZE);
452 strcpy((char*)ZERO_PGE, envval);
453
454#ifdef INITRD_IMAGE_SIZE
455
456#ifdef DEBUG_LAST_STEPS
457 srm_printk("Preparing INITRD info...\n");
458#endif
459
460 ((long *)(ZERO_PGE+256))[0] = initrd_image_start;
461 ((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
462
463#endif
464
465#ifdef DEBUG_LAST_STEPS
466 srm_printk("Doing 'runkernel()'...\n");
467#endif
468 runkernel();
469}
470
471
472void *__kmalloc(size_t size, gfp_t flags)
473{
474 return (void *)NULL;
475}
476