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