boot32.c revision 1.12 1 /* $NetBSD: boot32.c,v 1.12 2003/04/20 14:21:13 bjh21 Exp $ */
2
3 /*-
4 * Copyright (c) 2002 Reinoud Zandijk
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Thanks a bunch for Ben's framework for the bootloader and its suporting
30 * libs. This file tries to actually boot NetBSD/acorn32 !
31 *
32 * XXX eventually to be partly merged back with boot26 ? XXX
33 */
34
35 #include <lib/libsa/stand.h>
36 #include <lib/libsa/loadfile.h>
37 #include <lib/libkern/libkern.h>
38 #include <riscoscalls.h>
39 #include <srt0.h>
40 #include <sys/boot_flag.h>
41 #include <machine/vmparam.h>
42 #include <arm/arm32/pte.h>
43 #include <machine/bootconfig.h>
44
45
46 /* debugging flags */
47 int debug = 1;
48
49
50 /* constants */
51 #define PODRAM_START (512*1024*1024) /* XXX Kinetic cards XXX */
52
53 #define MAX_RELOCPAGES 4096
54
55 #define DEFAULT_ROOT "/dev/wd0a"
56
57
58 #define IO_BLOCKS 16 /* move these to the bootloader structure? */
59 #define ROM_BLOCKS 16
60 #define PODRAM_BLOCKS 16
61
62
63 /* booter variables */
64 char scrap[80], twirl_cnt; /* misc */
65 char booted_file[80];
66
67 struct bootconfig *bconfig; /* bootconfig passing */
68 u_long bconfig_new_phys; /* physical address its bound */
69
70 /* Computer knowledge */
71 u_int monitor_type, monitor_sync, ioeb_flags, lcd_flags;
72 u_int superio_flags, superio_flags_basic, superio_flags_extra;
73
74
75 int nbpp, memory_table_size, memory_image_size; /* sizes */
76 u_long reloc_tablesize, *reloc_instruction_table; /* relocate info */
77 u_long *reloc_pos; /* current empty entry */
78 int reloc_entries; /* number of relocations */
79 int first_mapped_DRAM_page_index; /* offset in RISC OS blob */
80 int first_mapped_PODRAM_page_index;/* offset in RISC OS blob */
81
82 struct page_info *mem_pages_info; /* {nr, virt, phys}* */
83 struct page_info *free_relocation_page; /* points to the page_info chain*/
84 struct page_info *relocate_table_pages; /* points to seq. relocate info */
85 struct page_info *relocate_code_page; /* points to the copied code */
86 struct page_info *bconfig_page; /* page for passing on settings */
87
88 unsigned char *memory_page_types; /* packed array of 4 bit typeId */
89
90 u_long *initial_page_tables; /* pagetables to be booted from */
91
92
93 /* XXX rename *_BLOCKS to MEM_BLOCKS */
94 /* DRAM/VRAM/ROM/IO info */
95 u_long videomem_start, videomem_pages, display_size;/* where the display is*/
96
97 u_long pv_offset, top_physdram; /* kernel_base - phys. diff */
98 u_long top_1Mb_dram; /* the lower mapped top 1Mb */
99 u_long new_L1_pages_phys; /* physical address of L1 pages */
100
101 /* for bootconfig passing*/
102 u_long total_podram_pages, total_dram_pages, total_vram_pages;
103 int dram_blocks, podram_blocks; /* number of mem. objects/type */
104 int vram_blocks, rom_blocks, io_blocks;
105
106 u_long DRAM_addr[DRAM_BLOCKS], DRAM_pages[DRAM_BLOCKS];
107 /* processor only RAM */
108 u_long PODRAM_addr[PODRAM_BLOCKS], PODRAM_pages[PODRAM_BLOCKS];
109 u_long VRAM_addr[VRAM_BLOCKS], VRAM_pages[VRAM_BLOCKS];
110 u_long ROM_addr[ROM_BLOCKS], ROM_pages[ROM_BLOCKS];
111 u_long IO_addr[IO_BLOCKS], IO_pages[IO_BLOCKS];
112
113
114 /* RISC OS memory pages we claimed */
115 u_long firstpage, lastpage, totalpages;/* RISC OS pagecounters */
116 char *memory_image, *bottom_memory, *top_memory;/* RISC OS memory */
117
118 u_long videomem_start_ro; /* for debugging mainly */
119
120 /* kernel info */
121 u_long marks[MARK_MAX]; /* loader mark pointers */
122 u_long kernel_physical_start; /* where does it get relocated */
123 u_long kernel_free_vm_start; /* where does the free VM start */
124 /* some free space to mess with */
125 u_long scratch_virtualbase, scratch_physicalbase;
126
127
128 /* bootprogram identifiers */
129 extern const char bootprog_rev[];
130 extern const char bootprog_name[];
131 extern const char bootprog_date[];
132 extern const char bootprog_maker[];
133
134
135 /* predefines / prototypes */
136 void init_datastructures(void);
137 void get_memory_configuration(void);
138 void get_memory_map(void);
139 void create_initial_page_tables(void);
140 void add_pagetables_at_top(void);
141 void sort_memory_map(void);
142 void add_initvectors(void);
143 void create_configuration(int argc, char **argv, int start_args);
144 void prepare_and_check_relocation_system(void);
145 void twirl(void);
146 int vdu_var(int);
147 void process_args(int argc, char **argv, int *howto, char *file,
148 int *start_args);
149
150 char *sprint0(int width, char prefix, char base, int value);
151 struct page_info *get_relocated_page(u_long destination, int size);
152
153 extern void start_kernel(
154 int relocate_code_page,
155 int relocation_pv_offset,
156 int configuration_structure_in_flat_physical_space,
157 int physical_address_of_relocation_tables,
158 int physical_address_of_new_L1_pages,
159 int kernel_entry_point
160 ); /* asm */
161
162
163 /* the loader itself */
164 void init_datastructures(void) {
165 /* Get number of pages and the memorytablesize */
166 osmemory_read_arrangement_table_size(&memory_table_size, &nbpp);
167
168 /* reserve some space for heap etc... 512 might be bigish though */
169 memory_image_size = (int) HIMEM - 512*1024;
170 if (memory_image_size <= 256*1024)
171 panic("I need more memory to boot up; increase Wimp slot");
172 memory_image = alloc(memory_image_size);
173 if (!memory_image) panic("Can't alloc get my memory image ?");
174
175 bottom_memory = memory_image;
176 top_memory = memory_image + memory_image_size;
177
178 firstpage = ((int) bottom_memory / nbpp) + 1; /* safety */
179 lastpage = ((int) top_memory / nbpp) - 1;
180 totalpages = lastpage - firstpage;
181
182 printf("Got %ld memory pages each %d kilobytes to mess with.\n\n",
183 totalpages, nbpp>>10);
184
185 /* allocate some space for the relocation table */
186 /* 3 entry table */
187 reloc_tablesize = (MAX_RELOCPAGES+1)*3*sizeof(u_long);
188 reloc_instruction_table = alloc(reloc_tablesize);
189 if (!reloc_instruction_table)
190 panic("Can't alloc my relocate instructions pages");
191
192 /*
193 * set up relocation table. First word gives number of
194 * relocations to be done
195 */
196 reloc_entries = 0;
197 reloc_pos = reloc_instruction_table;
198 *reloc_pos++ = 0;
199
200 /*
201 * set up the memory translation info structure; alloc one
202 * more for end of list marker; see get_memory_map
203 */
204 mem_pages_info = alloc((totalpages + 1)*sizeof(struct page_info));
205 if (!mem_pages_info) panic("Can't alloc my phys->virt page info");
206
207 /* allocate memory for the memory arrangement table */
208 memory_page_types = alloc(memory_table_size);
209 if (!memory_page_types) panic("Can't alloc my memory page type block");
210
211 initial_page_tables = alloc(16*1024);/* size is 16 kb per definition */
212 if (!initial_page_tables) panic("Can't alloc my initial page tables");
213 }
214
215
216 void prepare_and_check_relocation_system(void) {
217 int relocate_size, relocate_pages;
218 int bank, pages, found;
219 u_long dst, src, base, destination, extend;
220 u_long *reloc_entry, last_src, length;
221
222 /* set the number of relocation entries in the 1st word */
223 *reloc_instruction_table = reloc_entries;
224
225 /*
226 * the relocate information needs to be in one sequential
227 * physical space
228 */
229 /* round space up */
230 relocate_size = (reloc_tablesize + nbpp-1) & ~(nbpp-1);
231
232 printf("\nPreparing for booting %s ... ", booted_file);
233 relocate_pages = relocate_size / nbpp;
234
235 relocate_table_pages = free_relocation_page;
236 pages = 0;
237 while (pages < relocate_pages) {
238 src = (u_long) reloc_instruction_table + pages*nbpp;
239 dst = (relocate_table_pages + pages)->logical;
240 memcpy((void *) dst, (void *) src, nbpp);
241
242 if (pages < relocate_pages-1) {
243 /* check if next page is sequential physically */
244 if ((relocate_table_pages+pages+1)->physical -
245 (relocate_table_pages+pages)->physical != nbpp) {
246 /*
247 * Ieee! non contigunous relocate area
248 * -> try again
249 */
250 printf("*");
251 relocate_table_pages += pages;
252 /* will be incremented till zero later */
253 pages = -1;
254 };
255 };
256 pages++;
257 };
258 free_relocation_page = relocate_table_pages + pages;
259
260 /* copy the relocation code into this page in start_kernel */
261 relocate_code_page = free_relocation_page++;
262
263 /*
264 * All relocations are pages allocated in one big strict increasing
265 * physical DRAM address sequence. When the MMU is switched off all
266 * code and data is in this increasing order but not at the right
267 * place. This is where the relocation code kicks in; relocation is
268 * done in flat physical memory without MMU.
269 */
270
271 printf("shift and check ... ");
272 reloc_entry = reloc_instruction_table + 1;
273 last_src = -1;
274 while (reloc_entry < reloc_pos) {
275 src = reloc_entry[0];
276 destination = reloc_entry[1];
277 length = reloc_entry[2];
278
279 /* paranoia check */
280 if ((long) (src - last_src) <= 0)
281 printf("relocation sequence challenged -- "
282 "booting might fail ");
283 last_src = src;
284
285 /* check if its gonna be relocated into (PO)DRAM ! */
286 extend = destination + length;
287 found = 0;
288 for (bank = 0; (bank < dram_blocks) && !found; bank++) {
289 base = DRAM_addr[bank];
290 found = (destination >= base) &&
291 (extend <= base + DRAM_pages[bank]*nbpp);
292 };
293 for (bank = 0; (bank < podram_blocks) && !found; bank++) {
294 base = PODRAM_addr[bank];
295 found = (destination >= base) &&
296 (extend <= base + PODRAM_pages[bank]*nbpp);
297 };
298 if (!found || (extend > top_physdram)) {
299 panic( "Internal error: relocating range "
300 "[%lx +%lx => %lx] outside (PO)DRAM banks!",
301 src, length, destination);
302 };
303
304 reloc_entry+=3;
305 };
306 if (reloc_entry != reloc_pos)
307 panic("Relocation instruction table is corrupted");
308
309 printf("OK!\n");
310 }
311
312
313 void get_memory_configuration(void) {
314 int loop, current_page_type, page_count, phys_page;
315 int page, count, bank;
316 int mapped_screen_memory;
317
318 printf("Getting memory configuration ");
319
320 osmemory_read_arrangement_table(memory_page_types);
321
322 /* init counters */
323 bank = vram_blocks = dram_blocks = rom_blocks = io_blocks = 0;
324 podram_blocks = 0;
325
326 current_page_type = -1;
327 phys_page = 0; /* physical address in pages */
328 page_count = 0; /* page counter in this block */
329 loop = 0; /* loop variable over entries */
330
331 /* iterating over a packed array of 2 page types/byte i.e. 8 kb/byte */
332 while (loop < 2*memory_table_size) {
333 page = (memory_page_types[loop / 2]); /* read twice */
334 if (loop & 1) page >>= 4; /* take other nibble */
335
336 /* bits 0-2 give type, bit3 means the bit page is allocatable*/
337 page &= 0x7; /* only take bottom 3 bits */
338 if (page != current_page_type) {
339 /*
340 * passed a boundary ... note this block
341 * splitting in different vars is for
342 * compatability reasons
343 */
344 switch (current_page_type) {
345 case -1 :
346 case 0 :
347 break;
348 case osmemory_TYPE_DRAM :
349 if (phys_page < PODRAM_START) {
350 DRAM_addr[dram_blocks] =
351 phys_page * nbpp;
352 DRAM_pages[dram_blocks] =
353 page_count;
354 dram_blocks++;
355 } else {
356 PODRAM_addr[podram_blocks] =
357 phys_page * nbpp;
358 PODRAM_pages[podram_blocks] =
359 page_count;
360 podram_blocks++;
361 };
362 break;
363 case osmemory_TYPE_VRAM :
364 VRAM_addr[vram_blocks] =
365 phys_page * nbpp;
366 VRAM_pages[vram_blocks] = page_count;
367 vram_blocks++;
368 break;
369 case osmemory_TYPE_ROM :
370 ROM_addr[rom_blocks] =
371 phys_page * nbpp;
372 ROM_pages[rom_blocks] = page_count;
373 rom_blocks++;
374 break;
375 case osmemory_TYPE_IO :
376 IO_addr[io_blocks] = phys_page * nbpp;
377 IO_pages[io_blocks] = page_count;
378 io_blocks++;
379 break;
380 default :
381 printf("WARNING : found unknown "
382 "memory object %d ",
383 current_page_type);
384 printf(" at 0x%s",
385 sprint0(8,'0','x',
386 phys_page * nbpp));
387 printf(" for %s k\n",
388 sprint0(5,' ','d',
389 (page_count*nbpp)>>10));
390 break;
391 };
392 current_page_type = page;
393 phys_page = loop;
394 page_count = 0;
395 };
396 /*
397 * smallest unit we recognise is one page ... silly
398 * could be upto 64 pages i.e. 256 kb
399 */
400 page_count += 1;
401 loop += 1;
402 if ((loop & 31) == 0) twirl();
403 };
404
405 printf(" \n\n");
406
407 if (VRAM_pages[0] == 0) {
408 /* map DRAM as video memory */
409 display_size =
410 (vdu_var(os_VDUVAR_TOTAL_SCREEN_SIZE) & ~(nbpp-1));
411 #if 0
412 mapped_screen_memory = 1024 * 1024; /* max allowed on RiscPC */
413 videomem_pages = (mapped_screen_memory / nbpp);
414 videomem_start = DRAM_addr[0];
415 DRAM_addr[0] += videomem_pages * nbpp;
416 DRAM_pages[0] -= videomem_pages;
417 #else
418 mapped_screen_memory = display_size;
419 bank = dram_blocks-1; /* pick last SIMM */
420 videomem_pages = (mapped_screen_memory / nbpp);
421
422 /* Map video memory at the end of the SIMM */
423 videomem_start =
424 DRAM_addr[bank] + (DRAM_pages[bank] - videomem_pages)*nbpp;
425 DRAM_pages[bank]-= videomem_pages;
426 #endif
427 } else {
428 /* use VRAM */
429 mapped_screen_memory = 0;
430 videomem_start = VRAM_addr[0];
431 videomem_pages = VRAM_pages[0];
432 display_size = videomem_pages * nbpp;
433 };
434
435 if (mapped_screen_memory) {
436 printf("Used %d kb DRAM ", (mapped_screen_memory)/1024);
437 printf("at 0x%s for video memory\n",
438 sprint0(8,'0','x', videomem_start));
439 };
440
441 /* find top of DRAM pages */
442 top_physdram = 0;
443
444 for (loop = podram_blocks-1;
445 (loop >= 0) && (PODRAM_addr[loop] == 0);
446 loop++);
447 if (loop >= 0)
448 top_physdram = PODRAM_addr[loop] + PODRAM_pages[loop]*nbpp;
449 if (top_physdram == 0) {
450 for (loop = dram_blocks-1;
451 (loop >= 0) && (DRAM_addr[loop] == 0);
452 loop++);
453 if (loop >= 0)
454 top_physdram = DRAM_addr[loop] + DRAM_pages[loop]*nbpp;
455 };
456 if (top_physdram == 0) panic("reality check: No DRAM in this machine?");
457
458
459 videomem_start_ro = vdu_var(os_VDUVAR_DISPLAY_START);
460
461 /* pretty print the individual page types */
462 for (count = 0; count < rom_blocks; count++) {
463 printf("Found ROM (%d)", count);
464 printf(" at 0x%s", sprint0(8,'0','x', ROM_addr[count]));
465 printf(" for %s k\n",
466 sprint0(5,' ','d', (ROM_pages[count]*nbpp)>>10));
467 };
468
469 for (count = 0; count < io_blocks; count++) {
470 printf("Found I/O (%d)", count);
471 printf(" at 0x%s", sprint0(8,'0','x', IO_addr[count]));
472 printf(" for %s k\n",
473 sprint0(5,' ','d', (IO_pages[count]*nbpp)>>10));
474 };
475
476 /* for DRAM/VRAM also count the number of pages */
477 total_dram_pages = 0;
478 for (count = 0; count < dram_blocks; count++) {
479 total_dram_pages += DRAM_pages[count];
480 printf("Found DRAM (%d)", count);
481 printf(" at 0x%s", sprint0(8,'0','x', DRAM_addr[count]));
482 printf(" for %s k\n",
483 sprint0(5,' ','d', (DRAM_pages[count]*nbpp)>>10));
484 };
485
486 total_vram_pages = 0;
487 for (count = 0; count < vram_blocks; count++) {
488 total_vram_pages += VRAM_pages[count];
489 printf("Found VRAM (%d)", count);
490 printf(" at 0x%s", sprint0(8,'0','x', VRAM_addr[count]));
491 printf(" for %s k\n",
492 sprint0(5,' ','d', (VRAM_pages[count]*nbpp)>>10));
493 };
494
495 total_podram_pages = 0;
496 for (count = 0; count < podram_blocks; count++) {
497 total_podram_pages += PODRAM_pages[count];
498 printf("Found Processor only (S)DRAM (%d)", count);
499 printf(" at 0x%s", sprint0(8,'0','x', PODRAM_addr[count]));
500 printf(" for %s k\n",
501 sprint0(5,' ','d', (PODRAM_pages[count]*nbpp)>>10));
502 };
503 }
504
505
506 void get_memory_map(void) {
507 struct page_info *page_info;
508 int page, inout;
509 int phys_addr;
510
511 printf("\nGetting actual memorymapping");
512 for (page = 0, page_info = mem_pages_info;
513 page < totalpages;
514 page++, page_info++) {
515 page_info->pagenumber = 0; /* not used */
516 page_info->logical = (firstpage + page) * nbpp;
517 page_info->physical = 0; /* result comes here */
518 /* to avoid triggering a `bug' in RISC OS 4, page it in */
519 *((int *) page_info->logical) = 0;
520 };
521 /* close list */
522 page_info->pagenumber = -1;
523
524 inout = osmemory_GIVEN_LOG_ADDR | osmemory_RETURN_PAGE_NO |
525 osmemory_RETURN_PHYS_ADDR;
526 osmemory_page_op(inout, mem_pages_info, totalpages);
527
528 printf(" ; sorting ");
529 sort_memory_map();
530 printf(".\n");
531
532 /*
533 * get the first DRAM index and show the physical memory
534 * fragments we got
535 */
536 printf("\nFound physical memory blocks :\n");
537 first_mapped_DRAM_page_index = -1;
538 first_mapped_PODRAM_page_index = -1;
539 for (page=0; page < totalpages; page++) {
540 phys_addr = mem_pages_info[page].physical;
541 printf("[0x%x", phys_addr);
542 while (mem_pages_info[page+1].physical - phys_addr == nbpp) {
543 if ((first_mapped_DRAM_page_index<0) &&
544 (phys_addr >= DRAM_addr[0])) {
545 first_mapped_DRAM_page_index = page;
546 };
547 if ((first_mapped_PODRAM_page_index<0) &&
548 (phys_addr >= PODRAM_addr[0])) {
549 first_mapped_PODRAM_page_index = page;
550 };
551 page++;
552 phys_addr = mem_pages_info[page].physical;
553 };
554 printf("-0x%x] ", (phys_addr + nbpp -1));
555 };
556 printf("\n\n");
557 if (first_mapped_PODRAM_page_index < 0) {
558 if (PODRAM_addr[0])
559 panic("Found no (S)DRAM mapped in the bootloader ... "
560 "increase Wimpslot!");
561 };
562 if (first_mapped_DRAM_page_index < 0)
563 panic("No DRAM mapped in the bootloader ... "
564 "increase Wimpslot!");
565 }
566
567
568 void create_initial_page_tables(void) {
569 u_long page, section, addr, kpage;
570
571 /* mark a section by the following bits and domain 0, AP=01, CB=0 */
572 /* A P C B section */
573 section = (0<<11) | (1<<10) | (0<<3) | (0<<2) | (1<<4) | (1<<1) | (0) |
574 /* domain */
575 (0 << 5);
576
577 /* first of all a full 1:1 mapping */
578 for (page = 0; page < 4*1024; page++) {
579 initial_page_tables[page] = (page<<20) | section;
580 };
581
582 /* video memory is mapped 1:1 in the DRAM section or in VRAM section */
583
584 /* map 1Mb from top of memory to bottom 1Mb of virtual memmap */
585 top_1Mb_dram = (((top_physdram - 1024*1024) >> 20) << 20);
586 initial_page_tables[0] = top_1Mb_dram | section;
587
588 /* map 16 Mb of kernel space to KERNEL_BASE i.e. marks[KERNEL_START] */
589 for (page = 0; page < 16; page++) {
590 addr = (kernel_physical_start >> 20) + page;
591 kpage = (marks[MARK_START] >> 20) + page;
592 initial_page_tables[kpage] = (addr << 20) | section;
593 };
594 }
595
596
597 void add_pagetables_at_top(void) {
598 int page;
599 u_long src, dst, fragaddr;
600
601 /* Special : destination must be on a 16 Kb boundary */
602 /* get 4 pages on the top of the physical memory and copy PT's in it */
603 new_L1_pages_phys = top_physdram - 4*nbpp;
604
605 /*
606 * If the L1 page tables are not 16 kb aligned, adjust base
607 * until it is
608 */
609 while (new_L1_pages_phys & (16*1024-1)) {
610 new_L1_pages_phys -= nbpp;
611 };
612 if (new_L1_pages_phys & (16*1024-1))
613 panic("Paranoia : L1 pages not on 16Kb boundary");
614
615 dst = new_L1_pages_phys;
616 src = (u_long) initial_page_tables;
617
618 for (page = 0; page < 4; page++) {
619 /* get a page for a fragment */
620 fragaddr = get_relocated_page(dst, nbpp)->logical;
621 memcpy((void *) fragaddr, (void *) src, nbpp);
622
623 src += nbpp;
624 dst += nbpp;
625 };
626 }
627
628
629 void add_initvectors(void) {
630 u_long *pos;
631 u_long vectoraddr, count;
632
633 /* the top 1Mb of the physical DRAM pages is mapped at address 0 */
634 vectoraddr = get_relocated_page(top_1Mb_dram, nbpp)->logical;
635
636 /* fill the vectors with `movs pc, lr' opcodes */
637 pos = (u_long *) vectoraddr; memset(pos, 0, nbpp);
638 for (count = 0; count < 128; count++) *pos++ = 0xE1B0F00E;
639 }
640
641
642 void create_configuration(int argc, char **argv, int start_args) {
643 int i, root_specified, id_low, id_high;
644 char *pos;
645
646 bconfig_new_phys = kernel_free_vm_start - pv_offset;
647 bconfig_page = get_relocated_page(bconfig_new_phys, nbpp);
648 bconfig = (struct bootconfig *) (bconfig_page->logical);
649 kernel_free_vm_start += nbpp;
650
651 /* get some miscelanious info for the bootblock */
652 os_readsysinfo_monitor_info(NULL, &monitor_type, &monitor_sync);
653 os_readsysinfo_chip_presence(&ioeb_flags, &superio_flags, &lcd_flags);
654 os_readsysinfo_superio_features(&superio_flags_basic,
655 &superio_flags_extra);
656 os_readsysinfo_unique_id(&id_low, &id_high);
657
658 /* fill in the bootconfig *bconfig structure : generic version II */
659 memset(bconfig, 0, sizeof(bconfig));
660 bconfig->magic = BOOTCONFIG_MAGIC;
661 bconfig->version = BOOTCONFIG_VERSION;
662 strcpy(bconfig->kernelname, booted_file);
663
664 /*
665 * get the kernel base name and update the RiscOS name to a
666 * Unix name
667 */
668 i = strlen(bconfig->kernelname);
669 while ((i >= 0) && (bconfig->kernelname[i] != '.')) i--;
670 if (i)
671 memcpy(bconfig->kernelname, bconfig->kernelname+i+1,
672 strlen(booted_file)-i);
673
674 pos = bconfig->kernelname;
675 while (*pos) {
676 if (*pos == '/') *pos = '.';
677 pos++;
678 };
679
680 /* set the machine_id */
681 memcpy(&(bconfig->machine_id), &id_low, 4);
682
683 /* check if the `root' is specified */
684 root_specified = 0;
685 strcpy(bconfig->args, "");
686 for (i = start_args; i < argc; i++) {
687 if (strncmp(argv[i], "root=",5) ==0) root_specified = 1;
688 strcat(bconfig->args, argv[i]);
689 };
690 if (!root_specified) {
691 strcat(bconfig->args, "root=");
692 strcat(bconfig->args, DEFAULT_ROOT);
693 };
694
695 /* mark kernel pointers */
696 bconfig->kernvirtualbase = marks[MARK_START];
697 bconfig->kernphysicalbase = kernel_physical_start;
698 bconfig->kernsize = kernel_free_vm_start - marks[MARK_START];
699 bconfig->ksym_start = marks[MARK_SYM];
700 bconfig->ksym_end = marks[MARK_SYM] + marks[MARK_NSYM];
701
702 /* setup display info */
703 bconfig->display_phys = videomem_start;
704 bconfig->display_start = videomem_start;
705 bconfig->display_size = display_size;
706 bconfig->width = vdu_var(os_MODEVAR_XWIND_LIMIT);
707 bconfig->height = vdu_var(os_MODEVAR_YWIND_LIMIT);
708 bconfig->log2_bpp = vdu_var(os_MODEVAR_LOG2_BPP);
709 /* XXX why? better guessing possible? XXX */
710 bconfig->framerate = 56;
711
712 /* fill in memory info */
713 bconfig->pagesize = nbpp;
714 /* XXX */
715 bconfig->drampages = total_dram_pages + total_podram_pages;
716 bconfig->vrampages = total_vram_pages;
717 /* XXX */
718 bconfig->dramblocks = dram_blocks + podram_blocks;
719 bconfig->vramblocks = vram_blocks;
720
721 for (i = 0; i < dram_blocks; i++) {
722 bconfig->dram[i].address = DRAM_addr[i];
723 bconfig->dram[i].pages = DRAM_pages[i];
724 bconfig->dram[i].flags = PHYSMEM_TYPE_GENERIC;
725 };
726 for (; i < dram_blocks + podram_blocks; i++) {
727 bconfig->dram[i].address = PODRAM_addr[i];
728 bconfig->dram[i].pages = PODRAM_pages[i];
729 bconfig->dram[i].flags = PHYSMEM_TYPE_PROCESSOR_ONLY;
730 };
731 for (i = 0; i < vram_blocks; i++) {
732 bconfig->vram[i].address = VRAM_addr[i];
733 bconfig->vram[i].pages = VRAM_pages[i];
734 bconfig->vram[i].flags = PHYSMEM_TYPE_GENERIC;
735 };
736 }
737
738
739 int main(int argc, char **argv) {
740 int howto, start_args, ret;
741
742 printf("\n\n");
743 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
744 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
745 printf(">> Booting NetBSD/acorn32 on a RiscPC/A7000/NC\n");
746 printf("\n");
747
748 process_args(argc, argv, &howto, booted_file, &start_args);
749
750 printf("Booting %s (howto = 0x%x)\n", booted_file, howto);
751
752 init_datastructures();
753 get_memory_configuration();
754 get_memory_map();
755
756 /*
757 * point to the first free DRAM page guaranteed to be in
758 * strict order up
759 */
760 if (first_mapped_PODRAM_page_index) {
761 free_relocation_page =
762 mem_pages_info + first_mapped_PODRAM_page_index;
763 kernel_physical_start = PODRAM_addr[0];
764 } else {
765 free_relocation_page =
766 mem_pages_info + first_mapped_DRAM_page_index;
767 kernel_physical_start = DRAM_addr[0];
768 };
769
770 printf("\nLoading %s ", booted_file);
771
772 /* first count the kernel to get the markers */
773 ret = loadfile(booted_file, marks, COUNT_KERNEL);
774 if (ret == -1) panic("Kernel load failed"); /* lie to the user ... */
775 close(ret);
776
777 /*
778 * calculate how much the difference is between physical and
779 * virtual space for the kernel
780 */
781 pv_offset = ((u_long) marks[MARK_START] - kernel_physical_start);
782 /* round on a page */
783 kernel_free_vm_start = (marks[MARK_END] + nbpp-1) & ~(nbpp-1);
784
785 /* we seem to be forced to clear the marks() ? */
786 bzero(marks, sizeof(marks[MARK_MAX]));
787
788 /* really load it ! */
789 ret = loadfile(booted_file, marks, LOAD_KERNEL);
790 if (ret == -1) panic("Kernel load failed");
791 close(ret);
792
793 /* finish off the relocation information */
794 create_initial_page_tables();
795 add_initvectors();
796 add_pagetables_at_top();
797 create_configuration(argc, argv, start_args);
798
799 /*
800 * done relocating and creating information, now update and
801 * check the relocation mechanism
802 */
803 prepare_and_check_relocation_system();
804
805 printf("\nStarting at 0x%lx\n", marks[MARK_ENTRY]);
806 printf("Will boot in a few secs due to relocation....\n"
807 "bye bye from RISC OS!");
808
809 /* dismount all filesystems */
810 xosfscontrol_shutdown();
811
812 /* reset devices, well they try to anyway */
813 service_pre_reset();
814
815 start_kernel(
816 /* r0 relocation code page (V) */ relocate_code_page->logical,
817 /* r1 relocation pv offset */
818 relocate_code_page->physical-relocate_code_page->logical,
819 /* r2 configuration structure */ bconfig_new_phys,
820 /* r3 relocation table (P) */
821 relocate_table_pages->physical, /* one piece! */
822 /* r4 L1 page descriptor (P) */ new_L1_pages_phys,
823 /* r5 kernel entry point */ marks[MARK_ENTRY]
824 );
825 return 0;
826 }
827
828
829 ssize_t boot32_read(int f, void *addr, size_t size) {
830 caddr_t fragaddr;
831 size_t fragsize;
832 ssize_t bytes_read, total;
833
834 /* printf("read at %p for %ld bytes\n", addr, size); */
835 total = 0;
836 while (size > 0) {
837 fragsize = nbpp; /* select one page */
838 if (size < nbpp) fragsize = size;/* clip to size left */
839
840 /* get a page for a fragment */
841 fragaddr =
842 (caddr_t)get_relocated_page((u_long) addr - pv_offset,
843 fragsize)->logical;
844
845 bytes_read = read(f, fragaddr, fragsize);
846 if (bytes_read < 0) return bytes_read; /* error! */
847 total += bytes_read; /* account read bytes*/
848
849 /* does this happen? */
850 if (bytes_read < fragsize) return total;
851
852 size -= fragsize; /* advance */
853 addr += fragsize;
854 };
855 return total;
856 }
857
858
859 void *boot32_memcpy(void *dst, const void *src, size_t size) {
860 caddr_t fragaddr;
861 size_t fragsize;
862
863 /* printf("memcpy to %p from %p for %ld bytes\n", dst, src, size); */
864 while (size > 0) {
865 fragsize = nbpp; /* select one page */
866 if (size < nbpp) fragsize = size;/* clip to size left */
867
868 /* get a page for a fragment */
869 fragaddr =
870 (caddr_t) get_relocated_page((u_long) dst - pv_offset,
871 fragsize)->logical;
872 memcpy(fragaddr, src, size);
873
874 src += fragsize; /* account copy */
875 dst += fragsize;
876 size-= fragsize;
877 };
878 return dst;
879 };
880
881
882 void *boot32_memset(void *dst, int c, size_t size) {
883 caddr_t fragaddr;
884 size_t fragsize;
885
886 /* printf("memset %p for %ld bytes with %d\n", dst, size, c); */
887 while (size > 0) {
888 fragsize = nbpp; /* select one page */
889 if (size < nbpp) fragsize = size;/* clip to size left */
890
891 /* get a page for a fragment */
892 fragaddr =
893 (caddr_t) get_relocated_page((u_long) dst - pv_offset,
894 fragsize)->logical;
895 memset(fragaddr, c, fragsize);
896
897 dst += fragsize; /* account memsetting */
898 size-= fragsize;
899
900 };
901 return dst;
902 }
903
904
905 /* This sort routine needs to be re-implemented in either assembler or use other algorithm one day; its slow */
906 void sort_memory_map(void) {
907 int out, in, count;
908 struct page_info *out_page, *in_page, temp_page;
909
910 count = 0;
911 for (out = 0, out_page = mem_pages_info;
912 out < totalpages;
913 out++, out_page++) {
914 for (in = out+1, in_page = out_page+1;
915 in < totalpages;
916 in++, in_page++) {
917 if (in_page->physical < out_page->physical) {
918 memcpy(&temp_page, in_page,
919 sizeof(struct page_info));
920 memcpy(in_page, out_page,
921 sizeof(struct page_info));
922 memcpy(out_page, &temp_page,
923 sizeof(struct page_info));
924 };
925 count++;
926 if ((count & 0x3ffff) == 0) twirl();
927 };
928 };
929 }
930
931
932 struct page_info *get_relocated_page(u_long destination, int size) {
933 struct page_info *page;
934
935 /* get a page for a fragment */
936 page = free_relocation_page;
937 if (free_relocation_page->pagenumber < 0)
938 panic("\n\nOut of pages; increase Wimpslot and try again");
939 reloc_entries++;
940 if (reloc_entries >= MAX_RELOCPAGES)
941 panic("\n\nToo many relocations! What are you loading ??");
942
943 /* record the relocation */
944 *reloc_pos++ = free_relocation_page->physical;
945 *reloc_pos++ = destination;
946 *reloc_pos++ = size;
947 free_relocation_page++; /* advance */
948
949 return page;
950 }
951
952
953 int vdu_var(int var) {
954 int varlist[2], vallist[2];
955
956 varlist[0] = var;
957 varlist[1] = -1;
958 os_read_vdu_variables(varlist, vallist);
959 return vallist[0];
960 }
961
962
963 void twirl(void) {
964 printf("%c%c", "|/-\\"[(int) twirl_cnt], 8);
965 twirl_cnt++;
966 twirl_cnt &= 3;
967 }
968
969
970 void process_args(int argc, char **argv, int *howto, char *file,
971 int *start_args) {
972 int i, j;
973 static char filename[80];
974
975 *howto = 0;
976 *file = NULL; *start_args = 1;
977 for (i = 1; i < argc; i++) {
978 if (argv[i][0] == '-')
979 for (j = 1; argv[i][j]; j++)
980 BOOT_FLAG(argv[i][j], *howto);
981 else {
982 if (*file)
983 *start_args = i;
984 else {
985 strcpy(file, argv[i]);
986 *start_args = i+1;
987 };
988 break;
989 };
990 };
991 if (*file == NULL) {
992 if (*howto & RB_ASKNAME) {
993 printf("boot: ");
994 gets(filename);
995 strcpy(file, filename);
996 } else
997 strcpy(file, "netbsd");
998 };
999 }
1000
1001
1002 char *sprint0(int width, char prefix, char base, int value) {
1003 static char format[50], scrap[50];
1004 char *pos;
1005 int length;
1006
1007 for (pos = format, length = 0; length<width; length++) *pos++ = prefix;
1008 *pos++ = '%';
1009 *pos++ = base;
1010 *pos++ = (char) 0;
1011
1012 sprintf(scrap, format, value);
1013 length = strlen(scrap);
1014
1015 return scrap+length-width;
1016 }
1017
1018