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 Joyent, Inc. 27\ Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 28 29marker task-menu-commands.4th 30 31include /boot/forth/menusets.4th 32 33only forth definitions 34 35variable osconsole_state 36variable acpi_state 37variable kmdb_state 380 osconsole_state ! 390 acpi_state ! 400 kmdb_state ! 41 42also menu-namespace also menu-command-helpers 43 44\ 45\ Boot 46\ 47 48: init_boot ( N -- N ) 49 dup 50 s" smartos" getenv? if 51 s" set menu_keycode[N]=98" \ base command to execute 52 else 53 s" boot_single" getenv -1 <> if 54 drop ( n n c-addr -- n n ) \ unused 55 toggle_menuitem ( n n -- n n ) 56 s" set menu_keycode[N]=115" \ base command to execute 57 else 58 s" set menu_keycode[N]=98" \ base command to execute 59 then 60 then 61 17 +c! \ replace 'N' with ASCII numeral 62 evaluate 63; 64 65\ 66\ Alternate Boot 67\ 68 69: init_altboot ( N -- N ) 70 dup 71 s" smartos" getenv? if 72 s" set menu_keycode[N]=114" \ base command to execute 73 else 74 s" boot_single" getenv -1 <> if 75 drop ( n c-addr -- n ) \ unused 76 toggle_menuitem ( n -- n ) 77 s" set menu_keycode[N]=109" \ base command to execute 78 else 79 s" set menu_keycode[N]=115" \ base command to execute 80 then 81 then 82 17 +c! \ replace 'N' with ASCII numeral 83 evaluate 84; 85 86: altboot ( N -- NOTREACHED ) 87 s" smartos" getenv? if 88 s" alt-boot-args" getenv dup -1 <> if 89 s" boot-args" setenv ( c-addr/u -- ) 90 then 91 ." NoInstall/Recovery mode boot. login/pw: root/root" cr 92 else 93 s" boot_single" 2dup getenv -1 <> if 94 drop ( c-addr/u c-addr -- c-addr/u ) \ unused 95 unsetenv ( c-addr/u -- ) 96 else 97 2drop ( c-addr/u -- ) \ unused 98 s" set boot_single=YES" evaluate 99 then 100 then 101 0 boot ( state -- ) 102; 103 104\ 105\ Single User Mode 106\ 107 108: singleuser_enabled? ( -- flag ) 109 s" boot_single" getenv -1 <> dup if 110 swap drop ( c-addr flag -- flag ) 111 then 112; 113 114: singleuser_enable ( -- ) 115 s" set boot_single=YES" evaluate 116; 117 118: singleuser_disable ( -- ) 119 s" boot_single" unsetenv 120; 121 122: init_singleuser ( N -- N ) 123 singleuser_enabled? if 124 toggle_menuitem ( n -- n ) 125 then 126; 127 128: toggle_singleuser ( N -- N TRUE ) 129 toggle_menuitem 130 menu-redraw 131 132 \ Now we're going to make the change effective 133 134 dup toggle_stateN @ 0= if 135 singleuser_disable 136 else 137 singleuser_enable 138 then 139 140 TRUE \ loop menu again 141; 142 143\ 144\ Verbose Boot 145\ 146 147: verbose_enabled? ( -- flag ) 148 s" boot_verbose" getenv -1 <> dup if 149 swap drop ( c-addr flag -- flag ) 150 then 151; 152 153: verbose_enable ( -- ) 154 s" set boot_verbose=YES" evaluate 155; 156 157: verbose_disable ( -- ) 158 s" boot_verbose" unsetenv 159; 160 161: init_verbose ( N -- N ) 162 verbose_enabled? if 163 toggle_menuitem ( n -- n ) 164 then 165; 166 167: toggle_verbose ( N -- N TRUE ) 168 toggle_menuitem 169 menu-redraw 170 171 \ Now we're going to make the change effective 172 173 dup toggle_stateN @ 0= if 174 verbose_disable 175 else 176 verbose_enable 177 then 178 179 TRUE \ loop menu again 180; 181 182\ 183\ Reconfiguration boot 184\ 185 186: reconfigure_enabled? ( -- flag ) 187 s" boot_reconfigure" getenv -1 <> dup if 188 swap drop ( c-addr flag -- flag ) 189 then 190; 191 192: reconfigure_enable ( -- ) 193 s" set boot_reconfigure=YES" evaluate 194; 195 196: reconfigure_disable ( -- ) 197 s" boot_reconfigure" unsetenv 198; 199 200: init_reconfigure ( N -- N ) 201 reconfigure_enabled? if 202 toggle_menuitem ( n -- n ) 203 then 204; 205 206: toggle_reconfigure ( N -- N TRUE ) 207 toggle_menuitem 208 menu-redraw 209 210 \ Now we're going to make the change effective 211 212 dup toggle_stateN @ 0= if 213 reconfigure_disable 214 else 215 reconfigure_enable 216 then 217 218 TRUE \ loop menu again 219; 220 221\ 222\ Framebuffer 223\ 224 225: init_framebuffer ( N -- N ) 226 framebuffer? if 227 toggle_menuitem ( n -- n ) 228 then 229; 230 231: toggle_framebuffer ( N -- N TRUE ) 232 toggle_menuitem 233 234 dup toggle_stateN @ 0= if 235 s" off" 236 else 237 s" on" 238 then 1 framebuffer 239 240 draw-beastie 241 draw-brand 242 menu-init \ needed to reset menu position 243 menu-redraw 244 245 TRUE \ loop menu again 246; 247 248\ 249\ Escape to Prompt 250\ 251 252: goto_prompt ( N -- N FALSE ) 253 254 s" set autoboot_delay=NO" evaluate 255 256 cr 257 ." To get back to the menu, type `menu' and press ENTER" cr 258 ." or type `boot' and press ENTER to start illumos." cr 259 cr 260 261 FALSE \ exit the menu 262; 263 264\ 265\ Cyclestate (used by osconsole/acpi/kmdb below) 266\ 267 268: init_cyclestate ( N K -- N ) 269 over cycle_stateN ( n k -- n k addr ) 270 begin 271 tuck @ ( n k addr -- n addr k c ) 272 over <> ( n addr k c -- n addr k 0|-1 ) 273 while 274 rot ( n addr k -- addr k n ) 275 cycle_menuitem 276 swap rot ( addr k n -- n k addr ) 277 repeat 278 2drop ( n k addr -- n ) 279; 280 281\ 282\ OS Console 283\ getenv os_console, if not set getenv console, if not set, default to "text" 284\ allowed serial consoles: ttya .. ttyd 285\ if new console will be added (graphics?), this section needs to be updated 286\ 287: init_osconsole ( N -- N ) 288 s" os_console" getenv dup -1 = if 289 drop 290 s" console" getenv dup -1 = if 291 drop 0 \ default to text 292 then 293 then ( n c-addr/u | n 0 ) 294 295 dup 0<> if ( n c-addr/u ) 296 \ because all usable console names have 4 chars, 297 \ we can only compare first 4 chars. 298 drop 4 299 2dup s" ttyd" compare 0= if 300 2drop 4 301 else 2dup s" ttyc" compare 0= if 302 2drop 3 303 else 2dup s" ttyb" compare 0= if 304 2drop 2 305 else 2dup s" ttya" compare 0= if 306 2drop 1 307 else 308 2drop 0 \ anything else defaults to text 309 then then then then 310 then 311 osconsole_state ! 312; 313 314: activate_osconsole ( N -- N ) 315 dup cycle_stateN @ ( n -- n n2 ) 316 dup osconsole_state ! ( n n2 -- n n2 ) \ copy for re-initialization 317 318 case 319 0 of s" text" endof 320 1 of s" ttya" endof 321 2 of s" ttyb" endof 322 3 of s" ttyc" endof 323 4 of s" ttyd" endof 324 dup s" unknown state: " type . cr 325 endcase 326 s" os_console" setenv 327; 328 329: cycle_osconsole ( N -- N TRUE ) 330 cycle_menuitem \ cycle cycle_stateN to next value 331 activate_osconsole \ apply current cycle_stateN 332 menu-redraw \ redraw menu 333 TRUE \ loop menu again 334; 335 336\ 337\ ACPI 338\ 339: init_acpi ( N -- N ) 340 s" acpi-user-options" getenv dup -1 <> if 341 evaluate \ use ?number parse step 342 343 \ translate option to cycle state 344 case 345 1 of 1 acpi_state ! endof 346 2 of 2 acpi_state ! endof 347 4 of 3 acpi_state ! endof 348 8 of 4 acpi_state ! endof 349 0 acpi_state ! 350 endcase 351 else 352 drop 353 then 354; 355 356: activate_acpi ( N -- N ) 357 dup cycle_stateN @ ( n -- n n2 ) 358 dup acpi_state ! ( n n2 -- n n2 ) \ copy for re-initialization 359 360 \ if N == 0, it's default, just unset env. 361 dup 0= if 362 drop 363 s" acpi-user-options" unsetenv 364 else 365 case 366 1 of s" 1" endof 367 2 of s" 2" endof 368 3 of s" 4" endof 369 4 of s" 8" endof 370 endcase 371 s" acpi-user-options" setenv 372 then 373; 374 375: cycle_acpi ( N -- N TRUE ) 376 cycle_menuitem \ cycle cycle_stateN to next value 377 activate_acpi \ apply current cycle_stateN 378 menu-redraw \ redraw menu 379 TRUE \ loop menu again 380; 381 382\ 383\ kmdb 384\ 385 386: kmdb_disable 387 s" boot_kmdb" unsetenv 388 s" boot_drop_into_kmdb" unsetenv 389; 390 391: init_kmdb ( N -- N ) 392 \ Retrieve the contents of "nmi" or default to "panic" 393 ( N -- N c-addr/u ) 394 s" nmi" getenv dup -1 <> if else drop s" panic" then 395 \ Store the string in "nmi_initial" if not already set 396 \ (to support re-entering the menu from the loader prompt) 397 s" nmi_initial" getenv? if else 398 2dup s" nmi_initial" setenv 399 then 400 ( N caddr/u -- N flag ) 401 s" kmdb" compare if false else true then 402 403 s" boot_kmdb" getenv -1 <> if 404 drop 405 s" boot_drop_into_kmdb" getenv -1 <> if 406 drop 407 if 4 else 3 then 408 else 409 if 2 else 1 then 410 then 411 else 412 drop \ drop flag 413 0 414 then 415 kmdb_state ! 416; 417 418: activate_kmdb ( N -- N ) 419 dup cycle_stateN @ ( n -- n n2 ) 420 dup kmdb_state ! ( n n2 -- n n2 ) 421 422 \ Reset "nmi" to its initial value 423 s" nmi_initial" getenv s" nmi" setenv 424 425 case 4 of \ drop + nmi=kmdb 426 s" set boot_kmdb=YES" evaluate 427 s" set boot_drop_into_kmdb=YES" evaluate 428 s" set nmi=kmdb" evaluate 429 endof 3 of \ drop 430 s" set boot_kmdb=YES" evaluate 431 s" set boot_drop_into_kmdb=YES" evaluate 432 endof 2 of \ load + nmi=kmdb 433 s" set boot_kmdb=YES" evaluate 434 s" boot_drop_into_kmdb" unsetenv 435 s" set nmi=kmdb" evaluate 436 endof 1 of \ load 437 s" set boot_kmdb=YES" evaluate 438 s" boot_drop_into_kmdb" unsetenv 439 endof 440 kmdb_disable 441 endcase 442; 443 444: cycle_kmdb ( N -- N TRUE ) 445 cycle_menuitem \ cycle cycle_stateN to next value 446 activate_kmdb \ apply current cycle_stateN 447 menu-redraw \ redraw menu 448 TRUE \ loop menu again 449; 450 451\ 452\ Menusets 453\ 454 455: goto_menu ( N M -- N TRUE ) 456 menu-unset 457 menuset-loadsetnum ( n m -- n ) 458 menu-redraw 459 TRUE \ Loop menu again 460; 461 462\ 463\ Defaults 464\ 465 466: unset_boot_options 467 0 acpi_state ! 468 s" acpi-user-options" unsetenv 469 s" boot-args" unsetenv 470 s" boot_ask" unsetenv 471 singleuser_disable 472 verbose_disable 473 kmdb_disable \ disables drop_into_kmdb as well 474 reconfigure_disable 475; 476 477: set_default_boot_options ( N -- N TRUE ) 478 unset_boot_options 479 2 goto_menu 480; 481 482\ 483\ Set boot environment defaults 484\ 485 486 487: init_bootenv ( -- ) 488 s" set menu_caption[1]=${bemenu_current}${zfs_be_active}" evaluate 489 s" set ansi_caption[1]=${beansi_current}${zfs_be_active}" evaluate 490 s" set menu_caption[2]=${bemenu_bootfs}${currdev}" evaluate 491 s" set ansi_caption[2]=${beansi_bootfs}${currdev}" evaluate 492 s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate 493 s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate 494; 495 496\ 497\ Redraw the entire screen. A long BE name can corrupt the menu 498\ 499 500: be_draw_screen 501 clear \ Clear the screen (in screen.4th) 502 print_version \ print version string (bottom-right; see version.4th) 503 draw-beastie \ Draw FreeBSD logo at right (in beastie.4th) 504 draw-brand \ Draw brand.4th logo at top (in brand.4th) 505 menu-init \ Initialize menu and draw bounding box (in menu.4th) 506; 507 508\ 509\ Select a boot environment 510\ 511 512: set_bootenv ( N -- N TRUE ) 513 dup s" bootenv_root[E]" 13 +c! getenv 514 s" currdev" getenv compare 0= if 515 s" zfs_be_active" getenv type ." is already active" 516 else 517 dup s" set currdev=${bootenv_root[E]}" 27 +c! evaluate 518 dup s" bootenvmenu_caption[E]" 20 +c! getenv 519 s" zfs_be_active" setenv 520 ." Activating " s" currdev" getenv type cr 521 s" unload" evaluate 522 free-module-options 523 unset_boot_options 524 s" /boot/defaults/loader.conf" read-conf 525 s" /boot/loader.conf" read-conf 526 s" /boot/loader.conf.local" read-conf 527 init_bootenv 528 529 s" 1" s" zfs_be_currpage" setenv 530 s" be-set-page" evaluate 531 then 532 533 500 ms \ sleep so user can see the message 534 be_draw_screen 535 menu-redraw 536 TRUE 537; 538 539\ 540\ Chainload this entry. Normally we do not return, in case of error 541\ from chain load, we continue with normal menu code. 542\ 543 544: set_be_chain ( N -- no return | N TRUE ) 545 dup s" chain ${bootenv_root[E]}" 21 +c! evaluate catch drop 546 547 menu-redraw 548 TRUE 549; 550 551\ 552\ Switch to the next page of boot environments 553\ 554 555: set_be_page ( N -- N TRUE ) 556 s" zfs_be_currpage" getenv dup -1 = if 557 drop s" 1" 558 else 559 s2n 560 1+ \ increment the page number 561 dup 562 s" zfs_be_pages" getenv 563 s2n 564 > if drop 1 then 565 n2s 566 then 567 568 s" zfs_be_currpage" setenv 569 s" be-set-page" evaluate 570 3 goto_menu 571; 572 573only forth definitions 574