bootblk.fth revision 1.4
11.4Seeh\	$NetBSD: bootblk.fth,v 1.4 2002/06/12 22:18:02 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.4Seeh0 value cur-block			\ allocated dynamically in ufs-open
2881.4Seeh0 value cur-blocksize			\ size of cur-block
2891.1Smrg-1 value cur-blockno
2901.1Smrg0 value cur-offset
2911.1Smrg
2921.1Smrg: buf-read-file ( fs -- len buf )
2931.1Smrg   cur-offset swap			( seekp fs )
2941.1Smrg   2dup blkoff				( seekp fs off )
2951.1Smrg   -rot 2dup lblkno			( off seekp fs block )
2961.1Smrg   swap 2dup cur-inode			( off seekp block fs block fs inop )
2971.1Smrg   swap dblksize			( off seekp block fs size )
2981.1Smrg   rot dup cur-blockno			( off seekp fs size block block cur )
2991.1Smrg   <>  if 				( off seekp fs size block )
3001.1Smrg      block-map				( off seekp fs size diskblock )
3011.1Smrg      dup 0=  if			( off seekp fs size diskblock )
3021.1Smrg         over cur-block swap 0 fill	( off seekp fs size diskblock )
3031.1Smrg         boot-debug?  if ." buf-read-file fell off end of file" cr then
3041.1Smrg      else
3051.1Smrg         2dup sb-buf fsbtodb cur-block -rot strategy	( off seekp fs size diskblock nread )
3061.1Smrg         rot 2dup <>  if " buf-read-file: short read." cr abort then
3071.1Smrg      then				( off seekp fs diskblock nread size )
3081.1Smrg      nip nip				( off seekp fs size )
3091.1Smrg   else					( off seekp fs size block block cur )
3101.1Smrg      2drop				( off seekp fs size )
3111.1Smrg   then
3121.1Smrg\   dup cur-offset + to cur-offset	\ Set up next xfer -- not done
3131.1Smrg   nip nip swap -			( len )
3141.1Smrg   cur-block
3151.1Smrg;
3161.1Smrg
3171.1Smrg\
3181.1Smrg\ Read inode into cur-inode -- uses cur-block
3191.1Smrg\ 
3201.1Smrg
3211.1Smrg: read-inode ( inode fs -- )
3221.1Smrg   twiddle				( inode fs -- inode fs )
3231.1Smrg
3241.1Smrg   cur-block				( inode fs -- inode fs buffer )
3251.1Smrg
3261.1Smrg   over					( inode fs buffer -- inode fs buffer fs )
3271.1Smrg   fs_bsize l@				( inode fs buffer -- inode fs buffer size )
3281.1Smrg
3291.1Smrg   2over				( inode fs buffer size -- inode fs buffer size inode fs )
3301.1Smrg   2over				( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size )
3311.1Smrg   2swap tuck				( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs )
3321.1Smrg
3331.1Smrg   ino-to-fsba 				( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba )
3341.1Smrg   swap					( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs )
3351.1Smrg   fsbtodb				( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db )
3361.1Smrg
3371.1Smrg   dup to cur-blockno			( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart )
3381.1Smrg   strategy				( inode fs buffer size buffer size dstart -- inode fs buffer size nread )
3391.1Smrg   <>  if ." read-inode - residual" cr abort then
3401.1Smrg   dup 2over				( inode fs buffer -- inode fs buffer buffer inode fs )
3411.1Smrg   ino-to-fsbo				( inode fs buffer -- inode fs buffer buffer fsbo )
3421.1Smrg   dinode_SIZEOF * +			( inode fs buffer buffer fsbo -- inode fs buffer dinop )
3431.1Smrg   cur-inode dinode_SIZEOF move 	( inode fs buffer dinop -- inode fs buffer )
3441.1Smrg	\ clear out the old buffers
3451.1Smrg   drop					( inode fs buffer -- inode fs )
3461.1Smrg   2drop
3471.1Smrg;
3481.1Smrg
3491.1Smrg\ Identify inode type
3501.1Smrg
3511.1Smrg: is-dir? ( dinode -- true:false ) di_mode w@ ifmt and ifdir = ;
3521.1Smrg: is-symlink? ( dinode -- true:false ) di_mode w@ ifmt and iflnk = ;
3531.1Smrg
3541.1Smrg
3551.1Smrg
3561.1Smrg\
3571.1Smrg\ Hunt for directory entry:
3581.1Smrg\ 
3591.1Smrg\ repeat
3601.1Smrg\    load a buffer
3611.1Smrg\    while entries do
3621.1Smrg\       if entry == name return
3631.1Smrg\       next entry
3641.1Smrg\ until no buffers
3651.1Smrg\
3661.1Smrg
3671.1Smrg: search-directory ( str len -- ino|0 )
3681.1Smrg   0 to cur-offset
3691.1Smrg   begin cur-offset cur-inode di_size x@ < while	( str len )
3701.1Smrg      sb-buf buf-read-file		( str len len buf )
3711.1Smrg      over 0=  if ." search-directory: buf-read-file zero len" cr abort then
3721.1Smrg      swap dup cur-offset + to cur-offset	( str len buf len )
3731.1Smrg      2dup + nip			( str len buf bufend )
3741.1Smrg      swap 2swap rot			( bufend str len buf )
3751.1Smrg      begin dup 4 pick < while		( bufend str len buf )
3761.1Smrg         dup d_ino l@ 0<>  if 		( bufend str len buf )
3771.1Smrg            boot-debug?  if dup dup d_name swap d_namlen c@ type cr then
3781.1Smrg            2dup d_namlen c@ =  if	( bufend str len buf )
3791.1Smrg               dup d_name 2over		( bufend str len buf dname str len )
3801.1Smrg               comp 0= if		( bufend str len buf )
3811.1Smrg                  \ Found it -- return inode
3821.1Smrg                  d_ino l@ nip nip nip	( dino )
3831.1Smrg                  boot-debug?  if ." Found it" cr then 
3841.1Smrg                  exit 			( dino )
3851.1Smrg               then
3861.1Smrg            then			( bufend str len buf )
3871.1Smrg         then				( bufend str len buf )
3881.1Smrg         dup d_reclen w@ +		( bufend str len nextbuf )
3891.1Smrg      repeat
3901.1Smrg      drop rot drop			( str len )
3911.1Smrg   repeat
3921.1Smrg   2drop 2drop 0			( 0 )
3931.1Smrg;
3941.1Smrg
3951.1Smrg: ffs_oldcompat ( -- )
3961.1Smrg\ Make sure old ffs values in sb-buf are sane
3971.1Smrg   sb-buf fs_npsect dup l@ sb-buf fs_nsect l@ max swap l!
3981.1Smrg   sb-buf fs_interleave dup l@ 1 max swap l!
3991.1Smrg   sb-buf fs_postblformat l@ fs_42postblfmt =  if
4001.1Smrg      8 sb-buf fs_nrpos l!
4011.1Smrg   then
4021.1Smrg   sb-buf fs_inodefmt l@ fs_44inodefmt <  if
4031.1Smrg      sb-buf fs_bsize l@ 
4041.1Smrg      dup ndaddr * 1- sb-buf fs_maxfilesize x!
4051.1Smrg      niaddr 0 ?do
4061.1Smrg	sb-buf fs_nindir l@ * dup	( sizebp sizebp -- )
4071.1Smrg	sb-buf fs_maxfilesize dup x@	( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- )
4081.4Seeh	rot 				( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- )
4091.4Seeh	+ 				( sizebp *fs_maxfilesize new_fs_maxfilesize  -- ) 
4101.4Seeh        swap x! 			( sizebp -- )
4111.4Seeh      loop drop 			( -- )
4121.1Smrg      sb-buf dup fs_bmask l@ not swap fs_qbmask x!
4131.1Smrg      sb-buf dup fs_fmask l@ not swap fs_qfmask x!
4141.1Smrg   then
4151.1Smrg;
4161.1Smrg
4171.3Seeh: read-super ( sector -- )
4181.3Seeh0 " seek" boot-ihandle $call-method
4191.1Smrg   -1 = if 
4201.1Smrg      ." Seek failed" cr
4211.1Smrg      abort
4221.1Smrg   then
4231.1Smrg   sb-buf sbsize " read" boot-ihandle $call-method
4241.1Smrg   dup sbsize <>  if
4251.1Smrg      ." Read of superblock failed" cr
4261.1Smrg      ." requested" space sbsize .
4271.1Smrg      ." actual" space . cr
4281.1Smrg      abort
4291.1Smrg   else 
4301.1Smrg      drop
4311.1Smrg   then
4321.3Seeh;
4331.3Seeh
4341.3Seeh: ufs-open ( bootpath,len -- )
4351.3Seeh   boot-ihandle -1 =  if
4361.3Seeh      over cif-open dup 0=  if 		( boot-path len ihandle? )
4371.3Seeh         ." Could not open device" space type cr 
4381.3Seeh         abort
4391.3Seeh      then 				( boot-path len ihandle )
4401.3Seeh      to boot-ihandle			\ Save ihandle to boot device
4411.3Seeh   then 2drop
4421.3Seeh   sboff read-super
4431.1Smrg   sb-buf fs_magic l@ fs_magic_value <>  if
4441.3Seeh      64 dup to raid-offset 
4451.3Seeh      dev_bsize * sboff + read-super
4461.3Seeh      sb-buf fs_magic l@ fs_magic_value <>  if
4471.3Seeh         ." Invalid superblock magic" cr
4481.3Seeh         abort
4491.3Seeh      then
4501.1Smrg   then
4511.1Smrg   sb-buf fs_bsize l@ dup maxbsize >  if
4521.1Smrg      ." Superblock bsize" space . ." too large" cr
4531.1Smrg      abort
4541.1Smrg   then 
4551.4Seeh   dup fs_SIZEOF <  if
4561.1Smrg      ." Superblock bsize < size of superblock" cr
4571.1Smrg      abort
4581.1Smrg   then
4591.4Seeh   ffs_oldcompat	( fs_bsize -- fs_bsize )
4601.4Seeh   dup to cur-blocksize alloc-mem to cur-block    \ Allocate cur-block
4611.1Smrg   boot-debug?  if ." ufs-open complete" cr then
4621.1Smrg;
4631.1Smrg
4641.1Smrg: ufs-close ( -- ) 
4651.1Smrg   boot-ihandle dup -1 <>  if
4661.1Smrg      cif-close -1 to boot-ihandle 
4671.1Smrg   then
4681.4Seeh   cur-block 0<> if
4691.4Seeh      cur-block cur-blocksize free-mem
4701.4Seeh   then
4711.1Smrg;
4721.1Smrg
4731.1Smrg: boot-path ( -- boot-path )
4741.1Smrg   " bootpath" chosen-phandle get-package-property  if
4751.1Smrg      ." Could not find bootpath in /chosen" cr
4761.1Smrg      abort
4771.1Smrg   else
4781.1Smrg      decode-string 2swap 2drop
4791.1Smrg   then
4801.1Smrg;
4811.1Smrg
4821.1Smrg: boot-args ( -- boot-args )
4831.1Smrg   " bootargs" chosen-phandle get-package-property  if
4841.1Smrg      ." Could not find bootargs in /chosen" cr
4851.1Smrg      abort
4861.1Smrg   else
4871.1Smrg      decode-string 2swap 2drop
4881.1Smrg   then
4891.1Smrg;
4901.1Smrg
4911.1Smrg2000 buffer: boot-path-str
4921.1Smrg2000 buffer: boot-path-tmp
4931.1Smrg
4941.1Smrg: split-path ( path len -- right len left len )
4951.1Smrg\ Split a string at the `/'
4961.1Smrg   begin
4971.1Smrg      dup -rot				( oldlen right len left )
4981.1Smrg      ascii / left-parse-string		( oldlen right len left len )
4991.1Smrg      dup 0<>  if 4 roll drop exit then
5001.1Smrg      2drop				( oldlen right len )
5011.1Smrg      rot over =			( right len diff )
5021.1Smrg   until
5031.1Smrg;
5041.1Smrg
5051.1Smrg: find-file ( load-file len -- )
5061.1Smrg   rootino dup sb-buf read-inode	( load-file len -- load-file len ino )
5071.1Smrg   -rot					( load-file len ino -- pino load-file len )
5081.1Smrg   \
5091.1Smrg   \ For each path component
5101.1Smrg   \ 
5111.1Smrg   begin split-path dup 0<> while	( pino right len left len -- )
5121.1Smrg      cur-inode is-dir? not  if ." Inode not directory" cr abort then
5131.1Smrg      boot-debug?  if ." Looking for" space 2dup type space ." in directory..." cr then
5141.1Smrg      search-directory			( pino right len left len -- pino right len ino|false )
5151.1Smrg      dup 0=  if ." Bad path" cr abort then	( pino right len cino )
5161.1Smrg      sb-buf read-inode			( pino right len )
5171.1Smrg      cur-inode is-symlink?  if		\ Symlink -- follow the damn thing
5181.1Smrg         \ Save path in boot-path-tmp
5191.1Smrg         boot-path-tmp strmov		( pino new-right len )
5201.1Smrg
5211.1Smrg         \ Now deal with symlink
5221.1Smrg         cur-inode di_size x@		( pino right len linklen )
5231.1Smrg         dup sb-buf fs_maxsymlinklen l@	( pino right len linklen linklen maxlinklen )
5241.1Smrg         <  if				\ Now join the link to the path
5251.1Smrg            cur-inode di_shortlink l@	( pino right len linklen linkp )
5261.1Smrg            swap boot-path-str strmov	( pino right len new-linkp linklen )
5271.1Smrg         else				\ Read file for symlink -- Ugh
5281.1Smrg            \ Read link into boot-path-str
5291.1Smrg            boot-path-str dup sb-buf fs_bsize l@
5301.1Smrg            0 block-map			( pino right len linklen boot-path-str bsize blockno )
5311.1Smrg            strategy drop swap		( pino right len boot-path-str linklen )
5321.1Smrg         then 				( pino right len linkp linklen )
5331.1Smrg         \ Concatenate the two paths
5341.1Smrg         strcat				( pino new-right newlen )
5351.1Smrg         swap dup c@ ascii / =  if	\ go to root inode?
5361.1Smrg            rot drop rootino -rot	( rino len right )
5371.1Smrg         then
5381.1Smrg         rot dup sb-buf read-inode	( len right pino )
5391.1Smrg         -rot swap			( pino right len )
5401.1Smrg      then				( pino right len )
5411.1Smrg   repeat
5421.1Smrg   2drop drop
5431.1Smrg;
5441.1Smrg
5451.1Smrg: read-file ( size addr -- )
5461.1Smrg   \ Read x bytes from a file to buffer
5471.1Smrg   begin over 0> while
5481.1Smrg      cur-offset cur-inode di_size x@ >  if ." read-file EOF exceeded" cr abort then
5491.1Smrg      sb-buf buf-read-file		( size addr len buf )
5501.1Smrg      over 2over drop swap		( size addr len buf addr len )
5511.1Smrg      move				( size addr len )
5521.1Smrg      dup cur-offset + to cur-offset	( size len newaddr )
5531.1Smrg      tuck +				( size len newaddr )
5541.1Smrg      -rot - swap			( newaddr newsize )
5551.1Smrg   repeat
5561.1Smrg   2drop
5571.1Smrg;
5581.1Smrg
5591.4Seeh\
5601.4Seeh\ According to the 1275 addendum for SPARC processors:
5611.4Seeh\ Default load-base is 0x4000.  At least 0x8.0000 or
5621.4Seeh\ 512KB must be available at that address.  
5631.4Seeh\
5641.4Seeh\ The Fcode bootblock can take up up to 8KB (O.K., 7.5KB) 
5651.4Seeh\ so load programs at 0x4000 + 0x2000=> 0x6000
5661.4Seeh\
5671.4Seeh
5681.4Seehh# 6000 constant loader-base
5691.1Smrg
5701.1Smrg\
5711.1Smrg\ Elf support -- find the load addr
5721.1Smrg\
5731.1Smrg
5741.1Smrg: is-elf? ( hdr -- res? ) h# 7f454c46 = ;
5751.1Smrg
5761.1Smrg\
5771.1Smrg\ Finally we finish it all off
5781.1Smrg\
5791.1Smrg
5801.1Smrg: load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
5811.1Smrg   ." Loading file" space 2over type cr ." from device" space 2dup type cr
5821.1Smrg;
5831.1Smrg
5841.1Smrg: load-file-print-size ( size -- size )
5851.1Smrg   ." Loading" space dup . space ." bytes of file..." cr 
5861.1Smrg;
5871.1Smrg
5881.1Smrg: load-file ( load-file len boot-path len -- load-base )
5891.1Smrg   boot-debug?  if load-file-signon then
5901.1Smrg   the-file file_SIZEOF 0 fill		\ Clear out file structure
5911.1Smrg   ufs-open 				( load-file len )
5921.1Smrg   find-file				( )
5931.1Smrg
5941.1Smrg   \
5951.1Smrg   \ Now we've found the file we should read it in in one big hunk
5961.1Smrg   \
5971.1Smrg
5981.1Smrg   cur-inode di_size x@			( file-len )
5991.1Smrg   dup " to file-size" evaluate		( file-len )
6001.1Smrg   boot-debug?  if load-file-print-size then
6011.1Smrg   0 to cur-offset
6021.1Smrg   loader-base				( buf-len addr )
6031.1Smrg   2dup read-file			( buf-len addr )
6041.1Smrg   ufs-close				( buf-len addr )
6051.1Smrg   dup is-elf?  if ." load-file: not an elf executable" cr abort then
6061.1Smrg
6071.1Smrg   \ Luckily the prom should be able to handle ELF executables by itself
6081.1Smrg
6091.1Smrg   nip					( addr )
6101.1Smrg;
6111.1Smrg
6121.1Smrg: do-boot ( bootfile -- )
6131.1Smrg   ." NetBSD IEEE 1275 Bootblock" cr
6141.1Smrg   boot-path load-file ( -- load-base )
6151.1Smrg   dup 0<> if  " to load-base init-program" evaluate then
6161.1Smrg;
6171.1Smrg
6181.1Smrg
6191.1Smrgboot-args ascii V strchr 0<> swap drop if
6201.1Smrg true to boot-debug?
6211.1Smrgthen
6221.1Smrg
6231.1Smrgboot-args ascii D strchr 0= swap drop if
6241.1Smrg  " /ofwboot" do-boot
6251.1Smrgthen exit
6261.1Smrg
6271.1Smrg
628