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