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