Home | History | Annotate | Line # | Download | only in boot32
      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, &section, &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