bootblk.fth revision 1.2
11.2Swiz\	$NetBSD: bootblk.fth,v 1.2 2001/06/13 10:46:02 wiz Exp $
21.1Smrg\
31.1Smrg\	IEEE 1275 Open Firmware Boot Block
41.1Smrg\
51.1Smrg\	Parses disklabel and UFS and loads the file called `ofwboot'
61.1Smrg\
71.1Smrg\
81.1Smrg\	Copyright (c) 1998 Eduardo Horvath.
91.1Smrg\	All rights reserved.
101.1Smrg\
111.1Smrg\	Redistribution and use in source and binary forms, with or without
121.1Smrg\	modification, are permitted provided that the following conditions
131.1Smrg\	are met:
141.1Smrg\	1. Redistributions of source code must retain the above copyright
151.1Smrg\	   notice, this list of conditions and the following disclaimer.
161.1Smrg\	2. Redistributions in binary form must reproduce the above copyright
171.1Smrg\	   notice, this list of conditions and the following disclaimer in the
181.1Smrg\	   documentation and/or other materials provided with the distribution.
191.1Smrg\	3. All advertising materials mentioning features or use of this software
201.1Smrg\	   must display the following acknowledgement:
211.1Smrg\	     This product includes software developed by Eduardo Horvath.
221.1Smrg\	4. The name of the author may not be used to endorse or promote products
231.2Swiz\	   derived from this software without specific prior written permission
241.1Smrg\
251.1Smrg\	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
261.1Smrg\	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
271.1Smrg\	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
281.1Smrg\	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
291.1Smrg\	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
301.1Smrg\	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
311.1Smrg\	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
321.1Smrg\	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
331.1Smrg\	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
341.1Smrg\	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351.1Smrg\
361.1Smrg
371.1Smrgoffset16
381.1Smrghex
391.1Smrgheaders
401.1Smrg
411.1Smrgfalse value boot-debug?
421.1Smrg
431.1Smrg\
441.1Smrg\ First some housekeeping:  Open /chosen and set up vectors into
451.1Smrg\	client-services
461.1Smrg
471.1Smrg" /chosen" find-package 0=  if ." Cannot find /chosen" 0 then
481.1Smrgconstant chosen-phandle
491.1Smrg
501.1Smrg" /openprom/client-services" find-package 0=  if 
511.1Smrg	." Cannot find client-services" cr abort
521.1Smrgthen constant cif-phandle
531.1Smrg
541.1Smrgdefer cif-claim ( align size virt -- base )
551.1Smrgdefer cif-release ( size virt -- )
561.1Smrgdefer cif-open ( cstr -- ihandle|0 )
571.1Smrgdefer cif-close ( ihandle -- )
581.1Smrgdefer cif-read ( len adr ihandle -- #read )
591.1Smrgdefer cif-seek ( low high ihandle -- -1|0|1 )
601.1Smrg\ defer cif-peer ( phandle -- phandle )
611.1Smrg\ defer cif-getprop ( len adr cstr phandle -- )
621.1Smrg
631.1Smrg: find-cif-method ( method,len -- xf )
641.1Smrg   cif-phandle find-method drop 
651.1Smrg;
661.1Smrg
671.1Smrg" claim" find-cif-method to cif-claim
681.1Smrg" open" find-cif-method to cif-open
691.1Smrg" close" find-cif-method to cif-close
701.1Smrg" read" find-cif-method to cif-read
711.1Smrg" seek" find-cif-method to cif-seek
721.1Smrg
731.1Smrg: twiddle ( -- ) ." ." ; \ Need to do this right.  Just spit out periods for now.
741.1Smrg
751.1Smrg\
761.1Smrg\ Support routines
771.1Smrg\
781.1Smrg
791.1Smrg: strcmp ( s1 l1 s2 l2 -- true:false )
801.1Smrg   rot tuck <> if  3drop false exit then
811.1Smrg   comp 0=
821.1Smrg;
831.1Smrg
841.1Smrg\ Move string into buffer
851.1Smrg
861.1Smrg: strmov ( s1 l1 d -- d l1 )
871.1Smrg   dup 2over swap -rot		( s1 l1 d s1 d l1 )
881.1Smrg   move				( s1 l1 d )
891.1Smrg   rot drop swap
901.1Smrg;
911.1Smrg
921.1Smrg\ Move s1 on the end of s2 and return the result
931.1Smrg
941.1Smrg: strcat ( s1 l1 s2 l2 -- d tot )
951.1Smrg   2over swap 				( s1 l1 s2 l2 l1 s1 )
961.1Smrg   2over + rot				( s1 l1 s2 l2 s1 d l1 )
971.1Smrg   move rot + 				( s1 s2 len )
981.1Smrg   rot drop				( s2 len )
991.1Smrg;
1001.1Smrg
1011.1Smrg: strchr ( s1 l1 c -- s2 l2 )
1021.1Smrg   begin
1031.1Smrg      dup 2over 0= if			( s1 l1 c c s1  )
1041.1Smrg         2drop drop exit then
1051.1Smrg      c@ = if				( s1 l1 c )
1061.1Smrg         drop exit then
1071.1Smrg      -rot /c - swap ca1+		( c l2 s2 )
1081.1Smrg     swap rot
1091.1Smrg  again
1101.1Smrg;
1111.1Smrg
1121.1Smrg   
1131.1Smrg: cstr ( ptr -- str len )
1141.1Smrg   dup 
1151.1Smrg   begin dup c@ 0<>  while + repeat
1161.1Smrg   over -
1171.1Smrg;
1181.1Smrg
1191.1Smrg\
1201.1Smrg\ BSD FFS parameters
1211.1Smrg\
1221.1Smrg
1231.1Smrgfload	assym.fth.h
1241.1Smrg
1251.1Smrgsbsize buffer: sb-buf
1261.1Smrg-1 value boot-ihandle
1271.1Smrgdev_bsize value bsize
1281.1Smrg
1291.1Smrg: strategy ( addr size start -- nread )
1301.1Smrg   bsize * 0 " seek" boot-ihandle $call-method
1311.1Smrg   -1 = if 
1321.1Smrg      ." strategy: Seek failed" cr
1331.1Smrg      abort
1341.1Smrg   then
1351.1Smrg   " read" boot-ihandle $call-method
1361.1Smrg;
1371.1Smrg
1381.1Smrg\
1391.1Smrg\ Cylinder group macros
1401.1Smrg\
1411.1Smrg
1421.1Smrg: cgbase ( cg fs -- cgbase ) fs_fpg l@ * ;
1431.1Smrg: cgstart ( cg fs -- cgstart ) 
1441.1Smrg   2dup fs_cgmask l@ not and		( cg fs stuff -- )
1451.1Smrg   over fs_cgoffset l@ * -rot		( stuffcg fs -- )
1461.1Smrg   cgbase +
1471.1Smrg;
1481.1Smrg: cgdmin ( cg fs -- 1st-data-block ) dup fs_dblkno l@ -rot cgstart + ;
1491.1Smrg: cgimin ( cg fs -- inode-block ) dup fs_iblkno l@ -rot cgstart + ;
1501.1Smrg: cgsblock ( cg fs -- super-block ) dup fs_sblkno l@ -rot cgstart + ;
1511.1Smrg: cgstod ( cg fs -- cg-block ) dup fs_cblkno l@ -rot cgstart + ;
1521.1Smrg
1531.1Smrg\
1541.1Smrg\ Block and frag position macros
1551.1Smrg\
1561.1Smrg
1571.1Smrg: blkoff ( pos fs -- off ) fs_qbmask x@ and ;
1581.1Smrg: fragoff ( pos fs -- off ) fs_qfmask x@ and ;
1591.1Smrg: lblktosize ( blk fs -- off ) fs_bshift l@ << ;
1601.1Smrg: lblkno ( pos fs -- off ) fs_bshift l@ >> ;
1611.1Smrg: numfrags ( pos fs -- off ) fs_fshift l@ >> ;
1621.1Smrg: blkroundup ( pos fs -- off ) dup fs_bmask l@ -rot fs_qbmask x@ + and ;
1631.1Smrg: fragroundup ( pos fs -- off ) dup fs_fmask l@ -rot fs_qfmask x@ + and ;
1641.1Smrg\ : fragroundup ( pos fs -- off ) tuck fs_qfmask x@ + swap fs_fmask l@ and ;
1651.1Smrg: fragstoblks ( pos fs -- off ) fs_fragshift l@ >> ;
1661.1Smrg: blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ;
1671.1Smrg: fragnum ( fsb fs -- off ) fs_frag l@ 1- and ;
1681.1Smrg: blknum ( fsb fs -- off ) fs_frag l@ 1- not and ;
1691.1Smrg: dblksize ( lbn dino fs -- size )
1701.1Smrg   -rot 				( fs lbn dino )
1711.1Smrg   di_size x@				( fs lbn di_size )
1721.1Smrg   -rot dup 1+				( di_size fs lbn lbn+1 )
1731.1Smrg   2over fs_bshift l@			( di_size fs lbn lbn+1 di_size b_shift )
1741.1Smrg   rot swap <<	>=			( di_size fs lbn res1 )
1751.1Smrg   swap ndaddr >= or if			( di_size fs )
1761.1Smrg      swap drop fs_bsize l@ exit	( size )
1771.1Smrg   then	tuck blkoff swap fragroundup	( size )
1781.1Smrg;
1791.1Smrg
1801.1Smrg
1811.1Smrg: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ;
1821.1Smrg: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ;
1831.1Smrg: ino-to-fsba ( ino fs -- ba )	\ Need to remove the stupid stack diags someday
1841.1Smrg   2dup 				( ino fs ino fs )
1851.1Smrg   ino-to-cg				( ino fs cg )
1861.1Smrg   over					( ino fs cg fs )
1871.1Smrg   cgimin				( ino fs inode-blk )
1881.1Smrg   -rot					( inode-blk ino fs )
1891.1Smrg   tuck 				( inode-blk fs ino fs )
1901.1Smrg   fs_ipg l@ 				( inode-blk fs ino ipg )
1911.1Smrg   mod					( inode-blk fs mod )
1921.1Smrg   swap					( inode-blk mod fs )
1931.1Smrg   dup 					( inode-blk mod fs fs )
1941.1Smrg   fs_inopb l@ 				( inode-blk mod fs inopb )
1951.1Smrg   rot 					( inode-blk fs inopb mod )
1961.1Smrg   swap					( inode-blk fs mod inopb )
1971.1Smrg   /					( inode-blk fs div )
1981.1Smrg   swap					( inode-blk div fs )
1991.1Smrg   blkstofrags				( inode-blk frag )
2001.1Smrg   +
2011.1Smrg;
2021.1Smrg: fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ;
2031.1Smrg
2041.1Smrg\
2051.1Smrg\ File stuff
2061.1Smrg\
2071.1Smrg
2081.1Smrgniaddr /w* constant narraysize
2091.1Smrg
2101.1Smrgstruct 
2111.1Smrg   8		field	>f_ihandle	\ device handle
2121.1Smrg   8 		field 	>f_seekp	\ seek pointer
2131.1Smrg   8 		field 	>f_fs		\ pointer to super block
2141.1Smrg   dinode_SIZEOF 	field 	>f_di	\ copy of on-disk inode
2151.1Smrg   8		field	>f_buf		\ buffer for data block
2161.1Smrg   4		field 	>f_buf_size	\ size of data block
2171.1Smrg   4		field	>f_buf_blkno	\ block number of data block
2181.1Smrgconstant file_SIZEOF
2191.1Smrg
2201.1Smrgfile_SIZEOF buffer: the-file
2211.1Smrgsb-buf the-file >f_fs x!
2221.1Smrg
2231.1Smrgdinode_SIZEOF buffer: cur-inode
2241.1Smrgh# 2000 buffer: indir-block
2251.1Smrg-1 value indir-addr
2261.1Smrg
2271.1Smrg\
2281.1Smrg\ Translate a fileblock to a disk block
2291.1Smrg\
2301.1Smrg\ We only allow single indirection
2311.1Smrg\
2321.1Smrg
2331.1Smrg: block-map ( fileblock -- diskblock )
2341.1Smrg   \ Direct block?
2351.1Smrg   dup ndaddr <  if 			( fileblock )
2361.1Smrg      cur-inode di_db			( arr-indx arr-start )
2371.1Smrg      swap la+ l@ exit			( diskblock )
2381.1Smrg   then 				( fileblock )
2391.1Smrg   ndaddr -				( fileblock' )
2401.1Smrg   \ Now we need to check the indirect block
2411.1Smrg   dup sb-buf fs_nindir l@ <  if	( fileblock' )
2421.1Smrg      cur-inode di_ib l@ dup		( fileblock' indir-block indir-block )
2431.1Smrg      indir-addr <>  if 		( fileblock' indir-block )
2441.1Smrg         to indir-addr			( fileblock' )
2451.1Smrg         indir-block 			( fileblock' indir-block )
2461.1Smrg         sb-buf dup fs_bsize l@		( fileblock' indir-block fs fs_bsize )
2471.1Smrg         swap indir-addr swap		( fileblock' indir-block fs_bsize indiraddr fs )
2481.1Smrg         fsbtodb 			( fileblock' indir-block fs_bsize db )
2491.1Smrg         strategy			( fileblock' nread )
2501.1Smrg      then				( fileblock' nread|indir-block )
2511.1Smrg      drop \ Really should check return value
2521.1Smrg      indir-block swap la+ l@ exit
2531.1Smrg   then
2541.1Smrg   dup sb-buf fs_nindir -		( fileblock'' )
2551.1Smrg   \ Now try 2nd level indirect block -- just read twice 
2561.1Smrg   dup sb-buf fs_nindir l@ dup * < if	( fileblock'' )
2571.1Smrg      cur-inode di_ib 1 la+ l@		( fileblock'' indir2-block )
2581.1Smrg      to indir-addr			( fileblock'' )
2591.1Smrg      \ load 1st level indir block 
2601.1Smrg      indir-block 			( fileblock'' indir-block )
2611.1Smrg      sb-buf dup fs_bsize l@		( fileblock'' indir-block fs fs_bsize )
2621.1Smrg      swap indir-addr swap		( fileblock'' indir-block fs_bsize indiraddr fs )
2631.1Smrg      fsbtodb 				( fileblock'' indir-block fs_bsize db )
2641.1Smrg      strategy				( fileblock'' nread )
2651.1Smrg      drop				( fileblock'' )
2661.1Smrg      dup sb-buf fs_nindir /		( fileblock'' indir-offset )
2671.1Smrg      indir-block swap la+ l@		( fileblock'' indirblock )
2681.1Smrg      to indir-addr			( fileblock'' )
2691.1Smrg      \ load 2nd level indir block
2701.1Smrg      indir-block 			( fileblock'' indir-block )
2711.1Smrg      sb-buf dup fs_bsize l@		( fileblock'' indir-block fs fs_bsize )
2721.1Smrg      swap indir-addr swap		( fileblock'' indir-block fs_bsize indiraddr fs )
2731.1Smrg      fsbtodb 				( fileblock'' indir-block fs_bsize db )
2741.1Smrg      strategy				( fileblock'' nread )
2751.1Smrg      drop				( fileblock'' )
2761.1Smrg      sb-buf fs_nindir l@ mod indir-block swap la+ l@ exit
2771.1Smrg   then
2781.1Smrg   ." block-map: exceeded max file size" cr
2791.1Smrg   abort
2801.1Smrg;
2811.1Smrg
2821.1Smrg\
2831.1Smrg\ Read file into internal buffer and return pointer and len
2841.1Smrg\
2851.1Smrg
2861.1Smrg2000 buffer: cur-block		\ Why do dynamic allocation?
2871.1Smrg-1 value cur-blockno
2881.1Smrg0 value cur-offset
2891.1Smrg
2901.1Smrg: buf-read-file ( fs -- len buf )
2911.1Smrg   cur-offset swap			( seekp fs )
2921.1Smrg   2dup blkoff				( seekp fs off )
2931.1Smrg   -rot 2dup lblkno			( off seekp fs block )
2941.1Smrg   swap 2dup cur-inode			( off seekp block fs block fs inop )
2951.1Smrg   swap dblksize			( off seekp block fs size )
2961.1Smrg   rot dup cur-blockno			( off seekp fs size block block cur )
2971.1Smrg   <>  if 				( off seekp fs size block )
2981.1Smrg      block-map				( off seekp fs size diskblock )
2991.1Smrg      dup 0=  if			( off seekp fs size diskblock )
3001.1Smrg         over cur-block swap 0 fill	( off seekp fs size diskblock )
3011.1Smrg         boot-debug?  if ." buf-read-file fell off end of file" cr then
3021.1Smrg      else
3031.1Smrg         2dup sb-buf fsbtodb cur-block -rot strategy	( off seekp fs size diskblock nread )
3041.1Smrg         rot 2dup <>  if " buf-read-file: short read." cr abort then
3051.1Smrg      then				( off seekp fs diskblock nread size )
3061.1Smrg      nip nip				( off seekp fs size )
3071.1Smrg   else					( off seekp fs size block block cur )
3081.1Smrg      2drop				( off seekp fs size )
3091.1Smrg   then
3101.1Smrg\   dup cur-offset + to cur-offset	\ Set up next xfer -- not done
3111.1Smrg   nip nip swap -			( len )
3121.1Smrg   cur-block
3131.1Smrg;
3141.1Smrg
3151.1Smrg\
3161.1Smrg\ Read inode into cur-inode -- uses cur-block
3171.1Smrg\ 
3181.1Smrg
3191.1Smrg: read-inode ( inode fs -- )
3201.1Smrg   twiddle				( inode fs -- inode fs )
3211.1Smrg
3221.1Smrg   cur-block				( inode fs -- inode fs buffer )
3231.1Smrg
3241.1Smrg   over					( inode fs buffer -- inode fs buffer fs )
3251.1Smrg   fs_bsize l@				( inode fs buffer -- inode fs buffer size )
3261.1Smrg
3271.1Smrg   2over				( inode fs buffer size -- inode fs buffer size inode fs )
3281.1Smrg   2over				( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size )
3291.1Smrg   2swap tuck				( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs )
3301.1Smrg
3311.1Smrg   ino-to-fsba 				( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba )
3321.1Smrg   swap					( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs )
3331.1Smrg   fsbtodb				( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db )
3341.1Smrg
3351.1Smrg   dup to cur-blockno			( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart )
3361.1Smrg   strategy				( inode fs buffer size buffer size dstart -- inode fs buffer size nread )
3371.1Smrg   <>  if ." read-inode - residual" cr abort then
3381.1Smrg   dup 2over				( inode fs buffer -- inode fs buffer buffer inode fs )
3391.1Smrg   ino-to-fsbo				( inode fs buffer -- inode fs buffer buffer fsbo )
3401.1Smrg   dinode_SIZEOF * +			( inode fs buffer buffer fsbo -- inode fs buffer dinop )
3411.1Smrg   cur-inode dinode_SIZEOF move 	( inode fs buffer dinop -- inode fs buffer )
3421.1Smrg	\ clear out the old buffers
3431.1Smrg   drop					( inode fs buffer -- inode fs )
3441.1Smrg   2drop
3451.1Smrg;
3461.1Smrg
3471.1Smrg\ Identify inode type
3481.1Smrg
3491.1Smrg: is-dir? ( dinode -- true:false ) di_mode w@ ifmt and ifdir = ;
3501.1Smrg: is-symlink? ( dinode -- true:false ) di_mode w@ ifmt and iflnk = ;
3511.1Smrg
3521.1Smrg
3531.1Smrg
3541.1Smrg\
3551.1Smrg\ Hunt for directory entry:
3561.1Smrg\ 
3571.1Smrg\ repeat
3581.1Smrg\    load a buffer
3591.1Smrg\    while entries do
3601.1Smrg\       if entry == name return
3611.1Smrg\       next entry
3621.1Smrg\ until no buffers
3631.1Smrg\
3641.1Smrg
3651.1Smrg: search-directory ( str len -- ino|0 )
3661.1Smrg   0 to cur-offset
3671.1Smrg   begin cur-offset cur-inode di_size x@ < while	( str len )
3681.1Smrg      sb-buf buf-read-file		( str len len buf )
3691.1Smrg      over 0=  if ." search-directory: buf-read-file zero len" cr abort then
3701.1Smrg      swap dup cur-offset + to cur-offset	( str len buf len )
3711.1Smrg      2dup + nip			( str len buf bufend )
3721.1Smrg      swap 2swap rot			( bufend str len buf )
3731.1Smrg      begin dup 4 pick < while		( bufend str len buf )
3741.1Smrg         dup d_ino l@ 0<>  if 		( bufend str len buf )
3751.1Smrg            boot-debug?  if dup dup d_name swap d_namlen c@ type cr then
3761.1Smrg            2dup d_namlen c@ =  if	( bufend str len buf )
3771.1Smrg               dup d_name 2over		( bufend str len buf dname str len )
3781.1Smrg               comp 0= if		( bufend str len buf )
3791.1Smrg                  \ Found it -- return inode
3801.1Smrg                  d_ino l@ nip nip nip	( dino )
3811.1Smrg                  boot-debug?  if ." Found it" cr then 
3821.1Smrg                  exit 			( dino )
3831.1Smrg               then
3841.1Smrg            then			( bufend str len buf )
3851.1Smrg         then				( bufend str len buf )
3861.1Smrg         dup d_reclen w@ +		( bufend str len nextbuf )
3871.1Smrg      repeat
3881.1Smrg      drop rot drop			( str len )
3891.1Smrg   repeat
3901.1Smrg   2drop 2drop 0			( 0 )
3911.1Smrg;
3921.1Smrg
3931.1Smrg: ffs_oldcompat ( -- )
3941.1Smrg\ Make sure old ffs values in sb-buf are sane
3951.1Smrg   sb-buf fs_npsect dup l@ sb-buf fs_nsect l@ max swap l!
3961.1Smrg   sb-buf fs_interleave dup l@ 1 max swap l!
3971.1Smrg   sb-buf fs_postblformat l@ fs_42postblfmt =  if
3981.1Smrg      8 sb-buf fs_nrpos l!
3991.1Smrg   then
4001.1Smrg   sb-buf fs_inodefmt l@ fs_44inodefmt <  if
4011.1Smrg      sb-buf fs_bsize l@ 
4021.1Smrg      dup ndaddr * 1- sb-buf fs_maxfilesize x!
4031.1Smrg      niaddr 0 ?do
4041.1Smrg	sb-buf fs_nindir l@ * dup	( sizebp sizebp -- )
4051.1Smrg	sb-buf fs_maxfilesize dup x@	( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- )
4061.1Smrg	rot ( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- )
4071.1Smrg	+ ( sizebp *fs_maxfilesize new_fs_maxfilesize  -- ) swap x! ( sizebp -- )
4081.1Smrg      loop drop ( -- )
4091.1Smrg      sb-buf dup fs_bmask l@ not swap fs_qbmask x!
4101.1Smrg      sb-buf dup fs_fmask l@ not swap fs_qfmask x!
4111.1Smrg   then
4121.1Smrg;
4131.1Smrg
4141.1Smrg: ufs-open ( bootpath,len -- )
4151.1Smrg   boot-ihandle -1 =  if
4161.1Smrg      over cif-open dup 0=  if 		( boot-path len ihandle? )
4171.1Smrg         ." Could not open device" space type cr 
4181.1Smrg         abort
4191.1Smrg      then 				( boot-path len ihandle )
4201.1Smrg      to boot-ihandle			\ Save ihandle to boot device
4211.1Smrg   then 2drop
4221.1Smrg   sboff 0 " seek" boot-ihandle $call-method
4231.1Smrg   -1 = if 
4241.1Smrg      ." Seek failed" cr
4251.1Smrg      abort
4261.1Smrg   then
4271.1Smrg   sb-buf sbsize " read" boot-ihandle $call-method
4281.1Smrg   dup sbsize <>  if
4291.1Smrg      ." Read of superblock failed" cr
4301.1Smrg      ." requested" space sbsize .
4311.1Smrg      ." actual" space . cr
4321.1Smrg      abort
4331.1Smrg   else 
4341.1Smrg      drop
4351.1Smrg   then
4361.1Smrg   sb-buf fs_magic l@ fs_magic_value <>  if
4371.1Smrg      ." Invalid superblock magic" cr
4381.1Smrg      abort
4391.1Smrg   then
4401.1Smrg   sb-buf fs_bsize l@ dup maxbsize >  if
4411.1Smrg      ." Superblock bsize" space . ." too large" cr
4421.1Smrg      abort
4431.1Smrg   then 
4441.1Smrg   fs_SIZEOF <  if
4451.1Smrg      ." Superblock bsize < size of superblock" cr
4461.1Smrg      abort
4471.1Smrg   then
4481.1Smrg   ffs_oldcompat
4491.1Smrg   boot-debug?  if ." ufs-open complete" cr then
4501.1Smrg;
4511.1Smrg
4521.1Smrg: ufs-close ( -- ) 
4531.1Smrg   boot-ihandle dup -1 <>  if
4541.1Smrg      cif-close -1 to boot-ihandle 
4551.1Smrg   then
4561.1Smrg;
4571.1Smrg
4581.1Smrg: boot-path ( -- boot-path )
4591.1Smrg   " bootpath" chosen-phandle get-package-property  if
4601.1Smrg      ." Could not find bootpath in /chosen" cr
4611.1Smrg      abort
4621.1Smrg   else
4631.1Smrg      decode-string 2swap 2drop
4641.1Smrg   then
4651.1Smrg;
4661.1Smrg
4671.1Smrg: boot-args ( -- boot-args )
4681.1Smrg   " bootargs" chosen-phandle get-package-property  if
4691.1Smrg      ." Could not find bootargs in /chosen" cr
4701.1Smrg      abort
4711.1Smrg   else
4721.1Smrg      decode-string 2swap 2drop
4731.1Smrg   then
4741.1Smrg;
4751.1Smrg
4761.1Smrg2000 buffer: boot-path-str
4771.1Smrg2000 buffer: boot-path-tmp
4781.1Smrg
4791.1Smrg: split-path ( path len -- right len left len )
4801.1Smrg\ Split a string at the `/'
4811.1Smrg   begin
4821.1Smrg      dup -rot				( oldlen right len left )
4831.1Smrg      ascii / left-parse-string		( oldlen right len left len )
4841.1Smrg      dup 0<>  if 4 roll drop exit then
4851.1Smrg      2drop				( oldlen right len )
4861.1Smrg      rot over =			( right len diff )
4871.1Smrg   until
4881.1Smrg;
4891.1Smrg
4901.1Smrg: find-file ( load-file len -- )
4911.1Smrg   rootino dup sb-buf read-inode	( load-file len -- load-file len ino )
4921.1Smrg   -rot					( load-file len ino -- pino load-file len )
4931.1Smrg   \
4941.1Smrg   \ For each path component
4951.1Smrg   \ 
4961.1Smrg   begin split-path dup 0<> while	( pino right len left len -- )
4971.1Smrg      cur-inode is-dir? not  if ." Inode not directory" cr abort then
4981.1Smrg      boot-debug?  if ." Looking for" space 2dup type space ." in directory..." cr then
4991.1Smrg      search-directory			( pino right len left len -- pino right len ino|false )
5001.1Smrg      dup 0=  if ." Bad path" cr abort then	( pino right len cino )
5011.1Smrg      sb-buf read-inode			( pino right len )
5021.1Smrg      cur-inode is-symlink?  if		\ Symlink -- follow the damn thing
5031.1Smrg         \ Save path in boot-path-tmp
5041.1Smrg         boot-path-tmp strmov		( pino new-right len )
5051.1Smrg
5061.1Smrg         \ Now deal with symlink
5071.1Smrg         cur-inode di_size x@		( pino right len linklen )
5081.1Smrg         dup sb-buf fs_maxsymlinklen l@	( pino right len linklen linklen maxlinklen )
5091.1Smrg         <  if				\ Now join the link to the path
5101.1Smrg            cur-inode di_shortlink l@	( pino right len linklen linkp )
5111.1Smrg            swap boot-path-str strmov	( pino right len new-linkp linklen )
5121.1Smrg         else				\ Read file for symlink -- Ugh
5131.1Smrg            \ Read link into boot-path-str
5141.1Smrg            boot-path-str dup sb-buf fs_bsize l@
5151.1Smrg            0 block-map			( pino right len linklen boot-path-str bsize blockno )
5161.1Smrg            strategy drop swap		( pino right len boot-path-str linklen )
5171.1Smrg         then 				( pino right len linkp linklen )
5181.1Smrg         \ Concatenate the two paths
5191.1Smrg         strcat				( pino new-right newlen )
5201.1Smrg         swap dup c@ ascii / =  if	\ go to root inode?
5211.1Smrg            rot drop rootino -rot	( rino len right )
5221.1Smrg         then
5231.1Smrg         rot dup sb-buf read-inode	( len right pino )
5241.1Smrg         -rot swap			( pino right len )
5251.1Smrg      then				( pino right len )
5261.1Smrg   repeat
5271.1Smrg   2drop drop
5281.1Smrg;
5291.1Smrg
5301.1Smrg: read-file ( size addr -- )
5311.1Smrg   \ Read x bytes from a file to buffer
5321.1Smrg   begin over 0> while
5331.1Smrg      cur-offset cur-inode di_size x@ >  if ." read-file EOF exceeded" cr abort then
5341.1Smrg      sb-buf buf-read-file		( size addr len buf )
5351.1Smrg      over 2over drop swap		( size addr len buf addr len )
5361.1Smrg      move				( size addr len )
5371.1Smrg      dup cur-offset + to cur-offset	( size len newaddr )
5381.1Smrg      tuck +				( size len newaddr )
5391.1Smrg      -rot - swap			( newaddr newsize )
5401.1Smrg   repeat
5411.1Smrg   2drop
5421.1Smrg;
5431.1Smrg
5441.1Smrgh# 5000 constant loader-base
5451.1Smrg
5461.1Smrg\
5471.1Smrg\ Elf support -- find the load addr
5481.1Smrg\
5491.1Smrg
5501.1Smrg: is-elf? ( hdr -- res? ) h# 7f454c46 = ;
5511.1Smrg
5521.1Smrg\
5531.1Smrg\ Finally we finish it all off
5541.1Smrg\
5551.1Smrg
5561.1Smrg: load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
5571.1Smrg   ." Loading file" space 2over type cr ." from device" space 2dup type cr
5581.1Smrg;
5591.1Smrg
5601.1Smrg: load-file-print-size ( size -- size )
5611.1Smrg   ." Loading" space dup . space ." bytes of file..." cr 
5621.1Smrg;
5631.1Smrg
5641.1Smrg: load-file ( load-file len boot-path len -- load-base )
5651.1Smrg   boot-debug?  if load-file-signon then
5661.1Smrg   the-file file_SIZEOF 0 fill		\ Clear out file structure
5671.1Smrg   ufs-open 				( load-file len )
5681.1Smrg   find-file				( )
5691.1Smrg
5701.1Smrg   \
5711.1Smrg   \ Now we've found the file we should read it in in one big hunk
5721.1Smrg   \
5731.1Smrg
5741.1Smrg   cur-inode di_size x@			( file-len )
5751.1Smrg   dup " to file-size" evaluate		( file-len )
5761.1Smrg   boot-debug?  if load-file-print-size then
5771.1Smrg   0 to cur-offset
5781.1Smrg   loader-base				( buf-len addr )
5791.1Smrg   2dup read-file			( buf-len addr )
5801.1Smrg   ufs-close				( buf-len addr )
5811.1Smrg   dup is-elf?  if ." load-file: not an elf executable" cr abort then
5821.1Smrg
5831.1Smrg   \ Luckily the prom should be able to handle ELF executables by itself
5841.1Smrg
5851.1Smrg   nip					( addr )
5861.1Smrg;
5871.1Smrg
5881.1Smrg: do-boot ( bootfile -- )
5891.1Smrg   ." NetBSD IEEE 1275 Bootblock" cr
5901.1Smrg   boot-path load-file ( -- load-base )
5911.1Smrg   dup 0<> if  " to load-base init-program" evaluate then
5921.1Smrg;
5931.1Smrg
5941.1Smrg
5951.1Smrgboot-args ascii V strchr 0<> swap drop if
5961.1Smrg true to boot-debug?
5971.1Smrgthen
5981.1Smrg
5991.1Smrgboot-args ascii D strchr 0= swap drop if
6001.1Smrg  " /ofwboot" do-boot
6011.1Smrgthen exit
6021.1Smrg
6031.1Smrg
604