1281843Sdteske\ Copyright (c) 2006-2015 Devin Teske <dteske@FreeBSD.org>
2222417Sjulian\ All rights reserved.
3222417Sjulian\ 
4222417Sjulian\ Redistribution and use in source and binary forms, with or without
5222417Sjulian\ modification, are permitted provided that the following conditions
6222417Sjulian\ are met:
7222417Sjulian\ 1. Redistributions of source code must retain the above copyright
8222417Sjulian\    notice, this list of conditions and the following disclaimer.
9222417Sjulian\ 2. Redistributions in binary form must reproduce the above copyright
10222417Sjulian\    notice, this list of conditions and the following disclaimer in the
11222417Sjulian\    documentation and/or other materials provided with the distribution.
12222417Sjulian\ 
13222417Sjulian\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14222417Sjulian\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15222417Sjulian\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16222417Sjulian\ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17222417Sjulian\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18222417Sjulian\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19222417Sjulian\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20222417Sjulian\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21222417Sjulian\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22222417Sjulian\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23222417Sjulian\ SUCH DAMAGE.
24222417Sjulian\ 
25222417Sjulian\ $FreeBSD: releng/10.3/sys/boot/forth/menu-commands.4th 293802 2016-01-13 01:50:02Z allanjude $
26222417Sjulian
27222417Sjulianmarker task-menu-commands.4th
28222417Sjulian
29242667Sdteskeinclude /boot/menusets.4th
30242667Sdteske
31281843Sdteskeonly forth definitions
32281843Sdteske
33241523Sdteskevariable kernel_state
34241523Sdteskevariable root_state
35262701Sdteske0 kernel_state !
36262701Sdteske0 root_state !
37241523Sdteske
38281843Sdteskealso menu-namespace also menu-command-helpers
39281843Sdteske
40243114Sdteske\ 
41243660Sdteske\ Boot
42243660Sdteske\ 
43243660Sdteske
44243660Sdteske: init_boot ( N -- N )
45243660Sdteske	dup
46243660Sdteske	s" boot_single" getenv -1 <> if
47243660Sdteske		drop ( n n c-addr -- n n ) \ unused
48243660Sdteske		toggle_menuitem ( n n -- n n )
49243660Sdteske		s" set menu_keycode[N]=115" \ base command to execute
50243660Sdteske	else
51243660Sdteske		s" set menu_keycode[N]=98" \ base command to execute
52243660Sdteske	then
53243660Sdteske	17 +c! \ replace 'N' with ASCII numeral
54243660Sdteske	evaluate
55243660Sdteske;
56243660Sdteske
57243660Sdteske\ 
58243660Sdteske\ Alternate Boot
59243660Sdteske\ 
60243660Sdteske
61243660Sdteske: init_altboot ( N -- N )
62243660Sdteske	dup
63243660Sdteske	s" boot_single" getenv -1 <> if
64243660Sdteske		drop ( n c-addr -- n ) \ unused
65243660Sdteske		toggle_menuitem ( n -- n )
66243660Sdteske		s" set menu_keycode[N]=109" \ base command to execute
67243660Sdteske	else
68243660Sdteske		s" set menu_keycode[N]=115" \ base command to execute
69243660Sdteske	then
70243660Sdteske	17 +c! \ replace 'N' with ASCII numeral
71243660Sdteske	evaluate
72243660Sdteske;
73243660Sdteske
74281843Sdteske: altboot ( N -- NOTREACHED )
75243660Sdteske	s" boot_single" 2dup getenv -1 <> if
76243660Sdteske		drop ( c-addr/u c-addr -- c-addr/u ) \ unused
77243660Sdteske		unsetenv ( c-addr/u -- )
78243660Sdteske	else
79243660Sdteske		2drop ( c-addr/u -- ) \ unused
80243660Sdteske		s" set boot_single=YES" evaluate
81243660Sdteske	then
82243660Sdteske	0 boot ( state -- )
83243660Sdteske;
84243660Sdteske
85243660Sdteske\ 
86243114Sdteske\ ACPI
87243114Sdteske\ 
88243114Sdteske
89222417Sjulian: acpi_enable ( -- )
90222417Sjulian	s" set acpi_load=YES" evaluate \ XXX deprecated but harmless
91222417Sjulian	s" set hint.acpi.0.disabled=0" evaluate
92222417Sjulian	s" loader.acpi_disabled_by_user" unsetenv
93222417Sjulian;
94222417Sjulian
95222417Sjulian: acpi_disable ( -- )
96222417Sjulian	s" acpi_load" unsetenv \ XXX deprecated but harmless
97222417Sjulian	s" set hint.acpi.0.disabled=1" evaluate
98222417Sjulian	s" set loader.acpi_disabled_by_user=1" evaluate
99222417Sjulian;
100222417Sjulian
101222417Sjulian: toggle_acpi ( N -- N TRUE )
102222417Sjulian
103222417Sjulian	\ Make changes effective _before_ calling menu-redraw
104222417Sjulian
105222417Sjulian	acpienabled? if
106222417Sjulian		acpi_disable
107222417Sjulian	else
108222417Sjulian		acpi_enable
109222417Sjulian	then
110222417Sjulian
111222417Sjulian	menu-redraw
112222417Sjulian
113222417Sjulian	TRUE \ loop menu again
114222417Sjulian;
115222417Sjulian
116243114Sdteske\ 
117243114Sdteske\ Safe Mode
118243114Sdteske\ 
119243114Sdteske
120243114Sdteske: safemode_enabled? ( -- flag )
121243114Sdteske	s" kern.smp.disabled" getenv -1 <> dup if
122243114Sdteske		swap drop ( c-addr flag -- flag )
123243114Sdteske	then
124243114Sdteske;
125243114Sdteske
126243114Sdteske: safemode_enable ( -- )
127243114Sdteske	s" set kern.smp.disabled=1" evaluate
128243114Sdteske	s" set hw.ata.ata_dma=0" evaluate
129243114Sdteske	s" set hw.ata.atapi_dma=0" evaluate
130243114Sdteske	s" set hw.ata.wc=0" evaluate
131243114Sdteske	s" set hw.eisa_slots=0" evaluate
132243114Sdteske	s" set kern.eventtimer.periodic=1" evaluate
133243114Sdteske	s" set kern.geom.part.check_integrity=0" evaluate
134243114Sdteske;
135243114Sdteske
136243114Sdteske: safemode_disable ( -- )
137243114Sdteske	s" kern.smp.disabled" unsetenv
138243114Sdteske	s" hw.ata.ata_dma" unsetenv
139243114Sdteske	s" hw.ata.atapi_dma" unsetenv
140243114Sdteske	s" hw.ata.wc" unsetenv
141243114Sdteske	s" hw.eisa_slots" unsetenv
142243114Sdteske	s" kern.eventtimer.periodic" unsetenv
143243114Sdteske	s" kern.geom.part.check_integrity" unsetenv
144243114Sdteske;
145243114Sdteske
146241523Sdteske: init_safemode ( N -- N )
147243114Sdteske	safemode_enabled? if
148241523Sdteske		toggle_menuitem ( n -- n )
149241523Sdteske	then
150241523Sdteske;
151241523Sdteske
152222417Sjulian: toggle_safemode ( N -- N TRUE )
153222417Sjulian	toggle_menuitem
154222417Sjulian
155222417Sjulian	\ Now we're going to make the change effective
156222417Sjulian
157243114Sdteske	dup toggle_stateN @ 0= if
158243114Sdteske		safemode_disable
159222417Sjulian	else
160243114Sdteske		safemode_enable
161222417Sjulian	then
162222417Sjulian
163222417Sjulian	menu-redraw
164222417Sjulian
165222417Sjulian	TRUE \ loop menu again
166222417Sjulian;
167222417Sjulian
168243114Sdteske\ 
169243114Sdteske\ Single User Mode
170243114Sdteske\ 
171243114Sdteske
172243114Sdteske: singleuser_enabled? ( -- flag )
173243114Sdteske	s" boot_single" getenv -1 <> dup if
174243114Sdteske		swap drop ( c-addr flag -- flag )
175243114Sdteske	then
176243114Sdteske;
177243114Sdteske
178243114Sdteske: singleuser_enable ( -- )
179243114Sdteske	s" set boot_single=YES" evaluate
180243114Sdteske;
181243114Sdteske
182243114Sdteske: singleuser_disable ( -- )
183243114Sdteske	s" boot_single" unsetenv
184243114Sdteske;
185243114Sdteske
186241523Sdteske: init_singleuser ( N -- N )
187243114Sdteske	singleuser_enabled? if
188241523Sdteske		toggle_menuitem ( n -- n )
189241523Sdteske	then
190241523Sdteske;
191241523Sdteske
192222417Sjulian: toggle_singleuser ( N -- N TRUE )
193222417Sjulian	toggle_menuitem
194222417Sjulian	menu-redraw
195222417Sjulian
196222417Sjulian	\ Now we're going to make the change effective
197222417Sjulian
198243114Sdteske	dup toggle_stateN @ 0= if
199243114Sdteske		singleuser_disable
200222417Sjulian	else
201243114Sdteske		singleuser_enable
202222417Sjulian	then
203222417Sjulian
204222417Sjulian	TRUE \ loop menu again
205222417Sjulian;
206222417Sjulian
207243114Sdteske\ 
208243114Sdteske\ Verbose Boot
209243114Sdteske\ 
210243114Sdteske
211243114Sdteske: verbose_enabled? ( -- flag )
212243114Sdteske	s" boot_verbose" getenv -1 <> dup if
213243114Sdteske		swap drop ( c-addr flag -- flag )
214243114Sdteske	then
215243114Sdteske;
216243114Sdteske
217243114Sdteske: verbose_enable ( -- )
218243114Sdteske	s" set boot_verbose=YES" evaluate
219243114Sdteske;
220243114Sdteske
221243114Sdteske: verbose_disable ( -- )
222243114Sdteske	s" boot_verbose" unsetenv
223243114Sdteske;
224243114Sdteske
225241523Sdteske: init_verbose ( N -- N )
226243114Sdteske	verbose_enabled? if
227241523Sdteske		toggle_menuitem ( n -- n )
228241523Sdteske	then
229241523Sdteske;
230241523Sdteske
231222417Sjulian: toggle_verbose ( N -- N TRUE )
232222417Sjulian	toggle_menuitem
233222417Sjulian	menu-redraw
234222417Sjulian
235222417Sjulian	\ Now we're going to make the change effective
236222417Sjulian
237243114Sdteske	dup toggle_stateN @ 0= if
238243114Sdteske		verbose_disable
239222417Sjulian	else
240243114Sdteske		verbose_enable
241222417Sjulian	then
242222417Sjulian
243222417Sjulian	TRUE \ loop menu again
244222417Sjulian;
245222417Sjulian
246243114Sdteske\ 
247243114Sdteske\ Escape to Prompt
248243114Sdteske\ 
249243114Sdteske
250222417Sjulian: goto_prompt ( N -- N FALSE )
251222417Sjulian
252222417Sjulian	s" set autoboot_delay=NO" evaluate
253222417Sjulian
254222417Sjulian	cr
255222417Sjulian	." To get back to the menu, type `menu' and press ENTER" cr
256222417Sjulian	." or type `boot' and press ENTER to start FreeBSD." cr
257222417Sjulian	cr
258222417Sjulian
259222417Sjulian	FALSE \ exit the menu
260222417Sjulian;
261222417Sjulian
262243114Sdteske\ 
263243114Sdteske\ Cyclestate (used by kernel/root below)
264243114Sdteske\ 
265243114Sdteske
266241523Sdteske: init_cyclestate ( N K -- N )
267243114Sdteske	over cycle_stateN ( n k -- n k addr )
268241523Sdteske	begin
269241523Sdteske		tuck @  ( n k addr -- n addr k c )
270241523Sdteske		over <> ( n addr k c -- n addr k 0|-1 )
271241523Sdteske	while
272241523Sdteske		rot ( n addr k -- addr k n )
273241523Sdteske		cycle_menuitem
274241523Sdteske		swap rot ( addr k n -- n k addr )
275241523Sdteske	repeat
276241523Sdteske	2drop ( n k addr -- n )
277241523Sdteske;
278241523Sdteske
279243114Sdteske\
280243114Sdteske\ Kernel
281243114Sdteske\ 
282243114Sdteske
283241523Sdteske: init_kernel ( N -- N )
284241523Sdteske	kernel_state @  ( n -- n k )
285241523Sdteske	init_cyclestate ( n k -- n )
286241523Sdteske;
287241523Sdteske
288262701Sdteske: activate_kernel ( N -- N )
289262701Sdteske	dup cycle_stateN @	( n -- n n2 )
290262701Sdteske	dup kernel_state !	( n n2 -- n n2 )  \ copy for re-initialization
291262701Sdteske	48 +			( n n2 -- n n2' ) \ kernel_state to ASCII num
292222417Sjulian
293222417Sjulian	s" set kernel=${kernel_prefix}${kernel[N]}${kernel_suffix}"
294262701Sdteske	36 +c!		( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num
295262701Sdteske	evaluate	( n c-addr/u -- n ) \ sets $kernel to full kernel-path
296262701Sdteske;
297222417Sjulian
298262701Sdteske: cycle_kernel ( N -- N TRUE )
299262701Sdteske	cycle_menuitem	\ cycle cycle_stateN to next value
300262701Sdteske	activate_kernel \ apply current cycle_stateN
301262701Sdteske	menu-redraw	\ redraw menu
302262701Sdteske	TRUE		\ loop menu again
303222417Sjulian;
304222417Sjulian
305243114Sdteske\ 
306243114Sdteske\ Root
307243114Sdteske\ 
308243114Sdteske
309241523Sdteske: init_root ( N -- N )
310241523Sdteske	root_state @    ( n -- n k )
311241523Sdteske	init_cyclestate ( n k -- n )
312241523Sdteske;
313241523Sdteske
314262701Sdteske: activate_root ( N -- N )
315262701Sdteske	dup cycle_stateN @	( n -- n n2 )
316262701Sdteske	dup root_state !	( n n2 -- n n2 )  \ copy for re-initialization
317262701Sdteske	48 +			( n n2 -- n n2' ) \ root_state to ASCII num
318222417Sjulian
319241367Sdteske	s" set root=${root_prefix}${root[N]}${root_suffix}"
320262701Sdteske	30 +c!		( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num
321262701Sdteske	evaluate	( n c-addr/u -- n ) \ sets $root to full kernel-path
322262701Sdteske;
323222417Sjulian
324262701Sdteske: cycle_root ( N -- N TRUE )
325262701Sdteske	cycle_menuitem	\ cycle cycle_stateN to next value
326262701Sdteske	activate_root	\ apply current cycle_stateN
327262701Sdteske	menu-redraw	\ redraw menu
328262701Sdteske	TRUE		\ loop menu again
329222417Sjulian;
330242667Sdteske
331243114Sdteske\ 
332243114Sdteske\ Menusets
333243114Sdteske\ 
334243114Sdteske
335242667Sdteske: goto_menu ( N M -- N TRUE )
336242667Sdteske	menu-unset
337242667Sdteske	menuset-loadsetnum ( n m -- n )
338242667Sdteske	menu-redraw
339242667Sdteske	TRUE \ Loop menu again
340242667Sdteske;
341243660Sdteske
342243660Sdteske\ 
343243660Sdteske\ Defaults
344243660Sdteske\ 
345243660Sdteske
346243660Sdteske: set_default_boot_options ( N -- N TRUE )
347243660Sdteske	acpi_enable
348243660Sdteske	safemode_disable
349243660Sdteske	singleuser_disable
350243660Sdteske	verbose_disable
351243660Sdteske	2 goto_menu
352243660Sdteske;
353281843Sdteske
354293802Sallanjude\ 
355293802Sallanjude\ Set boot environment defaults
356293802Sallanjude\ 
357293802Sallanjude
358293802Sallanjude: init_bootenv ( -- )
359293802Sallanjude	s" set menu_caption[1]=${bemenu_current}${vfs.root.mountfrom}" evaluate
360293802Sallanjude	s" set ansi_caption[1]=${beansi_current}${vfs.root.mountfrom}" evaluate
361293802Sallanjude	s" set menu_caption[2]=${bemenu_bootfs}${zfs_be_active}" evaluate
362293802Sallanjude	s" set ansi_caption[2]=${beansi_bootfs}${zfs_be_active}" evaluate
363293802Sallanjude	s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
364293802Sallanjude	s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
365293802Sallanjude;
366293802Sallanjude
367293802Sallanjude\
368293802Sallanjude\ Redraw the entire screen. A long BE name can corrupt the menu
369293802Sallanjude\ 
370293802Sallanjude
371293802Sallanjude: be_draw_screen
372293802Sallanjude	clear		\ Clear the screen (in screen.4th)
373293802Sallanjude	print_version	\ print version string (bottom-right; see version.4th)
374293802Sallanjude	draw-beastie	\ Draw FreeBSD logo at right (in beastie.4th)
375293802Sallanjude	draw-brand	\ Draw brand.4th logo at top (in brand.4th)
376293802Sallanjude	menu-init	\ Initialize menu and draw bounding box (in menu.4th)
377293802Sallanjude;
378293802Sallanjude
379293802Sallanjude\
380293802Sallanjude\ Select a boot environment
381293802Sallanjude\ 
382293802Sallanjude
383293802Sallanjude: set_bootenv ( N -- N TRUE )
384293802Sallanjude	dup s" set vfs.root.mountfrom=${bootenv_root[E]}" 38 +c! evaluate
385293802Sallanjude	s" set currdev=${vfs.root.mountfrom}:" evaluate
386293802Sallanjude	s" unload" evaluate
387293802Sallanjude	free-module-options
388293802Sallanjude	s" /boot/defaults/loader.conf" read-conf
389293802Sallanjude	s" /boot/loader.conf" read-conf
390293802Sallanjude	s" /boot/loader.conf.local" read-conf
391293802Sallanjude	init_bootenv
392293802Sallanjude	be_draw_screen
393293802Sallanjude	menu-redraw
394293802Sallanjude	TRUE
395293802Sallanjude;
396293802Sallanjude
397293802Sallanjude\
398293802Sallanjude\ Switch to the next page of boot environments
399293802Sallanjude\
400293802Sallanjude
401293802Sallanjude: set_be_page ( N -- N TRUE )
402293802Sallanjude	s" zfs_be_currpage" getenv dup -1 = if
403293802Sallanjude		drop s" 1"
404293802Sallanjude	else
405293802Sallanjude		0 s>d 2swap
406293802Sallanjude		>number ( ud caddr/u -- ud' caddr'/u' )	\ convert string to numbers
407293802Sallanjude		2drop					\ drop the string
408293802Sallanjude		1 um/mod ( ud u1 -- u2 u3 ) 		\ convert double ud' to single u3' and remainder u2
409293802Sallanjude		swap drop ( ud2 u3 -- u3 )		\ drop the remainder u2
410293802Sallanjude		1+					\ increment the page number
411293802Sallanjude		s>d <# #s #>				\ convert back to a string
412293802Sallanjude	then
413293802Sallanjude	s" zfs_be_currpage" setenv
414293802Sallanjude	s" reloadbe" evaluate
415293802Sallanjude	3 goto_menu
416293802Sallanjude;
417293802Sallanjude
418281843Sdteskeonly forth definitions
419