bootblk.fth revision 1.9
1\	$NetBSD: bootblk.fth,v 1.9 2009/10/19 18:12:37 snj Exp $
2\
3\	IEEE 1275 Open Firmware Boot Block
4\
5\	Parses disklabel and UFS and loads the file called `ofwboot'
6\
7\
8\	Copyright (c) 1998 Eduardo Horvath.
9\	All rights reserved.
10\
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.
19\
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.
30\
31
32offset16
33hex
34headers
35
36false value boot-debug?
37
38\
39\ First some housekeeping:  Open /chosen and set up vectors into
40\	client-services
41
42" /chosen" find-package 0=  if ." Cannot find /chosen" 0 then
43constant chosen-phandle
44
45" /openprom/client-services" find-package 0=  if 
46	." Cannot find client-services" cr abort
47then constant cif-phandle
48
49defer cif-claim ( align size virt -- base )
50defer cif-release ( size virt -- )
51defer cif-open ( cstr -- ihandle|0 )
52defer cif-close ( ihandle -- )
53defer cif-read ( len adr ihandle -- #read )
54defer cif-seek ( low high ihandle -- -1|0|1 )
55\ defer cif-peer ( phandle -- phandle )
56\ defer cif-getprop ( len adr cstr phandle -- )
57
58: find-cif-method ( method,len -- xf )
59   cif-phandle find-method drop 
60;
61
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
67
68: twiddle ( -- ) ." ." ; \ Need to do this right.  Just spit out periods for now.
69
70\
71\ Support routines
72\
73
74: strcmp ( s1 l1 s2 l2 -- true:false )
75   rot tuck <> if  3drop false exit then
76   comp 0=
77;
78
79\ Move string into buffer
80
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
85;
86
87\ Move s1 on the end of s2 and return the result
88
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 )
94;
95
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
105;
106
107   
108: cstr ( ptr -- str len )
109   dup 
110   begin dup c@ 0<>  while + repeat
111   over -
112;
113
114\
115\ BSD FFS parameters
116\
117
118fload	assym.fth.h
119
120sbsize buffer: sb-buf
121-1 value boot-ihandle
122dev_bsize value bsize
1230 value raid-offset	\ Offset if it's a raid-frame partition
124false value force-raid	\ Force reads from raid offset
125
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
133;
134
135\
136\ Cylinder group macros
137\
138
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 +
144;
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 + ;
149
150\
151\ Block and frag position macros
152\
153
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 )
175;
176
177
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   +
198;
199: fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ;
200
201\
202\ File stuff
203\
204
205niaddr /w* constant narraysize
206
207struct 
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
215constant file_SIZEOF
216
217file_SIZEOF buffer: the-file
218sb-buf the-file >f_fs x!
219
220ufs1_dinode_SIZEOF buffer: cur-inode
221h# 2000 buffer: indir-block
222-1 value indir-addr
223
224\
225\ Translate a fileblock to a disk block
226\
227\ We only allow single indirection
228\
229
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
277;
278
279\
280\ Read file into internal buffer and return pointer and len
281\
282
2830 value cur-block			\ allocated dynamically in ufs-open
2840 value cur-blocksize			\ size of cur-block
285-1 value cur-blockno
2860 value cur-offset
287
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
311;
312
313\
314\ Read inode into cur-inode -- uses cur-block
315\ 
316
317: read-inode ( inode fs -- )
318   twiddle				( inode fs -- inode fs )
319
320   cur-block				( inode fs -- inode fs buffer )
321
322   over					( inode fs buffer -- inode fs buffer fs )
323   fs_bsize l@				( inode fs buffer -- inode fs buffer size )
324
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 )
328
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 )
332
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
343;
344
345\ Identify inode type
346
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 = ;
349
350
351
352\
353\ Hunt for directory entry:
354\ 
355\ repeat
356\    load a buffer
357\    while entries do
358\       if entry == name return
359\       next entry
360\ until no buffers
361\
362
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 )
389;
390
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
411;
412
413: read-super ( sector -- )
4140 " 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
428;
429
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
471;
472
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
480;
481
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
489;
490
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
498;
499
5002000 buffer: boot-path-str
5012000 buffer: boot-path-tmp
502
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
512;
513
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 )
529
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
553;
554
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
567;
568
569\
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.  
573\
574\ The Fcode bootblock can take up up to 8KB (O.K., 7.5KB) 
575\ so load programs at 0x4000 + 0x2000=> 0x6000
576\
577
578h# 6000 constant loader-base
579
580\
581\ Elf support -- find the load addr
582\
583
584: is-elf? ( hdr -- res? ) h# 7f454c46 = ;
585
586\
587\ Finally we finish it all off
588\
589
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
592;
593
594: load-file-print-size ( size -- size )
595   ." Loading" space dup . space ." bytes of file..." cr 
596;
597
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
619
620   \
621   \ Now we've found the file we should read it in in one big hunk
622   \
623
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
632
633   \ Luckily the prom should be able to handle ELF executables by itself
634
635   nip					( addr )
636;
637
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
642;
643
644
645boot-args ascii V strchr 0<> swap drop if
646 true to boot-debug?
647then
648
649boot-args ascii D strchr 0= swap drop if
650  " /ofwboot" do-boot
651then exit
652
653
654