bootblk.fth revision 1.9
1\ $NetBSD: bootblk.fth,v 1.9 2009/10/19 18:12:37 snj 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 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: strcmp ( s1 l1 s2 l2 -- true:false ) 75 rot tuck <> if 3drop false exit then 76 comp 0= 77; 78 79\ Move string into buffer 80 81: strmov ( s1 l1 d -- d l1 ) 82 dup 2over swap -rot ( s1 l1 d s1 d l1 ) 83 move ( s1 l1 d ) 84 rot drop swap 85; 86 87\ Move s1 on the end of s2 and return the result 88 89: strcat ( s1 l1 s2 l2 -- d tot ) 90 2over swap ( s1 l1 s2 l2 l1 s1 ) 91 2over + rot ( s1 l1 s2 l2 s1 d l1 ) 92 move rot + ( s1 s2 len ) 93 rot drop ( s2 len ) 94; 95 96: strchr ( s1 l1 c -- s2 l2 ) 97 begin 98 dup 2over 0= if ( s1 l1 c c s1 ) 99 2drop drop exit then 100 c@ = if ( s1 l1 c ) 101 drop exit then 102 -rot /c - swap ca1+ ( c l2 s2 ) 103 swap rot 104 again 105; 106 107 108: cstr ( ptr -- str len ) 109 dup 110 begin dup c@ 0<> while + repeat 111 over - 112; 113 114\ 115\ BSD FFS parameters 116\ 117 118fload assym.fth.h 119 120sbsize buffer: sb-buf 121-1 value boot-ihandle 122dev_bsize value bsize 1230 value raid-offset \ Offset if it's a raid-frame partition 124false value force-raid \ Force reads from raid offset 125 126: strategy ( addr size start -- nread ) 127 raid-offset + bsize * 0 " seek" boot-ihandle $call-method 128 -1 = if 129 ." strategy: Seek failed" cr 130 abort 131 then 132 " read" boot-ihandle $call-method 133; 134 135\ 136\ Cylinder group macros 137\ 138 139: cgbase ( cg fs -- cgbase ) fs_fpg l@ * ; 140: cgstart ( cg fs -- cgstart ) 141 2dup fs_old_cgmask l@ not and ( cg fs stuff -- ) 142 over fs_old_cgoffset l@ * -rot ( stuffcg fs -- ) 143 cgbase + 144; 145: cgdmin ( cg fs -- 1st-data-block ) dup fs_dblkno l@ -rot cgstart + ; 146: cgimin ( cg fs -- inode-block ) dup fs_iblkno l@ -rot cgstart + ; 147: cgsblock ( cg fs -- super-block ) dup fs_sblkno l@ -rot cgstart + ; 148: cgstod ( cg fs -- cg-block ) dup fs_cblkno l@ -rot cgstart + ; 149 150\ 151\ Block and frag position macros 152\ 153 154: blkoff ( pos fs -- off ) fs_qbmask x@ and ; 155: fragoff ( pos fs -- off ) fs_qfmask x@ and ; 156: lblktosize ( blk fs -- off ) fs_bshift l@ << ; 157: lblkno ( pos fs -- off ) fs_bshift l@ >> ; 158: numfrags ( pos fs -- off ) fs_fshift l@ >> ; 159: blkroundup ( pos fs -- off ) dup fs_bmask l@ -rot fs_qbmask x@ + and ; 160: fragroundup ( pos fs -- off ) dup fs_fmask l@ -rot fs_qfmask x@ + and ; 161\ : fragroundup ( pos fs -- off ) tuck fs_qfmask x@ + swap fs_fmask l@ and ; 162: fragstoblks ( pos fs -- off ) fs_fragshift l@ >> ; 163: blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ; 164: fragnum ( fsb fs -- off ) fs_frag l@ 1- and ; 165: blknum ( fsb fs -- off ) fs_frag l@ 1- not and ; 166: dblksize ( lbn dino fs -- size ) 167 -rot ( fs lbn dino ) 168 di_size x@ ( fs lbn di_size ) 169 -rot dup 1+ ( di_size fs lbn lbn+1 ) 170 2over fs_bshift l@ ( di_size fs lbn lbn+1 di_size b_shift ) 171 rot swap << >= ( di_size fs lbn res1 ) 172 swap ndaddr >= or if ( di_size fs ) 173 swap drop fs_bsize l@ exit ( size ) 174 then tuck blkoff swap fragroundup ( size ) 175; 176 177 178: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ; 179: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ; 180: ino-to-fsba ( ino fs -- ba ) \ Need to remove the stupid stack diags someday 181 2dup ( ino fs ino fs ) 182 ino-to-cg ( ino fs cg ) 183 over ( ino fs cg fs ) 184 cgimin ( ino fs inode-blk ) 185 -rot ( inode-blk ino fs ) 186 tuck ( inode-blk fs ino fs ) 187 fs_ipg l@ ( inode-blk fs ino ipg ) 188 mod ( inode-blk fs mod ) 189 swap ( inode-blk mod fs ) 190 dup ( inode-blk mod fs fs ) 191 fs_inopb l@ ( inode-blk mod fs inopb ) 192 rot ( inode-blk fs inopb mod ) 193 swap ( inode-blk fs mod inopb ) 194 / ( inode-blk fs div ) 195 swap ( inode-blk div fs ) 196 blkstofrags ( inode-blk frag ) 197 + 198; 199: fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ; 200 201\ 202\ File stuff 203\ 204 205niaddr /w* constant narraysize 206 207struct 208 8 field >f_ihandle \ device handle 209 8 field >f_seekp \ seek pointer 210 8 field >f_fs \ pointer to super block 211 ufs1_dinode_SIZEOF field >f_di \ copy of on-disk inode 212 8 field >f_buf \ buffer for data block 213 4 field >f_buf_size \ size of data block 214 4 field >f_buf_blkno \ block number of data block 215constant file_SIZEOF 216 217file_SIZEOF buffer: the-file 218sb-buf the-file >f_fs x! 219 220ufs1_dinode_SIZEOF buffer: cur-inode 221h# 2000 buffer: indir-block 222-1 value indir-addr 223 224\ 225\ Translate a fileblock to a disk block 226\ 227\ We only allow single indirection 228\ 229 230: block-map ( fileblock -- diskblock ) 231 \ Direct block? 232 dup ndaddr < if ( fileblock ) 233 cur-inode di_db ( arr-indx arr-start ) 234 swap la+ l@ exit ( diskblock ) 235 then ( fileblock ) 236 ndaddr - ( fileblock' ) 237 \ Now we need to check the indirect block 238 dup sb-buf fs_nindir l@ < if ( fileblock' ) 239 cur-inode di_ib l@ dup ( fileblock' indir-block indir-block ) 240 indir-addr <> if ( fileblock' indir-block ) 241 to indir-addr ( fileblock' ) 242 indir-block ( fileblock' indir-block ) 243 sb-buf dup fs_bsize l@ ( fileblock' indir-block fs fs_bsize ) 244 swap indir-addr swap ( fileblock' indir-block fs_bsize indiraddr fs ) 245 fsbtodb ( fileblock' indir-block fs_bsize db ) 246 strategy ( fileblock' nread ) 247 then ( fileblock' nread|indir-block ) 248 drop \ Really should check return value 249 indir-block swap la+ l@ exit 250 then 251 dup sb-buf fs_nindir - ( fileblock'' ) 252 \ Now try 2nd level indirect block -- just read twice 253 dup sb-buf fs_nindir l@ dup * < if ( fileblock'' ) 254 cur-inode di_ib 1 la+ l@ ( fileblock'' indir2-block ) 255 to indir-addr ( fileblock'' ) 256 \ load 1st level indir block 257 indir-block ( fileblock'' indir-block ) 258 sb-buf dup fs_bsize l@ ( fileblock'' indir-block fs fs_bsize ) 259 swap indir-addr swap ( fileblock'' indir-block fs_bsize indiraddr fs ) 260 fsbtodb ( fileblock'' indir-block fs_bsize db ) 261 strategy ( fileblock'' nread ) 262 drop ( fileblock'' ) 263 dup sb-buf fs_nindir / ( fileblock'' indir-offset ) 264 indir-block swap la+ l@ ( fileblock'' indirblock ) 265 to indir-addr ( fileblock'' ) 266 \ load 2nd level indir block 267 indir-block ( fileblock'' indir-block ) 268 sb-buf dup fs_bsize l@ ( fileblock'' indir-block fs fs_bsize ) 269 swap indir-addr swap ( fileblock'' indir-block fs_bsize indiraddr fs ) 270 fsbtodb ( fileblock'' indir-block fs_bsize db ) 271 strategy ( fileblock'' nread ) 272 drop ( fileblock'' ) 273 sb-buf fs_nindir l@ mod indir-block swap la+ l@ exit 274 then 275 ." block-map: exceeded max file size" cr 276 abort 277; 278 279\ 280\ Read file into internal buffer and return pointer and len 281\ 282 2830 value cur-block \ allocated dynamically in ufs-open 2840 value cur-blocksize \ size of cur-block 285-1 value cur-blockno 2860 value cur-offset 287 288: buf-read-file ( fs -- len buf ) 289 cur-offset swap ( seekp fs ) 290 2dup blkoff ( seekp fs off ) 291 -rot 2dup lblkno ( off seekp fs block ) 292 swap 2dup cur-inode ( off seekp block fs block fs inop ) 293 swap dblksize ( off seekp block fs size ) 294 rot dup cur-blockno ( off seekp fs size block block cur ) 295 <> if ( off seekp fs size block ) 296 block-map ( off seekp fs size diskblock ) 297 dup 0= if ( off seekp fs size diskblock ) 298 over cur-block swap 0 fill ( off seekp fs size diskblock ) 299 boot-debug? if ." buf-read-file fell off end of file" cr then 300 else 301 2dup sb-buf fsbtodb cur-block -rot strategy ( off seekp fs size diskblock nread ) 302 rot 2dup <> if " buf-read-file: short read." cr abort then 303 then ( off seekp fs diskblock nread size ) 304 nip nip ( off seekp fs size ) 305 else ( off seekp fs size block block cur ) 306 2drop ( off seekp fs size ) 307 then 308\ dup cur-offset + to cur-offset \ Set up next xfer -- not done 309 nip nip swap - ( len ) 310 cur-block 311; 312 313\ 314\ Read inode into cur-inode -- uses cur-block 315\ 316 317: read-inode ( inode fs -- ) 318 twiddle ( inode fs -- inode fs ) 319 320 cur-block ( inode fs -- inode fs buffer ) 321 322 over ( inode fs buffer -- inode fs buffer fs ) 323 fs_bsize l@ ( inode fs buffer -- inode fs buffer size ) 324 325 2over ( inode fs buffer size -- inode fs buffer size inode fs ) 326 2over ( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size ) 327 2swap tuck ( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs ) 328 329 ino-to-fsba ( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba ) 330 swap ( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs ) 331 fsbtodb ( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db ) 332 333 dup to cur-blockno ( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart ) 334 strategy ( inode fs buffer size buffer size dstart -- inode fs buffer size nread ) 335 <> if ." read-inode - residual" cr abort then 336 dup 2over ( inode fs buffer -- inode fs buffer buffer inode fs ) 337 ino-to-fsbo ( inode fs buffer -- inode fs buffer buffer fsbo ) 338 ufs1_dinode_SIZEOF * + ( inode fs buffer buffer fsbo -- inode fs buffer dinop ) 339 cur-inode ufs1_dinode_SIZEOF move ( inode fs buffer dinop -- inode fs buffer ) 340 \ clear out the old buffers 341 drop ( inode fs buffer -- inode fs ) 342 2drop 343; 344 345\ Identify inode type 346 347: is-dir? ( ufs1_dinode -- true:false ) di_mode w@ ifmt and ifdir = ; 348: is-symlink? ( ufs1_dinode -- true:false ) di_mode w@ ifmt and iflnk = ; 349 350 351 352\ 353\ Hunt for directory entry: 354\ 355\ repeat 356\ load a buffer 357\ while entries do 358\ if entry == name return 359\ next entry 360\ until no buffers 361\ 362 363: search-directory ( str len -- ino|0 ) 364 0 to cur-offset 365 begin cur-offset cur-inode di_size x@ < while ( str len ) 366 sb-buf buf-read-file ( str len len buf ) 367 over 0= if ." search-directory: buf-read-file zero len" cr abort then 368 swap dup cur-offset + to cur-offset ( str len buf len ) 369 2dup + nip ( str len buf bufend ) 370 swap 2swap rot ( bufend str len buf ) 371 begin dup 4 pick < while ( bufend str len buf ) 372 dup d_ino l@ 0<> if ( bufend str len buf ) 373 boot-debug? if dup dup d_name swap d_namlen c@ type cr then 374 2dup d_namlen c@ = if ( bufend str len buf ) 375 dup d_name 2over ( bufend str len buf dname str len ) 376 comp 0= if ( bufend str len buf ) 377 \ Found it -- return inode 378 d_ino l@ nip nip nip ( dino ) 379 boot-debug? if ." Found it" cr then 380 exit ( dino ) 381 then 382 then ( bufend str len buf ) 383 then ( bufend str len buf ) 384 dup d_reclen w@ + ( bufend str len nextbuf ) 385 repeat 386 drop rot drop ( str len ) 387 repeat 388 2drop 2drop 0 ( 0 ) 389; 390 391: ffs_oldcompat ( -- ) 392\ Make sure old ffs values in sb-buf are sane 393 sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l! 394 sb-buf fs_old_interleave dup l@ 1 max swap l! 395 sb-buf fs_old_postblformat l@ fs_42postblfmt = if 396 8 sb-buf fs_old_nrpos l! 397 then 398 sb-buf fs_old_inodefmt l@ fs_44inodefmt < if 399 sb-buf fs_bsize l@ 400 dup ndaddr * 1- sb-buf fs_maxfilesize x! 401 niaddr 0 ?do 402 sb-buf fs_nindir l@ * dup ( sizebp sizebp -- ) 403 sb-buf fs_maxfilesize dup x@ ( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- ) 404 rot ( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- ) 405 + ( sizebp *fs_maxfilesize new_fs_maxfilesize -- ) 406 swap x! ( sizebp -- ) 407 loop drop ( -- ) 408 sb-buf dup fs_bmask l@ not swap fs_qbmask x! 409 sb-buf dup fs_fmask l@ not swap fs_qfmask x! 410 then 411; 412 413: read-super ( sector -- ) 4140 " seek" boot-ihandle $call-method 415 -1 = if 416 ." Seek failed" cr 417 abort 418 then 419 sb-buf sbsize " read" boot-ihandle $call-method 420 dup sbsize <> if 421 ." Read of superblock failed" cr 422 ." requested" space sbsize . 423 ." actual" space . cr 424 abort 425 else 426 drop 427 then 428; 429 430: ufs-open ( bootpath,len -- ) 431 boot-ihandle -1 = if 432 over cif-open dup 0= if ( boot-path len ihandle? ) 433 ." Could not open device" space type cr 434 abort 435 then ( boot-path len ihandle ) 436 to boot-ihandle \ Save ihandle to boot device 437 then 2drop 438 force-raid if 439 boot-debug? if ." Force RAID superblock read" cr then 440 rf_protected dup to raid-offset 441 dev_bsize * sboff + read-super 442 sb-buf fs_magic l@ fs_magic_value <> if 443 ." Invalid superblock magic" cr 444 abort 445 then 446 else 447 boot-debug? if ." Normal superblock read" cr then 448 sboff read-super 449 sb-buf fs_magic l@ fs_magic_value <> if 450 boot-debug? if ." RAID superblock read" cr then 451 true to force-raid 452 rf_protected dup to raid-offset 453 dev_bsize * sboff + read-super 454 sb-buf fs_magic l@ fs_magic_value <> if 455 ." Invalid superblock magic" cr 456 abort 457 then 458 then 459 then 460 sb-buf fs_bsize l@ dup maxbsize > if 461 ." Superblock bsize" space . ." too large" cr 462 abort 463 then 464 dup fs_SIZEOF < if 465 ." Superblock bsize < size of superblock" cr 466 abort 467 then 468 ffs_oldcompat ( fs_bsize -- fs_bsize ) 469 dup to cur-blocksize alloc-mem to cur-block \ Allocate cur-block 470 boot-debug? if ." ufs-open complete" cr then 471; 472 473: ufs-close ( -- ) 474 boot-ihandle dup -1 <> if 475 cif-close -1 to boot-ihandle 476 then 477 cur-block 0<> if 478 cur-block cur-blocksize free-mem 479 then 480; 481 482: boot-path ( -- boot-path ) 483 " bootpath" chosen-phandle get-package-property if 484 ." Could not find bootpath in /chosen" cr 485 abort 486 else 487 decode-string 2swap 2drop 488 then 489; 490 491: boot-args ( -- boot-args ) 492 " bootargs" chosen-phandle get-package-property if 493 ." Could not find bootargs in /chosen" cr 494 abort 495 else 496 decode-string 2swap 2drop 497 then 498; 499 5002000 buffer: boot-path-str 5012000 buffer: boot-path-tmp 502 503: split-path ( path len -- right len left len ) 504\ Split a string at the `/' 505 begin 506 dup -rot ( oldlen right len left ) 507 ascii / left-parse-string ( oldlen right len left len ) 508 dup 0<> if 4 roll drop exit then 509 2drop ( oldlen right len ) 510 rot over = ( right len diff ) 511 until 512; 513 514: find-file ( load-file len -- ) 515 rootino dup sb-buf read-inode ( load-file len -- load-file len ino ) 516 -rot ( load-file len ino -- pino load-file len ) 517 \ 518 \ For each path component 519 \ 520 begin split-path dup 0<> while ( pino right len left len -- ) 521 cur-inode is-dir? not if ." Inode not directory" cr false exit then 522 boot-debug? if ." Looking for" space 2dup type space ." in directory..." cr then 523 search-directory ( pino right len left len -- pino right len ino|false ) 524 dup 0= if ." Bad path" cr abort then ( pino right len cino ) 525 sb-buf read-inode ( pino right len ) 526 cur-inode is-symlink? if \ Symlink -- follow the damn thing 527 \ Save path in boot-path-tmp 528 boot-path-tmp strmov ( pino new-right len ) 529 530 \ Now deal with symlink 531 cur-inode di_size x@ ( pino right len linklen ) 532 dup sb-buf fs_maxsymlinklen l@ ( pino right len linklen linklen maxlinklen ) 533 < if \ Now join the link to the path 534 cur-inode di_db l@ ( pino right len linklen linkp ) 535 swap boot-path-str strmov ( pino right len new-linkp linklen ) 536 else \ Read file for symlink -- Ugh 537 \ Read link into boot-path-str 538 boot-path-str dup sb-buf fs_bsize l@ 539 0 block-map ( pino right len linklen boot-path-str bsize blockno ) 540 strategy drop swap ( pino right len boot-path-str linklen ) 541 then ( pino right len linkp linklen ) 542 \ Concatenate the two paths 543 strcat ( pino new-right newlen ) 544 swap dup c@ ascii / = if \ go to root inode? 545 rot drop rootino -rot ( rino len right ) 546 then 547 rot dup sb-buf read-inode ( len right pino ) 548 -rot swap ( pino right len ) 549 then ( pino right len ) 550 repeat 551 2drop drop 552 true 553; 554 555: read-file ( size addr -- ) 556 \ Read x bytes from a file to buffer 557 begin over 0> while 558 cur-offset cur-inode di_size x@ > if ." read-file EOF exceeded" cr abort then 559 sb-buf buf-read-file ( size addr len buf ) 560 over 2over drop swap ( size addr len buf addr len ) 561 move ( size addr len ) 562 dup cur-offset + to cur-offset ( size len newaddr ) 563 tuck + ( size len newaddr ) 564 -rot - swap ( newaddr newsize ) 565 repeat 566 2drop 567; 568 569\ 570\ According to the 1275 addendum for SPARC processors: 571\ Default load-base is 0x4000. At least 0x8.0000 or 572\ 512KB must be available at that address. 573\ 574\ The Fcode bootblock can take up up to 8KB (O.K., 7.5KB) 575\ so load programs at 0x4000 + 0x2000=> 0x6000 576\ 577 578h# 6000 constant loader-base 579 580\ 581\ Elf support -- find the load addr 582\ 583 584: is-elf? ( hdr -- res? ) h# 7f454c46 = ; 585 586\ 587\ Finally we finish it all off 588\ 589 590: load-file-signon ( load-file len boot-path len -- load-file len boot-path len ) 591 ." Loading file" space 2over type cr ." from device" space 2dup type cr 592; 593 594: load-file-print-size ( size -- size ) 595 ." Loading" space dup . space ." bytes of file..." cr 596; 597 598: load-file ( load-file len boot-path len -- load-base ) 599 boot-debug? if load-file-signon then 600 the-file file_SIZEOF 0 fill \ Clear out file structure 601 \ copy "load-file len boot-path len" in case we need to set "force-raid" 602 2over 2over ( load-file len boot-path len load-file len boot-path len ) 603 ufs-open ( load-file len boot-path len load-file len ) 604 find-file not if ( load-file len boot-path len ) 605 force-raid not if 606 true to force-raid ( ) 607 ufs-close 608 2drop 2drop drop ( load-file len boot-path len ) 609 ufs-open ( load-file len ) 610 find-file ( true:false ) 611 drop 612 else 613 abort 614 then 615 else 616 \ We didn't set "force-raid", discard the copies 617 2drop 2drop ( ) 618 then 619 620 \ 621 \ Now we've found the file we should read it in in one big hunk 622 \ 623 624 cur-inode di_size x@ ( file-len ) 625 dup " to file-size" evaluate ( file-len ) 626 boot-debug? if load-file-print-size then 627 0 to cur-offset 628 loader-base ( buf-len addr ) 629 2dup read-file ( buf-len addr ) 630 ufs-close ( buf-len addr ) 631 dup is-elf? if ." load-file: not an elf executable" cr abort then 632 633 \ Luckily the prom should be able to handle ELF executables by itself 634 635 nip ( addr ) 636; 637 638: do-boot ( bootfile -- ) 639 ." NetBSD IEEE 1275 Bootblock" cr 640 boot-path load-file ( -- load-base ) 641 dup 0<> if " to load-base init-program" evaluate then 642; 643 644 645boot-args ascii V strchr 0<> swap drop if 646 true to boot-debug? 647then 648 649boot-args ascii D strchr 0= swap drop if 650 " /ofwboot" do-boot 651then exit 652 653 654