0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/string.h>
0016 #include <generated/utsrelease.h>
0017 #include <linux/mm.h>
0018
0019 #include <asm/console.h>
0020 #include <asm/hwrpb.h>
0021 #include <asm/io.h>
0022
0023 #include <stdarg.h>
0024
0025 #include "kzsize.h"
0026
0027
0028 #define MALLOC_AREA_SIZE 0x200000
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #undef DEBUG_CHECK_RANGE
0041 #undef DEBUG_ADDRESSES
0042 #undef DEBUG_LAST_STEPS
0043
0044 extern unsigned long switch_to_osf_pal(unsigned long nr,
0045 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
0046 unsigned long *vptb);
0047
0048 extern int decompress_kernel(void* destination, void *source,
0049 size_t ksize, size_t kzsize);
0050
0051 extern void move_stack(unsigned long new_stack);
0052
0053 struct hwrpb_struct *hwrpb = INIT_HWRPB;
0054 static struct pcb_struct pcb_va[1];
0055
0056
0057
0058
0059
0060
0061 #define VPTB ((unsigned long *) 0x200000000)
0062
0063 static inline unsigned long
0064 find_pa(unsigned long address)
0065 {
0066 unsigned long result;
0067
0068 result = VPTB[address >> 13];
0069 result >>= 32;
0070 result <<= 13;
0071 result |= address & 0x1fff;
0072 return result;
0073 }
0074
0075 int
0076 check_range(unsigned long vstart, unsigned long vend,
0077 unsigned long kstart, unsigned long kend)
0078 {
0079 unsigned long vaddr, kaddr;
0080
0081 #ifdef DEBUG_CHECK_RANGE
0082 srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n",
0083 vstart, vend, kstart, kend);
0084 #endif
0085
0086 for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE)
0087 {
0088 kaddr = (find_pa(vaddr) | PAGE_OFFSET);
0089 if (kaddr >= kstart && kaddr <= kend)
0090 {
0091 #ifdef DEBUG_CHECK_RANGE
0092 srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx"
0093 " [0x%lx:0x%lx]\n",
0094 vaddr, kaddr, kstart, kend);
0095 #endif
0096 return 1;
0097 }
0098 }
0099 return 0;
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 #define L1 ((unsigned long *) 0x200802000)
0114
0115 void
0116 pal_init(void)
0117 {
0118 unsigned long i, rev;
0119 struct percpu_struct * percpu;
0120 struct pcb_struct * pcb_pa;
0121
0122
0123 pcb_va->ksp = 0;
0124 pcb_va->usp = 0;
0125 pcb_va->ptbr = L1[1] >> 32;
0126 pcb_va->asn = 0;
0127 pcb_va->pcc = 0;
0128 pcb_va->unique = 0;
0129 pcb_va->flags = 1;
0130 pcb_va->res1 = 0;
0131 pcb_va->res2 = 0;
0132 pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va);
0133
0134
0135
0136
0137
0138
0139
0140
0141 srm_printk("Switching to OSF PAL-code... ");
0142
0143 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
0144 if (i) {
0145 srm_printk("failed, code %ld\n", i);
0146 __halt();
0147 }
0148
0149 percpu = (struct percpu_struct *)
0150 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
0151 rev = percpu->pal_revision = percpu->palcode_avail[2];
0152
0153 srm_printk("OK (rev %lx)\n", rev);
0154
0155 tbia();
0156 }
0157
0158
0159
0160
0161 static inline void
0162 runkernel(void)
0163 {
0164 __asm__ __volatile__(
0165 "bis %0,%0,$27\n\t"
0166 "jmp ($27)"
0167 :
0168 : "r" (START_ADDR));
0169 }
0170
0171
0172
0173 unsigned long SP_on_entry;
0174
0175
0176
0177
0178 extern char _end;
0179 #define KERNEL_ORIGIN \
0180 ((((unsigned long)&_end) + 511) & ~511)
0181
0182
0183 #define NEXT_PAGE(a) (((a) | (PAGE_SIZE - 1)) + 1)
0184
0185 #ifdef INITRD_IMAGE_SIZE
0186 # define REAL_INITRD_SIZE INITRD_IMAGE_SIZE
0187 #else
0188 # define REAL_INITRD_SIZE 0
0189 #endif
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 #define V_BOOT_IMAGE_START BOOT_ADDR
0219 #define V_BOOT_IMAGE_END SP_on_entry
0220
0221
0222 #define V_BOOTSTRAPPER_START BOOT_ADDR
0223 #define V_BOOTSTRAPPER_END KERNEL_ORIGIN
0224
0225
0226
0227
0228
0229 #define V_DATA_START KERNEL_ORIGIN
0230 #define V_INITRD_START (KERNEL_ORIGIN + KERNEL_Z_SIZE)
0231 #define V_INTRD_END (V_INITRD_START + REAL_INITRD_SIZE)
0232 #define V_DATA_END V_BOOT_IMAGE_END
0233
0234
0235
0236
0237
0238
0239
0240 #define K_KERNEL_DATA_START ZERO_PGE
0241 #define K_KERNEL_IMAGE_START START_ADDR
0242 #define K_KERNEL_IMAGE_END (START_ADDR + KERNEL_SIZE)
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 #define K_COPY_IMAGE_START NEXT_PAGE(K_KERNEL_IMAGE_END)
0253
0254 #define K_INITRD_START \
0255 NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
0256 #define K_COPY_IMAGE_END \
0257 (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
0258 #define K_COPY_IMAGE_SIZE \
0259 NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
0260
0261 void
0262 start_kernel(void)
0263 {
0264 int must_move = 0;
0265
0266
0267
0268
0269
0270
0271 unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
0272 unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
0273
0274 unsigned long initrd_image_start = K_INITRD_START;
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 static long nbytes;
0289 static char envval[256] __attribute__((aligned(8)));
0290 register unsigned long asm_sp asm("30");
0291
0292 SP_on_entry = asm_sp;
0293
0294 srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
0295
0296
0297 if (INIT_HWRPB->pagesize != 8192) {
0298 srm_printk("Expected 8kB pages, got %ldkB\n",
0299 INIT_HWRPB->pagesize >> 10);
0300 return;
0301 }
0302 if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
0303 srm_printk("Expected vptb at %p, got %p\n",
0304 VPTB, (void *)INIT_HWRPB->vptb);
0305 return;
0306 }
0307
0308
0309 pal_init();
0310
0311
0312 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
0313 if (nbytes < 0 || nbytes >= sizeof(envval)) {
0314 nbytes = 0;
0315 }
0316 envval[nbytes] = '\0';
0317
0318 #ifdef DEBUG_ADDRESSES
0319 srm_printk("START_ADDR 0x%lx\n", START_ADDR);
0320 srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
0321 srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
0322 srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
0323 #endif
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348 if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
0349 K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
0350 {
0351 srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
0352 __halt();
0353 }
0354
0355
0356
0357
0358
0359
0360
0361 if (check_range(V_DATA_START, V_DATA_END,
0362 K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
0363 {
0364 #ifdef DEBUG_ADDRESSES
0365 srm_printk("OVERLAP: cannot decompress in place\n");
0366 #endif
0367 uncompressed_image_start = K_COPY_IMAGE_START;
0368 uncompressed_image_end = K_COPY_IMAGE_END;
0369 must_move = 1;
0370
0371
0372
0373
0374
0375
0376
0377 while (check_range(V_DATA_START, V_DATA_END,
0378 uncompressed_image_start,
0379 uncompressed_image_end))
0380 {
0381 #if 0
0382 uncompressed_image_start += K_COPY_IMAGE_SIZE;
0383 uncompressed_image_end += K_COPY_IMAGE_SIZE;
0384 initrd_image_start += K_COPY_IMAGE_SIZE;
0385 #else
0386
0387 uncompressed_image_start += PAGE_SIZE;
0388 uncompressed_image_end += PAGE_SIZE;
0389 initrd_image_start += PAGE_SIZE;
0390 #endif
0391 }
0392 }
0393
0394 srm_printk("Starting to load the kernel with args '%s'\n", envval);
0395
0396 #ifdef DEBUG_ADDRESSES
0397 srm_printk("Decompressing the kernel...\n"
0398 "...from 0x%lx to 0x%lx size 0x%x\n",
0399 V_DATA_START,
0400 uncompressed_image_start,
0401 KERNEL_SIZE);
0402 #endif
0403 decompress_kernel((void *)uncompressed_image_start,
0404 (void *)V_DATA_START,
0405 KERNEL_SIZE, KERNEL_Z_SIZE);
0406
0407
0408
0409
0410
0411 #ifdef INITRD_IMAGE_SIZE
0412
0413
0414 #ifdef DEBUG_ADDRESSES
0415 srm_printk("Moving the INITRD image...\n"
0416 " from 0x%lx to 0x%lx size 0x%x\n",
0417 V_INITRD_START,
0418 initrd_image_start,
0419 INITRD_IMAGE_SIZE);
0420 #endif
0421 memcpy((void *)initrd_image_start, (void *)V_INITRD_START,
0422 INITRD_IMAGE_SIZE);
0423
0424 #endif
0425
0426
0427
0428
0429 if (must_move) {
0430 #ifdef DEBUG_ADDRESSES
0431 srm_printk("Moving the uncompressed kernel...\n"
0432 "...from 0x%lx to 0x%lx size 0x%x\n",
0433 uncompressed_image_start,
0434 K_KERNEL_IMAGE_START,
0435 (unsigned)KERNEL_SIZE);
0436 #endif
0437
0438
0439
0440
0441 move_stack(initrd_image_start - PAGE_SIZE);
0442
0443 memcpy((void *)K_KERNEL_IMAGE_START,
0444 (void *)uncompressed_image_start, KERNEL_SIZE);
0445 }
0446
0447
0448 #ifdef DEBUG_LAST_STEPS
0449 srm_printk("Preparing ZERO_PGE...\n");
0450 #endif
0451 memset((char*)ZERO_PGE, 0, PAGE_SIZE);
0452 strcpy((char*)ZERO_PGE, envval);
0453
0454 #ifdef INITRD_IMAGE_SIZE
0455
0456 #ifdef DEBUG_LAST_STEPS
0457 srm_printk("Preparing INITRD info...\n");
0458 #endif
0459
0460 ((long *)(ZERO_PGE+256))[0] = initrd_image_start;
0461 ((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
0462
0463 #endif
0464
0465 #ifdef DEBUG_LAST_STEPS
0466 srm_printk("Doing 'runkernel()'...\n");
0467 #endif
0468 runkernel();
0469 }
0470
0471
0472 void *__kmalloc(size_t size, gfp_t flags)
0473 {
0474 return (void *)NULL;
0475 }