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