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