11.18Sandvar\	$NetBSD: bootblk.fth,v 1.18 2025/02/28 09:07:12 andvar 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.10Seeh\	Copyright (c) 1998-2010 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\
201.1Smrg\	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
211.1Smrg\	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
221.1Smrg\	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
231.1Smrg\	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
241.1Smrg\	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
251.1Smrg\	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
261.1Smrg\	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
271.1Smrg\	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
281.1Smrg\	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
291.1Smrg\	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
301.1Smrg\
311.1Smrg
321.1Smrgoffset16
331.1Smrghex
341.1Smrgheaders
351.1Smrg
361.1Smrgfalse value boot-debug?
371.1Smrg
381.11Seeh: KB d# 1024 * ;
391.11Seeh
401.1Smrg\
411.1Smrg\ First some housekeeping:  Open /chosen and set up vectors into
421.1Smrg\	client-services
431.1Smrg
441.1Smrg" /chosen" find-package 0=  if ." Cannot find /chosen" 0 then
451.1Smrgconstant chosen-phandle
461.1Smrg
471.1Smrg" /openprom/client-services" find-package 0=  if 
481.1Smrg	." Cannot find client-services" cr abort
491.1Smrgthen constant cif-phandle
501.1Smrg
511.1Smrgdefer cif-claim ( align size virt -- base )
521.1Smrgdefer cif-release ( size virt -- )
531.1Smrgdefer cif-open ( cstr -- ihandle|0 )
541.1Smrgdefer cif-close ( ihandle -- )
551.1Smrgdefer cif-read ( len adr ihandle -- #read )
561.1Smrgdefer cif-seek ( low high ihandle -- -1|0|1 )
571.1Smrg\ defer cif-peer ( phandle -- phandle )
581.1Smrg\ defer cif-getprop ( len adr cstr phandle -- )
591.1Smrg
601.10Seeh: find-cif-method ( method len -- xf )
611.1Smrg   cif-phandle find-method drop 
621.1Smrg;
631.1Smrg
641.10Seeh" claim" find-cif-method  to  cif-claim
651.10Seeh" open" find-cif-method  to  cif-open
661.10Seeh" close" find-cif-method  to  cif-close
671.10Seeh" read" find-cif-method  to  cif-read
681.10Seeh" seek" find-cif-method  to  cif-seek
691.1Smrg
701.1Smrg: twiddle ( -- ) ." ." ; \ Need to do this right.  Just spit out periods for now.
711.1Smrg
721.1Smrg\
731.1Smrg\ Support routines
741.1Smrg\
751.1Smrg
761.10Seeh\ 64-bit math support
771.10Seeh
781.10Seehhere h# ffff over l! <w@ constant little-endian?
791.10Seeh: ul>d ( l -- d.lo d.hi )	0 ;
801.10Seeh: l>d ( l -- d.lo d.hi )	dup 0<  if  -1  else  0  then ;
811.10Seeh: d>l ( d.lo d.hi -- l )	drop ;
821.10Seeh: d@ ( addr -- d.lo d.hi )	dup l@ swap la1+ l@ little-endian? invert  if  swap  then ;
831.10Seeh: d! ( d.lo d.hi addr -- )
841.10Seeh   little-endian? invert  if  -rot swap rot  then  tuck la1+ l! l! ;
851.10Seeh: d-and ( d1 d2 -- d1-and-d2 )  rot and -rot and swap ;
861.10Seeh: d*u ( d1 u -- d2 )		tuck um* drop -rot um* rot + ;
871.10Seeh: d<< ( d1 n -- d1<<n )	\ Hope this works
881.12Seeh   ?dup  if  \ Shifting by 0 doesn't appear to work properly.
891.12Seeh      tuck <<			( d.lo n d.hi' )
901.12Seeh      -rot 2dup <<		( d.hi' d.lo n d.lo' )
911.12Seeh      -rot d# 32 swap - >>	( d.hi' d.lo' lo.hi )
921.12Seeh      rot +
931.12Seeh   then
941.10Seeh;
951.10Seeh: d>> ( d1 n -- d1>>n )	\ Hope this works
961.12Seeh   ?dup  if  \ Shifting by 0 doesn't appear to work properly.
971.12Seeh      rot over >>	-rot	( d.lo' d.hi n )
981.12Seeh      2dup >> -rot		( d.lo' d.hi' d.hi n )
991.12Seeh      d# 32 swap - << rot + swap
1001.12Seeh   then
1011.10Seeh;
1021.10Seeh: d> ( d1 d2 -- d1>d2? )
1031.10Seeh   rot swap 2dup = if
1041.10Seeh      2drop > exit
1051.10Seeh   then
1061.10Seeh   > nip nip
1071.10Seeh;
1081.10Seeh: d>= ( d1 d2 -- d1>=d2? )
1091.10Seeh   rot swap 2dup =  if
1101.10Seeh      2drop >= exit
1111.10Seeh   then
1121.10Seeh   >= nip nip
1131.10Seeh;
1141.10Seeh: d< ( d1 d2 -- d1<d2? )	d>= invert ;
1151.10Seeh: d= ( d1 d2 -- d1=d2? )	rot = -rot = and ;
1161.10Seeh: d<> ( d1 d2 -- d1<>d2? )	d= invert ;
1171.10Seeh
1181.10Seeh
1191.10Seeh\ String support 
1201.10Seeh
1211.1Smrg: strcmp ( s1 l1 s2 l2 -- true:false )
1221.10Seeh   rot tuck <>  if  3drop false exit  then
1231.1Smrg   comp 0=
1241.1Smrg;
1251.1Smrg
1261.1Smrg\ Move string into buffer
1271.1Smrg
1281.1Smrg: strmov ( s1 l1 d -- d l1 )
1291.1Smrg   dup 2over swap -rot		( s1 l1 d s1 d l1 )
1301.1Smrg   move				( s1 l1 d )
1311.1Smrg   rot drop swap
1321.1Smrg;
1331.1Smrg
1341.1Smrg\ Move s1 on the end of s2 and return the result
1351.1Smrg
1361.1Smrg: strcat ( s1 l1 s2 l2 -- d tot )
1371.1Smrg   2over swap 				( s1 l1 s2 l2 l1 s1 )
1381.1Smrg   2over + rot				( s1 l1 s2 l2 s1 d l1 )
1391.1Smrg   move rot + 				( s1 s2 len )
1401.1Smrg   rot drop				( s2 len )
1411.1Smrg;
1421.1Smrg
1431.1Smrg: strchr ( s1 l1 c -- s2 l2 )
1441.1Smrg   begin
1451.1Smrg      dup 2over 0= if			( s1 l1 c c s1  )
1461.1Smrg         2drop drop exit then
1471.1Smrg      c@ = if				( s1 l1 c )
1481.1Smrg         drop exit then
1491.1Smrg      -rot /c - swap ca1+		( c l2 s2 )
1501.1Smrg     swap rot
1511.1Smrg  again
1521.1Smrg;
1531.1Smrg
1541.1Smrg   
1551.1Smrg: cstr ( ptr -- str len )
1561.1Smrg   dup 
1571.1Smrg   begin dup c@ 0<>  while + repeat
1581.1Smrg   over -
1591.1Smrg;
1601.1Smrg
1611.1Smrg\
1621.10Seeh\ BSD UFS parameters
1631.1Smrg\
1641.1Smrg
1651.10Seehfload	ffs.fth.h
1661.10Seehfload   lfs.fth.h
1671.1Smrg
1681.1Smrgsbsize buffer: sb-buf
1691.1Smrg-1 value boot-ihandle
1701.1Smrgdev_bsize value bsize
1711.3Seeh0 value raid-offset	\ Offset if it's a raid-frame partition
1721.1Smrg
1731.10Seeh: strategy ( addr size db.lo db.hi -- nread )
1741.10Seeh    raid-offset l>d d+			( addr size db.lo' db.hi' )
1751.10Seeh    bsize d*u				( addr size sector.lo sector.hi )
1761.10Seeh    " seek" boot-ihandle $call-method -1 = if 
1771.10Seeh	." strategy: Seek failed" cr
1781.10Seeh	abort
1791.10Seeh    then				( addr size )
1801.10Seeh    " read" boot-ihandle $call-method
1811.10Seeh;
1821.10Seeh
1831.10Seeh
1841.10Seeh\
1851.10Seeh\ Multi-FS support
1861.10Seeh\
1871.10Seeh\ XXX Maybe the different filesystems should be segregated into separate files
1881.10Seeh\ XXX that are individually fload-ed.
1891.10Seeh\
1901.10Seeh
1911.10Seehdefer fs-size
1921.10Seehdefer di-size
1931.10Seehdefer di-mode
1941.10Seehdefer /dino
1951.10Seehdefer cgstart
1961.10Seehdefer di-db@
1971.10Seehdefer di-ib@
1981.10Seehdefer ib-ib@
1991.10Seehdefer fs-bsize
2001.10Seehdefer fsbtodb
2011.10Seehdefer blksize
2021.10Seehdefer lblkno
2031.10Seehdefer blkoff
2041.10Seehdefer read-inode
2051.10Seeh\ LFS ifile
2061.10Seehdefer /ifile
2071.10Seehdefer if_daddr
2081.10Seeh
2091.10Seeh\
2101.10Seeh\ FFS Cylinder group macros
2111.10Seeh\
2121.10Seeh
2131.10Seeh: cgdmin ( cg fs -- d-1st-data-block )	dup fs_dblkno l@ l>d 2swap cgstart d+ ;
2141.10Seeh: cgimin ( cg fs -- d-inode-block )	dup fs_iblkno l@ l>d 2swap cgstart d+ ;
2151.10Seeh: cgsblock ( cg fs -- d-super-block )	dup fs_sblkno l@ l>d 2swap cgstart d+ ;
2161.10Seeh: cgstod ( cg fs -- d-cg-block )	dup fs_cblkno l@ l>d 2swap cgstart d+ ;
2171.10Seeh
2181.10Seeh\
2191.10Seeh\ FFS Block and frag position macros
2201.10Seeh\
2211.10Seeh
2221.10Seeh: ffs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi )	fs_qbmask d@ d-and ;
2231.10Seeh\ : ffs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi )	fs_qfmask d@ d-and ;
2241.10Seeh\ : ffs-lblktosize ( blk fs -- off.lo off.hi )		0 fs_bshift l@ d<< ;
2251.10Seeh: ffs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi )	fs_bshift l@ d>> ;
2261.10Seeh: ffs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi )	fs_fshift l@ d>> ;
2271.10Seeh: ffs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi )
2281.10Seeh    >r r@ fs_qbmask d@ d+ r> fs_bmask l@ l>d d-and
2291.10Seeh;
2301.10Seeh: ffs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi )
2311.10Seeh    >r r@ fs_qfmask d@ d+ r> fs_fmask l@ l>d d-and
2321.10Seeh;
2331.10Seeh: ffs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi )	fs_fragshift l@ d>> ;
2341.10Seeh: ffs-blkstofrags ( blk fs -- frag )			fs_fragshift l@ << ;
2351.10Seeh\ : ffs-fragnum ( fsb fs -- off )			fs_frag l@ 1- and ;
2361.10Seeh\ : ffs-blknum ( fsb fs -- off )			fs_frag l@ 1- not and ;
2371.10Seeh: ffs-dblksize ( lbn.lo lbn.hi inodep fs -- size )
2381.10Seeh   >r -rot 2dup ndaddr l>d d>		( inop d-lbn >ndaddr? )
2391.10Seeh   -rot 1 0 d+				( inop >ndaddr? d-lbn+1 )
2401.10Seeh   r@ fs_bshift l@ d<<			( inop >ndaddr? d-lbn+1<<bshift )
2411.10Seeh   2swap >r di-size d@			( d-lbn+1<<bshift d-size )
2421.10Seeh   2swap 2over d< r> or  if		( d-size )
2431.10Seeh	2drop r> fs-bsize l@ exit
2441.10Seeh    then
2451.10Seeh    r@ ffs-blkoff			( size.lo size.hi )
2461.10Seeh    r> ffs-fragroundup d>l		( size )
2471.10Seeh;
2481.10Seeh
2491.10Seeh: ino-to-cg ( ino fs -- cg )		fs_ipg l@ / ;
2501.10Seeh: ino-to-fsbo ( ino fs -- fsb0 )	fs_inopb l@ mod ;
2511.10Seeh: ino-to-fsba ( ino fs -- ba.lo ba.hi )	\ Need to remove the stupid stack diags someday
2521.10Seeh   2dup 				( ino fs ino fs )
2531.10Seeh   ino-to-cg				( ino fs cg )
2541.10Seeh   over					( ino fs cg fs )
2551.10Seeh   cgimin				( ino fs inode-blk.lo inode-blk.hi )
2561.10Seeh   2swap				( d-inode-blk ino fs )
2571.10Seeh   tuck 				( d-inode-blk fs ino fs )
2581.10Seeh   fs_ipg l@ 				( d-inode-blk fs ino ipg )
2591.10Seeh   mod					( d-inode-blk fs mod )
2601.10Seeh   swap					( d-inode-blk mod fs )
2611.10Seeh   dup 					( d-inode-blk mod fs fs )
2621.10Seeh   fs_inopb l@ 				( d-inode-blk mod fs inopb )
2631.10Seeh   rot 					( d-inode-blk fs inopb mod )
2641.10Seeh   swap					( d-inode-blk fs mod inopb )
2651.10Seeh   /					( d-inode-blk fs div )
2661.10Seeh   swap					( d-inode-blk div fs )
2671.10Seeh   ffs-blkstofrags			( d-inode-blk frag )
2681.10Seeh   0 d+
2691.10Seeh;
2701.10Seeh: ffs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi )
2711.10Seeh    fs_fsbtodb l@ d<<
2721.10Seeh;
2731.10Seeh
2741.10Seeh
2751.10Seeh\
2761.10Seeh\ LFS suff
2771.10Seeh\
2781.10Seeh: lfs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_bmask d@ d-and ;
2791.10Seeh\ : lfs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_ffmask d@ d-and ;
2801.10Seeh\ : lfs-lblktosize ( blk fs -- off.lo off.hi )		0 lfs_bshift l@ d<< ;
2811.10Seeh: lfs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_bshift l@ d>> ;
2821.10Seeh: lfs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_ffshift l@ d>> ;
2831.10Seeh: lfs-roundup ( pos.lo pos.hi mask.lo mask.hi )
2841.10Seeh   2swap 2over d+ 2swap			( d-pos* d-mask )
2851.10Seeh   invert swap invert swap d-and
2861.10Seeh;
2871.10Seeh: lfs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_bmask d@ lfs-roundup ;
2881.10Seeh: lfs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_ffmask d@ lfs-roundup ;
2891.10Seeh: lfs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_fbshift l@ d>> ;
2901.10Seeh: lfs-dblksize ( lbn.lo lbn.hi inodep fs -- size )
2911.10Seeh   >r -rot 2dup ndaddr l>d d>		( inop d-lbn >ndaddr? )
2921.10Seeh   -rot 1 0 d+				( inop >ndaddr? d-lbn+1 )
2931.10Seeh   r@ fs_bshift l@ d<<			( inop >ndaddr? d-lbn+1<<bshift )
2941.10Seeh   2swap >r di-size d@			( d-lbn+1<<bshift d-size )
2951.10Seeh   2swap 2over d< r> or  if		( d-size )
2961.10Seeh      2drop r> fs-bsize l@ exit
2971.1Smrg   then
2981.10Seeh   r@ lfs-blkoff			( size.lo size.hi )
2991.10Seeh   r> lfs-fragroundup d>l		( size )
3001.10Seeh;
3011.10Seeh: lfs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi )
3021.10Seeh    lfs_fsbtodb l@ d<<
3031.1Smrg;
3041.1Smrg
3051.10Seeh\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3061.1Smrg\
3071.10Seeh\ The rest of the multi-filesystem stuff
3081.1Smrg\
3091.10Seeh\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3101.1Smrg
3111.10Seeh\
3121.10Seeh\ FFS v1
3131.10Seeh\
3141.10Seeh: di-db-v1@ ( indx dinode -- db.lo db.hi )	di1_db swap la+ l@ l>d ;
3151.10Seeh: di-ib-v1@ ( indx dinode -- db.lo db.hi )	di1_ib swap la+ l@ l>d ;
3161.10Seeh: ib-ib-v1@ ( indx iblk -- db.lo db.hi )	swap la+ l@ l>d ;
3171.10Seeh
3181.10Seeh: cgbase ( cg fs -- daddr.lo daddr.hi ) fs_fpg l@ um* ;
3191.10Seeh: cgstart-ufs1 ( cg fs -- cgstart ) 
3201.10Seeh    2dup fs_old_cgmask l@ invert and		( cg fs stuff )
3211.10Seeh    over fs_old_cgoffset l@ um*			( cg fs off.lo off.hi )
3221.10Seeh    2swap cgbase d+				( off.lo off.hi )
3231.1Smrg;
3241.1Smrg
3251.1Smrg\
3261.10Seeh\ FFS v2
3271.1Smrg\
3281.1Smrg
3291.10Seeh: di-db-v2@ ( indx dinode -- db.lo db.hi )	di2_db swap 2* la+ d@ ;
3301.10Seeh: di-ib-v2@ ( indx dinode -- db.lo db.hi )	di2_ib swap 2* la+ d@ ;
3311.10Seeh: ib-ib-v2@ ( indx iblk -- db.lo db.hi )	2* la+ d@ ;
3321.1Smrg
3331.10Seeh\
3341.10Seeh\ LFS v1
3351.10Seeh\
3361.1Smrg
3371.1Smrg
3381.1Smrg\
3391.1Smrg\ File stuff
3401.1Smrg\
3411.1Smrg
3421.1Smrgniaddr /w* constant narraysize
3431.1Smrg
3441.16Sandvar\ Assume UFS2 dinodes are always bigger than UFS1
3451.10Seehufs2_dinode_SIZEOF buffer: cur-inode
3461.13Seeh0 value indir-block
3471.10Seehcreate indir-addr -1 , -1 ,
3481.1Smrg
3491.1Smrg\
3501.1Smrg\ Translate a fileblock to a disk block
3511.1Smrg\
3521.10Seeh\ We don't do triple indirect blocks.
3531.1Smrg\
3541.1Smrg
3551.10Seeh\ Get the disk address from a single indirect block
3561.10Seeh: ib@ ( indx indir.lo indir.hi -- db.lo db.hi )
3571.10Seeh    2dup indir-addr d@ d<>  if		( indx indir.hi indir.lo )
3581.10Seeh	indir-addr d!			( indx )
3591.10Seeh	indir-block 			( indx indir-block )
3601.10Seeh	sb-buf fs-bsize l@		( indx indir-block fs fs-bsize )
3611.10Seeh	indir-addr d@ sb-buf		( indx indir-block fs-bsize indiraddr fs )
3621.10Seeh	fsbtodb 			( indx indir-block fs-bsize db.lo db.hi )
3631.10Seeh	strategy 0			( indx nread 0 ) \ Really should check return value
3641.10Seeh    then
3651.10Seeh    2drop				( indx )
3661.10Seeh    indir-block ib-ib@
3671.10Seeh;
3681.10Seeh
3691.10Seeh
3701.10Seeh: block-map ( fileblock -- diskblock.lo diskblock.hi )
3711.10Seeh    \ Direct block?
3721.10Seeh    dup ndaddr <  if			( fileblock )
3731.10Seeh	cur-inode di-db@ exit		( diskblock.lo diskblock.hi )
3741.10Seeh    then 				( fileblock )
3751.10Seeh    ndaddr -				( fileblock' )
3761.10Seeh    \ Now we need to check the indirect block
3771.10Seeh    dup sb-buf fs_nindir l@ <  if	( fileblock' )
3781.10Seeh	0 cur-inode di-ib@		( fileblock' indir.lo indir.hi )
3791.10Seeh	ib@ exit			( db.lo db.hi )
3801.1Smrg   then
3811.1Smrg   dup sb-buf fs_nindir -		( fileblock'' )
3821.1Smrg   \ Now try 2nd level indirect block -- just read twice 
3831.10Seeh   dup sb-buf fs_nindir l@ dup * >= if	( fileblock'' )
3841.10Seeh       ." block-map: exceeded max file size" cr
3851.10Seeh       abort
3861.1Smrg   then
3871.10Seeh       
3881.10Seeh   1 cur-inode di-ib@		( fileblock'' ib.lo ib.hi )
3891.10Seeh   
3901.10Seeh   \ Get 1st indirect block and find the 2nd indirect block
3911.10Seeh   rot dup sb-buf fs_nindir u/mod	( ib2.lo ib2.hi indx2 indx1 )
3921.10Seeh   2swap ib@			( indx2 ib2.lo ib2.hi )
3931.10Seeh   
3941.10Seeh   \ Get 2nd indirect block and find our diskblock
3951.10Seeh   ib@				( db.lo db.hi )
3961.1Smrg;
3971.1Smrg
3981.1Smrg\
3991.1Smrg\ Read file into internal buffer and return pointer and len
4001.1Smrg\
4011.1Smrg
4021.4Seeh0 value cur-block			\ allocated dynamically in ufs-open
4031.10Seeh0 value cur-blocksize			\ size allocated  to  cur-block
4041.10Seehcreate cur-blockno -1 l, -1 l,		\ Current disk block.
4051.10Seeh-1 value file-blockno			\ Current file block no.
4061.10Seeh0 value file-offset			\ Current file offset, max 4GB.
4071.10Seeh
4081.10Seeh: buf-read-file ( fs -- buf len )
4091.10Seeh    >r file-offset			( seek )
4101.10Seeh    dup l>d r@ lblkno drop		( seek blk )
4111.10Seeh    dup l>d cur-inode r@ blksize	( seek blk blksize )
4121.10Seeh    over file-blockno <> if		( seek blk blksize )
4131.10Seeh	over  to  file-blockno
4141.10Seeh	swap block-map			( seek blksize fsblk.lo fsblk.hi )
4151.10Seeh	2dup or 0=  if			( seek blksize fsblk.lo fsblk.hi )
4161.10Seeh	    \ Clear out curblock  XXX Why? Idunno.
4171.10Seeh	    2drop dup
4181.10Seeh	    cur-block swap erase	( seek blksize )
4191.10Seeh	    boot-debug?  if ." buf-read-file reading block 0" cr then
4201.10Seeh	    -1 l>d			\ Invalid disk block
4211.10Seeh	else
4221.10Seeh	    \ Call strategy to load the correct block.
4231.10Seeh	    r@ fsbtodb			( seek blksize dblk.lo dblk.hi )
4241.10Seeh	    rot >r cur-block r@ 2over	( seek addr size db.lo db.hi )
4251.10Seeh	    strategy r@	<>  if  ." buf-read-file: short read." cr abort  then
4261.10Seeh	    r> -rot			( seek size db.lo db.hi )
4271.10Seeh	then
4281.10Seeh	\ Save the new current disk block number
4291.10Seeh	cur-blockno d!			( seek size )
4301.10Seeh   else					
4311.10Seeh      nip				( seek size )
4321.10Seeh   then
4331.10Seeh   \ Now figure out how much we have in the buffer.
4341.10Seeh   swap l>d r> blkoff			( size off.lo off.hi )
4351.10Seeh   d>l cur-block over +			( size off buf )
4361.10Seeh   -rot -				( buf siz )
4371.1Smrg;
4381.1Smrg
4391.1Smrg\
4401.1Smrg\ Read inode into cur-inode -- uses cur-block
4411.1Smrg\ 
4421.1Smrg
4431.10Seeh: read-inode-ffs ( inode fs -- )
4441.10Seeh    twiddle
4451.10Seeh
4461.10Seeh    >r dup r@ ino-to-fsba		( ino fsblk.lo fsblck.hi )
4471.10Seeh    r@ fsbtodb				( ino dblk.lo dblk.hi )
4481.10Seeh    2dup cur-blockno d@ d<>  if		( ino dblk.lo dblk.hi )
4491.10Seeh	\ We need  to  read the block
4501.10Seeh	cur-block r@ fs-bsize l@	( ino dblk.lo dblk.hi addr size )
4511.10Seeh	>r r@ 2over strategy r> <> if	( ino dblk.lo dblk.hi )
4521.10Seeh	    ." read-inode - residual" cr abort
4531.10Seeh	then
4541.10Seeh	2dup cur-blockno d!		( ino dblk.lo dblk.hi )
4551.10Seeh    then 2drop				( ino )
4561.1Smrg
4571.10Seeh    r> ino-to-fsbo /dino *		( off )
4581.10Seeh    cur-block + cur-inode /dino move	( )
4591.10Seeh;
4601.10Seeh
4611.10Seeh: find-inode-sector ( ino fs -- d-dblkno true | false )
4621.10Seeh   >r r@ lfs_ifile l@ r@  read-inode	( ino )
4631.10Seeh
4641.10Seeh   r@ lfs_ifpb l@ u/mod			( rem q )
4651.10Seeh
4661.10Seeh   r@ lfs_cleansz l@ +
4671.10Seeh   r@ lfs_segtabsz l@ +			( rem blkno )
4681.1Smrg
4691.10Seeh   r@ fs-bsize l@ um* rot /ifile um* d+	( dseekp )
4701.1Smrg
4711.10Seeh   drop  to  file-offset r@ buf-read-file	( buf len )
4721.10Seeh
4731.10Seeh   /ifile <  if  r> 2drop false exit  then	( buf )
4741.10Seeh
4751.10Seeh   if_daddr l@ l>d r> fsbtodb		( daddr )
4761.10Seeh   2dup lfs_unused_daddr l>d d=  if  2drop false  then
4771.10Seeh   true
4781.10Seeh;
4791.10Seeh
4801.10Seeh: read-inode-lfs ( inode fs -- )
4811.10Seeh   twiddle
4821.10Seeh
4831.10Seeh   >r dup r@ lfs_ifile l@ =  if		( ino  r: fs )
4841.10Seeh      r@ lfs_idaddr l@ l>d		( ino d-idaddr )
4851.10Seeh      r@ fsbtodb			( ino d-db )
4861.10Seeh   else
4871.10Seeh      dup r@ find-inode-sector 0= abort" Could not find inode sector!"
4881.10Seeh   then					( ino d-db )
4891.10Seeh   
4901.10Seeh    2dup cur-blockno d@ d<>  if		( ino dblk.lo dblk.hi )
4911.10Seeh	\ We need to read the block
4921.10Seeh	cur-block r@ fs-bsize l@	( ino dblk.lo dblk.hi addr size )
4931.10Seeh	>r r@ 2over strategy r> <> if	( ino dblk.lo dblk.hi )
4941.10Seeh	    ." read-inode - residual" cr abort
4951.10Seeh	then
4961.10Seeh	2dup cur-blockno d!		( ino dblk.lo dblk.hi )
4971.10Seeh    then  2drop				( ino )
4981.10Seeh
4991.10Seeh    r@ lfs_inopb l@			( ino cnt )
5001.10Seeh    swap cur-block  begin		( cnt ino p )
5011.10Seeh       tuck di_inumber l@ over <>	( cnt p ino !found? )
5021.10Seeh    while				( cnt p ino )
5031.10Seeh	  rot 1- ?dup 0=  abort" Could not find inode!"
5041.10Seeh	  rot /dino + swap -rot		( cnt ino p )
5051.10Seeh    repeat  swap			( cnt ino p )
5061.10Seeh
5071.10Seeh    cur-inode /dino move		( cnt ino )
5081.10Seeh	  
5091.10Seeh    r> 3drop
5101.1Smrg;
5111.1Smrg
5121.1Smrg\ Identify inode type
5131.1Smrg
5141.10Seeh: is-dir? ( ufs1_dinode -- is-dir? )		di-mode w@ ifmt and ifdir = ;
5151.10Seeh: is-symlink? ( ufs1_dinode -- is-symlink? )	di-mode w@ ifmt and iflnk = ;
5161.10Seeh
5171.10Seeh\
5181.10Seeh\ Multi-FS initialiation.
5191.10Seeh\
5201.10Seeh\ It's way down here so all the fs-specific routines have already been defined.
5211.10Seeh\
5221.10Seeh
5231.10Seeh: init-ffs-common ( -- )
5241.10Seeh   ' fs_SIZEOF  to  fs-size 
5251.10Seeh   ' fs_bsize  to  fs-bsize
5261.10Seeh   ' ffs-dblksize  to  blksize
5271.10Seeh   ' read-inode-ffs  to  read-inode
5281.10Seeh   ' ffs-fsbtodb  to  fsbtodb
5291.10Seeh   ' ffs-lblkno  to  lblkno
5301.10Seeh   ' ffs-blkoff  to   blkoff
5311.10Seeh;   
5321.10Seeh
5331.10Seeh
5341.10Seeh: ffs-oldcompat ( -- )
5351.10Seeh   \ Make sure old ffs values in sb-buf are sane
5361.10Seeh   sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l!
5371.10Seeh   sb-buf fs_old_interleave dup l@ 1 max swap l!
5381.10Seeh   sb-buf fs_old_postblformat l@ fs_42postblfmt =  if
5391.10Seeh      8 sb-buf fs_old_nrpos l!
5401.10Seeh   then
5411.10Seeh   sb-buf fs_old_inodefmt l@ fs_44inodefmt <  if
5421.10Seeh      sb-buf fs-bsize l@ 
5431.10Seeh      dup ndaddr um* 1 d- sb-buf fs_maxfilesize d!
5441.10Seeh      niaddr 0  ?do
5451.10Seeh	 sb-buf fs_nindir l@ * dup	( sizebp sizebp )
5461.10Seeh	 sb-buf fs_maxfilesize dup d@ ( sizebp sizebp *mxfs mxfs.lo mxfs.hi )
5471.10Seeh	 2over drop l>d d+ 2swap d!	( sizebp )
5481.10Seeh      loop  drop 			( )
5491.10Seeh      sb-buf dup fs_bmask l@ invert l>d rot fs_qbmask d!
5501.10Seeh      sb-buf dup fs_fmask l@ invert l>d rot fs_qfmask d!
5511.10Seeh   then
5521.10Seeh;
5531.10Seeh
5541.10Seeh
5551.10Seeh: init-ffs-v1 ( -- )
5561.12Seeh   boot-debug?  if  ." FFS v1" cr  then
5571.10Seeh   init-ffs-common
5581.10Seeh   ' di1_size  to  di-size
5591.10Seeh   ' di1_mode  to  di-mode
5601.10Seeh   ' ufs1_dinode_SIZEOF  to  /dino
5611.10Seeh   ' cgstart-ufs1  to  cgstart
5621.10Seeh   ' di-db-v1@  to  di-db@
5631.10Seeh   ' di-ib-v1@  to  di-ib@
5641.10Seeh   ' ib-ib-v1@  to  ib-ib@
5651.10Seeh   ffs-oldcompat
5661.10Seeh;
5671.10Seeh
5681.10Seeh: init-ffs-v2 ( -- )
5691.12Seeh   boot-debug?  if  ." FFS v2" cr  then
5701.10Seeh   init-ffs-common
5711.10Seeh   ' di2_size  to  di-size
5721.10Seeh   ' di2_mode  to  di-mode
5731.10Seeh   ' ufs2_dinode_SIZEOF  to  /dino
5741.10Seeh   ' cgbase  to  cgstart
5751.10Seeh   ' di-db-v2@  to  di-db@
5761.10Seeh   ' di-ib-v2@  to  di-ib@
5771.10Seeh   ' ib-ib-v2@  to  ib-ib@
5781.10Seeh;
5791.10Seeh
5801.10Seeh: init-lfs-common ( -- )
5811.10Seeh   ' dlfs_SIZEOF  to  fs-size 
5821.10Seeh   ' di1_size  to  di-size
5831.10Seeh   ' di1_mode  to  di-mode
5841.15Sdholland   ' lfs32_dinode_SIZEOF  to  /dino
5851.10Seeh   ' cgbase  to  cgstart
5861.10Seeh   ' di-db-v1@  to  di-db@
5871.10Seeh   ' di-ib-v1@  to  di-ib@
5881.10Seeh   ' ib-ib-v1@  to  ib-ib@
5891.10Seeh   ' lfs-dblksize  to  blksize
5901.10Seeh   ' read-inode-lfs  to  read-inode
5911.10Seeh   ' lfs-fsbtodb  to  fsbtodb
5921.10Seeh   ' lfs-lblkno  to  lblkno
5931.10Seeh   ' lfs-blkoff  to  blkoff
5941.10Seeh;
5951.10Seeh
5961.10Seeh: init-lfs-v1 ( -- )
5971.12Seeh   boot-debug?  if  ." LFS v1" cr  then
5981.10Seeh   init-lfs-common
5991.10Seeh   ' lfs_ibsize  to  fs-bsize
6001.10Seeh   ' ifile_v1_SIZEOF  to  /ifile
6011.10Seeh   ' if1_daddr  to  if_daddr
6021.10Seeh;   
6031.10Seeh
6041.10Seeh: init-lfs-v2 ( -- )
6051.12Seeh   boot-debug?  if  ." LFS v2" cr  then
6061.10Seeh   init-lfs-common
6071.10Seeh   ' lfs_bsize  to  fs-bsize
6081.14Sjdc   ' ifile32_SIZEOF  to  /ifile
6091.10Seeh   ' if2_daddr  to  if_daddr
6101.10Seeh;   
6111.10Seeh
6121.10Seeh
6131.10Seeh: fs-magic? ( sb -- is-ufs? )
6141.10Seeh   \ The LFS magic is the first word in the superblock
6151.10Seeh   dup lfs_magic l@ lfs_magic_value =  if
6161.10Seeh      dup lfs_version l@  case		( sb sel )
6171.10Seeh	 1  of  init-lfs-v1 drop true exit  endof
6181.10Seeh	 2  of  init-lfs-v2 drop true exit  endof
6191.10Seeh	 ." Invalid LFS version."  \ Try FFS.
6201.10Seeh      endcase
6211.10Seeh   then					( sb )
6221.10Seeh   \ The FFS magic is at the end of the superblock
6231.11Seeh   \ XXX we should check to make sure this is not an alternate SB.
6241.10Seeh   fs_magic l@  case
6251.10Seeh      fs1_magic_value  of  init-ffs-v1 true  endof
6261.10Seeh      fs2_magic_value  of  init-ffs-v2 true  endof
6271.17Schs      fs2ea_magic_value  of  init-ffs-v2 true  endof
6281.10Seeh      false swap	\ Return false
6291.10Seeh   endcase
6301.10Seeh;
6311.1Smrg
6321.1Smrg
6331.1Smrg
6341.1Smrg\
6351.1Smrg\ Hunt for directory entry:
6361.1Smrg\ 
6371.1Smrg\ repeat
6381.1Smrg\    load a buffer
6391.1Smrg\    while entries do
6401.1Smrg\       if entry == name return
6411.1Smrg\       next entry
6421.1Smrg\ until no buffers
6431.1Smrg\
6441.1Smrg
6451.10Seeh: search-dir-block ( str len buf len -- ino | 0 )
6461.10Seeh    2dup + nip				( str len buf bufend )
6471.10Seeh    swap 2swap rot			( bufend str len direct )
6481.10Seeh    begin  dup 4 pick <  while		( bufend str len direct )
6491.10Seeh	    dup d_ino l@ 0<>  if	( bufend str len direct )
6501.10Seeh		boot-debug?  if
6511.10Seeh		    \ Print the current file name
6521.10Seeh		    dup dup d_name swap d_namlen c@ type cr
6531.10Seeh		then
6541.10Seeh		2dup d_namlen c@ =  if	( bufend str len direct )
6551.10Seeh		    dup d_name 2over	( bufend str len direct dname str len )
6561.10Seeh		    comp 0= if		( bufend str len direct )
6571.10Seeh			\ Found it -- return inode
6581.10Seeh			d_ino l@ nip nip nip	( dino )
6591.10Seeh			boot-debug?  if  ." Found it" cr  then 
6601.10Seeh			exit 		( dino )
6611.10Seeh		    then
6621.10Seeh		then			( bufend str len direct )
6631.10Seeh	    then			( bufend str len direct )
6641.10Seeh	    dup d_reclen w@ +		( bufend str len nextdirect )
6651.10Seeh    repeat
6661.10Seeh    2drop 2drop 0
6671.10Seeh;
6681.10Seeh    
6691.10Seeh
6701.10Seeh: search-directory ( str len -- ino | 0 )
6711.10Seeh    0  to  file-offset
6721.10Seeh    begin
6731.10Seeh	file-offset cur-inode di-size d@ drop <
6741.10Seeh    while				( str len )
6751.10Seeh	    \ Read a directory block
6761.10Seeh	    sb-buf buf-read-file	( str len buf len )
6771.10Seeh	    dup 0=  if  ." search-directory: buf-read-file zero len" cr abort  then
6781.10Seeh	    dup file-offset +  to  file-offset	( str len buf len )
6791.10Seeh
6801.10Seeh	    2over 2swap search-dir-block ?dup  if
6811.10Seeh		\ Found it
6821.10Seeh		nip nip exit
6831.10Seeh	    then			( str len )
6841.10Seeh    repeat
6851.10Seeh    2drop 2drop 0			( 0 )
6861.1Smrg;
6871.1Smrg
6881.3Seeh: read-super ( sector -- )
6891.10Seeh   0 " seek" boot-ihandle $call-method -1 =  if 
6901.10Seeh      ." Seek failed" cr abort
6911.1Smrg   then
6921.1Smrg   sb-buf sbsize " read" boot-ihandle $call-method
6931.1Smrg   dup sbsize <>  if
6941.1Smrg      ." Read of superblock failed" cr
6951.1Smrg      ." requested" space sbsize .
6961.1Smrg      ." actual" space . cr
6971.1Smrg      abort
6981.1Smrg   else 
6991.1Smrg      drop
7001.1Smrg   then
7011.3Seeh;
7021.3Seeh
7031.11Seeh: check-supers ( -- found? )
7041.11Seeh   \ Superblocks used to be 8KB into the partition, but ffsv2 changed that.
7051.11Seeh   \ See comments in src/sys/ufs/ffs/fs.h
7061.18Sandvar   \ Put a list of offsets to check on the stack, ending with -1
7071.11Seeh   -1
7081.11Seeh   0
7091.11Seeh   d# 128 KB
7101.11Seeh   d# 64 KB
7111.11Seeh   8 KB
7121.11Seeh   
7131.11Seeh   begin  dup -1 <>  while			( -1 .. off )
7141.11Seeh	 raid-offset dev_bsize * + read-super	( -1 .. )
7151.11Seeh	 sb-buf fs-magic?  if			( -1 .. )
7161.11Seeh	    begin  -1 =  until	 \ Clean out extra stuff from stack
7171.11Seeh	    true exit
7181.11Seeh	 then
7191.11Seeh   repeat
7201.11Seeh   drop false
7211.11Seeh;
7221.11Seeh
7231.10Seeh: ufs-open ( bootpath len -- )
7241.3Seeh   boot-ihandle -1 =  if
7251.10Seeh      2dup + 0 swap c!	\ Nul terminate.
7261.10Seeh      over cif-open dup 0=  if 	( boot-path len ihandle? )
7271.10Seeh	 ." Could not open device" space type cr 
7281.10Seeh	 abort
7291.3Seeh      then 				( boot-path len ihandle )
7301.10Seeh      to  boot-ihandle			\ Save ihandle to boot device
7311.10Seeh   then
7321.10Seeh   2drop
7331.10Seeh   
7341.10Seeh   boot-debug?  if ." Try a RAID superblock read" cr  then
7351.11Seeh   \ RAIDFRAME skips 64 sectors.
7361.11Seeh   d# 64  to  raid-offset
7371.11Seeh   check-supers invert  if
7381.10Seeh      boot-debug?  if ." Try a normal superblock read" cr  then
7391.10Seeh      0  to  raid-offset 
7401.11Seeh      check-supers 0=  abort" Invalid superblock magic"
7411.1Smrg   then
7421.10Seeh   sb-buf fs-bsize l@ dup maxbsize >  if
7431.1Smrg      ." Superblock bsize" space . ." too large" cr
7441.1Smrg      abort
7451.1Smrg   then 
7461.10Seeh   dup fs-size <  if
7471.1Smrg      ." Superblock bsize < size of superblock" cr
7481.1Smrg      abort
7491.1Smrg   then
7501.10Seeh   dup  to  cur-blocksize alloc-mem  to  cur-block    \ Allocate cur-block
7511.13Seeh   cur-blocksize alloc-mem  to  indir-block
7521.10Seeh   boot-debug?  if  ." ufs-open complete" cr  then
7531.1Smrg;
7541.1Smrg
7551.1Smrg: ufs-close ( -- ) 
7561.10Seeh    boot-ihandle dup -1 <>  if
7571.10Seeh	cif-close -1  to  boot-ihandle 
7581.10Seeh    then
7591.10Seeh    cur-block 0<> if
7601.13Seeh       cur-block cur-blocksize free-mem
7611.13Seeh       indir-block cur-blocksize free-mem
7621.10Seeh    then
7631.1Smrg;
7641.1Smrg
7651.1Smrg: boot-path ( -- boot-path )
7661.10Seeh    " bootpath" chosen-phandle get-package-property  if
7671.10Seeh	." Could not find bootpath in /chosen" cr
7681.10Seeh	abort
7691.10Seeh    else
7701.10Seeh	decode-string 2swap 2drop
7711.10Seeh    then
7721.1Smrg;
7731.1Smrg
7741.1Smrg: boot-args ( -- boot-args )
7751.10Seeh    " bootargs" chosen-phandle get-package-property  if
7761.10Seeh	." Could not find bootargs in /chosen" cr
7771.10Seeh	abort
7781.10Seeh    else
7791.10Seeh	decode-string 2swap 2drop
7801.10Seeh    then
7811.1Smrg;
7821.1Smrg
7831.1Smrg2000 buffer: boot-path-str
7841.1Smrg2000 buffer: boot-path-tmp
7851.1Smrg
7861.1Smrg: split-path ( path len -- right len left len )
7871.1Smrg\ Split a string at the `/'
7881.10Seeh    begin
7891.10Seeh	dup -rot				( oldlen right len left )
7901.10Seeh	ascii / left-parse-string		( oldlen right len left len )
7911.10Seeh	dup 0<>  if  4 roll drop exit  then
7921.10Seeh	2drop					( oldlen right len )
7931.10Seeh	rot over =				( right len diff )
7941.10Seeh    until
7951.1Smrg;
7961.1Smrg
7971.1Smrg: find-file ( load-file len -- )
7981.10Seeh    rootino dup sb-buf read-inode	( load-file len pino )
7991.10Seeh    -rot				( pino load-file len )
8001.10Seeh    \
8011.10Seeh    \ For each path component
8021.10Seeh    \ 
8031.10Seeh    begin  split-path dup 0<>  while	( pino right len left len )
8041.10Seeh	    cur-inode is-dir? not  if  ." Inode not directory" cr abort  then
8051.10Seeh	    boot-debug?  if  ." Looking for" space 2dup type space ." in directory..." cr  then
8061.10Seeh	    search-directory		( pino right len ino|false )
8071.10Seeh	    dup 0=  abort" Bad path" 	( pino right len cino )
8081.10Seeh	    sb-buf read-inode			( pino right len )
8091.10Seeh	    cur-inode is-symlink?  if		\ Symlink -- follow the damn thing
8101.10Seeh		\ Save path in boot-path-tmp
8111.10Seeh		boot-path-tmp strmov		( pino new-right len )
8121.10Seeh		
8131.10Seeh		\ Now deal with symlink  XXX drop high word of linklen
8141.10Seeh		cur-inode di-size d@ drop	( pino right len linklen.lo )
8151.10Seeh		dup sb-buf fs_maxsymlinklen l@	( pino right len linklen linklen maxlinklen )
8161.10Seeh		<  if				\ Now join the link to the path
8171.10Seeh		    0 cur-inode di-db@ drop	( pino right len linklen linkp )
8181.10Seeh		    swap boot-path-str strmov	( pino right len new-linkp linklen )
8191.10Seeh		else				\ Read file for symlink -- Ugh
8201.10Seeh		    \ Read link into boot-path-str
8211.10Seeh		    boot-path-str dup sb-buf fs-bsize l@
8221.10Seeh		    0 block-map			( pino right len linklen boot-path-str bsize blockno.lo blockno.hi )
8231.10Seeh		    strategy drop swap		( pino right len boot-path-str linklen )
8241.10Seeh		then 				( pino right len linkp linklen )
8251.10Seeh		\ Concatenate the two paths
8261.10Seeh		strcat				( pino new-right newlen )
8271.10Seeh		swap dup c@ ascii / =  if	\ go to root inode?
8281.10Seeh		    rot drop rootino -rot	( rino len right )
8291.10Seeh		then
8301.10Seeh		rot dup sb-buf read-inode	( len right pino )
8311.10Seeh		-rot swap			( pino right len )
8321.10Seeh	    then				( pino right len )
8331.10Seeh    repeat
8341.10Seeh    2drop drop
8351.10Seeh;
8361.10Seeh
8371.10Seeh: .read-file-msg ( addr xxx siz -- addr xxx siz )
8381.10Seeh    boot-debug? if
8391.10Seeh	." Copying " dup . ." bytes to " 3 pick . cr
8401.10Seeh    then
8411.10Seeh;
8421.10Seeh       
8431.10Seeh: read-file ( addr size -- )
8441.10Seeh    noop \ In case we need to debug this
8451.10Seeh    \ Read x bytes from a file to buffer
8461.10Seeh    begin  dup 0>  while
8471.10Seeh	    file-offset cur-inode di-size d@ drop >  if
8481.10Seeh		." read-file EOF exceeded" cr abort
8491.10Seeh	    then
8501.10Seeh	    sb-buf buf-read-file		( addr size buf len )
8511.10Seeh	    
8521.10Seeh	    .read-file-msg
8531.10Seeh	    
8541.10Seeh	    \ Copy len bytes to addr  XXX min ( len, size ) ?
8551.10Seeh	    2over drop 3dup swap move drop	( addr size buf len )
8561.10Seeh	    
8571.10Seeh	    dup file-offset +  to  file-offset	( addr size buf len )
8581.10Seeh	    
8591.10Seeh	    nip tuck - -rot + swap		( addr' size' )
8601.10Seeh    repeat
8611.10Seeh    2drop
8621.1Smrg;
8631.1Smrg
8641.10Seeh" load-base " evaluate constant loader-base
8651.1Smrg
8661.1Smrg: load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
8671.1Smrg   ." Loading file" space 2over type cr ." from device" space 2dup type cr
8681.1Smrg;
8691.1Smrg
8701.1Smrg: load-file ( load-file len boot-path len -- load-base )
8711.10Seeh   boot-debug?  if  load-file-signon  then
8721.10Seeh   
8731.10Seeh   ufs-open 				( load-file len )
8741.10Seeh   find-file				( )
8751.1Smrg
8761.10Seeh    \
8771.10Seeh    \ Now we've found the file we should read it in in one big hunk
8781.10Seeh    \
8791.10Seeh    
8801.10Seeh    cur-inode di-size d@  if  ." File len >2GB!" cr abort  then
8811.10Seeh\    dup " to file-size " evaluate	( file-len ) \ Wassthis?
8821.10Seeh    boot-debug?  if
8831.10Seeh	." Loading " dup . ."  bytes of file..." cr
8841.10Seeh    then
8851.10Seeh    0  to  file-offset
8861.10Seeh    -1  to  file-blockno
8871.10Seeh    loader-base				( buf-len addr )
8881.10Seeh    tuck swap read-file			( addr )
8891.10Seeh    ufs-close				( addr )
8901.1Smrg;
8911.1Smrg
8921.1Smrg: do-boot ( bootfile -- )
8931.11Seeh   ." NetBSD IEEE 1275 Multi-FS Bootblock" cr
8941.18Sandvar   ." Version $NetBSD: bootblk.fth,v 1.18 2025/02/28 09:07:12 andvar Exp $" cr
8951.11Seeh   boot-path load-file ( -- load-base )
8961.11Seeh   dup 0<>  if  " init-program " evaluate  then
8971.10Seeh; 
8981.1Smrg
8991.1Smrg
9001.10Seehboot-args ascii V strchr 0<> swap drop  if
9011.10Seeh    true  to  boot-debug?
9021.1Smrgthen
9031.1Smrg
9041.10Seehboot-args ascii D strchr 0= swap drop  if
9051.10Seeh    " /ofwboot" do-boot
9061.10Seehthen  exit
9071.1Smrg
9081.1Smrg
909