Home | History | Annotate | Line # | Download | only in !BtNetBSD
      1  1.1  jdolecek REM > BtNetBSD
      2  1.7    andvar REM $NetBSD: BtNetBSD,v 1.7 2025/08/18 20:59:54 andvar Exp $
      3  1.1  jdolecek REM
      4  1.1  jdolecek REM Copyright (c) 2000, 2001, 2002 Reinoud Zandijk
      5  1.1  jdolecek REM Copyright (c) 1998, 1999, 2000 Ben Harris
      6  1.1  jdolecek REM ELF file reading based on work by Ben Harris
      7  1.1  jdolecek REM All rights reserved.
      8  1.1  jdolecek REM
      9  1.1  jdolecek REM Redistribution and use in source and binary forms, with or without
     10  1.1  jdolecek REM modification, are permitted provided that the following conditions
     11  1.1  jdolecek REM are met:
     12  1.1  jdolecek REM 1. Redistributions of source code must retain the above copyright
     13  1.1  jdolecek REM    notice, this list of conditions and the following disclaimer.
     14  1.1  jdolecek REM 2. Redistributions in binary form must reproduce the above copyright
     15  1.1  jdolecek REM    notice, this list of conditions and the following disclaimer in the
     16  1.1  jdolecek REM    documentation and/or other materials provided with the distribution.
     17  1.1  jdolecek REM 3. The name of the author may not be used to endorse or promote products
     18  1.1  jdolecek REM    derived from this software without specific prior written permission.
     19  1.1  jdolecek REM
     20  1.1  jdolecek REM THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  1.1  jdolecek REM IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  1.1  jdolecek REM OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  1.1  jdolecek REM IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  1.1  jdolecek REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  1.1  jdolecek REM NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  1.1  jdolecek REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  1.1  jdolecek REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  1.1  jdolecek REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  1.1  jdolecek REM THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  1.1  jdolecek REM
     31  1.1  jdolecek REM This file is part of NetBSD/acorn32 -- a port of NetBSD to ARM6+ machines
     32  1.1  jdolecek REM This source contains pieces of code by Ben Harris (file structure)
     33  1.1  jdolecek REM and Mark Brinicombe (DRAM/VRAM search)
     34  1.1  jdolecek REM
     35  1.1  jdolecek REM Purpose : Trying to boot NetBSD/acorn32 !!
     36  1.1  jdolecek 
     37  1.1  jdolecek 
     38  1.1  jdolecek ON ERROR REPORT:PRINT " at line ";ERL: PRINT'"Press key":QQ=GET:END
     39  1.1  jdolecek 
     40  1.1  jdolecek debug%           = 0
     41  1.1  jdolecek emulateVRAM%     = 0
     42  1.1  jdolecek emulateDRAMsize% = 0
     43  1.1  jdolecek extradebug%      = 0
     44  1.1  jdolecek startdelay%      = 5
     45  1.1  jdolecek 
     46  1.1  jdolecek REM For Kinetic cards
     47  1.1  jdolecek SDRAM_ADDR_START% = 512*1024*1024
     48  1.1  jdolecek REM For debugging only :
     49  1.1  jdolecek REM SDRAM_ADDR_START% = &18000000
     50  1.1  jdolecek 
     51  1.1  jdolecek 
     52  1.1  jdolecek REM set pretty screen for printing without scrolling
     53  1.1  jdolecek SYS "XWimp_CommandWindow", -1: VDU 26
     54  1.1  jdolecek SYS "XHourglass_Smash"
     55  1.1  jdolecek MODE MODE
     56  1.1  jdolecek COLOUR 128+4:CLS
     57  1.1  jdolecek scwidth% = FNvdu_var(256): scheigth% = FNvdu_var(257)
     58  1.1  jdolecek width% = INT(scwidth%*0.75*0.5)*2: heigth% = INT(scheigth%*0.75*0.5)*2
     59  1.1  jdolecek VDU 4, 28, (scwidth%-width%)/2, (scheigth%+heigth%)/2, (scwidth%+width%)/2, (scheigth%-heigth%)/2
     60  1.1  jdolecek COLOUR 128:CLS
     61  1.1  jdolecek 
     62  1.1  jdolecek PRINT''
     63  1.3     bjh21 PROCcenter("BtNetBSD 0.99b")
     64  1.1  jdolecek PROCcenter("booting NetBSD/acorn32 on a RiscPC/A7000/NC")
     65  1.1  jdolecek PRINT''
     66  1.1  jdolecek 
     67  1.1  jdolecek REM get argument string
     68  1.1  jdolecek SYS "OS_GetEnv" TO args$
     69  1.1  jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE
     70  1.1  jdolecek IF LEFT$(args$, 5)="BASIC" THEN args$=MID$(args$, 6)
     71  1.1  jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE
     72  1.1  jdolecek IF LEFT$(args$, 5)="-quit" THEN args$=MID$(args$, 6)
     73  1.1  jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE
     74  1.1  jdolecek prog$ = LEFT$(args$, INSTR(args$, " ")-1)
     75  1.1  jdolecek args$ = MID$(args$, LEN(prog$)+1)
     76  1.1  jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE
     77  1.1  jdolecek 
     78  1.1  jdolecek REM get kernel name
     79  1.1  jdolecek file$ = LEFT$(args$, INSTR(args$, " ")-1)
     80  1.3     bjh21 
     81  1.3     bjh21 PRINT "Press return to boot now, any other key for boot prompt"
     82  1.3     bjh21 PRINT "Booting ";file$;" ";args$
     83  1.3     bjh21 PRINT "Starting in ";
     84  1.3     bjh21 c% = FNawaitkey(5)
     85  1.3     bjh21 IF c% <> 13 AND c% <> 0 THEN
     86  1.3     bjh21   INPUT "Boot: " cmd$
     87  1.3     bjh21   IF LEFT$(cmd$, 1) = "-" THEN
     88  1.3     bjh21     REM just add an option
     89  1.3     bjh21     args$ += " " + cmd$
     90  1.3     bjh21   ELSE
     91  1.3     bjh21     args$ = cmd$
     92  1.3     bjh21     file$ = LEFT$(args$, INSTR(args$, " ") - 1)
     93  1.3     bjh21   ENDIF
     94  1.3     bjh21   PRINT "Booting ";file$;" ";args$
     95  1.3     bjh21 ENDIF
     96  1.3     bjh21 PRINT''
     97  1.1  jdolecek 
     98  1.1  jdolecek 
     99  1.1  jdolecek IF FNtolower(LEFT$(file$,9))="unixfs:$." THEN
    100  1.1  jdolecek   kernelname$=MID$(file$, 10)
    101  1.1  jdolecek ELSE
    102  1.1  jdolecek   kernelname$="netbsd" : REM RISC OS file namen zeggen niets XXX
    103  1.1  jdolecek ENDIF
    104  1.1  jdolecek 
    105  1.1  jdolecek 
    106  1.1  jdolecek REM Get some space to mess with
    107  1.1  jdolecek REM Declare a large array ... and then wipe it/map it in in the OS_Mem loop
    108  1.1  jdolecek REM the difference is that RO4 won't map it in by default and
    109  1.1  jdolecek REM that could trigger a OS_Memory bug ...
    110  1.1  jdolecek SYS "OS_Memory", 6 TO ,memorytablesize%, nbpp% : REM get tablesize%
    111  1.1  jdolecek memory_image_size% = HIMEM-512*1024            : REM keep a 512 Kb for vars
    112  1.1  jdolecek DIM memory_image% memory_image_size%           : REM claim the space
    113  1.1  jdolecek 
    114  1.1  jdolecek bot_memory% = memory_image%
    115  1.1  jdolecek top_memory% = memory_image% + memory_image_size%
    116  1.1  jdolecek 
    117  1.1  jdolecek KERNEL_BASE = &F0000000
    118  1.1  jdolecek 
    119  1.1  jdolecek MAX_RELOCPAGES = 4096
    120  1.1  jdolecek MAX_DRAMBANKS = 32
    121  1.1  jdolecek MAX_VRAMBANKS = 16
    122  1.1  jdolecek 
    123  1.1  jdolecek twirl% = 0
    124  1.1  jdolecek firstpage%  = (bot_memory% DIV nbpp%)+1
    125  1.1  jdolecek lastpage%   = (top_memory% DIV nbpp%)-1
    126  1.1  jdolecek totalpages% = lastpage% - firstpage%
    127  1.1  jdolecek PRINT "I got a ";totalpages%;" memory pages to mess with"
    128  1.1  jdolecek 
    129  1.1  jdolecek relocsize% = (MAX_RELOCPAGES+1)*12
    130  1.1  jdolecek DIM relocinstr% relocsize%
    131  1.1  jdolecek relocpos% = relocinstr%+4 : REM first word in number of relocations
    132  1.1  jdolecek relocnr% = 0: relocoff% = 0
    133  1.1  jdolecek 
    134  1.1  jdolecek REM this memory block contains all information about the memory layout
    135  1.1  jdolecek REM maybe a bug in BASIC but if I DIM this variable in a procedure it
    136  1.1  jdolecek REM gets on the stack or so ? It malfunctions if I pass this on as a
    137  1.1  jdolecek REM procedure variable.
    138  1.1  jdolecek DIM memoryblock% (totalpages%*12+4)
    139  1.1  jdolecek 
    140  1.1  jdolecek PROCget_memory_configuration
    141  1.1  jdolecek PROCget_memory_map
    142  1.1  jdolecek 
    143  1.1  jdolecek PROCload_kernel(file$)
    144  1.1  jdolecek PROCcreate_initial_pagetables
    145  1.1  jdolecek PROCadd_pagetables
    146  1.1  jdolecek PROCcreate_configuration
    147  1.1  jdolecek 
    148  1.1  jdolecek REM now only the relocation code itself and then copying the relocation table itself
    149  1.1  jdolecek !relocinstr% = relocnr%
    150  1.1  jdolecek PROCcreate_relocate_mechanism
    151  1.1  jdolecek PRINT " "
    152  1.1  jdolecek 
    153  1.1  jdolecek REM start the kernel
    154  1.1  jdolecek A% = FNblock_paddr(configurationbasepage%)
    155  1.1  jdolecek B% = physical_start_address% - FNblock_vaddr(relocatebasepage%) + FNblock_paddr(relocatebasepage%)
    156  1.1  jdolecek C% = FNblock_paddr(relocatebasepage%) + nbpp% : REM one page after the code
    157  1.1  jdolecek D% = L1pages_phys%
    158  1.1  jdolecek E% = entry%
    159  1.1  jdolecek 
    160  1.1  jdolecek IF debug% THEN
    161  1.1  jdolecek   IF ((relocpos%-(relocinstr%+4)) MOD 12)<>0 THEN ERROR 0,"Sanity check for relocation entries failed!"
    162  1.1  jdolecek   PRINT"Entering kernel at 0x";~entry%
    163  1.1  jdolecek   REM  OSCLI("Memoryi "+STR$~(FNblock_vaddr(start_kernelpage%)+(entry% MOD nbpp%)))
    164  1.1  jdolecek   REM  PRINT"Go for it (key)":qq=GET
    165  1.1  jdolecek ENDIF
    166  1.1  jdolecek 
    167  1.1  jdolecek REM get ECID for each podule
    168  1.1  jdolecek FOR pod% =-1 TO 8
    169  1.1  jdolecek   SYS "XPodule_ReadID",,,,pod%
    170  1.1  jdolecek NEXT
    171  1.1  jdolecek 
    172  1.1  jdolecek REM shut down RiscOS
    173  1.1  jdolecek SYS "XOS_CLI", "RMKill UnixFS"
    174  1.1  jdolecek SYS "OS_FSControl", 23     : REM close files etc.
    175  1.1  jdolecek SYS "OS_ServiceCall",, &45 : REM prereset
    176  1.1  jdolecek 
    177  1.1  jdolecek REM Remove all cursors
    178  1.1  jdolecek *pointer 0
    179  1.1  jdolecek SYS "OS_RemoveCursors"
    180  1.1  jdolecek 
    181  1.5   reinoud REM Change screen's base address (VDU/displayed) to offset 0
    182  1.1  jdolecek DIM buf 8
    183  1.5   reinoud buf?3 = 3: buf!4 = 0: SYS "OS_Word", 22, buf+3
    184  1.1  jdolecek 
    185  1.1  jdolecek CALL relocate_entry%
    186  1.1  jdolecek 
    187  1.1  jdolecek END
    188  1.1  jdolecek 
    189  1.1  jdolecek 
    190  1.1  jdolecek DEF PROCload_kernel(file$)
    191  1.1  jdolecek   LOCAL file%, magic%
    192  1.1  jdolecek   file% = OPENIN(file$)
    193  1.1  jdolecek   IF file% = 0 THEN ERROR EXT 1, "Can't open kernel"
    194  1.1  jdolecek     DIM magic% 3
    195  1.1  jdolecek   SYS "OS_GBPB", 3, file%, magic%, 4, 0
    196  1.1  jdolecek   IF magic%?0 = 127 AND magic%?1 = ASC("E") AND magic%?2 = ASC("L") AND magic%?3 = ASC("F") THEN
    197  1.1  jdolecek     PROCload_kernel_elf(file%)
    198  1.1  jdolecek   ELSE
    199  1.1  jdolecek     PROCload_kernel_aout(file%)
    200  1.1  jdolecek   ENDIF
    201  1.1  jdolecek   CLOSE#file%
    202  1.1  jdolecek ENDPROC
    203  1.1  jdolecek 
    204  1.1  jdolecek 
    205  1.1  jdolecek 
    206  1.1  jdolecek REM *****************************************************************************
    207  1.1  jdolecek REM * ELF LOADER                                                                *
    208  1.1  jdolecek REM *****************************************************************************
    209  1.1  jdolecek 
    210  1.1  jdolecek 
    211  1.1  jdolecek DEF PROCload_kernel_elf(file%)
    212  1.1  jdolecek   REM read header
    213  1.1  jdolecek   DIM hdr% 52
    214  1.1  jdolecek   SYS "OS_GBPB", 3, file%, hdr%, 52, 0
    215  1.1  jdolecek  
    216  1.1  jdolecek   REM check if its a correct kernel to load
    217  1.1  jdolecek   IF hdr%?4 <> 1 THEN ERROR 1, "Not a 32-bit ELF file"
    218  1.1  jdolecek   IF hdr%?5 <> 1 THEN ERROR 1, "Not an LSB ELF file"
    219  1.1  jdolecek   IF hdr%?6 <> 1 THEN ERROR 1, "Not a version-1 ELF file"
    220  1.1  jdolecek   REM hdr%?7 is EI_OSABI.  Should it be 255 (ELFOSABI_STANDALONE)?
    221  1.1  jdolecek   IF (hdr%!16 AND &FFFF) <> 2 THEN ERROR 1, "Not an executable ELF file"
    222  1.1  jdolecek   IF (hdr%!18 AND &FFFF) <> 40 THEN ERROR 1, "Not an ARM ELF file"
    223  1.1  jdolecek 
    224  1.1  jdolecek   PRINT "(ELF) ";
    225  1.1  jdolecek   REM read kernel characteristics and headers
    226  1.1  jdolecek   entry% = hdr%!24
    227  1.1  jdolecek   phoff% = hdr%!28
    228  1.1  jdolecek   shoff% = hdr%!32
    229  1.1  jdolecek   phentsize% = hdr%!42 AND &FFFF
    230  1.1  jdolecek   phnum% = hdr%!44 AND &FFFF
    231  1.1  jdolecek   shentsize% = hdr%!46 AND &FFFF
    232  1.1  jdolecek   shnum% = hdr%!48 AND &FFFF
    233  1.1  jdolecek   DIM phdrs% phnum% * phentsize% - 1  : REM array with headers ?
    234  1.1  jdolecek   SYS "OS_GBPB", 3, file%, phdrs%, phnum% * phentsize%, phoff%
    235  1.1  jdolecek   IF phnum% = 0 THEN ERROR 1, "No program headers"
    236  1.1  jdolecek 
    237  1.1  jdolecek   REM start loading !
    238  1.1  jdolecek   freepagesbase% = first_mapped_DRAM_index% : REM == first virt address in DRAM0a
    239  1.1  jdolecek   start_kernelpage% = freepagesbase%
    240  1.1  jdolecek   pv_offset% = KERNEL_BASE - DRAM_addr%(0) : REM XXX hardcoded
    241  1.1  jdolecek 
    242  1.1  jdolecek   REM load the program blocks
    243  1.1  jdolecek   first% = TRUE
    244  1.1  jdolecek   FOR ph% = phdrs% TO phdrs% + (phnum% - 1) * phentsize% STEP phentsize%
    245  1.1  jdolecek     IF ph%!0 = 1 THEN
    246  1.1  jdolecek       REM We only do PT_LOAD
    247  1.1  jdolecek       IF NOT first% THEN PRINT "+";
    248  1.1  jdolecek       first%  = FALSE
    249  1.1  jdolecek       offset% = ph%!4
    250  1.1  jdolecek       vaddr%  = ph%!8
    251  1.1  jdolecek       REM physaddr% = ph%!12
    252  1.1  jdolecek       filesz% = ph%!16
    253  1.1  jdolecek       memsz%  = ph%!20
    254  1.1  jdolecek       flags%  = ph%!24
    255  1.1  jdolecek       PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%)
    256  1.1  jdolecek       REM freepagesbase% is updated
    257  1.1  jdolecek 
    258  1.1  jdolecek       vfreebase% = vaddr% + memsz% : REM memsz% is the real size.... filesz can be only Text f.e.
    259  1.1  jdolecek     ENDIF
    260  1.1  jdolecek   NEXT
    261  1.1  jdolecek 
    262  1.1  jdolecek   txtbase% = 0
    263  1.1  jdolecek   txtsize% = 0
    264  1.1  jdolecek   database% = 0
    265  1.1  jdolecek   datasize% = 0
    266  1.1  jdolecek   bssbase% = 0
    267  1.1  jdolecek   bsssize% = 0
    268  1.1  jdolecek   ssym% = 0
    269  1.1  jdolecek   esym% = 0
    270  1.1  jdolecek 
    271  1.1  jdolecek   DIM shdrs% shnum% * shentsize% - 1
    272  1.1  jdolecek   SYS "OS_GBPB", 3, file%, shdrs%, shnum% * shentsize%, shoff%
    273  1.1  jdolecek   IF shnum% <> 0 THEN
    274  1.1  jdolecek     havesyms% = FALSE
    275  1.1  jdolecek     FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize%
    276  1.1  jdolecek       IF sh%!4 = 2 THEN havesyms% = TRUE
    277  1.1  jdolecek     NEXT
    278  1.1  jdolecek     IF havesyms% THEN
    279  1.1  jdolecek       IF INSTR(args$, "symtab")=0 THEN havesyms% = FALSE
    280  1.1  jdolecek       IF debug% THEN
    281  1.1  jdolecek         IF havesyms% PRINT ;" (symbols avail) "; ELSE PRINT ;" (ignoring symbols) ";
    282  1.1  jdolecek       ENDIF
    283  1.1  jdolecek     ENDIF
    284  1.1  jdolecek     REM freepagesbase% points to first free relocation page
    285  1.1  jdolecek     IF havesyms% THEN
    286  1.1  jdolecek       REM vfreebase points to first free address in relocated area
    287  1.1  jdolecek       PRINT "+[";
    288  1.1  jdolecek 
    289  1.1  jdolecek       REM First, we have the munged ELF header
    290  1.1  jdolecek       ssym% = vfreebase%
    291  1.1  jdolecek       ssympage% = freepagesbase%
    292  1.1  jdolecek       PROCload_chunk(file%, 0, ssym%, 52, 52)
    293  1.1  jdolecek       !(FNblock_vaddr(ssympage%) + 32) = 52: REM  PROCwrite_word(ssym%+32, 52)
    294  1.1  jdolecek       vfreebase% += 52
    295  1.1  jdolecek 
    296  1.1  jdolecek       REM then, the munged section headers
    297  1.1  jdolecek       mshdrs% = vfreebase%
    298  1.1  jdolecek       mshdrspage% = freepagesbase%
    299  1.1  jdolecek       PRINT "+";
    300  1.1  jdolecek       PROCload_chunk(file%, shoff%, mshdrs%, shnum% * shentsize%, shnum% * shentsize%)
    301  1.1  jdolecek       vfreebase% += shnum% * shentsize%
    302  1.1  jdolecek       FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize%
    303  1.1  jdolecek         IF sh%!4 = 2 OR sh%!4 = 3 THEN
    304  1.1  jdolecek           PRINT "+";
    305  1.1  jdolecek           PROCload_chunk(file%, sh%!16, vfreebase%, sh%!20, sh%!20)
    306  1.1  jdolecek           !(FNblock_vaddr(mshdrspage%) + sh% - shdrs% + 16) = vfreebase% - ssym%
    307  1.1  jdolecek           vfreebase% += FNroundup(sh%!20, 4)
    308  1.1  jdolecek         ENDIF
    309  1.1  jdolecek       NEXT
    310  1.1  jdolecek       esym% = vfreebase%
    311  1.1  jdolecek       PRINT "]";
    312  1.1  jdolecek     ENDIF
    313  1.1  jdolecek   ENDIF
    314  1.1  jdolecek   PRINT " ";
    315  1.1  jdolecek 
    316  1.1  jdolecek   kernelpages% = freepagesbase% - start_kernelpage%
    317  1.1  jdolecek   IF extradebug% THEN PRINT ''"Number of kernel pages ";kernelpages%;" (";kernelpages%*nbpp%;" bytes)"
    318  1.1  jdolecek 
    319  1.1  jdolecek   PROCfinish_relocationtable
    320  1.1  jdolecek ENDPROC
    321  1.1  jdolecek 
    322  1.1  jdolecek 
    323  1.1  jdolecek DEF PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%)
    324  1.1  jdolecek   LOCAL paddr%, ppn%, fragaddr%, fragsz%
    325  1.1  jdolecek 
    326  1.1  jdolecek   REM offset%  offset in file
    327  1.1  jdolecek   REM vaddr%   indicates virtual address where stuff needs to be relocated to
    328  1.1  jdolecek   REM filesz%  number of bytes to read of `file' for this chunk
    329  1.1  jdolecek   REM memsz%   number of bytes to clear for this chunk
    330  1.1  jdolecek   PRINT ;filesz%;
    331  1.1  jdolecek   IF extradebug% PRINT ;" (";~vaddr%;"-";~(vaddr%+memsz%);" [till base+";INT((vaddr%+memsz%-&F0000000)/1024);"k]) ";
    332  1.1  jdolecek   WHILE filesz% > 0
    333  1.1  jdolecek     REM freepagesbase% is first page index in freepages list
    334  1.1  jdolecek     fragsz% = nbpp%
    335  1.1  jdolecek     IF fragsz% > filesz% THEN fragsz% = filesz%
    336  1.1  jdolecek 
    337  1.1  jdolecek     fragaddr% = FNblock_vaddr(freepagesbase%)
    338  1.1  jdolecek     SYS "OS_GBPB", 3, file%, fragaddr%, fragsz%, offset%
    339  1.1  jdolecek  
    340  1.1  jdolecek     REM create a relocation block
    341  1.1  jdolecek     relocpos%!0 = FNblock_paddr(freepagesbase%)
    342  1.1  jdolecek     relocpos%!4 = vaddr% - pv_offset%
    343  1.1  jdolecek     relocpos%!8 = fragsz%
    344  1.1  jdolecek     relocpos% += 12: relocnr%+=1: relocoff%+=1
    345  1.1  jdolecek     freepagesbase% += 1
    346  1.1  jdolecek 
    347  1.1  jdolecek     offset% += fragsz%
    348  1.1  jdolecek     vaddr% += fragsz%
    349  1.1  jdolecek     filesz% -= fragsz%
    350  1.1  jdolecek     memsz% -= fragsz%
    351  1.1  jdolecek     PROCtwirl
    352  1.1  jdolecek   ENDWHILE
    353  1.1  jdolecek  
    354  1.1  jdolecek   IF memsz% > 0 PRINT "+";memsz%;
    355  1.1  jdolecek   WHILE memsz% > 0
    356  1.1  jdolecek     REM freepagesbase% is first page index in freepages list
    357  1.1  jdolecek     fragsz% = nbpp%
    358  1.1  jdolecek     IF fragsz% > memsz% THEN fragsz% = memsz%
    359  1.1  jdolecek 
    360  1.1  jdolecek     PROCbzero(FNblock_vaddr(freepagesbase%), fragsz%)
    361  1.1  jdolecek 
    362  1.1  jdolecek     REM create a relocation block
    363  1.1  jdolecek     relocpos%!0 = FNblock_paddr(freepagesbase%)
    364  1.1  jdolecek     relocpos%!4 = vaddr% - pv_offset%
    365  1.1  jdolecek     relocpos%!8 = fragsz%
    366  1.1  jdolecek     relocpos% += 12: relocnr%+=1: relocoff%+=1
    367  1.1  jdolecek     freepagesbase% += 1
    368  1.1  jdolecek  
    369  1.1  jdolecek     offset% += fragsz%
    370  1.1  jdolecek     vaddr% += fragsz%
    371  1.1  jdolecek     filesz% -= fragsz%
    372  1.1  jdolecek     memsz% -= fragsz%
    373  1.1  jdolecek     PROCtwirl
    374  1.1  jdolecek   ENDWHILE
    375  1.1  jdolecek ENDPROC
    376  1.1  jdolecek 
    377  1.1  jdolecek 
    378  1.1  jdolecek REM *****************************************************************************
    379  1.1  jdolecek REM * A.OUT LOADER                                                              *
    380  1.1  jdolecek REM *****************************************************************************
    381  1.1  jdolecek 
    382  1.1  jdolecek DEF PROCload_kernel_aout(file%)
    383  1.1  jdolecek   LOCAL hdr%
    384  1.1  jdolecek   DIM hdr% 32
    385  1.1  jdolecek   ssym% = 0 : esym% = 0
    386  1.1  jdolecek   SYS "OS_GBPB", 3, file%, hdr%, 32, 0
    387  1.1  jdolecek   bemagic% = (hdr%?0 << 24) OR (hdr%?1 <<16) OR (hdr%?2 << 8) OR hdr%?3
    388  1.1  jdolecek   CASE bemagic% AND &0000FFFF OF
    389  1.1  jdolecek     WHEN &0107
    390  1.1  jdolecek       PRINT "(OMAGIC) ";
    391  1.1  jdolecek     WHEN &0108
    392  1.1  jdolecek       PRINT "(NMAGIC) ";
    393  1.1  jdolecek     WHEN &010B
    394  1.1  jdolecek       PRINT "(ZMAGIC) ";
    395  1.1  jdolecek     WHEN &00CC
    396  1.1  jdolecek       PRINT "(QMAGIC) ";
    397  1.1  jdolecek   ENDCASE
    398  1.1  jdolecek   REM XXX: Assume ZMAGIC
    399  1.1  jdolecek 
    400  1.1  jdolecek   REM foooff% is byte offset in file.  foobasepage% is base page in RAM.
    401  1.1  jdolecek   txtoff% = 0 : REM in arm26 its 4096
    402  1.1  jdolecek   txtbasepage% = first_mapped_DRAM_index% : REM == first virt address in DRAM0a
    403  1.1  jdolecek   start_kernelpage% = txtbasepage%
    404  1.1  jdolecek 
    405  1.1  jdolecek   txtsize% = hdr%!4
    406  1.1  jdolecek   IF txtsize% MOD nbpp% <> 0 THEN
    407  1.1  jdolecek     ERROR EXT 1, "Text size not a multiple of page size"
    408  1.1  jdolecek   ENDIF
    409  1.1  jdolecek   txtpages% = txtsize% DIV nbpp%
    410  1.1  jdolecek   dataoff% = txtoff% + txtsize%
    411  1.1  jdolecek   databasepage% = txtbasepage% + txtpages%
    412  1.1  jdolecek   database% = databasepage% * nbpp%
    413  1.1  jdolecek   datasize% = hdr%!8
    414  1.1  jdolecek   IF datasize% MOD nbpp% <> 0 THEN
    415  1.1  jdolecek     ERROR EXT 1, "Data size not a multiple of page size"
    416  1.1  jdolecek   ENDIF
    417  1.1  jdolecek   datapages% = datasize% DIV nbpp%
    418  1.1  jdolecek   bssbasepage% = databasepage% + datapages%
    419  1.1  jdolecek   bssbase% = bssbasepage% * nbpp%
    420  1.1  jdolecek   bsspages% = FNroundup(hdr%!12, nbpp%) DIV nbpp%
    421  1.1  jdolecek   bsssize% = bsspages% * nbpp%
    422  1.1  jdolecek   IF bsssize% MOD nbpp% <> 0 THEN
    423  1.1  jdolecek     ERROR EXT 1, "Bss size not a multiple of page size"
    424  1.1  jdolecek   ENDIF
    425  1.1  jdolecek  
    426  1.1  jdolecek   entry% = hdr%!20
    427  1.1  jdolecek   IF debug% THEN PRINT "Entry point at ";~entry%
    428  1.1  jdolecek 
    429  1.1  jdolecek   REM kernelpages without syms table is :
    430  1.1  jdolecek   kernelpages% = txtpages% + datapages% + bsspages% : REM
    431  1.1  jdolecek 
    432  1.1  jdolecek   REM  symbasepage% = bssbasepage% + bsspages%-1 : REM REAL size... not in pages
    433  1.1  jdolecek   symoff% = dataoff% + datasize%
    434  1.1  jdolecek   symsize% = hdr%!16
    435  1.1  jdolecek   stringtablesize% = EXT#file% - (txtsize% + datasize% + symsize%)
    436  1.1  jdolecek   IF INSTR(args$, "symtab")>0 THEN
    437  1.1  jdolecek     kernelpages% += FNroundup(stringtablesize% + symsize% + 4, nbpp%) DIV nbpp%
    438  1.1  jdolecek   ELSE
    439  1.1  jdolecek     symsize% = 0
    440  1.1  jdolecek     stringtablesize% = 0
    441  1.1  jdolecek   ENDIF
    442  1.1  jdolecek   REM reserve 1 extra word for the length
    443  1.1  jdolecek   symbolsize% = symsize% + stringtablesize% + 4
    444  1.1  jdolecek   symbolpages% = FNroundup(symbolsize%, nbpp%) DIV nbpp%
    445  1.1  jdolecek   IF debug% PRINT '"Stringtablesize = 0x";~stringtablesize%;"  symsize = 0x";~symsize%
    446  1.1  jdolecek  
    447  1.1  jdolecek   PRINT '"A total of about ";kernelpages%;" pages need to be relocated"
    448  1.1  jdolecek   IF (kernelpages%+40)*nbpp% > memory_image_size% THEN
    449  1.1  jdolecek     REM 40 is an estimation ...
    450  1.1  jdolecek     ERROR EXT 1, "Not enough memory free... please increase WimpSlot in the configuration file"
    451  1.1  jdolecek   ENDIF
    452  1.1  jdolecek 
    453  1.1  jdolecek   PRINT ;txtsize%;
    454  1.1  jdolecek   new_hdr% = FNblock_vaddr(txtbasepage%)
    455  1.1  jdolecek   FOR pg% = 0 TO txtpages%-1
    456  1.1  jdolecek     SYS "OS_GBPB", 3, file%, FNblock_vaddr(txtbasepage%+pg%), nbpp%, txtoff% + pg%*nbpp%
    457  1.1  jdolecek     relocpos%!0 = FNblock_paddr(txtbasepage%+pg%)
    458  1.1  jdolecek     relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1
    459  1.1  jdolecek     relocpos%!8 = nbpp%
    460  1.1  jdolecek     relocpos% += 12
    461  1.1  jdolecek     PROCtwirl
    462  1.1  jdolecek   NEXT
    463  1.1  jdolecek 
    464  1.1  jdolecek   PRINT "+";datasize%;
    465  1.1  jdolecek   FOR pg% = 0 TO datapages%-1
    466  1.1  jdolecek     SYS "OS_GBPB", 3, file%, FNblock_vaddr(databasepage%+pg%), nbpp%, dataoff% + pg%*nbpp%
    467  1.1  jdolecek     relocpos%!0 = FNblock_paddr(databasepage%+pg%)
    468  1.1  jdolecek     relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1
    469  1.1  jdolecek     relocpos%!8 = nbpp%
    470  1.1  jdolecek     relocpos% += 12
    471  1.1  jdolecek     PROCtwirl
    472  1.1  jdolecek   NEXT
    473  1.1  jdolecek   REM PRINT;"(";off%;" gaps)";
    474  1.1  jdolecek 
    475  1.1  jdolecek   PRINT "+";bsssize%;
    476  1.1  jdolecek   FOR pg% = 0 TO bsspages%-1 : REM overshoot is safe
    477  1.1  jdolecek     PROCbzero(FNblock_vaddr(bssbasepage%+pg%), nbpp%)
    478  1.1  jdolecek     relocpos%!0 = FNblock_paddr(bssbasepage%+pg%)
    479  1.1  jdolecek     relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1
    480  1.1  jdolecek     relocpos%!8 = nbpp%
    481  1.1  jdolecek     relocpos% += 12
    482  1.1  jdolecek     PROCtwirl
    483  1.1  jdolecek   NEXT
    484  1.1  jdolecek   REM PRINT;"(";off%;" gaps)";
    485  1.1  jdolecek 
    486  1.1  jdolecek   freepagesbase% = bssbasepage% + bsspages%
    487  1.1  jdolecek 
    488  1.1  jdolecek   IF INSTR(args$, "symtab")>0 THEN
    489  1.1  jdolecek     symbasepage% = freepagesbase%
    490  1.1  jdolecek 
    491  1.1  jdolecek     REM put a page for the value of symsize just after bss%
    492  1.1  jdolecek     symDaddr% = !(relocpos%-8) + ((hdr%!12) AND (nbpp%-1))
    493  1.1  jdolecek  
    494  1.1  jdolecek     symstartpagaddrV% = FNblock_vaddr(symbasepage%)
    495  1.1  jdolecek     PROCbzero(symstartpagaddrV%, nbpp%)
    496  1.1  jdolecek     !symstartpagaddrV% = symsize%
    497  1.1  jdolecek 
    498  1.1  jdolecek     relocpos%!0 = FNblock_paddr(symbasepage%)
    499  1.1  jdolecek     relocpos%!4 = symDaddr%  : relocnr%+=1: relocoff%+=1
    500  1.1  jdolecek     relocpos%!8 = nbpp% : REM XXX
    501  1.1  jdolecek     relocpos% += 12
    502  1.1  jdolecek     symDaddr% += 4
    503  1.1  jdolecek  
    504  1.1  jdolecek     REM update the symbasepage !! ... we used one!
    505  1.1  jdolecek     symbasepage%+=1
    506  1.1  jdolecek  
    507  1.1  jdolecek     PRINT "+";symbolsize%;
    508  1.1  jdolecek     REM now fill in rest of the file
    509  1.1  jdolecek     FOR pg% = 0 TO symbolpages%-1 : REM => due to first page to hold offset
    510  1.1  jdolecek       SYS "OS_GBPB", 3, file%, FNblock_vaddr(symbasepage%+pg%), nbpp%, symoff% + pg%*nbpp%
    511  1.1  jdolecek       relocpos%!0 = FNblock_paddr(symbasepage%+pg%)
    512  1.1  jdolecek       relocpos%!4 = symDaddr% + nbpp%*pg%: relocnr%+=1: relocoff%+=1
    513  1.1  jdolecek       relocpos%!8 = nbpp%
    514  1.1  jdolecek       relocpos% += 12
    515  1.1  jdolecek       PROCtwirl
    516  1.1  jdolecek     NEXT
    517  1.1  jdolecek  
    518  1.1  jdolecek     freepagesbase% = symbasepage% + symbolpages% + 4 : REM XXX
    519  1.1  jdolecek   ENDIF
    520  1.1  jdolecek  
    521  1.1  jdolecek   REM update new header structure
    522  1.1  jdolecek   new_hdr%!16 = symsize%
    523  1.1  jdolecek  
    524  1.1  jdolecek   REM mark highest virtual address free in NetBSD's mapping
    525  1.1  jdolecek   vfreebase% = KERNEL_BASE + nbpp%*relocoff%
    526  1.1  jdolecek 
    527  1.1  jdolecek   REM `patch' symbol table stuff
    528  1.1  jdolecek   ssym% = 0
    529  1.1  jdolecek   esym% = 0
    530  1.1  jdolecek  
    531  1.1  jdolecek   PROCfinish_relocationtable
    532  1.1  jdolecek ENDPROC
    533  1.1  jdolecek 
    534  1.1  jdolecek 
    535  1.1  jdolecek REM *****************************************************************************
    536  1.1  jdolecek REM * Common loader and relocate stuff                                          *
    537  1.1  jdolecek REM *****************************************************************************
    538  1.1  jdolecek 
    539  1.1  jdolecek DEF PROCfinish_relocationtable
    540  1.1  jdolecek   REM align vfreebase% to a page
    541  1.1  jdolecek   vfreebase% = FNroundup(vfreebase%, nbpp%)
    542  1.1  jdolecek   relocoff% = (vfreebase% - KERNEL_BASE) DIV nbpp%
    543  1.1  jdolecek 
    544  1.1  jdolecek   IF vfreebase% > (nbpp%*relocoff% + KERNEL_BASE) THEN
    545  1.1  jdolecek     PRINT ''"WHOOAH!' : 0x", ~vfreebase%;" > 0x";~(nbpp%*relocoff%+KERNEL_BASE)
    546  1.1  jdolecek     freepagesbase% += 16
    547  1.1  jdolecek     kernelpages%   += 16
    548  1.1  jdolecek     relocoff%      += 16
    549  1.1  jdolecek   ENDIF
    550  1.1  jdolecek 
    551  1.1  jdolecek   IF INSTR(args$, "oldkernel")>0 THEN
    552  1.1  jdolecek     REM place the arguments in a block ... for the old bootloader's sake
    553  1.1  jdolecek     argsbasepage% = freepagesbase%
    554  1.1  jdolecek     argspages% = 1
    555  1.1  jdolecek     argvirtualbase% = nbpp%*relocoff% + KERNEL_BASE
    556  1.1  jdolecek     relocpos%!0 = FNblock_paddr(argsbasepage%)
    557  1.1  jdolecek     relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1
    558  1.1  jdolecek     relocpos%!8 = nbpp%
    559  1.1  jdolecek     relocpos% += 12
    560  1.1  jdolecek     $(FNblock_vaddr(argsbasepage%)) = args$+CHR$0
    561  1.1  jdolecek     freepagesbase% += argspages%
    562  1.1  jdolecek     kernelpages%   += argspages%
    563  1.1  jdolecek     IF debug% THEN PRINT "Args at 0x";~argvirtualbase%
    564  1.1  jdolecek   ELSE
    565  1.1  jdolecek     REM reserve some space for the MDF file
    566  1.1  jdolecek     REM XXX not implemented yet XXX
    567  1.1  jdolecek   ENDIF
    568  1.1  jdolecek 
    569  1.1  jdolecek   REM I give it a 48k scratch space
    570  1.1  jdolecek   scratchbasepage% = freepagesbase%
    571  1.1  jdolecek   scratchpages% = 12
    572  1.1  jdolecek   scratchvirtualbase% = nbpp%*relocoff% + KERNEL_BASE
    573  1.1  jdolecek   freepagesbase% += scratchpages%
    574  1.1  jdolecek   kernelpages%   += scratchpages%
    575  1.1  jdolecek 
    576  1.1  jdolecek   REM Create one page for the initial vectors
    577  1.1  jdolecek   initvectorbasepage% = freepagesbase%
    578  1.1  jdolecek   initvectorpages%    = 1
    579  1.1  jdolecek   relocpos%!0 = FNblock_paddr(initvectorbasepage%)
    580  1.1  jdolecek   relocpos%!4 = top_physdram% - 1*1024*1024 : relocnr%+=1
    581  1.1  jdolecek   relocpos%!8 = nbpp%
    582  1.1  jdolecek   relocpos% += 12
    583  1.1  jdolecek   freepagesbase% += initvectorpages%
    584  1.1  jdolecek 
    585  1.1  jdolecek   P%=FNblock_vaddr(initvectorbasepage%)
    586  1.1  jdolecek   FOR vec=0 TO &20 STEP 4
    587  1.1  jdolecek     [OPT 2: MOVS PC, r14:]
    588  1.1  jdolecek   NEXT
    589  1.1  jdolecek ENDPROC
    590  1.1  jdolecek 
    591  1.1  jdolecek 
    592  1.1  jdolecek DEF PROCadd_pagetables
    593  1.1  jdolecek   REM DESTINATION MUST BE ON A 16kb boundary!!! (!!!!)
    594  1.1  jdolecek   REM get 4 pages on the top of physical memory (top_physdram%) and copy PT's in it
    595  1.1  jdolecek   addr% = top_physdram% - 4*nbpp%
    596  1.1  jdolecek   IF (addr% AND (16*1024-1)) <> 0 ERROR EXT 0, "L1 pages not on 16Kb boundary"
    597  1.1  jdolecek   FOR pg%=0 TO 3
    598  1.1  jdolecek     PROCcopy(FNblock_vaddr(freepagesbase% + pg%), bootpagetables% + pg%*nbpp%, nbpp%)
    599  1.1  jdolecek     relocpos%!0 = FNblock_paddr(freepagesbase%+pg%)
    600  1.1  jdolecek     relocpos%!4 = addr%+pg%*nbpp%: relocnr%+=1
    601  1.1  jdolecek     relocpos%!8 = nbpp%
    602  1.1  jdolecek     relocpos% += 12
    603  1.1  jdolecek   NEXT
    604  1.1  jdolecek   L1pages_phys% = addr%
    605  1.1  jdolecek   freepagesbase% = freepagesbase%+pg%
    606  1.1  jdolecek ENDPROC
    607  1.1  jdolecek 
    608  1.1  jdolecek 
    609  1.1  jdolecek DEF PROCcreate_initial_pagetables
    610  1.1  jdolecek   LOCAL I%, addr%, kaddr%, mapped_screenmemory%
    611  1.1  jdolecek   DIM bootpagetables% 16*1024
    612  1.1  jdolecek   REM linear translation on the whole domain 00 in blocks of 1Mb
    613  1.1  jdolecek   REM AP=%01, CB=%00 for easy initial setup, dom=0
    614  1.1  jdolecek   FOR I%=0 TO 4*1024-1
    615  1.1  jdolecek     bootpagetables%!(I%*4) = (I%<<20) + (0<<11)+(1<<10) + (1<<4) + (0<<3) + (0<<2) + (1<<1) + 0
    616  1.1  jdolecek   NEXT
    617  1.1  jdolecek 
    618  1.1  jdolecek   REM video memory is mapped 1:1 in the DRAM section or in VRAM section
    619  1.1  jdolecek 
    620  1.1  jdolecek   REM map 1Mb from top of memory to bottom 1Mb of virt. memmap
    621  1.1  jdolecek   addr% = (top_physdram%/1024/1024) -1
    622  1.1  jdolecek   bootpagetables%!0 = (addr%<<20) + (0<<11)+(1<<10) + (1<<4) + (0<<3) + (0<<2) + (1<<1) + 0
    623  1.1  jdolecek 
    624  1.1  jdolecek   REM map 16 Mb of DRAM0a (kernel space) to 0xf0000000
    625  1.1  jdolecek   FOR I%=0 TO 15
    626  1.1  jdolecek     addr% = (kernel_phys_start% >> 20) + I%
    627  1.1  jdolecek     kaddr% = &F00 + I% : REM &F0000000 LSR #20 + I%
    628  1.1  jdolecek     bootpagetables%!(kaddr%*4) = (addr%<<20) + (0<<11)+(1<<10) + (1<<4) + (0<<3) + (0<<2) + (1<<1) + 0
    629  1.1  jdolecek   NEXT
    630  1.1  jdolecek ENDPROC
    631  1.1  jdolecek 
    632  1.1  jdolecek 
    633  1.1  jdolecek DEF PROCcreate_relocate_mechanism
    634  1.1  jdolecek   REM relocate mechanism relies on a contigunous space of the relocator + tables
    635  1.1  jdolecek   REM this isn't finished yet
    636  1.1  jdolecek 
    637  1.1  jdolecek   relocatesize% = nbpp% + relocsize% : REM just ONE code page + relocation table
    638  1.1  jdolecek   PRINT ;"+";relocatesize%;
    639  1.1  jdolecek   relocatepages% = FNroundup(relocatesize%, nbpp%) DIV nbpp%
    640  1.1  jdolecek   relocatebasepage% = freepagesbase%
    641  1.1  jdolecek   pg%=0
    642  1.1  jdolecek   WHILE pg%<relocatepages%
    643  1.1  jdolecek     IF pg%>0 THEN
    644  1.1  jdolecek       PROCcopy(FNblock_vaddr(relocatebasepage%+pg%), relocinstr%+(pg%-1)*nbpp%, nbpp%)
    645  1.1  jdolecek     ENDIF
    646  1.1  jdolecek     PROCtwirl
    647  1.1  jdolecek 
    648  1.1  jdolecek     IF pg%<>relocatepages%-1 THEN
    649  1.1  jdolecek       IF FNblock_paddr(relocatebasepage%+pg%+1)-FNblock_paddr(relocatebasepage%+pg%)<>nbpp% THEN
    650  1.1  jdolecek         REM Help! non contigunous relocate area => try again
    651  1.1  jdolecek         REM ERROR EXT 0, "Help! non contigunous relocate area"
    652  1.1  jdolecek         PRINT ;"*";
    653  1.1  jdolecek         relocatebasepage% = freepagesbase% + pg% : REM  try again from this page
    654  1.1  jdolecek         pg%=-1 : REM will be auto incremented later ...
    655  1.1  jdolecek       ENDIF
    656  1.1  jdolecek     ENDIF
    657  1.1  jdolecek     pg%+=1
    658  1.1  jdolecek   ENDWHILE
    659  1.1  jdolecek   PROCassemble_relocate_code(FNblock_vaddr(relocatebasepage%), FNblock_paddr(relocatebasepage%), entry%, L1pages_phys%)
    660  1.1  jdolecek ENDPROC
    661  1.1  jdolecek 
    662  1.1  jdolecek 
    663  1.1  jdolecek DEF PROCcreate_configuration
    664  1.1  jdolecek   PRINT ;"+";nbpp%;
    665  1.1  jdolecek   configurationbasepage% = freepagesbase%
    666  1.1  jdolecek   configurationpages% = 1
    667  1.1  jdolecek   freepagesbase% += configurationpages%
    668  1.1  jdolecek 
    669  1.1  jdolecek   REM fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id));
    670  1.1  jdolecek   SYS "OS_ReadSysInfo", 2 TO r0,r1,r2, machineId%
    671  1.1  jdolecek 
    672  1.1  jdolecek   IF INSTR(args$, "oldkernel")>0 THEN
    673  1.1  jdolecek     PROCold_configuration_structure
    674  1.1  jdolecek   ELSE
    675  1.1  jdolecek     PROCnew_configuration_structure
    676  1.1  jdolecek   ENDIF
    677  1.1  jdolecek ENDPROC
    678  1.1  jdolecek 
    679  1.1  jdolecek 
    680  1.1  jdolecek DEF PROCnew_configuration_structure
    681  1.1  jdolecek   FOR opt%=0 TO 2 STEP 2
    682  1.1  jdolecek     P% = FNblock_vaddr(configurationbasepage%)
    683  1.1  jdolecek     [OPT opt%
    684  1.1  jdolecek     ; u_int magic
    685  1.1  jdolecek         EQUD          &43112233 ; BOOTCONFIG_MAGIC
    686  1.1  jdolecek     ; u_int bootconfig_version
    687  1.1  jdolecek         EQUD          2
    688  1.1  jdolecek 
    689  1.1  jdolecek     ; u_char machine_id[4]
    690  1.1  jdolecek         EQUD          machineId%
    691  1.1  jdolecek     ; char kernelname[80]
    692  1.1  jdolecek         EQUS          LEFT$(kernelname$+CHR$0+STRING$(80, " "), 80)
    693  1.1  jdolecek     ; char args[512]
    694  1.1  jdolecek         EQUS          args$+CHR$0
    695  1.1  jdolecek         ]: P% += 512 - LEN(args$+CHR$0): [ OPT opt%
    696  1.1  jdolecek 
    697  1.1  jdolecek     ; u_int kernvirtualbase             /* not used now */
    698  1.1  jdolecek         EQUD 0
    699  1.1  jdolecek     ; u_int kernphysicalbase            /* not used now */
    700  1.1  jdolecek         EQUD 0
    701  1.1  jdolecek     ; u_int kernsize
    702  1.1  jdolecek         EQUD          kernelpages% * nbpp%
    703  1.1  jdolecek     ; u_int scratchvirtualbase
    704  1.1  jdolecek         EQUD          scratchvirtualbase%
    705  1.1  jdolecek     ; u_int scratchphysicalbase
    706  1.1  jdolecek         EQUD          scratchvirtualbase%
    707  1.1  jdolecek     ; u_int scratchsize
    708  1.1  jdolecek         EQUD          scratchpages% * nbpp%
    709  1.1  jdolecek 
    710  1.1  jdolecek     ; u_int ksym_start
    711  1.1  jdolecek         EQUD ssym%
    712  1.1  jdolecek     ; u_int ksym_end
    713  1.1  jdolecek         EQUD esym%
    714  1.1  jdolecek 
    715  1.1  jdolecek     ; u_int MDFvirtualbase
    716  1.1  jdolecek         EQUD 0
    717  1.1  jdolecek     ; u_int MDFphysicalbase
    718  1.1  jdolecek         EQUD 0
    719  1.1  jdolecek     ; u_int MDFsize
    720  1.1  jdolecek         EQUD 0
    721  1.1  jdolecek  
    722  1.1  jdolecek     ; u_int display_phys
    723  1.1  jdolecek         EQUD          videomem_start%
    724  1.1  jdolecek     ; u_int display_start
    725  1.1  jdolecek         EQUD          videomem_start% ; screenstart (149)
    726  1.1  jdolecek     ; u_int display_size
    727  1.1  jdolecek         EQUD          display_size%   ; screensize  (150)
    728  1.1  jdolecek     ; u_int width
    729  1.1  jdolecek         EQUD          FNvdu_var(11)   ; acorn32 port needs 0..x-1
    730  1.1  jdolecek     ; u_int heigth
    731  1.1  jdolecek         EQUD          FNvdu_var(12)   ; acorn32 port needs 0..y-1
    732  1.1  jdolecek     ; u_int log2_bpp
    733  1.1  jdolecek         EQUD          FNvdu_var(9)    ; acorn32 port needs log(bitsperpixel)/log(2)
    734  1.1  jdolecek     ; u_int framerate
    735  1.1  jdolecek         EQUD          56 ; XXX why?
    736  1.1  jdolecek  
    737  1.1  jdolecek     ; char reserved[512]
    738  1.1  jdolecek     ]: P% += 512: [ OPT opt%
    739  1.1  jdolecek  
    740  1.1  jdolecek     ; u_int pagesize
    741  1.1  jdolecek         EQUD          nbpp%
    742  1.1  jdolecek     ; u_int drampages
    743  1.1  jdolecek         EQUD          totaldrampages%
    744  1.1  jdolecek     ; u_int vrampages;
    745  1.1  jdolecek         EQUD          totalvrampages%
    746  1.1  jdolecek     ; u_int dramblocks
    747  1.1  jdolecek         EQUD          dramblocks%
    748  1.1  jdolecek     ; u_int vramblocks
    749  1.1  jdolecek         EQUD          vramblocks%
    750  1.1  jdolecek 
    751  1.1  jdolecek     ]
    752  1.1  jdolecek     REM phys_mem dram[DRAM_BLOCKS]  <- 32
    753  1.1  jdolecek     FOR I%=0 TO MAX_DRAMBANKS-1
    754  1.1  jdolecek       [OPT opt%
    755  1.1  jdolecek         ; address% : EQUD DRAM_addr%(I%)
    756  1.1  jdolecek         ; length%  : EQUD DRAM_pages%(I%)
    757  1.1  jdolecek         ; flags%   : EQUD 0
    758  1.1  jdolecek       ]
    759  1.1  jdolecek     NEXT
    760  1.1  jdolecek     REM phys_mem vram[VRAM_BLOCKS]  <- 16
    761  1.1  jdolecek     FOR I%=0 TO MAX_VRAMBANKS-1
    762  1.1  jdolecek       [OPT opt%
    763  1.1  jdolecek         ; address% : EQUD VRAM_addr%(I%)
    764  1.1  jdolecek         ; length%  : EQUD VRAM_pages%(I%)
    765  1.1  jdolecek         ; flags%   : EQUD 0
    766  1.1  jdolecek       ]
    767  1.1  jdolecek     NEXT
    768  1.1  jdolecek   NEXT
    769  1.1  jdolecek ENDPROC
    770  1.1  jdolecek 
    771  1.1  jdolecek 
    772  1.1  jdolecek DEF PROCold_configuration_structure
    773  1.1  jdolecek   FOR opt%=0 TO 2 STEP 2
    774  1.1  jdolecek     P% = FNblock_vaddr(configurationbasepage%)
    775  1.1  jdolecek     [OPT opt%
    776  1.1  jdolecek     ;kernvirtualbase%
    777  1.1  jdolecek         EQUD          0   ; not used
    778  1.1  jdolecek     ;kernphysicalbase%
    779  1.1  jdolecek         EQUD          0   ; not used
    780  1.1  jdolecek     ;kernsize%
    781  1.1  jdolecek         EQUD          kernelpages% * nbpp%
    782  1.1  jdolecek     ;argvirtualbase
    783  1.1  jdolecek         EQUD          argvirtualbase%
    784  1.1  jdolecek     ;argphysicalbase
    785  1.1  jdolecek         EQUD          FNblock_paddr(argsbasepage%)
    786  1.1  jdolecek     ;argsize%
    787  1.1  jdolecek         EQUD          nbpp%
    788  1.1  jdolecek     ;scratchvirtualbase%
    789  1.1  jdolecek         EQUD          scratchvirtualbase%
    790  1.1  jdolecek     ;scratchphysicalbase%
    791  1.1  jdolecek         EQUD          scratchvirtualbase%
    792  1.1  jdolecek     ;scratchsize%
    793  1.1  jdolecek         EQUD          scratchpages% * nbpp%
    794  1.1  jdolecek     ;display_start%
    795  1.1  jdolecek         EQUD          videomem_start% ; screenstart (149)
    796  1.1  jdolecek     ;display_size%
    797  1.1  jdolecek         EQUD          display_size%   ; screensize  (150)
    798  1.1  jdolecek     ;width%
    799  1.1  jdolecek         EQUD          FNvdu_var(11)   ; arm32 port needs 0..x-1
    800  1.1  jdolecek     ;height%
    801  1.1  jdolecek         EQUD          FNvdu_var(12)   ; arm32 port needs 0..y-1
    802  1.1  jdolecek     ;bitsperpixel
    803  1.1  jdolecek         EQUD          FNvdu_var(9)    ; arm32 port needs log(bitsperpixel)/log(2)
    804  1.1  jdolecek     ]
    805  1.1  jdolecek     REM for compatibility for now just 4 DRAM and 1 VRAM
    806  1.1  jdolecek     FOR I%=0 TO 3
    807  1.1  jdolecek       [OPT opt%
    808  1.1  jdolecek         ;address% : EQUD DRAM_addr%(I%)
    809  1.1  jdolecek         ;length%  : EQUD DRAM_pages%(I%)
    810  1.1  jdolecek       ]
    811  1.1  jdolecek     NEXT
    812  1.1  jdolecek     REM current config structure only wants 1 VRAM entry !
    813  1.1  jdolecek     FOR I%=0 TO 0
    814  1.1  jdolecek       [OPT opt%
    815  1.1  jdolecek         ;address% : EQUD VRAM_addr%(I%)
    816  1.1  jdolecek         ;length%  : EQUD VRAM_pages%(I%)
    817  1.1  jdolecek       ]
    818  1.1  jdolecek     NEXT
    819  1.1  jdolecek     [OPT opt%
    820  1.1  jdolecek     ;c_dramblocks%
    821  1.1  jdolecek         EQUD          dramblocks%
    822  1.1  jdolecek     ;c_vramblocks%
    823  1.1  jdolecek         EQUD          vramblocks%
    824  1.1  jdolecek     ;pagesize%
    825  1.1  jdolecek         EQUD          nbpp%
    826  1.1  jdolecek     ;drampages%
    827  1.1  jdolecek         EQUD          totaldrampages%
    828  1.1  jdolecek     ;vrampages%
    829  1.1  jdolecek         EQUD          totalvrampages%
    830  1.1  jdolecek     ;kernelname%
    831  1.1  jdolecek         EQUS          LEFT$(kernelname$+CHR$0+STRING$(80, " "), 80)
    832  1.1  jdolecek     ;framerate%
    833  1.1  jdolecek         EQUD          56 ; XXXXX
    834  1.1  jdolecek     ;machine_id%
    835  1.1  jdolecek         EQUD          machineId%
    836  1.1  jdolecek     ;magic%
    837  1.1  jdolecek         EQUD          &43112233 ; BOOTCONFIG_MAGIC
    838  1.1  jdolecek     ;display_phys%
    839  1.1  jdolecek         EQUD          videomem_start%
    840  1.1  jdolecek     ]
    841  1.1  jdolecek   NEXT opt%
    842  1.1  jdolecek ENDPROC
    843  1.1  jdolecek 
    844  1.1  jdolecek 
    845  1.1  jdolecek REM XXXX a bit messy still
    846  1.1  jdolecek DEF PROCassemble_relocate_code(virtaddress%, physaddress%, entry%, L1pages_phys%)
    847  1.1  jdolecek   FOR opt%=0 TO 2 STEP 2
    848  1.1  jdolecek     P%=virtaddress%
    849  1.1  jdolecek     [OPT opt%
    850  1.1  jdolecek       ; entry conditions :
    851  1.1  jdolecek       ;   - on RiscOS page tables in usr26 mode on virt address ....
    852  1.1  jdolecek       ;   - R0  pointer to configuration structure
    853  1.1  jdolecek       ;   - R1  pointer to physical restart point
    854  1.1  jdolecek       ;   - R2  pointer to physical relocation table
    855  1.1  jdolecek       ;   - R3  pointer to physical new L1 page address
    856  1.1  jdolecek       ;   - R4  new virt adres of kernel entry%
    857  1.1  jdolecek       .relocate_entry%
    858  1.1  jdolecek         ; Enter sup26 mode
    859  1.1  jdolecek         SWI "OS_EnterOS"
    860  1.1  jdolecek  
    861  1.1  jdolecek         ; move args up in register bank
    862  1.1  jdolecek         STMFD r13!, {r0-r4}
    863  1.1  jdolecek         LDMFD r13!, {r8-r12}
    864  1.1  jdolecek 
    865  1.1  jdolecek         ; r8  = config structure address
    866  1.1  jdolecek         ; r9  = physical restart point address
    867  1.1  jdolecek         ; r10 = physical relocation table address
    868  1.1  jdolecek         ; r11 = physical address of new L1page
    869  1.1  jdolecek         ; r12 = kernel entry point in new virt. map
    870  1.1  jdolecek  
    871  1.1  jdolecek         ; go to sup32 mode with IRQ + FIQ disabled
    872  1.1  jdolecek         EQUD %11100001000011110000000000000000 ; MRS R0, CPSR
    873  1.1  jdolecek         BIC r0, r0, #&1F                       ; clear proc. mode
    874  1.1  jdolecek         ORR r0, r0, #(1<<7) + (1<<6)           ; set FIQ + IRQ disable
    875  1.1  jdolecek         ORR r0, r0, #%10011                    ; superv. 32 bit
    876  1.1  jdolecek         EQUD %11100001001010011111000000000000 ; MSR CPSR, r0
    877  1.1  jdolecek         MOV r0, r0
    878  1.1  jdolecek         MOV r0, r0                             ; nops ... nessisary?
    879  1.1  jdolecek 
    880  1.1  jdolecek         ; flush data cache
    881  1.1  jdolecek         ; just read a 64kb app space in the cache
    882  1.1  jdolecek         MOV r0, #&8000
    883  1.1  jdolecek         ADD r1, r0, r0
    884  1.1  jdolecek       .loop_flush1
    885  1.1  jdolecek         LDR r2, [r0], #4
    886  1.1  jdolecek         SUBS r1, r1, #4
    887  1.1  jdolecek         BNE loop_flush1
    888  1.1  jdolecek 
    889  1.1  jdolecek         ; determine processor type ... nessisary for correct copro instr .. store in r13
    890  1.1  jdolecek         EQUD %11101110000100000000111100010000 ; MRC cp15, 0, r0, c0, c0, 0 ; read CPU Id in r0
    891  1.1  jdolecek         MOV   r13, r0                          ; store in r13
    892  1.1  jdolecek 
    893  1.1  jdolecek         ; determine if its a StrongARM
    894  1.1  jdolecek         MOV   r14, #1                          ; r14 flags if its a StrongARM ... assume one
    895  1.1  jdolecek  
    896  1.1  jdolecek         ; detecting an ARM6 needs a special mask
    897  1.1  jdolecek         MOV   r0,     #&FF000000               ; get processor discr. mask in r0
    898  1.1  jdolecek         ADD   r0, r0, #&00000F00               ;
    899  1.1  jdolecek 
    900  1.1  jdolecek         MOV   r1,     #&41000000               ; check for 0x41xxx6xx => ARM6
    901  1.1  jdolecek         ADD   r1, r1, #&00000600
    902  1.1  jdolecek         AND   r2, r13, r0                      ; mask with discr. mask
    903  1.1  jdolecek         CMP   r2, r1                           ; is it a ARM6 ?
    904  1.1  jdolecek         MOVEQ r14, #0                          ; ifso ... then its a v3
    905  1.1  jdolecek  
    906  1.1  jdolecek         ; newer ARMs need a different mask
    907  1.1  jdolecek         MOV   r0,     #&FF000000               ; get processor discr. mask in r0
    908  1.1  jdolecek         ADD   r0, r0, #&0000F000               ;
    909  1.1  jdolecek 
    910  1.1  jdolecek         MOV   r1,     #&41000000               ; check for 0x41xx7xxx => ARM7
    911  1.1  jdolecek         ADD   r1, r1, #&00007000
    912  1.1  jdolecek         AND   r2, r13, r0                      ; mask with discr. mask
    913  1.1  jdolecek         CMP   r2, r1                           ; is it a ARM7 ?
    914  1.1  jdolecek         MOVEQ r14, #0                          ; ifso ... then its a v3
    915  1.1  jdolecek  
    916  1.1  jdolecek ;        MOV   r1,     #&44000000               ; check for 0x44xxaxxx => Strong ARM
    917  1.1  jdolecek ;        ADD   r1, r1, #&0000a000
    918  1.1  jdolecek ;        AND   r2, r13, r0                      ; mask with discr. mask
    919  1.1  jdolecek ;        CMP   r2, r1                           ; is it a StrongARM ?
    920  1.1  jdolecek  
    921  1.1  jdolecek         ; switch off MMU, IDcache and WB and branch to physical code !!
    922  1.1  jdolecek         CMP r14, #0
    923  1.1  jdolecek         EQUD %00011110000100010000111100010000 ; MRCNE cp15, 0, r0, c1, c0, 0 ; read control register
    924  1.1  jdolecek         BICNE r0, r0, #&3F                     ; clear only known bits please !
    925  1.1  jdolecek         MOVEQ r0, #0                           ; ARM6/7 only have these
    926  1.1  jdolecek         ORR r0, r0, #%0001110000
    927  1.1  jdolecek         ;             RSB1DPWCAM
    928  1.1  jdolecek         MOV r13, r0                            ; save this value in r13
    929  1.1  jdolecek         MOV r1, #0
    930  1.1  jdolecek         CMP r14, #0
    931  1.1  jdolecek         EQUD %11101110000000010000111100010000 ; MCR cp15, 0, r0, c1, c0, 0 ; write control register
    932  1.1  jdolecek         EQUD %00011110000001110001111100010101 ; MCRNE cp15, 0, r1, c7, c5, 0 ; write 0 in v4 MMU disable
    933  1.1  jdolecek         MOV pc, r9                             ; call rest of code in physical mem ... not flat
    934  1.1  jdolecek 
    935  1.1  jdolecek       .physical_start_address%
    936  1.1  jdolecek         ; should now be running in physical space
    937  1.1  jdolecek         ; this relocate code can be heavyly optimised ... but it is used only once ... and is fast enough
    938  1.1  jdolecek         ; relocate kernel (physical to physical) + debug in screenmemory
    939  1.1  jdolecek         MOV  r5, r10                           ; load PC relative r5 = startreloc table
    940  1.1  jdolecek         LDR  r6, [r5], #4                      ; r4 = number of relocated pages
    941  1.1  jdolecek       .loop_relocate_pages%
    942  1.1  jdolecek         LDR  r2, [r5], #4                      ; r2 = from address
    943  1.1  jdolecek         LDR  r3, [r5], #4                      ; r3 = to address
    944  1.5   reinoud         LDR  r7, [r5], #4                      ; r7 = number of bytes to travel
    945  1.1  jdolecek         MOV  r1, #0                            ; r1 = offset in page
    946  1.1  jdolecek       .loop_one_page%
    947  1.1  jdolecek         LDRB r0, [r2, r1]
    948  1.1  jdolecek         STRB r0, [r3, r1]
    949  1.1  jdolecek         ADD  r1, r1, #1
    950  1.1  jdolecek         CMP  r1, r7                            ; all bytes copied ?
    951  1.1  jdolecek         BNE loop_one_page%
    952  1.1  jdolecek         SUBS r6, r6, #1
    953  1.1  jdolecek         BNE loop_relocate_pages%
    954  1.1  jdolecek 
    955  1.1  jdolecek         ; switch over to the new L1 pages
    956  1.1  jdolecek 
    957  1.1  jdolecek         ; disable clockswitching for SA110  (WHY?)
    958  1.1  jdolecek         MOV r0,  #0                            ; write 0
    959  1.1  jdolecek         CMP r14, #0                            ; check v4 .. or SA110 specific ?
    960  1.1  jdolecek         EQUD %00011110000011110000111101010010 ; MCRNE cp15, 0, r0, c15, c2, 2 ; from Linux loader
    961  1.1  jdolecek 
    962  1.1  jdolecek         ; flush ID cache
    963  1.1  jdolecek         MOV r0,  #0
    964  1.1  jdolecek         CMP r14, #0
    965  1.1  jdolecek         EQUD %00001110000001110000111100010000 ; MCREQ cp15, 0, r0, c7, c0, 0 ; flush v3 ID cache
    966  1.1  jdolecek         EQUD %00011110000001110000111100010111 ; MCRNE cp15, 0, r0, c7, c7, 0 ; flush v4 ID cache
    967  1.1  jdolecek 
    968  1.1  jdolecek         ; drain WB (v4)
    969  1.1  jdolecek         MOV r0,  #0
    970  1.1  jdolecek         CMP r14, #0
    971  1.1  jdolecek         EQUD %00011110000001110000111110011010 ; MCRNE cp15, 0, r0, c7, c10, 4; drain WB v4 from Linux loader
    972  1.1  jdolecek 
    973  1.1  jdolecek         ; flush TLB
    974  1.1  jdolecek         EQUD %11101110000001010000111100010000 ; MCR cp15, 0, r0, c5, c0, 0 ; flush v3 TLB
    975  1.1  jdolecek 
    976  1.1  jdolecek         ; set new TLB address
    977  1.1  jdolecek         MOV r0, r11
    978  1.1  jdolecek         EQUD %11101110000000100000111100010000 ; MCR cp15, 0, r0, c2, c0, 0 ; write TLB base
    979  1.1  jdolecek  
    980  1.1  jdolecek         ; switch on MMU, IDcache and WB and keep on running (flat *translated*)
    981  1.1  jdolecek         ; in r13 last written value
    982  1.1  jdolecek         ORR r0, r13, #%0001111101
    983  1.1  jdolecek         ;              RSB1DPWCAM
    984  1.1  jdolecek         ORR r0, r0,  #%1000000000
    985  1.1  jdolecek         CMP r14, #0
    986  1.1  jdolecek         EQUD %11101110000000010000111100010000 ; MCR cp15, 0, r0, c1, c0, 0 ; write control register
    987  1.1  jdolecek         MOV r0, r0                             ; flat
    988  1.1  jdolecek         MOV r0, r0                             ; flat
    989  1.1  jdolecek         ; not flat anymore ... but it doesnt matter
    990  1.1  jdolecek     ]
    991  1.1  jdolecek     IF extradebug% THEN
    992  1.1  jdolecek       [OPT opt%
    993  1.1  jdolecek         MOV r6, #videomem_start%
    994  1.1  jdolecek         MOV r7, #videomem_pages% * nbpp%
    995  1.1  jdolecek         MOV r5, #KERNEL_BASE
    996  1.1  jdolecek         .loop_testing%
    997  1.1  jdolecek           LDR r0, [r5], #4
    998  1.1  jdolecek           STR r0, [r6], #4
    999  1.1  jdolecek           SUBS r7, r7, #4
   1000  1.1  jdolecek         BNE loop_testing%
   1001  1.1  jdolecek        ]
   1002  1.1  jdolecek      ENDIF
   1003  1.1  jdolecek      [OPT opt%
   1004  1.1  jdolecek         ; call kernel in new virtual space ... start()
   1005  1.1  jdolecek 
   1006  1.1  jdolecek         MOV  r0, r8
   1007  1.1  jdolecek         MOV  pc, r12
   1008  1.1  jdolecek     ]
   1009  1.1  jdolecek   NEXT
   1010  1.1  jdolecek ENDPROC
   1011  1.1  jdolecek 
   1012  1.1  jdolecek 
   1013  1.1  jdolecek DEF FNblock_vaddr(pagenr%)
   1014  1.1  jdolecek =!(memoryblock% + pagenr%*12 + 4)
   1015  1.1  jdolecek 
   1016  1.1  jdolecek 
   1017  1.1  jdolecek DEF FNblock_paddr(pagenr%)
   1018  1.1  jdolecek =!(memoryblock% + pagenr%*12 + 8)
   1019  1.1  jdolecek 
   1020  1.1  jdolecek 
   1021  1.1  jdolecek DEF PROCget_memory_map
   1022  1.1  jdolecek   PRINT '"Getting actual memory mapping ";
   1023  1.1  jdolecek   FOR pg%=0 TO totalpages%-1
   1024  1.1  jdolecek     pos% = memoryblock% + 12*pg%
   1025  1.1  jdolecek     pos%!0  = 0
   1026  1.1  jdolecek     pos%!4  = (firstpage% + pg%) * nbpp%
   1027  1.1  jdolecek     pos%!8  = 0
   1028  1.1  jdolecek     REM force paging in this page in RO4
   1029  1.1  jdolecek     IF (pg% MOD 5)=0 THEN PROCtwirl
   1030  1.1  jdolecek     !(pos%!4) = 0: REM PROCbzero(pos%!4, nbpp%)
   1031  1.1  jdolecek   NEXT
   1032  1.1  jdolecek   PRINT ;" "
   1033  1.1  jdolecek  
   1034  1.1  jdolecek   os_memory_GIVEN_LOG_ADDR   = &200
   1035  1.1  jdolecek   os_memory_RETURN_PAGE_NO   = &800
   1036  1.1  jdolecek   os_memory_RETURN_PHYS_ADDR = &2000
   1037  1.1  jdolecek   SYS "OS_Memory", os_memory_GIVEN_LOG_ADDR+os_memory_RETURN_PAGE_NO+os_memory_RETURN_PHYS_ADDR, memoryblock%, totalpages%
   1038  1.1  jdolecek  
   1039  1.1  jdolecek   PROCsort_memory_map(memoryblock%, totalpages%)
   1040  1.1  jdolecek  
   1041  1.1  jdolecek   REM Get first DRAM index
   1042  1.1  jdolecek   PRINT '"Found memory blocks ";
   1043  1.1  jdolecek   first_mapped_DRAM_index%=-1
   1044  1.1  jdolecek   pg% = 0
   1045  1.1  jdolecek   WHILE pg%<totalpages%
   1046  1.1  jdolecek     addr% = !(memoryblock% + pg%*12 + 8)
   1047  1.1  jdolecek     PRINT "[";"0x";~addr%;
   1048  1.1  jdolecek     num_seq_pag%=0
   1049  1.1  jdolecek     WHILE (!(memoryblock% + pg%*12 + 12 + 8) - addr%)=nbpp%
   1050  1.1  jdolecek       IF first_mapped_DRAM_index%<0 AND (addr%>=DRAM_addr%(0)) THEN first_mapped_DRAM_index% = pg%
   1051  1.1  jdolecek       num_seq_pag%+=1
   1052  1.1  jdolecek       pg%+=1
   1053  1.1  jdolecek       addr% = !(memoryblock% + pg%*12 + 8)
   1054  1.1  jdolecek     ENDWHILE
   1055  1.1  jdolecek     PRINT;"-0x";~(!(memoryblock% + pg%*12 + 8) + nbpp%-1);"]";
   1056  1.1  jdolecek     PRINT ;"  ";
   1057  1.1  jdolecek     pg%+=1
   1058  1.1  jdolecek   ENDWHILE
   1059  1.1  jdolecek   PRINT'
   1060  1.1  jdolecek   IF extradebug% THEN PRINT '"First DRAM index found at index ";first_mapped_DRAM_index%;" DRAM_addr%(0)=0x";~DRAM_addr%(0)
   1061  1.6       wiz   IF first_mapped_DRAM_index%<0 THEN ERROR EXT 1, "No (S)DRAM mapped in this program (weird) ... increase Wimpslot!"
   1062  1.1  jdolecek ENDPROC
   1063  1.1  jdolecek 
   1064  1.1  jdolecek 
   1065  1.1  jdolecek DEF PROCget_memory_configuration
   1066  1.1  jdolecek   REM Get memory distribution
   1067  1.1  jdolecek   PRINT "Getting memory configuration ";
   1068  1.1  jdolecek   DIM DRAM_addr%(MAX_DRAMBANKS), DRAM_pages%(MAX_DRAMBANKS)
   1069  1.1  jdolecek   DIM VRAM_addr%(MAX_VRAMBANKS), VRAM_pages%(MAX_VRAMBANKS)
   1070  1.1  jdolecek   DIM memorytable% memorytablesize%
   1071  1.1  jdolecek   SYS "OS_Memory", 7, memorytable% : REM read table
   1072  1.1  jdolecek   dramblocks% = 0: vramblocks% = 0: currentpages% = 0: currentadr% = 0
   1073  1.1  jdolecek   currentpage% = -1: loop%=0
   1074  1.1  jdolecek   WHILE loop% < memorytablesize%*2
   1075  1.1  jdolecek     page% = memorytable%!(loop% DIV 2)
   1076  1.1  jdolecek     IF loop% MOD 2 THEN page% = page% >> 4
   1077  1.1  jdolecek     page% = page% AND &07
   1078  1.1  jdolecek     IF page% <> currentpage% THEN
   1079  1.1  jdolecek       IF currentpage% = 1 THEN
   1080  1.1  jdolecek         DRAM_addr%(dramblocks%) = currentaddr% * nbpp%
   1081  1.1  jdolecek         DRAM_pages%(dramblocks%) = currentpages%
   1082  1.1  jdolecek         dramblocks% +=1
   1083  1.1  jdolecek       ENDIF
   1084  1.1  jdolecek       IF currentpage%=2 THEN
   1085  1.1  jdolecek         VRAM_addr%(vramblocks%) = currentaddr% * nbpp%
   1086  1.1  jdolecek         VRAM_pages%(vramblocks%) = currentpages%
   1087  1.1  jdolecek         vramblocks% +=1
   1088  1.1  jdolecek        ENDIF
   1089  1.1  jdolecek       currentpage% = page%
   1090  1.1  jdolecek       currentaddr% = loop%
   1091  1.1  jdolecek       currentpages% = 0
   1092  1.1  jdolecek     ENDIF
   1093  1.1  jdolecek     currentpages% += 64
   1094  1.1  jdolecek     loop% += 64
   1095  1.1  jdolecek     PROCtwirl
   1096  1.1  jdolecek   ENDWHILE
   1097  1.1  jdolecek  
   1098  1.1  jdolecek   IF emulateDRAMsize% > 0 THEN
   1099  1.1  jdolecek     REM emulate HACK
   1100  1.1  jdolecek     DRAM0% = DRAM_addr%(0)
   1101  1.1  jdolecek     DRAM_addr%() = 0
   1102  1.1  jdolecek     DRAM_pages%() = 0
   1103  1.1  jdolecek     DRAM_addr%(0) = DRAM0%
   1104  1.1  jdolecek     DRAM_pages%(0) = (emulateDRAMsize%*1024*1024)/nbpp%
   1105  1.1  jdolecek     dramblocks% = 1
   1106  1.1  jdolecek     REM END HACK
   1107  1.1  jdolecek   ENDIF
   1108  1.1  jdolecek 
   1109  1.1  jdolecek   REM find top of DRAM pages
   1110  1.1  jdolecek   I%=8: WHILE (I%>=0) AND DRAM_addr%(I%)=0: I%-=1: ENDWHILE
   1111  1.1  jdolecek 
   1112  1.1  jdolecek   IF I%>=0 THEN top_drambank% = I% ELSE ERROR EXT 0, "Reality check: No DRAM banks??"
   1113  1.1  jdolecek   top_physdram% = DRAM_addr%(top_drambank%) + DRAM_pages%(top_drambank%)*nbpp%
   1114  1.1  jdolecek 
   1115  1.1  jdolecek   PRINT " "
   1116  1.1  jdolecek   PRINT'
   1117  1.1  jdolecek  
   1118  1.1  jdolecek   REM Emulate VRAM by reporting different memory sizes
   1119  1.1  jdolecek   REM XXX assumption : no VRAM => screen is located in bottom DRAM; leave it there
   1120  1.1  jdolecek   IF (VRAM_pages%(0)=0) OR emulateVRAM% THEN
   1121  1.1  jdolecek     mapped_screenmemory% = 1024*1024 : REM Max allowed on RiscPC
   1122  1.1  jdolecek     videomem_start% = DRAM_addr%(0)
   1123  1.1  jdolecek     videomem_pages% = mapped_screenmemory% DIV nbpp%
   1124  1.1  jdolecek     display_size%   = FNvdu_var(150) AND NOT(nbpp%-1)
   1125  1.1  jdolecek     DRAM_addr%(0)  += videomem_pages% * nbpp%
   1126  1.1  jdolecek     DRAM_pages%(0) -= videomem_pages%
   1127  1.1  jdolecek   ELSE
   1128  1.1  jdolecek     mapped_screenmemory% = 0
   1129  1.1  jdolecek     videomem_start% = VRAM_addr%(0)
   1130  1.1  jdolecek     videomem_pages% = VRAM_pages%(0)
   1131  1.1  jdolecek     display_size%   = videomem_pages% * nbpp%
   1132  1.1  jdolecek   ENDIF
   1133  1.1  jdolecek  
   1134  1.1  jdolecek   IF mapped_screenmemory%>0 THEN PRINT "Used 1st Mb of DRAM at 0x";RIGHT$("00000000"+STR$~videomem_start%,8);" for video memory"
   1135  1.1  jdolecek 
   1136  1.1  jdolecek   totaldrampages% = 0
   1137  1.1  jdolecek   FOR I%=0 TO dramblocks%-1
   1138  1.1  jdolecek     totaldrampages% += DRAM_pages%(I%)
   1139  1.1  jdolecek     PRINT "Found ";
   1140  1.1  jdolecek     IF (DRAM_addr%(I%) >= SDRAM_ADDR_START%) PRINT ;"SDRAM"; ELSE PRINT ;" DRAM";
   1141  1.1  jdolecek     PRINT " (";I%;") at 0x";RIGHT$("00000000"+STR$~DRAM_addr%(I%),8);" for ";,DRAM_pages%(I%)*nbpp%/1024;" k"
   1142  1.1  jdolecek   NEXT
   1143  1.1  jdolecek 
   1144  1.1  jdolecek   totalvrampages% = 0
   1145  1.1  jdolecek   FOR I%=0 TO vramblocks%-1
   1146  1.1  jdolecek     totalvrampages% += VRAM_pages%(I%)
   1147  1.1  jdolecek     PRINT "Found  VRAM (";I%;") at 0x";RIGHT$("00000000"+STR$~VRAM_addr%(I%),8);" for ";,VRAM_pages%(I%)*nbpp%/1024;" k"
   1148  1.1  jdolecek   NEXT
   1149  1.1  jdolecek  
   1150  1.1  jdolecek   kernel_phys_start% = DRAM_addr%(0)
   1151  1.1  jdolecek  
   1152  1.1  jdolecek   REM Expirimental Kinetic support
   1153  1.1  jdolecek   IF INSTR(args$, "kinetic")>0 THEN
   1154  1.1  jdolecek     REM The Kinetic card has SDRAM on the processor module ... first fix is to only use this memory
   1155  1.4       wiz     REM for VRAM emulation and only pass it through as buffer memory for the DRAM is the only one
   1156  1.7    andvar     REM with DMA capabilities.
   1157  1.1  jdolecek  
   1158  1.1  jdolecek     PRINT ''"Kinetic support asked ... ";
   1159  1.1  jdolecek  
   1160  1.1  jdolecek     REM find SDRAM start... DRAM is under 512 Mb, SDRAM is above it
   1161  1.1  jdolecek     first_SDRAM% = -1
   1162  1.2     chris     FOR I%=0 TO MAX_DRAMBANKS
   1163  1.1  jdolecek       IF (DRAM_addr%(I%) >= SDRAM_ADDR_START%) AND (first_SDRAM%<0) THEN first_SDRAM% = I%
   1164  1.1  jdolecek     NEXT
   1165  1.1  jdolecek     IF first_SDRAM% >= 0 THEN
   1166  1.1  jdolecek       PRINT ;"granted"
   1167  1.1  jdolecek       REM put kernel pointer to the first SDRAM module and update DRAM reporting (yeah ...more clear than fast)
   1168  1.1  jdolecek       FOR I%=0 TO first_SDRAM%-1
   1169  1.1  jdolecek         PRINT "Moving DRAM at 0x";RIGHT$("00000000"+STR$~DRAM_addr%(I%),8);" for ";,DRAM_pages%(I%)*nbpp%/1024;" k"
   1170  1.1  jdolecek         REM save this block
   1171  1.1  jdolecek         DRAM_addr% = DRAM_addr%(I%): DRAM_pages% = DRAM_pages%(I%)
   1172  1.1  jdolecek         REM move everything down
   1173  1.2     chris         FOR J%=I% TO MAX_DRAMBANKS-1
   1174  1.1  jdolecek           DRAM_addr%(J%) = DRAM_addr%(J%+1): DRAM_pages%(J%) = DRAM_pages%(J%+1)
   1175  1.1  jdolecek         NEXT
   1176  1.2     chris         DRAM_addr%(MAX_DRAMBANKS) = 0: DRAM_pages%(MAX_DRAMBANKS) = 0
   1177  1.1  jdolecek         REM fill in the moved block at the top of the structure
   1178  1.1  jdolecek         DRAM_addr%(dramblocks%-1) = DRAM_addr%: DRAM_pages%(dramblocks%-1) = DRAM_pages%
   1179  1.1  jdolecek       NEXT
   1180  1.1  jdolecek       REM XXX kernel is loaded per definition in dram[0]
   1181  1.1  jdolecek       first_SDRAM% = 0
   1182  1.1  jdolecek       kernel_phys_start% = DRAM_addr%(first_SDRAM%)
   1183  1.1  jdolecek     ELSE
   1184  1.1  jdolecek       PRINT ;"ignored; no SDRAM found"
   1185  1.1  jdolecek     ENDIF
   1186  1.1  jdolecek     PRINT
   1187  1.1  jdolecek   ENDIF
   1188  1.1  jdolecek ENDPROC
   1189  1.1  jdolecek 
   1190  1.1  jdolecek 
   1191  1.1  jdolecek DEF PROCsort_memory_map(memoryblock%, totalpages%)
   1192  1.1  jdolecek   LOCAL out%, in%, outp%, inp%
   1193  1.1  jdolecek 
   1194  1.1  jdolecek   DIM code% 1024
   1195  1.1  jdolecek   FOR opt%=0 TO 2 STEP 2
   1196  1.1  jdolecek     P%=code%
   1197  1.1  jdolecek     [OPT opt%
   1198  1.1  jdolecek      .sortit%
   1199  1.1  jdolecek           STMFD r13!, {r0-r12}
   1200  1.1  jdolecek           ; R0  = A% = memory block%
   1201  1.1  jdolecek           ; R1  = B% = totalpages%
   1202  1.1  jdolecek           ; r2  = out%
   1203  1.1  jdolecek           ; r3  = inp%
   1204  1.1  jdolecek           ; R12 = limit r3
   1205  1.1  jdolecek           SUB r2, r1, #2
   1206  1.1  jdolecek      .loop_outer%
   1207  1.1  jdolecek           MOV r3, r0
   1208  1.1  jdolecek           MOV r4, #12
   1209  1.1  jdolecek           MLA r12, r2, r4, r0
   1210  1.1  jdolecek      .loop_inner%
   1211  1.1  jdolecek           LDR r4, [r3, #8]
   1212  1.1  jdolecek           LDR r5, [r3, #20]
   1213  1.1  jdolecek           CMP r4, r5
   1214  1.1  jdolecek           BLT not_bigger%
   1215  1.1  jdolecek             LDMIA r3, {r6, r7, r8}
   1216  1.1  jdolecek             ADD r4, r3, #12
   1217  1.1  jdolecek             LDMIA r4, {r9, r10, r11}
   1218  1.1  jdolecek             STMIA r3, {r9, r10, r11}
   1219  1.1  jdolecek             STMIA r4, {r6, r7, r8}
   1220  1.1  jdolecek      .not_bigger%
   1221  1.1  jdolecek           ADD r3, r3, #12
   1222  1.1  jdolecek           CMP r3, r12
   1223  1.1  jdolecek           BLE loop_inner%
   1224  1.1  jdolecek           SUBS r2, r2, #1
   1225  1.1  jdolecek           BPL loop_outer%
   1226  1.1  jdolecek           LDMFD r13!, {r0-r12}
   1227  1.1  jdolecek           MOV pc, r14
   1228  1.1  jdolecek   ]
   1229  1.1  jdolecek   NEXT
   1230  1.1  jdolecek 
   1231  1.1  jdolecek   A% = memoryblock%
   1232  1.1  jdolecek   B% = totalpages%
   1233  1.1  jdolecek   CALL sortit%
   1234  1.1  jdolecek 
   1235  1.1  jdolecek ENDPROC
   1236  1.1  jdolecek 
   1237  1.1  jdolecek 
   1238  1.1  jdolecek DEF PROCcenter(line$)
   1239  1.1  jdolecek   PRINT STRING$((width%-LEN(line$))/2, " ");line$
   1240  1.1  jdolecek ENDPROC
   1241  1.1  jdolecek 
   1242  1.1  jdolecek 
   1243  1.1  jdolecek DEF PROCbzero(addr%, len%)
   1244  1.1  jdolecek   LOCAL a%
   1245  1.1  jdolecek   FOR a% = 0 TO len%-4 STEP 4
   1246  1.1  jdolecek     addr%!a% = 0
   1247  1.1  jdolecek   NEXT
   1248  1.1  jdolecek ENDPROC
   1249  1.1  jdolecek 
   1250  1.1  jdolecek 
   1251  1.1  jdolecek DEF PROCcopy(dest%, src%, len%)
   1252  1.1  jdolecek   LOCAL a%
   1253  1.1  jdolecek   FOR a% = 0 TO len%-4 STEP 4
   1254  1.1  jdolecek     dest%!a% = src%!a%
   1255  1.1  jdolecek   NEXT
   1256  1.1  jdolecek ENDPROC
   1257  1.1  jdolecek 
   1258  1.1  jdolecek 
   1259  1.1  jdolecek DEF PROCtwirl
   1260  1.1  jdolecek   PRINT MID$("|/-\", twirl%+1, 1)+CHR$(8);
   1261  1.1  jdolecek   twirl% += 1
   1262  1.1  jdolecek   twirl% = twirl% MOD 4
   1263  1.1  jdolecek ENDPROC
   1264  1.1  jdolecek 
   1265  1.1  jdolecek 
   1266  1.1  jdolecek DEF FNvdu_var(var%)
   1267  1.1  jdolecek   LOCAL b%
   1268  1.1  jdolecek   DIM b% 7
   1269  1.1  jdolecek   b%!0 = var%
   1270  1.1  jdolecek   b%!4 = -1
   1271  1.1  jdolecek   SYS "OS_ReadVduVariables", b%, b%
   1272  1.1  jdolecek = b%!0
   1273  1.1  jdolecek 
   1274  1.1  jdolecek 
   1275  1.1  jdolecek DEF FNroundup(val%, size%)
   1276  1.1  jdolecek =val% + (size% - 1) AND NOT (size% - 1)
   1277  1.1  jdolecek 
   1278  1.1  jdolecek 
   1279  1.1  jdolecek DEF FNtolower(name$)
   1280  1.1  jdolecek   LOCAL A$, Ch$, i%
   1281  1.1  jdolecek   FOR i%=1 TO LEN(name$)
   1282  1.1  jdolecek     Ch$ = LEFT$(name$,1)
   1283  1.1  jdolecek     IF Ch$>="A" AND Ch$<="Z" THEN
   1284  1.1  jdolecek       A$ += CHR$(ASC(Ch$)+ASC("a")-ASC("A"))
   1285  1.1  jdolecek     ELSE
   1286  1.1  jdolecek       A$ += Ch$
   1287  1.1  jdolecek     ENDIF
   1288  1.1  jdolecek     name$ = MID$(name$, 2)
   1289  1.1  jdolecek   NEXT
   1290  1.1  jdolecek = A$
   1291  1.3     bjh21 
   1292  1.3     bjh21 DEF FNawaitkey(timeout%)
   1293  1.3     bjh21   LOCAL i%, i$, c%
   1294  1.3     bjh21   REM Flush keyboard buffer first
   1295  1.3     bjh21   REPEAT UNTIL INKEY(0) = -1
   1296  1.3     bjh21   FOR i% = timeout% TO 1 STEP -1
   1297  1.3     bjh21     i$ = STR$(i%)
   1298  1.3     bjh21     PRINT ; i% STRING$(LEN(i$), CHR$(8));
   1299  1.3     bjh21     c% = INKEY(100)
   1300  1.3     bjh21     IF c% <> -1 THEN
   1301  1.3     bjh21       PRINT
   1302  1.3     bjh21       = c%
   1303  1.3     bjh21     ENDIF
   1304  1.3     bjh21   NEXT
   1305  1.3     bjh21   PRINT "0"
   1306  1.3     bjh21 = 0
   1307