xref: /illumos-gate/usr/src/boot/forth/menu-commands.4th (revision 1fa2a66491e7d8ae0be84e7da4da8e812480c710)
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		2dup s" ttyd" compare 0= if
297			2drop 4
298		else 2dup s" ttyc" compare 0= if
299			2drop 3
300		else 2dup s" ttyb" compare 0= if
301			2drop 2
302		else 2dup s" ttya" compare 0= if
303			2drop 1
304		else
305			2drop 0		\ anything else defaults to text
306		then then then then
307	then
308	osconsole_state !
309;
310
311: activate_osconsole ( N -- N )
312	dup cycle_stateN @	( n -- n n2 )
313	dup osconsole_state !	( n n2 -- n n2 )  \ copy for re-initialization
314
315	case
316	0 of s" text" endof
317	1 of s" ttya" endof
318	2 of s" ttyb" endof
319	3 of s" ttyc" endof
320	4 of s" ttyd" endof
321	dup s" unknown state: " type . cr
322	endcase
323	s" os_console" setenv
324;
325
326: cycle_osconsole ( N -- N TRUE )
327	cycle_menuitem	\ cycle cycle_stateN to next value
328	activate_osconsole	\ apply current cycle_stateN
329	menu-redraw	\ redraw menu
330	TRUE		\ loop menu again
331;
332
333\
334\ ACPI
335\
336: init_acpi ( N -- N )
337	s" acpi-user-options" getenv dup -1 <> if
338		evaluate		\ use ?number parse step
339
340		\ translate option to cycle state
341		case
342		1 of 1 acpi_state ! endof
343		2 of 2 acpi_state ! endof
344		4 of 3 acpi_state ! endof
345		8 of 4 acpi_state ! endof
346		0 acpi_state !
347		endcase
348	else
349		drop
350	then
351;
352
353: activate_acpi ( N -- N )
354	dup cycle_stateN @	( n -- n n2 )
355	dup acpi_state !	( n n2 -- n n2 )  \ copy for re-initialization
356
357	\ if N == 0, it's default, just unset env.
358	dup 0= if
359		drop
360		s" acpi-user-options" unsetenv
361	else
362		case
363		1 of s" 1" endof
364		2 of s" 2" endof
365		3 of s" 4" endof
366		4 of s" 8" endof
367		endcase
368		s" acpi-user-options" setenv
369	then
370;
371
372: cycle_acpi ( N -- N TRUE )
373	cycle_menuitem	\ cycle cycle_stateN to next value
374	activate_acpi	\ apply current cycle_stateN
375	menu-redraw	\ redraw menu
376	TRUE		\ loop menu again
377;
378
379\
380\ kmdb
381\
382
383: kmdb_disable
384	s" boot_kmdb" unsetenv
385	s" boot_drop_into_kmdb" unsetenv
386;
387
388: init_kmdb ( N -- N )
389	\ Retrieve the contents of "nmi" or default to "panic"
390	( N -- N c-addr/u )
391	s" nmi" getenv dup -1 <> if else drop s" panic" then
392	\ Store the string in "nmi_initial" if not already set
393	\ (to support re-entering the menu from the loader prompt)
394	s" nmi_initial" getenv? if else
395		2dup s" nmi_initial" setenv
396	then
397	( N caddr/u -- N flag )
398	s" kmdb" compare if false else true then
399
400	s" boot_kmdb" getenv -1 <> if
401		drop
402		s" boot_drop_into_kmdb" getenv -1 <> if
403			drop
404			if 4 else 3 then
405		else
406			if 2 else 1 then
407		then
408	else
409		drop	\ drop flag
410		0
411	then
412	kmdb_state !
413;
414
415: activate_kmdb ( N -- N )
416	dup cycle_stateN @	( n -- n n2 )
417	dup kmdb_state !	( n n2 -- n n2 )
418
419	\ Reset "nmi" to its initial value
420	s" nmi_initial" getenv s" nmi" setenv
421
422	case 4 of		\ drop + nmi=kmdb
423		s" set boot_kmdb=YES" evaluate
424		s" set boot_drop_into_kmdb=YES" evaluate
425		s" set nmi=kmdb" evaluate
426	endof 3 of		\ drop
427		s" set boot_kmdb=YES" evaluate
428		s" set boot_drop_into_kmdb=YES" evaluate
429	endof 2 of		\ load + nmi=kmdb
430		s" set boot_kmdb=YES" evaluate
431		s" boot_drop_into_kmdb" unsetenv
432		s" set nmi=kmdb" evaluate
433	endof 1 of		\ load
434		s" set boot_kmdb=YES" evaluate
435		s" boot_drop_into_kmdb" unsetenv
436	endof
437		kmdb_disable
438	endcase
439;
440
441: cycle_kmdb ( N -- N TRUE )
442	cycle_menuitem	\ cycle cycle_stateN to next value
443	activate_kmdb	\ apply current cycle_stateN
444	menu-redraw	\ redraw menu
445	TRUE		\ loop menu again
446;
447
448\
449\ Menusets
450\
451
452: goto_menu ( N M -- N TRUE )
453	menu-unset
454	menuset-loadsetnum ( n m -- n )
455	menu-redraw
456	TRUE \ Loop menu again
457;
458
459\
460\ Defaults
461\
462
463: unset_boot_options
464	0 acpi_state !
465	s" acpi-user-options" unsetenv
466	s" boot-args" unsetenv
467	s" boot_ask" unsetenv
468	singleuser_disable
469	verbose_disable
470	kmdb_disable		\ disables drop_into_kmdb as well
471	reconfigure_disable
472;
473
474: set_default_boot_options ( N -- N TRUE )
475	unset_boot_options
476	2 goto_menu
477;
478
479\
480\ Set boot environment defaults
481\
482
483
484: init_bootenv ( -- )
485	s" set menu_caption[1]=${bemenu_current}${zfs_be_active}" evaluate
486	s" set ansi_caption[1]=${beansi_current}${zfs_be_active}" evaluate
487	s" set menu_caption[2]=${bemenu_bootfs}${currdev}" evaluate
488	s" set ansi_caption[2]=${beansi_bootfs}${currdev}" evaluate
489	s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
490	s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
491;
492
493\
494\ Redraw the entire screen. A long BE name can corrupt the menu
495\
496
497: be_draw_screen
498	clear		\ Clear the screen (in screen.4th)
499	print_version	\ print version string (bottom-right; see version.4th)
500	draw-beastie	\ Draw FreeBSD logo at right (in beastie.4th)
501	draw-brand	\ Draw brand.4th logo at top (in brand.4th)
502	menu-init	\ Initialize menu and draw bounding box (in menu.4th)
503;
504
505\
506\ Select a boot environment
507\
508
509: set_bootenv ( N -- N TRUE )
510	dup s" bootenv_root[E]" 13 +c! getenv
511	s" currdev" getenv compare 0= if
512		s" zfs_be_active" getenv type ."  is already active"
513	else
514		dup s" set currdev=${bootenv_root[E]}" 27 +c! evaluate
515		dup s" bootenvmenu_caption[E]" 20 +c! getenv
516		s" zfs_be_active" setenv
517		." Activating " s" currdev" getenv type cr
518		s" unload" evaluate
519		free-module-options
520		unset_boot_options
521		s" /boot/defaults/loader.conf" read-conf
522		s" /boot/loader.conf" read-conf
523		s" /boot/loader.conf.local" read-conf
524		init_bootenv
525
526		s" 1" s" zfs_be_currpage" setenv
527		s" be-set-page" evaluate
528	then
529
530	500 ms			\ sleep so user can see the message
531	be_draw_screen
532	menu-redraw
533	TRUE
534;
535
536\
537\ Chainload this entry. Normally we do not return, in case of error
538\ from chain load, we continue with normal menu code.
539\
540
541: set_be_chain ( N -- no return | N TRUE )
542	dup s" chain ${bootenv_root[E]}" 21 +c! evaluate catch drop
543
544	menu-redraw
545	TRUE
546;
547
548\
549\ Switch to the next page of boot environments
550\
551
552: set_be_page ( N -- N TRUE )
553	s" zfs_be_currpage" getenv dup -1 = if
554		drop s" 1"
555	else
556		s2n
557		1+		\ increment the page number
558		dup
559		s" zfs_be_pages" getenv
560		s2n
561		> if drop 1 then
562		n2s
563	then
564
565	s" zfs_be_currpage" setenv
566	s" be-set-page" evaluate
567	3 goto_menu
568;
569
570only forth definitions
571