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