Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / sparc / stand / bootblk / bootblk.fth
blob6401095ff816bc3822cfb9e2e083f48fb937a131
1 \       $NetBSD: bootblk.fth,v 1.8 2008/06/29 14:13:23 jdc Exp $
3 \       IEEE 1275 Open Firmware Boot Block
5 \       Parses disklabel and UFS and loads the file called `ofwboot'
8 \       Copyright (c) 1998 Eduardo Horvath.
9 \       All rights reserved.
11 \       Redistribution and use in source and binary forms, with or without
12 \       modification, are permitted provided that the following conditions
13 \       are met:
14 \       1. Redistributions of source code must retain the above copyright
15 \          notice, this list of conditions and the following disclaimer.
16 \       2. Redistributions in binary form must reproduce the above copyright
17 \          notice, this list of conditions and the following disclaimer in the
18 \          documentation and/or other materials provided with the distribution.
20 \       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 \       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 \       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 \       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 \       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 \       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 \       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 \       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 \       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 \       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 offset16
33 hex
34 headers
36 false value boot-debug?
39 \ First some housekeeping:  Open /chosen and set up vectors into
40 \       client-services
42 " /chosen" find-package 0=  if ." Cannot find /chosen" 0 then
43 constant chosen-phandle
45 " /openprom/client-services" find-package 0=  if 
46         ." Cannot find client-services" cr abort
47 then constant cif-phandle
49 defer cif-claim ( align size virt -- base )
50 defer cif-release ( size virt -- )
51 defer cif-open ( cstr -- ihandle|0 )
52 defer cif-close ( ihandle -- )
53 defer cif-read ( len adr ihandle -- #read )
54 defer cif-seek ( low high ihandle -- -1|0|1 )
55 \ defer cif-peer ( phandle -- phandle )
56 \ defer cif-getprop ( len adr cstr phandle -- )
58 : find-cif-method ( method,len -- xf )
59    cif-phandle find-method drop 
62 " claim" find-cif-method to cif-claim
63 " open" find-cif-method to cif-open
64 " close" find-cif-method to cif-close
65 " read" find-cif-method to cif-read
66 " seek" find-cif-method to cif-seek
68 : twiddle ( -- ) ." ." ; \ Need to do this right.  Just spit out periods for now.
71 \ Support routines
74 : strcmp ( s1 l1 s2 l2 -- true:false )
75    rot tuck <> if  3drop false exit then
76    comp 0=
79 \ Move string into buffer
81 : strmov ( s1 l1 d -- d l1 )
82    dup 2over swap -rot          ( s1 l1 d s1 d l1 )
83    move                         ( s1 l1 d )
84    rot drop swap
87 \ Move s1 on the end of s2 and return the result
89 : strcat ( s1 l1 s2 l2 -- d tot )
90    2over swap                           ( s1 l1 s2 l2 l1 s1 )
91    2over + rot                          ( s1 l1 s2 l2 s1 d l1 )
92    move rot +                           ( s1 s2 len )
93    rot drop                             ( s2 len )
96 : strchr ( s1 l1 c -- s2 l2 )
97    begin
98       dup 2over 0= if                   ( s1 l1 c c s1  )
99          2drop drop exit then
100       c@ = if                           ( s1 l1 c )
101          drop exit then
102       -rot /c - swap ca1+               ( c l2 s2 )
103      swap rot
104   again
107    
108 : cstr ( ptr -- str len )
109    dup 
110    begin dup c@ 0<>  while + repeat
111    over -
115 \ BSD FFS parameters
118 fload   assym.fth.h
120 sbsize buffer: sb-buf
121 -1 value boot-ihandle
122 dev_bsize value bsize
123 0 value raid-offset     \ Offset if it's a raid-frame partition
124 false value force-raid  \ Force reads from raid offset
126 : strategy ( addr size start -- nread )
127    raid-offset + bsize * 0 " seek" boot-ihandle $call-method
128    -1 = if 
129       ." strategy: Seek failed" cr
130       abort
131    then
132    " read" boot-ihandle $call-method
136 \ Cylinder group macros
139 : cgbase ( cg fs -- cgbase ) fs_fpg l@ * ;
140 : cgstart ( cg fs -- cgstart ) 
141    2dup fs_old_cgmask l@ not and                ( cg fs stuff -- )
142    over fs_old_cgoffset l@ * -rot               ( stuffcg fs -- )
143    cgbase +
145 : cgdmin ( cg fs -- 1st-data-block ) dup fs_dblkno l@ -rot cgstart + ;
146 : cgimin ( cg fs -- inode-block ) dup fs_iblkno l@ -rot cgstart + ;
147 : cgsblock ( cg fs -- super-block ) dup fs_sblkno l@ -rot cgstart + ;
148 : cgstod ( cg fs -- cg-block ) dup fs_cblkno l@ -rot cgstart + ;
151 \ Block and frag position macros
154 : blkoff ( pos fs -- off ) fs_qbmask x@ and ;
155 : fragoff ( pos fs -- off ) fs_qfmask x@ and ;
156 : lblktosize ( blk fs -- off ) fs_bshift l@ << ;
157 : lblkno ( pos fs -- off ) fs_bshift l@ >> ;
158 : numfrags ( pos fs -- off ) fs_fshift l@ >> ;
159 : blkroundup ( pos fs -- off ) dup fs_bmask l@ -rot fs_qbmask x@ + and ;
160 : fragroundup ( pos fs -- off ) dup fs_fmask l@ -rot fs_qfmask x@ + and ;
161 \ : fragroundup ( pos fs -- off ) tuck fs_qfmask x@ + swap fs_fmask l@ and ;
162 : fragstoblks ( pos fs -- off ) fs_fragshift l@ >> ;
163 : blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ;
164 : fragnum ( fsb fs -- off ) fs_frag l@ 1- and ;
165 : blknum ( fsb fs -- off ) fs_frag l@ 1- not and ;
166 : dblksize ( lbn dino fs -- size )
167    -rot                                 ( fs lbn dino )
168    di_size x@                           ( fs lbn di_size )
169    -rot dup 1+                          ( di_size fs lbn lbn+1 )
170    2over fs_bshift l@                   ( di_size fs lbn lbn+1 di_size b_shift )
171    rot swap <<  >=                      ( di_size fs lbn res1 )
172    swap ndaddr >= or if                 ( di_size fs )
173       swap drop fs_bsize l@ exit        ( size )
174    then tuck blkoff swap fragroundup    ( size )
178 : ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ;
179 : ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ;
180 : ino-to-fsba ( ino fs -- ba )  \ Need to remove the stupid stack diags someday
181    2dup                                 ( ino fs ino fs )
182    ino-to-cg                            ( ino fs cg )
183    over                                 ( ino fs cg fs )
184    cgimin                               ( ino fs inode-blk )
185    -rot                                 ( inode-blk ino fs )
186    tuck                                 ( inode-blk fs ino fs )
187    fs_ipg l@                            ( inode-blk fs ino ipg )
188    mod                                  ( inode-blk fs mod )
189    swap                                 ( inode-blk mod fs )
190    dup                                  ( inode-blk mod fs fs )
191    fs_inopb l@                          ( inode-blk mod fs inopb )
192    rot                                  ( inode-blk fs inopb mod )
193    swap                                 ( inode-blk fs mod inopb )
194    /                                    ( inode-blk fs div )
195    swap                                 ( inode-blk div fs )
196    blkstofrags                          ( inode-blk frag )
197    +
199 : fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ;
202 \ File stuff
205 niaddr /w* constant narraysize
207 struct 
208    8            field   >f_ihandle      \ device handle
209    8            field   >f_seekp        \ seek pointer
210    8            field   >f_fs           \ pointer to super block
211    ufs1_dinode_SIZEOF   field   >f_di   \ copy of on-disk inode
212    8            field   >f_buf          \ buffer for data block
213    4            field   >f_buf_size     \ size of data block
214    4            field   >f_buf_blkno    \ block number of data block
215 constant file_SIZEOF
217 file_SIZEOF buffer: the-file
218 sb-buf the-file >f_fs x!
220 ufs1_dinode_SIZEOF buffer: cur-inode
221 h# 2000 buffer: indir-block
222 -1 value indir-addr
225 \ Translate a fileblock to a disk block
227 \ We only allow single indirection
230 : block-map ( fileblock -- diskblock )
231    \ Direct block?
232    dup ndaddr <  if                     ( fileblock )
233       cur-inode di_db                   ( arr-indx arr-start )
234       swap la+ l@ exit                  ( diskblock )
235    then                                 ( fileblock )
236    ndaddr -                             ( fileblock' )
237    \ Now we need to check the indirect block
238    dup sb-buf fs_nindir l@ <  if        ( fileblock' )
239       cur-inode di_ib l@ dup            ( fileblock' indir-block indir-block )
240       indir-addr <>  if                 ( fileblock' indir-block )
241          to indir-addr                  ( fileblock' )
242          indir-block                    ( fileblock' indir-block )
243          sb-buf dup fs_bsize l@         ( fileblock' indir-block fs fs_bsize )
244          swap indir-addr swap           ( fileblock' indir-block fs_bsize indiraddr fs )
245          fsbtodb                        ( fileblock' indir-block fs_bsize db )
246          strategy                       ( fileblock' nread )
247       then                              ( fileblock' nread|indir-block )
248       drop \ Really should check return value
249       indir-block swap la+ l@ exit
250    then
251    dup sb-buf fs_nindir -               ( fileblock'' )
252    \ Now try 2nd level indirect block -- just read twice 
253    dup sb-buf fs_nindir l@ dup * < if   ( fileblock'' )
254       cur-inode di_ib 1 la+ l@          ( fileblock'' indir2-block )
255       to indir-addr                     ( fileblock'' )
256       \ load 1st level indir block 
257       indir-block                       ( fileblock'' indir-block )
258       sb-buf dup fs_bsize l@            ( fileblock'' indir-block fs fs_bsize )
259       swap indir-addr swap              ( fileblock'' indir-block fs_bsize indiraddr fs )
260       fsbtodb                           ( fileblock'' indir-block fs_bsize db )
261       strategy                          ( fileblock'' nread )
262       drop                              ( fileblock'' )
263       dup sb-buf fs_nindir /            ( fileblock'' indir-offset )
264       indir-block swap la+ l@           ( fileblock'' indirblock )
265       to indir-addr                     ( fileblock'' )
266       \ load 2nd level indir block
267       indir-block                       ( fileblock'' indir-block )
268       sb-buf dup fs_bsize l@            ( fileblock'' indir-block fs fs_bsize )
269       swap indir-addr swap              ( fileblock'' indir-block fs_bsize indiraddr fs )
270       fsbtodb                           ( fileblock'' indir-block fs_bsize db )
271       strategy                          ( fileblock'' nread )
272       drop                              ( fileblock'' )
273       sb-buf fs_nindir l@ mod indir-block swap la+ l@ exit
274    then
275    ." block-map: exceeded max file size" cr
276    abort
280 \ Read file into internal buffer and return pointer and len
283 0 value cur-block                       \ allocated dynamically in ufs-open
284 0 value cur-blocksize                   \ size of cur-block
285 -1 value cur-blockno
286 0 value cur-offset
288 : buf-read-file ( fs -- len buf )
289    cur-offset swap                      ( seekp fs )
290    2dup blkoff                          ( seekp fs off )
291    -rot 2dup lblkno                     ( off seekp fs block )
292    swap 2dup cur-inode                  ( off seekp block fs block fs inop )
293    swap dblksize                        ( off seekp block fs size )
294    rot dup cur-blockno                  ( off seekp fs size block block cur )
295    <>  if                               ( off seekp fs size block )
296       block-map                         ( off seekp fs size diskblock )
297       dup 0=  if                        ( off seekp fs size diskblock )
298          over cur-block swap 0 fill     ( off seekp fs size diskblock )
299          boot-debug?  if ." buf-read-file fell off end of file" cr then
300       else
301          2dup sb-buf fsbtodb cur-block -rot strategy    ( off seekp fs size diskblock nread )
302          rot 2dup <>  if " buf-read-file: short read." cr abort then
303       then                              ( off seekp fs diskblock nread size )
304       nip nip                           ( off seekp fs size )
305    else                                 ( off seekp fs size block block cur )
306       2drop                             ( off seekp fs size )
307    then
308 \   dup cur-offset + to cur-offset      \ Set up next xfer -- not done
309    nip nip swap -                       ( len )
310    cur-block
314 \ Read inode into cur-inode -- uses cur-block
317 : read-inode ( inode fs -- )
318    twiddle                              ( inode fs -- inode fs )
320    cur-block                            ( inode fs -- inode fs buffer )
322    over                                 ( inode fs buffer -- inode fs buffer fs )
323    fs_bsize l@                          ( inode fs buffer -- inode fs buffer size )
325    2over                                ( inode fs buffer size -- inode fs buffer size inode fs )
326    2over                                ( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size )
327    2swap tuck                           ( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs )
329    ino-to-fsba                          ( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba )
330    swap                                 ( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs )
331    fsbtodb                              ( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db )
333    dup to cur-blockno                   ( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart )
334    strategy                             ( inode fs buffer size buffer size dstart -- inode fs buffer size nread )
335    <>  if ." read-inode - residual" cr abort then
336    dup 2over                            ( inode fs buffer -- inode fs buffer buffer inode fs )
337    ino-to-fsbo                          ( inode fs buffer -- inode fs buffer buffer fsbo )
338    ufs1_dinode_SIZEOF * +                       ( inode fs buffer buffer fsbo -- inode fs buffer dinop )
339    cur-inode ufs1_dinode_SIZEOF move    ( inode fs buffer dinop -- inode fs buffer )
340         \ clear out the old buffers
341    drop                                 ( inode fs buffer -- inode fs )
342    2drop
345 \ Identify inode type
347 : is-dir? ( ufs1_dinode -- true:false ) di_mode w@ ifmt and ifdir = ;
348 : is-symlink? ( ufs1_dinode -- true:false ) di_mode w@ ifmt and iflnk = ;
353 \ Hunt for directory entry:
355 \ repeat
356 \    load a buffer
357 \    while entries do
358 \       if entry == name return
359 \       next entry
360 \ until no buffers
363 : search-directory ( str len -- ino|0 )
364    0 to cur-offset
365    begin cur-offset cur-inode di_size x@ < while        ( str len )
366       sb-buf buf-read-file              ( str len len buf )
367       over 0=  if ." search-directory: buf-read-file zero len" cr abort then
368       swap dup cur-offset + to cur-offset       ( str len buf len )
369       2dup + nip                        ( str len buf bufend )
370       swap 2swap rot                    ( bufend str len buf )
371       begin dup 4 pick < while          ( bufend str len buf )
372          dup d_ino l@ 0<>  if           ( bufend str len buf )
373             boot-debug?  if dup dup d_name swap d_namlen c@ type cr then
374             2dup d_namlen c@ =  if      ( bufend str len buf )
375                dup d_name 2over         ( bufend str len buf dname str len )
376                comp 0= if               ( bufend str len buf )
377                   \ Found it -- return inode
378                   d_ino l@ nip nip nip  ( dino )
379                   boot-debug?  if ." Found it" cr then 
380                   exit                  ( dino )
381                then
382             then                        ( bufend str len buf )
383          then                           ( bufend str len buf )
384          dup d_reclen w@ +              ( bufend str len nextbuf )
385       repeat
386       drop rot drop                     ( str len )
387    repeat
388    2drop 2drop 0                        ( 0 )
391 : ffs_oldcompat ( -- )
392 \ Make sure old ffs values in sb-buf are sane
393    sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l!
394    sb-buf fs_old_interleave dup l@ 1 max swap l!
395    sb-buf fs_old_postblformat l@ fs_42postblfmt =  if
396       8 sb-buf fs_old_nrpos l!
397    then
398    sb-buf fs_old_inodefmt l@ fs_44inodefmt <  if
399       sb-buf fs_bsize l@ 
400       dup ndaddr * 1- sb-buf fs_maxfilesize x!
401       niaddr 0 ?do
402         sb-buf fs_nindir l@ * dup       ( sizebp sizebp -- )
403         sb-buf fs_maxfilesize dup x@    ( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- )
404         rot                             ( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- )
405         +                               ( sizebp *fs_maxfilesize new_fs_maxfilesize  -- ) 
406         swap x!                         ( sizebp -- )
407       loop drop                         ( -- )
408       sb-buf dup fs_bmask l@ not swap fs_qbmask x!
409       sb-buf dup fs_fmask l@ not swap fs_qfmask x!
410    then
413 : read-super ( sector -- )
414 0 " seek" boot-ihandle $call-method
415    -1 = if 
416       ." Seek failed" cr
417       abort
418    then
419    sb-buf sbsize " read" boot-ihandle $call-method
420    dup sbsize <>  if
421       ." Read of superblock failed" cr
422       ." requested" space sbsize .
423       ." actual" space . cr
424       abort
425    else 
426       drop
427    then
430 : ufs-open ( bootpath,len -- )
431    boot-ihandle -1 =  if
432       over cif-open dup 0=  if          ( boot-path len ihandle? )
433          ." Could not open device" space type cr 
434          abort
435       then                              ( boot-path len ihandle )
436       to boot-ihandle                   \ Save ihandle to boot device
437    then 2drop
438    force-raid if
439       boot-debug?  if ." Force RAID superblock read" cr then
440       rf_protected dup to raid-offset 
441       dev_bsize * sboff + read-super
442       sb-buf fs_magic l@ fs_magic_value <>  if
443          ." Invalid superblock magic" cr
444          abort
445       then
446    else
447       boot-debug?  if ." Normal superblock read" cr then
448       sboff read-super
449       sb-buf fs_magic l@ fs_magic_value <>  if
450          boot-debug?  if ." RAID superblock read" cr then
451          true to force-raid
452          rf_protected dup to raid-offset 
453          dev_bsize * sboff + read-super
454          sb-buf fs_magic l@ fs_magic_value <>  if
455             ." Invalid superblock magic" cr
456             abort
457          then
458       then
459    then
460    sb-buf fs_bsize l@ dup maxbsize >  if
461       ." Superblock bsize" space . ." too large" cr
462       abort
463    then 
464    dup fs_SIZEOF <  if
465       ." Superblock bsize < size of superblock" cr
466       abort
467    then
468    ffs_oldcompat        ( fs_bsize -- fs_bsize )
469    dup to cur-blocksize alloc-mem to cur-block    \ Allocate cur-block
470    boot-debug?  if ." ufs-open complete" cr then
473 : ufs-close ( -- ) 
474    boot-ihandle dup -1 <>  if
475       cif-close -1 to boot-ihandle 
476    then
477    cur-block 0<> if
478       cur-block cur-blocksize free-mem
479    then
482 : boot-path ( -- boot-path )
483    " bootpath" chosen-phandle get-package-property  if
484       ." Could not find bootpath in /chosen" cr
485       abort
486    else
487       decode-string 2swap 2drop
488    then
491 : boot-args ( -- boot-args )
492    " bootargs" chosen-phandle get-package-property  if
493       ." Could not find bootargs in /chosen" cr
494       abort
495    else
496       decode-string 2swap 2drop
497    then
500 2000 buffer: boot-path-str
501 2000 buffer: boot-path-tmp
503 : split-path ( path len -- right len left len )
504 \ Split a string at the `/'
505    begin
506       dup -rot                          ( oldlen right len left )
507       ascii / left-parse-string         ( oldlen right len left len )
508       dup 0<>  if 4 roll drop exit then
509       2drop                             ( oldlen right len )
510       rot over =                        ( right len diff )
511    until
514 : find-file ( load-file len -- )
515    rootino dup sb-buf read-inode        ( load-file len -- load-file len ino )
516    -rot                                 ( load-file len ino -- pino load-file len )
517    \
518    \ For each path component
519    \ 
520    begin split-path dup 0<> while       ( pino right len left len -- )
521       cur-inode is-dir? not  if ." Inode not directory" cr false exit then
522       boot-debug?  if ." Looking for" space 2dup type space ." in directory..." cr then
523       search-directory                  ( pino right len left len -- pino right len ino|false )
524       dup 0=  if ." Bad path" cr abort then     ( pino right len cino )
525       sb-buf read-inode                 ( pino right len )
526       cur-inode is-symlink?  if         \ Symlink -- follow the damn thing
527          \ Save path in boot-path-tmp
528          boot-path-tmp strmov           ( pino new-right len )
530          \ Now deal with symlink
531          cur-inode di_size x@           ( pino right len linklen )
532          dup sb-buf fs_maxsymlinklen l@ ( pino right len linklen linklen maxlinklen )
533          <  if                          \ Now join the link to the path
534             cur-inode di_db l@  ( pino right len linklen linkp )
535             swap boot-path-str strmov   ( pino right len new-linkp linklen )
536          else                           \ Read file for symlink -- Ugh
537             \ Read link into boot-path-str
538             boot-path-str dup sb-buf fs_bsize l@
539             0 block-map                 ( pino right len linklen boot-path-str bsize blockno )
540             strategy drop swap          ( pino right len boot-path-str linklen )
541          then                           ( pino right len linkp linklen )
542          \ Concatenate the two paths
543          strcat                         ( pino new-right newlen )
544          swap dup c@ ascii / =  if      \ go to root inode?
545             rot drop rootino -rot       ( rino len right )
546          then
547          rot dup sb-buf read-inode      ( len right pino )
548          -rot swap                      ( pino right len )
549       then                              ( pino right len )
550    repeat
551    2drop drop
552    true
555 : read-file ( size addr -- )
556    \ Read x bytes from a file to buffer
557    begin over 0> while
558       cur-offset cur-inode di_size x@ >  if ." read-file EOF exceeded" cr abort then
559       sb-buf buf-read-file              ( size addr len buf )
560       over 2over drop swap              ( size addr len buf addr len )
561       move                              ( size addr len )
562       dup cur-offset + to cur-offset    ( size len newaddr )
563       tuck +                            ( size len newaddr )
564       -rot - swap                       ( newaddr newsize )
565    repeat
566    2drop
570 \ According to the 1275 addendum for SPARC processors:
571 \ Default load-base is 0x4000.  At least 0x8.0000 or
572 \ 512KB must be available at that address.  
574 \ The Fcode bootblock can take up up to 8KB (O.K., 7.5KB) 
575 \ so load programs at 0x4000 + 0x2000=> 0x6000
578 h# 6000 constant loader-base
581 \ Elf support -- find the load addr
584 : is-elf? ( hdr -- res? ) h# 7f454c46 = ;
587 \ Finally we finish it all off
590 : load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
591    ." Loading file" space 2over type cr ." from device" space 2dup type cr
594 : load-file-print-size ( size -- size )
595    ." Loading" space dup . space ." bytes of file..." cr 
598 : load-file ( load-file len boot-path len -- load-base )
599    boot-debug?  if load-file-signon then
600    the-file file_SIZEOF 0 fill          \ Clear out file structure
601    \ copy "load-file len boot-path len" in case we need to set "force-raid"
602    2over 2over                          ( load-file len boot-path len load-file len boot-path len )
603    ufs-open                             ( load-file len boot-path len load-file len )
604    find-file not if                     ( load-file len boot-path len )
605       force-raid not if
606          true to force-raid             ( )
607          ufs-close
608          2drop 2drop drop               ( load-file len boot-path len )
609          ufs-open                       ( load-file len )
610          find-file                      ( true:false )
611          drop
612       else
613          abort
614       then
615    else
616       \ We didn't set "force-raid", discard the copies
617       2drop 2drop                       ( )
618    then
620    \
621    \ Now we've found the file we should read it in in one big hunk
622    \
624    cur-inode di_size x@                 ( file-len )
625    dup " to file-size" evaluate         ( file-len )
626    boot-debug?  if load-file-print-size then
627    0 to cur-offset
628    loader-base                          ( buf-len addr )
629    2dup read-file                       ( buf-len addr )
630    ufs-close                            ( buf-len addr )
631    dup is-elf?  if ." load-file: not an elf executable" cr abort then
633    \ Luckily the prom should be able to handle ELF executables by itself
635    nip                                  ( addr )
638 : do-boot ( bootfile -- )
639    ." NetBSD IEEE 1275 Bootblock" cr
640    boot-path load-file ( -- load-base )
641    dup 0<> if  " to load-base init-program" evaluate then
645 boot-args ascii V strchr 0<> swap drop if
646  true to boot-debug?
647 then
649 boot-args ascii D strchr 0= swap drop if
650   " /ofwboot" do-boot
651 then exit