Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Synchronize releng/9.2 Forth code with stable/9 via MFS of 2 revisions:

First, MFS of SVN r254109: itself an MFC of 22 revisions:
227727, 233941, 235560, 238431, 241310, 241361, 241363, 241365, 241367,
241523, 242667-242669, 242923, 243114, 243660, 244048, 244089, 244158,
253715, 254105, and 254108.

This includes critical fixes that sadly should have been merged prior.
Namely, SVN r244158 fixes a possible regression.

Second, MFS of SVN r254146: Itself an MFC of r242688.

Approved by:	re (marius)
  • Loading branch information...
commit 93b011e50a30a0e96e28f428803033d70eedbb3e 1 parent 6ede941
devinteske devinteske authored
Showing with 1,821 additions and 439 deletions.
  1. +1 −0  sys/boot/common/Makefile.inc
  2. +3 −4 sys/boot/forth/beastie.4th
  3. +5 −4 sys/boot/forth/beastie.4th.8
  4. +1 −1  sys/boot/forth/brand.4th
  5. +1 −1  sys/boot/forth/brand.4th.8
  6. +28 −14 sys/boot/forth/check-password.4th
  7. +35 −19 sys/boot/forth/check-password.4th.8
  8. +9 −8 sys/boot/forth/color.4th
  9. +12 −13 sys/boot/forth/color.4th.8
  10. +1 −1  sys/boot/forth/delay.4th
  11. +1 −1  sys/boot/forth/delay.4th.8
  12. +16 −0 sys/boot/forth/frames.4th
  13. +13 −0 sys/boot/forth/loader.4th
  14. +1 −1  sys/boot/forth/loader.4th.8
  15. +1 −1  sys/boot/forth/loader.conf
  16. +18 −3 sys/boot/forth/loader.conf.5
  17. +4 −0 sys/boot/forth/loader.rc
  18. +219 −63 sys/boot/forth/menu-commands.4th
  19. +284 −236 sys/boot/forth/menu.4th
  20. +44 −15 sys/boot/forth/menu.4th.8
  21. +86 −40 sys/boot/forth/menu.rc
  22. +610 −0 sys/boot/forth/menusets.4th
  23. +372 −0 sys/boot/forth/menusets.4th.8
  24. +1 −1  sys/boot/forth/shortcuts.4th
  25. +40 −0 sys/boot/forth/support.4th
  26. +1 −1  sys/boot/forth/version.4th
  27. +8 −6 sys/boot/forth/version.4th.8
  28. +1 −1  sys/boot/i386/loader/Makefile
  29. +1 −1  sys/boot/ia64/common/Makefile
  30. +1 −1  sys/boot/pc98/loader/Makefile
  31. +1 −1  sys/boot/powerpc/ofw/Makefile
  32. +1 −1  sys/boot/powerpc/ps3/Makefile
  33. +1 −1  sys/boot/sparc64/loader/Makefile
