1 /* $NetBSD: boot32.c,v 1.30 2007/03/04 05:59:07 christos 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 extern char end[]; 46 47 /* debugging flags */ 48 int debug = 1; 49 50 51 /* constants */ 52 #define PODRAM_START (512*1024*1024) /* XXX Kinetic cards XXX */ 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 */ 65 char scrap[80], twirl_cnt; /* misc */ 66 char booted_file[80]; 67 68 struct bootconfig *bconfig; /* bootconfig passing */ 69 u_long bconfig_new_phys; /* physical address its bound */ 70 71 /* computer knowledge */ 72 u_int monitor_type, monitor_sync, ioeb_flags, lcd_flags; 73 u_int superio_flags, superio_flags_basic, superio_flags_extra; 74 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 */ 89 90 unsigned char *memory_page_types; /* packed array of 4 bit typeId */ 91 92 u_long *initial_page_tables; /* pagetables to be booted from */ 93 94 95 /* XXX rename *_BLOCKS to MEM_BLOCKS */ 96 /* DRAM/VRAM/ROM/IO info */ 97 /* where the display is */ 98 u_long videomem_start, videomem_pages, display_size; 99 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 */ 107 int vram_blocks, rom_blocks, io_blocks; 108 109 u_long DRAM_addr[DRAM_BLOCKS], DRAM_pages[DRAM_BLOCKS]; 110 /* processor only RAM */ 111 u_long PODRAM_addr[PODRAM_BLOCKS], PODRAM_pages[PODRAM_BLOCKS]; 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]; 115 116 117 /* RISC OS memory pages we claimed */ 118 u_long firstpage, lastpage, totalpages; /* RISC OS pagecounters */ 119 /* RISC OS memory */ 120 char *memory_image, *bottom_memory, *top_memory; 121 122 u_long videomem_start_ro; /* for debugging mainly */ 123 124 /* kernel info */ 125 u_long marks[MARK_MAX]; /* loader mark pointers */ 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; 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); 145 int page_info_cmp(const void *a, const void *); 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); 151 void process_args(int argc, char **argv, int *howto, char *file, 152 int *start_args); 153 154 char *sprint0(int width, char prefix, char base, int value); 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 */ 168 void 169 init_datastructures(void) 170 { 171 172 /* Get number of pages and the memorytablesize */ 173 osmemory_read_arrangement_table_size(&memory_table_size, &nbpp); 174 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; 179 if (memory_image_size <= 256*1024) 180 panic("Insufficient memory"); 181 182 memory_image = alloc(memory_image_size); 183 if (!memory_image) 184 panic("Can't alloc get my memory image ?"); 185 186 bottom_memory = memory_image; 187 top_memory = memory_image + memory_image_size; 188 189 firstpage = ((int)bottom_memory / nbpp) + 1; /* safety */ 190 lastpage = ((int)top_memory / nbpp) - 1; 191 totalpages = lastpage - firstpage; 192 193 printf("Allocated %ld memory pages, each of %d kilobytes.\n\n", 194 totalpages, nbpp>>10 ); 195 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); 202 reloc_instruction_table = alloc(reloc_tablesize); 203 if (!reloc_instruction_table) 204 panic("Can't alloc my relocate instructions pages"); 205 206 reloc_entries = 0; 207 reloc_pos = reloc_instruction_table; 208 *reloc_pos++ = 0; 209 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 */ 214 mem_pages_info = alloc((totalpages + 1)*sizeof(struct page_info)); 215 if (!mem_pages_info) 216 panic("Can't alloc my phys->virt page info"); 217 218 /* 219 * Allocate memory for the memory arrangement table. We use this 220 * structure to retrieve memory page properties to clasify them. 221 */ 222 memory_page_types = alloc(memory_table_size); 223 if (!memory_page_types) 224 panic("Can't alloc my memory page type block"); 225 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"); 233 } 234 235 236 void 237 prepare_and_check_relocation_system(void) 238 { 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; 243 244 /* set the number of relocation entries in the 1st word */ 245 *reloc_instruction_table = reloc_entries; 246 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 */ 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) { 259 src = (u_long)reloc_instruction_table + pages*nbpp; 260 dst = relocate_table_pages[pages].logical; 261 memcpy((void *)dst, (void *)src, nbpp); 262 263 if (pages < relocate_pages - 1) { 264 /* check if next page is sequential physically */ 265 if (relocate_table_pages[pages+1].physical - 266 relocate_table_pages[pages].physical != nbpp) { 267 /* 268 * Non contigunous relocate area -> 269 * try again 270 */ 271 printf("*"); 272 relocate_table_pages += pages; 273 pages = 0; 274 continue; /* while */ 275 } 276 } 277 pages++; 278 } 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 292 printf("shift and check ... "); 293 reloc_entry = reloc_instruction_table + 1; 294 last_src = -1; 295 while (reloc_entry < reloc_pos) { 296 src = reloc_entry[0]; 297 destination = reloc_entry[1]; 298 length = reloc_entry[2]; 299 300 /* paranoia check */ 301 if ((long) (src - last_src) <= 0) 302 printf("relocation sequence challenged -- " 303 "booting might fail "); 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]; 311 found = (destination >= base) && 312 (extend <= base + DRAM_pages[bank]*nbpp); 313 } 314 for (bank = 0; (bank < podram_blocks) && !found; bank++) { 315 base = PODRAM_addr[bank]; 316 found = (destination >= base) && 317 (extend <= base + PODRAM_pages[bank]*nbpp); 318 } 319 if (!found || (extend > top_physdram)) { 320 panic("Internal error: relocating range " 321 "[%lx +%lx => %lx] outside (PO)DRAM banks!", 322 src, length, destination); 323 } 324 325 reloc_entry += 3; 326 } 327 if (reloc_entry != reloc_pos) 328 panic("Relocation instruction table is corrupted"); 329 330 printf("OK!\n"); 331 } 332 333 334 void 335 get_memory_configuration(void) 336 { 337 int loop, current_page_type, page_count, phys_page; 338 int page, count, bank, top_bank, video_bank; 339 int mapped_screen_memory; 340 int one_mb_pages; 341 u_long top; 342 343 printf("Getting memory configuration "); 344 345 osmemory_read_arrangement_table(memory_page_types); 346 347 /* init counters */ 348 bank = vram_blocks = dram_blocks = rom_blocks = io_blocks = 349 podram_blocks = 0; 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) { 358 page = memory_page_types[loop / 2]; /* read twice */ 359 if (loop & 1) page >>= 4; /* take other nibble */ 360 361 /* 362 * bits 0-2 give type, bit3 means the bit page is 363 * allocatable 364 */ 365 page &= 0x7; /* only take bottom 3 bits */ 366 if (page != current_page_type) { 367 /* passed a boundary ... note this block */ 368 /* 369 * splitting in different vars is for 370 * compatability reasons 371 */ 372 switch (current_page_type) { 373 case -1: 374 case 0: 375 break; 376 case osmemory_TYPE_DRAM: 377 if (phys_page < PODRAM_START) { 378 DRAM_addr[dram_blocks] = 379 phys_page * nbpp; 380 DRAM_pages[dram_blocks] = 381 page_count; 382 dram_blocks++; 383 } else { 384 PODRAM_addr[podram_blocks] = 385 phys_page * nbpp; 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); 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)); 413 break; 414 } 415 current_page_type = page; 416 phys_page = loop; 417 page_count = 0; 418 } 419 /* 420 * smallest unit we recognise is one page ... silly 421 * could be upto 64 pages i.e. 256 kb 422 */ 423 page_count += 1; 424 loop += 1; 425 if ((loop & 31) == 0) twirl(); 426 } 427 428 printf(" \n\n"); 429 430 if (VRAM_pages[0] == 0) { 431 /* map DRAM as video memory */ 432 display_size = 433 vdu_var(os_VDUVAR_TOTAL_SCREEN_SIZE) & ~(nbpp-1); 434 #if 0 435 mapped_screen_memory = 1024 * 1024; /* max allowed on RiscPC */ 436 videomem_pages = (mapped_screen_memory / nbpp); 437 videomem_start = DRAM_addr[0]; 438 DRAM_addr[0] += videomem_pages * nbpp; 439 DRAM_pages[0] -= videomem_pages; 440 #else 441 mapped_screen_memory = display_size; 442 videomem_pages = mapped_screen_memory / nbpp; 443 one_mb_pages = (1024*1024)/nbpp; 444 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) 457 panic("Weird memory configuration found; please " 458 "contact acorn32 portmaster."); 459 460 /* split off the top 1Mb */ 461 DRAM_addr [top_bank+1] = DRAM_addr[top_bank] + 462 (DRAM_pages[top_bank] - one_mb_pages)*nbpp; 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 */ 468 videomem_start = DRAM_addr[video_bank] + 469 (DRAM_pages[video_bank] - videomem_pages)*nbpp; 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--; 477 } 478 #endif 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; 485 } 486 487 if (mapped_screen_memory) { 488 printf("Used %d kb DRAM ", mapped_screen_memory / 1024); 489 printf("at 0x%s for video memory\n", 490 sprint0(8,'0','x', videomem_start)); 491 } 492 493 /* find top of (PO)DRAM pages */ 494 top_physdram = 0; 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; 498 } 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; 502 } 503 if (top_physdram == 0) 504 panic("reality check: No DRAM in this machine?"); 505 if (((top_physdram >> 20) << 20) != top_physdram) 506 panic("Top is not not aligned on a Mb; " 507 "remove very small DIMMS?"); 508 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); 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)); 517 } 518 519 for (count = 0; count < io_blocks; count++) { 520 printf("Found I/O (%d)", count); 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)); 524 } 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); 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)); 534 } 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); 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)); 543 } 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); 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)); 552 } 553 } 554 555 556 void 557 get_memory_map(void) 558 { 559 struct page_info *page_info; 560 int page, inout; 561 int phys_addr; 562 563 printf("\nGetting actual memorymapping"); 564 for (page = 0, page_info = mem_pages_info; 565 page < totalpages; 566 page++, page_info++) { 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 */ 571 *((int *)page_info->logical) = 0; 572 } 573 /* close list */ 574 page_info->pagenumber = -1; 575 576 inout = osmemory_GIVEN_LOG_ADDR | osmemory_RETURN_PAGE_NO | 577 osmemory_RETURN_PHYS_ADDR; 578 osmemory_page_op(inout, mem_pages_info, totalpages); 579 580 printf(" ; sorting "); 581 qsort(mem_pages_info, totalpages, sizeof(struct page_info), 582 &page_info_cmp); 583 printf(".\n"); 584 585 /* 586 * get the first DRAM index and show the physical memory 587 * fragments we got 588 */ 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) { 596 if (first_mapped_DRAM_page_index < 0 && 597 phys_addr >= DRAM_addr[0]) 598 first_mapped_DRAM_page_index = page; 599 if (first_mapped_PODRAM_page_index < 0 && 600 phys_addr >= PODRAM_addr[0]) 601 first_mapped_PODRAM_page_index = page; 602 page++; 603 phys_addr = mem_pages_info[page].physical; 604 } 605 printf("-0x%x] ", phys_addr + nbpp -1); 606 } 607 printf("\n\n"); 608 if (first_mapped_PODRAM_page_index < 0 && PODRAM_addr[0]) 609 panic("Found no (S)DRAM mapped in the bootloader"); 610 if (first_mapped_DRAM_page_index < 0) 611 panic("No DRAM mapped in the bootloader"); 612 } 613 614 615 void 616 create_initial_page_tables(void) 617 { 618 u_long page, section, addr, kpage; 619 620 /* mark a section by the following bits and domain 0, AP=01, CB=0 */ 621 /* A P C B section 622 domain */ 623 section = (0<<11) | (1<<10) | (0<<3) | (0<<2) | (1<<4) | (1<<1) | 624 (0) | (0 << 5); 625 626 /* first of all a full 1:1 mapping */ 627 for (page = 0; page < 4*1024; page++) 628 initial_page_tables[page] = (page<<20) | section; 629 630 /* 631 * video memory is mapped 1:1 in the DRAM section or in VRAM 632 * section 633 * 634 * map 1Mb from top of DRAM memory to bottom 1Mb of virtual memmap 635 */ 636 top_1Mb_dram = (((top_physdram - 1024*1024) >> 20) << 20); 637 638 initial_page_tables[0] = top_1Mb_dram | section; 639 640 /* 641 * map 16 Mb of kernel space to KERNEL_BASE 642 * i.e. marks[KERNEL_START] 643 */ 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; 648 } 649 } 650 651 652 void 653 add_pagetables_at_top(void) 654 { 655 int page; 656 u_long src, dst, fragaddr; 657 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 */ 660 new_L1_pages_phys = top_physdram - 4 * nbpp; 661 662 /* 663 * If the L1 page tables are not 16 kb aligned, adjust base 664 * until it is 665 */ 666 while (new_L1_pages_phys & (16*1024-1)) 667 new_L1_pages_phys -= nbpp; 668 if (new_L1_pages_phys & (16*1024-1)) 669 panic("Paranoia : L1 pages not on 16Kb boundary"); 670 671 dst = new_L1_pages_phys; 672 src = (u_long)initial_page_tables; 673 674 for (page = 0; page < 4; page++) { 675 /* get a page for a fragment */ 676 fragaddr = get_relocated_page(dst, nbpp)->logical; 677 memcpy((void *)fragaddr, (void *)src, nbpp); 678 679 src += nbpp; 680 dst += nbpp; 681 } 682 } 683 684 685 void 686 add_initvectors(void) 687 { 688 u_long *pos; 689 u_long vectoraddr, count; 690 691 /* the top 1Mb of the physical DRAM pages is mapped at address 0 */ 692 vectoraddr = get_relocated_page(top_1Mb_dram, nbpp)->logical; 693 694 /* fill the vectors with `movs pc, lr' opcodes */ 695 pos = (u_long *)vectoraddr; memset(pos, 0, nbpp); 696 for (count = 0; count < 128; count++) *pos++ = 0xE1B0F00E; 697 } 698 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 } 716 717 void 718 create_configuration(int argc, char **argv, int start_args) 719 { 720 int i, root_specified, id_low, id_high; 721 char *pos; 722 723 bconfig_new_phys = kernel_free_vm_start - pv_offset; 724 bconfig_page = get_relocated_page(bconfig_new_phys, nbpp); 725 bconfig = (struct bootconfig *)(bconfig_page->logical); 726 kernel_free_vm_start += nbpp; 727 728 /* get some miscelanious info for the bootblock */ 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); 733 os_readsysinfo_unique_id(&id_low, &id_high); 734 735 /* fill in the bootconfig *bconfig structure : generic version II */ 736 memset(bconfig, 0, sizeof(bconfig)); 737 bconfig->magic = BOOTCONFIG_MAGIC; 738 bconfig->version = BOOTCONFIG_VERSION; 739 strcpy(bconfig->kernelname, booted_file); 740 741 /* 742 * get the kernel base name and update the RiscOS name to a 743 * Unix name 744 */ 745 i = strlen(booted_file); 746 while (i >= 0 && booted_file[i] != '.') i--; 747 if (i) { 748 strcpy(bconfig->kernelname, "/"); 749 strcat(bconfig->kernelname, booted_file+i+1); 750 } 751 752 pos = bconfig->kernelname+1; 753 while (*pos) { 754 if (*pos == '/') *pos = '.'; 755 pos++; 756 } 757 758 /* set the machine_id */ 759 memcpy(&(bconfig->machine_id), &id_low, 4); 760 761 /* check if the `root' is specified */ 762 root_specified = 0; 763 strcpy(bconfig->args, ""); 764 for (i = start_args; i < argc; i++) { 765 if (strncmp(argv[i], "root=",5) ==0) root_specified = 1; 766 strcat(bconfig->args, argv[i]); 767 } 768 if (!root_specified) { 769 strcat(bconfig->args, "root="); 770 strcat(bconfig->args, DEFAULT_ROOT); 771 } 772 773 /* mark kernel pointers */ 774 bconfig->kernvirtualbase = marks[MARK_START]; 775 bconfig->kernphysicalbase = kernel_physical_start; 776 bconfig->kernsize = kernel_free_vm_start - 777 marks[MARK_START]; 778 bconfig->ksym_start = marks[MARK_SYM]; 779 bconfig->ksym_end = marks[MARK_SYM] + marks[MARK_NSYM]; 780 781 /* setup display info */ 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); 788 bconfig->framerate = vsync_rate(); 789 790 /* fill in memory info */ 791 bconfig->pagesize = nbpp; 792 bconfig->drampages = total_dram_pages + 793 total_podram_pages; /* XXX */ 794 bconfig->vrampages = total_vram_pages; 795 bconfig->dramblocks = dram_blocks + podram_blocks; /*XXX*/ 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; 802 } 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; 807 } 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; 812 } 813 } 814 815 816 int 817 main(int argc, char **argv) 818 { 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 835 /* 836 * point to the first free DRAM page guaranteed to be in 837 * strict order up 838 */ 839 if (podram_blocks != 0) { 840 free_relocation_page = 841 mem_pages_info + first_mapped_PODRAM_page_index; 842 kernel_physical_start = PODRAM_addr[0]; 843 } else { 844 free_relocation_page = 845 mem_pages_info + first_mapped_DRAM_page_index; 846 kernel_physical_start = DRAM_addr[0]; 847 } 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); 853 if (ret == -1) panic("Kernel load failed"); /* lie to the user ... */ 854 close(ret); 855 856 /* 857 * calculate how much the difference is between physical and 858 * virtual space for the kernel 859 */ 860 pv_offset = ((u_long)marks[MARK_START] - kernel_physical_start); 861 /* round on a page */ 862 kernel_free_vm_start = (marks[MARK_END] + nbpp-1) & ~(nbpp-1); 863 864 /* we seem to be forced to clear the marks[] ? */ 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 878 /* 879 * done relocating and creating information, now update and 880 * check the relocation mechanism 881 */ 882 prepare_and_check_relocation_system(); 883 884 printf("\nStarting at 0x%lx\n", marks[MARK_ENTRY]); 885 printf("Will boot in a few secs due to relocation....\n" 886 "bye bye from RISC OS!"); 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, 896 /* r1 relocation pv offset */ 897 relocate_code_page->physical-relocate_code_page->logical, 898 /* r2 configuration structure */ bconfig_new_phys, 899 /* r3 relocation table (P) */ 900 relocate_table_pages->physical, /* one piece! */ 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 908 ssize_t 909 boot32_read(int f, void *addr, size_t size) 910 { 911 void *fragaddr; 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) { 918 fragsize = nbpp; /* select one page */ 919 if (size < nbpp) fragsize = size;/* clip to size left */ 920 921 /* get a page for a fragment */ 922 fragaddr = (void *)get_relocated_page((u_long) addr - 923 pv_offset, fragsize)->logical; 924 925 bytes_read = read(f, fragaddr, fragsize); 926 if (bytes_read < 0) return bytes_read; /* error! */ 927 total += bytes_read; /* account read bytes */ 928 929 if (bytes_read < fragsize) 930 return total; /* does this happen? */ 931 932 size -= fragsize; /* advance */ 933 addr += fragsize; 934 } 935 return total; 936 } 937 938 939 void * 940 boot32_memcpy(void *dst, const void *src, size_t size) 941 { 942 void *fragaddr; 943 size_t fragsize; 944 945 /* printf("memcpy to %p from %p for %ld bytes\n", dst, src, size); */ 946 while (size > 0) { 947 fragsize = nbpp; /* select one page */ 948 if (size < nbpp) fragsize = size;/* clip to size left */ 949 950 /* get a page for a fragment */ 951 fragaddr = (void *)get_relocated_page((u_long) dst - 952 pv_offset, fragsize)->logical; 953 memcpy(fragaddr, src, size); 954 955 src += fragsize; /* account copy */ 956 dst += fragsize; 957 size-= fragsize; 958 } 959 return dst; 960 } 961 962 963 void * 964 boot32_memset(void *dst, int c, size_t size) 965 { 966 void *fragaddr; 967 size_t fragsize; 968 969 /* printf("memset %p for %ld bytes with %d\n", dst, size, c); */ 970 while (size > 0) { 971 fragsize = nbpp; /* select one page */ 972 if (size < nbpp) fragsize = size;/* clip to size left */ 973 974 /* get a page for a fragment */ 975 fragaddr = (void *)get_relocated_page((u_long)dst - pv_offset, 976 fragsize)->logical; 977 memset(fragaddr, c, fragsize); 978 979 dst += fragsize; /* account memsetting */ 980 size-= fragsize; 981 982 } 983 return dst; 984 } 985 986 987 /* We can rely on the fact that two entries never have identical ->physical */ 988 int 989 page_info_cmp(const void *a, const void *b) 990 { 991 992 return (((struct page_info *)a)->physical < 993 ((struct page_info *)b)->physical) ? -1 : 1; 994 } 995 996 struct page_info * 997 get_relocated_page(u_long destination, int size) 998 { 999 struct page_info *page; 1000 1001 /* get a page for a fragment */ 1002 page = free_relocation_page; 1003 if (free_relocation_page->pagenumber < 0) panic("\n\nOut of pages"); 1004 reloc_entries++; 1005 if (reloc_entries >= MAX_RELOCPAGES) 1006 panic("\n\nToo many relocations! What are you loading ??"); 1007 1008 /* record the relocation */ 1009 *reloc_pos++ = free_relocation_page->physical; 1010 *reloc_pos++ = destination; 1011 *reloc_pos++ = size; 1012 free_relocation_page++; /* advance */ 1013 1014 return page; 1015 } 1016 1017 1018 int 1019 vdu_var(int var) 1020 { 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 1030 void 1031 twirl(void) 1032 { 1033 1034 printf("%c%c", "|/-\\"[(int) twirl_cnt], 8); 1035 twirl_cnt++; 1036 twirl_cnt &= 3; 1037 } 1038 1039 1040 void 1041 process_args(int argc, char **argv, int *howto, char *file, int *start_args) 1042 { 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; 1058 } 1059 break; 1060 } 1061 } 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"); 1069 } 1070 } 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 1091