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
26marker task-menu-commands.4th
27
28include /boot/menusets.4th
29
30only forth definitions
31
32variable kernel_state
33variable root_state
340 kernel_state !
350 root_state !
36
37also menu-namespace also menu-command-helpers
38
39\ 
40\ Boot
41\ 
42
43: init_boot ( N -- N )
44	dup
45	s" boot_single" getenv -1 <> if
46		drop ( n n c-addr -- n n ) \ unused
47		toggle_menuitem ( n n -- n n )
48		s" set menu_keycode[N]=115" \ base command to execute
49	else
50		s" set menu_keycode[N]=98" \ base command to execute
51	then
52	17 +c! \ replace 'N' with ASCII numeral
53	evaluate
54;
55
56\ 
57\ Alternate Boot
58\ 
59
60: init_altboot ( N -- N )
61	dup
62	s" boot_single" getenv -1 <> if
63		drop ( n c-addr -- n ) \ unused
64		toggle_menuitem ( n -- n )
65		s" set menu_keycode[N]=109" \ base command to execute
66	else
67		s" set menu_keycode[N]=115" \ base command to execute
68	then
69	17 +c! \ replace 'N' with ASCII numeral
70	evaluate
71;
72
73: altboot ( N -- NOTREACHED )
74	s" boot_single" 2dup getenv -1 <> if
75		drop ( c-addr/u c-addr -- c-addr/u ) \ unused
76		unsetenv ( c-addr/u -- )
77	else
78		2drop ( c-addr/u -- ) \ unused
79		s" set boot_single=YES" evaluate
80	then
81	0 boot ( state -- )
82;
83
84\ 
85\ ACPI
86\ 
87
88: acpi_enable ( -- )
89	s" set acpi_load=YES" evaluate \ XXX deprecated but harmless
90	s" set hint.acpi.0.disabled=0" evaluate
91	s" loader.acpi_disabled_by_user" unsetenv
92;
93
94: acpi_disable ( -- )
95	s" acpi_load" unsetenv \ XXX deprecated but harmless
96	s" set hint.acpi.0.disabled=1" evaluate
97	s" set loader.acpi_disabled_by_user=1" evaluate
98;
99
100: toggle_acpi ( N -- N TRUE )
101
102	\ Make changes effective _before_ calling menu-redraw
103
104	acpienabled? if
105		acpi_disable
106	else
107		acpi_enable
108	then
109
110	menu-redraw
111
112	TRUE \ loop menu again
113;
114
115\ 
116\ Safe Mode
117\ 
118
119: safemode_enabled? ( -- flag )
120	s" kern.smp.disabled" getenv -1 <> dup if
121		swap drop ( c-addr flag -- flag )
122	then
123;
124
125: safemode_enable ( -- )
126	s" set kern.smp.disabled=1" evaluate
127	s" set hw.ata.ata_dma=0" evaluate
128	s" set hw.ata.atapi_dma=0" evaluate
129	s" set kern.eventtimer.periodic=1" evaluate
130	s" set kern.geom.part.check_integrity=0" evaluate
131;
132
133: safemode_disable ( -- )
134	s" kern.smp.disabled" unsetenv
135	s" hw.ata.ata_dma" unsetenv
136	s" hw.ata.atapi_dma" unsetenv
137	s" kern.eventtimer.periodic" unsetenv
138	s" kern.geom.part.check_integrity" unsetenv
139;
140
141: init_safemode ( N -- N )
142	safemode_enabled? if
143		toggle_menuitem ( n -- n )
144	then
145;
146
147: toggle_safemode ( N -- N TRUE )
148	toggle_menuitem
149
150	\ Now we're going to make the change effective
151
152	dup toggle_stateN @ 0= if
153		safemode_disable
154	else
155		safemode_enable
156	then
157
158	menu-redraw
159
160	TRUE \ loop menu again
161;
162
163\ 
164\ Single User Mode
165\ 
166
167: singleuser_enabled? ( -- flag )
168	s" boot_single" getenv -1 <> dup if
169		swap drop ( c-addr flag -- flag )
170	then
171;
172
173: singleuser_enable ( -- )
174	s" set boot_single=YES" evaluate
175;
176
177: singleuser_disable ( -- )
178	s" boot_single" unsetenv
179;
180
181: init_singleuser ( N -- N )
182	singleuser_enabled? if
183		toggle_menuitem ( n -- n )
184	then
185;
186
187: toggle_singleuser ( N -- N TRUE )
188	toggle_menuitem
189	menu-redraw
190
191	\ Now we're going to make the change effective
192
193	dup toggle_stateN @ 0= if
194		singleuser_disable
195	else
196		singleuser_enable
197	then
198
199	TRUE \ loop menu again
200;
201
202\ 
203\ Verbose Boot
204\ 
205
206: verbose_enabled? ( -- flag )
207	s" boot_verbose" getenv -1 <> dup if
208		swap drop ( c-addr flag -- flag )
209	then
210;
211
212: verbose_enable ( -- )
213	s" set boot_verbose=YES" evaluate
214;
215
216: verbose_disable ( -- )
217	s" boot_verbose" unsetenv
218;
219
220: init_verbose ( N -- N )
221	verbose_enabled? if
222		toggle_menuitem ( n -- n )
223	then
224;
225
226: toggle_verbose ( N -- N TRUE )
227	toggle_menuitem
228	menu-redraw
229
230	\ Now we're going to make the change effective
231
232	dup toggle_stateN @ 0= if
233		verbose_disable
234	else
235		verbose_enable
236	then
237
238	TRUE \ loop menu again
239;
240
241\ 
242\ Escape to Prompt
243\ 
244
245: goto_prompt ( N -- N FALSE )
246
247	s" set autoboot_delay=NO" evaluate
248
249	cr
250	." To get back to the menu, type `menu' and press ENTER" cr
251	." or type `boot' and press ENTER to start FreeBSD." cr
252	cr
253
254	FALSE \ exit the menu
255;
256
257\ 
258\ Cyclestate (used by kernel/root below)
259\ 
260
261: init_cyclestate ( N K -- N )
262	over cycle_stateN ( n k -- n k addr )
263	begin
264		tuck @  ( n k addr -- n addr k c )
265		over <> ( n addr k c -- n addr k 0|-1 )
266	while
267		rot ( n addr k -- addr k n )
268		cycle_menuitem
269		swap rot ( addr k n -- n k addr )
270	repeat
271	2drop ( n k addr -- n )
272;
273
274\
275\ Kernel
276\ 
277
278: init_kernel ( N -- N )
279	kernel_state @  ( n -- n k )
280	init_cyclestate ( n k -- n )
281;
282
283: activate_kernel ( N -- N )
284	dup cycle_stateN @	( n -- n n2 )
285	dup kernel_state !	( n n2 -- n n2 )  \ copy for re-initialization
286	48 +			( n n2 -- n n2' ) \ kernel_state to ASCII num
287
288	s" set kernel=${kernel_prefix}${kernel[N]}${kernel_suffix}"
289	36 +c!		( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num
290	evaluate	( n c-addr/u -- n ) \ sets $kernel to full kernel-path
291;
292
293: cycle_kernel ( N -- N TRUE )
294	cycle_menuitem	\ cycle cycle_stateN to next value
295	activate_kernel \ apply current cycle_stateN
296	menu-redraw	\ redraw menu
297	TRUE		\ loop menu again
298;
299
300\ 
301\ Root
302\ 
303
304: init_root ( N -- N )
305	root_state @    ( n -- n k )
306	init_cyclestate ( n k -- n )
307;
308
309: activate_root ( N -- N )
310	dup cycle_stateN @	( n -- n n2 )
311	dup root_state !	( n n2 -- n n2 )  \ copy for re-initialization
312	48 +			( n n2 -- n n2' ) \ root_state to ASCII num
313
314	s" set root=${root_prefix}${root[N]}${root_suffix}"
315	30 +c!		( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num
316	evaluate	( n c-addr/u -- n ) \ sets $root to full kernel-path
317;
318
319: cycle_root ( N -- N TRUE )
320	cycle_menuitem	\ cycle cycle_stateN to next value
321	activate_root	\ apply current cycle_stateN
322	menu-redraw	\ redraw menu
323	TRUE		\ loop menu again
324;
325
326\ 
327\ Menusets
328\ 
329
330: goto_menu ( N M -- N TRUE )
331	menu-unset
332	menuset-loadsetnum ( n m -- n )
333	menu-redraw
334	TRUE \ Loop menu again
335;
336
337\ 
338\ Defaults
339\ 
340
341: set_default_boot_options ( N -- N TRUE )
342	acpi_enable
343	safemode_disable
344	singleuser_disable
345	verbose_disable
346	2 goto_menu
347;
348
349\ 
350\ Set boot environment defaults
351\ 
352
353: init_bootenv ( -- )
354	s" set menu_caption[1]=${bemenu_current}${vfs.root.mountfrom}" evaluate
355	s" set ansi_caption[1]=${beansi_current}${vfs.root.mountfrom}" evaluate
356	s" set menu_caption[2]=${bemenu_bootfs}${zfs_be_active}" evaluate
357	s" set ansi_caption[2]=${beansi_bootfs}${zfs_be_active}" evaluate
358	s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
359	s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
360;
361
362\
363\ Redraw the entire screen. A long BE name can corrupt the menu
364\ 
365
366: be_draw_screen
367	clear		\ Clear the screen (in screen.4th)
368	print_version	\ print version string (bottom-right; see version.4th)
369	draw-beastie	\ Draw FreeBSD logo at right (in beastie.4th)
370	draw-brand	\ Draw brand.4th logo at top (in brand.4th)
371	menu-init	\ Initialize menu and draw bounding box (in menu.4th)
372;
373
374\
375\ Select a boot environment
376\ 
377
378: set_bootenv ( N -- N TRUE )
379	dup s" set vfs.root.mountfrom=${bootenv_root[E]}" 38 +c! evaluate
380	s" set currdev=${vfs.root.mountfrom}:" evaluate
381	s" unload" evaluate
382	free-module-options
383	s" /boot/defaults/loader.conf" read-conf
384	s" /boot/loader.conf" read-conf
385	s" /boot/loader.conf.local" read-conf
386	init_bootenv
387	be_draw_screen
388	menu-redraw
389	TRUE
390;
391
392\
393\ Switch to the next page of boot environments
394\
395
396: set_be_page ( N -- N TRUE )
397	s" zfs_be_currpage" getenv dup -1 = if
398		drop s" 1"
399	else
400		0 s>d 2swap
401		>number ( ud caddr/u -- ud' caddr'/u' )	\ convert string to numbers
402		2drop					\ drop the string
403		1 um/mod ( ud u1 -- u2 u3 ) 		\ convert double ud' to single u3' and remainder u2
404		swap drop ( ud2 u3 -- u3 )		\ drop the remainder u2
405		1+					\ increment the page number
406		s>d <# #s #>				\ convert back to a string
407	then
408	s" zfs_be_currpage" setenv
409	s" reloadbe" evaluate
410	3 goto_menu
411;
412
413only forth definitions
414