1  sys/boot/common/Makefile.inc
View
@@ -64,6 +64,7 @@ MAN+= ../forth/delay.4th.8
MAN+= ../forth/loader.conf.5
MAN+= ../forth/loader.4th.8
MAN+= ../forth/menu.4th.8
+MAN+= ../forth/menusets.4th.8
MAN+= ../forth/version.4th.8
.endif
7 sys/boot/forth/beastie.4th
View
@@ -1,6 +1,6 @@
\ Copyright (c) 2003 Scott Long <scottl@freebsd.org>
\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
-\ Copyright (c) 2006-2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2006-2013 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@
marker task-beastie.4th
-include /boot/color.4th
include /boot/delay.4th
variable logoX
@@ -182,8 +181,8 @@ variable logoY
\ beastie Color ``Helper Daemon'' mascot (19 rows x 34 columns)
\ beastiebw B/W ``Helper Daemon'' mascot (19 rows x 34 columns)
\ fbsdbw "FreeBSD" logo in B/W (13 rows x 21 columns)
-\ orb Color ``Orb'' mascot (15 rows x 30 columns)
-\ orbbw B/W ``Orb'' mascot (15 rows x 32 columns) (default)
+\ orb Color ``Orb'' mascot (15 rows x 30 columns) (default)
+\ orbbw B/W ``Orb'' mascot (15 rows x 32 columns)
\
\ NOTE: Setting `loader_logo' to an undefined value (such as "none") will
\ prevent beastie from being drawn.
9 sys/boot/forth/beastie.4th.8
View
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2011 Devin Teske
+.\" Copyright (c) 2011-2012 Devin Teske
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -94,8 +94,9 @@ The
variable can be configured in
.Xr loader.conf 5
to the number of seconds you would like to delay loading the boot menu.
-During the delay the user can press Ctrl-C to fall back to autoboot or ENTER
-to proceed.
+During the delay the user can press Ctrl-C to fall back to
+.Ic autoboot
+or ENTER to proceed.
The default behavior is to not delay.
.El
.Pp
@@ -168,4 +169,4 @@ set of commands was written by
.An Scott Long Aq scottl@FreeBSD.org ,
.An Aleksander Fafula Aq alex@fafula.com
and
-.An Devin Teske Aq devinteske@hotmail.com .
+.An Devin Teske Aq dteske@FreeBSD.org .
2  sys/boot/forth/brand.4th
View
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
2  sys/boot/forth/brand.4th.8
View
@@ -122,4 +122,4 @@ The
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske@hotmail.com .
+.An Devin Teske Aq dteske@FreeBSD.org .
42 sys/boot/forth/check-password.4th
View
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -74,7 +74,7 @@ variable readlen \ input length
again
;
-: read ( -- String prompt )
+: read ( String prompt -- )
0 25 at-xy \ Move the cursor to the bottom-left
dup 1+ read-start ! \ Store X offset after the prompt
@@ -134,23 +134,37 @@ variable readlen \ input length
: check-password ( -- )
- \ Exit if a password was not set
- s" password" getenv dup -1 = if
- drop exit
+ \ Do not allow the user to proceed beyond this point if a boot-lock
+ \ password has been set (preventing even boot from proceeding)
+ s" bootlock_password" getenv dup -1 <> if
+ begin
+ s" Boot Password: " read ( prompt -- )
+ 2dup readval readlen @ compare 0<>
+ while
+ 3000 ms ." loader: incorrect password" 10 emit
+ repeat
+ 2drop ( c-addr/u )
+ else
+ drop ( -1 ) \ getenv cruft
then
- begin \ Loop as long as it takes to get the right password
+ \ Exit if a password was not set
+ s" password" getenv -1 = if exit else drop then
+
+ \ We should prevent the user from visiting the menu or dropping to the
+ \ interactive loader(8) prompt, but still allow the machine to boot...
- s" Password: " \ Output a prompt for a password
- read \ Read the user's input until Enter
+ 0 autoboot
+ \ Only reached if autoboot fails for any reason (including if/when
+ \ the user aborts/escapes the countdown sequence leading to boot).
+
+ s" password" getenv
+ begin
+ s" Password: " read ( prompt -- )
2dup readval readlen @ compare 0= if
2drop exit \ Correct password
then
-
- \ Bad Password
- 3000 ms
- ." loader: incorrect password" 10 emit
-
- again \ Not the right password; repeat
+ 3000 ms ." loader: incorrect password" 10 emit
+ again
;
54 sys/boot/forth/check-password.4th.8
View
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2011 Devin Teske
+.\" Copyright (c) 2011-2012 Devin Teske
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 18, 2011
+.Dd December 10, 2012
.Dt CHECK-PASSWORD.4TH 8
.Os
.Sh NAME
@@ -33,7 +33,8 @@
.Sh DESCRIPTION
The file that goes by the name of
.Nm
-is a set of commands designed to prevent booting without the proper password.
+is a set of commands designed to either prevent booting or prevent modification
+of boot options without an appropriately configured password.
The commands of
.Nm
by themselves are not enough for most uses.
@@ -57,30 +58,36 @@ The commands provided by it are:
.Pp
.Bl -tag -width disable-module_module -compact -offset indent
.It Ic check-password
-Once called, the user cannot continue until the correct password is entered.
-If the user enters the correct password the function returns.
+Dual-purpose function that can either protect the interactive boot menu or
+prevent boot without password (separately).
.Pp
-The password that is required is configured by setting the
-.Ic password
-variable in
-.Xr loader.conf 5 .
+First checks
+.Va bootlock_password
+and if-set, the user cannot continue until the correct password is entered.
.Pp
-Subsequent calls after a successful password
-has been entered will not cause reprompting
-\(em the function will silently return.
+Next checks
+.Va password
+and if-set, tries to
+.Ic autoboot
+and only prompts for password on failure or user-interrupt.
+See
+.Xr loader.conf 5
+for additional information.
.El
.Pp
The environment variables that effect its behavior are:
-.Bl -tag -width bootfile -offset indent
+.Bl -tag -width bootlock_password -offset indent
+.It Va bootlock_password
+Sets the bootlock password (up to 16 characters long) that is required by
+.Ic check-password
+to be entered before the system is allowed to boot.
.It Va password
Sets the password (up to 16 characters long) that is required by
.Ic check-password
-to be entered before the system is allowed to boot. If unset (default) or NULL,
-.Ic check-password
-will silently abort.
+before the user is allowed to visit the boot menu.
.El
.Sh FILES
-.Bl -tag -width /boot/loader.4th -compact
+.Bl -tag -width /boot/check-password.4th -compact
.It Pa /boot/loader
The
.Xr loader 8 .
@@ -101,11 +108,20 @@ check-password
.Ed
.Pp
Set a password in
-.Xr loader.conf 5 :
+.Xr loader.conf 5
+to prevent modification of boot options:
.Pp
.Bd -literal -offset indent -compact
password="abc123"
.Ed
+.Pp
+Set a password in
+.Xr loader.conf 5
+to prevent booting without password:
+.Pp
+.Bd -literal -offset indent -compact
+bootlock_password="boot"
+.Ed
.Sh SEE ALSO
.Xr loader.conf 5 ,
.Xr loader 8 ,
@@ -120,4 +136,4 @@ The
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske@hotmail.com .
+.An Devin Teske Aq dteske@FreeBSD.org .
17 sys/boot/forth/color.4th
View
@@ -1,4 +1,4 @@
-\ Copyright (c) 2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2011-2013 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -26,23 +26,24 @@
marker task-color.4th
-\ This function returns TRUE if the `loader_color' environment variable is set
-\ to YES, yes, or 1. Otherwise, FALSE is returned.
+\ This function returns FALSE if the `loader_color' environment variable is set
+\ to NO, no, or 0. Otherwise, TRUE is returned (unless booting serial).
\
: loader_color? ( -- N )
s" loader_color" getenv dup -1 <> if
- 2dup s" YES" compare-insensitive 0= if
+ 2dup s" NO" compare-insensitive 0= if
2drop
- TRUE exit
+ FALSE exit
then
- 2dup s" 1" compare 0= if
+ 2dup s" 0" compare 0= if
2drop
- TRUE exit
+ FALSE exit
then
drop
then
+ drop
- drop FALSE exit
+ boot_serial? if FALSE else TRUE then
;
25 sys/boot/forth/color.4th.8
View
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2011 Devin Teske
+.\" Copyright (c) 2011-2013 Devin Teske
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 18, 2011
+.Dd August 6, 2013
.Dt COLOR.4TH 8
.Os
.Sh NAME
@@ -50,33 +50,33 @@ through the command:
.Dl include color.4th
.Pp
This line is present in
-.Pa /boot/beastie.4th
+.Pa /boot/loader.4th
file, so it is not needed (and should not be re-issued) in a normal setup.
.Pp
The commands provided by it are:
.Pp
.Bl -tag -width disable-module_module -compact -offset indent
.It Ic loader_color?
-Returns TRUE if the
+Returns FALSE if the
.Ic loader_color
environment variable is set to
-.Dq YES
+.Dq NO
(case-insensitive) or
-.Dq 1 .
-Otherwise returns FALSE.
+.Dq 0 .
+Otherwise returns TRUE
+.Pq unless booting serial .
.El
.Pp
The environment variables that effect its behavior are:
.Bl -tag -width bootfile -offset indent
.It Va loader_color
If set to
-.Dq YES
+.Dq NO
(case-insensitive) or
-.Dq 1 ,
+.Dq 0 ,
causes
.Ic loader_color?
-to return TRUE, indicating to many other modules that color should be used
-whenever/wherever possible.
+to return FALSE, indicating to many modules that color should not be used.
.El
.Sh FILES
.Bl -tag -width /boot/loader.4th -compact
@@ -102,7 +102,6 @@ loader_color="YES"
.Sh SEE ALSO
.Xr loader.conf 5 ,
.Xr loader 8 ,
-.Xr beastie.4th 8 ,
.Xr loader.4th 8
.Sh HISTORY
The
@@ -114,4 +113,4 @@ The
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske@hotmail.com .
+.An Devin Teske Aq dteske@FreeBSD.org .
2  sys/boot/forth/delay.4th
View
@@ -1,4 +1,4 @@
-\ Copyright (c) 2008-2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2008-2011 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
2  sys/boot/forth/delay.4th.8
View
@@ -123,4 +123,4 @@ The
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske@hotmail.com .
+.An Devin Teske Aq dteske@FreeBSD.org .
16 sys/boot/forth/frames.4th
View
@@ -12,6 +12,11 @@ variable rt_el
variable rb_el
variable fill
+\ ASCII frames (used when serial console is detected)
+ 45 constant ascii_dash
+124 constant ascii_pipe
+ 43 constant ascii_plus
+
s" arch-pc98" environment? [if]
\ Single frames
149 constant sh_el
@@ -63,7 +68,17 @@ s" arch-pc98" environment? [if]
loop
;
+: f_ascii ( -- ) ( -- ) \ set frames to ascii
+ ascii_dash h_el !
+ ascii_pipe v_el !
+ ascii_plus lt_el !
+ ascii_plus lb_el !
+ ascii_plus rt_el !
+ ascii_plus rb_el !
+;
+
: f_single ( -- ) \ set frames to single
+ boot_serial? if f_ascii exit then
sh_el h_el !
sv_el v_el !
slt_el lt_el !
@@ -73,6 +88,7 @@ s" arch-pc98" environment? [if]
;
: f_double ( -- ) \ set frames to double
+ boot_serial? if f_ascii exit then
dh_el h_el !
dv_el v_el !
dlt_el lt_el !
13 sys/boot/forth/loader.4th
View
@@ -40,6 +40,7 @@ s" arch-i386" environment? [if] [if]
2048 dictincrease ! \ 2048 additional cells each time
include /boot/support.4th
+include /boot/color.4th
only forth also support-functions also builtins definitions
@@ -59,11 +60,23 @@ only forth also support-functions also builtins definitions
else
drop
then
+ s" menusets-unset"
+ sfind if
+ execute
+ else
+ drop
+ then
;
: boot
0= if ( interpreted ) get_arguments then
+ loader_color? if
+ ." Booting..." cr
+ else
+ ." Booting..." cr
+ then
+
\ Unload only if a path was passed
dup if
>r over r> swap
2  sys/boot/forth/loader.4th.8
View
@@ -99,7 +99,7 @@ This
is the command used in the default
.Pa /boot/loader.rc
file, and it uses the
-.Pa autoboot
+.Ic autoboot
command (see
.Xr loader 8 ) ,
so it can be stopped for further interaction with
2  sys/boot/forth/loader.conf
View
@@ -48,7 +48,7 @@ bitmap_type="splash_image_data" # and place it on the module_path
# escape to the loader prompt, set to
# "NO" to disable autobooting
#beastie_disable="NO" # Turn the beastie boot menu on and off
-#loader_logo="fbsdbw" # Desired logo: fbsdbw, beastiebw, beastie, none
+#loader_logo="orbbw" # Desired logo: orbbw, orb, fbsdbw, beastiebw, beastie, none
#comconsole_speed="9600" # Set the current serial console speed
#console="vidconsole" # A comma separated list of console(s)
#currdev="disk1s1a" # Set the current device
21 sys/boot/forth/loader.conf.5
View
@@ -23,7 +23,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd July 20, 2011
+.Dd August 6, 2013
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -113,8 +113,23 @@ that contains a kernel.
.It Ar kernel_options
Flags to be passed to the kernel.
.It Ar password
+Protect boot menu with a password without interrupting
+.Ic autoboot
+process.
+The password should be in clear text format.
+If a password is set, boot menu will not appear until any key is pressed during
+countdown period specified by
+.Va autoboot_delay
+variable or
+.Ic autoboot
+process fails.
+In both cases user should provide specified password to be able to access boot
+menu.
+.It Ar bootlock_password
Provides a password to be required by check-password before execution is
allowed to continue.
+The password should be in clear text format.
+If a password is set, the user must provide specified password to boot.
.It Ar verbose_loading
If set to
.Dq YES ,
@@ -230,8 +245,8 @@ and
.Dq Li none .
.It Va loader_color
If set to
-.Dq YES ,
-the beastie boot menu will be displayed using ANSI coloring where possible.
+.Dq NO ,
+the beastie boot menu will be displayed without ANSI coloring.
.El
.Sh FILES
.Bl -tag -width /boot/defaults/loader.conf -compact
4 sys/boot/forth/loader.rc
View
@@ -10,5 +10,9 @@ start
\ Tests for password -- executes autoboot first if a password was defined
check-password
+\ Uncomment to enable boot menu
+\ include /boot/beastie.4th
+\ beastie-start
+
\ Unless set otherwise, autoboot is automatic at this point
282 sys/boot/forth/menu-commands.4th
View
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,60 @@
marker task-menu-commands.4th
+include /boot/menusets.4th
+
+variable kernel_state
+variable root_state
+
+\
+\ Boot
+\
+
+: init_boot ( N -- N )
+ dup
+ s" boot_single" getenv -1 <> if
+ drop ( n n c-addr -- n n ) \ unused
+ toggle_menuitem ( n n -- n n )
+ s" set menu_keycode[N]=115" \ base command to execute
+ else
+ s" set menu_keycode[N]=98" \ base command to execute
+ then
+ 17 +c! \ replace 'N' with ASCII numeral
+ evaluate
+;
+
+\
+\ Alternate Boot
+\
+
+: init_altboot ( N -- N )
+ dup
+ s" boot_single" getenv -1 <> if
+ drop ( n c-addr -- n ) \ unused
+ toggle_menuitem ( n -- n )
+ s" set menu_keycode[N]=109" \ base command to execute
+ else
+ s" set menu_keycode[N]=115" \ base command to execute
+ then
+ 17 +c! \ replace 'N' with ASCII numeral
+ evaluate
+;
+
+: altboot ( -- )
+ s" boot_single" 2dup getenv -1 <> if
+ drop ( c-addr/u c-addr -- c-addr/u ) \ unused
+ unsetenv ( c-addr/u -- )
+ else
+ 2drop ( c-addr/u -- ) \ unused
+ s" set boot_single=YES" evaluate
+ then
+ 0 boot ( state -- )
+;
+
+\
+\ ACPI
+\
+
: acpi_enable ( -- )
s" set acpi_load=YES" evaluate \ XXX deprecated but harmless
s" set hint.acpi.0.disabled=0" evaluate
@@ -53,39 +107,51 @@ marker task-menu-commands.4th
TRUE \ loop menu again
;
+\
+\ Safe Mode
+\
+
+: safemode_enabled? ( -- flag )
+ s" kern.smp.disabled" getenv -1 <> dup if
+ swap drop ( c-addr flag -- flag )
+ then
+;
+
+: safemode_enable ( -- )
+ s" set kern.smp.disabled=1" evaluate
+ s" set hw.ata.ata_dma=0" evaluate
+ s" set hw.ata.atapi_dma=0" evaluate
+ s" set hw.ata.wc=0" evaluate
+ s" set hw.eisa_slots=0" evaluate
+ s" set kern.eventtimer.periodic=1" evaluate
+ s" set kern.geom.part.check_integrity=0" evaluate
+;
+
+: safemode_disable ( -- )
+ s" kern.smp.disabled" unsetenv
+ s" hw.ata.ata_dma" unsetenv
+ s" hw.ata.atapi_dma" unsetenv
+ s" hw.ata.wc" unsetenv
+ s" hw.eisa_slots" unsetenv
+ s" kern.eventtimer.periodic" unsetenv
+ s" kern.geom.part.check_integrity" unsetenv
+;
+
+: init_safemode ( N -- N )
+ safemode_enabled? if
+ toggle_menuitem ( n -- n )
+ then
+;
+
: toggle_safemode ( N -- N TRUE )
toggle_menuitem
\ Now we're going to make the change effective
- s" toggle_stateN @" \ base name of toggle state var
- -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral
-
- evaluate 0= if
- s" hint.apic.0.disabled" unsetenv
- s" hw.ata.ata_dma" unsetenv
- s" hw.ata.atapi_dma" unsetenv
- s" hw.ata.wc" unsetenv
- s" hw.eisa_slots" unsetenv
- s" hint.kbdmux.0.disabled" unsetenv
+ dup toggle_stateN @ 0= if
+ safemode_disable
else
- \
- \ Toggle ACPI elements if necessary
- \
- acpipresent? if acpienabled? if
- menuacpi @ dup 0<> if
- toggle_menuitem ( N -- N )
- then
- drop
- acpi_disable
- then then
-
- s" set hint.apic.0.disabled=1" evaluate
- s" set hw.ata.ata_dma=0" evaluate
- s" set hw.ata.atapi_dma=0" evaluate
- s" set hw.ata.wc=0" evaluate
- s" set hw.eisa_slots=0" evaluate
- s" set hint.kbdmux.0.disabled=1" evaluate
+ safemode_enable
then
menu-redraw
@@ -93,42 +159,88 @@ marker task-menu-commands.4th
TRUE \ loop menu again
;
+\
+\ Single User Mode
+\
+
+: singleuser_enabled? ( -- flag )
+ s" boot_single" getenv -1 <> dup if
+ swap drop ( c-addr flag -- flag )
+ then
+;
+
+: singleuser_enable ( -- )
+ s" set boot_single=YES" evaluate
+;
+
+: singleuser_disable ( -- )
+ s" boot_single" unsetenv
+;
+
+: init_singleuser ( N -- N )
+ singleuser_enabled? if
+ toggle_menuitem ( n -- n )
+ then
+;
+
: toggle_singleuser ( N -- N TRUE )
toggle_menuitem
menu-redraw
\ Now we're going to make the change effective
- s" toggle_stateN @" \ base name of toggle state var
- -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral
-
- evaluate 0= if
- s" boot_single" unsetenv
+ dup toggle_stateN @ 0= if
+ singleuser_disable
else
- s" set boot_single=YES" evaluate
+ singleuser_enable
then
TRUE \ loop menu again
;
+\
+\ Verbose Boot
+\
+
+: verbose_enabled? ( -- flag )
+ s" boot_verbose" getenv -1 <> dup if
+ swap drop ( c-addr flag -- flag )
+ then
+;
+
+: verbose_enable ( -- )
+ s" set boot_verbose=YES" evaluate
+;
+
+: verbose_disable ( -- )
+ s" boot_verbose" unsetenv
+;
+
+: init_verbose ( N -- N )
+ verbose_enabled? if
+ toggle_menuitem ( n -- n )
+ then
+;
+
: toggle_verbose ( N -- N TRUE )
toggle_menuitem
menu-redraw
\ Now we're going to make the change effective
- s" toggle_stateN @" \ base name of toggle state var
- -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral
-
- evaluate 0= if
- s" boot_verbose" unsetenv
+ dup toggle_stateN @ 0= if
+ verbose_disable
else
- s" set boot_verbose=YES" evaluate
+ verbose_enable
then
TRUE \ loop menu again
;
+\
+\ Escape to Prompt
+\
+
: goto_prompt ( N -- N FALSE )
s" set autoboot_delay=NO" evaluate
@@ -141,50 +253,94 @@ marker task-menu-commands.4th
FALSE \ exit the menu
;
+\
+\ Cyclestate (used by kernel/root below)
+\
+
+: init_cyclestate ( N K -- N )
+ over cycle_stateN ( n k -- n k addr )
+ begin
+ tuck @ ( n k addr -- n addr k c )
+ over <> ( n addr k c -- n addr k 0|-1 )
+ while
+ rot ( n addr k -- addr k n )
+ cycle_menuitem
+ swap rot ( addr k n -- n k addr )
+ repeat
+ 2drop ( n k addr -- n )
+;
+
+\
+\ Kernel
+\
+
+: init_kernel ( N -- N )
+ kernel_state @ ( n -- n k )
+ init_cyclestate ( n k -- n )
+;
+
: cycle_kernel ( N -- N TRUE )
cycle_menuitem
menu-redraw
\ Now we're going to make the change effective
- s" cycle_stateN" \ base name of array state var
- -rot 2dup 11 + c! rot \ replace 'N' with ASCII numeral
- evaluate \ translate name into address
- @ \ dereference address into value
+ dup cycle_stateN @
+ dup kernel_state ! \ save a copy for re-initialization
48 + \ convert to ASCII numeral
- \ Since we are [in this file] going to override the standard `boot'
- \ routine with a custom one, you should know that we use $kernel
- \ when referencing the desired kernel. Set $kernel below.
-
s" set kernel=${kernel_prefix}${kernel[N]}${kernel_suffix}"
- \ command to assemble full kernel-path
- -rot tuck 36 + c! swap \ replace 'N' with array index value
- evaluate \ sets $kernel to full kernel-path
+ 36 +c! \ replace 'N' with ASCII numeral
+ evaluate \ sets $kernel to full kernel-path
TRUE \ loop menu again
;
+\
+\ Root
+\
+
+: init_root ( N -- N )
+ root_state @ ( n -- n k )
+ init_cyclestate ( n k -- n )
+;
+
: cycle_root ( N -- N TRUE )
cycle_menuitem
menu-redraw
\ Now we're going to make the change effective
- s" cycle_stateN" \ base name of array state var
- -rot 2dup 11 + c! rot \ replace 'N' with ASCII numeral
- evaluate \ translate name into address
- @ \ dereference address into value
+ dup cycle_stateN @
+ dup root_state ! \ save a copy for re-initialization
48 + \ convert to ASCII numeral
- \ Since we are [in this file] going to override the standard `boot'
- \ routine with a custom one, you should know that we use $root when
- \ booting. Set $root below.
-
- s" set root=${root_prefix}${root[N]}${root_prefix}"
- \ command to assemble full kernel-path
- -rot tuck 30 + c! swap \ replace 'N' with array index value
- evaluate \ sets $kernel to full kernel-path
+ s" set root=${root_prefix}${root[N]}${root_suffix}"
+ 30 +c! \ replace 'N' with ASCII numeral
+ evaluate \ sets $root to full root-path
TRUE \ loop menu again
;
+
+\
+\ Menusets
+\
+
+: goto_menu ( N M -- N TRUE )
+ menu-unset
+ menuset-loadsetnum ( n m -- n )
+ menu-redraw
+ TRUE \ Loop menu again
+;
+
+\
+\ Defaults
+\
+
+: set_default_boot_options ( N -- N TRUE )
+ acpi_enable
+ safemode_disable
+ singleuser_disable
+ verbose_disable
+ 2 goto_menu
+;
520 sys/boot/forth/menu.4th
View
@@ -1,6 +1,6 @@
\ Copyright (c) 2003 Scott Long <scottl@freebsd.org>
\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
-\ Copyright (c) 2006-2011 Devin Teske <devinteske@hotmail.com>
+\ Copyright (c) 2006-2013 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,8 @@ f_double \ Set frames to double (see frames.4th). Replace with
\ f_single if you want single frames.
46 constant dot \ ASCII definition of a period (in decimal)
+ 5 constant menu_default_x \ default column position of timeout
+10 constant menu_default_y \ default row position of timeout msg
4 constant menu_timeout_default_x \ default column position of timeout
23 constant menu_timeout_default_y \ default row position of timeout msg
10 constant menu_timeout_default \ default timeout (in seconds)
@@ -76,6 +78,16 @@ variable menu_timeout \ determined configurable delay duration
variable menu_timeout_x \ column position of timeout message
variable menu_timeout_y \ row position of timeout message
+\ Menu initialization status variables
+variable init_state1
+variable init_state2
+variable init_state3
+variable init_state4
+variable init_state5
+variable init_state6
+variable init_state7
+variable init_state8
+
\ Boolean option status variables
variable toggle_state1
variable toggle_state2
@@ -106,6 +118,52 @@ create init_text6 255 allot
create init_text7 255 allot
create init_text8 255 allot
+: +c! ( N C-ADDR/U K -- C-ADDR/U )
+ 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr )
+ rot + c! ( n c-addr/u k n c-addr -- n c-addr/u )
+ rot drop ( n c-addr/u -- c-addr/u )
+;
+
+: menukeyN ( N -- ADDR ) s" menukeyN" 7 +c! evaluate ;
+: init_stateN ( N -- ADDR ) s" init_stateN" 10 +c! evaluate ;
+: toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 +c! evaluate ;
+: cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 +c! evaluate ;
+: init_textN ( N -- C-ADDR ) s" init_textN" 9 +c! evaluate ;
+
+: str_loader_menu_frame ( -- C-ADDR/U ) s" loader_menu_frame" ;
+: str_loader_menu_title ( -- C-ADDR/U ) s" loader_menu_title" ;
+: str_loader_menu_title_align ( -- C-ADDR/U ) s" loader_menu_title_align" ;
+: str_loader_menu_x ( -- C-ADDR/U ) s" loader_menu_x" ;
+: str_loader_menu_y ( -- C-ADDR/U ) s" loader_menu_y" ;
+: str_loader_menu_timeout_x ( -- C-ADDR/U ) s" loader_menu_timeout_x" ;
+: str_loader_menu_timeout_y ( -- C-ADDR/U ) s" loader_menu_timeout_y" ;
+: str_menu_init ( -- C-ADDR/U ) s" menu_init" ;
+: str_menu_timeout_command ( -- C-ADDR/U ) s" menu_timeout_command" ;
+: str_menu_reboot ( -- C-ADDR/U ) s" menu_reboot" ;
+: str_menu_acpi ( -- C-ADDR/U ) s" menu_acpi" ;
+: str_menu_options ( -- C-ADDR/U ) s" menu_options" ;
+: str_menu_optionstext ( -- C-ADDR/U ) s" menu_optionstext" ;
+
+: str_menu_init[x] ( -- C-ADDR/U ) s" menu_init[x]" ;
+: str_menu_command[x] ( -- C-ADDR/U ) s" menu_command[x]" ;
+: str_menu_caption[x] ( -- C-ADDR/U ) s" menu_caption[x]" ;
+: str_ansi_caption[x] ( -- C-ADDR/U ) s" ansi_caption[x]" ;
+: str_menu_keycode[x] ( -- C-ADDR/U ) s" menu_keycode[x]" ;
+: str_toggled_text[x] ( -- C-ADDR/U ) s" toggled_text[x]" ;
+: str_toggled_ansi[x] ( -- C-ADDR/U ) s" toggled_ansi[x]" ;
+: str_menu_caption[x][y] ( -- C-ADDR/U ) s" menu_caption[x][y]" ;
+: str_ansi_caption[x][y] ( -- C-ADDR/U ) s" ansi_caption[x][y]" ;
+
+: menu_init[x] ( N -- C-ADDR/U ) str_menu_init[x] 10 +c! ;
+: menu_command[x] ( N -- C-ADDR/U ) str_menu_command[x] 13 +c! ;
+: menu_caption[x] ( N -- C-ADDR/U ) str_menu_caption[x] 13 +c! ;
+: ansi_caption[x] ( N -- C-ADDR/U ) str_ansi_caption[x] 13 +c! ;
+: menu_keycode[x] ( N -- C-ADDR/U ) str_menu_keycode[x] 13 +c! ;
+: toggled_text[x] ( N -- C-ADDR/U ) str_toggled_text[x] 13 +c! ;
+: toggled_ansi[x] ( N -- C-ADDR/U ) str_toggled_ansi[x] 13 +c! ;
+: menu_caption[x][y] ( N M -- C-ADDR/U ) str_menu_caption[x][y] 16 +c! 13 +c! ;
+: ansi_caption[x][y] ( N M -- C-ADDR/U ) str_ansi_caption[x][y] 16 +c! 13 +c! ;
+
: arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise.
s" arch-i386" environment? dup if
drop
@@ -162,30 +220,24 @@ create init_text8 255 allot
\ ASCII numeral equal to user-selected menu item must be on the stack.
\ We do not modify the stack, so the ASCII numeral is left on top.
- s" init_textN" \ base name of buffer
- -rot 2dup 9 + c! rot \ replace 'N' with ASCII num
-
- evaluate c@ 0= if
+ dup init_textN c@ 0= if
\ NOTE: no need to check toggle_stateN since the first time we
\ are called, we will populate init_textN. Further, we don't
\ need to test whether menu_caption[x] (ansi_caption[x] when
- \ loader_color=1) is available since we would not have been
+ \ loader_color?=1) is available since we would not have been
\ called if the caption was NULL.
\ base name of environment variable
+ dup ( n -- n n ) \ key pressed
loader_color? if
- s" ansi_caption[x]"
+ ansi_caption[x]
else
- s" menu_caption[x]"
+ menu_caption[x]
then
- -rot 2dup 13 + c! rot \ replace 'x' with ASCII numeral
-
getenv dup -1 <> if
- s" init_textN" \ base name of buffer
- 4 pick \ copy ASCII num to top
- rot tuck 9 + c! swap \ replace 'N' with ASCII num
- evaluate
+ 2 pick ( n c-addr/u -- n c-addr/u n )
+ init_textN ( n c-addr/u n -- n c-addr/u c-addr )
\ now we have the buffer c-addr on top
\ ( followed by c-addr/u of current caption )
@@ -217,67 +269,49 @@ create init_text8 255 allot
\ negate the toggled state so that we reverse the flow on subsequent
\ calls.
- s" toggle_stateN @" \ base name of toggle state var
- -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral
-
- evaluate 0= if
+ dup toggle_stateN @ 0= if
\ state is OFF, toggle to ON
- \ base name of toggled text var
+ dup ( n -- n n ) \ key pressed
loader_color? if
- s" toggled_ansi[x]"
+ toggled_ansi[x]
else
- s" toggled_text[x]"
+ toggled_text[x]
then
- -rot 2dup 13 + c! rot \ replace 'x' with ASCII num
-
getenv dup -1 <> if
\ Assign toggled text to menu caption
-
- \ base name of caption var
+ 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
loader_color? if
- s" ansi_caption[x]"
+ ansi_caption[x]
else
- s" menu_caption[x]"
+ menu_caption[x]
then
- 4 pick \ copy ASCII num to top
- rot tuck 13 + c! swap \ replace 'x' with ASCII num
-
- setenv \ set new caption
+ setenv
else
\ No toggled text, keep the same caption
-
- drop
+ drop ( n -1 -- n ) \ getenv cruft
then
true \ new value of toggle state var (to be stored later)
else
\ state is ON, toggle to OFF
- s" init_textN" \ base name of initial text buffer
- -rot 2dup 9 + c! rot \ replace 'N' with ASCII numeral
- evaluate \ convert string to c-addr
- count \ convert c-addr to c-addr/u
+ dup init_textN count ( n -- n c-addr/u )
- \ base name of caption var
+ \ Assign init_textN text to menu caption
+ 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
loader_color? if
- s" ansi_caption[x]"
+ ansi_caption[x]
else
- s" menu_caption[x]"
+ menu_caption[x]
then
- 4 pick \ copy ASCII num to top
- rot tuck 13 + c! swap \ replace 'x' with ASCII numeral
+ setenv
- setenv \ set new caption
- false \ new value of toggle state var (to be stored below)
+ false \ new value of toggle state var (to be stored below)
then
\ now we'll store the new toggle state (on top of stack)
- s" toggle_stateN" \ base name of toggle state var
- 3 pick \ copy ASCII numeral to top
- rot tuck 12 + c! swap \ replace 'N' with ASCII numeral
- evaluate \ convert string to addr
- ! \ store new value
+ over toggle_stateN !
;
: cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem
@@ -285,28 +319,23 @@ create init_text8 255 allot
\ ASCII numeral equal to user-selected menu item must be on the stack.
\ We do not modify the stack, so the ASCII numeral is left on top.
- s" cycle_stateN" \ base name of array state var
- -rot 2dup 11 + c! rot \ replace 'N' with ASCII numeral
-
- evaluate \ we now have a pointer to the proper variable
- dup @ \ resolve the pointer (but leave it on the stack)
- 1+ \ increment the value
+ dup cycle_stateN dup @ 1+ \ get value and increment
\ Before assigning the (incremented) value back to the pointer,
\ let's test for the existence of this particular array element.
\ If the element exists, we'll store index value and move on.
\ Otherwise, we'll loop around to zero and store that.
- dup 48 + \ duplicate Array index and convert to ASCII numeral
+ dup 48 + ( n addr k -- n addr k k' )
+ \ duplicate array index and convert to ASCII numeral
- \ base name of array caption text
+ 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y)
loader_color? if
- s" ansi_caption[x][y]"
+ ansi_caption[x][y]
else
- s" menu_caption[x][y]"
+ menu_caption[x][y]
then
- -rot tuck 16 + c! swap \ replace 'y' with Array index
- 4 pick rot tuck 13 + c! swap \ replace 'x' with menu choice
+ ( n addr k n k' -- n addr k c-addr/u )
\ Now test for the existence of our incremented array index in the
\ form of $menu_caption[x][y] ($ansi_caption[x][y] with loader_color
@@ -315,48 +344,47 @@ create init_text8 255 allot
getenv dup -1 = if
\ No caption set for this array index. Loop back to zero.
- drop ( getenv cruft )
- drop ( incremented array index )
- 0 ( new array index that will be stored later )
+ drop ( n addr k -1 -- n addr k ) \ getenv cruft
+ drop 0 ( n addr k -- n addr 0 ) \ new value to store later
- \ base name of caption var
+ 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y)
loader_color? if
- s" ansi_caption[x][0]"
+ ansi_caption[x][y]
else
- s" menu_caption[x][0]"
+ menu_caption[x][y]
then
- 4 pick rot tuck 13 + c! swap \ replace 'x' with menu choice
-
+ ( n addr 0 n 48 -- n addr 0 c-addr/u )
getenv dup -1 = if
\ This is highly unlikely to occur, but to make
\ sure that things move along smoothly, allocate
\ a temporary NULL string
- s" "
+ drop ( n addr 0 -1 -- n addr 0 ) \ getenv cruft
+ s" " ( n addr 0 -- n addr 0 c-addr/u )
then
then
\ At this point, we should have the following on the stack (in order,
\ from bottom to top):
\
- \ N - Ascii numeral representing the menu choice (inherited)
- \ Addr - address of our internal cycle_stateN variable
- \ N - zero-based number we intend to store to the above
- \ C-Addr - string value we intend to store to menu_caption[x]
- \ (or ansi_caption[x] with loader_color enabled)
+ \ n - Ascii numeral representing the menu choice (inherited)
+ \ addr - address of our internal cycle_stateN variable
+ \ k - zero-based number we intend to store to the above
+ \ c-addr/u - string value we intend to store to menu_caption[x]
+ \ (or ansi_caption[x] with loader_color enabled)
\
\ Let's perform what we need to with the above.
- \ base name of menuitem caption var
+ \ Assign array value text to menu caption
+ 4 pick ( n addr k c-addr/u -- n addr k c-addr/u n )
loader_color? if
- s" ansi_caption[x]"
+ ansi_caption[x]
else
- s" menu_caption[x]"
+ menu_caption[x]
then
- 6 pick rot tuck 13 + c! swap \ replace 'x' with menu choice
- setenv \ set the new caption
+ setenv
- swap ! \ update array state variable
+ swap ! ( n addr k -- n ) \ update array state variable
;
: acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise
@@ -384,21 +412,21 @@ create init_text8 255 allot
\ ACPI option is to be presented to the user, otherwise returns -1. Used
\ internally by menu-create, you need not (nor should you) call this directly.
\
-: acpimenuitem ( -- C-Addr | -1 )
+: acpimenuitem ( -- C-Addr/U | -1 )
arch-i386? if
acpipresent? if
acpienabled? if
loader_color? if
- s" toggled_ansi[x]"
+ str_toggled_ansi[x]
else
- s" toggled_text[x]"
+ str_toggled_text[x]
then
else
loader_color? if
- s" ansi_caption[x]"
+ str_ansi_caption[x]
else
- s" menu_caption[x]"
+ str_menu_caption[x]
then
then
else
@@ -416,10 +444,37 @@ create init_text8 255 allot
: menu-create ( -- )
\ Print the frame caption at (x,y)
- s" loader_menu_title" getenv dup -1 = if
+ str_loader_menu_title getenv dup -1 = if
drop s" Welcome to FreeBSD"
then
- 24 over 2 / - 9 at-xy type
+ TRUE ( use default alignment )
+ str_loader_menu_title_align getenv dup -1 <> if
+ 2dup s" left" compare-insensitive 0= if ( 1 )
+ 2drop ( c-addr/u ) drop ( bool )
+ menuX @ menuY @ 1-
+ FALSE ( don't use default alignment )
+ else ( 1 ) 2dup s" right" compare-insensitive 0= if ( 2 )
+ 2drop ( c-addr/u ) drop ( bool )
+ menuX @ 42 + 4 - over - menuY @ 1-
+ FALSE ( don't use default alignment )
+ else ( 2 ) 2drop ( c-addr/u ) then ( 1 ) then
+ else
+ drop ( getenv cruft )
+ then
+ if ( use default center alignement? )
+ menuX @ 19 + over 2 / - menuY @ 1-
+ then
+ at-xy type
+
+ \ If $menu_init is set, evaluate it (allowing for whole menus to be
+ \ constructed dynamically -- as this function could conceivably set
+ \ the remaining environment variables to construct the menu entirely).
+ \
+ str_menu_init getenv dup -1 <> if
+ evaluate
+ else
+ drop
+ then
\ Print our menu options with respective key/variable associations.
\ `printmenuitem' ends by adding the decimal ASCII value for the
@@ -440,7 +495,7 @@ create init_text8 255 allot
\ Initialize the ACPI option status.
\
0 menuacpi !
- s" menu_acpi" getenv -1 <> if
+ str_menu_acpi getenv -1 <> if
c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
menuacpi !
arch-i386? if acpipresent? if
@@ -448,10 +503,7 @@ create init_text8 255 allot
\ Set menu toggle state to active state
\ (required by generic toggle_menuitem)
\
- menuacpi @
- s" acpienabled? toggle_stateN !"
- -rot tuck 25 + c! swap
- evaluate
+ acpienabled? menuacpi @ toggle_stateN !
then then
else
drop
@@ -462,7 +514,7 @@ create init_text8 255 allot
\ Initialize the menu_options visual separator.
\
0 menuoptions !
- s" menu_options" getenv -1 <> if
+ str_menu_options getenv -1 <> if
c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
menuoptions !
else
@@ -473,12 +525,16 @@ create init_text8 255 allot
\ Initialize "Reboot" menu state variable (prevents double-entry)
false menurebootadded !
+ menu_start
+ 1- menuidx ! \ Initialize the starting index for the menu
+ 0 menurow ! \ Initialize the starting position for the menu
+
49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
begin
\ If the "Options:" separator, print it.
dup menuoptions @ = if
\ Optionally add a reboot option to the menu
- s" menu_reboot" getenv -1 <> if
+ str_menu_reboot getenv -1 <> if
drop
s" Reboot" printmenuitem menureboot !
true menurebootadded !
@@ -488,42 +544,57 @@ create init_text8 255 allot
menurow @ 2 + menurow !
menurow @ menuY @ +
at-xy
- ." Options:"
+ str_menu_optionstext getenv dup -1 <> if
+ type
+ else
+ drop ." Options:"
+ then
then
\ If this is the ACPI menu option, act accordingly.
dup menuacpi @ = if
- acpimenuitem ( -- C-Addr | -1 )
+ dup acpimenuitem ( n -- n n c-addr/u | n n -1 )
+ dup -1 <> if
+ 13 +c! ( n n c-addr/u -- n c-addr/u )
+ \ replace 'x' with n
+ else
+ swap drop ( n n -1 -- n -1 )
+ over menu_command[x] unsetenv
+ then
else
+ \ make sure we have not already initialized this item
+ dup init_stateN dup @ 0= if
+ 1 swap !
+
+ \ If this menuitem has an initializer, run it
+ dup menu_init[x]
+ getenv dup -1 <> if
+ evaluate
+ else
+ drop
+ then
+ else
+ drop
+ then
+
+ dup
loader_color? if
- s" ansi_caption[x]"
+ ansi_caption[x]
else
- s" menu_caption[x]"
+ menu_caption[x]
then
then
- ( C-Addr | -1 )
dup -1 <> if
- \ replace 'x' with current iteration
- -rot 2dup 13 + c! rot
-
\ test for environment variable
getenv dup -1 <> if
- printmenuitem ( C-Addr -- N )
-
- s" menukeyN !" \ generate cmd to store result
- -rot 2dup 7 + c! rot
-
- evaluate
+ printmenuitem ( c-addr/u -- n )
+ dup menukeyN !
else
drop
then
else
drop
-
- s" menu_command[x]"
- -rot 2dup 13 + c! rot ( replace 'x' )
- unsetenv
then
1+ dup 56 > \ add 1 to iterator, continue if less than 57
@@ -532,7 +603,7 @@ create init_text8 255 allot
\ Optionally add a reboot option to the menu
menurebootadded @ true <> if
- s" menu_reboot" getenv -1 <> if
+ str_menu_reboot getenv -1 <> if
drop \ no need for the value
s" Reboot" \ menu caption (required by printmenuitem)
@@ -550,45 +621,22 @@ create init_text8 255 allot
\
: menu-timeout-update ( N -- )
- dup 9 > if ( N N 9 -- N )
- drop ( N -- )
- 9 ( maximum: -- N )
- then
-
- dup 0 < if ( N N 0 -- N )
- drop ( N -- )
- 0 ( minimum: -- N )
- then
-
- 48 + ( convert single-digit numeral to ASCII: N 48 -- N )
-
- s" Autoboot in N seconds. [Space] to pause" ( N -- N Addr C )
-
- 2 pick 48 - 0> if ( N Addr C N 48 -- N Addr C )
-
- \ Modify 'N' (Addr+12) above to reflect time-left
-
- -rot ( N Addr C -- C N Addr )
- tuck ( C N Addr -- C Addr N Addr )
- 12 + ( C Addr N Addr -- C Addr N Addr2 )
- c! ( C Addr N Addr2 -- C Addr )
- swap ( C Addr -- Addr C )
-
- menu_timeout_x @
- menu_timeout_y @
- at-xy ( position cursor: Addr C N N -- Addr C )
-
- type ( print message: Addr C -- )
-
- else ( N Addr C N -- N Addr C )
+ \ Enforce minimum/maximum
+ dup 9 > if drop 9 then
+ dup 0 < if drop 0 then
- menu_timeout_x @
- menu_timeout_y @
- at-xy ( position cursor: N Addr C N N -- N Addr C )
+ s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u )
- spaces ( erase message: N Addr C -- N Addr )
- 2drop ( N Addr -- )
+ 2 pick 0> if
+ rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to ASCII
+ 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace 'N' above
+ menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
+ type ( c-addr/u -- ) \ print message
+ else
+ menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
+ spaces ( n c-addr/u -- n c-addr ) \ erase message
+ 2drop ( n c-addr -- )
then
0 25 at-xy ( position cursor back at bottom-left )
@@ -636,7 +684,7 @@ create init_text8 255 allot
\ (user did not cancel by pressing ANY
\ key)
- s" menu_timeout_command" getenv dup
+ str_menu_timeout_command getenv dup
-1 = if
drop \ clean-up
else
@@ -708,8 +756,45 @@ create init_text8 255 allot
menu_start
1- menuidx ! \ Initialize the starting index for the menu
0 menurow ! \ Initialize the starting position for the menu
- 42 13 2 9 box \ Draw frame (w,h,x,y)
- 0 25 at-xy \ Move cursor to the bottom for output
+
+ \ Assign configuration values
+ str_loader_menu_y getenv dup -1 = if
+ drop \ no custom row position
+ menu_default_y
+ else
+ \ make sure custom position is a number
+ ?number 0= if
+ menu_default_y \ or use default
+ then
+ then
+ menuY !
+ str_loader_menu_x getenv dup -1 = if
+ drop \ no custom column position
+ menu_default_x
+ else
+ \ make sure custom position is a number
+ ?number 0= if
+ menu_default_x \ or use default
+ then
+ then
+ menuX !
+
+ \ Interpret a custom frame type for the menu
+ TRUE ( draw a box? default yes, but might be altered below )
+ str_loader_menu_frame getenv dup -1 = if ( 1 )
+ drop \ no custom frame type
+ else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 )
+ f_single ( see frames.4th )
+ else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 )
+ f_double ( see frames.4th )
+ else ( 3 ) s" none" compare-insensitive 0= if ( 4 )
+ drop FALSE \ don't draw a box
+ ( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then
+ if
+ 42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y)
+ then
+
+ 0 25 at-xy \ Move cursor to the bottom for output
;
\ Main function. Call this from your `loader.rc' file.
@@ -719,7 +804,7 @@ create init_text8 255 allot
0 menu_timeout_enabled ! \ start with automatic timeout disabled
\ check indication that automatic execution after delay is requested
- s" menu_timeout_command" getenv -1 <> if ( Addr C -1 -- | Addr )
+ str_menu_timeout_command getenv -1 <> if ( Addr C -1 -- | Addr )
drop ( just testing existence right now: Addr -- )
\ initialize state variables
@@ -755,7 +840,7 @@ create init_text8 255 allot
menu_timeout_enabled @ 1 = if
\ read custom column position (if set)
- s" loader_menu_timeout_x" getenv dup -1 = if
+ str_loader_menu_timeout_x getenv dup -1 = if
drop \ no custom column position
menu_timeout_default_x \ use default setting
else
@@ -767,7 +852,7 @@ create init_text8 255 allot
menu_timeout_x ! ( store value on stack from above )
\ read custom row position (if set)
- s" loader_menu_timeout_y" getenv dup -1 = if
+ str_loader_menu_timeout_y getenv dup -1 = if
drop \ no custom row position
menu_timeout_default_y \ use default setting
else
@@ -799,17 +884,15 @@ create init_text8 255 allot
exit ( pedantic; never reached )
then
+ dup menureboot @ = if 0 reboot then
+
\ Evaluate the decimal ASCII value against known menu item
\ key associations and act accordingly
49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
begin
- s" menukeyN @"
-
- \ replace 'N' with current iteration
- -rot 2dup 7 + c! rot
-
- evaluate rot tuck = if
+ dup menukeyN @
+ rot tuck = if
\ Adjust for missing ACPI menuitem on non-i386
arch-i386? true <> menuacpi @ 0<> and if
@@ -820,13 +903,8 @@ create init_text8 255 allot
then
then
- \ base env name for the value (x is a number)
- s" menu_command[x]"
-
- \ Copy ASCII number to string at offset 13
- -rot 2dup 13 + c! rot
-
\ Test for the environment variable
+ dup menu_command[x]
getenv dup -1 <> if
\ Execute the stored procedure
evaluate
@@ -861,16 +939,14 @@ create init_text8 255 allot
\
\ Check for menu keycode shortcut(s)
\
- s" menu_keycode[x]"
- -rot 2dup 13 + c! rot
+ dup menu_keycode[x]
getenv dup -1 = if
drop
else
?number 0<> if
rot tuck = if
swap
- s" menu_command[x]"
- -rot 2dup 13 + c! rot
+ dup menu_command[x]
getenv dup -1 <> if
evaluate
0= if
@@ -890,8 +966,7 @@ create init_text8 255 allot
\ continue if less than 57
until
drop \ loop iterator
-
- menureboot @ = if 0 reboot then
+ drop \ key pressed
again \ Non-operational key was pressed; repeat
;
@@ -903,77 +978,43 @@ create init_text8 255 allot
49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
begin
- \ Unset variables in-order of appearance in menu.4th(8)
-
- s" menu_caption[x]" \ basename for caption variable
- -rot 2dup 13 + c! rot \ replace 'x' with current iteration
- unsetenv \ not erroneous to unset unknown var
-
- s" menu_command[x]" \ command basename
- -rot 2dup 13 + c! rot \ replace 'x'
- unsetenv
-
- s" menu_keycode[x]" \ keycode basename
- -rot 2dup 13 + c! rot \ replace 'x'
- unsetenv
-
- s" ansi_caption[x]" \ ANSI caption basename
- -rot 2dup 13 + c! rot \ replace 'x'
- unsetenv
-
- s" toggled_text[x]" \ toggle_menuitem caption basename
- -rot 2dup 13 + c! rot \ replace 'x'
- unsetenv
-
- s" toggled_ansi[x]" \ toggle_menuitem ANSI caption basename
- -rot 2dup 13 + c! rot \ replace 'x'
- unsetenv
-
- s" menu_caption[x][y]" \ cycle_menuitem caption
- -rot 2dup 13 + c! rot \ replace 'x'
- 49 -rot
- begin
- 16 2over rot + c! \ replace 'y'
- 2dup unsetenv
-
- rot 1+ dup 56 > 2swap rot
- until
- 2drop drop
-
- s" ansi_caption[x][y]" \ cycle_menuitem ANSI caption
- -rot 2dup 13 + c! rot \ replace 'x'
- 49 -rot
+ dup menu_init[x] unsetenv \ menu initializer
+ dup menu_command[x] unsetenv \ menu command
+ dup menu_caption[x] unsetenv \ menu caption
+ dup ansi_caption[x] unsetenv \ ANSI caption
+ dup menu_keycode[x] unsetenv \ menu keycode
+ dup toggled_text[x] unsetenv \ toggle_menuitem caption
+ dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI caption
+
+ 48 \ Iterator start (inner range 48 to 57; ASCII '0' to '9')
begin
- 16 2over rot + c! \ replace 'y'
- 2dup unsetenv
-
- rot 1+ dup 56 > 2swap rot
+ \ cycle_menuitem caption and ANSI caption
+ 2dup menu_caption[x][y] unsetenv
+ 2dup ansi_caption[x][y] unsetenv
+ 1+ dup 57 >
until
- 2drop drop
+ drop \ inner iterator
- s" 0 menukeyN !" \ basename for key association var
- -rot 2dup 9 + c! rot \ replace 'N' with current iteration
- evaluate \ assign zero (0) to key assoc. var
+ 0 over menukeyN ! \ used by menu-create, menu-display
+ 0 over init_stateN ! \ used by menu-create
+ 0 over toggle_stateN ! \ used by toggle_menuitem
+ 0 over init_textN c! \ used by toggle_menuitem
+ 0 over cycle_stateN ! \ used by cycle_menuitem
1+ dup 56 > \ increment, continue if less than 57
until
drop \ iterator
- \ unset the timeout command
- s" menu_timeout_command" unsetenv
+ str_menu_timeout_command unsetenv \ menu timeout command
+ str_menu_reboot unsetenv \ Reboot menu option flag
+ str_menu_acpi unsetenv \ ACPI menu option flag
+ str_menu_options unsetenv \ Options separator flag
+ str_menu_optionstext unsetenv \ separator display text
+ str_menu_init unsetenv \ menu initializer
- \ clear the "Reboot" menu option flag
- s" menu_reboot" unsetenv
0 menureboot !
-
- \ clear the ACPI menu option flag
- s" menu_acpi" unsetenv
0 menuacpi !
-
- \ clear the "Options" menu separator flag
- s" menu_options" unsetenv
0 menuoptions !
-
;
\ This function both unsets menu variables and visually erases the menu area
@@ -984,10 +1025,17 @@ create init_text8 255 allot
menu-erase
;
-\ Assign configuration values
bullet menubllt !
-10 menuY !
-5 menuX !
+
+\ Initialize our menu initialization state variables
+0 init_state1 !
+0 init_state2 !
+0 init_state3 !
+0 init_state4 !
+0 init_state5 !
+0 init_state6 !
+0 init_state7 !
+0 init_state8 !
\ Initialize our boolean state variables
0 toggle_state1 !
59 sys/boot/forth/menu.4th.8
View
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2011 Devin Teske
+.\" Copyright (c) 2011-2013 Devin Teske
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 25, 2012
+.Dd August 6, 2013
.Dt MENU.4TH 8
.Os
.Sh NAME
@@ -83,13 +83,14 @@ The environment variables that effect its behavior are:
.Bl -tag -width bootfile -offset indent
.It Va loader_color
If set to
-.Dq Li YES
+.Dq Li NO
(case-insensitive) or
-.Dq Li 1 ,
-causes the menu to be displayed in color wherever possible.
-This includes the
-use of ANSI bold for numbers appearing to the left of menuitems and the use of
-special
+.Dq Li 0 ,
+causes the menu to be displayed without color.
+The default is to use ANSI coloring whenever possible.
+If serial boot is enabled, color is disabled by default.
+Color features include the use of ANSI bold for numbers appearing to the left
+of menuitems and the use of special
.Dq Li ansi
variables described below.
.It Va autoboot_delay
@@ -108,8 +109,9 @@ will wait for user input and never execute
If set to
.Dq Li -1 ,
.Ic menu-display
-will boot immediately, preventing both interruption of the autoboot process and
-escaping to the loader prompt.
+will boot immediately, preventing both interruption of the
+.Ic autoboot
+process and escaping to the loader prompt.
Default is
.Dq Li 10 .
See
@@ -121,6 +123,14 @@ The command to be executed after
seconds if a key is not pressed.
The default is
.Ic boot .
+.It Va loader_menu_frame
+Sets the desired box style to draw around the boot menu.
+Possible values are:
+.Dq Li single
+.Pq the default ,
+.Dq Li double ,
+and
+.Dq Li none .
.It Va loader_menu_timeout_x
Sets the desired column position of the timeout countdown text.
Default is 4.
@@ -128,9 +138,24 @@ Default is 4.
Sets the desired row position of the timeout countdown text.
Default is 23.
.It Va loader_menu_title
-The text to display centered above the menu.
+The text to display above the menu.
Default is
.Dq Li "Welcome to FreeBSD" .
+.It Va loader_menu_title_align
+Default is to align
+.Ic loader_menu_title
+centered above the menu. This can be set to
+.Dq Li left
+or
+.Dq Li right
+to instead display the title left-or-right justified
+.Pq respectively .
+.It Va loader_menu_x
+Sets the desired column position of the boot menu.
+Default is 5.
+.It Va loader_menu_y
+Sets the desired row position of the boot menu.
+Default is 10.
.It Va menu_caption[x]
The text to be displayed for the numbered menuitem
.Dq Li x .
@@ -147,7 +172,9 @@ When pressed, will cause the execution of
.It Va ansi_caption[x]
If
.Va loader_color
-is set, use this caption for menuitem
+is set
+.Pq enabled by default ,
+use this caption for menuitem
.Dq Li x
instead of
.Va menu_caption[x] .
@@ -164,7 +191,8 @@ Like
.Va toggled_text[x]
except used when
.Va loader_color
-is enabled.
+is enabled
+.Pq default .
.It Va menu_caption[x][y]
For menuitems where
.Va menu_command[x]
@@ -178,7 +206,8 @@ Like
.Va menu_caption[x][y]
except used when
.Va loader_color
-is enabled.
+is enabled
+.Pq default .
.It Va menu_acpi
When set to a number
.Dq Li x
@@ -320,4 +349,4 @@ The
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske@hotmail.com .
+.An Devin Teske Aq dteske@FreeBSD.org .
126 sys/boot/forth/menu.rc
View
@@ -16,56 +16,100 @@ draw-brand \ draw the FreeBSD title (top-left; see `brand.4th')
menu-init \ initialize the menu area (see `menu.4th')
\ Initialize main menu constructs (see `menu.4th')
-\ NOTE: To use the `ansi' variants, add `loader_color=1' to loader.conf(5)
+\ NOTE: To use `non-ansi' variants, add `loader_color=0' to loader.conf(5)
-set menu_caption[1]="Boot [Enter]"
-set menu_command[1]="boot"
-set ansi_caption[1]="Boot [Enter]"
-set menu_keycode[1]="98"
+\
+\ MAIN MENU
+\
+
+set menuset_name1="main"
+
+set mainmenu_init[1]="init_boot"
+set mainmenu_caption[1]="Boot Multi User [Enter]"
+set maintoggled_text[1]="Boot [S]ingle User [Enter]"
+set mainmenu_command[1]="boot"
+set mainansi_caption[1]="Boot Multi User [Enter]"
+set maintoggled_ansi[1]="Boot Single User [Enter]"
+\ keycode set by init_boot
+
+set mainmenu_init[2]="init_altboot"
+set mainmenu_caption[2]="Boot [S]ingle User"
+set maintoggled_text[2]="Boot [M]ulti User"
+set mainmenu_command[2]="altboot"
+set mainansi_caption[2]="Boot Single User"
+set maintoggled_ansi[2]="Boot Multi User"
+\ keycode set by init_altboot
-set menu_caption[2]="[Esc]ape to loader prompt"
-set menu_command[2]="goto_prompt"
-set menu_keycode[2]="27"
-set ansi_caption[2]="Escape to loader prompt"
+set mainmenu_caption[3]="[Esc]ape to loader prompt"
+set mainmenu_command[3]="goto_prompt"
+set mainmenu_keycode[3]=27
+set mainansi_caption[3]="Escape to loader prompt"
\ Enable built-in "Reboot" trailing menuitem
\ NOTE: appears before menu_options if configured
\
-set menu_reboot
+set mainmenu_reboot
\ Enable "Options:" separator. When set to a numerical value (1-8), a visual
\ separator is inserted before that menuitem number.
\
-set menu_options=4
-
-set menu_caption[4]="[A]CPI Support off"
-set toggled_text[4]="[A]CPI Support On"
-set menu_command[4]="toggle_acpi"
-set menu_keycode[4]="97"
-set menu_acpi=4
-set ansi_caption[4]="ACPI Support Off"
-set toggled_ansi[4]="ACPI Support On"
-
-set menu_caption[5]="Safe [M]ode... off"
-set toggled_text[5]="Safe [M]ode... On"
-set menu_command[5]="toggle_safemode"
-set menu_keycode[5]="109"
-set ansi_caption[5]="Safe Mode... Off"
-set toggled_ansi[5]="Safe Mode... On"
-
-set menu_caption[6]="[S]ingle User. off"
-set toggled_text[6]="[S]ingle User. On"
-set menu_command[6]="toggle_singleuser"
-set menu_keycode[6]="115"
-set ansi_caption[6]="Single User. Off"
-set toggled_ansi[6]="Single User. On"
-
-set menu_caption[7]="[V]erbose..... off"
-set toggled_text[7]="[V]erbose..... On"
-set menu_command[7]="toggle_verbose"
-set menu_keycode[7]="118"
-set ansi_caption[7]="Verbose..... Off"
-set toggled_ansi[7]="Verbose..... On"
+set mainmenu_options=5
+
+set mainmenu_caption[5]="Configure Boot [O]ptions..."
+set mainmenu_command[5]="2 goto_menu"
+set mainmenu_keycode[5]=111
+set mainansi_caption[5]="Configure Boot Options..."
+
+\
+\ BOOT OPTIONS MENU
+\
+
+set menuset_name2="options"
+
+set optionsmenu_caption[1]="Back to Main Menu [Backspace]"
+set optionsmenu_command[1]="1 goto_menu"
+set optionsmenu_keycode[1]=8
+set optionsansi_caption[1]="Back to Main Menu [Backspace]"
+
+set optionsmenu_caption[2]="Load System [D]efaults"
+set optionsmenu_command[2]="set_default_boot_options"
+set optionsmenu_keycode[2]=100
+set optionsansi_caption[2]="Load System Defaults"
+
+set optionsmenu_options=3
+set optionsmenu_optionstext="Boot Options:"
+
+set optionsmenu_acpi=3
+set optionsmenu_caption[3]="[A]CPI Support off"
+set optionstoggled_text[3]="[A]CPI Support On"
+set optionsmenu_command[3]="toggle_acpi"
+set optionsmenu_keycode[3]=97
+set optionsansi_caption[3]="ACPI Support Off"
+set optionstoggled_ansi[3]="ACPI Support On"
+
+set optionsmenu_init[4]="init_safemode"
+set optionsmenu_caption[4]="Safe [M]ode... off"
+set optionstoggled_text[4]="Safe [M]ode... On"
+set optionsmenu_command[4]="toggle_safemode"
+set optionsmenu_keycode[4]=109
+set optionsansi_caption[4]="Safe Mode... Off"
+set optionstoggled_ansi[4]="Safe Mode... On"
+
+set optionsmenu_init[5]="init_singleuser"
+set optionsmenu_caption[5]="[S]ingle User. off"
+set optionstoggled_text[5]="[S]ingle User. On"
+set optionsmenu_command[5]="toggle_singleuser"
+set optionsmenu_keycode[5]=115
+set optionsansi_caption[5]="Single User. Off"
+set optionstoggled_ansi[5]="Single User. On"
+
+set optionsmenu_init[6]="init_verbose"
+set optionsmenu_caption[6]="[V]erbose..... off"
+set optionstoggled_text[6]="[V]erbose..... On"
+set optionsmenu_command[6]="toggle_verbose"
+set optionsmenu_keycode[6]=118
+set optionsansi_caption[6]="Verbose..... Off"
+set optionstoggled_ansi[6]="Verbose..... On"
\ Enable automatic booting (add ``autoboot_delay=N'' to loader.conf(5) to
\ customize the timeout; default is 10-seconds)
@@ -73,4 +117,6 @@ set toggled_ansi[7]="Verbose..... On"
set menu_timeout_command="boot"
\ Display the main menu (see `menu.4th')
+set menuset_initial=1
+menuset-loadinitial
menu-display
610 sys/boot/forth/menusets.4th
View
@@ -0,0 +1,610 @@
+\ Copyright (c) 2012 Devin Teske <dteske@FreeBSD.org>
+\ All rights reserved.
+\
+\ Redistribution and use in source and binary forms, with or without
+\ modification, are permitted provided that the following conditions
+\ are met:
+\ 1. Redistributions of source code must retain the above copyright
+\ notice, this list of conditions and the following disclaimer.
+\ 2. Redistributions in binary form must reproduce the above copyright
+\ notice, this list of conditions and the following disclaimer in the
+\ documentation and/or other materials provided with the distribution.
+\
+\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+\ SUCH DAMAGE.
+\
+\ $FreeBSD$
+
+marker task-menusets.4th
+
+variable menuset_use_name
+
+create menuset_affixbuf 255 allot
+create menuset_x 1 allot
+create menuset_y 1 allot
+
+: menuset-loadvar ( -- )
+
+ \ menuset_use_name is true or false
+ \ $type should be set to one of:
+ \ menu toggled ansi
+ \ $var should be set to one of:
+ \ caption command keycode text ...
+ \ $affix is either prefix (menuset_use_name is true)
+ \ or infix (menuset_use_name is false)
+
+ s" set cmdbuf='set ${type}_${var}=\$'" evaluate
+ s" cmdbuf" getenv swap drop ( -- u1 ) \ get string length
+ menuset_use_name @ true = if
+ s" set cmdbuf=${cmdbuf}${affix}${type}_${var}"
+ ( u1 -- u1 c-addr2 u2 )
+ else
+ s" set cmdbuf=${cmdbuf}${type}set${affix}_${var}"
+ ( u1 -- u1 c-addr2 u2 )
+ then
+ evaluate ( u1 c-addr2 u2 -- u1 )
+ s" cmdbuf" getenv ( u1 -- u1 c-addr2 u2 )
+ rot 2 pick 2 pick over + -rot + tuck -
+ ( u1 c-addr2 u2 -- c-addr2 u2 c-addr1 u1 )
+ \ Generate a string representing rvalue inheritance var
+ getenv dup -1 = if
+ ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 -1 )
+ \ NOT set -- clean up the stack
+ drop ( c-addr2 u2 -1 -- c-addr2 u2 )
+ 2drop ( c-addr2 u2 -- )
+ else
+ ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 c-addr1 u1 )
+ \ SET -- execute cmdbuf (c-addr2/u2) to inherit value
+ 2drop ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 )
+ evaluate ( c-addr2 u2 -- )
+ then
+
+ s" cmdbuf" unsetenv
+;
+
+: menuset-unloadvar ( -- )
+
+ \ menuset_use_name is true or false
+ \ $type should be set to one of:
+ \ menu toggled ansi
+ \ $var should be set to one of:
+ \ caption command keycode text ...
+ \ $affix is either prefix (menuset_use_name is true)
+ \ or infix (menuset_use_name is false)
+
+ menuset_use_name @ true = if
+ s" set buf=${affix}${type}_${var}"
+ else
+ s" set buf=${type}set${affix}_${var}"
+ then
+ evaluate
+ s" buf" getenv unsetenv
+ s" buf" unsetenv
+;
+
+: menuset-loadmenuvar ( -- )
+ s" set type=menu" evaluate
+ menuset-loadvar
+;
+
+: menuset-unloadmenuvar ( -- )
+ s" set type=menu" evaluate
+ menuset-unloadvar
+;
+
+: menuset-loadxvar ( -- )
+
+ \ menuset_use_name is true or false
+ \ $type should be set to one of:
+ \ menu toggled ansi
+ \ $var should be set to one of:
+ \ caption command keycode text ...
+ \ $x is "1" through "8"
+ \ $affix is either prefix (menuset_use_name is true)
+ \ or infix (menuset_use_name is false)
+
+ s" set cmdbuf='set ${type}_${var}[${x}]=\$'" evaluate
+ s" cmdbuf" getenv swap drop ( -- u1 ) \ get string length
+ menuset_use_name @ true = if
+ s" set cmdbuf=${cmdbuf}${affix}${type}_${var}[${x}]"
+ ( u1 -- u1 c-addr2 u2 )
+ else
+ s" set cmdbuf=${cmdbuf}${type}set${affix}_${var}[${x}]"
+ ( u1 -- u1 c-addr2 u2 )
+ then
+ evaluate ( u1 c-addr2 u2 -- u1 )
+ s" cmdbuf" getenv ( u1 -- u1 c-addr2 u2 )
+ rot 2 pick 2 pick over + -rot + tuck -
+ ( u1 c-addr2 u2 -- c-addr2 u2 c-addr1 u1 )
+ \ Generate a string representing rvalue inheritance var
+ getenv dup -1 = if
+ ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 -1 )
+ \ NOT set -- clean up the stack
+ drop ( c-addr2 u2 -1 -- c-addr2 u2 )
+ 2drop ( c-addr2 u2 -- )
+ else
+ ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 c-addr1 u1 )
+ \ SET -- execute cmdbuf (c-addr2/u2) to inherit value
+ 2drop ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 )
+ evaluate ( c-addr2 u2 -- )
+ then
+
+ s" cmdbuf" unsetenv
+;
+
+: menuset-unloadxvar ( -- )
+
+ \ menuset_use_name is true or false
+ \ $type should be set to one of:
+ \ menu toggled ansi
+ \ $var should be set to one of:
+ \ caption command keycode text ...
+ \ $x is "1" through "8"
+ \ $affix is either prefix (menuset_use_name is true)
+ \ or infix (menuset_use_name is false)
+
+ menuset_use_name @ true = if
+ s" set buf=${affix}${type}_${var}[${x}]"
+ else
+ s" set buf=${type}set${affix}_${var}[${x}]"
+ then
+ evaluate
+ s" buf" getenv unsetenv
+ s" buf" unsetenv
+;
+
+: menuset-loadansixvar ( -- )
+ s" set type=ansi" evaluate
+ menuset-loadxvar
+;
+
+: menuset-unloadansixvar ( -- )
+ s" set type=ansi" evaluate
+ menuset-unloadxvar
+;
+
+: menuset-loadmenuxvar ( -- )
+ s" set type=menu" evaluate
+ menuset-loadxvar
+;
+
+: menuset-unloadmenuxvar ( -- )
+ s" set type=menu" evaluate
+ menuset-unloadxvar
+;
+
+: menuset-loadtoggledxvar ( -- )
+ s" set type=toggled" evaluate
+ menuset-loadxvar
+;
+
+: menuset-unloadtoggledxvar ( -- )
+ s" set type=toggled" evaluate
+ menuset-unloadxvar
+;
+
+: menuset-loadxyvar ( -- )
+
+ \ menuset_use_name is true or false
+ \ $type should be set to one of:
+ \ menu toggled ansi
+ \ $var should be set to one of:
+ \ caption command keycode text ...
+ \ $x is "1" through "8"
+ \ $y is "0" through "9"
+ \ $affix is either prefix (menuset_use_name is true)
+ \ or infix (menuset_use_name is false)
+
+ s" set cmdbuf='set ${type}_${var}[${x}][${y}]=\$'" evaluate
+ s" cmdbuf" getenv swap drop ( -- u1 ) \ get string length
+ menuset_use_name @ true = if
+ s" set cmdbuf=${cmdbuf}${affix}${type}_${var}[${x}][${y}]"
+ ( u1 -- u1 c-addr2 u2 )
+ else
+ s" set cmdbuf=${cmdbuf}${type}set${affix}_${var}[${x}][${y}]"
+ ( u1 -- u1 c-addr2 u2 )
+ then
+ evaluate ( u1 c-addr2 u2 -- u1 )
+ s" cmdbuf" getenv ( u1 -- u1 c-addr2 u2 )
+ rot 2 pick 2 pick over + -rot + tuck -
+ ( u1 c-addr2 u2 -- c-addr2 u2 c-addr1 u1 )
+ \ Generate a string representing rvalue inheritance var
+ getenv dup -1 = if
+ ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 -1 )
+ \ NOT set -- clean up the stack
+ drop ( c-addr2 u2 -1 -- c-addr2 u2 )
+ 2drop ( c-addr2 u2 -- )
+ else
+ ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 c-addr1 u1 )
+ \ SET -- execute cmdbuf (c-addr2/u2) to inherit value
+ 2drop ( c-addr2 u2 c-addr1 u1 -- c-addr2 u2 )
+ evaluate ( c-addr2 u2 -- )
+ then
+
+ s" cmdbuf" unsetenv
+;
+
+: menuset-unloadxyvar ( -- )
+
+ \ menuset_use_name is true or false
+ \ $type should be set to one of:
+ \ menu toggled ansi
+ \ $var should be set to one of:
+ \ caption command keycode text ...
+ \ $x is "1" through "8"
+ \ $y is "0" through "9"
+ \ $affix is either prefix (menuset_use_name is true)
+ \ or infix (menuset_use_name is false)
+
+ menuset_use_name @ true = if
+ s" set buf=${affix}${type}_${var}[${x}][${y}]"
+ else
+ s" set buf=${type}set${affix}_${var}[${x}][${y}]"
+ then
+ evaluate
+ s" buf" getenv unsetenv
+ s" buf" unsetenv
+;
+
+: menuset-loadansixyvar ( -- )
+ s" set type=ansi" evaluate
+ menuset-loadxyvar
+;
+
+: menuset-unloadansixyvar ( -- )
+ s" set type=ansi" evaluate
+ menuset-unloadxyvar
+;
+
+: menuset-loadmenuxyvar ( -- )
+ s" set type=menu" evaluate
+ menuset-loadxyvar
+;
+
+: menuset-unloadmenuxyvar ( -- )
+ s" set type=menu" evaluate
+ menuset-unloadxyvar
+;
+
+: menuset-setnum-namevar ( N -- C-Addr/U )
+
+ s" menuset_nameNNNNN" ( n -- n c-addr1 u1 ) \ variable basename
+ drop 12 ( n c-addr1 u1 -- n c-addr1 12 ) \ remove "NNNNN"
+ rot ( n c-addr1 12 -- c-addr1 12 n ) \ move number on top
+
+ \ convert to string
+ s>d <# #s #> ( c-addr1 12 n -- c-addr1 12 c-addr2 u2 )
+
+ \ Combine strings
+ begin ( using u2 in c-addr2/u2 pair as countdown to zero )
+ over ( c-addr1 u1 c-addr2 u2 -- continued below )
+ ( c-addr1 u1 c-addr2 u2 c-addr2 ) \ copy src-addr
+ c@ ( c-addr1 u1 c-addr2 u2 c-addr2 -- continued below )
+ ( c-addr1 u1 c-addr2 u2 c ) \ get next src-addr byte
+ 4 pick 4 pick
+ ( c-addr1 u1 c-addr2 u2 c -- continued below )
+ ( c-addr1 u1 c-addr2 u2 c c-addr1 u1 )
+ \ get destination c-addr1/u1 pair
+ + ( c-addr1 u1 c-addr2 u2 c c-addr1 u1 -- cont. below )
+ ( c-addr1 u1 c-addr2 u2 c c-addr3 )
+ \ combine dest-c-addr to get dest-addr for byte
+ c! ( c-addr1 u1 c-addr2 u2 c c-addr3 -- continued below )
+ ( c-addr1 u1 c-addr2 u2 )
+ \ store the current src-addr byte into dest-addr
+
+ 2swap 1+ 2swap \ increment u1 in destination c-addr1/u1 pair
+ swap 1+ swap \ increment c-addr2 in source c-addr2/u2 pair
+ 1- \ decrement u2 in the source c-addr2/u2 pair
+
+ dup 0= \ time to break?
+ until
+
+ 2drop ( c-addr1 u1 c-addr2 u2 -- c-addr1 u1 )
+ \ drop temporary number-format conversion c-addr2/u2
+;
+
+: menuset-checksetnum ( N -- )
+
+ \
+ \ adjust input to be both positive and no-higher than 65535
+ \
+ abs dup 65535 > if drop 65535 then ( n -- n )
+
+ \
+ \ The next few blocks will determine if we should use the default
+ \ methodology (referencing the original numeric stack-input), or if-
+ \ instead $menuset_name{N} has been defined wherein we would then
+ \ use the value thereof as the prefix to every menu variable.
+ \
+
+ false menuset_use_name ! \ assume name is not set
+
+ menuset-setnum-namevar
+ \
+ \ We now have a string that is the assembled variable name to check
+ \ for... $menuset_name{N}. Let's check for it.
+ \
+ 2dup ( c-addr1 u1 -- c-addr1 u1 c-addr1 u1 ) \ save a copy
+ getenv dup -1 <> if ( c-addr1 u1 c-addr1 u1 -- c-addr1 u1 c-addr2 u2 )
+ \ The variable is set. Let's clean up the stack leaving only
+ \ its value for later use.
+
+ true menuset_use_name !
+ 2swap 2drop ( c-addr1 u1 c-addr2 u2 -- c-addr2 u2 )
+ \ drop assembled variable name, leave the value
+ else ( c-addr1 u1 c-addr1 u1 -- c-addr1 u1 -1 ) \ no such variable
+ \ The variable is not set. Let's clean up the stack leaving the
+ \ string [portion] representing the original numeric input.
+
+ drop ( c-addr1 u1 -1 -- c-addr1 u1 ) \ drop -1 result
+ 12 - swap 12 + swap ( c-addr1 u1 -- c-addr2 u2 )
+ \ truncate to original numeric stack-input
+ then
+
+ \
+ \ Now, depending on whether $menuset_name{N} has been set, we have
+ \ either the value thereof to be used as a prefix to all menu_*
+ \ variables or we have a string representing the numeric stack-input
+ \ to be used as a "set{N}" infix to the same menu_* variables.
+ \
+ \ For example, if the stack-input is 1 and menuset_name1 is NOT set
+ \ the following variables will be referenced:
+ \ ansiset1_caption[x] -> ansi_caption[x]
+ \ ansiset1_caption[x][y] -> ansi_caption[x][y]
+ \ menuset1_acpi -> menu_acpi
+ \ menuset1_caption[x] -> menu_caption[x]
+ \ menuset1_caption[x][y] -> menu_caption[x][y]
+ \ menuset1_command[x] -> menu_command[x]
+ \ menuset1_init -> ``evaluated''
+ \ menuset1_init[x] -> menu_init[x]
+ \ menuset1_keycode[x] -> menu_keycode[x]
+ \ menuset1_options -> menu_options
+ \ menuset1_optionstext -> menu_optionstext
+ \ menuset1_reboot -> menu_reboot
+ \ toggledset1_ansi[x] -> toggled_ansi[x]
+ \ toggledset1_text[x] -> toggled_text[x]
+ \ otherwise, the following variables are referenced (where {name}
+ \ represents the value of $menuset_name1 (given 1 as stack-input):
+ \ {name}ansi_caption[x] -> ansi_caption[x]
+ \ {name}ansi_caption[x][y] -> ansi_caption[x][y]
+ \ {name}menu_acpi -> menu_acpi
+ \ {name}menu_caption[x] -> menu_caption[x]
+ \ {name}menu_caption[x][y] -> menu_caption[x][y]
+ \ {name}menu_command[x] -> menu_command[x]
+ \ {name}menu_init -> ``evaluated''
+ \ {name}menu_init[x] -> menu_init[x]
+ \ {name}menu_keycode[x] -> menu_keycode[x]
+ \ {name}menu_options -> menu_options
+ \ {name}menu_optionstext -> menu_optionstext
+ \ {name}menu_reboot -> menu_reboot
+ \ {name}toggled_ansi[x] -> toggled_ansi[x]
+ \ {name}toggled_text[x] -> toggled_text[x]
+ \
+ \ Note that menuset{N}_init and {name}menu_init are the initializers
+ \ for the entire menu (for wholly dynamic menus) opposed to the per-
+ \ menuitem initializers (with [x] afterward). The whole-menu init
+ \ routine is evaluated and not passed down to $menu_init (which
+ \ would result in double evaluation). By doing this, the initializer
+ \ can initialize the menuset before we transfer it to active-duty.
+ \
+
+ \
+ \ Copy our affixation (prefix or infix depending on menuset_use_name)
+ \ to our buffer so that we can safely use the s-quote (s") buf again.
+ \
+ menuset_affixbuf 0 2swap ( c-addr2 u2 -- c-addr1 0 c-addr2 u2 )
+ begin ( using u2 in c-addr2/u2 pair as countdown to zero )
+ over ( c-addr1 u1 c-addr2 u2 -- c-addr1 u1 c-addr2 u2 c-addr2 )
+ c@ ( c-addr1 u1 c-addr2 u2 -- c-addr1 u1 c-addr2 u2 c )
+ 4 pick 4 pick
+ ( c-addr1 u1 c-addr2 u2 c -- continued below )
+ ( c-addr1 u1 c-addr2 u2 c c-addr1 u1 )
+ + ( c-addr1 u1 c-addr2 u2 c c-addr1 u1 -- continued below )
+ ( c-addr1 u1 c-addr2 u2 c c-addr3 )
+ c! ( c-addr1 u1 c-addr2 u2 c c-addr3 -- continued below )
+ ( c-addr1 u1 c-addr2 u2 )
+ 2swap 1+ 2swap \ increment affixbuf byte position/count
+ swap 1+ swap \ increment strbuf pointer (source c-addr2)
+ 1- \ decrement strbuf byte count (source u2)
+ dup 0= \ time to break?
+ until
+ 2drop ( c-addr1 u1 c-addr2 u2 -- c-addr1 u1 ) \ drop strbuf c-addr2/u2
+
+ \
+ \ Create a variable for referencing our affix data (prefix or infix
+ \ depending on menuset_use_name as described above). This variable will
+ \ be temporary and only used to simplify cmdbuf assembly.
+ \
+ s" affix" setenv ( c-addr1 u1 -- )
+;
+
+: menuset-cleanup ( -- )
+ s" type" unsetenv
+ s" var" unsetenv
+ s" x" unsetenv
+ s" y" unsetenv
+ s" affix" unsetenv
+;
+
+: menuset-loadsetnum ( N -- )
+
+ menuset-checksetnum ( n -- )
+
+ \
+ \ From here out, we use temporary environment variables to make
+ \ dealing with variable-length strings easier.
+ \
+ \ menuset_use_name is true or false
+ \ $affix should be used appropriately w/respect to menuset_use_name
+ \
+
+ \ ... menu_init ...
+ s" set var=init" evaluate
+ menuset-loadmenuvar
+
+ \ If menu_init was set by the above, evaluate it here-and-now
+ \ so that the remaining variables are influenced by its actions
+ s" menu_init" 2dup getenv dup -1 <> if
+ 2swap unsetenv \ don't want later menu-create to re-call this
+ evaluate
+ else
+ drop 2drop ( n c-addr u -1 -- n )
+ then
+
+ [char] 1 ( -- x ) \ Loop range ASCII '1' (49) to '8' (56)
+ begin
+ dup menuset_x tuck c! 1 s" x" setenv \ set loop iterator and $x
+
+ s" set var=caption" evaluate
+
+ \ ... menu_caption[x] ...
+ menuset-loadmenuxvar
+
+ \ ... ansi_caption[x] ...
+ menuset-loadansixvar
+
+ [char] 0 ( x -- x y ) \ Inner Loop ASCII '1' (48) to '9' (57)
+ begin
+ dup me