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