bootblk.fth revision 1.8
11.8Sjdc\	$NetBSD: bootblk.fth,v 1.8 2008/06/29 14:13:23 jdc 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.8Sjdcfalse value force-raid	\ Force reads from raid offset
1301.1Smrg
1311.1Smrg: strategy ( addr size start -- nread )
1321.3Seeh   raid-offset + bsize * 0 " seek" boot-ihandle $call-method
1331.1Smrg   -1 = if 
1341.1Smrg      ." strategy: Seek failed" cr
1351.1Smrg      abort
1361.1Smrg   then
1371.1Smrg   " read" boot-ihandle $call-method
1381.1Smrg;
1391.1Smrg
1401.1Smrg\
1411.1Smrg\ Cylinder group macros
1421.1Smrg\
1431.1Smrg
1441.1Smrg: cgbase ( cg fs -- cgbase ) fs_fpg l@ * ;
1451.1Smrg: cgstart ( cg fs -- cgstart ) 
1461.5She   2dup fs_old_cgmask l@ not and		( cg fs stuff -- )
1471.5She   over fs_old_cgoffset l@ * -rot		( stuffcg fs -- )
1481.1Smrg   cgbase +
1491.1Smrg;
1501.1Smrg: cgdmin ( cg fs -- 1st-data-block ) dup fs_dblkno l@ -rot cgstart + ;
1511.1Smrg: cgimin ( cg fs -- inode-block ) dup fs_iblkno l@ -rot cgstart + ;
1521.1Smrg: cgsblock ( cg fs -- super-block ) dup fs_sblkno l@ -rot cgstart + ;
1531.1Smrg: cgstod ( cg fs -- cg-block ) dup fs_cblkno l@ -rot cgstart + ;
1541.1Smrg
1551.1Smrg\
1561.1Smrg\ Block and frag position macros
1571.1Smrg\
1581.1Smrg
1591.1Smrg: blkoff ( pos fs -- off ) fs_qbmask x@ and ;
1601.1Smrg: fragoff ( pos fs -- off ) fs_qfmask x@ and ;
1611.1Smrg: lblktosize ( blk fs -- off ) fs_bshift l@ << ;
1621.1Smrg: lblkno ( pos fs -- off ) fs_bshift l@ >> ;
1631.1Smrg: numfrags ( pos fs -- off ) fs_fshift l@ >> ;
1641.1Smrg: blkroundup ( pos fs -- off ) dup fs_bmask l@ -rot fs_qbmask x@ + and ;
1651.1Smrg: fragroundup ( pos fs -- off ) dup fs_fmask l@ -rot fs_qfmask x@ + and ;
1661.1Smrg\ : fragroundup ( pos fs -- off ) tuck fs_qfmask x@ + swap fs_fmask l@ and ;
1671.1Smrg: fragstoblks ( pos fs -- off ) fs_fragshift l@ >> ;
1681.1Smrg: blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ;
1691.1Smrg: fragnum ( fsb fs -- off ) fs_frag l@ 1- and ;
1701.1Smrg: blknum ( fsb fs -- off ) fs_frag l@ 1- not and ;
1711.1Smrg: dblksize ( lbn dino fs -- size )
1721.1Smrg   -rot 				( fs lbn dino )
1731.1Smrg   di_size x@				( fs lbn di_size )
1741.1Smrg   -rot dup 1+				( di_size fs lbn lbn+1 )
1751.1Smrg   2over fs_bshift l@			( di_size fs lbn lbn+1 di_size b_shift )
1761.1Smrg   rot swap <<	>=			( di_size fs lbn res1 )
1771.1Smrg   swap ndaddr >= or if			( di_size fs )
1781.1Smrg      swap drop fs_bsize l@ exit	( size )
1791.1Smrg   then	tuck blkoff swap fragroundup	( size )
1801.1Smrg;
1811.1Smrg
1821.1Smrg
1831.1Smrg: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ;
1841.1Smrg: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ;
1851.1Smrg: ino-to-fsba ( ino fs -- ba )	\ Need to remove the stupid stack diags someday
1861.1Smrg   2dup 				( ino fs ino fs )
1871.1Smrg   ino-to-cg				( ino fs cg )
1881.1Smrg   over					( ino fs cg fs )
1891.1Smrg   cgimin				( ino fs inode-blk )
1901.1Smrg   -rot					( inode-blk ino fs )
1911.1Smrg   tuck 				( inode-blk fs ino fs )
1921.1Smrg   fs_ipg l@ 				( inode-blk fs ino ipg )
1931.1Smrg   mod					( inode-blk fs mod )
1941.1Smrg   swap					( inode-blk mod fs )
1951.1Smrg   dup 					( inode-blk mod fs fs )
1961.1Smrg   fs_inopb l@ 				( inode-blk mod fs inopb )
1971.1Smrg   rot 					( inode-blk fs inopb mod )
1981.1Smrg   swap					( inode-blk fs mod inopb )
1991.1Smrg   /					( inode-blk fs div )
2001.1Smrg   swap					( inode-blk div fs )
2011.1Smrg   blkstofrags				( inode-blk frag )
2021.1Smrg   +
2031.1Smrg;
2041.1Smrg: fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ;
2051.1Smrg
2061.1Smrg\
2071.1Smrg\ File stuff
2081.1Smrg\
2091.1Smrg
2101.1Smrgniaddr /w* constant narraysize
2111.1Smrg
2121.1Smrgstruct 
2131.1Smrg   8		field	>f_ihandle	\ device handle
2141.1Smrg   8 		field 	>f_seekp	\ seek pointer
2151.1Smrg   8 		field 	>f_fs		\ pointer to super block
2161.5She   ufs1_dinode_SIZEOF 	field 	>f_di	\ copy of on-disk inode
2171.1Smrg   8		field	>f_buf		\ buffer for data block
2181.1Smrg   4		field 	>f_buf_size	\ size of data block
2191.1Smrg   4		field	>f_buf_blkno	\ block number of data block
2201.1Smrgconstant file_SIZEOF
2211.1Smrg
2221.1Smrgfile_SIZEOF buffer: the-file
2231.1Smrgsb-buf the-file >f_fs x!
2241.1Smrg
2251.5Sheufs1_dinode_SIZEOF buffer: cur-inode
2261.1Smrgh# 2000 buffer: indir-block
2271.1Smrg-1 value indir-addr
2281.1Smrg
2291.1Smrg\
2301.1Smrg\ Translate a fileblock to a disk block
2311.1Smrg\
2321.1Smrg\ We only allow single indirection
2331.1Smrg\
2341.1Smrg
2351.1Smrg: block-map ( fileblock -- diskblock )
2361.1Smrg   \ Direct block?
2371.1Smrg   dup ndaddr <  if 			( fileblock )
2381.1Smrg      cur-inode di_db			( arr-indx arr-start )
2391.1Smrg      swap la+ l@ exit			( diskblock )
2401.1Smrg   then 				( fileblock )
2411.1Smrg   ndaddr -				( fileblock' )
2421.1Smrg   \ Now we need to check the indirect block
2431.1Smrg   dup sb-buf fs_nindir l@ <  if	( fileblock' )
2441.1Smrg      cur-inode di_ib l@ dup		( fileblock' indir-block indir-block )
2451.1Smrg      indir-addr <>  if 		( fileblock' indir-block )
2461.1Smrg         to indir-addr			( fileblock' )
2471.1Smrg         indir-block 			( fileblock' indir-block )
2481.1Smrg         sb-buf dup fs_bsize l@		( fileblock' indir-block fs fs_bsize )
2491.1Smrg         swap indir-addr swap		( fileblock' indir-block fs_bsize indiraddr fs )
2501.1Smrg         fsbtodb 			( fileblock' indir-block fs_bsize db )
2511.1Smrg         strategy			( fileblock' nread )
2521.1Smrg      then				( fileblock' nread|indir-block )
2531.1Smrg      drop \ Really should check return value
2541.1Smrg      indir-block swap la+ l@ exit
2551.1Smrg   then
2561.1Smrg   dup sb-buf fs_nindir -		( fileblock'' )
2571.1Smrg   \ Now try 2nd level indirect block -- just read twice 
2581.1Smrg   dup sb-buf fs_nindir l@ dup * < if	( fileblock'' )
2591.1Smrg      cur-inode di_ib 1 la+ l@		( fileblock'' indir2-block )
2601.1Smrg      to indir-addr			( fileblock'' )
2611.1Smrg      \ load 1st level indir block 
2621.1Smrg      indir-block 			( fileblock'' indir-block )
2631.1Smrg      sb-buf dup fs_bsize l@		( fileblock'' indir-block fs fs_bsize )
2641.1Smrg      swap indir-addr swap		( fileblock'' indir-block fs_bsize indiraddr fs )
2651.1Smrg      fsbtodb 				( fileblock'' indir-block fs_bsize db )
2661.1Smrg      strategy				( fileblock'' nread )
2671.1Smrg      drop				( fileblock'' )
2681.1Smrg      dup sb-buf fs_nindir /		( fileblock'' indir-offset )
2691.1Smrg      indir-block swap la+ l@		( fileblock'' indirblock )
2701.1Smrg      to indir-addr			( fileblock'' )
2711.1Smrg      \ load 2nd level indir block
2721.1Smrg      indir-block 			( fileblock'' indir-block )
2731.1Smrg      sb-buf dup fs_bsize l@		( fileblock'' indir-block fs fs_bsize )
2741.1Smrg      swap indir-addr swap		( fileblock'' indir-block fs_bsize indiraddr fs )
2751.1Smrg      fsbtodb 				( fileblock'' indir-block fs_bsize db )
2761.1Smrg      strategy				( fileblock'' nread )
2771.1Smrg      drop				( fileblock'' )
2781.1Smrg      sb-buf fs_nindir l@ mod indir-block swap la+ l@ exit
2791.1Smrg   then
2801.1Smrg   ." block-map: exceeded max file size" cr
2811.1Smrg   abort
2821.1Smrg;
2831.1Smrg
2841.1Smrg\
2851.1Smrg\ Read file into internal buffer and return pointer and len
2861.1Smrg\
2871.1Smrg
2881.4Seeh0 value cur-block			\ allocated dynamically in ufs-open
2891.4Seeh0 value cur-blocksize			\ size of cur-block
2901.1Smrg-1 value cur-blockno
2911.1Smrg0 value cur-offset
2921.1Smrg
2931.1Smrg: buf-read-file ( fs -- len buf )
2941.1Smrg   cur-offset swap			( seekp fs )
2951.1Smrg   2dup blkoff				( seekp fs off )
2961.1Smrg   -rot 2dup lblkno			( off seekp fs block )
2971.1Smrg   swap 2dup cur-inode			( off seekp block fs block fs inop )
2981.1Smrg   swap dblksize			( off seekp block fs size )
2991.1Smrg   rot dup cur-blockno			( off seekp fs size block block cur )
3001.1Smrg   <>  if 				( off seekp fs size block )
3011.1Smrg      block-map				( off seekp fs size diskblock )
3021.1Smrg      dup 0=  if			( off seekp fs size diskblock )
3031.1Smrg         over cur-block swap 0 fill	( off seekp fs size diskblock )
3041.1Smrg         boot-debug?  if ." buf-read-file fell off end of file" cr then
3051.1Smrg      else
3061.1Smrg         2dup sb-buf fsbtodb cur-block -rot strategy	( off seekp fs size diskblock nread )
3071.1Smrg         rot 2dup <>  if " buf-read-file: short read." cr abort then
3081.1Smrg      then				( off seekp fs diskblock nread size )
3091.1Smrg      nip nip				( off seekp fs size )
3101.1Smrg   else					( off seekp fs size block block cur )
3111.1Smrg      2drop				( off seekp fs size )
3121.1Smrg   then
3131.1Smrg\   dup cur-offset + to cur-offset	\ Set up next xfer -- not done
3141.1Smrg   nip nip swap -			( len )
3151.1Smrg   cur-block
3161.1Smrg;
3171.1Smrg
3181.1Smrg\
3191.1Smrg\ Read inode into cur-inode -- uses cur-block
3201.1Smrg\ 
3211.1Smrg
3221.1Smrg: read-inode ( inode fs -- )
3231.1Smrg   twiddle				( inode fs -- inode fs )
3241.1Smrg
3251.1Smrg   cur-block				( inode fs -- inode fs buffer )
3261.1Smrg
3271.1Smrg   over					( inode fs buffer -- inode fs buffer fs )
3281.1Smrg   fs_bsize l@				( inode fs buffer -- inode fs buffer size )
3291.1Smrg
3301.1Smrg   2over				( inode fs buffer size -- inode fs buffer size inode fs )
3311.1Smrg   2over				( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size )
3321.1Smrg   2swap tuck				( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs )
3331.1Smrg
3341.1Smrg   ino-to-fsba 				( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba )
3351.1Smrg   swap					( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs )
3361.1Smrg   fsbtodb				( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db )
3371.1Smrg
3381.1Smrg   dup to cur-blockno			( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart )
3391.1Smrg   strategy				( inode fs buffer size buffer size dstart -- inode fs buffer size nread )
3401.1Smrg   <>  if ." read-inode - residual" cr abort then
3411.1Smrg   dup 2over				( inode fs buffer -- inode fs buffer buffer inode fs )
3421.1Smrg   ino-to-fsbo				( inode fs buffer -- inode fs buffer buffer fsbo )
3431.5She   ufs1_dinode_SIZEOF * +			( inode fs buffer buffer fsbo -- inode fs buffer dinop )
3441.5She   cur-inode ufs1_dinode_SIZEOF move 	( inode fs buffer dinop -- inode fs buffer )
3451.1Smrg	\ clear out the old buffers
3461.1Smrg   drop					( inode fs buffer -- inode fs )
3471.1Smrg   2drop
3481.1Smrg;
3491.1Smrg
3501.1Smrg\ Identify inode type
3511.1Smrg
3521.5She: is-dir? ( ufs1_dinode -- true:false ) di_mode w@ ifmt and ifdir = ;
3531.5She: is-symlink? ( ufs1_dinode -- true:false ) di_mode w@ ifmt and iflnk = ;
3541.1Smrg
3551.1Smrg
3561.1Smrg
3571.1Smrg\
3581.1Smrg\ Hunt for directory entry:
3591.1Smrg\ 
3601.1Smrg\ repeat
3611.1Smrg\    load a buffer
3621.1Smrg\    while entries do
3631.1Smrg\       if entry == name return
3641.1Smrg\       next entry
3651.1Smrg\ until no buffers
3661.1Smrg\
3671.1Smrg
3681.1Smrg: search-directory ( str len -- ino|0 )
3691.1Smrg   0 to cur-offset
3701.1Smrg   begin cur-offset cur-inode di_size x@ < while	( str len )
3711.1Smrg      sb-buf buf-read-file		( str len len buf )
3721.1Smrg      over 0=  if ." search-directory: buf-read-file zero len" cr abort then
3731.1Smrg      swap dup cur-offset + to cur-offset	( str len buf len )
3741.1Smrg      2dup + nip			( str len buf bufend )
3751.1Smrg      swap 2swap rot			( bufend str len buf )
3761.1Smrg      begin dup 4 pick < while		( bufend str len buf )
3771.1Smrg         dup d_ino l@ 0<>  if 		( bufend str len buf )
3781.1Smrg            boot-debug?  if dup dup d_name swap d_namlen c@ type cr then
3791.1Smrg            2dup d_namlen c@ =  if	( bufend str len buf )
3801.1Smrg               dup d_name 2over		( bufend str len buf dname str len )
3811.1Smrg               comp 0= if		( bufend str len buf )
3821.1Smrg                  \ Found it -- return inode
3831.1Smrg                  d_ino l@ nip nip nip	( dino )
3841.1Smrg                  boot-debug?  if ." Found it" cr then 
3851.1Smrg                  exit 			( dino )
3861.1Smrg               then
3871.1Smrg            then			( bufend str len buf )
3881.1Smrg         then				( bufend str len buf )
3891.1Smrg         dup d_reclen w@ +		( bufend str len nextbuf )
3901.1Smrg      repeat
3911.1Smrg      drop rot drop			( str len )
3921.1Smrg   repeat
3931.1Smrg   2drop 2drop 0			( 0 )
3941.1Smrg;
3951.1Smrg
3961.1Smrg: ffs_oldcompat ( -- )
3971.1Smrg\ Make sure old ffs values in sb-buf are sane
3981.5She   sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l!
3991.5She   sb-buf fs_old_interleave dup l@ 1 max swap l!
4001.5She   sb-buf fs_old_postblformat l@ fs_42postblfmt =  if
4011.5She      8 sb-buf fs_old_nrpos l!
4021.1Smrg   then
4031.5She   sb-buf fs_old_inodefmt l@ fs_44inodefmt <  if
4041.1Smrg      sb-buf fs_bsize l@ 
4051.1Smrg      dup ndaddr * 1- sb-buf fs_maxfilesize x!
4061.1Smrg      niaddr 0 ?do
4071.1Smrg	sb-buf fs_nindir l@ * dup	( sizebp sizebp -- )
4081.1Smrg	sb-buf fs_maxfilesize dup x@	( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- )
4091.4Seeh	rot 				( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- )
4101.4Seeh	+ 				( sizebp *fs_maxfilesize new_fs_maxfilesize  -- ) 
4111.4Seeh        swap x! 			( sizebp -- )
4121.4Seeh      loop drop 			( -- )
4131.1Smrg      sb-buf dup fs_bmask l@ not swap fs_qbmask x!
4141.1Smrg      sb-buf dup fs_fmask l@ not swap fs_qfmask x!
4151.1Smrg   then
4161.1Smrg;
4171.1Smrg
4181.3Seeh: read-super ( sector -- )
4191.3Seeh0 " seek" boot-ihandle $call-method
4201.1Smrg   -1 = if 
4211.1Smrg      ." Seek failed" cr
4221.1Smrg      abort
4231.1Smrg   then
4241.1Smrg   sb-buf sbsize " read" boot-ihandle $call-method
4251.1Smrg   dup sbsize <>  if
4261.1Smrg      ." Read of superblock failed" cr
4271.1Smrg      ." requested" space sbsize .
4281.1Smrg      ." actual" space . cr
4291.1Smrg      abort
4301.1Smrg   else 
4311.1Smrg      drop
4321.1Smrg   then
4331.3Seeh;
4341.3Seeh
4351.3Seeh: ufs-open ( bootpath,len -- )
4361.3Seeh   boot-ihandle -1 =  if
4371.3Seeh      over cif-open dup 0=  if 		( boot-path len ihandle? )
4381.3Seeh         ." Could not open device" space type cr 
4391.3Seeh         abort
4401.3Seeh      then 				( boot-path len ihandle )
4411.3Seeh      to boot-ihandle			\ Save ihandle to boot device
4421.3Seeh   then 2drop
4431.8Sjdc   force-raid if
4441.8Sjdc      boot-debug?  if ." Force RAID superblock read" cr then
4451.6Smartin      rf_protected dup to raid-offset 
4461.3Seeh      dev_bsize * sboff + read-super
4471.3Seeh      sb-buf fs_magic l@ fs_magic_value <>  if
4481.3Seeh         ." Invalid superblock magic" cr
4491.3Seeh         abort
4501.3Seeh      then
4511.8Sjdc   else
4521.8Sjdc      boot-debug?  if ." Normal superblock read" cr then
4531.8Sjdc      sboff read-super
4541.8Sjdc      sb-buf fs_magic l@ fs_magic_value <>  if
4551.8Sjdc         boot-debug?  if ." RAID superblock read" cr then
4561.8Sjdc         true to force-raid
4571.8Sjdc         rf_protected dup to raid-offset 
4581.8Sjdc         dev_bsize * sboff + read-super
4591.8Sjdc         sb-buf fs_magic l@ fs_magic_value <>  if
4601.8Sjdc            ." Invalid superblock magic" cr
4611.8Sjdc            abort
4621.8Sjdc         then
4631.8Sjdc      then
4641.1Smrg   then
4651.1Smrg   sb-buf fs_bsize l@ dup maxbsize >  if
4661.1Smrg      ." Superblock bsize" space . ." too large" cr
4671.1Smrg      abort
4681.1Smrg   then 
4691.4Seeh   dup fs_SIZEOF <  if
4701.1Smrg      ." Superblock bsize < size of superblock" cr
4711.1Smrg      abort
4721.1Smrg   then
4731.4Seeh   ffs_oldcompat	( fs_bsize -- fs_bsize )
4741.4Seeh   dup to cur-blocksize alloc-mem to cur-block    \ Allocate cur-block
4751.1Smrg   boot-debug?  if ." ufs-open complete" cr then
4761.1Smrg;
4771.1Smrg
4781.1Smrg: ufs-close ( -- ) 
4791.1Smrg   boot-ihandle dup -1 <>  if
4801.1Smrg      cif-close -1 to boot-ihandle 
4811.1Smrg   then
4821.4Seeh   cur-block 0<> if
4831.4Seeh      cur-block cur-blocksize free-mem
4841.4Seeh   then
4851.1Smrg;
4861.1Smrg
4871.1Smrg: boot-path ( -- boot-path )
4881.1Smrg   " bootpath" chosen-phandle get-package-property  if
4891.1Smrg      ." Could not find bootpath in /chosen" cr
4901.1Smrg      abort
4911.1Smrg   else
4921.1Smrg      decode-string 2swap 2drop
4931.1Smrg   then
4941.1Smrg;
4951.1Smrg
4961.1Smrg: boot-args ( -- boot-args )
4971.1Smrg   " bootargs" chosen-phandle get-package-property  if
4981.1Smrg      ." Could not find bootargs in /chosen" cr
4991.1Smrg      abort
5001.1Smrg   else
5011.1Smrg      decode-string 2swap 2drop
5021.1Smrg   then
5031.1Smrg;
5041.1Smrg
5051.1Smrg2000 buffer: boot-path-str
5061.1Smrg2000 buffer: boot-path-tmp
5071.1Smrg
5081.1Smrg: split-path ( path len -- right len left len )
5091.1Smrg\ Split a string at the `/'
5101.1Smrg   begin
5111.1Smrg      dup -rot				( oldlen right len left )
5121.1Smrg      ascii / left-parse-string		( oldlen right len left len )
5131.1Smrg      dup 0<>  if 4 roll drop exit then
5141.1Smrg      2drop				( oldlen right len )
5151.1Smrg      rot over =			( right len diff )
5161.1Smrg   until
5171.1Smrg;
5181.1Smrg
5191.1Smrg: find-file ( load-file len -- )
5201.1Smrg   rootino dup sb-buf read-inode	( load-file len -- load-file len ino )
5211.1Smrg   -rot					( load-file len ino -- pino load-file len )
5221.1Smrg   \
5231.1Smrg   \ For each path component
5241.1Smrg   \ 
5251.1Smrg   begin split-path dup 0<> while	( pino right len left len -- )
5261.8Sjdc      cur-inode is-dir? not  if ." Inode not directory" cr false exit then
5271.1Smrg      boot-debug?  if ." Looking for" space 2dup type space ." in directory..." cr then
5281.1Smrg      search-directory			( pino right len left len -- pino right len ino|false )
5291.1Smrg      dup 0=  if ." Bad path" cr abort then	( pino right len cino )
5301.1Smrg      sb-buf read-inode			( pino right len )
5311.1Smrg      cur-inode is-symlink?  if		\ Symlink -- follow the damn thing
5321.1Smrg         \ Save path in boot-path-tmp
5331.1Smrg         boot-path-tmp strmov		( pino new-right len )
5341.1Smrg
5351.1Smrg         \ Now deal with symlink
5361.1Smrg         cur-inode di_size x@		( pino right len linklen )
5371.1Smrg         dup sb-buf fs_maxsymlinklen l@	( pino right len linklen linklen maxlinklen )
5381.1Smrg         <  if				\ Now join the link to the path
5391.5She            cur-inode di_db l@	( pino right len linklen linkp )
5401.1Smrg            swap boot-path-str strmov	( pino right len new-linkp linklen )
5411.1Smrg         else				\ Read file for symlink -- Ugh
5421.1Smrg            \ Read link into boot-path-str
5431.1Smrg            boot-path-str dup sb-buf fs_bsize l@
5441.1Smrg            0 block-map			( pino right len linklen boot-path-str bsize blockno )
5451.1Smrg            strategy drop swap		( pino right len boot-path-str linklen )
5461.1Smrg         then 				( pino right len linkp linklen )
5471.1Smrg         \ Concatenate the two paths
5481.1Smrg         strcat				( pino new-right newlen )
5491.1Smrg         swap dup c@ ascii / =  if	\ go to root inode?
5501.1Smrg            rot drop rootino -rot	( rino len right )
5511.1Smrg         then
5521.1Smrg         rot dup sb-buf read-inode	( len right pino )
5531.1Smrg         -rot swap			( pino right len )
5541.1Smrg      then				( pino right len )
5551.1Smrg   repeat
5561.1Smrg   2drop drop
5571.8Sjdc   true
5581.1Smrg;
5591.1Smrg
5601.1Smrg: read-file ( size addr -- )
5611.1Smrg   \ Read x bytes from a file to buffer
5621.1Smrg   begin over 0> while
5631.1Smrg      cur-offset cur-inode di_size x@ >  if ." read-file EOF exceeded" cr abort then
5641.1Smrg      sb-buf buf-read-file		( size addr len buf )
5651.1Smrg      over 2over drop swap		( size addr len buf addr len )
5661.1Smrg      move				( size addr len )
5671.1Smrg      dup cur-offset + to cur-offset	( size len newaddr )
5681.1Smrg      tuck +				( size len newaddr )
5691.1Smrg      -rot - swap			( newaddr newsize )
5701.1Smrg   repeat
5711.1Smrg   2drop
5721.1Smrg;
5731.1Smrg
5741.4Seeh\
5751.4Seeh\ According to the 1275 addendum for SPARC processors:
5761.4Seeh\ Default load-base is 0x4000.  At least 0x8.0000 or
5771.4Seeh\ 512KB must be available at that address.  
5781.4Seeh\
5791.4Seeh\ The Fcode bootblock can take up up to 8KB (O.K., 7.5KB) 
5801.4Seeh\ so load programs at 0x4000 + 0x2000=> 0x6000
5811.4Seeh\
5821.4Seeh
5831.4Seehh# 6000 constant loader-base
5841.1Smrg
5851.1Smrg\
5861.1Smrg\ Elf support -- find the load addr
5871.1Smrg\
5881.1Smrg
5891.1Smrg: is-elf? ( hdr -- res? ) h# 7f454c46 = ;
5901.1Smrg
5911.1Smrg\
5921.1Smrg\ Finally we finish it all off
5931.1Smrg\
5941.1Smrg
5951.1Smrg: load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
5961.1Smrg   ." Loading file" space 2over type cr ." from device" space 2dup type cr
5971.1Smrg;
5981.1Smrg
5991.1Smrg: load-file-print-size ( size -- size )
6001.1Smrg   ." Loading" space dup . space ." bytes of file..." cr 
6011.1Smrg;
6021.1Smrg
6031.1Smrg: load-file ( load-file len boot-path len -- load-base )
6041.1Smrg   boot-debug?  if load-file-signon then
6051.1Smrg   the-file file_SIZEOF 0 fill		\ Clear out file structure
6061.8Sjdc   \ copy "load-file len boot-path len" in case we need to set "force-raid"
6071.8Sjdc   2over 2over				( load-file len boot-path len load-file len boot-path len )
6081.8Sjdc   ufs-open 				( load-file len boot-path len load-file len )
6091.8Sjdc   find-file not if			( load-file len boot-path len )
6101.8Sjdc      force-raid not if
6111.8Sjdc         true to force-raid		( )
6121.8Sjdc         ufs-close
6131.8Sjdc         2drop 2drop drop		( load-file len boot-path len )
6141.8Sjdc         ufs-open 			( load-file len )
6151.8Sjdc         find-file			( true:false )
6161.8Sjdc         drop
6171.8Sjdc      else
6181.8Sjdc         abort
6191.8Sjdc      then
6201.8Sjdc   else
6211.8Sjdc      \ We didn't set "force-raid", discard the copies
6221.8Sjdc      2drop 2drop			( )
6231.8Sjdc   then
6241.1Smrg
6251.1Smrg   \
6261.1Smrg   \ Now we've found the file we should read it in in one big hunk
6271.1Smrg   \
6281.1Smrg
6291.1Smrg   cur-inode di_size x@			( file-len )
6301.1Smrg   dup " to file-size" evaluate		( file-len )
6311.1Smrg   boot-debug?  if load-file-print-size then
6321.1Smrg   0 to cur-offset
6331.1Smrg   loader-base				( buf-len addr )
6341.1Smrg   2dup read-file			( buf-len addr )
6351.1Smrg   ufs-close				( buf-len addr )
6361.1Smrg   dup is-elf?  if ." load-file: not an elf executable" cr abort then
6371.1Smrg
6381.1Smrg   \ Luckily the prom should be able to handle ELF executables by itself
6391.1Smrg
6401.1Smrg   nip					( addr )
6411.1Smrg;
6421.1Smrg
6431.1Smrg: do-boot ( bootfile -- )
6441.1Smrg   ." NetBSD IEEE 1275 Bootblock" cr
6451.1Smrg   boot-path load-file ( -- load-base )
6461.1Smrg   dup 0<> if  " to load-base init-program" evaluate then
6471.1Smrg;
6481.1Smrg
6491.1Smrg
6501.1Smrgboot-args ascii V strchr 0<> swap drop if
6511.1Smrg true to boot-debug?
6521.1Smrgthen
6531.1Smrg
6541.1Smrgboot-args ascii D strchr 0= swap drop if
6551.1Smrg  " /ofwboot" do-boot
6561.1Smrgthen exit
6571.1Smrg
6581.1Smrg
659