xref: /illumos-gate/usr/src/boot/forth/menu-commands.4th (revision ddb365bfc9e868ad24ccdcb0dc91af18b10df082)
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