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