bootblk.fth revision 1.10
11.10Seeh\ $NetBSD: bootblk.fth,v 1.10 2010/02/13 23:38:17 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.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.1Smrg\ 391.1Smrg\ First some housekeeping: Open /chosen and set up vectors into 401.1Smrg\ client-services 411.1Smrg 421.1Smrg" /chosen" find-package 0= if ." Cannot find /chosen" 0 then 431.1Smrgconstant chosen-phandle 441.1Smrg 451.1Smrg" /openprom/client-services" find-package 0= if 461.1Smrg ." Cannot find client-services" cr abort 471.1Smrgthen constant cif-phandle 481.1Smrg 491.1Smrgdefer cif-claim ( align size virt -- base ) 501.1Smrgdefer cif-release ( size virt -- ) 511.1Smrgdefer cif-open ( cstr -- ihandle|0 ) 521.1Smrgdefer cif-close ( ihandle -- ) 531.1Smrgdefer cif-read ( len adr ihandle -- #read ) 541.1Smrgdefer cif-seek ( low high ihandle -- -1|0|1 ) 551.1Smrg\ defer cif-peer ( phandle -- phandle ) 561.1Smrg\ defer cif-getprop ( len adr cstr phandle -- ) 571.1Smrg 581.10Seeh: find-cif-method ( method len -- xf ) 591.1Smrg cif-phandle find-method drop 601.1Smrg; 611.1Smrg 621.10Seeh" claim" find-cif-method to cif-claim 631.10Seeh" open" find-cif-method to cif-open 641.10Seeh" close" find-cif-method to cif-close 651.10Seeh" read" find-cif-method to cif-read 661.10Seeh" seek" find-cif-method to cif-seek 671.1Smrg 681.1Smrg: twiddle ( -- ) ." ." ; \ Need to do this right. Just spit out periods for now. 691.1Smrg 701.1Smrg\ 711.1Smrg\ Support routines 721.1Smrg\ 731.1Smrg 741.10Seeh\ 64-bit math support 751.10Seeh 761.10Seehhere h# ffff over l! <w@ constant little-endian? 771.10Seeh: ul>d ( l -- d.lo d.hi ) 0 ; 781.10Seeh: l>d ( l -- d.lo d.hi ) dup 0< if -1 else 0 then ; 791.10Seeh: d>l ( d.lo d.hi -- l ) drop ; 801.10Seeh: d@ ( addr -- d.lo d.hi ) dup l@ swap la1+ l@ little-endian? invert if swap then ; 811.10Seeh: d! ( d.lo d.hi addr -- ) 821.10Seeh little-endian? invert if -rot swap rot then tuck la1+ l! l! ; 831.10Seeh: d-and ( d1 d2 -- d1-and-d2 ) rot and -rot and swap ; 841.10Seeh: d*u ( d1 u -- d2 ) tuck um* drop -rot um* rot + ; 851.10Seeh: d<< ( d1 n -- d1<<n ) \ Hope this works 861.10Seeh tuck << ( d.lo n d.hi' ) 871.10Seeh -rot 2dup << ( d.hi' d.lo n d.lo' ) 881.10Seeh -rot d# 32 swap - >> ( d.hi' d.lo' lo.hi ) 891.10Seeh rot + 901.10Seeh; 911.10Seeh: d>> ( d1 n -- d1>>n ) \ Hope this works 921.10Seeh rot over >> -rot ( d.lo' d.hi n ) 931.10Seeh 2dup >> -rot ( d.lo' d.hi' d.hi n ) 941.10Seeh d# 32 swap - << rot + swap 951.10Seeh; 961.10Seeh: d> ( d1 d2 -- d1>d2? ) 971.10Seeh rot swap 2dup = if 981.10Seeh 2drop > exit 991.10Seeh then 1001.10Seeh > nip nip 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? ) d>= invert ; 1091.10Seeh: d= ( d1 d2 -- d1=d2? ) rot = -rot = and ; 1101.10Seeh: d<> ( d1 d2 -- d1<>d2? ) d= invert ; 1111.10Seeh 1121.10Seeh 1131.10Seeh\ String support 1141.10Seeh 1151.1Smrg: strcmp ( s1 l1 s2 l2 -- true:false ) 1161.10Seeh rot tuck <> if 3drop false exit then 1171.1Smrg comp 0= 1181.1Smrg; 1191.1Smrg 1201.1Smrg\ Move string into buffer 1211.1Smrg 1221.1Smrg: strmov ( s1 l1 d -- d l1 ) 1231.1Smrg dup 2over swap -rot ( s1 l1 d s1 d l1 ) 1241.1Smrg move ( s1 l1 d ) 1251.1Smrg rot drop swap 1261.1Smrg; 1271.1Smrg 1281.1Smrg\ Move s1 on the end of s2 and return the result 1291.1Smrg 1301.1Smrg: strcat ( s1 l1 s2 l2 -- d tot ) 1311.1Smrg 2over swap ( s1 l1 s2 l2 l1 s1 ) 1321.1Smrg 2over + rot ( s1 l1 s2 l2 s1 d l1 ) 1331.1Smrg move rot + ( s1 s2 len ) 1341.1Smrg rot drop ( s2 len ) 1351.1Smrg; 1361.1Smrg 1371.1Smrg: strchr ( s1 l1 c -- s2 l2 ) 1381.1Smrg begin 1391.1Smrg dup 2over 0= if ( s1 l1 c c s1 ) 1401.1Smrg 2drop drop exit then 1411.1Smrg c@ = if ( s1 l1 c ) 1421.1Smrg drop exit then 1431.1Smrg -rot /c - swap ca1+ ( c l2 s2 ) 1441.1Smrg swap rot 1451.1Smrg again 1461.1Smrg; 1471.1Smrg 1481.1Smrg 1491.1Smrg: cstr ( ptr -- str len ) 1501.1Smrg dup 1511.1Smrg begin dup c@ 0<> while + repeat 1521.1Smrg over - 1531.1Smrg; 1541.1Smrg 1551.1Smrg\ 1561.10Seeh\ BSD UFS parameters 1571.1Smrg\ 1581.1Smrg 1591.10Seehfload ffs.fth.h 1601.10Seehfload lfs.fth.h 1611.1Smrg 1621.1Smrgsbsize buffer: sb-buf 1631.1Smrg-1 value boot-ihandle 1641.1Smrgdev_bsize value bsize 1651.3Seeh0 value raid-offset \ Offset if it's a raid-frame partition 1661.1Smrg 1671.10Seeh: strategy ( addr size db.lo db.hi -- nread ) 1681.10Seeh raid-offset l>d d+ ( addr size db.lo' db.hi' ) 1691.10Seeh bsize d*u ( addr size sector.lo sector.hi ) 1701.10Seeh " seek" boot-ihandle $call-method -1 = if 1711.10Seeh ." strategy: Seek failed" cr 1721.10Seeh abort 1731.10Seeh then ( addr size ) 1741.10Seeh " read" boot-ihandle $call-method 1751.10Seeh; 1761.10Seeh 1771.10Seeh 1781.10Seeh\ 1791.10Seeh\ Multi-FS support 1801.10Seeh\ 1811.10Seeh\ XXX Maybe the different filesystems should be segregated into separate files 1821.10Seeh\ XXX that are individually fload-ed. 1831.10Seeh\ 1841.10Seeh 1851.10Seehdefer fs-size 1861.10Seehdefer di-size 1871.10Seehdefer di-mode 1881.10Seehdefer /dino 1891.10Seehdefer cgstart 1901.10Seehdefer di-db@ 1911.10Seehdefer di-ib@ 1921.10Seehdefer ib-ib@ 1931.10Seehdefer fs-bsize 1941.10Seehdefer fsbtodb 1951.10Seehdefer blksize 1961.10Seehdefer lblkno 1971.10Seehdefer blkoff 1981.10Seehdefer read-inode 1991.10Seeh\ LFS ifile 2001.10Seehdefer /ifile 2011.10Seehdefer if_daddr 2021.10Seeh 2031.10Seeh\ 2041.10Seeh\ FFS Cylinder group macros 2051.10Seeh\ 2061.10Seeh 2071.10Seeh: cgdmin ( cg fs -- d-1st-data-block ) dup fs_dblkno l@ l>d 2swap cgstart d+ ; 2081.10Seeh: cgimin ( cg fs -- d-inode-block ) dup fs_iblkno l@ l>d 2swap cgstart d+ ; 2091.10Seeh: cgsblock ( cg fs -- d-super-block ) dup fs_sblkno l@ l>d 2swap cgstart d+ ; 2101.10Seeh: cgstod ( cg fs -- d-cg-block ) dup fs_cblkno l@ l>d 2swap cgstart d+ ; 2111.10Seeh 2121.10Seeh\ 2131.10Seeh\ FFS Block and frag position macros 2141.10Seeh\ 2151.10Seeh 2161.10Seeh: ffs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi ) fs_qbmask d@ d-and ; 2171.10Seeh\ : ffs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi ) fs_qfmask d@ d-and ; 2181.10Seeh\ : ffs-lblktosize ( blk fs -- off.lo off.hi ) 0 fs_bshift l@ d<< ; 2191.10Seeh: ffs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi ) fs_bshift l@ d>> ; 2201.10Seeh: ffs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi ) fs_fshift l@ d>> ; 2211.10Seeh: ffs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi ) 2221.10Seeh >r r@ fs_qbmask d@ d+ r> fs_bmask l@ l>d d-and 2231.10Seeh; 2241.10Seeh: ffs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi ) 2251.10Seeh >r r@ fs_qfmask d@ d+ r> fs_fmask l@ l>d d-and 2261.10Seeh; 2271.10Seeh: ffs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi ) fs_fragshift l@ d>> ; 2281.10Seeh: ffs-blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ; 2291.10Seeh\ : ffs-fragnum ( fsb fs -- off ) fs_frag l@ 1- and ; 2301.10Seeh\ : ffs-blknum ( fsb fs -- off ) fs_frag l@ 1- not and ; 2311.10Seeh: ffs-dblksize ( lbn.lo lbn.hi inodep fs -- size ) 2321.10Seeh >r -rot 2dup ndaddr l>d d> ( inop d-lbn >ndaddr? ) 2331.10Seeh -rot 1 0 d+ ( inop >ndaddr? d-lbn+1 ) 2341.10Seeh r@ fs_bshift l@ d<< ( inop >ndaddr? d-lbn+1<<bshift ) 2351.10Seeh 2swap >r di-size d@ ( d-lbn+1<<bshift d-size ) 2361.10Seeh 2swap 2over d< r> or if ( d-size ) 2371.10Seeh 2drop r> fs-bsize l@ exit 2381.10Seeh then 2391.10Seeh r@ ffs-blkoff ( size.lo size.hi ) 2401.10Seeh r> ffs-fragroundup d>l ( size ) 2411.10Seeh; 2421.10Seeh 2431.10Seeh: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ; 2441.10Seeh: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ; 2451.10Seeh: ino-to-fsba ( ino fs -- ba.lo ba.hi ) \ Need to remove the stupid stack diags someday 2461.10Seeh 2dup ( ino fs ino fs ) 2471.10Seeh ino-to-cg ( ino fs cg ) 2481.10Seeh over ( ino fs cg fs ) 2491.10Seeh cgimin ( ino fs inode-blk.lo inode-blk.hi ) 2501.10Seeh 2swap ( d-inode-blk ino fs ) 2511.10Seeh tuck ( d-inode-blk fs ino fs ) 2521.10Seeh fs_ipg l@ ( d-inode-blk fs ino ipg ) 2531.10Seeh mod ( d-inode-blk fs mod ) 2541.10Seeh swap ( d-inode-blk mod fs ) 2551.10Seeh dup ( d-inode-blk mod fs fs ) 2561.10Seeh fs_inopb l@ ( d-inode-blk mod fs inopb ) 2571.10Seeh rot ( d-inode-blk fs inopb mod ) 2581.10Seeh swap ( d-inode-blk fs mod inopb ) 2591.10Seeh / ( d-inode-blk fs div ) 2601.10Seeh swap ( d-inode-blk div fs ) 2611.10Seeh ffs-blkstofrags ( d-inode-blk frag ) 2621.10Seeh 0 d+ 2631.10Seeh; 2641.10Seeh: ffs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi ) 2651.10Seeh fs_fsbtodb l@ d<< 2661.10Seeh; 2671.10Seeh 2681.10Seeh 2691.10Seeh\ 2701.10Seeh\ LFS suff 2711.10Seeh\ 2721.10Seeh: lfs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_bmask d@ d-and ; 2731.10Seeh\ : lfs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_ffmask d@ d-and ; 2741.10Seeh\ : lfs-lblktosize ( blk fs -- off.lo off.hi ) 0 lfs_bshift l@ d<< ; 2751.10Seeh: lfs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_bshift l@ d>> ; 2761.10Seeh: lfs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_ffshift l@ d>> ; 2771.10Seeh: lfs-roundup ( pos.lo pos.hi mask.lo mask.hi ) 2781.10Seeh 2swap 2over d+ 2swap ( d-pos* d-mask ) 2791.10Seeh invert swap invert swap d-and 2801.10Seeh; 2811.10Seeh: lfs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_bmask d@ lfs-roundup ; 2821.10Seeh: lfs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_ffmask d@ lfs-roundup ; 2831.10Seeh: lfs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_fbshift l@ d>> ; 2841.10Seeh: lfs-dblksize ( lbn.lo lbn.hi inodep fs -- size ) 2851.10Seeh >r -rot 2dup ndaddr l>d d> ( inop d-lbn >ndaddr? ) 2861.10Seeh -rot 1 0 d+ ( inop >ndaddr? d-lbn+1 ) 2871.10Seeh r@ fs_bshift l@ d<< ( inop >ndaddr? d-lbn+1<<bshift ) 2881.10Seeh 2swap >r di-size d@ ( d-lbn+1<<bshift d-size ) 2891.10Seeh 2swap 2over d< r> or if ( d-size ) 2901.10Seeh 2drop r> fs-bsize l@ exit 2911.1Smrg then 2921.10Seeh r@ lfs-blkoff ( size.lo size.hi ) 2931.10Seeh r> lfs-fragroundup d>l ( size ) 2941.10Seeh; 2951.10Seeh: lfs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi ) 2961.10Seeh lfs_fsbtodb l@ d<< 2971.1Smrg; 2981.1Smrg 2991.10Seeh\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 3001.1Smrg\ 3011.10Seeh\ The rest of the multi-filesystem stuff 3021.1Smrg\ 3031.10Seeh\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 3041.1Smrg 3051.10Seeh\ 3061.10Seeh\ FFS v1 3071.10Seeh\ 3081.10Seeh: di-db-v1@ ( indx dinode -- db.lo db.hi ) di1_db swap la+ l@ l>d ; 3091.10Seeh: di-ib-v1@ ( indx dinode -- db.lo db.hi ) di1_ib swap la+ l@ l>d ; 3101.10Seeh: ib-ib-v1@ ( indx iblk -- db.lo db.hi ) swap la+ l@ l>d ; 3111.10Seeh 3121.10Seeh: cgbase ( cg fs -- daddr.lo daddr.hi ) fs_fpg l@ um* ; 3131.10Seeh: cgstart-ufs1 ( cg fs -- cgstart ) 3141.10Seeh 2dup fs_old_cgmask l@ invert and ( cg fs stuff ) 3151.10Seeh over fs_old_cgoffset l@ um* ( cg fs off.lo off.hi ) 3161.10Seeh 2swap cgbase d+ ( off.lo off.hi ) 3171.1Smrg; 3181.1Smrg 3191.1Smrg\ 3201.10Seeh\ FFS v2 3211.1Smrg\ 3221.1Smrg 3231.10Seeh: di-db-v2@ ( indx dinode -- db.lo db.hi ) di2_db swap 2* la+ d@ ; 3241.10Seeh: di-ib-v2@ ( indx dinode -- db.lo db.hi ) di2_ib swap 2* la+ d@ ; 3251.10Seeh: ib-ib-v2@ ( indx iblk -- db.lo db.hi ) 2* la+ d@ ; 3261.1Smrg 3271.10Seeh\ 3281.10Seeh\ LFS v1 3291.10Seeh\ 3301.1Smrg 3311.1Smrg 3321.1Smrg\ 3331.1Smrg\ File stuff 3341.1Smrg\ 3351.1Smrg 3361.1Smrgniaddr /w* constant narraysize 3371.1Smrg 3381.10Seeh\ Assume UFS2 dinodes are always biger than UFS1 3391.10Seehufs2_dinode_SIZEOF buffer: cur-inode 3401.1Smrgh# 2000 buffer: indir-block 3411.10Seehcreate indir-addr -1 , -1 , 3421.1Smrg 3431.1Smrg\ 3441.1Smrg\ Translate a fileblock to a disk block 3451.1Smrg\ 3461.10Seeh\ We don't do triple indirect blocks. 3471.1Smrg\ 3481.1Smrg 3491.10Seeh\ Get the disk address from a single indirect block 3501.10Seeh: ib@ ( indx indir.lo indir.hi -- db.lo db.hi ) 3511.10Seeh 2dup indir-addr d@ d<> if ( indx indir.hi indir.lo ) 3521.10Seeh indir-addr d! ( indx ) 3531.10Seeh indir-block ( indx indir-block ) 3541.10Seeh sb-buf fs-bsize l@ ( indx indir-block fs fs-bsize ) 3551.10Seeh indir-addr d@ sb-buf ( indx indir-block fs-bsize indiraddr fs ) 3561.10Seeh fsbtodb ( indx indir-block fs-bsize db.lo db.hi ) 3571.10Seeh strategy 0 ( indx nread 0 ) \ Really should check return value 3581.10Seeh then 3591.10Seeh 2drop ( indx ) 3601.10Seeh indir-block ib-ib@ 3611.10Seeh; 3621.10Seeh 3631.10Seeh 3641.10Seeh: block-map ( fileblock -- diskblock.lo diskblock.hi ) 3651.10Seeh \ Direct block? 3661.10Seeh dup ndaddr < if ( fileblock ) 3671.10Seeh cur-inode di-db@ exit ( diskblock.lo diskblock.hi ) 3681.10Seeh then ( fileblock ) 3691.10Seeh ndaddr - ( fileblock' ) 3701.10Seeh \ Now we need to check the indirect block 3711.10Seeh dup sb-buf fs_nindir l@ < if ( fileblock' ) 3721.10Seeh 0 cur-inode di-ib@ ( fileblock' indir.lo indir.hi ) 3731.10Seeh ib@ exit ( db.lo db.hi ) 3741.1Smrg then 3751.1Smrg dup sb-buf fs_nindir - ( fileblock'' ) 3761.1Smrg \ Now try 2nd level indirect block -- just read twice 3771.10Seeh dup sb-buf fs_nindir l@ dup * >= if ( fileblock'' ) 3781.10Seeh ." block-map: exceeded max file size" cr 3791.10Seeh abort 3801.1Smrg then 3811.10Seeh 3821.10Seeh 1 cur-inode di-ib@ ( fileblock'' ib.lo ib.hi ) 3831.10Seeh 3841.10Seeh \ Get 1st indirect block and find the 2nd indirect block 3851.10Seeh rot dup sb-buf fs_nindir u/mod ( ib2.lo ib2.hi indx2 indx1 ) 3861.10Seeh 2swap ib@ ( indx2 ib2.lo ib2.hi ) 3871.10Seeh 3881.10Seeh \ Get 2nd indirect block and find our diskblock 3891.10Seeh ib@ ( db.lo db.hi ) 3901.1Smrg; 3911.1Smrg 3921.1Smrg\ 3931.1Smrg\ Read file into internal buffer and return pointer and len 3941.1Smrg\ 3951.1Smrg 3961.4Seeh0 value cur-block \ allocated dynamically in ufs-open 3971.10Seeh0 value cur-blocksize \ size allocated to cur-block 3981.10Seehcreate cur-blockno -1 l, -1 l, \ Current disk block. 3991.10Seeh-1 value file-blockno \ Current file block no. 4001.10Seeh0 value file-offset \ Current file offset, max 4GB. 4011.10Seeh 4021.10Seeh: buf-read-file ( fs -- buf len ) 4031.10Seeh >r file-offset ( seek ) 4041.10Seeh dup l>d r@ lblkno drop ( seek blk ) 4051.10Seeh dup l>d cur-inode r@ blksize ( seek blk blksize ) 4061.10Seeh over file-blockno <> if ( seek blk blksize ) 4071.10Seeh over to file-blockno 4081.10Seeh swap block-map ( seek blksize fsblk.lo fsblk.hi ) 4091.10Seeh 2dup or 0= if ( seek blksize fsblk.lo fsblk.hi ) 4101.10Seeh \ Clear out curblock XXX Why? Idunno. 4111.10Seeh 2drop dup 4121.10Seeh cur-block swap erase ( seek blksize ) 4131.10Seeh boot-debug? if ." buf-read-file reading block 0" cr then 4141.10Seeh -1 l>d \ Invalid disk block 4151.10Seeh else 4161.10Seeh \ Call strategy to load the correct block. 4171.10Seeh r@ fsbtodb ( seek blksize dblk.lo dblk.hi ) 4181.10Seeh rot >r cur-block r@ 2over ( seek addr size db.lo db.hi ) 4191.10Seeh strategy r@ <> if ." buf-read-file: short read." cr abort then 4201.10Seeh r> -rot ( seek size db.lo db.hi ) 4211.10Seeh then 4221.10Seeh \ Save the new current disk block number 4231.10Seeh cur-blockno d! ( seek size ) 4241.10Seeh else 4251.10Seeh nip ( seek size ) 4261.10Seeh then 4271.10Seeh \ Now figure out how much we have in the buffer. 4281.10Seeh swap l>d r> blkoff ( size off.lo off.hi ) 4291.10Seeh d>l cur-block over + ( size off buf ) 4301.10Seeh -rot - ( buf siz ) 4311.1Smrg; 4321.1Smrg 4331.1Smrg\ 4341.1Smrg\ Read inode into cur-inode -- uses cur-block 4351.1Smrg\ 4361.1Smrg 4371.10Seeh: read-inode-ffs ( inode fs -- ) 4381.10Seeh twiddle 4391.10Seeh 4401.10Seeh >r dup r@ ino-to-fsba ( ino fsblk.lo fsblck.hi ) 4411.10Seeh r@ fsbtodb ( ino dblk.lo dblk.hi ) 4421.10Seeh 2dup cur-blockno d@ d<> if ( ino dblk.lo dblk.hi ) 4431.10Seeh \ We need to read the block 4441.10Seeh cur-block r@ fs-bsize l@ ( ino dblk.lo dblk.hi addr size ) 4451.10Seeh >r r@ 2over strategy r> <> if ( ino dblk.lo dblk.hi ) 4461.10Seeh ." read-inode - residual" cr abort 4471.10Seeh then 4481.10Seeh 2dup cur-blockno d! ( ino dblk.lo dblk.hi ) 4491.10Seeh then 2drop ( ino ) 4501.1Smrg 4511.10Seeh r> ino-to-fsbo /dino * ( off ) 4521.10Seeh cur-block + cur-inode /dino move ( ) 4531.10Seeh; 4541.10Seeh 4551.10Seeh: find-inode-sector ( ino fs -- d-dblkno true | false ) 4561.10Seeh >r r@ lfs_ifile l@ r@ read-inode ( ino ) 4571.10Seeh 4581.10Seeh r@ lfs_ifpb l@ u/mod ( rem q ) 4591.10Seeh 4601.10Seeh r@ lfs_cleansz l@ + 4611.10Seeh r@ lfs_segtabsz l@ + ( rem blkno ) 4621.1Smrg 4631.10Seeh r@ fs-bsize l@ um* rot /ifile um* d+ ( dseekp ) 4641.1Smrg 4651.10Seeh drop to file-offset r@ buf-read-file ( buf len ) 4661.10Seeh 4671.10Seeh /ifile < if r> 2drop false exit then ( buf ) 4681.10Seeh 4691.10Seeh if_daddr l@ l>d r> fsbtodb ( daddr ) 4701.10Seeh 2dup lfs_unused_daddr l>d d= if 2drop false then 4711.10Seeh true 4721.10Seeh; 4731.10Seeh 4741.10Seeh: read-inode-lfs ( inode fs -- ) 4751.10Seeh twiddle 4761.10Seeh 4771.10Seeh >r dup r@ lfs_ifile l@ = if ( ino r: fs ) 4781.10Seeh r@ lfs_idaddr l@ l>d ( ino d-idaddr ) 4791.10Seeh r@ fsbtodb ( ino d-db ) 4801.10Seeh else 4811.10Seeh dup r@ find-inode-sector 0= abort" Could not find inode sector!" 4821.10Seeh then ( ino d-db ) 4831.10Seeh 4841.10Seeh 2dup cur-blockno d@ d<> if ( ino dblk.lo dblk.hi ) 4851.10Seeh \ We need to read the block 4861.10Seeh cur-block r@ fs-bsize l@ ( ino dblk.lo dblk.hi addr size ) 4871.10Seeh >r r@ 2over strategy r> <> if ( ino dblk.lo dblk.hi ) 4881.10Seeh ." read-inode - residual" cr abort 4891.10Seeh then 4901.10Seeh 2dup cur-blockno d! ( ino dblk.lo dblk.hi ) 4911.10Seeh then 2drop ( ino ) 4921.10Seeh 4931.10Seeh r@ lfs_inopb l@ ( ino cnt ) 4941.10Seeh swap cur-block begin ( cnt ino p ) 4951.10Seeh tuck di_inumber l@ over <> ( cnt p ino !found? ) 4961.10Seeh while ( cnt p ino ) 4971.10Seeh rot 1- ?dup 0= abort" Could not find inode!" 4981.10Seeh rot /dino + swap -rot ( cnt ino p ) 4991.10Seeh repeat swap ( cnt ino p ) 5001.10Seeh 5011.10Seeh cur-inode /dino move ( cnt ino ) 5021.10Seeh 5031.10Seeh r> 3drop 5041.1Smrg; 5051.1Smrg 5061.1Smrg\ Identify inode type 5071.1Smrg 5081.10Seeh: is-dir? ( ufs1_dinode -- is-dir? ) di-mode w@ ifmt and ifdir = ; 5091.10Seeh: is-symlink? ( ufs1_dinode -- is-symlink? ) di-mode w@ ifmt and iflnk = ; 5101.10Seeh 5111.10Seeh\ 5121.10Seeh\ Multi-FS initialiation. 5131.10Seeh\ 5141.10Seeh\ It's way down here so all the fs-specific routines have already been defined. 5151.10Seeh\ 5161.10Seeh 5171.10Seeh: init-ffs-common ( -- ) 5181.10Seeh ' fs_SIZEOF to fs-size 5191.10Seeh ' fs_bsize to fs-bsize 5201.10Seeh ' ffs-dblksize to blksize 5211.10Seeh ' read-inode-ffs to read-inode 5221.10Seeh ' ffs-fsbtodb to fsbtodb 5231.10Seeh ' ffs-lblkno to lblkno 5241.10Seeh ' ffs-blkoff to blkoff 5251.10Seeh; 5261.10Seeh 5271.10Seeh 5281.10Seeh: ffs-oldcompat ( -- ) 5291.10Seeh \ Make sure old ffs values in sb-buf are sane 5301.10Seeh sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l! 5311.10Seeh sb-buf fs_old_interleave dup l@ 1 max swap l! 5321.10Seeh sb-buf fs_old_postblformat l@ fs_42postblfmt = if 5331.10Seeh 8 sb-buf fs_old_nrpos l! 5341.10Seeh then 5351.10Seeh sb-buf fs_old_inodefmt l@ fs_44inodefmt < if 5361.10Seeh sb-buf fs-bsize l@ 5371.10Seeh dup ndaddr um* 1 d- sb-buf fs_maxfilesize d! 5381.10Seeh niaddr 0 ?do 5391.10Seeh sb-buf fs_nindir l@ * dup ( sizebp sizebp ) 5401.10Seeh sb-buf fs_maxfilesize dup d@ ( sizebp sizebp *mxfs mxfs.lo mxfs.hi ) 5411.10Seeh 2over drop l>d d+ 2swap d! ( sizebp ) 5421.10Seeh loop drop ( ) 5431.10Seeh sb-buf dup fs_bmask l@ invert l>d rot fs_qbmask d! 5441.10Seeh sb-buf dup fs_fmask l@ invert l>d rot fs_qfmask d! 5451.10Seeh then 5461.10Seeh; 5471.10Seeh 5481.10Seeh 5491.10Seeh: init-ffs-v1 ( -- ) 5501.10Seeh init-ffs-common 5511.10Seeh ' di1_size to di-size 5521.10Seeh ' di1_mode to di-mode 5531.10Seeh ' ufs1_dinode_SIZEOF to /dino 5541.10Seeh ' cgstart-ufs1 to cgstart 5551.10Seeh ' di-db-v1@ to di-db@ 5561.10Seeh ' di-ib-v1@ to di-ib@ 5571.10Seeh ' ib-ib-v1@ to ib-ib@ 5581.10Seeh ffs-oldcompat 5591.10Seeh; 5601.10Seeh 5611.10Seeh: init-ffs-v2 ( -- ) 5621.10Seeh init-ffs-common 5631.10Seeh ' di2_size to di-size 5641.10Seeh ' di2_mode to di-mode 5651.10Seeh ' ufs2_dinode_SIZEOF to /dino 5661.10Seeh ' cgbase to cgstart 5671.10Seeh ' di-db-v2@ to di-db@ 5681.10Seeh ' di-ib-v2@ to di-ib@ 5691.10Seeh ' ib-ib-v2@ to ib-ib@ 5701.10Seeh; 5711.10Seeh 5721.10Seeh: init-lfs-common ( -- ) 5731.10Seeh ' dlfs_SIZEOF to fs-size 5741.10Seeh ' di1_size to di-size 5751.10Seeh ' di1_mode to di-mode 5761.10Seeh ' ufs1_dinode_SIZEOF to /dino 5771.10Seeh ' cgbase to cgstart 5781.10Seeh ' di-db-v1@ to di-db@ 5791.10Seeh ' di-ib-v1@ to di-ib@ 5801.10Seeh ' ib-ib-v1@ to ib-ib@ 5811.10Seeh ' lfs-dblksize to blksize 5821.10Seeh ' read-inode-lfs to read-inode 5831.10Seeh ' lfs-fsbtodb to fsbtodb 5841.10Seeh ' lfs-lblkno to lblkno 5851.10Seeh ' lfs-blkoff to blkoff 5861.10Seeh; 5871.10Seeh 5881.10Seeh: init-lfs-v1 ( -- ) 5891.10Seeh init-lfs-common 5901.10Seeh ' lfs_ibsize to fs-bsize 5911.10Seeh ' ifile_v1_SIZEOF to /ifile 5921.10Seeh ' if1_daddr to if_daddr 5931.10Seeh; 5941.10Seeh 5951.10Seeh: init-lfs-v2 ( -- ) 5961.10Seeh init-lfs-common 5971.10Seeh ' lfs_bsize to fs-bsize 5981.10Seeh ' ifile_SIZEOF to /ifile 5991.10Seeh ' if2_daddr to if_daddr 6001.10Seeh; 6011.10Seeh 6021.10Seeh 6031.10Seeh: fs-magic? ( sb -- is-ufs? ) 6041.10Seeh \ The LFS magic is the first word in the superblock 6051.10Seeh dup lfs_magic l@ lfs_magic_value = if 6061.10Seeh dup lfs_version l@ case ( sb sel ) 6071.10Seeh 1 of init-lfs-v1 drop true exit endof 6081.10Seeh 2 of init-lfs-v2 drop true exit endof 6091.10Seeh ." Invalid LFS version." \ Try FFS. 6101.10Seeh endcase 6111.10Seeh then ( sb ) 6121.10Seeh \ The FFS magic is at the end of the superblock 6131.10Seeh fs_magic l@ case 6141.10Seeh fs1_magic_value of init-ffs-v1 true endof 6151.10Seeh fs2_magic_value of init-ffs-v2 true endof 6161.10Seeh false swap \ Return false 6171.10Seeh endcase 6181.10Seeh; 6191.1Smrg 6201.1Smrg 6211.1Smrg 6221.1Smrg\ 6231.1Smrg\ Hunt for directory entry: 6241.1Smrg\ 6251.1Smrg\ repeat 6261.1Smrg\ load a buffer 6271.1Smrg\ while entries do 6281.1Smrg\ if entry == name return 6291.1Smrg\ next entry 6301.1Smrg\ until no buffers 6311.1Smrg\ 6321.1Smrg 6331.10Seeh: search-dir-block ( str len buf len -- ino | 0 ) 6341.10Seeh 2dup + nip ( str len buf bufend ) 6351.10Seeh swap 2swap rot ( bufend str len direct ) 6361.10Seeh begin dup 4 pick < while ( bufend str len direct ) 6371.10Seeh dup d_ino l@ 0<> if ( bufend str len direct ) 6381.10Seeh boot-debug? if 6391.10Seeh \ Print the current file name 6401.10Seeh dup dup d_name swap d_namlen c@ type cr 6411.10Seeh then 6421.10Seeh 2dup d_namlen c@ = if ( bufend str len direct ) 6431.10Seeh dup d_name 2over ( bufend str len direct dname str len ) 6441.10Seeh comp 0= if ( bufend str len direct ) 6451.10Seeh \ Found it -- return inode 6461.10Seeh d_ino l@ nip nip nip ( dino ) 6471.10Seeh boot-debug? if ." Found it" cr then 6481.10Seeh exit ( dino ) 6491.10Seeh then 6501.10Seeh then ( bufend str len direct ) 6511.10Seeh then ( bufend str len direct ) 6521.10Seeh dup d_reclen w@ + ( bufend str len nextdirect ) 6531.10Seeh repeat 6541.10Seeh 2drop 2drop 0 6551.10Seeh; 6561.10Seeh 6571.10Seeh 6581.10Seeh: search-directory ( str len -- ino | 0 ) 6591.10Seeh 0 to file-offset 6601.10Seeh begin 6611.10Seeh file-offset cur-inode di-size d@ drop < 6621.10Seeh while ( str len ) 6631.10Seeh \ Read a directory block 6641.10Seeh sb-buf buf-read-file ( str len buf len ) 6651.10Seeh dup 0= if ." search-directory: buf-read-file zero len" cr abort then 6661.10Seeh dup file-offset + to file-offset ( str len buf len ) 6671.10Seeh 6681.10Seeh 2over 2swap search-dir-block ?dup if 6691.10Seeh \ Found it 6701.10Seeh nip nip exit 6711.10Seeh then ( str len ) 6721.10Seeh repeat 6731.10Seeh 2drop 2drop 0 ( 0 ) 6741.1Smrg; 6751.1Smrg 6761.3Seeh: read-super ( sector -- ) 6771.10Seeh 0 " seek" boot-ihandle $call-method -1 = if 6781.10Seeh ." Seek failed" cr abort 6791.1Smrg then 6801.1Smrg sb-buf sbsize " read" boot-ihandle $call-method 6811.1Smrg dup sbsize <> if 6821.1Smrg ." Read of superblock failed" cr 6831.1Smrg ." requested" space sbsize . 6841.1Smrg ." actual" space . cr 6851.1Smrg abort 6861.1Smrg else 6871.1Smrg drop 6881.1Smrg then 6891.3Seeh; 6901.3Seeh 6911.10Seeh: ufs-open ( bootpath len -- ) 6921.3Seeh boot-ihandle -1 = if 6931.10Seeh 2dup + 0 swap c! \ Nul terminate. 6941.10Seeh over cif-open dup 0= if ( boot-path len ihandle? ) 6951.10Seeh ." Could not open device" space type cr 6961.10Seeh abort 6971.3Seeh then ( boot-path len ihandle ) 6981.10Seeh to boot-ihandle \ Save ihandle to boot device 6991.10Seeh then 7001.10Seeh 2drop 7011.10Seeh 7021.10Seeh boot-debug? if ." Try a RAID superblock read" cr then 7031.10Seeh rf_protected dup to raid-offset 7041.10Seeh dev_bsize * sboff + read-super 7051.10Seeh sb-buf fs-magic? invert if 7061.10Seeh boot-debug? if ." Try a normal superblock read" cr then 7071.10Seeh 0 to raid-offset 7081.8Sjdc sboff read-super 7091.10Seeh sb-buf fs-magic? invert abort" Invalid superblock magic" 7101.1Smrg then 7111.10Seeh sb-buf fs-bsize l@ dup maxbsize > if 7121.1Smrg ." Superblock bsize" space . ." too large" cr 7131.1Smrg abort 7141.1Smrg then 7151.10Seeh dup fs-size < if 7161.1Smrg ." Superblock bsize < size of superblock" cr 7171.1Smrg abort 7181.1Smrg then 7191.10Seeh dup to cur-blocksize alloc-mem to cur-block \ Allocate cur-block 7201.10Seeh boot-debug? if ." ufs-open complete" cr then 7211.1Smrg; 7221.1Smrg 7231.1Smrg: ufs-close ( -- ) 7241.10Seeh boot-ihandle dup -1 <> if 7251.10Seeh cif-close -1 to boot-ihandle 7261.10Seeh then 7271.10Seeh cur-block 0<> if 7281.10Seeh cur-block cur-blocksize free-mem 7291.10Seeh then 7301.1Smrg; 7311.1Smrg 7321.1Smrg: boot-path ( -- boot-path ) 7331.10Seeh " bootpath" chosen-phandle get-package-property if 7341.10Seeh ." Could not find bootpath in /chosen" cr 7351.10Seeh abort 7361.10Seeh else 7371.10Seeh decode-string 2swap 2drop 7381.10Seeh then 7391.1Smrg; 7401.1Smrg 7411.1Smrg: boot-args ( -- boot-args ) 7421.10Seeh " bootargs" chosen-phandle get-package-property if 7431.10Seeh ." Could not find bootargs in /chosen" cr 7441.10Seeh abort 7451.10Seeh else 7461.10Seeh decode-string 2swap 2drop 7471.10Seeh then 7481.1Smrg; 7491.1Smrg 7501.1Smrg2000 buffer: boot-path-str 7511.1Smrg2000 buffer: boot-path-tmp 7521.1Smrg 7531.1Smrg: split-path ( path len -- right len left len ) 7541.1Smrg\ Split a string at the `/' 7551.10Seeh begin 7561.10Seeh dup -rot ( oldlen right len left ) 7571.10Seeh ascii / left-parse-string ( oldlen right len left len ) 7581.10Seeh dup 0<> if 4 roll drop exit then 7591.10Seeh 2drop ( oldlen right len ) 7601.10Seeh rot over = ( right len diff ) 7611.10Seeh until 7621.1Smrg; 7631.1Smrg 7641.1Smrg: find-file ( load-file len -- ) 7651.10Seeh rootino dup sb-buf read-inode ( load-file len pino ) 7661.10Seeh -rot ( pino load-file len ) 7671.10Seeh \ 7681.10Seeh \ For each path component 7691.10Seeh \ 7701.10Seeh begin split-path dup 0<> while ( pino right len left len ) 7711.10Seeh cur-inode is-dir? not if ." Inode not directory" cr abort then 7721.10Seeh boot-debug? if ." Looking for" space 2dup type space ." in directory..." cr then 7731.10Seeh search-directory ( pino right len ino|false ) 7741.10Seeh dup 0= abort" Bad path" ( pino right len cino ) 7751.10Seeh sb-buf read-inode ( pino right len ) 7761.10Seeh cur-inode is-symlink? if \ Symlink -- follow the damn thing 7771.10Seeh \ Save path in boot-path-tmp 7781.10Seeh boot-path-tmp strmov ( pino new-right len ) 7791.10Seeh 7801.10Seeh \ Now deal with symlink XXX drop high word of linklen 7811.10Seeh cur-inode di-size d@ drop ( pino right len linklen.lo ) 7821.10Seeh dup sb-buf fs_maxsymlinklen l@ ( pino right len linklen linklen maxlinklen ) 7831.10Seeh < if \ Now join the link to the path 7841.10Seeh 0 cur-inode di-db@ drop ( pino right len linklen linkp ) 7851.10Seeh swap boot-path-str strmov ( pino right len new-linkp linklen ) 7861.10Seeh else \ Read file for symlink -- Ugh 7871.10Seeh \ Read link into boot-path-str 7881.10Seeh boot-path-str dup sb-buf fs-bsize l@ 7891.10Seeh 0 block-map ( pino right len linklen boot-path-str bsize blockno.lo blockno.hi ) 7901.10Seeh strategy drop swap ( pino right len boot-path-str linklen ) 7911.10Seeh then ( pino right len linkp linklen ) 7921.10Seeh \ Concatenate the two paths 7931.10Seeh strcat ( pino new-right newlen ) 7941.10Seeh swap dup c@ ascii / = if \ go to root inode? 7951.10Seeh rot drop rootino -rot ( rino len right ) 7961.10Seeh then 7971.10Seeh rot dup sb-buf read-inode ( len right pino ) 7981.10Seeh -rot swap ( pino right len ) 7991.10Seeh then ( pino right len ) 8001.10Seeh repeat 8011.10Seeh 2drop drop 8021.10Seeh; 8031.10Seeh 8041.10Seeh: .read-file-msg ( addr xxx siz -- addr xxx siz ) 8051.10Seeh boot-debug? if 8061.10Seeh ." Copying " dup . ." bytes to " 3 pick . cr 8071.10Seeh then 8081.10Seeh; 8091.10Seeh 8101.10Seeh: read-file ( addr size -- ) 8111.10Seeh noop \ In case we need to debug this 8121.10Seeh \ Read x bytes from a file to buffer 8131.10Seeh begin dup 0> while 8141.10Seeh file-offset cur-inode di-size d@ drop > if 8151.10Seeh ." read-file EOF exceeded" cr abort 8161.10Seeh then 8171.10Seeh sb-buf buf-read-file ( addr size buf len ) 8181.10Seeh 8191.10Seeh .read-file-msg 8201.10Seeh 8211.10Seeh \ Copy len bytes to addr XXX min ( len, size ) ? 8221.10Seeh 2over drop 3dup swap move drop ( addr size buf len ) 8231.10Seeh 8241.10Seeh dup file-offset + to file-offset ( addr size buf len ) 8251.10Seeh 8261.10Seeh nip tuck - -rot + swap ( addr' size' ) 8271.10Seeh repeat 8281.10Seeh 2drop 8291.1Smrg; 8301.1Smrg 8311.10Seeh" load-base " evaluate constant loader-base 8321.1Smrg 8331.1Smrg: load-file-signon ( load-file len boot-path len -- load-file len boot-path len ) 8341.1Smrg ." Loading file" space 2over type cr ." from device" space 2dup type cr 8351.1Smrg; 8361.1Smrg 8371.1Smrg: load-file ( load-file len boot-path len -- load-base ) 8381.10Seeh boot-debug? if load-file-signon then 8391.10Seeh 8401.10Seeh ufs-open ( load-file len ) 8411.10Seeh find-file ( ) 8421.1Smrg 8431.10Seeh \ 8441.10Seeh \ Now we've found the file we should read it in in one big hunk 8451.10Seeh \ 8461.10Seeh 8471.10Seeh cur-inode di-size d@ if ." File len >2GB!" cr abort then 8481.10Seeh\ dup " to file-size " evaluate ( file-len ) \ Wassthis? 8491.10Seeh boot-debug? if 8501.10Seeh ." Loading " dup . ." bytes of file..." cr 8511.10Seeh then 8521.10Seeh 0 to file-offset 8531.10Seeh -1 to file-blockno 8541.10Seeh loader-base ( buf-len addr ) 8551.10Seeh tuck swap read-file ( addr ) 8561.10Seeh ufs-close ( addr ) 8571.1Smrg; 8581.1Smrg 8591.1Smrg: do-boot ( bootfile -- ) 8601.10Seeh ." NetBSD IEEE 1275 Multi-FS Bootblock" cr 8611.10Seeh boot-path load-file ( -- load-base ) 8621.10Seeh dup 0<> if " init-program " evaluate then 8631.10Seeh; 8641.1Smrg 8651.1Smrg 8661.10Seehboot-args ascii V strchr 0<> swap drop if 8671.10Seeh true to boot-debug? 8681.1Smrgthen 8691.1Smrg 8701.10Seehboot-args ascii D strchr 0= swap drop if 8711.10Seeh " /ofwboot" do-boot 8721.10Seehthen exit 8731.1Smrg 8741.1Smrg 875