1 /* $NetBSD: boot32.c,v 1.36 2009/03/18 16:00:08 cegger Exp $ */
4 * Copyright (c) 2002 Reinoud Zandijk
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Thanks a bunch for Ben's framework for the bootloader and its suporting
30 * libs. This file tries to actually boot NetBSD/acorn32 !
32 * XXX eventually to be partly merged back with boot26 ? XXX
35 #include <lib/libsa/stand.h>
36 #include <lib/libsa/loadfile.h>
37 #include <lib/libkern/libkern.h>
38 #include <riscoscalls.h>
40 #include <sys/boot_flag.h>
41 #include <machine/vmparam.h>
42 #include <arm/arm32/pte.h>
43 #include <machine/bootconfig.h>
52 #define PODRAM_START (512*1024*1024) /* XXX Kinetic cards XXX */
54 #define MAX_RELOCPAGES 4096
56 #define DEFAULT_ROOT "/dev/wd0a"
59 #define IO_BLOCKS 16 /* move these to the bootloader structure? */
61 #define PODRAM_BLOCKS 16
64 /* booter variables */
65 char scrap
[80], twirl_cnt
; /* misc */
68 struct bootconfig
*bconfig
; /* bootconfig passing */
69 u_long bconfig_new_phys
; /* physical address its bound */
71 /* computer knowledge */
72 u_int monitor_type
, monitor_sync
, ioeb_flags
, lcd_flags
;
73 u_int superio_flags
, superio_flags_basic
, superio_flags_extra
;
76 int nbpp
, memory_table_size
, memory_image_size
;
78 u_long reloc_tablesize
, *reloc_instruction_table
;
79 u_long
*reloc_pos
; /* current empty entry */
80 int reloc_entries
; /* number of relocations */
81 int first_mapped_DRAM_page_index
; /* offset in RISC OS blob */
82 int first_mapped_PODRAM_page_index
;/* offset in RISC OS blob */
84 struct page_info
*mem_pages_info
; /* {nr, virt, phys}* */
85 struct page_info
*free_relocation_page
; /* points to the page_info chain*/
86 struct page_info
*relocate_code_page
; /* points to the copied code */
87 struct page_info
*bconfig_page
; /* page for passing on settings */
89 unsigned char *memory_page_types
; /* packed array of 4 bit typeId */
91 u_long
*initial_page_tables
; /* pagetables to be booted from */
94 /* XXX rename *_BLOCKS to MEM_BLOCKS */
95 /* DRAM/VRAM/ROM/IO info */
96 /* where the display is */
97 u_long videomem_start
, videomem_pages
, display_size
;
99 u_long pv_offset
, top_physdram
; /* kernel_base - phys. diff */
100 u_long top_1Mb_dram
; /* the lower mapped top 1Mb */
101 u_long new_L1_pages_phys
; /* physical address of L1 pages */
103 /* for bootconfig passing */
104 u_long total_podram_pages
, total_dram_pages
, total_vram_pages
;
105 int dram_blocks
, podram_blocks
; /* number of mem. objects/type */
106 int vram_blocks
, rom_blocks
, io_blocks
;
108 u_long DRAM_addr
[DRAM_BLOCKS
], DRAM_pages
[DRAM_BLOCKS
];
109 /* processor only RAM */
110 u_long PODRAM_addr
[PODRAM_BLOCKS
], PODRAM_pages
[PODRAM_BLOCKS
];
111 u_long VRAM_addr
[VRAM_BLOCKS
], VRAM_pages
[VRAM_BLOCKS
];
112 u_long ROM_addr
[ROM_BLOCKS
], ROM_pages
[ROM_BLOCKS
];
113 u_long IO_addr
[IO_BLOCKS
], IO_pages
[IO_BLOCKS
];
116 /* RISC OS memory pages we claimed */
117 u_long firstpage
, lastpage
, totalpages
; /* RISC OS pagecounters */
119 char *memory_image
, *bottom_memory
, *top_memory
;
122 u_long marks
[MARK_MAX
]; /* loader mark pointers */
123 u_long kernel_physical_start
; /* where does it get relocated */
124 u_long kernel_physical_maxsize
; /* Max allowed size of kernel */
125 u_long kernel_free_vm_start
; /* where does the free VM start */
126 /* some free space to mess with */
127 u_long scratch_virtualbase
, scratch_physicalbase
;
130 /* bootprogram identifiers */
131 extern const char bootprog_rev
[];
132 extern const char bootprog_name
[];
133 extern const char bootprog_date
[];
134 extern const char bootprog_maker
[];
137 /* predefines / prototypes */
138 void init_datastructures(void);
139 void get_memory_configuration(void);
140 void get_memory_map(void);
141 void create_initial_page_tables(void);
142 void add_pagetables_at_top(void);
143 int page_info_cmp(const void *a
, const void *);
144 void add_initvectors(void);
145 void create_configuration(int argc
, char **argv
, int start_args
);
146 void prepare_and_check_relocation_system(void);
147 void compact_relocations(void);
150 void process_args(int argc
, char **argv
, int *howto
, char *file
,
153 char *sprint0(int width
, char prefix
, char base
, int value
);
154 struct page_info
*get_relocated_page(u_long destination
, int size
);
156 extern void start_kernel(
157 int relocate_code_page
,
158 int relocation_pv_offset
,
159 int configuration_structure_in_flat_physical_space
,
160 int virtual_address_relocation_table
,
161 int physical_address_of_new_L1_pages
,
162 int kernel_entry_point
166 /* the loader itself */
168 init_datastructures(void)
171 /* Get number of pages and the memorytablesize */
172 osmemory_read_arrangement_table_size(&memory_table_size
, &nbpp
);
174 /* Allocate 99% - (small fixed amount) of the heap for memory_image */
175 memory_image_size
= (int)HIMEM
- (int)end
- 512 * 1024;
176 memory_image_size
/= 100;
177 memory_image_size
*= 99;
178 if (memory_image_size
<= 256*1024)
179 panic("Insufficient memory");
181 memory_image
= alloc(memory_image_size
);
183 panic("Can't alloc get my memory image ?");
185 bottom_memory
= memory_image
;
186 top_memory
= memory_image
+ memory_image_size
;
188 firstpage
= ((int)bottom_memory
/ nbpp
) + 1; /* safety */
189 lastpage
= ((int)top_memory
/ nbpp
) - 1;
190 totalpages
= lastpage
- firstpage
;
192 printf("Allocated %ld memory pages, each of %d kilobytes.\n\n",
193 totalpages
, nbpp
>>10 );
196 * Setup the relocation table. Its a simple array of 3 * 32 bit
197 * entries. The first word in the array is the number of relocations
200 reloc_tablesize
= (MAX_RELOCPAGES
+1)*3*sizeof(u_long
);
201 reloc_instruction_table
= alloc(reloc_tablesize
);
202 if (!reloc_instruction_table
)
203 panic("Can't alloc my relocate instructions pages");
206 reloc_pos
= reloc_instruction_table
;
210 * Set up the memory translation info structure. We need to allocate
211 * one more for the end of list marker. See get_memory_map.
213 mem_pages_info
= alloc((totalpages
+ 1)*sizeof(struct page_info
));
215 panic("Can't alloc my phys->virt page info");
218 * Allocate memory for the memory arrangement table. We use this
219 * structure to retrieve memory page properties to clasify them.
221 memory_page_types
= alloc(memory_table_size
);
222 if (!memory_page_types
)
223 panic("Can't alloc my memory page type block");
226 * Initial page tables is 16 kb per definition since only sections are
229 initial_page_tables
= alloc(16*1024);
230 if (!initial_page_tables
)
231 panic("Can't alloc my initial page tables");
235 compact_relocations(void)
237 u_long
*reloc_entry
, current_length
, length
;
238 u_long src
, destination
, current_src
, current_destination
;
239 u_long
*current_entry
;
241 current_entry
= reloc_entry
= reloc_instruction_table
+ 1;
244 current_src
= reloc_entry
[0];
245 current_destination
= reloc_entry
[1];
246 current_length
= reloc_entry
[2];
249 while (reloc_entry
< reloc_pos
) {
250 src
= reloc_entry
[0];
251 destination
= reloc_entry
[1];
252 length
= reloc_entry
[2];
254 if (src
== (current_src
+ current_length
) &&
255 destination
== (current_destination
+ current_length
)) {
257 current_length
+= length
;
259 /* nothing else to do, so save the length */
260 current_entry
[2] = current_length
;
261 /* fill in next entry */
263 current_src
= current_entry
[0] = src
;
264 current_destination
= current_entry
[1] = destination
;
265 current_length
= length
;
269 /* save last length */
270 current_entry
[2] = current_length
;
273 /* workout new count of entries */
274 length
= current_entry
- (reloc_instruction_table
+ 1);
275 printf("Compacted relocations from %d entries to %ld\n",
276 reloc_entries
, length
/3);
278 /* update table to reflect new size */
279 reloc_entries
= length
/3;
280 reloc_instruction_table
[0] = length
/3;
281 reloc_pos
= current_entry
;
285 get_memory_configuration(void)
287 int loop
, current_page_type
, page_count
, phys_page
;
288 int page
, count
, bank
, top_bank
, video_bank
;
289 int mapped_screen_memory
;
293 printf("Getting memory configuration ");
295 osmemory_read_arrangement_table(memory_page_types
);
298 bank
= vram_blocks
= dram_blocks
= rom_blocks
= io_blocks
=
301 current_page_type
= -1;
302 phys_page
= 0; /* physical address in pages */
303 page_count
= 0; /* page counter in this block */
304 loop
= 0; /* loop variable over entries */
306 /* iterating over a packed array of 2 page types/byte i.e. 8 kb/byte */
307 while (loop
< 2*memory_table_size
) {
308 page
= memory_page_types
[loop
/ 2]; /* read twice */
309 if (loop
& 1) page
>>= 4; /* take other nibble */
312 * bits 0-2 give type, bit3 means the bit page is
315 page
&= 0x7; /* only take bottom 3 bits */
316 if (page
!= current_page_type
) {
317 /* passed a boundary ... note this block */
319 * splitting in different vars is for
320 * compatability reasons
322 switch (current_page_type
) {
326 case osmemory_TYPE_DRAM
:
327 if ((phys_page
* nbpp
)< PODRAM_START
) {
328 DRAM_addr
[dram_blocks
] =
330 DRAM_pages
[dram_blocks
] =
334 PODRAM_addr
[podram_blocks
] =
336 PODRAM_pages
[podram_blocks
] =
341 case osmemory_TYPE_VRAM
:
342 VRAM_addr
[vram_blocks
] = phys_page
* nbpp
;
343 VRAM_pages
[vram_blocks
] = page_count
;
346 case osmemory_TYPE_ROM
:
347 ROM_addr
[rom_blocks
] = phys_page
* nbpp
;
348 ROM_pages
[rom_blocks
] = page_count
;
351 case osmemory_TYPE_IO
:
352 IO_addr
[io_blocks
] = phys_page
* nbpp
;
353 IO_pages
[io_blocks
] = page_count
;
357 printf("WARNING : found unknown "
358 "memory object %d ", current_page_type
);
360 sprint0(8,'0','x', phys_page
* nbpp
));
361 printf(" for %s k\n",
362 sprint0(5,' ','d', (page_count
*nbpp
)>>10));
365 current_page_type
= page
;
370 * smallest unit we recognise is one page ... silly
371 * could be upto 64 pages i.e. 256 kb
375 if ((loop
& 31) == 0) twirl();
380 if (VRAM_pages
[0] == 0) {
381 /* map DRAM as video memory */
383 vdu_var(os_VDUVAR_TOTAL_SCREEN_SIZE
) & ~(nbpp
-1);
385 mapped_screen_memory
= 1024 * 1024; /* max allowed on RiscPC */
386 videomem_pages
= (mapped_screen_memory
/ nbpp
);
387 videomem_start
= DRAM_addr
[0];
388 DRAM_addr
[0] += videomem_pages
* nbpp
;
389 DRAM_pages
[0] -= videomem_pages
;
391 mapped_screen_memory
= display_size
;
392 videomem_pages
= mapped_screen_memory
/ nbpp
;
393 one_mb_pages
= (1024*1024)/nbpp
;
396 * OK... we need one Mb at the top for compliance with current
397 * kernel structure. This ought to be abolished one day IMHO.
398 * Also we have to take care that the kernel needs to be in
399 * DRAM0a and even has to start there.
400 * XXX one Mb simms are the smallest supported XXX
402 top_bank
= dram_blocks
-1;
403 video_bank
= top_bank
;
404 if (DRAM_pages
[top_bank
] == one_mb_pages
) video_bank
--;
406 if (DRAM_pages
[video_bank
] < videomem_pages
)
407 panic("Weird memory configuration found; please "
408 "contact acorn32 portmaster.");
410 /* split off the top 1Mb */
411 DRAM_addr
[top_bank
+1] = DRAM_addr
[top_bank
] +
412 (DRAM_pages
[top_bank
] - one_mb_pages
)*nbpp
;
413 DRAM_pages
[top_bank
+1] = one_mb_pages
;
414 DRAM_pages
[top_bank
] -= one_mb_pages
;
417 /* Map video memory at the end of the choosen DIMM */
418 videomem_start
= DRAM_addr
[video_bank
] +
419 (DRAM_pages
[video_bank
] - videomem_pages
)*nbpp
;
420 DRAM_pages
[video_bank
] -= videomem_pages
;
423 if (DRAM_pages
[top_bank
] == 0) {
424 DRAM_addr
[top_bank
] = DRAM_addr
[top_bank
+1];
425 DRAM_pages
[top_bank
] = DRAM_pages
[top_bank
+1];
431 mapped_screen_memory
= 0;
432 videomem_start
= VRAM_addr
[0];
433 videomem_pages
= VRAM_pages
[0];
434 display_size
= videomem_pages
* nbpp
;
437 if (mapped_screen_memory
) {
438 printf("Used %d kb DRAM ", mapped_screen_memory
/ 1024);
439 printf("at 0x%s for video memory\n",
440 sprint0(8,'0','x', videomem_start
));
443 /* find top of (PO)DRAM pages */
445 for (loop
= 0; loop
< podram_blocks
; loop
++) {
446 top
= PODRAM_addr
[loop
] + PODRAM_pages
[loop
]*nbpp
;
447 if (top
> top_physdram
) top_physdram
= top
;
449 for (loop
= 0; loop
< dram_blocks
; loop
++) {
450 top
= DRAM_addr
[loop
] + DRAM_pages
[loop
]*nbpp
;
451 if (top
> top_physdram
) top_physdram
= top
;
453 if (top_physdram
== 0)
454 panic("reality check: No DRAM in this machine?");
455 if (((top_physdram
>> 20) << 20) != top_physdram
)
456 panic("Top is not not aligned on a Mb; "
457 "remove very small DIMMS?");
459 /* pretty print the individual page types */
460 for (count
= 0; count
< rom_blocks
; count
++) {
461 printf("Found ROM (%d)", count
);
462 printf(" at 0x%s", sprint0(8,'0','x', ROM_addr
[count
]));
463 printf(" for %s k\n",
464 sprint0(5,' ','d', (ROM_pages
[count
]*nbpp
)>>10));
467 for (count
= 0; count
< io_blocks
; count
++) {
468 printf("Found I/O (%d)", count
);
469 printf(" at 0x%s", sprint0(8,'0','x', IO_addr
[count
]));
470 printf(" for %s k\n",
471 sprint0(5,' ','d', (IO_pages
[count
]*nbpp
)>>10));
474 /* for DRAM/VRAM also count the number of pages */
475 total_dram_pages
= 0;
476 for (count
= 0; count
< dram_blocks
; count
++) {
477 total_dram_pages
+= DRAM_pages
[count
];
478 printf("Found DRAM (%d)", count
);
479 printf(" at 0x%s", sprint0(8,'0','x', DRAM_addr
[count
]));
480 printf(" for %s k\n",
481 sprint0(5,' ','d', (DRAM_pages
[count
]*nbpp
)>>10));
484 total_vram_pages
= 0;
485 for (count
= 0; count
< vram_blocks
; count
++) {
486 total_vram_pages
+= VRAM_pages
[count
];
487 printf("Found VRAM (%d)", count
);
488 printf(" at 0x%s", sprint0(8,'0','x', VRAM_addr
[count
]));
489 printf(" for %s k\n",
490 sprint0(5,' ','d', (VRAM_pages
[count
]*nbpp
)>>10));
493 total_podram_pages
= 0;
494 for (count
= 0; count
< podram_blocks
; count
++) {
495 total_podram_pages
+= PODRAM_pages
[count
];
496 printf("Found Processor only (S)DRAM (%d)", count
);
497 printf(" at 0x%s", sprint0(8,'0','x', PODRAM_addr
[count
]));
498 printf(" for %s k\n",
499 sprint0(5,' ','d', (PODRAM_pages
[count
]*nbpp
)>>10));
507 struct page_info
*page_info
;
511 printf("\nGetting actual memorymapping");
512 for (page
= 0, page_info
= mem_pages_info
;
514 page
++, page_info
++) {
515 page_info
->pagenumber
= 0; /* not used */
516 page_info
->logical
= (firstpage
+ page
) * nbpp
;
517 page_info
->physical
= 0; /* result comes here */
518 /* to avoid triggering a `bug' in RISC OS 4, page it in */
519 *((int *)page_info
->logical
) = 0;
522 page_info
->pagenumber
= -1;
524 inout
= osmemory_GIVEN_LOG_ADDR
| osmemory_RETURN_PAGE_NO
|
525 osmemory_RETURN_PHYS_ADDR
;
526 osmemory_page_op(inout
, mem_pages_info
, totalpages
);
528 printf(" ; sorting ");
529 qsort(mem_pages_info
, totalpages
, sizeof(struct page_info
),
534 * get the first DRAM index and show the physical memory
537 printf("\nFound physical memory blocks :\n");
538 first_mapped_DRAM_page_index
= -1;
539 first_mapped_PODRAM_page_index
= -1;
540 for (page
=0; page
< totalpages
; page
++) {
541 phys_addr
= mem_pages_info
[page
].physical
;
542 printf("[0x%x", phys_addr
);
543 while (mem_pages_info
[page
+1].physical
- phys_addr
== nbpp
) {
544 if (first_mapped_DRAM_page_index
< 0 &&
545 phys_addr
>= DRAM_addr
[0])
546 first_mapped_DRAM_page_index
= page
;
547 if (first_mapped_PODRAM_page_index
< 0 &&
548 phys_addr
>= PODRAM_addr
[0])
549 first_mapped_PODRAM_page_index
= page
;
551 phys_addr
= mem_pages_info
[page
].physical
;
553 printf("-0x%x] ", phys_addr
+ nbpp
-1);
557 if (first_mapped_PODRAM_page_index
< 0 && PODRAM_addr
[0])
558 panic("Found no (S)DRAM mapped in the bootloader");
559 if (first_mapped_DRAM_page_index
< 0)
560 panic("No DRAM mapped in the bootloader");
565 create_initial_page_tables(void)
567 u_long page
, section
, addr
, kpage
;
569 /* mark a section by the following bits and domain 0, AP=01, CB=0 */
572 section
= (0<<11) | (1<<10) | (0<<3) | (0<<2) | (1<<4) | (1<<1) |
575 /* first of all a full 1:1 mapping */
576 for (page
= 0; page
< 4*1024; page
++)
577 initial_page_tables
[page
] = (page
<<20) | section
;
580 * video memory is mapped 1:1 in the DRAM section or in VRAM
583 * map 1Mb from top of DRAM memory to bottom 1Mb of virtual memmap
585 top_1Mb_dram
= (((top_physdram
- 1024*1024) >> 20) << 20);
587 initial_page_tables
[0] = top_1Mb_dram
| section
;
590 * map 16 Mb of kernel space to KERNEL_BASE
591 * i.e. marks[KERNEL_START]
593 for (page
= 0; page
< 16; page
++) {
594 addr
= (kernel_physical_start
>> 20) + page
;
595 kpage
= (marks
[MARK_START
] >> 20) + page
;
596 initial_page_tables
[kpage
] = (addr
<< 20) | section
;
602 add_pagetables_at_top(void)
605 u_long src
, dst
, fragaddr
;
607 /* Special : destination must be on a 16 Kb boundary */
608 /* get 4 pages on the top of the physical memory and copy PT's in it */
609 new_L1_pages_phys
= top_physdram
- 4 * nbpp
;
612 * If the L1 page tables are not 16 kb aligned, adjust base
615 while (new_L1_pages_phys
& (16*1024-1))
616 new_L1_pages_phys
-= nbpp
;
617 if (new_L1_pages_phys
& (16*1024-1))
618 panic("Paranoia : L1 pages not on 16Kb boundary");
620 dst
= new_L1_pages_phys
;
621 src
= (u_long
)initial_page_tables
;
623 for (page
= 0; page
< 4; page
++) {
624 /* get a page for a fragment */
625 fragaddr
= get_relocated_page(dst
, nbpp
)->logical
;
626 memcpy((void *)fragaddr
, (void *)src
, nbpp
);
635 add_initvectors(void)
638 u_long vectoraddr
, count
;
640 /* the top 1Mb of the physical DRAM pages is mapped at address 0 */
641 vectoraddr
= get_relocated_page(top_1Mb_dram
, nbpp
)->logical
;
643 /* fill the vectors with `movs pc, lr' opcodes */
644 pos
= (u_long
*)vectoraddr
; memset(pos
, 0, nbpp
);
645 for (count
= 0; count
< 128; count
++) *pos
++ = 0xE1B0F00E;
649 * Work out the display's vertical sync rate. One might hope that there
650 * would be a simpler way than by counting vsync interrupts for a second,
651 * but if there is, I can't find it.
659 count0
= osbyte_read(osbyte_VAR_VSYNC_TIMER
);
660 time0
= os_read_monotonic_time();
661 while (os_read_monotonic_time() - time0
< 100)
663 return (u_int8_t
)(count0
- osbyte_read(osbyte_VAR_VSYNC_TIMER
));
667 create_configuration(int argc
, char **argv
, int start_args
)
669 int i
, root_specified
, id_low
, id_high
;
672 bconfig_new_phys
= kernel_free_vm_start
- pv_offset
;
673 bconfig_page
= get_relocated_page(bconfig_new_phys
, nbpp
);
674 bconfig
= (struct bootconfig
*)(bconfig_page
->logical
);
675 kernel_free_vm_start
+= nbpp
;
677 /* get some miscelanious info for the bootblock */
678 os_readsysinfo_monitor_info(NULL
, (int *)&monitor_type
, (int *)&monitor_sync
);
679 os_readsysinfo_chip_presence((int *)&ioeb_flags
, (int *)&superio_flags
, (int *)&lcd_flags
);
680 os_readsysinfo_superio_features((int *)&superio_flags_basic
,
681 (int *)&superio_flags_extra
);
682 os_readsysinfo_unique_id(&id_low
, &id_high
);
684 /* fill in the bootconfig *bconfig structure : generic version II */
685 memset(bconfig
, 0, sizeof(*bconfig
));
686 bconfig
->magic
= BOOTCONFIG_MAGIC
;
687 bconfig
->version
= BOOTCONFIG_VERSION
;
688 strcpy(bconfig
->kernelname
, booted_file
);
691 * get the kernel base name and update the RiscOS name to a
694 i
= strlen(booted_file
);
695 while (i
>= 0 && booted_file
[i
] != '.') i
--;
697 strcpy(bconfig
->kernelname
, "/");
698 strcat(bconfig
->kernelname
, booted_file
+i
+1);
701 pos
= bconfig
->kernelname
+1;
703 if (*pos
== '/') *pos
= '.';
707 /* set the machine_id */
708 memcpy(&(bconfig
->machine_id
), &id_low
, 4);
710 /* check if the `root' is specified */
712 strcpy(bconfig
->args
, "");
713 for (i
= start_args
; i
< argc
; i
++) {
714 if (strncmp(argv
[i
], "root=",5) ==0) root_specified
= 1;
716 strcat(bconfig
->args
, " ");
717 strcat(bconfig
->args
, argv
[i
]);
719 if (!root_specified
) {
720 if (start_args
< argc
)
721 strcat(bconfig
->args
, " ");
722 strcat(bconfig
->args
, "root=");
723 strcat(bconfig
->args
, DEFAULT_ROOT
);
726 /* mark kernel pointers */
727 bconfig
->kernvirtualbase
= marks
[MARK_START
];
728 bconfig
->kernphysicalbase
= kernel_physical_start
;
729 bconfig
->kernsize
= kernel_free_vm_start
-
731 bconfig
->ksym_start
= marks
[MARK_SYM
];
732 bconfig
->ksym_end
= marks
[MARK_SYM
] + marks
[MARK_NSYM
];
734 /* setup display info */
735 bconfig
->display_phys
= videomem_start
;
736 bconfig
->display_start
= videomem_start
;
737 bconfig
->display_size
= display_size
;
738 bconfig
->width
= vdu_var(os_MODEVAR_XWIND_LIMIT
);
739 bconfig
->height
= vdu_var(os_MODEVAR_YWIND_LIMIT
);
740 bconfig
->log2_bpp
= vdu_var(os_MODEVAR_LOG2_BPP
);
741 bconfig
->framerate
= vsync_rate();
743 /* fill in memory info */
744 bconfig
->pagesize
= nbpp
;
745 bconfig
->drampages
= total_dram_pages
+
746 total_podram_pages
; /* XXX */
747 bconfig
->vrampages
= total_vram_pages
;
748 bconfig
->dramblocks
= dram_blocks
+ podram_blocks
; /*XXX*/
749 bconfig
->vramblocks
= vram_blocks
;
751 for (i
= 0; i
< dram_blocks
; i
++) {
752 bconfig
->dram
[i
].address
= DRAM_addr
[i
];
753 bconfig
->dram
[i
].pages
= DRAM_pages
[i
];
754 bconfig
->dram
[i
].flags
= PHYSMEM_TYPE_GENERIC
;
756 for (; i
< dram_blocks
+ podram_blocks
; i
++) {
757 bconfig
->dram
[i
].address
= PODRAM_addr
[i
-dram_blocks
];
758 bconfig
->dram
[i
].pages
= PODRAM_pages
[i
-dram_blocks
];
759 bconfig
->dram
[i
].flags
= PHYSMEM_TYPE_PROCESSOR_ONLY
;
761 for (i
= 0; i
< vram_blocks
; i
++) {
762 bconfig
->vram
[i
].address
= VRAM_addr
[i
];
763 bconfig
->vram
[i
].pages
= VRAM_pages
[i
];
764 bconfig
->vram
[i
].flags
= PHYSMEM_TYPE_GENERIC
;
770 main(int argc
, char **argv
)
772 int howto
, start_args
, ret
;
776 printf(">> %s, Revision %s\n", bootprog_name
, bootprog_rev
);
777 printf(">> (%s, %s)\n", bootprog_maker
, bootprog_date
);
778 printf(">> Booting NetBSD/acorn32 on a RiscPC/A7000/NC\n");
781 process_args(argc
, argv
, &howto
, booted_file
, &start_args
);
783 printf("Booting %s (howto = 0x%x)\n", booted_file
, howto
);
785 init_datastructures();
786 get_memory_configuration();
790 * point to the first free DRAM page guaranteed to be in
793 if (podram_blocks
!= 0) {
794 free_relocation_page
=
795 mem_pages_info
+ first_mapped_PODRAM_page_index
;
796 kernel_physical_start
= PODRAM_addr
[0];
797 kernel_physical_maxsize
= PODRAM_pages
[0] * nbpp
;
799 free_relocation_page
=
800 mem_pages_info
+ first_mapped_DRAM_page_index
;
801 kernel_physical_start
= DRAM_addr
[0];
802 kernel_physical_maxsize
= DRAM_pages
[0] * nbpp
;
805 printf("\nLoading %s ", booted_file
);
807 /* first count the kernel to get the markers */
808 ret
= loadfile(booted_file
, marks
, COUNT_KERNEL
);
809 if (ret
== -1) panic("Kernel load failed"); /* lie to the user ... */
812 if (marks
[MARK_END
] - marks
[MARK_START
] > kernel_physical_maxsize
)
814 panic("\nKernel is bigger than the first DRAM module, unable to boot\n");
818 * calculate how much the difference is between physical and
819 * virtual space for the kernel
821 pv_offset
= ((u_long
)marks
[MARK_START
] - kernel_physical_start
);
822 /* round on a page */
823 kernel_free_vm_start
= (marks
[MARK_END
] + nbpp
-1) & ~(nbpp
-1);
825 /* we seem to be forced to clear the marks[] ? */
826 memset(marks
, 0, sizeof(marks
));
828 /* really load it ! */
829 ret
= loadfile(booted_file
, marks
, LOAD_KERNEL
);
830 if (ret
== -1) panic("Kernel load failed");
833 /* finish off the relocation information */
834 create_initial_page_tables();
836 add_pagetables_at_top();
837 create_configuration(argc
, argv
, start_args
);
840 * done relocating and creating information, now update and
841 * check the relocation mechanism
843 compact_relocations();
846 * grab a page to copy the bootstrap code into
848 relocate_code_page
= free_relocation_page
++;
850 printf("\nStarting at 0x%lx, p@0x%lx\n", marks
[MARK_ENTRY
], kernel_physical_start
);
851 printf("%ld entries, first one is 0x%lx->0x%lx for %lx bytes\n",
852 reloc_instruction_table
[0],
853 reloc_instruction_table
[1],
854 reloc_instruction_table
[2],
855 reloc_instruction_table
[3]);
857 printf("Will boot in a few secs due to relocation....\n"
858 "bye bye from RISC OS!");
860 /* dismount all filesystems */
861 xosfscontrol_shutdown();
863 os_readsysinfo_platform_class(&class, NULL
, NULL
);
864 if (class != osreadsysinfo_Platform_Pace
) {
865 /* reset devices, well they try to anyway */
870 /* r0 relocation code page (V) */ relocate_code_page
->logical
,
871 /* r1 relocation pv offset */
872 relocate_code_page
->physical
-relocate_code_page
->logical
,
873 /* r2 configuration structure */ bconfig_new_phys
,
874 /* r3 relocation table (l) */
875 (int)reloc_instruction_table
, /* one piece! */
876 /* r4 L1 page descriptor (P) */ new_L1_pages_phys
,
877 /* r5 kernel entry point */ marks
[MARK_ENTRY
]
884 boot32_read(int f
, void *addr
, size_t size
)
888 ssize_t bytes_read
, total
;
890 /* printf("read at %p for %ld bytes\n", addr, size); */
893 fragsize
= nbpp
; /* select one page */
894 if (size
< nbpp
) fragsize
= size
;/* clip to size left */
896 /* get a page for a fragment */
897 fragaddr
= (void *)get_relocated_page((u_long
) addr
-
898 pv_offset
, fragsize
)->logical
;
900 bytes_read
= read(f
, fragaddr
, fragsize
);
901 if (bytes_read
< 0) return bytes_read
; /* error! */
902 total
+= bytes_read
; /* account read bytes */
904 if (bytes_read
< fragsize
)
905 return total
; /* does this happen? */
907 size
-= fragsize
; /* advance */
915 boot32_memcpy(void *dst
, const void *src
, size_t size
)
920 /* printf("memcpy to %p from %p for %ld bytes\n", dst, src, size); */
922 fragsize
= nbpp
; /* select one page */
923 if (size
< nbpp
) fragsize
= size
;/* clip to size left */
925 /* get a page for a fragment */
926 fragaddr
= (void *)get_relocated_page((u_long
) dst
-
927 pv_offset
, fragsize
)->logical
;
928 memcpy(fragaddr
, src
, size
);
930 src
+= fragsize
; /* account copy */
939 boot32_memset(void *dst
, int c
, size_t size
)
944 /* printf("memset %p for %ld bytes with %d\n", dst, size, c); */
946 fragsize
= nbpp
; /* select one page */
947 if (size
< nbpp
) fragsize
= size
;/* clip to size left */
949 /* get a page for a fragment */
950 fragaddr
= (void *)get_relocated_page((u_long
)dst
- pv_offset
,
952 memset(fragaddr
, c
, fragsize
);
954 dst
+= fragsize
; /* account memsetting */
962 /* We can rely on the fact that two entries never have identical ->physical */
964 page_info_cmp(const void *a
, const void *b
)
967 return (((struct page_info
*)a
)->physical
<
968 ((struct page_info
*)b
)->physical
) ? -1 : 1;
972 get_relocated_page(u_long destination
, int size
)
974 struct page_info
*page
;
976 /* get a page for a fragment */
977 page
= free_relocation_page
;
978 if (free_relocation_page
->pagenumber
< 0) panic("\n\nOut of pages");
980 if (reloc_entries
>= MAX_RELOCPAGES
)
981 panic("\n\nToo many relocations! What are you loading ??");
983 /* record the relocation */
984 if (free_relocation_page
->physical
& 0x3)
985 panic("\n\nphysical address is not aligned!");
987 if (destination
& 0x3)
988 panic("\n\ndestination address is not aligned!");
990 *reloc_pos
++ = free_relocation_page
->physical
;
991 *reloc_pos
++ = destination
;
993 free_relocation_page
++; /* advance */
1002 int varlist
[2], vallist
[2];
1006 os_read_vdu_variables(varlist
, vallist
);
1015 printf("%c%c", "|/-\\"[(int) twirl_cnt
], 8);
1022 process_args(int argc
, char **argv
, int *howto
, char *file
, int *start_args
)
1025 static char filename
[80];
1028 *file
= NULL
; *start_args
= 1;
1029 for (i
= 1; i
< argc
; i
++) {
1030 if (argv
[i
][0] == '-')
1031 for (j
= 1; argv
[i
][j
]; j
++)
1032 BOOT_FLAG(argv
[i
][j
], *howto
);
1037 strcpy(file
, argv
[i
]);
1043 if (*file
== NULL
) {
1044 if (*howto
& RB_ASKNAME
) {
1047 strcpy(file
, filename
);
1049 strcpy(file
, "netbsd");
1055 sprint0(int width
, char prefix
, char base
, int value
)
1057 static char format
[50], scrap
[50];
1061 for (pos
= format
, length
= 0; length
<width
; length
++) *pos
++ = prefix
;
1066 sprintf(scrap
, format
, value
);
1067 length
= strlen(scrap
);
1069 return scrap
+length
-width
;