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