>BBBB 7 $Id: BBBB,fd1,v 1.3 2000/02/18 22:10:19 ben Exp $  (/ Copyright (c) 1998, 1999, 2000 Ben Harris 2 All rights reserved. < FH Redistribution and use in source and binary forms, with or without PH modification, are permitted provided that the following conditions Z are met: dG 1. Redistributions of source code must retain the above copyright nF notice, this list of conditions and the following disclaimer. xJ 2. Redistributions in binary form must reproduce the above copyright L notice, this list of conditions and the following disclaimer in the M documentation and/or other materials provided with the distribution. N 3. The name of the author may not be used to endorse or promote products N derived from this software without specific prior written permission.  J THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR O IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES M OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. F IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, N INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT O NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, K DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY I THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT N (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF G THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  "O This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. , 6( Ben's BASIC BSD Booter (allegedly) @debug% = 1 J ">> BBBB, Revision 0.30" T+ș "OS_ReadMemMapInfo" nbpp%, npages% ^ debug% hE "Machine has ";npages%;" pages of ";nbpp% 1024;"K each. "; r8 "Total RAM: ";npages% * nbpp% 1024 1024;"Mb" | "Lowering HIMEM: &";~;   = &10000  debug% " -> &";~  twirl% = 0  = vaddr%(npages%-1), access%(npages%-1), pgok%(npages%-1) pgok%() =  get_mem_map ș "OS_GetEnv" A$  debug% A$ 2ȕ A$, 1) <> " " (A$) > 0 A$ = A$, 2) : %ȕ A$, 1) = " " A$ = A$, 2) : !ȕ A$,1) = " " A$ = A$) : # tolower(A$, 5)) = "-quit" & A$ = A$, 7) 04 ȕ A$, 1) <> " " (A$) > 0 A$ = A$, 2) : :' ȕ A$, 1) = " " A$ = A$, 2) : D Nfile$ = "" Xhowto% = 0 bȕ (A$) > 0 l Ȏ A$, 1) v "-"  done% =   A$ = A$, 2) " Ȏ tolower(A$, 1)) : "a" : howto% = howto% &01 : RB_ASKNAME 9 "s" : howto% = howto% &02 : RB_SINGLE 6 "d" : howto% = howto% &40 : RB_KDB # " ", "" : done% = 1  : 0, "Bad option: " + A$, 1)   done%  " "  A$ = A$, 2)    2 file$ <> "" 0, "Too many files!" ' ȕ A$, 1) <> " " (A$) > 0   file$ += A$,1) * A$ = A$, 2) 4 > H R# file$ = "" (howto% &01) \ "boot: "file$ f p% file$ = "" file$ = "netbsd" z 5 "Booting "; file$; " (howto = 0x"; ~howto%; ")" load_kernel(file$)  P% 1023   [ OPT 2  .config% ( EQUD &942B7DFE ; magic * EQUD 0 ; version , EQUD howto% ; boothowto * EQUD 0 ; bootdev ' EQUD ssym% ; ssym ' EQUD esym% ; esym ' EQUD nbpp% ; nbpp ) EQUD npages% ; npages * EQUD txtbase% ; txtbase * EQUD txtsize% ; txtsize $+ EQUD database% ; database .+ EQUD datasize% ; datasize 8* EQUD bssbase% ; bssbase B* EQUD bsssize% ; bsssize L+ EQUD freebase% ; freebase V) EQUD vdu_var(11) + 1 ; xpixels `) EQUD vdu_var(12) + 1 ; ypixels j% EQUD 1 << vdu_var(9) ; bpp tH EQUD vdu_var(149) + vdu_var(150) - &02000000 ; screenbase (XXX?) ~, EQUD vdu_var(150) ; screensize ] ș "OS_Byte", 165 ,,crow%  [ OPT 2 , EQUD crow% * vdu_var(170) ; cpixelrow ] ! }; +start_kernel(config%, 0, 0, 0, entry%)    get_mem_map  block%  block% (npages%+1)*12  page%=0 npages%-1  ! block%!(page%*12) = page%   block%!(npages%*12) = -1 (' ș "OS_ReadMemMapEntries", block% 2 page% = 0 npages%-1 <+ vaddr%(page%) = block%!(page%*12+4) F, access%(page%) = block%!(page%*12+8) P Z5 debug% "--------/-------/-------/-------" d page%=0 npages%-1 n access%(page%) = 3 x debug% ".";   Ȏ 9 vaddr%(page%) < &0008000: debug% "0"; 9 vaddr%(page%) < &0010000: debug% "+"; ' vaddr%(page%) < &1000000: $ access%(page%) = 0 ! debug% "*";  pgok%(page%) =  " debug% "a";  9 vaddr%(page%) < &1400000: debug% "d"; 9 vaddr%(page%) < &1800000: debug% "s"; 9 vaddr%(page%) < &1C00000: debug% "m"; 9 vaddr%(page%) < &1E00000: debug% "h"; 9 vaddr%(page%) < &1F00000: debug% "f"; "9 vaddr%(page%) < &2000000: debug% "S"; , 6 @& page% 32 = 31 debug% J T ^ h load_kernel(file$) r file%, magic% | file% = (file$) , file% = 0 1, "Can't open kernel"  magic% 3 * ș "OS_GBPB", 3, file%, magic%, 4, 0 T magic%?0 = 127 magic%?1 = ("E") magic%?2 = ("L") magic%?3 = ("F")  load_kernel_elf(file%)   load_kernel_aout(file%)   #file%    load_kernel_elf(file%) 5 hdr%, phoff%, phentsize%, phnum%, phdrs%, ph% 8 offset%, vaddr%, filesz%, memsz%, flags%, first% C shoff%, shentsize%, shnum%, shdrs%, sh%, havesyms%, mshdrs%  hdr% 51 &) ș "OS_GBPB", 3, file%, hdr%, 52, 0 02 hdr%?4 <> 1 1, "Not a 32-bit ELF file" :0 hdr%?5 <> 1 1, "Not an LSB ELF file" D5 hdr%?6 <> 1 1, "Not a version-1 ELF file" ND hdr%?7 is EI_OSABI. Should it be 255 (ELFOSABI_STANDALONE)? XB (hdr%!16 &FFFF) <> 2 1, "Not an executable ELF file" b< (hdr%!18 &FFFF) <> 40 1, "Not an ARM ELF file" l entry% = hdr%!24 v phoff% = hdr%!28  shoff% = hdr%!32 " phentsize% = hdr%!42 &FFFF  phnum% = hdr%!44 &FFFF " shentsize% = hdr%!46 &FFFF  shnum% = hdr%!48 &FFFF & phdrs% phnum% * phentsize% - 1 A ș "OS_GBPB", 3, file%, phdrs%, phnum% * phentsize%, phoff% . phnum% = 0 1, "No program headers"  first% = F ph% = phdrs% phdrs% + (phnum% - 1) * phentsize% phentsize% / ph%!0 <> 1 : We only do PT_LOAD  first% "+";  first% =  offset% = ph%!4   vaddr% = ph%!8  filesz% = ph%!16   memsz% = ph%!20 * flags% = ph%!24 4< load_chunk(file%, offset%, vaddr%, filesz%, memsz%) >7 freebase% = vaddr% - &02000000 + memsz% : XXX H R txtbase% = 0 \ txtsize% = 0 f database% = 0 p datasize% = 0 z bssbase% = 0  bsssize% = 0  ssym% = 0  esym% = 0 & shdrs% shnum% * shentsize% - 1 A ș "OS_GBPB", 3, file%, shdrs%, shnum% * shentsize%, shoff%  shnum% <> 0  havesyms% = H sh% = shdrs% shdrs% + (shnum% - 1) * shentsize% shentsize% % sh%!4 = 2 havesyms% =   havesyms%  ssym% = freebase% 0 First, we have the munged ELF header  "+["; : load_chunk(file%, 0, &02000000 + ssym%, 52, 52) # write_word(ssym%+32, 52) $ freebase% += 52 ., then, the munged section headers 8 mshdrs% = freebase% B "+"; Lc load_chunk(file%, shoff%, &02000000 + mshdrs%, shnum% * shentsize%, shnum% * shentsize%) V* freebase% += shnum% * shentsize% `J sh% = shdrs% shdrs% + (shnum% - 1) * shentsize% shentsize% j% sh%!4 = 2 sh%!4 = 3 t "+"; ~O load_chunk(file%, sh%!16, &02000000 + freebase%, sh%!20, sh%!20) I write_word(mshdrs% + sh% - shdrs% + 16, freebase% - ssym%) . freebase% += roundup(sh%!20, 4)  esym% = freebase%  "]";  " " XXX   : load_chunk(file%, offset%, vaddr%, filesz%, memsz%) ( paddr%, ppn%, fragaddr%, fragsz%  ;filesz%;  ȕ filesz% > 0 (# paddr% = vaddr% - &02000000 2 ppn% = paddr% nbpp% <> pgok%(ppn%) 1, "Page " + (ppn$) + " not free" F1 fragaddr% = vaddr%(ppn%) + paddr% nbpp% P* fragsz% = nbpp% - (paddr% nbpp%) Z/ fragsz% > filesz% fragsz% = filesz% d; ș "OS_GBPB", 3, file%, fragaddr%, fragsz%, offset% n twirl x offset% += fragsz%  vaddr% += fragsz%  filesz% -= fragsz%  memsz% -= fragsz%  memsz% > 0 "+";memsz%;  ȕ memsz% > 0 # paddr% = vaddr% - &02000000  ppn% = paddr% nbpp% > pgok%(ppn%) 1, "Page " + (ppn$) + " not free" 1 fragaddr% = vaddr%(ppn%) + paddr% nbpp% ) fragsz = nbpp% - (paddr% nbpp%) - fragsz% > memsz% fragsz% = memsz% " bzero(fragaddr%, fragsz%)  twirl  offset% += fragsz%  vaddr% += fragsz% " filesz% -= fragsz% , memsz% -= fragsz% 6 @ J T write_word(paddr%, val%) ^7 !(vaddr%(paddr% nbpp%) + paddr% nbpp%) = val% h r | load_kernel_aout(file%) hdr%  hdr% 32  ssym% = 0 : esym% = 0 ) ș "OS_GBPB", 3, file%, hdr%, 32, 0 H bemagic% = (hdr%?0 << 24) (hdr%?1 <<16) (hdr%?2 << 8) hdr%?3  debug% ! Ȏ bemagic% &0000FFFF  &0107  "(OMAGIC)";  &0108  "(NMAGIC)";  &010B  "(ZMAGIC)";  &00CC  "(QMAGIC)";  & 0 XXX: Assume ZMAGIC : DJ foooff% is byte offset in file. foobasepage% is base page in RAM. N txtoff% = nbpp% X txtbase% = &98000 b% txtbasepage% = txtbase% nbpp% l txtsize% = hdr%!4 v txtsize% nbpp% <> 0 6 1, "Text size not a multiple of page size"  " txtpages% = txtsize% nbpp% # dataoff% = txtoff% + txtsize% . databasepage% = txtbasepage% + txtpages% ' database% = databasepage% * nbpp%  datasize% = hdr%!8 datasize% nbpp% <> 0 6 1, "Data size not a multiple of page size"  $ datapages% = datasize% nbpp% / bssbasepage% = databasepage% + datapages% % bssbase% = bssbasepage% * nbpp%  bsssize% = hdr%!12 % freebase% = bssbase% + bsssize%  entry% = hdr%!20  * ;txtsize%; 4 pg% = 0 txtpages%-1 >< pgok%(txtbasepage% + pg%) 0,"Page not mine!" HT ș "OS_GBPB", 3, file%, vaddr%(txtbasepage%+pg%), nbpp%, txtoff% + pg%*nbpp% R twirl \ f p "+";datasize%; z pg% = 0 datapages%-1 = pgok%(databasepage% + pg%) 0,"Page not mine!" V ș "OS_GBPB", 3, file%, vaddr%(databasepage%+pg%), nbpp%, dataoff% + pg%*nbpp%  twirl    "+";bsssize%; 8 pg% = 0 bsssize% nbpp% : overshoot is safe < pgok%(bssbasepage% + pg%) 0,"Page not mine!" / bzero(vaddr%(bssbasepage%+pg%), nbpp%)  twirl   " "    $ twirl .# "|/-\", twirl%+1, 1)+(8); 8 twirl% += 1 B twirl% = twirl% 4 L V ` tolower(string$) j ptr%, c%, out$ t out$ = "" ~ string$ = "" =string$  ptr% = 1 (string$) " c% = (string$, ptr%, 1)) 0 c% >= ("A") c% <= ("Z") c% += 32  out$ += (c%)   =out$   bzero(addr%, len%)  a%  a% = 0 len%-4 4  addr%!a% = 0     ' start_kernel(A%, B%, C%, D%, E%)  parameters: (# R0: -> bootconfig structure 2 R1: unused < R2: unused F R3: unused P R4: kernel entry point Z asm%, P% d asm% 256 n pass% = 0 2 2 x P%=asm%  [ OPT pass%  STMFD R13!,{R14}  STMFD R13!,{R0-R4}  ] ' swi_valid("Cache_Control")  [ OPT pass%  MOV R0, 1 ' MVN R1, 1 ; Disable cache ! SWI "Cache_Control"  SWI "Cache_Flush"  ]   [ OPT pass%  MOV R0, #1  SWI "Sound_Enable"  SWI "OS_IntOff" " LDMFD R13!, {R0-R4} , SWI "OS_EnterOS" 6G ; We now attempt to be APCS compliant on entry to the kernel. @@ ; Kernel APCS is 26bit/explicit/nofpregs/non-reentrant JM ; Kernel stack is &02090000--&02088000 and coincides with RISC OS's T0 ; system stack page on >=4Mb machines. ^ ADR R5, regs% h LDMIA R5, {R10-R14} r MOV PC, R4 | .regs% / EQUD &02088000; R10 -- Stack limit E EQUD &00000000; R11 -- Frame pointer (NULL in this case) B EQUD &00000000; R12 -- Scratch in non-re-entrant APCS 1 EQUD &02090000; R13 -- Stack pointer ; EQUD &03800003; R14 -- Return address and mode  ]   asm%    swi_valid(swi$)  flags% 2 ș "XOS_SWINumberFromString",,swi$ ;flags%  flags% 1 = =  & vdu_var(var%) 0 b% : b% 7 D b%!0 = var% N b%!4 = -1 X& ș "OS_ReadVduVariables", b%, b% b = b%!0 l v roundup(val%, size%) '=val% + (size% - 1) (size% - 1)