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