1\ $OpenBSD: bootblk.fth,v 1.4 2009/09/03 16:39:37 jsing Exp $ 2\ $NetBSD: bootblk.fth,v 1.3 2001/08/15 20:10:24 eeh 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 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\ 3. All advertising materials mentioning features or use of this software 21\ must display the following acknowledgement: 22\ This product includes software developed by Eduardo Horvath. 23\ 4. The name of the author may not be used to endorse or promote products 24\ derived from this software without specific prior written permission 25\ 26\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27\ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28\ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29\ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30\ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31\ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32\ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33\ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34\ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35\ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36\ 37 38offset16 39hex 40headers 41 42false value boot-debug? 43 44\ 45\ First some housekeeping: Open /chosen and set up vectors into 46\ client-services 47 48" /chosen" find-package 0= if ." Cannot find /chosen" 0 then 49constant chosen-phandle 50 51" /openprom/client-services" find-package 0= if 52 ." Cannot find client-services" cr abort 53then constant cif-phandle 54 55defer cif-claim ( align size virt -- base ) 56defer cif-release ( size virt -- ) 57defer cif-open ( cstr -- ihandle|0 ) 58defer cif-close ( ihandle -- ) 59defer cif-read ( len adr ihandle -- #read ) 60defer cif-seek ( low high ihandle -- -1|0|1 ) 61\ defer cif-peer ( phandle -- phandle ) 62\ defer cif-getprop ( len adr cstr phandle -- ) 63 64: find-cif-method ( method,len -- xf ) 65 cif-phandle find-method drop 66; 67 68" claim" find-cif-method to cif-claim 69" open" find-cif-method to cif-open 70" close" find-cif-method to cif-close 71" read" find-cif-method to cif-read 72" seek" find-cif-method to cif-seek 73 74: twiddle ( -- ) ." ." ; \ Need to do this right. Just spit out periods for now. 75 76\ 77\ Support routines 78\ 79 80: strcmp ( s1 l1 s2 l2 -- true:false ) 81 rot tuck <> if 3drop false exit then 82 comp 0= 83; 84 85\ Move string into buffer 86 87: strmov ( s1 l1 d -- d l1 ) 88 dup 2over swap -rot ( s1 l1 d s1 d l1 ) 89 move ( s1 l1 d ) 90 rot drop swap 91; 92 93\ Move s1 on the end of s2 and return the result 94 95: strcat ( s1 l1 s2 l2 -- d tot ) 96 2over swap ( s1 l1 s2 l2 l1 s1 ) 97 2over + rot ( s1 l1 s2 l2 s1 d l1 ) 98 move rot + ( s1 s2 len ) 99 rot drop ( s2 len ) 100; 101 102: strchr ( s1 l1 c -- s2 l2 ) 103 begin 104 dup 2over 0= if ( s1 l1 c c s1 ) 105 2drop drop exit then 106 c@ = if ( s1 l1 c ) 107 drop exit then 108 -rot /c - swap ca1+ ( c l2 s2 ) 109 swap rot 110 again 111; 112 113 114: cstr ( ptr -- str len ) 115 dup 116 begin dup c@ 0<> while + repeat 117 over - 118; 119 120\ 121\ BSD FFS parameters 122\ 123 124fload assym.fth.h 125 126sbsize buffer: sb-buf 127-1 value boot-ihandle 128dev_bsize value bsize 1290 value raid-offset \ Offset if it's a raid-frame partition 130 131: strategy ( addr size start -- nread ) 132 raid-offset + bsize * 0 " seek" boot-ihandle $call-method 133 -1 = if 134 ." strategy: Seek failed" cr 135 abort 136 then 137 " read" boot-ihandle $call-method 138; 139 140\ 141\ Cylinder group macros 142\ 143 144: cgbase ( cg fs -- cgbase ) fs_fpg l@ * ; 145: cgstart ( cg fs -- cgstart ) 146 2dup fs_cgmask l@ not and ( cg fs stuff -- ) 147 over fs_cgoffset l@ * -rot ( stuffcg fs -- ) 148 cgbase + 149; 150: cgdmin ( cg fs -- 1st-data-block ) dup fs_dblkno l@ -rot cgstart + ; 151: cgimin ( cg fs -- inode-block ) dup fs_iblkno l@ -rot cgstart + ; 152: cgsblock ( cg fs -- super-block ) dup fs_sblkno l@ -rot cgstart + ; 153: cgstod ( cg fs -- cg-block ) dup fs_cblkno l@ -rot cgstart + ; 154 155\ 156\ Block and frag position macros 157\ 158 159: blkoff ( pos fs -- off ) fs_qbmask x@ and ; 160: fragoff ( pos fs -- off ) fs_qfmask x@ and ; 161: lblktosize ( blk fs -- off ) fs_bshift l@ << ; 162: lblkno ( pos fs -- off ) fs_bshift l@ >> ; 163: numfrags ( pos fs -- off ) fs_fshift l@ >> ; 164: blkroundup ( pos fs -- off ) dup fs_bmask l@ -rot fs_qbmask x@ + and ; 165: fragroundup ( pos fs -- off ) dup fs_fmask l@ -rot fs_qfmask x@ + and ; 166\ : fragroundup ( pos fs -- off ) tuck fs_qfmask x@ + swap fs_fmask l@ and ; 167: fragstoblks ( pos fs -- off ) fs_fragshift l@ >> ; 168: blkstofrags ( blk fs -- frag ) fs_fragshift l@ << ; 169: fragnum ( fsb fs -- off ) fs_frag l@ 1- and ; 170: blknum ( fsb fs -- off ) fs_frag l@ 1- not and ; 171: dblksize ( lbn dino fs -- size ) 172 -rot ( fs lbn dino ) 173 di_size x@ ( fs lbn di_size ) 174 -rot dup 1+ ( di_size fs lbn lbn+1 ) 175 2over fs_bshift l@ ( di_size fs lbn lbn+1 di_size b_shift ) 176 rot swap << >= ( di_size fs lbn res1 ) 177 swap ndaddr >= or if ( di_size fs ) 178 swap drop fs_bsize l@ exit ( size ) 179 then tuck blkoff swap fragroundup ( size ) 180; 181 182 183: ino-to-cg ( ino fs -- cg ) fs_ipg l@ / ; 184: ino-to-fsbo ( ino fs -- fsb0 ) fs_inopb l@ mod ; 185: ino-to-fsba ( ino fs -- ba ) \ Need to remove the stupid stack diags someday 186 2dup ( ino fs ino fs ) 187 ino-to-cg ( ino fs cg ) 188 over ( ino fs cg fs ) 189 cgimin ( ino fs inode-blk ) 190 -rot ( inode-blk ino fs ) 191 tuck ( inode-blk fs ino fs ) 192 fs_ipg l@ ( inode-blk fs ino ipg ) 193 mod ( inode-blk fs mod ) 194 swap ( inode-blk mod fs ) 195 dup ( inode-blk mod fs fs ) 196 fs_inopb l@ ( inode-blk mod fs inopb ) 197 rot ( inode-blk fs inopb mod ) 198 swap ( inode-blk fs mod inopb ) 199 / ( inode-blk fs div ) 200 swap ( inode-blk div fs ) 201 blkstofrags ( inode-blk frag ) 202 + 203; 204: fsbtodb ( fsb fs -- db ) fs_fsbtodb l@ << ; 205 206\ 207\ File stuff 208\ 209 210niaddr /w* constant narraysize 211 212struct 213 8 field >f_ihandle \ device handle 214 8 field >f_seekp \ seek pointer 215 8 field >f_fs \ pointer to super block 216 ufs1_dinode_SIZEOF field >f_di \ copy of on-disk inode 217 8 field >f_buf \ buffer for data block 218 4 field >f_buf_size \ size of data block 219 4 field >f_buf_blkno \ block number of data block 220constant file_SIZEOF 221 222file_SIZEOF buffer: the-file 223sb-buf the-file >f_fs x! 224 225ufs1_dinode_SIZEOF buffer: cur-inode 226h# 2000 buffer: indir-block 227-1 value indir-addr 228 229\ 230\ Translate a fileblock to a disk block 231\ 232\ We only allow single indirection 233\ 234 235: block-map ( fileblock -- diskblock ) 236 \ Direct block? 237 dup ndaddr < if ( fileblock ) 238 cur-inode di_db ( arr-indx arr-start ) 239 swap la+ l@ exit ( diskblock ) 240 then ( fileblock ) 241 ndaddr - ( fileblock' ) 242 \ Now we need to check the indirect block 243 dup sb-buf fs_nindir l@ < if ( fileblock' ) 244 cur-inode di_ib l@ dup ( fileblock' indir-block indir-block ) 245 indir-addr <> if ( fileblock' indir-block ) 246 to indir-addr ( fileblock' ) 247 indir-block ( fileblock' indir-block ) 248 sb-buf dup fs_bsize l@ ( fileblock' indir-block fs fs_bsize ) 249 swap indir-addr swap ( fileblock' indir-block fs_bsize indiraddr fs ) 250 fsbtodb ( fileblock' indir-block fs_bsize db ) 251 strategy ( fileblock' nread ) 252 then ( fileblock' nread|indir-block ) 253 drop \ Really should check return value 254 indir-block swap la+ l@ exit 255 then 256 dup sb-buf fs_nindir - ( fileblock'' ) 257 \ Now try 2nd level indirect block -- just read twice 258 dup sb-buf fs_nindir l@ dup * < if ( fileblock'' ) 259 cur-inode di_ib 1 la+ l@ ( fileblock'' indir2-block ) 260 to indir-addr ( fileblock'' ) 261 \ load 1st level indir block 262 indir-block ( fileblock'' indir-block ) 263 sb-buf dup fs_bsize l@ ( fileblock'' indir-block fs fs_bsize ) 264 swap indir-addr swap ( fileblock'' indir-block fs_bsize indiraddr fs ) 265 fsbtodb ( fileblock'' indir-block fs_bsize db ) 266 strategy ( fileblock'' nread ) 267 drop ( fileblock'' ) 268 dup sb-buf fs_nindir / ( fileblock'' indir-offset ) 269 indir-block swap la+ l@ ( fileblock'' indirblock ) 270 to indir-addr ( fileblock'' ) 271 \ load 2nd level indir block 272 indir-block ( fileblock'' indir-block ) 273 sb-buf dup fs_bsize l@ ( fileblock'' indir-block fs fs_bsize ) 274 swap indir-addr swap ( fileblock'' indir-block fs_bsize indiraddr fs ) 275 fsbtodb ( fileblock'' indir-block fs_bsize db ) 276 strategy ( fileblock'' nread ) 277 drop ( fileblock'' ) 278 sb-buf fs_nindir l@ mod indir-block swap la+ l@ exit 279 then 280 ." block-map: exceeded max file size" cr 281 abort 282; 283 284\ 285\ Read file into internal buffer and return pointer and len 286\ 287 2880 value cur-block \ allocated dynamically in ufs-open 2890 value cur-blocksize \ size of cur-block 290-1 value cur-blockno 2910 value cur-offset 292 293: buf-read-file ( fs -- len buf ) 294 cur-offset swap ( seekp fs ) 295 2dup blkoff ( seekp fs off ) 296 -rot 2dup lblkno ( off seekp fs block ) 297 swap 2dup cur-inode ( off seekp block fs block fs inop ) 298 swap dblksize ( off seekp block fs size ) 299 rot dup cur-blockno ( off seekp fs size block block cur ) 300 <> if ( off seekp fs size block ) 301 block-map ( off seekp fs size diskblock ) 302 dup 0= if ( off seekp fs size diskblock ) 303 over cur-block swap 0 fill ( off seekp fs size diskblock ) 304 boot-debug? if ." buf-read-file fell off end of file" cr then 305 else 306 2dup sb-buf fsbtodb cur-block -rot strategy ( off seekp fs size diskblock nread ) 307 rot 2dup <> if " buf-read-file: short read." cr abort then 308 then ( off seekp fs diskblock nread size ) 309 nip nip ( off seekp fs size ) 310 else ( off seekp fs size block block cur ) 311 2drop ( off seekp fs size ) 312 then 313\ dup cur-offset + to cur-offset \ Set up next xfer -- not done 314 nip nip swap - ( len ) 315 cur-block 316; 317 318\ 319\ Read inode into cur-inode -- uses cur-block 320\ 321 322: read-inode ( inode fs -- ) 323 twiddle ( inode fs -- inode fs ) 324 325 cur-block ( inode fs -- inode fs buffer ) 326 327 over ( inode fs buffer -- inode fs buffer fs ) 328 fs_bsize l@ ( inode fs buffer -- inode fs buffer size ) 329 330 2over ( inode fs buffer size -- inode fs buffer size inode fs ) 331 2over ( inode fs buffer size inode fs -- inode fs buffer size inode fs buffer size ) 332 2swap tuck ( inode fs buffer size inode fs buffer size -- inode fs buffer size buffer size fs inode fs ) 333 334 ino-to-fsba ( inode fs buffer size buffer size fs inode fs -- inode fs buffer size buffer size fs fsba ) 335 swap ( inode fs buffer size buffer size fs fsba -- inode fs buffer size buffer size fsba fs ) 336 fsbtodb ( inode fs buffer size buffer size fsba fs -- inode fs buffer size buffer size db ) 337 338 dup to cur-blockno ( inode fs buffer size buffer size dstart -- inode fs buffer size buffer size dstart ) 339 strategy ( inode fs buffer size buffer size dstart -- inode fs buffer size nread ) 340 <> if ." read-inode - residual" cr abort then 341 dup 2over ( inode fs buffer -- inode fs buffer buffer inode fs ) 342 ino-to-fsbo ( inode fs buffer -- inode fs buffer buffer fsbo ) 343 ufs1_dinode_SIZEOF * + ( inode fs buffer buffer fsbo -- inode fs buffer dinop ) 344 cur-inode ufs1_dinode_SIZEOF move ( inode fs buffer dinop -- inode fs buffer ) 345 \ clear out the old buffers 346 drop ( inode fs buffer -- inode fs ) 347 2drop 348; 349 350\ Identify inode type 351 352: is-dir? ( dinode -- true:false ) di_mode w@ ifmt and ifdir = ; 353: is-symlink? ( dinode -- true:false ) di_mode w@ ifmt and iflnk = ; 354 355 356 357\ 358\ Hunt for directory entry: 359\ 360\ repeat 361\ load a buffer 362\ while entries do 363\ if entry == name return 364\ next entry 365\ until no buffers 366\ 367 368: search-directory ( str len -- ino|0 ) 369 0 to cur-offset 370 begin cur-offset cur-inode di_size x@ < while ( str len ) 371 sb-buf buf-read-file ( str len len buf ) 372 over 0= if ." search-directory: buf-read-file zero len" cr abort then 373 swap dup cur-offset + to cur-offset ( str len buf len ) 374 2dup + nip ( str len buf bufend ) 375 swap 2swap rot ( bufend str len buf ) 376 begin dup 4 pick < while ( bufend str len buf ) 377 dup d_ino l@ 0<> if ( bufend str len buf ) 378 boot-debug? if dup dup d_name swap d_namlen c@ type cr then 379 2dup d_namlen c@ = if ( bufend str len buf ) 380 dup d_name 2over ( bufend str len buf dname str len ) 381 comp 0= if ( bufend str len buf ) 382 \ Found it -- return inode 383 d_ino l@ nip nip nip ( dino ) 384 boot-debug? if ." Found it" cr then 385 exit ( dino ) 386 then 387 then ( bufend str len buf ) 388 then ( bufend str len buf ) 389 dup d_reclen w@ + ( bufend str len nextbuf ) 390 repeat 391 drop rot drop ( str len ) 392 repeat 393 2drop 2drop 0 ( 0 ) 394; 395 396: ffs_oldcompat ( -- ) 397\ Make sure old ffs values in sb-buf are sane 398 sb-buf fs_npsect dup l@ sb-buf fs_nsect l@ max swap l! 399 sb-buf fs_interleave dup l@ 1 max swap l! 400 sb-buf fs_postblformat l@ fs_42postblfmt = if 401 8 sb-buf fs_nrpos l! 402 then 403 sb-buf fs_inodefmt l@ fs_44inodefmt < if 404 sb-buf fs_bsize l@ 405 dup ndaddr * 1- sb-buf fs_maxfilesize x! 406 niaddr 0 ?do 407 sb-buf fs_nindir l@ * dup ( sizebp sizebp -- ) 408 sb-buf fs_maxfilesize dup x@ ( sizebp sizebp *fs_maxfilesize fs_maxfilesize -- ) 409 rot ( sizebp *fs_maxfilesize fs_maxfilesize sizebp -- ) 410 + ( sizebp *fs_maxfilesize new_fs_maxfilesize -- ) 411 swap x! ( sizebp -- ) 412 loop drop ( -- ) 413 sb-buf dup fs_bmask l@ not swap fs_qbmask x! 414 sb-buf dup fs_fmask l@ not swap fs_qfmask x! 415 then 416; 417 418: read-super ( sector -- ) 4190 " seek" boot-ihandle $call-method 420 -1 = if 421 ." Seek failed" cr 422 abort 423 then 424 sb-buf sbsize " read" boot-ihandle $call-method 425 dup sbsize <> if 426 ." Read of superblock failed" cr 427 ." requested" space sbsize . 428 ." actual" space . cr 429 abort 430 else 431 drop 432 then 433; 434 435: ufs-open ( bootpath,len -- ) 436 boot-ihandle -1 = if 437 over cif-open dup 0= if ( boot-path len ihandle? ) 438 ." Could not open device" space type cr 439 abort 440 then ( boot-path len ihandle ) 441 to boot-ihandle \ Save ihandle to boot device 442 then 2drop 443 sboff read-super 444 sb-buf fs_magic l@ fs_magic_value <> if 445 64 dup to raid-offset 446 dev_bsize * sboff + read-super 447 sb-buf fs_magic l@ fs_magic_value <> if 448 ." Invalid superblock magic" cr 449 abort 450 then 451 then 452 sb-buf fs_bsize l@ dup maxbsize > if 453 ." Superblock bsize" space . ." too large" cr 454 abort 455 then 456 dup fs_SIZEOF < if 457 ." Superblock bsize < size of superblock" cr 458 abort 459 then 460 ffs_oldcompat ( fs_bsize -- fs_bsize ) 461 dup to cur-blocksize alloc-mem to cur-block \ Allocate cur-block 462 boot-debug? if ." ufs-open complete" cr then 463; 464 465: ufs-close ( -- ) 466 boot-ihandle dup -1 <> if 467 cif-close -1 to boot-ihandle 468 then 469 cur-block 0<> if 470 cur-block cur-blocksize free-mem 471 then 472; 473 474: boot-path ( -- boot-path ) 475 " bootpath" chosen-phandle get-package-property if 476 ." Could not find bootpath in /chosen" cr 477 abort 478 else 479 decode-string 2swap 2drop 480 then 481; 482 483: boot-args ( -- boot-args ) 484 " bootargs" chosen-phandle get-package-property if 485 ." Could not find bootargs in /chosen" cr 486 abort 487 else 488 decode-string 2swap 2drop 489 then 490; 491 4922000 buffer: boot-path-str 4932000 buffer: boot-path-tmp 494 495: split-path ( path len -- right len left len ) 496\ Split a string at the `/' 497 begin 498 dup -rot ( oldlen right len left ) 499 ascii / left-parse-string ( oldlen right len left len ) 500 dup 0<> if 4 roll drop exit then 501 2drop ( oldlen right len ) 502 rot over = ( right len diff ) 503 until 504; 505 506: find-file ( load-file len -- ) 507 rootino dup sb-buf read-inode ( load-file len -- load-file len ino ) 508 -rot ( load-file len ino -- pino load-file len ) 509 \ 510 \ For each path component 511 \ 512 begin split-path dup 0<> while ( pino right len left len -- ) 513 cur-inode is-dir? not if ." Inode not directory" cr abort then 514 boot-debug? if ." Looking for" space 2dup type space ." in directory..." cr then 515 search-directory ( pino right len left len -- pino right len ino|false ) 516 dup 0= if ." Bad path" cr abort then ( pino right len cino ) 517 sb-buf read-inode ( pino right len ) 518 cur-inode is-symlink? if \ Symlink -- follow the damn thing 519 \ Save path in boot-path-tmp 520 boot-path-tmp strmov ( pino new-right len ) 521 522 \ Now deal with symlink 523 cur-inode di_size x@ ( pino right len linklen ) 524 dup sb-buf fs_maxsymlinklen l@ ( pino right len linklen linklen maxlinklen ) 525 < if \ Now join the link to the path 526 cur-inode di_shortlink l@ ( pino right len linklen linkp ) 527 swap boot-path-str strmov ( pino right len new-linkp linklen ) 528 else \ Read file for symlink -- Ugh 529 \ Read link into boot-path-str 530 boot-path-str dup sb-buf fs_bsize l@ 531 0 block-map ( pino right len linklen boot-path-str bsize blockno ) 532 strategy drop swap ( pino right len boot-path-str linklen ) 533 then ( pino right len linkp linklen ) 534 \ Concatenate the two paths 535 strcat ( pino new-right newlen ) 536 swap dup c@ ascii / = if \ go to root inode? 537 rot drop rootino -rot ( rino len right ) 538 then 539 rot dup sb-buf read-inode ( len right pino ) 540 -rot swap ( pino right len ) 541 then ( pino right len ) 542 repeat 543 2drop drop 544; 545 546: read-file ( size addr -- ) 547 \ Read x bytes from a file to buffer 548 begin over 0> while 549 cur-offset cur-inode di_size x@ > if ." read-file EOF exceeded" cr abort then 550 sb-buf buf-read-file ( size addr len buf ) 551 over 2over drop swap ( size addr len buf addr len ) 552 move ( size addr len ) 553 dup cur-offset + to cur-offset ( size len newaddr ) 554 tuck + ( size len newaddr ) 555 -rot - swap ( newaddr newsize ) 556 repeat 557 2drop 558; 559 560\ 561\ According to the 1275 addendum for SPARC processors: 562\ Default load-base is 0x4000. At least 0x8.0000 or 563\ 512KB must be available at that address. 564\ 565\ The Fcode bootblock can take up up to 8KB (O.K., 7.5KB) 566\ so load programs at 0x4000 + 0x2000=> 0x6000 567\ 568 569h# 6000 constant loader-base 570 571\ 572\ Elf support -- find the load addr 573\ 574 575: is-elf? ( hdr -- res? ) h# 7f454c46 = ; 576 577\ 578\ Finally we finish it all off 579\ 580 581: load-file-signon ( load-file len boot-path len -- load-file len boot-path len ) 582 ." Loading file" space 2over type cr ." from device" space 2dup type cr 583; 584 585: load-file-print-size ( size -- size ) 586 ." Loading" space dup . space ." bytes of file..." cr 587; 588 589: load-file ( load-file len boot-path len -- load-base ) 590 boot-debug? if load-file-signon then 591 the-file file_SIZEOF 0 fill \ Clear out file structure 592 ufs-open ( load-file len ) 593 find-file ( ) 594 595 \ 596 \ Now we've found the file we should read it in in one big hunk 597 \ 598 599 cur-inode di_size x@ ( file-len ) 600 dup " to file-size" evaluate ( file-len ) 601 boot-debug? if load-file-print-size then 602 0 to cur-offset 603 loader-base ( buf-len addr ) 604 2dup read-file ( buf-len addr ) 605 ufs-close ( buf-len addr ) 606 607 dup l@ is-elf? false = if 608 ." load-file: not an elf executable" cr 609 abort 610 then 611 612 \ Luckily the prom should be able to handle ELF executables by itself 613 614 nip ( addr ) 615; 616 617: do-boot ( bootfile -- ) 618 ." OpenBSD IEEE 1275 Bootblock 1.1" cr 619 boot-path load-file ( -- load-base ) 620 dup 0<> if " to load-base init-program" evaluate then 621; 622 623 624boot-args ascii V strchr 0<> swap drop if 625 true to boot-debug? 626then 627 628boot-args ascii D strchr 0= swap drop if 629 " /ofwboot" do-boot 630then exit 631 632 633