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