bootblk.fth revision 1.3
11.3Seeh\	$NetBSD: bootblk.fth,v 1.3 2001/08/15 20:10:24 eeh 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.3Seeh0 value raid-offset	\ Offset if it's a raid-frame partition
1291.1Smrg
1301.1Smrg: strategy ( addr size start -- nread )
1311.3Seeh   raid-offset + bsize * 0 " seek" boot-ihandle $call-method
1321.1Smrg   -1 = if 
1331.1Smrg      ." strategy: Seek failed" cr
1341.1Smrg      abort
1351.1Smrg   then
1361.1Smrg   " read" boot-ihandle $call-method
1371.1Smrg;
1381.1Smrg
1391.1Smrg\
1401.1Smrg\ Cylinder group macros
1411.1Smrg\
1421.1Smrg
1431.1Smrg: cgbase ( cg fs -- cgbase ) fs_fpg l@ * ;
1441.1Smrg: cgstart ( cg fs -- cgstart ) 
1451.1Smrg   2dup fs_cgmask l@ not and		( cg fs stuff -- )
1461.1Smrg   over fs_cgoffset l@ * -rot		( stuffcg fs -- )
1471.1Smrg   cgbase +
1481.1Smrg;
1491.1Smrg: cgdmin ( cg fs -- 1st-data-block ) dup fs_dblkno l@ -rot cgstart + ;
1501.1Smrg: cgimin ( cg fs -- inode-block ) dup fs_iblkno l@ -rot cgstart + ;
1511.1Smrg: cgsblock ( cg fs -- super-block ) dup fs_sblkno l@ -rot cgstart + ;
1521.1Smrg: cgstod ( cg fs -- cg-block ) dup fs_cblkno l@ -rot cgstart + ;
1531.1Smrg
1541.1Smrg\
1551.1Smrg\ Block and frag position macros
1561.1Smrg\
1571.1Smrg
1581.1Smrg: blkoff ( pos fs -- off ) fs_qbmask x@ and ;
1591.1Smrg: fragoff ( pos fs -- off ) fs_qfmask x@ and ;
1601.1Smrg: lblktosize ( blk fs -- off ) fs_bshift l@ << ;
1611.1Smrg: lblkno ( pos fs -- off ) fs_bshift l@ >> ;
1621.1Smrg: numfrags ( pos fs -- off ) fs_fshift l@ >> ;
1631.1Smrg: blkroundup ( pos fs -- off ) dup fs_bmask l@ -rot fs_qbmask x@ + and ;
1641.1Smrg: fragroundup ( pos fs -- off ) dup fs_fmask l@ -rot fs_qfmask x@ + and ;
1651.1Smrg\ : fragroundup ( pos fs -- off ) tuck fs_qfmask x@ + swap fs_fmask l@ and ;
1661.1Smrg: fragstoblks ( pos fs -- off ) fs_fragshift l@ >> ;
1671.1Smrg: blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ;
1681.1Smrg: fragnum ( fsb fs -- off ) fs_frag l@ 1- and ;
1691.1Smrg: blknum ( fsb fs -- off ) fs_frag l@ 1- not and ;
1701.1Smrg: dblksize ( lbn dino fs -- size )
1711.1Smrg   -rot 				( fs lbn dino )
1721.1Smrg   di_size x@				( fs lbn di_size )
1731.1Smrg   -rot dup 1+				( di_size fs lbn lbn+1 )
1741.1Smrg   2over fs_bshift l@			( di_size fs lbn lbn+1 di_size b_shift )
1751.1Smrg   rot swap <<	>=			( di_size fs lbn res1 )
1761.1Smrg   swap ndaddr >= or if			( di_size fs )
1771.1Smrg      swap drop fs_bsize l@ exit	( size )
1781.1Smrg   then	tuck blkoff swap fragroundup	( size )
1791.1Smrg;
1801.1Smrg
1811.1Smrg
1821.1Smrg: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ;
1831.1Smrg: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ;
1841.1Smrg: ino-to-fsba ( ino fs -- ba )	\ Need to remove the stupid stack diags someday
1851.1Smrg   2dup 				( ino fs ino fs )
1861.1Smrg   ino-to-cg				( ino fs cg )
1871.1Smrg   over					( ino fs cg fs )
1881.1Smrg   cgimin				( ino fs inode-blk )
1891.1Smrg   -rot					( inode-blk ino fs )
1901.1Smrg   tuck 				( inode-blk fs ino fs )
1911.1Smrg   fs_ipg l@ 				( inode-blk fs ino ipg )
1921.1Smrg   mod					( inode-blk fs mod )
1931.1Smrg   swap					( inode-blk mod fs )
1941.1Smrg   dup 					( inode-blk mod fs fs )
1951.1Smrg   fs_inopb l@ 				( inode-blk mod fs inopb )
1961.1Smrg   rot 					( inode-blk fs inopb mod )
1971.1Smrg   swap					( inode-blk fs mod inopb )
1981.1Smrg   /					( inode-blk fs div )
1991.1Smrg   swap					( inode-blk div fs )
2001.1Smrg   blkstofrags				( inode-blk frag )
2011.1Smrg   +
2021.1Smrg;
2031.1Smrg: fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ;
2041.1Smrg
2051.1Smrg\
2061.1Smrg\ File stuff
2071.1Smrg\
2081.1Smrg
2091.1Smrgniaddr /w* constant narraysize
2101.1Smrg
2111.1Smrgstruct 
2121.1Smrg   8		field	>f_ihandle	\ device handle
2131.1Smrg   8 		field 	>f_seekp	\ seek pointer
2141.1Smrg   8 		field 	>f_fs		\ pointer to super block
2151.1Smrg   dinode_SIZEOF 	field 	>f_di	\ copy of on-disk inode
2161.1Smrg   8		field	>f_buf		\ buffer for data block
2171.1Smrg   4		field 	>f_buf_size	\ size of data block
2181.1Smrg   4		field	>f_buf_blkno	\ block number of data block
2191.1Smrgconstant file_SIZEOF
2201.1Smrg
2211.1Smrgfile_SIZEOF buffer: the-file
2221.1Smrgsb-buf the-file >f_fs x!
2231.1Smrg
2241.1Smrgdinode_SIZEOF buffer: cur-inode
2251.1Smrgh# 2000 buffer: indir-block
2261.1Smrg-1 value indir-addr
2271.1Smrg
2281.1Smrg\
2291.1Smrg\ Translate a fileblock to a disk block
2301.1Smrg\
2311.1Smrg\ We only allow single indirection
2321.1Smrg\
2331.1Smrg
2341.1Smrg: block-map ( fileblock -- diskblock )
2351.1Smrg   \ Direct block?
2361.1Smrg   dup ndaddr <  if 			( fileblock )
2371.1Smrg      cur-inode di_db			( arr-indx arr-start )
2381.1Smrg      swap la+ l@ exit			( diskblock )
2391.1Smrg   then 				( fileblock )
2401.1Smrg   ndaddr -				( fileblock' )
2411.1Smrg   \ Now we need to check the indirect block
2421.1Smrg   dup sb-buf fs_nindir l@ <  if	( fileblock' )
2431.1Smrg      cur-inode di_ib l@ dup		( fileblock' indir-block indir-block )
2441.1Smrg      indir-addr <>  if 		( fileblock' indir-block )
2451.1Smrg         to indir-addr			( fileblock' )
2461.1Smrg         indir-block 			( fileblock' indir-block )
2471.1Smrg         sb-buf dup fs_bsize l@		( fileblock' indir-block fs fs_bsize )
2481.1Smrg         swap indir-addr swap		( fileblock' indir-block fs_bsize indiraddr fs )
2491.1Smrg         fsbtodb 			( fileblock' indir-block fs_bsize db )
2501.1Smrg         strategy			( fileblock' nread )
2511.1Smrg      then				( fileblock' nread|indir-block )
2521.1Smrg      drop \ Really should check return value
2531.1Smrg      indir-block swap la+ l@ exit
2541.1Smrg   then
2551.1Smrg   dup sb-buf fs_nindir -		( fileblock'' )
2561.1Smrg   \ Now try 2nd level indirect block -- just read twice 
2571.1Smrg   dup sb-buf fs_nindir l@ dup * < if	( fileblock'' )
2581.1Smrg      cur-inode di_ib 1 la+ l@		( fileblock'' indir2-block )
2591.1Smrg      to indir-addr			( fileblock'' )
2601.1Smrg      \ load 1st level indir block 
2611.1Smrg      indir-block 			( fileblock'' indir-block )
2621.1Smrg      sb-buf dup fs_bsize l@		( fileblock'' indir-block fs fs_bsize )
2631.1Smrg      swap indir-addr swap		( fileblock'' indir-block fs_bsize indiraddr fs )
2641.1Smrg      fsbtodb 				( fileblock'' indir-block fs_bsize db )
2651.1Smrg      strategy				( fileblock'' nread )
2661.1Smrg      drop				( fileblock'' )
2671.1Smrg      dup sb-buf fs_nindir /		( fileblock'' indir-offset )
2681.1Smrg      indir-block swap la+ l@		( fileblock'' indirblock )
2691.1Smrg      to indir-addr			( fileblock'' )
2701.1Smrg      \ load 2nd level indir block
2711.1Smrg      indir-block 			( fileblock'' indir-block )
2721.1Smrg      sb-buf dup fs_bsize l@		( fileblock'' indir-block fs fs_bsize )
2731.1Smrg      swap indir-addr swap		( fileblock'' indir-block fs_bsize indiraddr fs )
2741.1Smrg      fsbtodb 				( fileblock'' indir-block fs_bsize db )
2751.1Smrg      strategy				( fileblock'' nread )
2761.1Smrg      drop				( fileblock'' )
2771.1Smrg      sb-buf fs_nindir l@ mod indir-block swap la+ l@ exit
2781.1Smrg   then
2791.1Smrg   ." block-map: exceeded max file size" cr
2801.1Smrg   abort
2811.1Smrg;
2821.1Smrg
2831.1Smrg\
2841.1Smrg\ Read file into internal buffer and return pointer and len
2851.1Smrg\
2861.1Smrg
2871.1Smrg2000 buffer: cur-block		\ Why do dynamic allocation?
2881.1Smrg-1 value cur-blockno
2891.1Smrg0 value cur-offset
2901.1Smrg
2911.1Smrg: buf-read-file ( fs -- len buf )
2921.1Smrg   cur-offset swap			( seekp fs )
2931.1Smrg   2dup blkoff				( seekp fs off )
2941.1Smrg   -rot 2dup lblkno			( off seekp fs block )
2951.1Smrg   swap 2dup cur-inode			( off seekp block fs block fs inop )
2961.1Smrg   swap dblksize			( off seekp block fs size )
2971.1Smrg   rot dup cur-blockno			( off seekp fs size block block cur )
2981.1Smrg   <>  if 				( off seekp fs size block )
2991.1Smrg      block-map				( off seekp fs size diskblock )
3001.1Smrg      dup 0=  if			( off seekp fs size diskblock )
3011.1Smrg         over cur-block swap 0 fill	( off seekp fs size diskblock )
3021.1Smrg         boot-debug?  if ." buf-read-file fell off end of file" cr then
3031.1Smrg      else
3041.1Smrg         2dup sb-buf fsbtodb cur-block -rot strategy	( off seekp fs size diskblock nread )
3051.1Smrg         rot 2dup <>  if " buf-read-file: short read." cr abort then
3061.1Smrg      then				( off seekp fs diskblock nread size )
3071.1Smrg      nip nip				( off seekp fs size )
3081.1Smrg   else					( off seekp fs size block block cur )
3091.1Smrg      2drop				( off seekp fs size )
3101.1Smrg   then
3111.1Smrg\   dup cur-offset + to cur-offset	\ Set up next xfer -- not done
3121.1Smrg   nip nip swap -			( len )
3131.1Smrg   cur-block
3141.1Smrg;
3151.1Smrg
3161.1Smrg\
3171.1Smrg\ Read inode into cur-inode -- uses cur-block
3181.1Smrg\ 
3191.1Smrg
3201.1Smrg: read-inode ( inode fs -- )
3211.1Smrg   twiddle				( inode fs -- inode fs )
3221.1Smrg
3231.1Smrg   cur-block				( inode fs -- inode fs buffer )
3241.1Smrg
3251.1Smrg   over					( inode fs buffer -- inode fs buffer fs )
3261.1Smrg   fs_bsize l@				( inode fs buffer -- inode fs buffer size )
3271.1Smrg
3281.1Smrg   2over				( inode fs buffer size -- inode fs buffer size inode fs )
3291.1Smrg   2over				( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size )
3301.1Smrg   2swap tuck				( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs )
3311.1Smrg
3321.1Smrg   ino-to-fsba 				( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba )
3331.1Smrg   swap					( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs )
3341.1Smrg   fsbtodb				( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db )
3351.1Smrg
3361.1Smrg   dup to cur-blockno			( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart )
3371.1Smrg   strategy				( inode fs buffer size buffer size dstart -- inode fs buffer size nread )
3381.1Smrg   <>  if ." read-inode - residual" cr abort then
3391.1Smrg   dup 2over				( inode fs buffer -- inode fs buffer buffer inode fs )
3401.1Smrg   ino-to-fsbo				( inode fs buffer -- inode fs buffer buffer fsbo )
3411.1Smrg   dinode_SIZEOF * +			( inode fs buffer buffer fsbo -- inode fs buffer dinop )
3421.1Smrg   cur-inode dinode_SIZEOF move 	( inode fs buffer dinop -- inode fs buffer )
3431.1Smrg	\ clear out the old buffers
3441.1Smrg   drop					( inode fs buffer -- inode fs )
3451.1Smrg   2drop
3461.1Smrg;
3471.1Smrg
3481.1Smrg\ Identify inode type
3491.1Smrg
3501.1Smrg: is-dir? ( dinode -- true:false ) di_mode w@ ifmt and ifdir = ;
3511.1Smrg: is-symlink? ( dinode -- true:false ) di_mode w@ ifmt and iflnk = ;
3521.1Smrg
3531.1Smrg
3541.1Smrg
3551.1Smrg\
3561.1Smrg\ Hunt for directory entry:
3571.1Smrg\ 
3581.1Smrg\ repeat
3591.1Smrg\    load a buffer
3601.1Smrg\    while entries do
3611.1Smrg\       if entry == name return
3621.1Smrg\       next entry
3631.1Smrg\ until no buffers
3641.1Smrg\
3651.1Smrg
3661.1Smrg: search-directory ( str len -- ino|0 )
3671.1Smrg   0 to cur-offset
3681.1Smrg   begin cur-offset cur-inode di_size x@ < while	( str len )
3691.1Smrg      sb-buf buf-read-file		( str len len buf )
3701.1Smrg      over 0=  if ." search-directory: buf-read-file zero len" cr abort then
3711.1Smrg      swap dup cur-offset + to cur-offset	( str len buf len )
3721.1Smrg      2dup + nip			( str len buf bufend )
3731.1Smrg      swap 2swap rot			( bufend str len buf )
3741.1Smrg      begin dup 4 pick < while		( bufend str len buf )
3751.1Smrg         dup d_ino l@ 0<>  if 		( bufend str len buf )
3761.1Smrg            boot-debug?  if dup dup d_name swap d_namlen c@ type cr then
3771.1Smrg            2dup d_namlen c@ =  if	( bufend str len buf )
3781.1Smrg               dup d_name 2over		( bufend str len buf dname str len )
3791.1Smrg               comp 0= if		( bufend str len buf )
3801.1Smrg                  \ Found it -- return inode
3811.1Smrg                  d_ino l@ nip nip nip	( dino )
3821.1Smrg                  boot-debug?  if ." Found it" cr then 
3831.1Smrg                  exit 			( dino )
3841.1Smrg               then
3851.1Smrg            then			( bufend str len buf )
3861.1Smrg         then				( bufend str len buf )
3871.1Smrg         dup d_reclen w@ +		( bufend str len nextbuf )
3881.1Smrg      repeat
3891.1Smrg      drop rot drop			( str len )
3901.1Smrg   repeat
3911.1Smrg   2drop 2drop 0			( 0 )
3921.1Smrg;
3931.1Smrg
3941.1Smrg: ffs_oldcompat ( -- )
3951.1Smrg\ Make sure old ffs values in sb-buf are sane
3961.1Smrg   sb-buf fs_npsect dup l@ sb-buf fs_nsect l@ max swap l!
3971.1Smrg   sb-buf fs_interleave dup l@ 1 max swap l!
3981.1Smrg   sb-buf fs_postblformat l@ fs_42postblfmt =  if
3991.1Smrg      8 sb-buf fs_nrpos l!
4001.1Smrg   then
4011.1Smrg   sb-buf fs_inodefmt l@ fs_44inodefmt <  if
4021.1Smrg      sb-buf fs_bsize l@ 
4031.1Smrg      dup ndaddr * 1- sb-buf fs_maxfilesize x!
4041.1Smrg      niaddr 0 ?do
4051.1Smrg	sb-buf fs_nindir l@ * dup	( sizebp sizebp -- )
4061.1Smrg	sb-buf fs_maxfilesize dup x@	( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- )
4071.1Smrg	rot ( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- )
4081.1Smrg	+ ( sizebp *fs_maxfilesize new_fs_maxfilesize  -- ) swap x! ( sizebp -- )
4091.1Smrg      loop drop ( -- )
4101.1Smrg      sb-buf dup fs_bmask l@ not swap fs_qbmask x!
4111.1Smrg      sb-buf dup fs_fmask l@ not swap fs_qfmask x!
4121.1Smrg   then
4131.1Smrg;
4141.1Smrg
4151.3Seeh: read-super ( sector -- )
4161.3Seeh0 " seek" boot-ihandle $call-method
4171.1Smrg   -1 = if 
4181.1Smrg      ." Seek failed" cr
4191.1Smrg      abort
4201.1Smrg   then
4211.1Smrg   sb-buf sbsize " read" boot-ihandle $call-method
4221.1Smrg   dup sbsize <>  if
4231.1Smrg      ." Read of superblock failed" cr
4241.1Smrg      ." requested" space sbsize .
4251.1Smrg      ." actual" space . cr
4261.1Smrg      abort
4271.1Smrg   else 
4281.1Smrg      drop
4291.1Smrg   then
4301.3Seeh;
4311.3Seeh
4321.3Seeh: ufs-open ( bootpath,len -- )
4331.3Seeh   boot-ihandle -1 =  if
4341.3Seeh      over cif-open dup 0=  if 		( boot-path len ihandle? )
4351.3Seeh         ." Could not open device" space type cr 
4361.3Seeh         abort
4371.3Seeh      then 				( boot-path len ihandle )
4381.3Seeh      to boot-ihandle			\ Save ihandle to boot device
4391.3Seeh   then 2drop
4401.3Seeh   sboff read-super
4411.1Smrg   sb-buf fs_magic l@ fs_magic_value <>  if
4421.3Seeh      64 dup to raid-offset 
4431.3Seeh      dev_bsize * sboff + read-super
4441.3Seeh      sb-buf fs_magic l@ fs_magic_value <>  if
4451.3Seeh         ." Invalid superblock magic" cr
4461.3Seeh         abort
4471.3Seeh      then
4481.1Smrg   then
4491.1Smrg   sb-buf fs_bsize l@ dup maxbsize >  if
4501.1Smrg      ." Superblock bsize" space . ." too large" cr
4511.1Smrg      abort
4521.1Smrg   then 
4531.1Smrg   fs_SIZEOF <  if
4541.1Smrg      ." Superblock bsize < size of superblock" cr
4551.1Smrg      abort
4561.1Smrg   then
4571.1Smrg   ffs_oldcompat
4581.1Smrg   boot-debug?  if ." ufs-open complete" cr then
4591.1Smrg;
4601.1Smrg
4611.1Smrg: ufs-close ( -- ) 
4621.1Smrg   boot-ihandle dup -1 <>  if
4631.1Smrg      cif-close -1 to boot-ihandle 
4641.1Smrg   then
4651.1Smrg;
4661.1Smrg
4671.1Smrg: boot-path ( -- boot-path )
4681.1Smrg   " bootpath" chosen-phandle get-package-property  if
4691.1Smrg      ." Could not find bootpath in /chosen" cr
4701.1Smrg      abort
4711.1Smrg   else
4721.1Smrg      decode-string 2swap 2drop
4731.1Smrg   then
4741.1Smrg;
4751.1Smrg
4761.1Smrg: boot-args ( -- boot-args )
4771.1Smrg   " bootargs" chosen-phandle get-package-property  if
4781.1Smrg      ." Could not find bootargs in /chosen" cr
4791.1Smrg      abort
4801.1Smrg   else
4811.1Smrg      decode-string 2swap 2drop
4821.1Smrg   then
4831.1Smrg;
4841.1Smrg
4851.1Smrg2000 buffer: boot-path-str
4861.1Smrg2000 buffer: boot-path-tmp
4871.1Smrg
4881.1Smrg: split-path ( path len -- right len left len )
4891.1Smrg\ Split a string at the `/'
4901.1Smrg   begin
4911.1Smrg      dup -rot				( oldlen right len left )
4921.1Smrg      ascii / left-parse-string		( oldlen right len left len )
4931.1Smrg      dup 0<>  if 4 roll drop exit then
4941.1Smrg      2drop				( oldlen right len )
4951.1Smrg      rot over =			( right len diff )
4961.1Smrg   until
4971.1Smrg;
4981.1Smrg
4991.1Smrg: find-file ( load-file len -- )
5001.1Smrg   rootino dup sb-buf read-inode	( load-file len -- load-file len ino )
5011.1Smrg   -rot					( load-file len ino -- pino load-file len )
5021.1Smrg   \
5031.1Smrg   \ For each path component
5041.1Smrg   \ 
5051.1Smrg   begin split-path dup 0<> while	( pino right len left len -- )
5061.1Smrg      cur-inode is-dir? not  if ." Inode not directory" cr abort then
5071.1Smrg      boot-debug?  if ." Looking for" space 2dup type space ." in directory..." cr then
5081.1Smrg      search-directory			( pino right len left len -- pino right len ino|false )
5091.1Smrg      dup 0=  if ." Bad path" cr abort then	( pino right len cino )
5101.1Smrg      sb-buf read-inode			( pino right len )
5111.1Smrg      cur-inode is-symlink?  if		\ Symlink -- follow the damn thing
5121.1Smrg         \ Save path in boot-path-tmp
5131.1Smrg         boot-path-tmp strmov		( pino new-right len )
5141.1Smrg
5151.1Smrg         \ Now deal with symlink
5161.1Smrg         cur-inode di_size x@		( pino right len linklen )
5171.1Smrg         dup sb-buf fs_maxsymlinklen l@	( pino right len linklen linklen maxlinklen )
5181.1Smrg         <  if				\ Now join the link to the path
5191.1Smrg            cur-inode di_shortlink l@	( pino right len linklen linkp )
5201.1Smrg            swap boot-path-str strmov	( pino right len new-linkp linklen )
5211.1Smrg         else				\ Read file for symlink -- Ugh
5221.1Smrg            \ Read link into boot-path-str
5231.1Smrg            boot-path-str dup sb-buf fs_bsize l@
5241.1Smrg            0 block-map			( pino right len linklen boot-path-str bsize blockno )
5251.1Smrg            strategy drop swap		( pino right len boot-path-str linklen )
5261.1Smrg         then 				( pino right len linkp linklen )
5271.1Smrg         \ Concatenate the two paths
5281.1Smrg         strcat				( pino new-right newlen )
5291.1Smrg         swap dup c@ ascii / =  if	\ go to root inode?
5301.1Smrg            rot drop rootino -rot	( rino len right )
5311.1Smrg         then
5321.1Smrg         rot dup sb-buf read-inode	( len right pino )
5331.1Smrg         -rot swap			( pino right len )
5341.1Smrg      then				( pino right len )
5351.1Smrg   repeat
5361.1Smrg   2drop drop
5371.1Smrg;
5381.1Smrg
5391.1Smrg: read-file ( size addr -- )
5401.1Smrg   \ Read x bytes from a file to buffer
5411.1Smrg   begin over 0> while
5421.1Smrg      cur-offset cur-inode di_size x@ >  if ." read-file EOF exceeded" cr abort then
5431.1Smrg      sb-buf buf-read-file		( size addr len buf )
5441.1Smrg      over 2over drop swap		( size addr len buf addr len )
5451.1Smrg      move				( size addr len )
5461.1Smrg      dup cur-offset + to cur-offset	( size len newaddr )
5471.1Smrg      tuck +				( size len newaddr )
5481.1Smrg      -rot - swap			( newaddr newsize )
5491.1Smrg   repeat
5501.1Smrg   2drop
5511.1Smrg;
5521.1Smrg
5531.1Smrgh# 5000 constant loader-base
5541.1Smrg
5551.1Smrg\
5561.1Smrg\ Elf support -- find the load addr
5571.1Smrg\
5581.1Smrg
5591.1Smrg: is-elf? ( hdr -- res? ) h# 7f454c46 = ;
5601.1Smrg
5611.1Smrg\
5621.1Smrg\ Finally we finish it all off
5631.1Smrg\
5641.1Smrg
5651.1Smrg: load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
5661.1Smrg   ." Loading file" space 2over type cr ." from device" space 2dup type cr
5671.1Smrg;
5681.1Smrg
5691.1Smrg: load-file-print-size ( size -- size )
5701.1Smrg   ." Loading" space dup . space ." bytes of file..." cr 
5711.1Smrg;
5721.1Smrg
5731.1Smrg: load-file ( load-file len boot-path len -- load-base )
5741.1Smrg   boot-debug?  if load-file-signon then
5751.1Smrg   the-file file_SIZEOF 0 fill		\ Clear out file structure
5761.1Smrg   ufs-open 				( load-file len )
5771.1Smrg   find-file				( )
5781.1Smrg
5791.1Smrg   \
5801.1Smrg   \ Now we've found the file we should read it in in one big hunk
5811.1Smrg   \
5821.1Smrg
5831.1Smrg   cur-inode di_size x@			( file-len )
5841.1Smrg   dup " to file-size" evaluate		( file-len )
5851.1Smrg   boot-debug?  if load-file-print-size then
5861.1Smrg   0 to cur-offset
5871.1Smrg   loader-base				( buf-len addr )
5881.1Smrg   2dup read-file			( buf-len addr )
5891.1Smrg   ufs-close				( buf-len addr )
5901.1Smrg   dup is-elf?  if ." load-file: not an elf executable" cr abort then
5911.1Smrg
5921.1Smrg   \ Luckily the prom should be able to handle ELF executables by itself
5931.1Smrg
5941.1Smrg   nip					( addr )
5951.1Smrg;
5961.1Smrg
5971.1Smrg: do-boot ( bootfile -- )
5981.1Smrg   ." NetBSD IEEE 1275 Bootblock" cr
5991.1Smrg   boot-path load-file ( -- load-base )
6001.1Smrg   dup 0<> if  " to load-base init-program" evaluate then
6011.1Smrg;
6021.1Smrg
6031.1Smrg
6041.1Smrgboot-args ascii V strchr 0<> swap drop if
6051.1Smrg true to boot-debug?
6061.1Smrgthen
6071.1Smrg
6081.1Smrgboot-args ascii D strchr 0= swap drop if
6091.1Smrg  " /ofwboot" do-boot
6101.1Smrgthen exit
6111.1Smrg
6121.1Smrg
613