1 \ Copyright (c) 2006-2015 Devin Teske <dteske@FreeBSD.org> 2 \ All rights reserved. 3 \ 4 \ Redistribution and use in source and binary forms, with or without 5 \ modification, are permitted provided that the following conditions 6 \ are met: 7 \ 1. Redistributions of source code must retain the above copyright 8 \ notice, this list of conditions and the following disclaimer. 9 \ 2. Redistributions in binary form must reproduce the above copyright 10 \ notice, this list of conditions and the following disclaimer in the 11 \ documentation and/or other materials provided with the distribution. 12 \ 13 \ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 \ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 \ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 \ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 \ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 \ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 \ SUCH DAMAGE. 24 \ 25 \ Copyright 2015 Toomas Soome <tsoome@me.com> 26 \ Copyright 2019 OmniOS Community Edition (OmniOSce) Association. 27 \ Copyright 2019 Joyent, Inc. 28 29 marker task-menu-commands.4th 30 31 include /boot/forth/menusets.4th 32 33 only forth definitions 34 35 variable osconsole_state 36 variable acpi_state 37 variable kernel_state 38 variable root_state 39 variable kmdb_state 40 variable drop_into_kmdb_state 41 0 kmdb_state ! 42 0 drop_into_kmdb_state ! 43 0 osconsole_state ! 44 0 acpi_state ! 45 0 kernel_state ! 46 0 root_state ! 47 48 also menu-namespace also menu-command-helpers 49 50 \ 51 \ Boot 52 \ 53 54 : init_boot ( N -- N ) 55 dup 56 s" smartos" getenv? if 57 s" set menu_keycode[N]=98" \ base command to execute 58 else 59 s" boot_single" getenv -1 <> if 60 drop ( n n c-addr -- n n ) \ unused 61 toggle_menuitem ( n n -- n n ) 62 s" set menu_keycode[N]=115" \ base command to execute 63 else 64 s" set menu_keycode[N]=98" \ base command to execute 65 then 66 then 67 17 +c! \ replace 'N' with ASCII numeral 68 evaluate 69 ; 70 71 \ 72 \ Alternate Boot 73 \ 74 75 : init_altboot ( N -- N ) 76 dup 77 s" smartos" getenv? if 78 s" set menu_keycode[N]=114" \ base command to execute 79 else 80 s" boot_single" getenv -1 <> if 81 drop ( n c-addr -- n ) \ unused 82 toggle_menuitem ( n -- n ) 83 s" set menu_keycode[N]=109" \ base command to execute 84 else 85 s" set menu_keycode[N]=115" \ base command to execute 86 then 87 then 88 17 +c! \ replace 'N' with ASCII numeral 89 evaluate 90 ; 91 92 : altboot ( N -- NOTREACHED ) 93 s" smartos" getenv? if 94 s" alt-boot-args" getenv dup -1 <> if 95 s" boot-args" setenv ( c-addr/u -- ) 96 then 97 ." NoInstall/Recovery mode boot. login/pw: root/root" cr 98 else 99 s" boot_single" 2dup getenv -1 <> if 100 drop ( c-addr/u c-addr -- c-addr/u ) \ unused 101 unsetenv ( c-addr/u -- ) 102 else 103 2drop ( c-addr/u -- ) \ unused 104 s" set boot_single=YES" evaluate 105 then 106 then 107 0 boot ( state -- ) 108 ; 109 110 \ 111 \ Single User Mode 112 \ 113 114 : singleuser_enabled? ( -- flag ) 115 s" boot_single" getenv -1 <> dup if 116 swap drop ( c-addr flag -- flag ) 117 then 118 ; 119 120 : singleuser_enable ( -- ) 121 s" set boot_single=YES" evaluate 122 ; 123 124 : singleuser_disable ( -- ) 125 s" boot_single" unsetenv 126 ; 127 128 : init_singleuser ( N -- N ) 129 singleuser_enabled? if 130 toggle_menuitem ( n -- n ) 131 then 132 ; 133 134 : toggle_singleuser ( N -- N TRUE ) 135 toggle_menuitem 136 menu-redraw 137 138 \ Now we're going to make the change effective 139 140 dup toggle_stateN @ 0= if 141 singleuser_disable 142 else 143 singleuser_enable 144 then 145 146 TRUE \ loop menu again 147 ; 148 149 \ 150 \ Verbose Boot 151 \ 152 153 : verbose_enabled? ( -- flag ) 154 s" boot_verbose" getenv -1 <> dup if 155 swap drop ( c-addr flag -- flag ) 156 then 157 ; 158 159 : verbose_enable ( -- ) 160 s" set boot_verbose=YES" evaluate 161 ; 162 163 : verbose_disable ( -- ) 164 s" boot_verbose" unsetenv 165 ; 166 167 : init_verbose ( N -- N ) 168 verbose_enabled? if 169 toggle_menuitem ( n -- n ) 170 then 171 ; 172 173 : toggle_verbose ( N -- N TRUE ) 174 toggle_menuitem 175 menu-redraw 176 177 \ Now we're going to make the change effective 178 179 dup toggle_stateN @ 0= if 180 verbose_disable 181 else 182 verbose_enable 183 then 184 185 TRUE \ loop menu again 186 ; 187 188 \ 189 \ kmdb 190 \ 191 192 : kmdb_enabled? ( -- flag ) 193 s" boot_kmdb" getenv -1 <> dup if 194 swap drop ( c-addr flag -- flag ) 195 then 196 ; 197 198 : kmdb_enable ( -- ) 199 s" set boot_kmdb=YES" evaluate 200 ; 201 202 : kmdb_disable ( -- ) 203 s" boot_kmdb" unsetenv 204 s" boot_drop_into_kmdb" unsetenv 205 ; 206 207 : init_kmdb ( N -- N ) 208 dup kmdb_state ! \ store entry number for kmdb+drop_into_kmdb 209 kmdb_enabled? if 210 toggle_menuitem ( n -- n ) 211 then 212 ; 213 214 : toggle_kmdb ( N -- N TRUE ) 215 toggle_menuitem 216 dup toggle_stateN @ 0= if ( kmdb is not set ) 217 drop_into_kmdb_state @ if ( drop_into_kmdb is set? ) 218 drop_into_kmdb_state @ toggle_stateN @ if ( drop_into_kmdb is enabled? ) 219 drop_into_kmdb_state @ toggle_menuitem drop 220 then 221 then 222 then 223 menu-redraw 224 225 \ Now we're going to make the change effective 226 227 dup toggle_stateN @ 0= if 228 kmdb_disable 229 else 230 kmdb_enable 231 then 232 233 TRUE \ loop menu again 234 ; 235 236 \ 237 \ drop into kmdb 238 \ 239 240 : drop_into_kmdb_disable ( -- ) 241 s" boot_drop_into_kmdb" unsetenv 242 ; 243 244 : drop_into_kmdb_enabled? ( -- flag ) 245 \ -d is only allowed with -k 246 s" boot_drop_into_kmdb" getenv -1 <> kmdb_enabled? and dup if 247 swap drop ( c-addr flag -- flag ) 248 else 249 drop_into_kmdb_disable \ make sure env is not set 250 then 251 ; 252 253 : drop_into_kmdb_enable ( -- ) 254 kmdb_enable 255 s" set boot_drop_into_kmdb=YES" evaluate 256 ; 257 258 : init_drop_into_kmdb ( N -- N ) 259 dup drop_into_kmdb_state ! \ store entry number for kmdb 260 kmdb_enabled? drop_into_kmdb_enabled? and if 261 toggle_menuitem ( n -- n ) 262 then 263 ; 264 265 : toggle_drop_into_kmdb ( N -- N TRUE ) 266 toggle_menuitem 267 kmdb_enabled? 0= if 268 kmdb_state @ toggle_menuitem drop 269 then 270 menu-redraw 271 272 \ Now we're going to make the change effective 273 274 dup toggle_stateN @ 0= if 275 drop_into_kmdb_disable 276 else 277 drop_into_kmdb_enable 278 then 279 280 TRUE \ loop menu again 281 ; 282 283 \ 284 \ Reconfiguration boot 285 \ 286 287 : reconfigure_enabled? ( -- flag ) 288 s" boot_reconfigure" getenv -1 <> dup if 289 swap drop ( c-addr flag -- flag ) 290 then 291 ; 292 293 : reconfigure_enable ( -- ) 294 s" set boot_reconfigure=YES" evaluate 295 ; 296 297 : reconfigure_disable ( -- ) 298 s" boot_reconfigure" unsetenv 299 ; 300 301 : init_reconfigure ( N -- N ) 302 reconfigure_enabled? if 303 toggle_menuitem ( n -- n ) 304 then 305 ; 306 307 : toggle_reconfigure ( N -- N TRUE ) 308 toggle_menuitem 309 menu-redraw 310 311 \ Now we're going to make the change effective 312 313 dup toggle_stateN @ 0= if 314 reconfigure_disable 315 else 316 reconfigure_enable 317 then 318 319 TRUE \ loop menu again 320 ; 321 322 \ 323 \ Escape to Prompt 324 \ 325 326 : goto_prompt ( N -- N FALSE ) 327 328 s" set autoboot_delay=NO" evaluate 329 330 cr 331 ." To get back to the menu, type `menu' and press ENTER" cr 332 ." or type `boot' and press ENTER to start illumos." cr 333 cr 334 335 FALSE \ exit the menu 336 ; 337 338 \ 339 \ Cyclestate (used by osconsole/acpi/kernel/root below) 340 \ 341 342 : init_cyclestate ( N K -- N ) 343 over cycle_stateN ( n k -- n k addr ) 344 begin 345 tuck @ ( n k addr -- n addr k c ) 346 over <> ( n addr k c -- n addr k 0|-1 ) 347 while 348 rot ( n addr k -- addr k n ) 349 cycle_menuitem 350 swap rot ( addr k n -- n k addr ) 351 repeat 352 2drop ( n k addr -- n ) 353 ; 354 355 \ 356 \ OS Console 357 \ getenv os_console, if not set getenv console, if not set, default to "text" 358 \ allowed serial consoles: ttya .. ttyd 359 \ if new console will be added (graphics?), this section needs to be updated 360 \ 361 : init_osconsole ( N -- N ) 362 s" os_console" getenv dup -1 = if 363 drop 364 s" console" getenv dup -1 = if 365 drop 0 \ default to text 366 then 367 then ( n c-addr/u | n 0 ) 368 369 dup 0<> if ( n c-addr/u ) 370 2dup s" ttyd" compare 0= if 371 2drop 4 372 else 2dup s" ttyc" compare 0= if 373 2drop 3 374 else 2dup s" ttyb" compare 0= if 375 2drop 2 376 else 2dup s" ttya" compare 0= if 377 2drop 1 378 else 379 2drop 0 \ anything else defaults to text 380 then then then then 381 then 382 osconsole_state ! 383 ; 384 385 : activate_osconsole ( N -- N ) 386 dup cycle_stateN @ ( n -- n n2 ) 387 dup osconsole_state ! ( n n2 -- n n2 ) \ copy for re-initialization 388 389 case 390 0 of s" text" endof 391 1 of s" ttya" endof 392 2 of s" ttyb" endof 393 3 of s" ttyc" endof 394 4 of s" ttyd" endof 395 dup s" unknown state: " type . cr 396 endcase 397 s" os_console" setenv 398 ; 399 400 : cycle_osconsole ( N -- N TRUE ) 401 cycle_menuitem \ cycle cycle_stateN to next value 402 activate_osconsole \ apply current cycle_stateN 403 menu-redraw \ redraw menu 404 TRUE \ loop menu again 405 ; 406 407 \ 408 \ ACPI 409 \ 410 : init_acpi ( N -- N ) 411 s" acpi-user-options" getenv dup -1 <> if 412 evaluate \ use ?number parse step 413 414 \ translate option to cycle state 415 case 416 1 of 1 acpi_state ! endof 417 2 of 2 acpi_state ! endof 418 4 of 3 acpi_state ! endof 419 8 of 4 acpi_state ! endof 420 0 acpi_state ! 421 endcase 422 else 423 drop 424 then 425 ; 426 427 : activate_acpi ( N -- N ) 428 dup cycle_stateN @ ( n -- n n2 ) 429 dup acpi_state ! ( n n2 -- n n2 ) \ copy for re-initialization 430 431 \ if N == 0, it's default, just unset env. 432 dup 0= if 433 drop 434 s" acpi-user-options" unsetenv 435 else 436 case 437 1 of s" 1" endof 438 2 of s" 2" endof 439 3 of s" 4" endof 440 4 of s" 8" endof 441 endcase 442 s" acpi-user-options" setenv 443 then 444 ; 445 446 : cycle_acpi ( N -- N TRUE ) 447 cycle_menuitem \ cycle cycle_stateN to next value 448 activate_acpi \ apply current cycle_stateN 449 menu-redraw \ redraw menu 450 TRUE \ loop menu again 451 ; 452 453 \ 454 \ Kernel 455 \ 456 457 : init_kernel ( N -- N ) 458 kernel_state @ ( n -- n k ) 459 init_cyclestate ( n k -- n ) 460 ; 461 462 : activate_kernel ( N -- N ) 463 dup cycle_stateN @ ( n -- n n2 ) 464 dup kernel_state ! ( n n2 -- n n2 ) \ copy for re-initialization 465 48 + ( n n2 -- n n2' ) \ kernel_state to ASCII num 466 467 s" set kernel=${kernel_prefix}${kernel[N]}${kernel_suffix}" 468 36 +c! ( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num 469 evaluate ( n c-addr/u -- n ) \ sets $kernel to full kernel-path 470 ; 471 472 : cycle_kernel ( N -- N TRUE ) 473 cycle_menuitem \ cycle cycle_stateN to next value 474 activate_kernel \ apply current cycle_stateN 475 menu-redraw \ redraw menu 476 TRUE \ loop menu again 477 ; 478 479 \ 480 \ Root 481 \ 482 483 : init_root ( N -- N ) 484 root_state @ ( n -- n k ) 485 init_cyclestate ( n k -- n ) 486 ; 487 488 : activate_root ( N -- N ) 489 dup cycle_stateN @ ( n -- n n2 ) 490 dup root_state ! ( n n2 -- n n2 ) \ copy for re-initialization 491 48 + ( n n2 -- n n2' ) \ root_state to ASCII num 492 493 s" set root=${root_prefix}${root[N]}${root_suffix}" 494 30 +c! ( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num 495 evaluate ( n c-addr/u -- n ) \ sets $root to full kernel-path 496 ; 497 498 : cycle_root ( N -- N TRUE ) 499 cycle_menuitem \ cycle cycle_stateN to next value 500 activate_root \ apply current cycle_stateN 501 menu-redraw \ redraw menu 502 TRUE \ loop menu again 503 ; 504 505 \ 506 \ Menusets 507 \ 508 509 : goto_menu ( N M -- N TRUE ) 510 menu-unset 511 menuset-loadsetnum ( n m -- n ) 512 menu-redraw 513 TRUE \ Loop menu again 514 ; 515 516 \ 517 \ Defaults 518 \ 519 520 : unset_boot_options 521 0 acpi_state ! 522 s" acpi-user-options" unsetenv 523 s" boot-args" unsetenv 524 s" boot_ask" unsetenv 525 singleuser_disable 526 verbose_disable 527 kmdb_disable \ disables drop_into_kmdb as well 528 reconfigure_disable 529 ; 530 531 : set_default_boot_options ( N -- N TRUE ) 532 unset_boot_options 533 2 goto_menu 534 ; 535 536 \ 537 \ Set boot environment defaults 538 \ 539 540 541 : init_bootenv ( -- ) 542 s" set menu_caption[1]=${bemenu_current}${zfs_be_active}" evaluate 543 s" set ansi_caption[1]=${beansi_current}${zfs_be_active}" evaluate 544 s" set menu_caption[2]=${bemenu_bootfs}${currdev}" evaluate 545 s" set ansi_caption[2]=${beansi_bootfs}${currdev}" evaluate 546 s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate 547 s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate 548 ; 549 550 \ 551 \ Redraw the entire screen. A long BE name can corrupt the menu 552 \ 553 554 : be_draw_screen 555 clear \ Clear the screen (in screen.4th) 556 print_version \ print version string (bottom-right; see version.4th) 557 draw-beastie \ Draw FreeBSD logo at right (in beastie.4th) 558 draw-brand \ Draw brand.4th logo at top (in brand.4th) 559 menu-init \ Initialize menu and draw bounding box (in menu.4th) 560 ; 561 562 \ 563 \ Select a boot environment 564 \ 565 566 : set_bootenv ( N -- N TRUE ) 567 dup s" bootenv_root[E]" 13 +c! getenv 568 s" currdev" getenv compare 0= if 569 s" zfs_be_active" getenv type ." is already active" 570 else 571 dup s" set currdev=${bootenv_root[E]}" 27 +c! evaluate 572 dup s" bootenvmenu_caption[E]" 20 +c! getenv 573 s" zfs_be_active" setenv 574 ." Activating " s" currdev" getenv type cr 575 s" unload" evaluate 576 free-module-options 577 unset_boot_options 578 s" /boot/defaults/loader.conf" read-conf 579 s" /boot/loader.conf" read-conf 580 s" /boot/loader.conf.local" read-conf 581 init_bootenv 582 583 s" 1" s" zfs_be_currpage" setenv 584 s" be-set-page" evaluate 585 then 586 587 500 ms \ sleep so user can see the message 588 be_draw_screen 589 menu-redraw 590 TRUE 591 ; 592 593 \ 594 \ Chainload this entry. Normally we do not return, in case of error 595 \ from chain load, we continue with normal menu code. 596 \ 597 598 : set_be_chain ( N -- no return | N TRUE ) 599 dup s" chain ${bootenv_root[E]}" 21 +c! evaluate catch drop 600 601 menu-redraw 602 TRUE 603 ; 604 605 \ 606 \ Switch to the next page of boot environments 607 \ 608 609 : set_be_page ( N -- N TRUE ) 610 s" zfs_be_currpage" getenv dup -1 = if 611 drop s" 1" 612 else 613 s2n 614 1+ \ increment the page number 615 dup 616 s" zfs_be_pages" getenv 617 s2n 618 > if drop 1 then 619 n2s 620 then 621 622 s" zfs_be_currpage" setenv 623 s" be-set-page" evaluate 624 3 goto_menu 625 ; 626 627 only forth definitions