1\ Copyright (c) 1999 Daniel C. Sobral <dcs@FreeBSD.org> 2\ Copyright (c) 2011-2015 Devin Teske <dteske@FreeBSD.org> 3\ All rights reserved. 4\ 5\ Redistribution and use in source and binary forms, with or without 6\ modification, are permitted provided that the following conditions 7\ are met: 8\ 1. Redistributions of source code must retain the above copyright 9\ notice, this list of conditions and the following disclaimer. 10\ 2. Redistributions in binary form must reproduce the above copyright 11\ notice, this list of conditions and the following disclaimer in the 12\ documentation and/or other materials provided with the distribution. 13\ 14\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24\ SUCH DAMAGE. 25\ 26\ $FreeBSD$ 27 28only forth definitions 29 30s" arch-i386" environment? [if] [if] 31 s" loader_version" environment? [if] 32 11 < [if] 33 .( Loader version 1.1+ required) cr 34 abort 35 [then] 36 [else] 37 .( Could not get loader version!) cr 38 abort 39 [then] 40[then] [then] 41 42include /boot/forth/support.4th 43include /boot/forth/color.4th 44include /boot/forth/delay.4th 45include /boot/forth/check-password.4th 46 47only forth definitions 48 49: bootmsg ( -- ) 50 loader_color? dup ( -- bool bool ) 51 if 7 fg 4 bg then 52 ." Booting..." 53 if me then 54 cr 55; 56 57: try-menu-unset 58 \ menu-unset may not be present 59 s" beastie_disable" getenv 60 dup -1 <> if 61 s" YES" compare-insensitive 0= if 62 exit 63 then 64 else 65 drop 66 then 67 s" menu-unset" 68 sfind if 69 execute 70 else 71 drop 72 then 73 s" menusets-unset" 74 sfind if 75 execute 76 else 77 drop 78 then 79; 80 81only forth also support-functions also builtins definitions 82 83\ the boot-args was parsed to individual options while loaded 84\ now compose boot-args, so the boot can set kernel arguments 85\ note the command line switched for boot command will cause 86\ environment variable boot-args to be ignored 87\ There are 2 larger strings, acpi-user-options and existing boot-args 88\ other switches are 1 byte each, so allocate boot-args+acpi + extra bytes 89\ for rest. Be sure to review this, if more options are to be added into 90\ environment. 91 92: set-boot-args { | addr len baddr blen aaddr alen -- } 93 s" boot-args" getenv dup -1 <> if 94 to blen to baddr 95 else 96 drop 97 then 98 s" acpi-user-options" getenv dup -1 <> if 99 to alen to aaddr 100 else 101 drop 102 then 103 104 \ allocate temporary space. max is: 105 \ 7 kernel switches 106 \ 26 for acpi, so use 40 for safety 107 blen alen 40 + + allocate abort" out of memory" 108 to addr 109 \ boot-addr may have file name before options, copy it to addr 110 baddr 0<> if 111 baddr c@ [char] - <> if 112 baddr blen [char] - strchr ( addr len ) 113 dup 0= if \ no options, copy all 114 2drop 115 baddr addr blen move 116 blen to len 117 0 to blen 118 0 to baddr 119 else ( addr len ) 120 dup blen 121 swap - 122 to len ( addr len ) 123 to blen ( addr ) 124 baddr addr len move ( addr ) 125 to baddr \ baddr points now to first option 126 then 127 then 128 then 129 \ now add kernel switches 130 len 0<> if 131 bl addr len + c! len 1+ to len 132 then 133 [char] - addr len + c! len 1+ to len 134 135 s" boot_single" getenv dup -1 <> if 136 s" YES" compare-insensitive 0= if 137 [char] s addr len + c! len 1+ to len 138 then 139 else 140 drop 141 then 142 s" boot_verbose" getenv dup -1 <> if 143 s" YES" compare-insensitive 0= if 144 [char] v addr len + c! len 1+ to len 145 then 146 else 147 drop 148 then 149 s" boot_kmdb" getenv dup -1 <> if 150 s" YES" compare-insensitive 0= if 151 [char] k addr len + c! len 1+ to len 152 then 153 else 154 drop 155 then 156 s" boot_debug" getenv dup -1 <> if 157 s" YES" compare-insensitive 0= if 158 [char] d addr len + c! len 1+ to len 159 then 160 else 161 drop 162 then 163 s" boot_reconfigure" getenv dup -1 <> if 164 s" YES" compare-insensitive 0= if 165 [char] r addr len + c! len 1+ to len 166 then 167 else 168 drop 169 then 170 s" boot_ask" getenv dup -1 <> if 171 s" YES" compare-insensitive 0= if 172 [char] a addr len + c! len 1+ to len 173 then 174 else 175 drop 176 then 177 178 \ now add remining boot args if blen != 0. 179 \ baddr[0] is '-', if baddr[1] != 'B' append to addr, 180 \ otherwise add space then copy 181 blen 0<> if 182 baddr 1+ c@ [char] B = if 183 addr len + 1- c@ [char] - = if \ if addr[len -1] == '-' 184 baddr 1+ to baddr 185 blen 1- to blen 186 else 187 bl addr len + c! len 1+ to len 188 then 189 else 190 baddr 1+ to baddr 191 blen 1- to blen 192 then 193 baddr addr len + blen move 194 len blen + to len 195 0 to baddr 196 0 to blen 197 then 198 \ last part - add acpi. 199 alen 0<> if 200 addr len + 1- c@ [char] - <> if 201 bl addr len + c! len 1+ to len 202 [char] - addr len + c! len 1+ to len 203 then 204 s" B acpi-user-options=" dup -rot ( len addr len ) 205 addr len + swap move ( len ) 206 len + to len 207 aaddr addr len + alen move 208 len alen + to len 209 then 210 211 \ check for left over '-' 212 addr len 1- + c@ [char] - = if 213 len 1- to len 214 \ but now we may also have left over ' ' 215 len if ( len <> 0 ) 216 addr len 1- + c@ bl = if 217 len 1- to len 218 then 219 then 220 then 221 222 \ if len != 0, set boot-args 223 len 0<> if 224 addr len s" boot-args" setenv 225 then 226 addr free drop 227; 228 229: boot 230 0= if ( interpreted ) get_arguments then 231 set-boot-args 232 233 \ Unload only if a path was passed. Paths start with / 234 dup if 235 >r over r> swap 236 c@ [char] / = if 237 0 1 unload drop 238 else 239 s" kernelname" getenv? if ( a kernel has been loaded ) 240 try-menu-unset 241 bootmsg 1 boot exit 242 then 243 load_kernel_and_modules 244 ?dup if exit then 245 try-menu-unset 246 bootmsg 0 1 boot exit 247 then 248 else 249 s" kernelname" getenv? if ( a kernel has been loaded ) 250 try-menu-unset 251 bootmsg 1 boot exit 252 then 253 load_kernel_and_modules 254 ?dup if exit then 255 try-menu-unset 256 bootmsg 0 1 boot exit 257 then 258 load_kernel_and_modules 259 ?dup 0= if bootmsg 0 1 boot then 260; 261 262\ ***** boot-conf 263\ 264\ Prepares to boot as specified by loaded configuration files. 265 266: boot-conf 267 0= if ( interpreted ) get_arguments then 268 0 1 unload drop 269 load_kernel_and_modules 270 ?dup 0= if 0 1 autoboot then 271; 272 273also forth definitions previous 274 275builtin: boot 276builtin: boot-conf 277 278only forth definitions also support-functions 279 280\ 281\ in case the boot-args is set, parse it and extract following options: 282\ -a to boot_ask=YES 283\ -s to boot_single=YES 284\ -v to boot_verbose=YES 285\ -k to boot_kmdb=YES 286\ -d to boot_debug=YES 287\ -r to boot_reconfigure=YES 288\ -B acpi-user-options=X to acpi-user-options=X 289\ 290\ This is needed so that the menu can manage these options. Unfortunately, this 291\ also means that boot-args will override previously set options, but we have no\ way to control the processing order here. boot-args will be rebuilt at boot. 292\ 293\ NOTE: The best way to address the order is to *not* set any above options 294\ in boot-args. 295 296: parse-boot-args { | baddr blen -- } 297 s" boot-args" getenv dup -1 = if drop exit then 298 to blen 299 to baddr 300 301 baddr blen 302 303 \ loop over all instances of switch blocks, starting with '-' 304 begin 305 [char] - strchr 306 2dup to blen to baddr 307 dup 0<> 308 while ( addr len ) \ points to - 309 \ block for switch B. keep it on top of the stack for case 310 \ the property list will get empty. 311 312 over 1+ c@ [char] B = if 313 2dup \ save "-B ...." in case options is empty 314 2 - swap 2 + ( addr len len-2 addr+2 ) \ skip -B 315 316 begin \ skip spaces 317 dup c@ bl = 318 while 319 1+ swap 1- swap 320 repeat 321 322 ( addr len len' addr' ) 323 \ its 3 cases now: end of string, -switch, or option list 324 325 over 0= if \ end of string, remove trailing -B 326 2drop ( addr len ) 327 swap 0 swap c! \ store 0 at -B 328 blen swap ( blen len ) 329 - ( rem ) 330 baddr swap ( addr rem ) 331 dup 0= if 332 s" boot-args" unsetenv 333 2drop 334 exit 335 then 336 \ trailing space(s) 337 begin 338 over ( addr rem addr ) 339 over + 1- ( addr rem addr+rem-1 ) 340 c@ bl = 341 while 342 1- swap ( rem-1 addr ) 343 over ( rem-1 addr rem-1 ) 344 over + ( rem-1 addr addr+rem-1 ) 345 0 swap c! 346 swap 347 repeat 348 s" boot-args" setenv 349 recurse \ restart 350 exit 351 then 352 ( addr len len' addr' ) 353 dup c@ [char] - = if \ it is switch. set to boot-args 354 swap s" boot-args" setenv 355 2drop 356 recurse \ restart 357 exit 358 then 359 ( addr len len' addr' ) 360 \ its options string "option1,option2,... -..." 361 \ cut acpi-user-options=xxx and restart the parser 362 \ or skip to next option block 363 begin 364 dup c@ dup 0<> swap bl <> and \ stop if space or 0 365 while 366 dup 18 s" acpi-user-options=" compare 0= if \ matched 367 ( addr len len' addr' ) 368 \ addr' points to acpi options, find its end [',' or ' ' or 0 ] 369 \ set it as acpi-user-options and move remaining to addr' 370 2dup ( addr len len' addr' len' addr' ) 371 \ skip to next option in list 372 \ loop to first , or bl or 0 373 begin 374 dup c@ [char] , <> >r 375 dup c@ bl <> >r 376 dup c@ 0<> r> r> and and 377 while 378 1+ swap 1- swap 379 repeat 380 ( addr len len' addr' len" addr" ) 381 >r >r ( addr len len' addr' R: addr" len" ) 382 over r@ - ( addr len len' addr' proplen R: addr" len" ) 383 dup 5 + ( addr len len' addr' proplen proplen+5 ) 384 allocate abort" out of memory" 385 386 0 s" set " strcat ( addr len len' addr' proplen caddr clen ) 387 >r >r 2dup r> r> 2swap strcat ( addr len len' addr' proplen caddr clen ) 388 2dup + 0 swap c! \ terminate with 0 389 2dup evaluate drop free drop 390 ( addr len len' addr' proplen R: addr" len" ) 391 \ acpi-user-options is set, now move remaining string to its place. 392 \ addr: -B, addr': acpi... addr": reminder 393 swap ( addr len len' proplen addr' ) 394 r> r> ( addr len len' proplen addr' len" addr" ) 395 dup c@ [char] , = if 396 \ skip , and move addr" to addr' 397 1+ swap 1- ( addr len len' proplen addr' addr" len" ) 398 rot swap 1+ move ( addr len len' proplen ) 399 else \ its bl or 0 ( addr len len' proplen addr' len" addr" ) 400 \ for both bl and 0 we need to copy to addr'-1 to remove 401 \ comma, then reset boot-args, and recurse will clear -B 402 \ if there are no properties left. 403 dup c@ 0= if 404 2drop ( addr len len' proplen addr' ) 405 1- 0 swap c! ( addr len len' proplen ) 406 else 407 >r >r ( addr len len' proplen addr' R: addr" len" ) 408 1- swap 1+ swap 409 r> r> ( addr len len' proplen addr' len" addr" ) 410 rot rot move ( addr len len' proplen ) 411 then 412 then 413 414 2swap 2drop ( len' proplen ) 415 nip ( proplen ) 416 baddr blen rot - 417 s" boot-args" setenv 418 recurse 419 exit 420 else 421 ( addr len len' addr' ) 422 \ not acpi option, skip to next option in list 423 \ loop to first , or bl or 0 424 begin 425 dup c@ [char] , <> >r 426 dup c@ bl <> >r 427 dup c@ 0<> r> r> and and 428 while 429 1+ swap 1- swap 430 repeat 431 \ if its ',', skip over 432 dup c@ [char] , = if 433 1+ swap 1- swap 434 then 435 then 436 repeat 437 ( addr len len' addr' ) 438 \ this block is done, remove addr and len from stack 439 2swap 2drop swap 440 then 441 442 over c@ [char] - = if ( addr len ) 443 2dup 1- swap 1+ ( addr len len' addr' ) 444 begin \ loop till ' ' or 0 445 dup c@ dup 0<> swap bl <> and 446 while 447 dup c@ [char] s = if 448 s" set boot_single=YES" evaluate TRUE 449 else dup c@ [char] v = if 450 s" set boot_verbose=YES" evaluate TRUE 451 else dup c@ [char] k = if 452 s" set boot_kmdb=YES" evaluate TRUE 453 else dup c@ [char] d = if 454 s" set boot_debug=YES" evaluate TRUE 455 else dup c@ [char] r = if 456 s" set boot_reconfigure=YES" evaluate TRUE 457 else dup c@ [char] a = if 458 s" set boot_ask=YES" evaluate TRUE 459 then then then then then then 460 dup TRUE = if 461 drop 462 dup >r ( addr len len' addr' R: addr' ) 463 1+ swap 1- ( addr len addr'+1 len'-1 R: addr' ) 464 r> swap move ( addr len ) 465 466 2drop baddr blen 1- 467 \ check if we have space after '-', if so, drop '- ' 468 swap dup 1+ c@ bl = if 469 2 + swap 2 - 470 else 471 swap 472 then 473 dup dup 0= swap 1 = or if \ empty or only '-' is left. 474 2drop 475 s" boot-args" unsetenv 476 exit 477 else 478 s" boot-args" setenv 479 then 480 recurse 481 exit 482 then 483 1+ swap 1- swap 484 repeat 485 486 2swap 2drop 487 dup c@ 0= if \ end of string 488 2drop 489 exit 490 else 491 swap 492 then 493 then 494 repeat 495 496 2drop 497; 498 499\ ***** start 500\ 501\ Initializes support.4th global variables, sets loader_conf_files, 502\ processes conf files, and, if any one such file was succesfully 503\ read to the end, loads kernel and modules. 504 505: start ( -- ) ( throws: abort & user-defined ) 506 s" /boot/defaults/loader.conf" initialize 507 include_bootenv 508 include_conf_files 509 include_transient 510 parse-boot-args 511 \ Will *NOT* try to load kernel and modules if no configuration file 512 \ was succesfully loaded! 513 any_conf_read? if 514 s" loader_delay" getenv -1 = if 515 load_xen_throw 516 load_kernel 517 load_modules 518 else 519 drop 520 ." Loading Kernel and Modules (Ctrl-C to Abort)" cr 521 s" also support-functions" evaluate 522 s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate 523 s" set delay_showdots" evaluate 524 delay_execute 525 then 526 then 527; 528 529\ ***** initialize 530\ 531\ Overrides support.4th initialization word with one that does 532\ everything start one does, short of loading the kernel and 533\ modules. Returns a flag 534 535: initialize ( -- flag ) 536 s" /boot/defaults/loader.conf" initialize 537 include_bootenv 538 include_conf_files 539 include_transient 540 parse-boot-args 541 any_conf_read? 542; 543 544\ ***** read-conf 545\ 546\ Read a configuration file, whose name was specified on the command 547\ line, if interpreted, or given on the stack, if compiled in. 548 549: (read-conf) ( addr len -- ) 550 conf_files string= 551 include_conf_files \ Will recurse on new loader_conf_files definitions 552; 553 554: read-conf ( <filename> | addr len -- ) ( throws: abort & user-defined ) 555 state @ if 556 \ Compiling 557 postpone (read-conf) 558 else 559 \ Interpreting 560 bl parse (read-conf) 561 then 562; immediate 563 564\ show, enable, disable, toggle module loading. They all take module from 565\ the next word 566 567: set-module-flag ( module_addr val -- ) \ set and print flag 568 over module.flag ! 569 dup module.name strtype 570 module.flag @ if ." will be loaded" else ." will not be loaded" then cr 571; 572 573: enable-module find-module ?dup if true set-module-flag then ; 574 575: disable-module find-module ?dup if false set-module-flag then ; 576 577: toggle-module find-module ?dup if dup module.flag @ 0= set-module-flag then ; 578 579\ ***** show-module 580\ 581\ Show loading information about a module. 582 583: show-module ( <module> -- ) find-module ?dup if show-one-module then ; 584 585\ Words to be used inside configuration files 586 587: retry false ; \ For use in load error commands 588: ignore true ; \ For use in load error commands 589 590\ Return to strict forth vocabulary 591 592: #type 593 over - >r 594 type 595 r> spaces 596; 597 598: .? 2 spaces 2swap 15 #type 2 spaces type cr ; 599 600: ? 601 ['] ? execute 602 s" boot-conf" s" load kernel and modules, then autoboot" .? 603 s" read-conf" s" read a configuration file" .? 604 s" enable-module" s" enable loading of a module" .? 605 s" disable-module" s" disable loading of a module" .? 606 s" toggle-module" s" toggle loading of a module" .? 607 s" show-module" s" show module load data" .? 608 s" try-include" s" try to load/interpret files" .? 609 s" beadm" s" list or activate Boot Environments" .? 610; 611 612: try-include ( -- ) \ see loader.4th(8) 613 ['] include ( -- xt ) \ get the execution token of `include' 614 catch ( xt -- exception# | 0 ) if \ failed 615 LF parse ( c -- s-addr/u ) 2drop \ advance >in to EOL (drop data) 616 \ ... prevents words unused by `include' from being interpreted 617 then 618; immediate \ interpret immediately for access to `source' (aka tib) 619 620include /boot/forth/beadm.4th 621only forth definitions 622