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