bootblk.fth revision 1.10
1\ $NetBSD: bootblk.fth,v 1.10 2010/02/13 23:38:17 eeh Exp $ 2\ 3\ IEEE 1275 Open Firmware Boot Block 4\ 5\ Parses disklabel and UFS and loads the file called `ofwboot' 6\ 7\ 8\ Copyright (c) 1998-2010 Eduardo Horvath. 9\ All rights reserved. 10\ 11\ Redistribution and use in source and binary forms, with or without 12\ modification, are permitted provided that the following conditions 13\ are met: 14\ 1. Redistributions of source code must retain the above copyright 15\ notice, this list of conditions and the following disclaimer. 16\ 2. Redistributions in binary form must reproduce the above copyright 17\ notice, this list of conditions and the following disclaimer in the 18\ documentation and/or other materials provided with the distribution. 19\ 20\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21\ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22\ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23\ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24\ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25\ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26\ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27\ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28\ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29\ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30\ 31 32offset16 33hex 34headers 35 36false value boot-debug? 37 38\ 39\ First some housekeeping: Open /chosen and set up vectors into 40\ client-services 41 42" /chosen" find-package 0= if ." Cannot find /chosen" 0 then 43constant chosen-phandle 44 45" /openprom/client-services" find-package 0= if 46 ." Cannot find client-services" cr abort 47then constant cif-phandle 48 49defer cif-claim ( align size virt -- base ) 50defer cif-release ( size virt -- ) 51defer cif-open ( cstr -- ihandle|0 ) 52defer cif-close ( ihandle -- ) 53defer cif-read ( len adr ihandle -- #read ) 54defer cif-seek ( low high ihandle -- -1|0|1 ) 55\ defer cif-peer ( phandle -- phandle ) 56\ defer cif-getprop ( len adr cstr phandle -- ) 57 58: find-cif-method ( method len -- xf ) 59 cif-phandle find-method drop 60; 61 62" claim" find-cif-method to cif-claim 63" open" find-cif-method to cif-open 64" close" find-cif-method to cif-close 65" read" find-cif-method to cif-read 66" seek" find-cif-method to cif-seek 67 68: twiddle ( -- ) ." ." ; \ Need to do this right. Just spit out periods for now. 69 70\ 71\ Support routines 72\ 73 74\ 64-bit math support 75 76here h# ffff over l! <w@ constant little-endian? 77: ul>d ( l -- d.lo d.hi ) 0 ; 78: l>d ( l -- d.lo d.hi ) dup 0< if -1 else 0 then ; 79: d>l ( d.lo d.hi -- l ) drop ; 80: d@ ( addr -- d.lo d.hi ) dup l@ swap la1+ l@ little-endian? invert if swap then ; 81: d! ( d.lo d.hi addr -- ) 82 little-endian? invert if -rot swap rot then tuck la1+ l! l! ; 83: d-and ( d1 d2 -- d1-and-d2 ) rot and -rot and swap ; 84: d*u ( d1 u -- d2 ) tuck um* drop -rot um* rot + ; 85: d<< ( d1 n -- d1<<n ) \ Hope this works 86 tuck << ( d.lo n d.hi' ) 87 -rot 2dup << ( d.hi' d.lo n d.lo' ) 88 -rot d# 32 swap - >> ( d.hi' d.lo' lo.hi ) 89 rot + 90; 91: d>> ( d1 n -- d1>>n ) \ Hope this works 92 rot over >> -rot ( d.lo' d.hi n ) 93 2dup >> -rot ( d.lo' d.hi' d.hi n ) 94 d# 32 swap - << rot + swap 95; 96: d> ( d1 d2 -- d1>d2? ) 97 rot swap 2dup = if 98 2drop > exit 99 then 100 > nip nip 101; 102: d>= ( d1 d2 -- d1>=d2? ) 103 rot swap 2dup = if 104 2drop >= exit 105 then 106 >= nip nip 107; 108: d< ( d1 d2 -- d1<d2? ) d>= invert ; 109: d= ( d1 d2 -- d1=d2? ) rot = -rot = and ; 110: d<> ( d1 d2 -- d1<>d2? ) d= invert ; 111 112 113\ String support 114 115: strcmp ( s1 l1 s2 l2 -- true:false ) 116 rot tuck <> if 3drop false exit then 117 comp 0= 118; 119 120\ Move string into buffer 121 122: strmov ( s1 l1 d -- d l1 ) 123 dup 2over swap -rot ( s1 l1 d s1 d l1 ) 124 move ( s1 l1 d ) 125 rot drop swap 126; 127 128\ Move s1 on the end of s2 and return the result 129 130: strcat ( s1 l1 s2 l2 -- d tot ) 131 2over swap ( s1 l1 s2 l2 l1 s1 ) 132 2over + rot ( s1 l1 s2 l2 s1 d l1 ) 133 move rot + ( s1 s2 len ) 134 rot drop ( s2 len ) 135; 136 137: strchr ( s1 l1 c -- s2 l2 ) 138 begin 139 dup 2over 0= if ( s1 l1 c c s1 ) 140 2drop drop exit then 141 c@ = if ( s1 l1 c ) 142 drop exit then 143 -rot /c - swap ca1+ ( c l2 s2 ) 144 swap rot 145 again 146; 147 148 149: cstr ( ptr -- str len ) 150 dup 151 begin dup c@ 0<> while + repeat 152 over - 153; 154 155\ 156\ BSD UFS parameters 157\ 158 159fload ffs.fth.h 160fload lfs.fth.h 161 162sbsize buffer: sb-buf 163-1 value boot-ihandle 164dev_bsize value bsize 1650 value raid-offset \ Offset if it's a raid-frame partition 166 167: strategy ( addr size db.lo db.hi -- nread ) 168 raid-offset l>d d+ ( addr size db.lo' db.hi' ) 169 bsize d*u ( addr size sector.lo sector.hi ) 170 " seek" boot-ihandle $call-method -1 = if 171 ." strategy: Seek failed" cr 172 abort 173 then ( addr size ) 174 " read" boot-ihandle $call-method 175; 176 177 178\ 179\ Multi-FS support 180\ 181\ XXX Maybe the different filesystems should be segregated into separate files 182\ XXX that are individually fload-ed. 183\ 184 185defer fs-size 186defer di-size 187defer di-mode 188defer /dino 189defer cgstart 190defer di-db@ 191defer di-ib@ 192defer ib-ib@ 193defer fs-bsize 194defer fsbtodb 195defer blksize 196defer lblkno 197defer blkoff 198defer read-inode 199\ LFS ifile 200defer /ifile 201defer if_daddr 202 203\ 204\ FFS Cylinder group macros 205\ 206 207: cgdmin ( cg fs -- d-1st-data-block ) dup fs_dblkno l@ l>d 2swap cgstart d+ ; 208: cgimin ( cg fs -- d-inode-block ) dup fs_iblkno l@ l>d 2swap cgstart d+ ; 209: cgsblock ( cg fs -- d-super-block ) dup fs_sblkno l@ l>d 2swap cgstart d+ ; 210: cgstod ( cg fs -- d-cg-block ) dup fs_cblkno l@ l>d 2swap cgstart d+ ; 211 212\ 213\ FFS Block and frag position macros 214\ 215 216: ffs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi ) fs_qbmask d@ d-and ; 217\ : ffs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi ) fs_qfmask d@ d-and ; 218\ : ffs-lblktosize ( blk fs -- off.lo off.hi ) 0 fs_bshift l@ d<< ; 219: ffs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi ) fs_bshift l@ d>> ; 220: ffs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi ) fs_fshift l@ d>> ; 221: ffs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi ) 222 >r r@ fs_qbmask d@ d+ r> fs_bmask l@ l>d d-and 223; 224: ffs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi ) 225 >r r@ fs_qfmask d@ d+ r> fs_fmask l@ l>d d-and 226; 227: ffs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi ) fs_fragshift l@ d>> ; 228: ffs-blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ; 229\ : ffs-fragnum ( fsb fs -- off ) fs_frag l@ 1- and ; 230\ : ffs-blknum ( fsb fs -- off ) fs_frag l@ 1- not and ; 231: ffs-dblksize ( lbn.lo lbn.hi inodep fs -- size ) 232 >r -rot 2dup ndaddr l>d d> ( inop d-lbn >ndaddr? ) 233 -rot 1 0 d+ ( inop >ndaddr? d-lbn+1 ) 234 r@ fs_bshift l@ d<< ( inop >ndaddr? d-lbn+1<<bshift ) 235 2swap >r di-size d@ ( d-lbn+1<<bshift d-size ) 236 2swap 2over d< r> or if ( d-size ) 237 2drop r> fs-bsize l@ exit 238 then 239 r@ ffs-blkoff ( size.lo size.hi ) 240 r> ffs-fragroundup d>l ( size ) 241; 242 243: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ; 244: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ; 245: ino-to-fsba ( ino fs -- ba.lo ba.hi ) \ Need to remove the stupid stack diags someday 246 2dup ( ino fs ino fs ) 247 ino-to-cg ( ino fs cg ) 248 over ( ino fs cg fs ) 249 cgimin ( ino fs inode-blk.lo inode-blk.hi ) 250 2swap ( d-inode-blk ino fs ) 251 tuck ( d-inode-blk fs ino fs ) 252 fs_ipg l@ ( d-inode-blk fs ino ipg ) 253 mod ( d-inode-blk fs mod ) 254 swap ( d-inode-blk mod fs ) 255 dup ( d-inode-blk mod fs fs ) 256 fs_inopb l@ ( d-inode-blk mod fs inopb ) 257 rot ( d-inode-blk fs inopb mod ) 258 swap ( d-inode-blk fs mod inopb ) 259 / ( d-inode-blk fs div ) 260 swap ( d-inode-blk div fs ) 261 ffs-blkstofrags ( d-inode-blk frag ) 262 0 d+ 263; 264: ffs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi ) 265 fs_fsbtodb l@ d<< 266; 267 268 269\ 270\ LFS suff 271\ 272: lfs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_bmask d@ d-and ; 273\ : lfs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_ffmask d@ d-and ; 274\ : lfs-lblktosize ( blk fs -- off.lo off.hi ) 0 lfs_bshift l@ d<< ; 275: lfs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_bshift l@ d>> ; 276: lfs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_ffshift l@ d>> ; 277: lfs-roundup ( pos.lo pos.hi mask.lo mask.hi ) 278 2swap 2over d+ 2swap ( d-pos* d-mask ) 279 invert swap invert swap d-and 280; 281: lfs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_bmask d@ lfs-roundup ; 282: lfs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_ffmask d@ lfs-roundup ; 283: lfs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi ) lfs_fbshift l@ d>> ; 284: lfs-dblksize ( lbn.lo lbn.hi inodep fs -- size ) 285 >r -rot 2dup ndaddr l>d d> ( inop d-lbn >ndaddr? ) 286 -rot 1 0 d+ ( inop >ndaddr? d-lbn+1 ) 287 r@ fs_bshift l@ d<< ( inop >ndaddr? d-lbn+1<<bshift ) 288 2swap >r di-size d@ ( d-lbn+1<<bshift d-size ) 289 2swap 2over d< r> or if ( d-size ) 290 2drop r> fs-bsize l@ exit 291 then 292 r@ lfs-blkoff ( size.lo size.hi ) 293 r> lfs-fragroundup d>l ( size ) 294; 295: lfs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi ) 296 lfs_fsbtodb l@ d<< 297; 298 299\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 300\ 301\ The rest of the multi-filesystem stuff 302\ 303\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 304 305\ 306\ FFS v1 307\ 308: di-db-v1@ ( indx dinode -- db.lo db.hi ) di1_db swap la+ l@ l>d ; 309: di-ib-v1@ ( indx dinode -- db.lo db.hi ) di1_ib swap la+ l@ l>d ; 310: ib-ib-v1@ ( indx iblk -- db.lo db.hi ) swap la+ l@ l>d ; 311 312: cgbase ( cg fs -- daddr.lo daddr.hi ) fs_fpg l@ um* ; 313: cgstart-ufs1 ( cg fs -- cgstart ) 314 2dup fs_old_cgmask l@ invert and ( cg fs stuff ) 315 over fs_old_cgoffset l@ um* ( cg fs off.lo off.hi ) 316 2swap cgbase d+ ( off.lo off.hi ) 317; 318 319\ 320\ FFS v2 321\ 322 323: di-db-v2@ ( indx dinode -- db.lo db.hi ) di2_db swap 2* la+ d@ ; 324: di-ib-v2@ ( indx dinode -- db.lo db.hi ) di2_ib swap 2* la+ d@ ; 325: ib-ib-v2@ ( indx iblk -- db.lo db.hi ) 2* la+ d@ ; 326 327\ 328\ LFS v1 329\ 330 331 332\ 333\ File stuff 334\ 335 336niaddr /w* constant narraysize 337 338\ Assume UFS2 dinodes are always biger than UFS1 339ufs2_dinode_SIZEOF buffer: cur-inode 340h# 2000 buffer: indir-block 341create indir-addr -1 , -1 , 342 343\ 344\ Translate a fileblock to a disk block 345\ 346\ We don't do triple indirect blocks. 347\ 348 349\ Get the disk address from a single indirect block 350: ib@ ( indx indir.lo indir.hi -- db.lo db.hi ) 351 2dup indir-addr d@ d<> if ( indx indir.hi indir.lo ) 352 indir-addr d! ( indx ) 353 indir-block ( indx indir-block ) 354 sb-buf fs-bsize l@ ( indx indir-block fs fs-bsize ) 355 indir-addr d@ sb-buf ( indx indir-block fs-bsize indiraddr fs ) 356 fsbtodb ( indx indir-block fs-bsize db.lo db.hi ) 357 strategy 0 ( indx nread 0 ) \ Really should check return value 358 then 359 2drop ( indx ) 360 indir-block ib-ib@ 361; 362 363 364: block-map ( fileblock -- diskblock.lo diskblock.hi ) 365 \ Direct block? 366 dup ndaddr < if ( fileblock ) 367 cur-inode di-db@ exit ( diskblock.lo diskblock.hi ) 368 then ( fileblock ) 369 ndaddr - ( fileblock' ) 370 \ Now we need to check the indirect block 371 dup sb-buf fs_nindir l@ < if ( fileblock' ) 372 0 cur-inode di-ib@ ( fileblock' indir.lo indir.hi ) 373 ib@ exit ( db.lo db.hi ) 374 then 375 dup sb-buf fs_nindir - ( fileblock'' ) 376 \ Now try 2nd level indirect block -- just read twice 377 dup sb-buf fs_nindir l@ dup * >= if ( fileblock'' ) 378 ." block-map: exceeded max file size" cr 379 abort 380 then 381 382 1 cur-inode di-ib@ ( fileblock'' ib.lo ib.hi ) 383 384 \ Get 1st indirect block and find the 2nd indirect block 385 rot dup sb-buf fs_nindir u/mod ( ib2.lo ib2.hi indx2 indx1 ) 386 2swap ib@ ( indx2 ib2.lo ib2.hi ) 387 388 \ Get 2nd indirect block and find our diskblock 389 ib@ ( db.lo db.hi ) 390; 391 392\ 393\ Read file into internal buffer and return pointer and len 394\ 395 3960 value cur-block \ allocated dynamically in ufs-open 3970 value cur-blocksize \ size allocated to cur-block 398create cur-blockno -1 l, -1 l, \ Current disk block. 399-1 value file-blockno \ Current file block no. 4000 value file-offset \ Current file offset, max 4GB. 401 402: buf-read-file ( fs -- buf len ) 403 >r file-offset ( seek ) 404 dup l>d r@ lblkno drop ( seek blk ) 405 dup l>d cur-inode r@ blksize ( seek blk blksize ) 406 over file-blockno <> if ( seek blk blksize ) 407 over to file-blockno 408 swap block-map ( seek blksize fsblk.lo fsblk.hi ) 409 2dup or 0= if ( seek blksize fsblk.lo fsblk.hi ) 410 \ Clear out curblock XXX Why? Idunno. 411 2drop dup 412 cur-block swap erase ( seek blksize ) 413 boot-debug? if ." buf-read-file reading block 0" cr then 414 -1 l>d \ Invalid disk block 415 else 416 \ Call strategy to load the correct block. 417 r@ fsbtodb ( seek blksize dblk.lo dblk.hi ) 418 rot >r cur-block r@ 2over ( seek addr size db.lo db.hi ) 419 strategy r@ <> if ." buf-read-file: short read." cr abort then 420 r> -rot ( seek size db.lo db.hi ) 421 then 422 \ Save the new current disk block number 423 cur-blockno d! ( seek size ) 424 else 425 nip ( seek size ) 426 then 427 \ Now figure out how much we have in the buffer. 428 swap l>d r> blkoff ( size off.lo off.hi ) 429 d>l cur-block over + ( size off buf ) 430 -rot - ( buf siz ) 431; 432 433\ 434\ Read inode into cur-inode -- uses cur-block 435\ 436 437: read-inode-ffs ( inode fs -- ) 438 twiddle 439 440 >r dup r@ ino-to-fsba ( ino fsblk.lo fsblck.hi ) 441 r@ fsbtodb ( ino dblk.lo dblk.hi ) 442 2dup cur-blockno d@ d<> if ( ino dblk.lo dblk.hi ) 443 \ We need to read the block 444 cur-block r@ fs-bsize l@ ( ino dblk.lo dblk.hi addr size ) 445 >r r@ 2over strategy r> <> if ( ino dblk.lo dblk.hi ) 446 ." read-inode - residual" cr abort 447 then 448 2dup cur-blockno d! ( ino dblk.lo dblk.hi ) 449 then 2drop ( ino ) 450 451 r> ino-to-fsbo /dino * ( off ) 452 cur-block + cur-inode /dino move ( ) 453; 454 455: find-inode-sector ( ino fs -- d-dblkno true | false ) 456 >r r@ lfs_ifile l@ r@ read-inode ( ino ) 457 458 r@ lfs_ifpb l@ u/mod ( rem q ) 459 460 r@ lfs_cleansz l@ + 461 r@ lfs_segtabsz l@ + ( rem blkno ) 462 463 r@ fs-bsize l@ um* rot /ifile um* d+ ( dseekp ) 464 465 drop to file-offset r@ buf-read-file ( buf len ) 466 467 /ifile < if r> 2drop false exit then ( buf ) 468 469 if_daddr l@ l>d r> fsbtodb ( daddr ) 470 2dup lfs_unused_daddr l>d d= if 2drop false then 471 true 472; 473 474: read-inode-lfs ( inode fs -- ) 475 twiddle 476 477 >r dup r@ lfs_ifile l@ = if ( ino r: fs ) 478 r@ lfs_idaddr l@ l>d ( ino d-idaddr ) 479 r@ fsbtodb ( ino d-db ) 480 else 481 dup r@ find-inode-sector 0= abort" Could not find inode sector!" 482 then ( ino d-db ) 483 484 2dup cur-blockno d@ d<> if ( ino dblk.lo dblk.hi ) 485 \ We need to read the block 486 cur-block r@ fs-bsize l@ ( ino dblk.lo dblk.hi addr size ) 487 >r r@ 2over strategy r> <> if ( ino dblk.lo dblk.hi ) 488 ." read-inode - residual" cr abort 489 then 490 2dup cur-blockno d! ( ino dblk.lo dblk.hi ) 491 then 2drop ( ino ) 492 493 r@ lfs_inopb l@ ( ino cnt ) 494 swap cur-block begin ( cnt ino p ) 495 tuck di_inumber l@ over <> ( cnt p ino !found? ) 496 while ( cnt p ino ) 497 rot 1- ?dup 0= abort" Could not find inode!" 498 rot /dino + swap -rot ( cnt ino p ) 499 repeat swap ( cnt ino p ) 500 501 cur-inode /dino move ( cnt ino ) 502 503 r> 3drop 504; 505 506\ Identify inode type 507 508: is-dir? ( ufs1_dinode -- is-dir? ) di-mode w@ ifmt and ifdir = ; 509: is-symlink? ( ufs1_dinode -- is-symlink? ) di-mode w@ ifmt and iflnk = ; 510 511\ 512\ Multi-FS initialiation. 513\ 514\ It's way down here so all the fs-specific routines have already been defined. 515\ 516 517: init-ffs-common ( -- ) 518 ' fs_SIZEOF to fs-size 519 ' fs_bsize to fs-bsize 520 ' ffs-dblksize to blksize 521 ' read-inode-ffs to read-inode 522 ' ffs-fsbtodb to fsbtodb 523 ' ffs-lblkno to lblkno 524 ' ffs-blkoff to blkoff 525; 526 527 528: ffs-oldcompat ( -- ) 529 \ Make sure old ffs values in sb-buf are sane 530 sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l! 531 sb-buf fs_old_interleave dup l@ 1 max swap l! 532 sb-buf fs_old_postblformat l@ fs_42postblfmt = if 533 8 sb-buf fs_old_nrpos l! 534 then 535 sb-buf fs_old_inodefmt l@ fs_44inodefmt < if 536 sb-buf fs-bsize l@ 537 dup ndaddr um* 1 d- sb-buf fs_maxfilesize d! 538 niaddr 0 ?do 539 sb-buf fs_nindir l@ * dup ( sizebp sizebp ) 540 sb-buf fs_maxfilesize dup d@ ( sizebp sizebp *mxfs mxfs.lo mxfs.hi ) 541 2over drop l>d d+ 2swap d! ( sizebp ) 542 loop drop ( ) 543 sb-buf dup fs_bmask l@ invert l>d rot fs_qbmask d! 544 sb-buf dup fs_fmask l@ invert l>d rot fs_qfmask d! 545 then 546; 547 548 549: init-ffs-v1 ( -- ) 550 init-ffs-common 551 ' di1_size to di-size 552 ' di1_mode to di-mode 553 ' ufs1_dinode_SIZEOF to /dino 554 ' cgstart-ufs1 to cgstart 555 ' di-db-v1@ to di-db@ 556 ' di-ib-v1@ to di-ib@ 557 ' ib-ib-v1@ to ib-ib@ 558 ffs-oldcompat 559; 560 561: init-ffs-v2 ( -- ) 562 init-ffs-common 563 ' di2_size to di-size 564 ' di2_mode to di-mode 565 ' ufs2_dinode_SIZEOF to /dino 566 ' cgbase to cgstart 567 ' di-db-v2@ to di-db@ 568 ' di-ib-v2@ to di-ib@ 569 ' ib-ib-v2@ to ib-ib@ 570; 571 572: init-lfs-common ( -- ) 573 ' dlfs_SIZEOF to fs-size 574 ' di1_size to di-size 575 ' di1_mode to di-mode 576 ' ufs1_dinode_SIZEOF to /dino 577 ' cgbase to cgstart 578 ' di-db-v1@ to di-db@ 579 ' di-ib-v1@ to di-ib@ 580 ' ib-ib-v1@ to ib-ib@ 581 ' lfs-dblksize to blksize 582 ' read-inode-lfs to read-inode 583 ' lfs-fsbtodb to fsbtodb 584 ' lfs-lblkno to lblkno 585 ' lfs-blkoff to blkoff 586; 587 588: init-lfs-v1 ( -- ) 589 init-lfs-common 590 ' lfs_ibsize to fs-bsize 591 ' ifile_v1_SIZEOF to /ifile 592 ' if1_daddr to if_daddr 593; 594 595: init-lfs-v2 ( -- ) 596 init-lfs-common 597 ' lfs_bsize to fs-bsize 598 ' ifile_SIZEOF to /ifile 599 ' if2_daddr to if_daddr 600; 601 602 603: fs-magic? ( sb -- is-ufs? ) 604 \ The LFS magic is the first word in the superblock 605 dup lfs_magic l@ lfs_magic_value = if 606 dup lfs_version l@ case ( sb sel ) 607 1 of init-lfs-v1 drop true exit endof 608 2 of init-lfs-v2 drop true exit endof 609 ." Invalid LFS version." \ Try FFS. 610 endcase 611 then ( sb ) 612 \ The FFS magic is at the end of the superblock 613 fs_magic l@ case 614 fs1_magic_value of init-ffs-v1 true endof 615 fs2_magic_value of init-ffs-v2 true endof 616 false swap \ Return false 617 endcase 618; 619 620 621 622\ 623\ Hunt for directory entry: 624\ 625\ repeat 626\ load a buffer 627\ while entries do 628\ if entry == name return 629\ next entry 630\ until no buffers 631\ 632 633: search-dir-block ( str len buf len -- ino | 0 ) 634 2dup + nip ( str len buf bufend ) 635 swap 2swap rot ( bufend str len direct ) 636 begin dup 4 pick < while ( bufend str len direct ) 637 dup d_ino l@ 0<> if ( bufend str len direct ) 638 boot-debug? if 639 \ Print the current file name 640 dup dup d_name swap d_namlen c@ type cr 641 then 642 2dup d_namlen c@ = if ( bufend str len direct ) 643 dup d_name 2over ( bufend str len direct dname str len ) 644 comp 0= if ( bufend str len direct ) 645 \ Found it -- return inode 646 d_ino l@ nip nip nip ( dino ) 647 boot-debug? if ." Found it" cr then 648 exit ( dino ) 649 then 650 then ( bufend str len direct ) 651 then ( bufend str len direct ) 652 dup d_reclen w@ + ( bufend str len nextdirect ) 653 repeat 654 2drop 2drop 0 655; 656 657 658: search-directory ( str len -- ino | 0 ) 659 0 to file-offset 660 begin 661 file-offset cur-inode di-size d@ drop < 662 while ( str len ) 663 \ Read a directory block 664 sb-buf buf-read-file ( str len buf len ) 665 dup 0= if ." search-directory: buf-read-file zero len" cr abort then 666 dup file-offset + to file-offset ( str len buf len ) 667 668 2over 2swap search-dir-block ?dup if 669 \ Found it 670 nip nip exit 671 then ( str len ) 672 repeat 673 2drop 2drop 0 ( 0 ) 674; 675 676: read-super ( sector -- ) 677 0 " seek" boot-ihandle $call-method -1 = if 678 ." Seek failed" cr abort 679 then 680 sb-buf sbsize " read" boot-ihandle $call-method 681 dup sbsize <> if 682 ." Read of superblock failed" cr 683 ." requested" space sbsize . 684 ." actual" space . cr 685 abort 686 else 687 drop 688 then 689; 690 691: ufs-open ( bootpath len -- ) 692 boot-ihandle -1 = if 693 2dup + 0 swap c! \ Nul terminate. 694 over cif-open dup 0= if ( boot-path len ihandle? ) 695 ." Could not open device" space type cr 696 abort 697 then ( boot-path len ihandle ) 698 to boot-ihandle \ Save ihandle to boot device 699 then 700 2drop 701 702 boot-debug? if ." Try a RAID superblock read" cr then 703 rf_protected dup to raid-offset 704 dev_bsize * sboff + read-super 705 sb-buf fs-magic? invert if 706 boot-debug? if ." Try a normal superblock read" cr then 707 0 to raid-offset 708 sboff read-super 709 sb-buf fs-magic? invert abort" Invalid superblock magic" 710 then 711 sb-buf fs-bsize l@ dup maxbsize > if 712 ." Superblock bsize" space . ." too large" cr 713 abort 714 then 715 dup fs-size < if 716 ." Superblock bsize < size of superblock" cr 717 abort 718 then 719 dup to cur-blocksize alloc-mem to cur-block \ Allocate cur-block 720 boot-debug? if ." ufs-open complete" cr then 721; 722 723: ufs-close ( -- ) 724 boot-ihandle dup -1 <> if 725 cif-close -1 to boot-ihandle 726 then 727 cur-block 0<> if 728 cur-block cur-blocksize free-mem 729 then 730; 731 732: boot-path ( -- boot-path ) 733 " bootpath" chosen-phandle get-package-property if 734 ." Could not find bootpath in /chosen" cr 735 abort 736 else 737 decode-string 2swap 2drop 738 then 739; 740 741: boot-args ( -- boot-args ) 742 " bootargs" chosen-phandle get-package-property if 743 ." Could not find bootargs in /chosen" cr 744 abort 745 else 746 decode-string 2swap 2drop 747 then 748; 749 7502000 buffer: boot-path-str 7512000 buffer: boot-path-tmp 752 753: split-path ( path len -- right len left len ) 754\ Split a string at the `/' 755 begin 756 dup -rot ( oldlen right len left ) 757 ascii / left-parse-string ( oldlen right len left len ) 758 dup 0<> if 4 roll drop exit then 759 2drop ( oldlen right len ) 760 rot over = ( right len diff ) 761 until 762; 763 764: find-file ( load-file len -- ) 765 rootino dup sb-buf read-inode ( load-file len pino ) 766 -rot ( pino load-file len ) 767 \ 768 \ For each path component 769 \ 770 begin split-path dup 0<> while ( pino right len left len ) 771 cur-inode is-dir? not if ." Inode not directory" cr abort then 772 boot-debug? if ." Looking for" space 2dup type space ." in directory..." cr then 773 search-directory ( pino right len ino|false ) 774 dup 0= abort" Bad path" ( pino right len cino ) 775 sb-buf read-inode ( pino right len ) 776 cur-inode is-symlink? if \ Symlink -- follow the damn thing 777 \ Save path in boot-path-tmp 778 boot-path-tmp strmov ( pino new-right len ) 779 780 \ Now deal with symlink XXX drop high word of linklen 781 cur-inode di-size d@ drop ( pino right len linklen.lo ) 782 dup sb-buf fs_maxsymlinklen l@ ( pino right len linklen linklen maxlinklen ) 783 < if \ Now join the link to the path 784 0 cur-inode di-db@ drop ( pino right len linklen linkp ) 785 swap boot-path-str strmov ( pino right len new-linkp linklen ) 786 else \ Read file for symlink -- Ugh 787 \ Read link into boot-path-str 788 boot-path-str dup sb-buf fs-bsize l@ 789 0 block-map ( pino right len linklen boot-path-str bsize blockno.lo blockno.hi ) 790 strategy drop swap ( pino right len boot-path-str linklen ) 791 then ( pino right len linkp linklen ) 792 \ Concatenate the two paths 793 strcat ( pino new-right newlen ) 794 swap dup c@ ascii / = if \ go to root inode? 795 rot drop rootino -rot ( rino len right ) 796 then 797 rot dup sb-buf read-inode ( len right pino ) 798 -rot swap ( pino right len ) 799 then ( pino right len ) 800 repeat 801 2drop drop 802; 803 804: .read-file-msg ( addr xxx siz -- addr xxx siz ) 805 boot-debug? if 806 ." Copying " dup . ." bytes to " 3 pick . cr 807 then 808; 809 810: read-file ( addr size -- ) 811 noop \ In case we need to debug this 812 \ Read x bytes from a file to buffer 813 begin dup 0> while 814 file-offset cur-inode di-size d@ drop > if 815 ." read-file EOF exceeded" cr abort 816 then 817 sb-buf buf-read-file ( addr size buf len ) 818 819 .read-file-msg 820 821 \ Copy len bytes to addr XXX min ( len, size ) ? 822 2over drop 3dup swap move drop ( addr size buf len ) 823 824 dup file-offset + to file-offset ( addr size buf len ) 825 826 nip tuck - -rot + swap ( addr' size' ) 827 repeat 828 2drop 829; 830 831" load-base " evaluate constant loader-base 832 833: load-file-signon ( load-file len boot-path len -- load-file len boot-path len ) 834 ." Loading file" space 2over type cr ." from device" space 2dup type cr 835; 836 837: load-file ( load-file len boot-path len -- load-base ) 838 boot-debug? if load-file-signon then 839 840 ufs-open ( load-file len ) 841 find-file ( ) 842 843 \ 844 \ Now we've found the file we should read it in in one big hunk 845 \ 846 847 cur-inode di-size d@ if ." File len >2GB!" cr abort then 848\ dup " to file-size " evaluate ( file-len ) \ Wassthis? 849 boot-debug? if 850 ." Loading " dup . ." bytes of file..." cr 851 then 852 0 to file-offset 853 -1 to file-blockno 854 loader-base ( buf-len addr ) 855 tuck swap read-file ( addr ) 856 ufs-close ( addr ) 857; 858 859: do-boot ( bootfile -- ) 860 ." NetBSD IEEE 1275 Multi-FS Bootblock" cr 861 boot-path load-file ( -- load-base ) 862 dup 0<> if " init-program " evaluate then 863; 864 865 866boot-args ascii V strchr 0<> swap drop if 867 true to boot-debug? 868then 869 870boot-args ascii D strchr 0= swap drop if 871 " /ofwboot" do-boot 872then exit 873 874 875