aboutsummaryrefslogtreecommitdiff
path: root/stand/forth
diff options
context:
space:
mode:
Diffstat (limited to 'stand/forth')
-rw-r--r--stand/forth/Makefile49
-rw-r--r--stand/forth/Makefile.depend11
-rw-r--r--stand/forth/beastie.4th110
-rw-r--r--stand/forth/beastie.4th.8173
-rw-r--r--stand/forth/brand-fbsd.4th46
-rw-r--r--stand/forth/brand.4th74
-rw-r--r--stand/forth/brand.4th.8125
-rw-r--r--stand/forth/check-password.4th179
-rw-r--r--stand/forth/check-password.4th.8167
-rw-r--r--stand/forth/color.4th49
-rw-r--r--stand/forth/color.4th.8116
-rw-r--r--stand/forth/delay.4th119
-rw-r--r--stand/forth/delay.4th.8126
-rw-r--r--stand/forth/efi.4th30
-rw-r--r--stand/forth/frames.4th142
-rw-r--r--stand/forth/loader.4th266
-rw-r--r--stand/forth/loader.4th.8233
-rw-r--r--stand/forth/loader.conf568
-rw-r--r--stand/forth/loader.conf.5330
-rw-r--r--stand/forth/loader.rc23
-rw-r--r--stand/forth/logo-beastie.4th61
-rw-r--r--stand/forth/logo-beastiebw.4th59
-rw-r--r--stand/forth/logo-fbsdbw.4th53
-rw-r--r--stand/forth/logo-orb.4th55
-rw-r--r--stand/forth/logo-orbbw.4th54
-rw-r--r--stand/forth/menu-commands.4th418
-rw-r--r--stand/forth/menu.4th1319
-rw-r--r--stand/forth/menu.4th.8352
-rw-r--r--stand/forth/menu.rc202
-rw-r--r--stand/forth/menusets.4th624
-rw-r--r--stand/forth/menusets.4th.8372
-rw-r--r--stand/forth/pcibios.4th47
-rw-r--r--stand/forth/pnp.4th205
-rw-r--r--stand/forth/screen.4th74
-rw-r--r--stand/forth/shortcuts.4th50
-rw-r--r--stand/forth/support.4th1606
-rw-r--r--stand/forth/version.4th96
-rw-r--r--stand/forth/version.4th.8128
38 files changed, 8711 insertions, 0 deletions
diff --git a/stand/forth/Makefile b/stand/forth/Makefile
new file mode 100644
index 000000000000..74d9ed744322
--- /dev/null
+++ b/stand/forth/Makefile
@@ -0,0 +1,49 @@
+# $FreeBSD$
+
+.include <bsd.init.mk>
+
+MAN+= beastie.4th.8 \
+ brand.4th.8 \
+ check-password.4th.8 \
+ color.4th.8 \
+ delay.4th.8 \
+ loader.conf.5 \
+ loader.4th.8 \
+ menu.4th.8 \
+ menusets.4th.8 \
+ version.4th.8
+
+FILES+= beastie.4th
+FILES+= brand.4th
+FILES+= brand-fbsd.4th
+FILES+= check-password.4th
+FILES+= color.4th
+FILES+= delay.4th
+FILES+= efi.4th
+FILES+= frames.4th
+FILES+= loader.4th
+FILES+= logo-beastie.4th
+FILES+= logo-beastiebw.4th
+FILES+= logo-fbsdbw.4th
+FILES+= logo-orb.4th
+FILES+= logo-orbbw.4th
+FILES+= menu.4th
+FILES+= menu-commands.4th
+FILES+= menusets.4th
+FILES+= pcibios.4th
+FILES+= screen.4th
+FILES+= shortcuts.4th
+FILES+= support.4th
+FILES+= version.4th
+FILESDIR_loader.conf= /boot/defaults
+
+# Allow machine specific loader.rc to be installed.
+.for f in loader.rc menu.rc loader.conf
+.if exists(${BOOTSRC}/${MACHINE:C/amd64/i386/}/loader/${f})
+FILES+= ${BOOTSRC}/${MACHINE:C/amd64/i386/}/loader/${f}
+.else
+FILES+= ${f}
+.endif
+.endfor
+
+.include <bsd.prog.mk>
diff --git a/stand/forth/Makefile.depend b/stand/forth/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/stand/forth/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/stand/forth/beastie.4th b/stand/forth/beastie.4th
new file mode 100644
index 000000000000..752cce22a4ff
--- /dev/null
+++ b/stand/forth/beastie.4th
@@ -0,0 +1,110 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
+\ Copyright (c) 2006-2015 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-beastie.4th
+
+only forth definitions
+
+variable logoX
+variable logoY
+
+\ Initialize logo placement to defaults
+46 logoX !
+4 logoY !
+
+\ This function draws any number of beastie logos at (loader_logo_x,
+\ loader_logo_y) if defined, else (46,4) (to the right of the menu). To choose
+\ your beastie, set the variable `loader_logo' to the respective logo name.
+\
+\ NOTE: Each is defined as a logo function in /boot/logo-${loader_logo}.4th
+\ NOTE: If `/boot/logo-${loader_logo}.4th' does not exist or does not define
+\ a `logo' function, no beastie is drawn.
+\
+: draw-beastie ( -- ) \ at (loader_logo_x,loader_logo_y), else (46,4)
+
+ s" loader_logo_x" getenv dup -1 <> if
+ ?number 1 = if logoX ! then
+ else drop then
+ s" loader_logo_y" getenv dup -1 <> if
+ ?number 1 = if logoY ! then
+ else drop then
+
+
+ \ If `logo' is defined, execute it
+ s" logo" sfind ( -- xt|0 bool ) if
+ logoX @ logoY @ rot execute
+ else
+ \ Not defined; try-include desired logo file
+ drop ( xt = 0 ) \ cruft
+ s" loader_logo" getenv dup -1 = over 0= or if
+ dup 0= if 2drop else drop then \ getenv result unused
+ loader_color? if
+ s" try-include /boot/logo-orb.4th"
+ else
+ s" try-include /boot/logo-orbbw.4th"
+ then
+ else
+ 2drop ( c-addr/u -- ) \ getenv result unused
+ s" try-include /boot/logo-${loader_logo}.4th"
+ then
+ evaluate
+ 1 spaces
+
+ \ Execute `logo' if defined now
+ s" logo" sfind if
+ logoX @ logoY @ rot execute
+ else drop then
+ then
+;
+
+also support-functions
+
+: beastie-start ( -- ) \ starts the menu
+ s" beastie_disable" getenv dup -1 <> if
+ s" YES" compare-insensitive 0= if
+ any_conf_read? if
+ load_xen_throw
+ load_kernel
+ load_modules
+ then
+ exit \ to autoboot (default)
+ then
+ else drop then
+
+ s" loader_delay" getenv -1 = if
+ s" include /boot/menu.rc" evaluate
+ else
+ drop
+ ." Loading Menu (Ctrl-C to Abort)" cr
+ s" set delay_command='include /boot/menu.rc'" evaluate
+ s" set delay_showdots" evaluate
+ delay_execute
+ then
+;
+
+only forth definitions
diff --git a/stand/forth/beastie.4th.8 b/stand/forth/beastie.4th.8
new file mode 100644
index 000000000000..e99f65474b43
--- /dev/null
+++ b/stand/forth/beastie.4th.8
@@ -0,0 +1,173 @@
+.\" Copyright (c) 2011-2012 Devin Teske
+.\" 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$
+.\"
+.Dd January 6, 2016
+.Dt BEASTIE.4TH 8
+.Os
+.Sh NAME
+.Nm beastie.4th
+.Nd FreeBSD ASCII art boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to draw the ASCII art FreeBSD mascot
+\(en known simply as
+.Em beastie
+\(en to the right of the boot loader menu.
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include beastie.4th
+.Pp
+This line is present in the default
+.Pa /boot/loader.rc
+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 draw-beastie
+Draws the FreeBSD logo.
+.Pp
+The logo that is drawn is configured by setting the
+.Ic loader_logo
+variable in
+.Xr loader.conf 5
+to one of
+.Dq Li beastie ,
+.Dq Li beastiebw ,
+.Dq Li fbsdbw ,
+.Dq Li orb ,
+and
+.Dq Li orbbw
+(the default).
+.Pp
+The position of the logo can be configured by setting the
+.Ic loader_logo_x
+and
+.Ic loader_logo_y
+variables in
+.Xr loader.conf 5 .
+The default values are 46 (x) and 4 (y).
+.Pp
+.It Ic clear-beastie
+Clears the screen of beastie.
+.Pp
+.It Ic beastie-start
+Initializes the interactive boot loader menu.
+.Pp
+The
+.Ic loader_delay
+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
+.Ic autoboot
+or ENTER to proceed.
+The default behavior is to not delay.
+.El
+.Pp
+The environment variables that effect its behavior are:
+.Bl -tag -width bootfile -offset indent
+.It Va loader_logo
+Selects the desired logo in the beastie boot menu. Possible values are:
+.Dq Li fbsdbw ,
+.Dq Li beastie ,
+.Dq Li beastiebw ,
+.Dq Li orb ,
+.Dq Li orbbw
+(default), and
+.Dq Li none .
+.It Va loader_logo_x
+Sets the desired column position of the logo. Default is 46.
+.It Va loader_logo_y
+Sets the desired row position of the logo. Default is 4.
+.It Va beastie_disable
+If set to
+.Dq YES ,
+the beastie boot menu will be skipped.
+The beastie boot menu is always skipped if running non-x86 hardware.
+.It Va loader_delay
+If set to a number higher than zero, introduces a delay before starting the
+beastie boot menu. During the delay the user can press either Ctrl-C to skip
+the menu or ENTER to proceed to the menu. The default is to not delay when
+loading the menu.
+.El
+.Sh FILES
+.Bl -tag -width /boot/loader.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/beastie.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+Standard i386
+.Pa /boot/loader.rc :
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/beastie.4th
+beastie-start
+.Ed
+.Pp
+Set a different logo in
+.Xr loader.conf 5 :
+.Pp
+.Bd -literal -offset indent -compact
+loader_logo="beastie"
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr loader 8 ,
+.Xr loader.4th 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 5.1 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Scott Long Aq scottl@FreeBSD.org ,
+.An Aleksander Fafula Aq alex@fafula.com
+and
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/brand-fbsd.4th b/stand/forth/brand-fbsd.4th
new file mode 100644
index 000000000000..9cd017f84a3f
--- /dev/null
+++ b/stand/forth/brand-fbsd.4th
@@ -0,0 +1,46 @@
+\ Copyright (c) 2006-2015 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$
+
+2 brandX ! 1 brandY ! \ Initialize brand placement defaults
+
+: brand+ ( x y c-addr/u -- x y' )
+ 2swap 2dup at-xy 2swap \ position the cursor
+ type \ print to the screen
+ 1+ \ increase y for next time we're called
+;
+
+: brand ( x y -- ) \ "FreeBSD" [wide] logo in B/W (7 rows x 42 columns)
+
+ s" ______ ____ _____ _____ " brand+
+ s" | ____| | _ \ / ____| __ \ " brand+
+ s" | |___ _ __ ___ ___ | |_) | (___ | | | |" brand+
+ s" | ___| '__/ _ \/ _ \| _ < \___ \| | | |" brand+
+ s" | | | | | __/ __/| |_) |____) | |__| |" brand+
+ s" | | | | | | || | | |" brand+
+ s" |_| |_| \___|\___||____/|_____/|_____/ " brand+
+
+ 2drop
+;
diff --git a/stand/forth/brand.4th b/stand/forth/brand.4th
new file mode 100644
index 000000000000..39a9bfae753c
--- /dev/null
+++ b/stand/forth/brand.4th
@@ -0,0 +1,74 @@
+\ Copyright (c) 2006-2015 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-brand.4th
+
+variable brandX
+variable brandY
+
+\ Initialize brand placement to defaults
+2 brandX !
+1 brandY !
+
+\ This function draws any number of company brands at (loader_brand_x,
+\ loader_brand_y) if defined, or (2,1) (top-left). To choose your brand, set
+\ the variable `loader_brand' to the respective brand name.
+\
+\ NOTE: Each is defined as a brand function in /boot/brand-${loader_brand}.4th
+\ NOTE: If `/boot/brand-${loader_brand}.4th' does not exist or does not define
+\ a `brand' function, no brand is drawn.
+\
+: draw-brand ( -- ) \ at (loader_brand_x,loader_brand_y), else (2,1)
+
+ s" loader_brand_x" getenv dup -1 <> if
+ ?number 1 = if brandX ! then
+ else drop then
+ s" loader_brand_y" getenv dup -1 <> if
+ ?number 1 = if brandY ! then
+ else drop then
+
+ \ If `brand' is defined, execute it
+ s" brand" sfind ( -- xt|0 bool ) if
+ brandX @ brandY @ rot execute
+ else
+ \ Not defined; try-include desired brand file
+ drop ( xt = 0 ) \ cruft
+ s" loader_brand" getenv dup -1 = over 0= or if
+ dup 0= if 2drop else drop then \ getenv result unused
+ s" try-include /boot/brand-fbsd.4th"
+ else
+ 2drop ( c-addr/u -- ) \ getenv result unused
+ s" try-include /boot/brand-${loader_brand}.4th"
+ then
+ evaluate
+ 1 spaces
+
+ \ Execute `brand' if defined now
+ s" brand" sfind if
+ brandX @ brandY @ rot execute
+ else drop then
+ then
+;
diff --git a/stand/forth/brand.4th.8 b/stand/forth/brand.4th.8
new file mode 100644
index 000000000000..dfd188d0ff84
--- /dev/null
+++ b/stand/forth/brand.4th.8
@@ -0,0 +1,125 @@
+.\" Copyright (c) 2011 Devin Teske
+.\" 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$
+.\"
+.Dd May 18, 2011
+.Dt BRAND.4TH 8
+.Os
+.Sh NAME
+.Nm brand.4th
+.Nd FreeBSD ASCII art boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to draw the ASCII art BSD brand above the boot
+loader menu.
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include brand.4th
+.Pp
+This line is present in the default
+.Pa /boot/menu.rc
+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 draw-brand
+Draws the BSD brand.
+.Pp
+The brand that is drawn is configured by setting the
+.Ic loader_brand
+variable in
+.Xr loader.conf 5
+to one of
+.Dq Li fbsd
+(the default) or
+.Dq Li none .
+.Pp
+The position of the logo can be configured by setting the
+.Ic loader_brand_x
+and
+.Ic loader_brand_y
+variables in
+.Xr loader.conf 5 .
+The default values are 2 (x) and 1 (y).
+.El
+.Pp
+The environment variables that effect its behavior are:
+.Bl -tag -width bootfile -offset indent
+.It Va loader_brand
+Selects the desired brand in the beastie boot menu. Possible values are:
+.Dq Li fbsd
+(default) or
+.Dq Li none .
+.It Va loader_brand_x
+Sets the desired column position of the brand. Default is 2.
+.It Va loader_brand_y
+Sets the desired row position of the brand. Default is 1.
+.El
+.Sh FILES
+.Bl -tag -width /boot/loader.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/brand.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+Set FreeBSD brand in
+.Xr loader.conf 5 :
+.Pp
+.Bd -literal -offset indent -compact
+loader_brand="fbsd"
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr loader 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/check-password.4th b/stand/forth/check-password.4th
new file mode 100644
index 000000000000..d41777c8bd2a
--- /dev/null
+++ b/stand/forth/check-password.4th
@@ -0,0 +1,179 @@
+\ Copyright (c) 2006-2015 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-check-password.4th
+
+include /boot/screen.4th
+
+vocabulary password-processing
+only forth also password-processing definitions
+
+13 constant enter_key \ The decimal ASCII value for Enter key
+8 constant bs_key \ The decimal ASCII value for Backspace key
+21 constant ctrl_u \ The decimal ASCII value for Ctrl-U sequence
+255 constant readmax \ Maximum number of characters for the password
+
+variable read-tick \ Twiddle position (used by read)
+variable read-start \ Starting X offset (column)(used by read)
+
+create readval readmax allot \ input obtained (up to readmax characters)
+variable readlen \ input length
+
+\ This function blocks program flow (loops forever) until a key is pressed.
+\ The key that was pressed is added to the top of the stack in the form of its
+\ decimal ASCII representation. Note: the stack cannot be empty when this
+\ function starts or an underflow exception will occur. Simplest way to prevent
+\ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is
+\ called by the read function. You need not call it directly. NOTE: arrow keys
+\ show as 0 on the stack
+\
+: sgetkey ( -- )
+
+ begin \ Loop forever
+ key? if \ Was a key pressed? (see loader(8))
+ drop \ Remove stack-cruft
+ key \ Get the key that was pressed
+
+ \ Check key pressed (see loader(8)) and input limit
+ dup 0<> if ( and ) readlen @ readmax < if
+ \ Spin the twiddle and then exit this function
+ read-tick @ dup 1+ 4 mod read-tick !
+ 2 spaces
+ dup 0 = if ( 1 ) ." /" else
+ dup 1 = if ( 2 ) ." -" else
+ dup 2 = if ( 3 ) ." \" else
+ dup 3 = if ( 4 ) ." |" else
+ 1 spaces
+ then then then then drop
+ read-start @ 25 at-xy
+ exit
+ then then
+
+ \ Always allow Backspace, Enter, and Ctrl-U
+ dup bs_key = if exit then
+ dup enter_key = if exit then
+ dup ctrl_u = if exit then
+ then
+ 50 ms \ Sleep for 50 milliseconds (see loader(8))
+ again
+;
+
+: cfill ( c c-addr/u -- )
+ begin dup 0> while
+ -rot 2dup c! 1+ rot 1-
+ repeat 2drop drop
+;
+
+: read-reset ( -- )
+ 0 readlen !
+ 0 readval readmax cfill
+;
+
+: read ( c-addr/u -- ) \ Expects string prompt as stack input
+
+ 0 25 at-xy \ Move the cursor to the bottom-left
+ dup 1+ read-start ! \ Store X offset after the prompt
+ 0 readlen ! \ Initialize the read length
+ type \ Print the prompt
+
+ begin \ Loop forever
+
+ 0 sgetkey \ Block here, waiting for a key to be pressed
+
+ \ We are not going to echo the password to the screen (for
+ \ security reasons). If Enter is pressed, we process the
+ \ password, otherwise augment the key to a string.
+
+ dup enter_key = if
+ drop \ Clean up stack cruft
+ 3 spaces \ Erase the twiddle
+ 10 emit \ Echo new line
+ exit
+ else dup ctrl_u = if
+ 3 spaces read-start @ 25 at-xy \ Erase the twiddle
+ 0 readlen ! \ Reset input to NULL
+ else dup bs_key = if
+ readlen @ 1 - dup readlen ! \ Decrement input length
+ dup 0< if drop 0 dup readlen ! then \ Don't go negative
+ 0= if 3 spaces read-start @ 25 at-xy then \ Twiddle
+ else dup \ Store the character
+ \ NB: sgetkey prevents overflow by way of blocking
+ \ at readmax except for Backspace or Enter
+ readlen @ 1+ dup readlen ! 1- readval + c!
+ then then then
+
+ drop \ last key pressed
+ again \ Enter was not pressed; repeat
+;
+
+only forth definitions also password-processing
+
+: check-password ( -- )
+
+ \ 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
+ dup readmax > if drop readmax then
+ begin
+ s" Boot Password: " read ( prompt -- )
+ 2dup readval readlen @ compare 0<>
+ while
+ 3000 ms ." loader: incorrect password" 10 emit
+ repeat
+ 2drop read-reset
+ else drop then
+
+ \ Prompt for GEOM ELI (geli(8)) passphrase if enabled
+ s" geom_eli_passphrase_prompt" getenv dup -1 <> if
+ s" YES" compare-insensitive 0= if
+ s" GELI Passphrase: " read ( prompt -- )
+ readval readlen @ s" kern.geom.eli.passphrase" setenv
+ read-reset
+ then
+ else drop then
+
+ \ 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...
+
+ 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 dup readmax > if drop readmax then
+ begin
+ s" Password: " read ( prompt -- )
+ 2dup readval readlen @ compare 0= if \ Correct password?
+ 2drop read-reset exit
+ then
+ 3000 ms ." loader: incorrect password" 10 emit
+ again
+;
+
+only forth definitions
diff --git a/stand/forth/check-password.4th.8 b/stand/forth/check-password.4th.8
new file mode 100644
index 000000000000..db0aa4bc6bc4
--- /dev/null
+++ b/stand/forth/check-password.4th.8
@@ -0,0 +1,167 @@
+.\" Copyright (c) 2011-2015 Devin Teske
+.\" 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$
+.\"
+.Dd March 20, 2015
+.Dt CHECK-PASSWORD.4TH 8
+.Os
+.Sh NAME
+.Nm check-password.4th
+.Nd FreeBSD password-checking boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to do one or more of the following:
+.Pp
+.Dl o Prevent booting without password
+.Dl o Prevent modification of boot options without password
+.Dl o Provide a password to mount geli(8) encrypted root disk(s)
+.Pp
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include check-password.4th
+.Pp
+This line is present in
+.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 check-password
+Multi-purpose function that can protect the interactive boot menu,
+prevent boot without password, or prompt for geli(8) passphrase
+.Pq depending on Xr loader.conf 5 settings .
+.Pp
+First checks
+.Va bootlock_password
+and if-set, the user cannot continue until the correct password is entered.
+.Pp
+Next, checks
+.Va geom_eli_passphrase_prompt
+and if set to
+.Li YES
+.Pq case-insensitive
+prompts the user to enter their GELI password for later mounting of the root
+device(s) during boot.
+.Pp
+Last, 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 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 geom_eli_passphrase_prompt
+Selects whether loader(8) will prompt for GELI credentials, handing-off to the
+kernel for later mounting of
+.Xr geli 8
+encrypted root device(s).
+.It Va password
+Sets the password (up to 16 characters long) that is required by
+.Ic check-password
+before the user is allowed to visit the boot menu.
+.El
+.Sh FILES
+.Bl -tag -width /boot/check-password.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/check-password.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+Standard i386
+.Pa /boot/loader.rc :
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/loader.4th
+check-password
+.Ed
+.Pp
+Set a password in
+.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
+.Pp
+Add the following to
+.Xr loader.conf 5
+to generate a prompt at boot to collect GELI credentials for mounting
+.Xr geli 8
+encrypted root device(s):
+.Pp
+.Bd -literal -offset indent -compact
+geom_eli_passphrase_prompt="YES"
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr loader 8 ,
+.Xr loader.4th 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/color.4th b/stand/forth/color.4th
new file mode 100644
index 000000000000..65e6de905ac6
--- /dev/null
+++ b/stand/forth/color.4th
@@ -0,0 +1,49 @@
+\ Copyright (c) 2011-2013 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-color.4th
+
+\ 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" NO" compare-insensitive 0= if
+ 2drop
+ FALSE exit
+ then
+ 2dup s" 0" compare 0= if
+ 2drop
+ FALSE exit
+ then
+ drop
+ then
+ drop
+
+ boot_serial? if FALSE else TRUE then
+;
diff --git a/stand/forth/color.4th.8 b/stand/forth/color.4th.8
new file mode 100644
index 000000000000..9191da0f0457
--- /dev/null
+++ b/stand/forth/color.4th.8
@@ -0,0 +1,116 @@
+.\" Copyright (c) 2011-2013 Devin Teske
+.\" 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$
+.\"
+.Dd August 6, 2013
+.Dt COLOR.4TH 8
+.Os
+.Sh NAME
+.Nm color.4th
+.Nd FreeBSD color-detection boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to simplify color logic.
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include color.4th
+.Pp
+This line is present in
+.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 FALSE if the
+.Ic loader_color
+environment variable is set to
+.Dq NO
+(case-insensitive) or
+.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 NO
+(case-insensitive) or
+.Dq 0 ,
+causes
+.Ic loader_color?
+to return FALSE, indicating to many modules that color should not be used.
+.El
+.Sh FILES
+.Bl -tag -width /boot/loader.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/color.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+Standard i386
+.Pa /boot/loader.rc :
+.Pp
+Use color where applicable:
+.Pp
+.Bd -literal -offset indent -compact
+loader_color="YES"
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr loader 8 ,
+.Xr loader.4th 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/delay.4th b/stand/forth/delay.4th
new file mode 100644
index 000000000000..28cfa5c26eb9
--- /dev/null
+++ b/stand/forth/delay.4th
@@ -0,0 +1,119 @@
+\ Copyright (c) 2008-2015 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-delay.4th
+
+vocabulary delay-processing
+only forth also delay-processing definitions
+
+2 constant delay_default \ Default delay (in seconds)
+3 constant etx_key \ End-of-Text character produced by Ctrl+C
+13 constant enter_key \ Carriage-Return character produce by ENTER
+27 constant esc_key \ Escape character produced by ESC or Ctrl+[
+
+variable delay_tstart \ state variable used for delay timing
+variable delay_delay \ determined configurable delay duration
+variable delay_cancelled \ state variable for user cancellation
+variable delay_showdots \ whether continually print dots while waiting
+
+only forth definitions also delay-processing
+
+: delay_execute ( -- )
+
+ \ make sure that we have a command to execute
+ s" delay_command" getenv dup -1 = if
+ drop exit
+ then
+
+ \ read custom time-duration (if set)
+ s" loader_delay" getenv dup -1 = if
+ drop \ no custom duration (remove dup'd bunk -1)
+ delay_default \ use default setting (replacing bunk -1)
+ else
+ \ make sure custom duration is a number
+ ?number 0= if
+ delay_default \ use default if otherwise
+ then
+ then
+
+ \ initialize state variables
+ delay_delay ! \ stored value is on the stack from above
+ seconds delay_tstart ! \ store the time we started
+ 0 delay_cancelled ! \ boolean flag indicating user-cancelled event
+
+ false delay_showdots ! \ reset to zero and read from environment
+ s" delay_showdots" getenv dup -1 <> if
+ 2drop \ don't need the value, just existence
+ true delay_showdots !
+ else
+ drop
+ then
+
+ \ Loop until we have exceeded the desired time duration
+ begin
+ 25 ms \ sleep for 25 milliseconds (40 iterations/sec)
+
+ \ throw some dots up on the screen if desired
+ delay_showdots @ if
+ ." ." \ dots visually aid in the perception of time
+ then
+
+ \ was a key depressed?
+ key? if
+ key \ obtain ASCII value for keystroke
+ dup enter_key = if
+ -1 delay_delay ! \ break loop
+ then
+ dup etx_key = swap esc_key = OR if
+ -1 delay_delay ! \ break loop
+ -1 delay_cancelled ! \ set cancelled flag
+ then
+ then
+
+ \ if the time duration is set to zero, loop forever
+ \ waiting for either ENTER or Ctrl-C/Escape to be pressed
+ delay_delay @ 0> if
+ \ calculate elapsed time
+ seconds delay_tstart @ - delay_delay @ >
+ else
+ -1 \ break loop
+ then
+ until
+
+ \ if we were throwing up dots, throw up a line-break
+ delay_showdots @ if
+ cr
+ then
+
+ \ did the user press either Ctrl-C or Escape?
+ delay_cancelled @ if
+ 2drop \ we don't need the command string anymore
+ else
+ evaluate \ evaluate/execute the command string
+ then
+;
+
+only forth definitions
diff --git a/stand/forth/delay.4th.8 b/stand/forth/delay.4th.8
new file mode 100644
index 000000000000..af31fd04bad6
--- /dev/null
+++ b/stand/forth/delay.4th.8
@@ -0,0 +1,126 @@
+.\" Copyright (c) 2011 Devin Teske
+.\" 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$
+.\"
+.Dd May 18, 2011
+.Dt DELAY.4TH 8
+.Os
+.Sh NAME
+.Nm delay.4th
+.Nd FreeBSD debugging boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to add debugging capabilities to
+.Xr loader 8 .
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include delay.4th
+.Pp
+This line is present in
+.Pa /boot/beastie.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 delay_execute
+Executes the [string] procedure stored in the
+.Ic delay_command
+environment variable after
+.Ic loader_delay
+seconds.
+.Pp
+If the optional
+.Ic delay_showdots
+environment variable is set, a continuous series of dots is printed.
+.Pp
+During the duration, the user can either press Ctrl-C (or Esc) to abort or
+ENTER to proceed immediately.
+.El
+.Pp
+The environment variables that effect its behavior are:
+.Bl -tag -width bootfile -offset indent
+.It Va delay_command
+The command to be executed by
+.Ic delay_execute .
+.It Va loader_delay
+The duration (in seconds) to delay before executing
+.Ic delay_command .
+.It Va delay_showdots
+If set, will cause
+.Ic delay_execute
+to print a continuous series of dots during the delay duration.
+.El
+.Sh FILES
+.Bl -tag -width /boot/loader.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/delay.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+Introducing a 5-second delay before including another file from
+.Pa /boot/loader.rc :
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/delay.4th
+set delay_command="include /boot/other.4th"
+set delay_showdots
+set loader_delay=5
+delay_execute
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr beastie.4th 8 ,
+.Xr loader 8 ,
+.Xr loader.4th 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/efi.4th b/stand/forth/efi.4th
new file mode 100644
index 000000000000..7c1bdf30b8e1
--- /dev/null
+++ b/stand/forth/efi.4th
@@ -0,0 +1,30 @@
+\ Copyright (c) 2016 Netflix, Inc
+\ 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$
+
+only forth definitions
+
+\ Place holder for more functions
+.( EFI boot environment) cr
diff --git a/stand/forth/frames.4th b/stand/forth/frames.4th
new file mode 100644
index 000000000000..b237afe7ac43
--- /dev/null
+++ b/stand/forth/frames.4th
@@ -0,0 +1,142 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2012-2015 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-frames.4th
+
+vocabulary frame-drawing
+only forth also frame-drawing definitions
+
+\ XXX Filled boxes are left as an exercise for the reader... ;-/
+
+variable h_el
+variable v_el
+variable lt_el
+variable lb_el
+variable rt_el
+variable rb_el
+variable fill
+
+\ ASCII frames (used when serial console is detected)
+ 45 constant ascii_dash
+ 61 constant ascii_equal
+124 constant ascii_pipe
+ 43 constant ascii_plus
+
+\ Single frames
+196 constant sh_el
+179 constant sv_el
+218 constant slt_el
+192 constant slb_el
+191 constant srt_el
+217 constant srb_el
+\ Double frames
+205 constant dh_el
+186 constant dv_el
+201 constant dlt_el
+200 constant dlb_el
+187 constant drt_el
+188 constant drb_el
+\ Fillings
+0 constant fill_none
+32 constant fill_blank
+176 constant fill_dark
+177 constant fill_med
+178 constant fill_bright
+
+only forth definitions also frame-drawing
+
+: hline ( len x y -- ) \ Draw horizontal single line
+ at-xy \ move cursor
+ 0 do
+ h_el @ emit
+ 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 !
+ slb_el lb_el !
+ srt_el rt_el !
+ srb_el rb_el !
+;
+
+: f_double ( -- ) \ set frames to double
+ boot_serial? if
+ f_ascii
+ ascii_equal h_el !
+ exit
+ then
+ dh_el h_el !
+ dv_el v_el !
+ dlt_el lt_el !
+ dlb_el lb_el !
+ drt_el rt_el !
+ drb_el rb_el !
+;
+
+: vline ( len x y -- ) \ Draw vertical single line
+ 2dup 4 pick
+ 0 do
+ at-xy
+ v_el @ emit
+ 1+
+ 2dup
+ loop
+ 2drop 2drop drop
+;
+
+: box ( w h x y -- ) \ Draw a box
+ 2dup 1+ 4 pick 1- -rot
+ vline \ Draw left vert line
+ 2dup 1+ swap 5 pick + swap 4 pick 1- -rot
+ vline \ Draw right vert line
+ 2dup swap 1+ swap 5 pick 1- -rot
+ hline \ Draw top horiz line
+ 2dup swap 1+ swap 4 pick + 5 pick 1- -rot
+ hline \ Draw bottom horiz line
+ 2dup at-xy lt_el @ emit \ Draw left-top corner
+ 2dup 4 pick + at-xy lb_el @ emit \ Draw left bottom corner
+ 2dup swap 5 pick + swap at-xy rt_el @ emit \ Draw right top corner
+ 2 pick + swap 3 pick + swap at-xy rb_el @ emit
+ 2drop
+;
+
+f_single
+fill_none fill !
+
+only forth definitions
diff --git a/stand/forth/loader.4th b/stand/forth/loader.4th
new file mode 100644
index 000000000000..9486237b8a93
--- /dev/null
+++ b/stand/forth/loader.4th
@@ -0,0 +1,266 @@
+\ Copyright (c) 1999 Daniel C. Sobral <dcs@FreeBSD.org>
+\ Copyright (c) 2011-2015 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$
+
+only forth definitions
+
+s" arch-i386" environment? [if] [if]
+ s" loader_version" environment? [if]
+ 11 < [if]
+ .( Loader version 1.1+ required) cr
+ abort
+ [then]
+ [else]
+ .( Could not get loader version!) cr
+ abort
+ [then]
+[then] [then]
+
+256 dictthreshold ! \ 256 cells minimum free space
+2048 dictincrease ! \ 2048 additional cells each time
+
+include /boot/support.4th
+include /boot/color.4th
+include /boot/delay.4th
+include /boot/check-password.4th
+s" efi-version" getenv? [if]
+ include /boot/efi.4th
+[then]
+
+only forth definitions
+
+: bootmsg ( -- )
+ loader_color? dup ( -- bool bool )
+ if 7 fg 4 bg then
+ ." Booting..."
+ if me then
+ cr
+;
+
+: try-menu-unset
+ \ menu-unset may not be present
+ s" beastie_disable" getenv
+ dup -1 <> if
+ s" YES" compare-insensitive 0= if
+ exit
+ then
+ else
+ drop
+ then
+ s" menu-unset"
+ sfind if
+ execute
+ else
+ drop
+ then
+ s" menusets-unset"
+ sfind if
+ execute
+ else
+ drop
+ then
+;
+
+only forth also support-functions also builtins definitions
+
+: boot
+ 0= if ( interpreted ) get_arguments then
+
+ \ Unload only if a path was passed
+ dup if
+ >r over r> swap
+ c@ [char] - <> if
+ 0 1 unload drop
+ else
+ s" kernelname" getenv? if ( a kernel has been loaded )
+ try-menu-unset
+ bootmsg 1 boot exit
+ then
+ load_kernel_and_modules
+ ?dup if exit then
+ try-menu-unset
+ bootmsg 0 1 boot exit
+ then
+ else
+ s" kernelname" getenv? if ( a kernel has been loaded )
+ try-menu-unset
+ bootmsg 1 boot exit
+ then
+ load_kernel_and_modules
+ ?dup if exit then
+ try-menu-unset
+ bootmsg 0 1 boot exit
+ then
+ load_kernel_and_modules
+ ?dup 0= if bootmsg 0 1 boot then
+;
+
+\ ***** boot-conf
+\
+\ Prepares to boot as specified by loaded configuration files.
+
+: boot-conf
+ 0= if ( interpreted ) get_arguments then
+ 0 1 unload drop
+ load_kernel_and_modules
+ ?dup 0= if 0 1 autoboot then
+;
+
+also forth definitions previous
+
+builtin: boot
+builtin: boot-conf
+
+only forth definitions also support-functions
+
+\ ***** start
+\
+\ Initializes support.4th global variables, sets loader_conf_files,
+\ processes conf files, and, if any one such file was successfully
+\ read to the end, loads kernel and modules.
+
+: start ( -- ) ( throws: abort & user-defined )
+ s" /boot/defaults/loader.conf" initialize
+ include_conf_files
+ include_nextboot_file
+ \ If the user defined a post-initialize hook, call it now
+ s" post-initialize" sfind if execute else drop then
+ \ Will *NOT* try to load kernel and modules if no configuration file
+ \ was successfully loaded!
+ any_conf_read? if
+ s" loader_delay" getenv -1 = if
+ load_xen_throw
+ load_kernel
+ load_modules
+ else
+ drop
+ ." Loading Kernel and Modules (Ctrl-C to Abort)" cr
+ s" also support-functions" evaluate
+ s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate
+ s" set delay_showdots" evaluate
+ delay_execute
+ then
+ then
+;
+
+\ ***** initialize
+\
+\ Overrides support.4th initialization word with one that does
+\ everything start one does, short of loading the kernel and
+\ modules. Returns a flag.
+
+: initialize ( -- flag )
+ s" /boot/defaults/loader.conf" initialize
+ include_conf_files
+ include_nextboot_file
+ \ If the user defined a post-initialize hook, call it now
+ s" post-initialize" sfind if execute else drop then
+ any_conf_read?
+;
+
+\ ***** read-conf
+\
+\ Read a configuration file, whose name was specified on the command
+\ line, if interpreted, or given on the stack, if compiled in.
+
+: (read-conf) ( addr len -- )
+ conf_files string=
+ include_conf_files \ Will recurse on new loader_conf_files definitions
+;
+
+: read-conf ( <filename> | addr len -- ) ( throws: abort & user-defined )
+ state @ if
+ \ Compiling
+ postpone (read-conf)
+ else
+ \ Interpreting
+ bl parse (read-conf)
+ then
+; immediate
+
+\ show, enable, disable, toggle module loading. They all take module from
+\ the next word
+
+: set-module-flag ( module_addr val -- ) \ set and print flag
+ over module.flag !
+ dup module.name strtype
+ module.flag @ if ." will be loaded" else ." will not be loaded" then cr
+;
+
+: enable-module find-module ?dup if true set-module-flag then ;
+
+: disable-module find-module ?dup if false set-module-flag then ;
+
+: toggle-module find-module ?dup if dup module.flag @ 0= set-module-flag then ;
+
+\ ***** show-module
+\
+\ Show loading information about a module.
+
+: show-module ( <module> -- ) find-module ?dup if show-one-module then ;
+
+\ Words to be used inside configuration files
+
+: retry false ; \ For use in load error commands
+: ignore true ; \ For use in load error commands
+
+\ Return to strict forth vocabulary
+
+: #type
+ over - >r
+ type
+ r> spaces
+;
+
+: .? 2 spaces 2swap 15 #type 2 spaces type cr ;
+
+\ Execute the ? command to print all the commands defined in
+\ C, then list the ones we support here. Please note that this
+\ doesn't use pager_* routines that the C implementation of ?
+\ does, so these will always appear, even if you stop early
+\ there. And they may cause the commands to scroll off the
+\ screen if the number of commands modulus LINES is close
+\ to LINEs....
+: ?
+ ['] ? execute
+ s" boot-conf" s" load kernel and modules, then autoboot" .?
+ s" read-conf" s" read a configuration file" .?
+ s" enable-module" s" enable loading of a module" .?
+ s" disable-module" s" disable loading of a module" .?
+ s" toggle-module" s" toggle loading of a module" .?
+ s" show-module" s" show module load data" .?
+ s" try-include" s" try to load/interpret files" .?
+;
+
+: try-include ( -- ) \ see loader.4th(8)
+ ['] include ( -- xt ) \ get the execution token of `include'
+ catch ( xt -- exception# | 0 ) if \ failed
+ LF parse ( c -- s-addr/u ) 2drop \ advance >in to EOL (drop data)
+ \ ... prevents words unused by `include' from being interpreted
+ then
+; immediate \ interpret immediately for access to `source' (aka tib)
+
+only forth definitions
diff --git a/stand/forth/loader.4th.8 b/stand/forth/loader.4th.8
new file mode 100644
index 000000000000..b689077058da
--- /dev/null
+++ b/stand/forth/loader.4th.8
@@ -0,0 +1,233 @@
+.\" Copyright (c) 1999 Daniel C. Sobral
+.\" 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$
+.\"
+.Dd November 13, 2013
+.Dt LOADER.4TH 8
+.Os
+.Sh NAME
+.Nm loader.4th
+.Nd loader.conf processing tools
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to manipulate
+.Xr loader.conf 5
+files.
+The default
+.Pa /boot/loader.rc
+includes
+.Nm
+and uses one of its commands to automatically read and process
+the standard
+.Xr loader.conf 5
+files.
+Other commands exists to help the user specify alternate
+configurations.
+.Pp
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include loader.4th
+.Pp
+This line is present in the default
+.Pa /boot/loader.rc
+file, so it is not needed (and should not be re-issued) in a normal setup.
+.Pp
+The commands provided by it are:
+.Bl -tag -width disable-module_module -compact -offset indent
+.It Ic boot
+.It Ic boot Ar kernelname Op Cm ...
+.It Ic boot Ar directory Op Cm ...
+.It Ic boot Fl flag Cm ...
+Boot as specified by the
+.Xr loader.conf 5
+files read.
+.Pp
+Depending on the arguments passed, it can override boot flags and
+either the kernel name or the search path for kernel and modules.
+.Pp
+.It Ic boot-conf
+.It Ic boot-conf Ar kernelname Op Cm ...
+.It Ic boot-conf Ar directory Op Cm ...
+.It Ic boot-conf Fl flag Cm ...
+Works like
+.Ic boot
+described above, but instead of booting immediately, uses
+.Ic autoboot ,
+so it can be stopped.
+.Pp
+.It Ic start
+Reads
+.Pa /boot/defaults/loader.conf ,
+all other
+.Xr loader.conf 5
+files specified in it, then loads the desired kernel and modules
+.Pq if not already loaded .
+After which you can use the
+.Ic boot
+or
+.Ic autoboot
+commmands or simply exit (provided
+.Va autoboot_delay
+is not set to NO) to boot the system.
+.Ic start
+is the command used in the default
+.Pa /boot/loader.rc
+file
+.Pq see Xr loader 8 .
+.Pp
+.It Ic initialize
+Initialize the support library so commands can be used without executing
+.Ic start
+first.
+Like
+.Ic start ,
+it reads
+.Pa /boot/defaults/loader.conf
+and all other
+.Xr loader.conf 5
+files specified in it
+.Pq but does not load kernel or modules .
+Returns a flag on the stack to indicate
+if any configuration files were successfully loaded.
+.Pp
+.It Ic read-conf Ar filename
+Reads and processes a
+.Xr loader.conf 5
+file.
+Does not proceed to boot.
+.Pp
+.It Ic enable-module Ar module
+Enables the loading of
+.Ar module .
+.Pp
+.It Ic disable-module Ar module
+Disables the loading of
+.Ar module .
+.Pp
+.It Ic toggle-module Ar module
+Toggles the loading of
+.Ar module
+on and off.
+.Pp
+.It Ic show-module Ar module
+Shows the information gathered in the
+.Xr loader.conf 5
+files about the module
+.Ar module .
+.Pp
+.It Ic retry
+Used inside
+.Xr loader.conf 5
+files to specify the action after a module loading fails.
+.Pp
+.It Ic ignore
+Used inside
+.Xr loader.conf 5
+files to specify the action after a module loading fails.
+.It Ic try-include Ar file Op Ar
+Process script files if they exist.
+Each file, in turn, is completely read into memory,
+and then each of its lines is passed to the command line interpreter.
+If any error is returned by the interpreter, the try-include
+command aborts immediately, without reading any other files, and
+silently returns without error.
+.El
+.Sh FILES
+.Bl -tag -width /boot/loader.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/loader.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.It Pa /boot/defaults/loader.conf
+File loaded by the
+.Ic start
+command.
+.El
+.Sh EXAMPLES
+Standard
+.Pa /boot/loader.rc :
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/loader.4th
+start
+.Ed
+.Pp
+Load a different kernel with the standard configuration:
+.Pp
+.Bd -literal -offset indent -compact
+set kernel="kernel.old"
+unload
+boot-conf
+.Ed
+.Pp
+Read an additional configuration file and then proceed to boot:
+.Pp
+.Bd -literal -offset indent -compact
+unload
+read-conf /boot/special.conf
+boot-conf
+.Ed
+.Pp
+Disable the loading of the splash screen module and bitmap and then
+proceed to boot:
+.Pp
+.Bd -literal -offset indent -compact
+unload
+disable-module splash_bmp
+disable-module bitmap
+boot-conf
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr loader 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 3.2 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An Daniel C. Sobral Aq dcs@FreeBSD.org .
+.Sh BUGS
+A British espionage series.
diff --git a/stand/forth/loader.conf b/stand/forth/loader.conf
new file mode 100644
index 000000000000..8fe533fd2deb
--- /dev/null
+++ b/stand/forth/loader.conf
@@ -0,0 +1,568 @@
+# This is loader.conf - a file full of useful variables that you can
+# set to change the default load behavior of your system. You should
+# not edit this file! Put any overrides into one of the
+# loader_conf_files instead and you will be able to update these
+# defaults later without spamming your local configuration information.
+#
+# All arguments must be in double quotes.
+#
+# $FreeBSD$
+
+##############################################################
+### Basic configuration options ############################
+##############################################################
+
+exec="echo Loading /boot/defaults/loader.conf"
+
+kernel="kernel" # /boot sub-directory containing kernel and modules
+bootfile="kernel" # Kernel name (possibly absolute path)
+kernel_options="" # Flags to be passed to the kernel
+
+loader_conf_files="/boot/device.hints /boot/loader.conf /boot/loader.conf.local"
+nextboot_conf="/boot/nextboot.conf"
+nextboot_enable="NO"
+
+verbose_loading="NO" # Set to YES for verbose loader output
+
+
+##############################################################
+### Splash screen configuration ############################
+##############################################################
+
+splash_bmp_load="NO" # Set this to YES for bmp splash screen!
+splash_pcx_load="NO" # Set this to YES for pcx splash screen!
+splash_txt_load="NO" # Set this to YES for TheDraw splash screen!
+vesa_load="NO" # Set this to YES to load the vesa module
+bitmap_load="NO" # Set this to YES if you want splash screen!
+bitmap_name="splash.bmp" # Set this to the name of the file
+bitmap_type="splash_image_data" # and place it on the module_path
+
+
+##############################################################
+### Random number generator configuration ##################
+##############################################################
+
+# See rc.conf(5). The entropy_boot_file config variable must agree with the
+# settings below.
+
+entropy_cache_load="YES" # Set this to NO to disable loading
+ # entropy at boot time
+entropy_cache_name="/boot/entropy" # Set this to the name of the file
+entropy_cache_type="boot_entropy_cache" # Required for the kernel to find
+ # the boot-time entropy cache. This
+ # must not change value even if the
+ # _name above does change!
+
+
+##############################################################
+### RAM Blacklist configuration ############################
+##############################################################
+
+ram_blacklist_load="NO" # Set this to YES to load a file
+ # containing a list of addresses to
+ # exclude from the running system.
+ram_blacklist_name="/boot/blacklist.txt" # Set this to the name of the file
+ram_blacklist_type="ram_blacklist" # Required for the kernel to find
+ # the blacklist module
+
+
+##############################################################
+### Initial memory disk settings ###########################
+##############################################################
+
+#mdroot_load="YES" # The "mdroot" prefix is arbitrary.
+#mdroot_type="md_image" # Create md(4) disk at boot.
+#mdroot_name="/boot/root.img" # Path to a file containing the image.
+#rootdev="ufs:/dev/md0" # Set the root filesystem to md(4) device.
+
+
+##############################################################
+### Loader settings ########################################
+##############################################################
+
+#loader_delay="3" # Delay in seconds before loading anything.
+ # Default is unset and disabled (no delay).
+#autoboot_delay="10" # Delay in seconds before autobooting,
+ # set to -1 if you don't want user to be
+ # allowed to interrupt autoboot process and
+ # escape to the loader prompt, set to
+ # "NO" to disable autobooting
+#password="" # Prevent changes to boot options
+#bootlock_password="" # Prevent booting (see check-password.4th(8))
+#geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root
+bootenv_autolist="YES" # Auto populate the list of ZFS Boot Environments
+#beastie_disable="NO" # Turn the beastie boot menu on and off
+#kernels="kernel kernel.old" # Kernels to display in the boot menu
+#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
+module_path="/boot/modules;/boot/dtb" # Set the module search path
+#prompt="\\${interpret}" # Set the command prompt
+#root_disk_unit="0" # Force the root disk unit number
+#rootdev="disk1s1a" # Set the root filesystem
+#dumpdev="disk1s1b" # Set a dump device early in the boot process
+#tftp.blksize="1428" # Set the RFC 2348 TFTP block size.
+ # If the TFTP server does not support RFC 2348,
+ # the block size is set to 512. If the value
+ # is out of range ( < 8 || > 9008 ) an error is
+ # returned.
+#twiddle_divisor="1" # >1 means slow down the progress indicator.
+
+
+##############################################################
+### Kernel settings ########################################
+##############################################################
+
+# The following boot_ variables are enabled by setting them to any value.
+# Their presence in the kernel environment (see kenv(1)) has the same
+# effect as setting the given boot flag (see boot(8)).
+
+#boot_askname="" # -a: Prompt the user for the name of the root device
+#boot_cdrom="" # -C: Attempt to mount root file system from CD-ROM
+#boot_ddb="" # -d: Instructs the kernel to start in the DDB debugger
+#boot_dfltroot="" # -r: Use the statically configured root file system
+#boot_gdb="" # -g: Selects gdb-remote mode for the kernel debugger
+#boot_multicons="" # -D: Use multiple consoles
+#boot_mute="" # -m: Mute the console
+#boot_pause="" # -p: Pause after each line during device probing
+#boot_serial="" # -h: Use serial console
+#boot_single="" # -s: Start system in single-user mode
+#boot_verbose="" # -v: Causes extra debugging information to be printed
+#init_path="/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init"
+ # Sets the list of init candidates
+#init_shell="/bin/sh" # The shell binary used by init(8).
+#init_script="" # Initial script to run by init(8) before chrooting.
+#init_chroot="" # Directory for init(8) to chroot into.
+
+
+##############################################################
+### Kernel tunables ########################################
+##############################################################
+
+#hw.physmem="1G" # Limit physical memory. See loader(8)
+#kern.dfldsiz="" # Set the initial data size limit
+#kern.dflssiz="" # Set the initial stack size limit
+#kern.hz="100" # Set the kernel interval timer rate
+#kern.maxbcache="" # Set the max buffer cache KVA storage
+#kern.maxdsiz="" # Set the max data size
+#kern.maxfiles="" # Set the sys. wide open files limit
+#kern.maxproc="" # Set the maximum # of processes
+#kern.maxssiz="" # Set the max stack size
+#kern.maxswzone="" # Set the max swmeta KVA storage
+#kern.maxtsiz="" # Set the max text size
+#kern.maxusers="32" # Set size of various static tables
+#kern.msgbufsize="65536" # Set size of kernel message buffer
+#kern.nbuf="" # Set the number of buffer headers
+#kern.ncallout="" # Set the maximum # of timer events
+#kern.ngroups="1023" # Set the maximum # of supplemental groups
+#kern.sgrowsiz="" # Set the amount to grow stack
+#kern.cam.boot_delay="10000" # Delay (in ms) of root mount for CAM bus
+ # registration, useful for USB sticks as root
+#kern.cam.scsi_delay="2000" # Delay (in ms) before probing SCSI
+#kern.ipc.maxsockets="" # Set the maximum number of sockets available
+#kern.ipc.nmbclusters="" # Set the number of mbuf clusters
+#kern.ipc.nsfbufs="" # Set the number of sendfile(2) bufs
+#net.inet.tcp.tcbhashsize="" # Set the value of TCBHASHSIZE
+#vfs.root.mountfrom="" # Specify root partition in a way the
+ # kernel understands
+#vm.kmem_size="" # Sets the size of kernel memory (bytes)
+#debug.kdb.break_to_debugger="0" # Allow console to break into debugger.
+#debug.ktr.cpumask="0xf" # Bitmask of CPUs to enable KTR on
+#debug.ktr.mask="0x1200" # Bitmask of KTR events to enable
+#debug.ktr.verbose="1" # Enable console dump of KTR events
+#net.graph.maxalloc="128" # Maximum number of queue items to allocate
+
+
+##############################################################
+### ATA modules ############################################
+##############################################################
+
+ataacard_load="NO" # ACARD
+ataacerlabs_load="NO" # Acer Labs Inc. (ALI)
+ataamd_load="NO" # American Micro Devices (AMD)
+ataati_load="NO" # ATI
+atacenatek_load="NO" # Cenatek
+atacypress_load="NO" # Cypress
+atacyrix_load="NO" # Cyrix
+atahighpoint_load="NO" # HighPoint
+ataintel_load="NO" # Intel
+ataite_load="NO" # Integrated Technology Inc. (ITE)
+atajmicron_load="NO" # JMicron
+atamarvell_load="NO" # Marvell
+atamicron_load="NO" # Micron
+atanational_load="NO" # National
+atanetcell_load="NO" # NetCell
+atanvidia_load="NO" # nVidia
+atapromise_load="NO" # Promise
+ataserverworks_load="NO" # ServerWorks
+atasiliconimage_load="NO" # Silicon Image Inc. (SiI) (formerly CMD)
+atasis_load="NO" # Silicon Integrated Systems Corp.(SiS)
+atavia_load="NO" # VIA Technologies Inc.
+
+
+##############################################################
+### Filesystem and related modules #########################
+##############################################################
+
+# Filesystems
+
+cd9660_load="NO" # ISO 9660 filesystem
+fdescfs_load="NO" # Filedescriptors filesystem
+linprocfs_load="NO" # Linux compatibility process filesystem
+linsysfs_load="NO" # Linux compatibility system filesystem
+msdosfs_load="NO" # FAT-12/16/32
+nfsclient_load="NO" # NFS client
+nfsserver_load="NO" # NFS server
+nullfs_load="NO" # Null filesystem
+procfs_load="NO" # Process filesystem
+unionfs_load="NO" # Union filesystem
+zfs_load="NO" # ZFS
+
+# Related stuff
+
+geom_bde_load="NO" # Disk encryption driver (see gbde(4,8))
+geom_ccd_load="NO" # Concatenated disk driver (see ccd(4),
+ # ccdconfig(8))
+geom_concat_load="NO" # Concatenated disk driver (see gconcat(8))
+geom_eli_load="NO" # Disk encryption driver (see geli(8))
+geom_gate_load="NO" # Userland disk driver (see geom_gate(4),
+ # ggatec(8), ggated(8), ggatel(8))
+geom_journal_load="NO" # Journaled filesystem driver (see gjournal(8))
+geom_label_load="NO" # File system labels (see glabel(8))
+geom_md_load="NO" # Memory disk driver (vnode/swap/malloc) (see
+ # md(4), mdconfig(8))
+geom_mirror_load="NO" # RAID1 disk driver (see gmirror(8))
+geom_mountver_load="NO" # Mount verification disk driver
+geom_nop_load="NO" # Transparent disk driver (see gnop(8))
+geom_raid3_load="NO" # RAID3 disk driver (see graid3(8))
+geom_shsec_load="NO" # Shared secret disk driver (see gshsec(8))
+geom_stripe_load="NO" # RAID0 disk driver (see gstripe(8))
+geom_uzip_load="NO" # Compressed disk images driver (see mkuzip(8))
+geom_vinum_load="NO" # Concatenated/mirror/raid driver (see vinum(4))
+
+
+##############################################################
+### FireWire modules #######################################
+##############################################################
+
+firewire_load="NO" # IEEE1394 High-performance Serial Bus
+fwe_load="NO" # Ethernet emulation driver for FireWire
+fwip_load="NO" # IP over FireWire driver
+fwohci_load="NO" # OHCI FireWire chipset device driver
+sbp_load="NO" # SBP-2 Mass Storage Devices driver
+sbp_targ_load="NO" # SBP-2 Target mode
+
+
+##############################################################
+### Screen saver modules ###################################
+##############################################################
+
+# This is best done in rc.conf
+
+screensave_load="NO" # Set to YES to load a screensaver module
+screensave_name="green_saver" # Set to the name of the screensaver module
+
+
+##############################################################
+### Emulation modules ######################################
+##############################################################
+
+cloudabi_load="NO" # Platform independent CloudABI support
+cloudabi64_load="NO" # 64-bit CloudABI executables support
+ibcs2_load="NO" # IBCS2 (SCO) emulation
+ibcs2_coff_load="NO"
+linux_load="NO" # Linux emulation
+
+
+##############################################################
+### Networking modules #####################################
+##############################################################
+
+if_disc_load="NO" # Discard device
+if_ef_load="NO" # pseudo-device providing support for multiple
+ # ethernet frame types
+if_epair_load="NO" # Virtual b-t-b Ethernet-like interface pair
+if_gif_load="NO" # generic tunnel interface
+if_gre_load="NO" # encapsulating network device
+if_stf_load="NO" # 6to4 tunnel interface
+if_tap_load="NO" # Ethernet tunnel software network interface
+if_tun_load="NO" # Tunnel driver (user process ppp)
+if_vlan_load="NO" # IEEE 802.1Q VLAN network interface
+ipfw_load="NO" # Firewall
+pf_load="NO" # packet filter
+
+
+##############################################################
+### Networking drivers #####################################
+##############################################################
+
+bridgestp_load="NO" # if_bridge(4) support
+miibus_load="NO" # miibus support, needed for some drivers
+carp_load="NO" # carp(4) protocol
+if_ae_load="NO" # Attansic/Atheros L2 FastEthernet
+if_age_load="NO" # Attansic/Atheros L1 Gigabit Ethernet
+if_alc_load="NO" # Atheros AR8131/AR8132 Ethernet
+if_ale_load="NO" # Atheros AR8121/AR8113/AR8114 Ethernet
+if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs
+if_ath_load="NO" # Atheros IEEE 802.11 wireless NICs
+if_aue_load="NO" # ADMtek AN986 Pegasus USB Ethernet
+if_axe_load="NO" # ASIX Electronics AX88172 USB Ethernet
+if_bce_load="NO" # Broadcom NetXtreme II Gigabit Ethernet
+if_bfe_load="NO" # Broadcom BCM4401
+if_bge_load="NO" # Broadcom BCM570x PCI Gigabit Ethernet
+if_bnxt_load="NO" # Broadcom NetXtreme-C/NetXtreme-E
+if_bridge_load="NO" # if_bridge(4) devices
+if_bwi_load="NO" # Broadcom BCM53xx IEEE 802.11b/g wireness NICs
+if_bwn_load="NO" # Broadcom BCM43xx IEEE 802.11 wireless NICs
+if_bxe_load="NO" # Broadcom NetXtreme II 10Gb Ethernet
+if_cas_load="NO" # Sun Cassini/Cassini+ and NS DP83065 Saturn
+if_cm_load="NO" # SMC (90c26, 90c56, 90c66)
+if_cs_load="NO" # Crystal Semiconductor CS8920
+if_cue_load="NO" # CATC USB-EL1210A USB Ethernet
+if_cxgb_load="NO" # Chelsio T3 10 Gigabit Ethernet
+if_cxgbe_load="NO" # Chelsio T4/T5/T6 1/10/25/40/100 Gigabit Ethernet
+if_dc_load="NO" # DEC/Intel 21143 and various workalikes
+if_de_load="NO" # DEC DC21x4x Ethernet
+if_ed_load="NO" # National Semiconductor DS8390/WD83C690
+ # Ethernet
+if_em_load="NO" # Intel(R) PRO/1000 Gigabit Ethernet
+if_ep_load="NO" # 3Com Etherlink III (3c5x9)
+if_et_load="NO" # Agere ET1310 10/100/Gigabit Ethernet
+if_ex_load="NO" # Intel EtherExpress Pro/10 Ethernet
+if_fe_load="NO" # Fujitsu MB86960A/MB86965A based Ethernet
+ # adapters
+if_fxp_load="NO" # Intel EtherExpress PRO/100B (82557, 82558)
+if_gem_load="NO" # Sun GEM/Sun ERI/Apple GMAC
+if_hme_load="NO" # Sun Microelectronics STP2002-STQ Ethernet
+if_ie_load="NO" # Intel 82586
+if_ipw_load="NO" # Intel PRO/Wireless 2100 wireless
+if_iwi_load="NO" # Intel PRO/Wireless 2200BG/2225BG/2915ABG
+ # wireless
+if_iwn_load="NO" # Intel Wireless WiFi Link 802.11n wireless
+if_ixgb_load="NO" # Intel PRO/10Gb Ethernet
+if_ixgbe_load="NO" # Intel PRO/10Gb Ethernet PCI Express
+if_ixl_load="NO" # Intel XL710 Ethernet 40Gb Base driver
+if_ixlv_load="NO" # Intel XL710 Ethernet 40Gb VF driver
+if_jme_load="NO" # JMicron JMC250 Gigabit/JMC260 Fast Ethernet
+if_lagg_load="NO" # lagg(4) devices
+if_le_load="NO" # AMD Am7900 LANCE and Am79C9xx PCnet
+if_lge_load="NO" # Level 1 LXT1001 NetCellerator PCI Gigabit
+ # Ethernet
+if_malo_load="NO" # Marvell Libertas 88W8335 802.11 wireless
+ # adapter
+if_msk_load="NO" # Marvell/SysKonnect Yukon II Gigabit Ethernet
+if_mxge_load="NO" # Myricom Myri10GE 10Gb Ethernet
+if_my_load="NO" # Myson PCI Fast Ethernet
+if_nfe_load="NO" # NVIDIA nForce MCP Networking Adapter
+if_nge_load="NO" # National Semiconductor PCI Gigabit Ethernet
+if_nxge_load="NO" # Neterion Xframe 10Gb Ethernet
+if_pcn_load="NO" # AMD PCnet PCI
+if_ral_load="NO" # Ralink Technology wireless
+if_re_load="NO" # RealTek 8139C+/8169/8169S/8110S
+if_rl_load="NO" # RealTek 8129/8139
+if_rue_load="NO" # RealTek RTL8150 USB to Fast Ethernet
+if_rum_load="NO" # Ralink Technology USB 802.11a/b/g wireless
+if_run_load="NO" # Ralink Technology USB 802.11a/g/n wireless
+if_sbni_load="NO" # Granch SBNI12 leased line adapters
+if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire")
+if_sge_load="NO" # Silicon Integrated Systems SiS 190/191
+if_sis_load="NO" # Silicon Integrated Systems SiS 900/7016
+if_sk_load="NO" # SysKonnect SK-984x series PCI Gigabit Ethernet
+if_sn_load="NO" # SMC 91Cxx
+if_ste_load="NO" # Sundance Technologies ST201 Fast Ethernet
+if_stge_load="NO" # Sundance/Tamarack TC9021 Gigabit Ethernet
+if_ti_load="NO" # Alteon Networks Tigon 1 and Tigon 2
+if_tl_load="NO" # Texas Instruments TNETE100 ("ThunderLAN")
+if_tx_load="NO" # SMC 83c17x Fast Ethernet
+if_txp_load="NO" # 3Com 3XP Typhoon/Sidewinder (3CR990)
+if_vge_load="NO" # VIA VT6122 PCI Gigabit Ethernet
+if_vte_load="NO" # DM&P Vortex86 RDC R6040 Fast Ethernet
+if_uath_load="NO" # Atheros USB wireless for AR5005UG & AR5005UX
+if_udav_load="NO" # Davicom DM9601 USB Ethernet
+if_upgt_load="NO" # Conexant/Intersil PrismGT USB wireless
+if_ural_load="NO" # Ralink Technology USB wireless
+if_urtw_load="NO" # Realtek 8187L USB wireless
+if_vr_load="NO" # VIA Rhine I and Rhine II
+if_vx_load="NO" # 3Com 3C590 family
+if_wb_load="NO" # Winbond W89C840F
+if_wi_load="NO" # WaveLAN/IEEE 802.11 wireless NICs
+if_wpi_load="NO" # Intel 3945ABG Wireless LAN IEEE 802.11
+if_xe_load="NO" # Xircom CreditCard PCMCIA
+if_xl_load="NO" # 3Com Etherlink XL (3c900, 3c905, 3c905B)
+sfxge_load="NO" # Solarflare 10Gb Ethernet adapter driver
+
+
+##############################################################
+### Netgraph modules #######################################
+##############################################################
+
+ng_UI_load="NO" # UI netgraph node type
+ng_async_load="NO" # asynchronous framing netgraph node type
+ng_bpf_load="NO" # Berkeley packet filter netgraph node type
+ng_bridge_load="NO" # Ethernet bridging netgraph node type
+ng_cisco_load="NO" # Cisco HDLC protocol netgraph node type
+ng_echo_load="NO" # Netgraph echo node type
+ng_eiface_load="NO" # generic Ethernet interface netgraph node type
+ng_etf_load="NO" # Ethertype filtering netgraph node type
+ng_ether_load="NO" # Ethernet netgraph node type
+ng_frame_relay_load="NO" # frame relay netgraph node type
+ng_gif_load="NO" # generic tunnel interface netgraph node type
+ng_gif_demux_load="NO" # demultiplexer for packets from ng_gif(4) nodes
+ng_hole_load="NO" # Netgraph discard node type
+ng_hub_load="NO" # packet distribution netgraph node type
+ng_iface_load="NO" # interface Netgraph node type
+ng_ip_input_load="NO" # netgraph IP input node type
+ng_ksocket_load="NO" # kernel socket netgraph node type
+ng_l2tp_load="NO" # L2TP protocol netgraph node type
+ng_lmi_load="NO" # frame relay LMI protocol netgraph node type
+ng_mppc_load="NO" # Microsoft MPPC/MPPE compression and
+ # encryption netgraph node type
+ng_netflow_load="NO" # Cisco's NetFlow netgraph node type
+ng_one2many_load="NO" # packet multiplexing netgraph node type
+ng_ppp_load="NO" # PPP protocol netgraph node type
+ng_pppoe_load="NO" # RFC 2516 PPPOE protocol netgraph node type
+ng_pptpgre_load="NO" # PPTP GRE protocol netgraph node type
+ng_rfc1490_load="NO" # RFC 1490 netgraph node type
+ng_socket_load="NO" # Netgraph socket node type
+ng_split_load="NO" # netgraph node to separate incoming and
+ # outgoing flows
+ng_sppp_load="NO" # sppp netgraph node type
+ng_tee_load="NO" # Netgraph ``tee'' node type
+ng_tty_load="NO" # Netgraph node type that is also a line
+ # discipline
+ng_vjc_load="NO" # Van Jacobsen compression netgraph node type
+ng_vlan_load="NO" # IEEE 802.1Q VLAN tagging netgraph node type
+
+
+##############################################################
+### Sound modules ##########################################
+##############################################################
+
+sound_load="NO" # Digital sound subsystem
+snd_ad1816_load="NO" # ad1816
+snd_als4000_load="NO" # als4000
+snd_atiixp_load="NO" # atiixp
+snd_cmi_load="NO" # cmi
+snd_cs4281_load="NO" # cs4281
+snd_csa_load="NO" # csa
+snd_ds1_load="NO" # ds1
+snd_emu10k1_load="NO" # Creative Sound Blaster Live
+snd_emu10kx_load="NO" # Creative SoundBlaster Live! and Audigy
+snd_envy24_load="NO" # VIA Envy24
+snd_envy24ht_load="NO" # VIA Envy24HT
+snd_es137x_load="NO" # es137x
+snd_ess_load="NO" # ess
+snd_fm801_load="NO" # fm801
+snd_hda_load="NO" # Intel High Definition Audio (Controller)
+snd_ich_load="NO" # Intel ICH
+snd_maestro_load="NO" # Maestro
+snd_maestro3_load="NO" # Maestro3
+snd_mss_load="NO" # Mss
+snd_neomagic_load="NO" # Neomagic
+snd_sb16_load="NO" # Sound Blaster 16
+snd_sb8_load="NO" # Sound Blaster Pro
+snd_sbc_load="NO" # Sbc
+snd_solo_load="NO" # Solo
+snd_spicds_load="NO" # SPI codecs
+snd_t4dwave_load="NO" # t4dwave
+snd_via8233_load="NO" # via8233
+snd_via82c686_load="NO" # via82c686
+snd_vibes_load="NO" # vibes
+snd_driver_load="NO" # All sound drivers
+
+
+##############################################################
+### USB modules ############################################
+##############################################################
+
+usb_load="NO" # USB subsystem
+udbp_load="NO" # USB double bulk pipe host 2 host cables
+ugen_load="NO" # USB generic device, if all else fails ...
+ucycom_load="NO" # Cyprus USB serial adapters
+ufm_load="NO" # Fm Radio
+uhid_load="NO" # Human Interface Devices
+ukbd_load="NO" # Keyboard
+ulpt_load="NO" # Printer
+ums_load="NO" # Mouse
+umass_load="NO" # Mass Storage Devices
+umct_load="NO" # Magic Control Technology USB-RS232
+umodem_load="NO" # Modems
+uplcom_load="NO" # Prolific USB serial adapters
+urio_load="NO" # Rio MP3 players
+uvisor_load="NO" # PalmOS based PDAs
+if_aue_load="NO" # ADMtek USB ethernet
+if_axe_load="NO" # ASIX Electronics AX88172 USB ethernet
+if_cdce_load="NO" # Ethernet over USB (CDC)
+if_cue_load="NO" # CATC USB ethernet
+if_kue_load="NO" # Kawasaki LSI USB ethernet
+if_rae_load="NO" # Realtek RTL8150 USB adapter.
+if_rum_load="NO" # Ralink USB 802.11 wireless adapter
+if_uath_load="NO" # Atheros AR5523 wireless adapter
+if_run_load="NO" # Ralink USB 802.11 wireless adapter
+if_ural_load="NO" # Ralink RT2500USB 802.11 wireless adapter
+if_zyd_load="NO" # ZyDAS ZD1211(B) USB 802.11 wireless adapter
+snd_uaudio_load="NO" # USB audio
+
+
+##############################################################
+### Other modules ##########################################
+##############################################################
+
+aio_load="NO" # Asynchronous I/O
+bktr_load="NO" # Brooktree Bt848/Bt878 TV/Video Capture Card
+ispfw_load="NO" # Qlogic ISP Firmware
+agp_load="NO" # agp module
+accf_data_load="NO" # Wait for data accept filter
+accf_dns_load="NO" # Wait for full DNS request accept filter
+accf_http_load="NO" # Wait for full HTTP request accept filter
+ppi_load="NO" # Interface to ppbus parallel 'geek' port
+pps_load="NO" # Pulse per second devices
+puc_load="NO" # PCI "Universal" Communications driver
+random_load="NO" # Random device
+speaker_load="NO" # AT speaker module
+coretemp_load="NO" # Intel Core CPU temperature monitor
+vkbd_load="NO" # Virtual AT keyboard interface
+vpd_load="NO" # Vital Product Data kernel interface
+vpo_load="NO" # Parallel to SCSI interface driver
+amdsmn_load="NO" # AMD Family 17h System Management Network
+amdtemp_load="NO" # AMD K8/K10/K11 temperature monitor
+tpm_load="NO" # Trusted Platform Module
+wbwd_load="NO" # Winbond watchdog
+
+
+##############################################################
+### ACPI settings ##########################################
+##############################################################
+
+acpi_dsdt_load="NO" # DSDT Overriding
+acpi_dsdt_type="acpi_dsdt" # Don't change this
+acpi_dsdt_name="/boot/acpi_dsdt.aml"
+ # Override DSDT in BIOS by this file
+acpi_video_load="NO" # Load the ACPI video extension driver
+
+
+##############################################################
+### TrustedBSD MAC settings ################################
+##############################################################
+
+mac_biba_load="NO" # Biba MAC policy
+mac_bsdextended_load="NO" # BSD/extended MAC policy
+mac_ifoff="NO" # Interface silencing policy
+mac_mls_load="NO" # MLS MAC policy
+mac_none_load="NO" # Null MAC policy
+mac_partition_load="NO" # Partition MAC policy
+mac_seeotheruids_load="NO" # UID visbility MAC policy
+
+
+##############################################################
+### Module loading syntax example ##########################
+##############################################################
+
+#module_load="YES" # loads module "module"
+#module_name="realname" # uses "realname" instead of "module"
+#module_type="type" # passes "-t type" to load
+#module_flags="flags" # passes "flags" to the module
+#module_before="cmd" # executes "cmd" before loading the module
+#module_after="cmd" # executes "cmd" after loading the module
+#module_error="cmd" # executes "cmd" if load fails
diff --git a/stand/forth/loader.conf.5 b/stand/forth/loader.conf.5
new file mode 100644
index 000000000000..631250c5278c
--- /dev/null
+++ b/stand/forth/loader.conf.5
@@ -0,0 +1,330 @@
+.\" Copyright (c) 1999 Daniel C. Sobral
+.\" 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$
+.Dd January 6, 2016
+.Dt LOADER.CONF 5
+.Os
+.Sh NAME
+.Nm loader.conf
+.Nd "system bootstrap configuration information"
+.Sh DESCRIPTION
+The file
+.Nm
+contains descriptive information on bootstrapping the system.
+Through
+it you can specify the kernel to be booted, parameters to be passed to
+it, and additional modules to be loaded; and generally set all variables
+described in
+.Xr loader 8 .
+.Pp
+The file
+.Pa /boot/loader.rc
+must contain the following two lines for
+.Nm
+to be automatically processed:
+.Pp
+.Dl include /boot/loader.4th
+.Dl start
+.Pp
+If no
+.Pa /boot/loader.rc
+exists at installworld time, one with the above lines will be installed.
+.Sh SYNTAX
+Though
+.Nm Ns 's
+format was defined explicitly to resemble
+.Xr rc.conf 5 ,
+and can be sourced by
+.Xr sh 1 ,
+some settings are treated in a special fashion.
+Also, the
+behavior of some settings is defined by the setting's suffix;
+the prefix identifies which module the setting controls.
+.Pp
+The general parsing rules are:
+.Bl -bullet
+.It
+Spaces and empty lines are ignored.
+.It
+A # sign will mark the remainder of the line as a comment.
+.It
+Only one setting can be present on each line.
+.El
+.Pp
+All settings have the following format:
+.Pp
+.Dl variable="value"
+.Pp
+Unless it belongs to one of the classes of settings that receive special
+treatment, a setting will set the value of a
+.Xr loader 8
+environment variable.
+The settings that receive special
+treatment are listed below.
+Settings beginning with
+.Qq *
+below define the modules to be loaded and
+may have any prefix; the prefix identifies a module.
+All such settings sharing a common
+prefix refer to the same module.
+.Bl -tag -width Ar
+.It Ar exec
+Immediately executes a
+.Xr loader 8
+command.
+This type of setting cannot be processed by programs other
+than
+.Xr loader 8 ,
+so its use should be avoided.
+Multiple instances of it will be processed
+independently.
+.It Ar loader_conf_files
+Defines additional configuration files to be processed right after the
+present file.
+.It Ar kernel
+Name of the kernel to be loaded.
+If no kernel name is set, no additional
+modules will be loaded.
+The name must be a subdirectory of
+.Pa /boot
+that contains a kernel.
+.It Ar kernel_options
+Flags to be passed to the kernel.
+.It Ar vfs.root.mountfrom
+Specify the root partition to mount.
+For example:
+.Pp
+.Dl vfs.root.mountfrom="ufs:/dev/da0s1a"
+.Pp
+.Xr loader 8
+automatically calculates the value of this tunable from
+.Pa /etc/fstab
+from the partition the kernel was loaded from.
+The calculated value might be calculated incorrectly when
+.Pa /etc/fstab
+is not available during
+.Xr loader 8
+startup (as during diskless booting from NFS), or if a different
+device is desired by the user.
+The preferred value can be set in
+.Pa /loader.conf .
+.Pp
+The value can also be overridden from the
+.Xr loader 8
+command line.
+This is useful for system recovery when
+.Pa /etc/fstab
+is damaged, lost, or read from the wrong partition.
+.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 ,
+module names will be displayed as they are loaded.
+.It Ar *_load
+If set to
+.Dq YES ,
+that module will be loaded.
+If no name is defined (see below), the
+module's name is taken to be the same as the prefix.
+.It Ar *_name
+Defines the name of the module.
+.It Ar *_type
+Defines the module's type.
+If none is given, it defaults to a kld module.
+.It Ar *_flags
+Flags and parameters to be passed to the module.
+.It Ar *_before
+Commands to be executed before the module is loaded.
+Use of this setting
+should be avoided.
+.It Ar *_after
+Commands to be executed after the module is loaded.
+Use of this setting
+should be avoided.
+.It Ar *_error
+Commands to be executed if the loading of a module fails.
+Except for the
+special value
+.Dq abort ,
+which aborts the bootstrap process, use of this setting should be avoided.
+.El
+.Pp
+.Em WARNING:
+developers should never use these suffixes for any kernel environment
+variables (tunables) or conflicts will result.
+.Sh DEFAULT SETTINGS
+Most of
+.Nm Ns 's
+default settings can be ignored.
+The few of them which are important
+or useful are:
+.Bl -tag -width bootfile -offset indent
+.It Va bitmap_load
+.Pq Dq NO
+If set to
+.Dq YES ,
+a bitmap will be loaded to be displayed on screen while booting.
+.It Va bitmap_name
+.Pq Dq Pa /boot/splash.bmp
+Name of the bitmap to be loaded.
+Any other name can be used.
+.It Va comconsole_speed
+.Dq ( 9600
+or the value of the
+.Va BOOT_COMCONSOLE_SPEED
+variable when
+.Xr loader 8
+was compiled).
+Sets the speed of the serial console.
+If the previous boot loader stage specified that a serial console
+is in use then the default speed is determined from the current
+serial port speed setting.
+.It Va console
+.Pq Dq vidconsole
+.Dq comconsole
+selects serial console,
+.Dq vidconsole
+selects the video console,
+.Dq nullconsole
+selects a mute console
+(useful for systems with neither a video console nor a serial port), and
+.Dq spinconsole
+selects the video console which prevents any input and hides all output
+replacing it with
+.Dq spinning
+character (useful for embedded products and such).
+.It Va kernel
+.Pq Dq kernel
+.It Va kernels
+.Pq Dq kernel kernel.old
+Space or comma separated list of kernels to present in the boot menu.
+.It Va loader_conf_files
+.Pq Dq Pa /boot/loader.conf /boot/loader.conf.local
+.It Va splash_bmp_load
+.Pq Dq NO
+If set to
+.Dq YES ,
+will load the splash screen module, making it possible to display a bmp image
+on the screen while booting.
+.It Va splash_pcx_load
+.Pq Dq NO
+If set to
+.Dq YES ,
+will load the splash screen module, making it possible to display a pcx image
+on the screen while booting.
+.It Va vesa_load
+.Pq Dq NO
+If set to
+.Dq YES ,
+the vesa module will be loaded, enabling bitmaps above VGA resolution to
+be displayed.
+.It Va beastie_disable
+If set to
+.Dq YES ,
+the beastie boot menu will be skipped.
+The beastie boot menu is always skipped if running non-x86 hardware.
+.It Va loader_logo Pq Dq Li orbbw
+Selects a desired logo in the beastie boot menu.
+Possible values are:
+.Dq Li orbbw ,
+.Dq Li orb ,
+.Dq Li fbsdbw ,
+.Dq Li beastiebw ,
+.Dq Li beastie ,
+and
+.Dq Li none .
+.It Va loader_color
+If set to
+.Dq NO ,
+the beastie boot menu will be displayed without ANSI coloring.
+.It Va entropy_cache_load
+.Pq Dq YES
+If set to
+.Dq NO ,
+the very early
+boot-time entropy file
+will not be loaded.
+See the entropy entries in
+.Xr rc.conf 5 .
+.It Va entropy_cache_name
+.Pq Dq /boot/entropy
+The name of the very early
+boot-time entropy cache file.
+.El
+.Sh FILES
+.Bl -tag -width /boot/defaults/loader.conf -compact
+.It Pa /boot/defaults/loader.conf
+default settings -- do not change this file.
+.It Pa /boot/loader.4th
+defines the commands used by loader to read and process
+.Nm .
+.It Pa /boot/loader.conf
+user defined settings.
+.It Pa /boot/loader.conf.local
+machine-specific settings for sites with a common loader.conf.
+.It Pa /boot/loader.rc
+contains the instructions to automatically process
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr rc.conf 5 ,
+.Xr boot 8 ,
+.Xr loader 8 ,
+.Xr loader.4th 8
+.Sh HISTORY
+The file
+.Nm
+first appeared in
+.Fx 3.2 .
+.Sh AUTHORS
+This manual page was written by
+.An Daniel C. Sobral Aq dcs@FreeBSD.org .
+.Sh BUGS
+The
+.Xr loader 8
+stops reading
+.Nm
+when it encounters a syntax error, so any options which are vital for
+booting a particular system (i.e.\&
+.Dq Va hw.ata.ata_dma Ns "=0" )
+should precede any experimental additions to
+.Nm .
diff --git a/stand/forth/loader.rc b/stand/forth/loader.rc
new file mode 100644
index 000000000000..0bc66579cd0f
--- /dev/null
+++ b/stand/forth/loader.rc
@@ -0,0 +1,23 @@
+\ Loader.rc
+\ $FreeBSD$
+\
+\ You should not edit this file! Put any overrides in loader.rc.local
+\ instead as this file can be replaced during system updates.
+\
+\ Includes additional commands
+include /boot/loader.4th
+try-include /boot/loader.rc.local
+
+\ Reads and processes loader.conf variables
+\ NOTE: Change to `initialize' if you enable the below boot menu
+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
+
diff --git a/stand/forth/logo-beastie.4th b/stand/forth/logo-beastie.4th
new file mode 100644
index 000000000000..671eb5e496b2
--- /dev/null
+++ b/stand/forth/logo-beastie.4th
@@ -0,0 +1,61 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
+\ Copyright (c) 2006-2015 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$
+
+46 logoX ! 4 logoY ! \ Initialize logo placement defaults
+
+: logo+ ( x y c-addr/u -- x y' )
+ 2swap 2dup at-xy 2swap \ position the cursor
+ [char] @ escc! \ replace @ with Esc
+ type \ print to the screen
+ 1+ \ increase y for next time we're called
+;
+
+: logo ( x y -- ) \ color BSD mascot (19 rows x 34 columns)
+
+ s" @[31m, ," logo+
+ s" /( )`" logo+
+ s" \ \___ / |" logo+
+ s" /- @[m_@[31m `-/ '" logo+
+ s" (@[m/\/ \@[31m \ /\" logo+
+ s" @[m/ / |@[31m ` \" logo+
+ s" @[34mO O @[m) @[31m/ |" logo+
+ s" @[m`-^--'@[31m`< '" logo+
+ s" (_.) _ ) /" logo+
+ s" `.___/` /" logo+
+ s" `-----' /" logo+
+ s" @[33m<----.@[31m __ / __ \" logo+
+ s" @[33m<----|====@[31mO)))@[33m==@[31m) \) /@[33m====|" logo+
+ s" @[33m<----'@[31m `--' `.__,' \" logo+
+ s" | |" logo+
+ s" \ / /\" logo+
+ s" @[36m______@[31m( (_ / \______/" logo+
+ s" @[36m,' ,-----' |" logo+
+ s" `--{__________)@[m" logo+
+
+ 2drop
+;
diff --git a/stand/forth/logo-beastiebw.4th b/stand/forth/logo-beastiebw.4th
new file mode 100644
index 000000000000..197099cda0bc
--- /dev/null
+++ b/stand/forth/logo-beastiebw.4th
@@ -0,0 +1,59 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2006-2015 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$
+
+46 logoX ! 4 logoY ! \ Initialize logo placement defaults
+
+: logo+ ( x y c-addr/u -- x y' )
+ 2swap 2dup at-xy 2swap \ position the cursor
+ type \ print to the screen
+ 1+ \ increase y for next time we're called
+;
+
+: logo ( x y -- ) \ B/W BSD mascot (19 rows x 34 columns)
+
+ s" , ," logo+
+ s" /( )`" logo+
+ s" \ \___ / |" logo+
+ s" /- _ `-/ '" logo+
+ s" (/\/ \ \ /\" logo+
+ s" / / | ` \" logo+
+ s" O O ) / |" logo+
+ s" `-^--'`< '" logo+
+ s" (_.) _ ) /" logo+
+ s" `.___/` /" logo+
+ s" `-----' /" logo+
+ s" <----. __ / __ \" logo+
+ s" <----|====O)))==) \) /====|" logo+
+ s" <----' `--' `.__,' \" logo+
+ s" | |" logo+
+ s" \ / /\" logo+
+ s" ______( (_ / \______/" logo+
+ s" ,' ,-----' |" logo+
+ s" `--{__________)" logo+
+
+ 2drop
+;
diff --git a/stand/forth/logo-fbsdbw.4th b/stand/forth/logo-fbsdbw.4th
new file mode 100644
index 000000000000..d4a532b78f4f
--- /dev/null
+++ b/stand/forth/logo-fbsdbw.4th
@@ -0,0 +1,53 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2006-2015 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$
+
+52 logoX ! 9 logoY ! \ Initialize logo placement defaults
+
+: logo+ ( x y c-addr/u -- x y' )
+ 2swap 2dup at-xy 2swap \ position the cursor
+ type \ print to the screen
+ 1+ \ increase y for next time we're called
+;
+
+: logo ( x y -- ) \ "FreeBSD" logo in B/W (13 rows x 21 columns)
+
+ s" ______" logo+
+ s" | ____| __ ___ ___ " logo+
+ s" | |__ | '__/ _ \/ _ \" logo+
+ s" | __|| | | __/ __/" logo+
+ s" | | | | | | |" logo+
+ s" |_| |_| \___|\___|" logo+
+ s" ____ _____ _____" logo+
+ s" | _ \ / ____| __ \" logo+
+ s" | |_) | (___ | | | |" logo+
+ s" | _ < \___ \| | | |" logo+
+ s" | |_) |____) | |__| |" logo+
+ s" | | | |" logo+
+ s" |____/|_____/|_____/" logo+
+
+ 2drop
+;
diff --git a/stand/forth/logo-orb.4th b/stand/forth/logo-orb.4th
new file mode 100644
index 000000000000..c2a504d1ddf5
--- /dev/null
+++ b/stand/forth/logo-orb.4th
@@ -0,0 +1,55 @@
+\ Copyright (c) 2006-2015 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$
+
+46 logoX ! 7 logoY ! \ Initialize logo placement defaults
+
+: logo+ ( x y c-addr/u -- x y' )
+ 2swap 2dup at-xy 2swap \ position the cursor
+ [char] @ escc! \ replace @ with Esc
+ type \ print to the screen
+ 1+ \ increase y for next time we're called
+;
+
+: logo ( x y -- ) \ color Orb mascot (15 rows x 30 columns)
+
+ s" @[31m``` @[31;1m`@[31m" logo+
+ s" s` `.....---...@[31;1m....--.``` -/@[31m" logo+
+ s" +o .--` @[31;1m/y:` +.@[31m" logo+
+ s" yo`:. @[31;1m:o `+-@[31m" logo+
+ s" y/ @[31;1m-/` -o/@[31m" logo+
+ s" .- @[31;1m::/sy+:.@[31m" logo+
+ s" / @[31;1m`-- /@[31m" logo+
+ s" `: @[31;1m:`@[31m" logo+
+ s" `: @[31;1m:`@[31m" logo+
+ s" / @[31;1m/@[31m" logo+
+ s" .- @[31;1m-.@[31m" logo+
+ s" -- @[31;1m-.@[31m" logo+
+ s" `:` @[31;1m`:`" logo+
+ s" @[31;1m.-- `--." logo+
+ s" .---.....----.@[m" logo+
+
+ 2drop
+;
diff --git a/stand/forth/logo-orbbw.4th b/stand/forth/logo-orbbw.4th
new file mode 100644
index 000000000000..11dc11cabb77
--- /dev/null
+++ b/stand/forth/logo-orbbw.4th
@@ -0,0 +1,54 @@
+\ Copyright (c) 2006-2015 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$
+
+46 logoX ! 7 logoY ! \ Initialize logo placement defaults
+
+: logo+ ( x y c-addr/u -- x y' )
+ 2swap 2dup at-xy 2swap \ position the cursor
+ type \ print to the screen
+ 1+ \ increase y for next time we're called
+;
+
+: logo ( x y -- ) \ B/W Orb mascot (15 rows x 32 columns)
+
+ s" ``` `" logo+
+ s" s` `.....---.......--.``` -/" logo+
+ s" +o .--` /y:` +." logo+
+ s" yo`:. :o `+-" logo+
+ s" y/ -/` -o/" logo+
+ s" .- ::/sy+:." logo+
+ s" / `-- /" logo+
+ s" `: :`" logo+
+ s" `: :`" logo+
+ s" / /" logo+
+ s" .- -." logo+
+ s" -- -." logo+
+ s" `:` `:`" logo+
+ s" .-- `--." logo+
+ s" .---.....----." logo+
+
+ 2drop
+;
diff --git a/stand/forth/menu-commands.4th b/stand/forth/menu-commands.4th
new file mode 100644
index 000000000000..9adf30a46b66
--- /dev/null
+++ b/stand/forth/menu-commands.4th
@@ -0,0 +1,418 @@
+\ Copyright (c) 2006-2015 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-menu-commands.4th
+
+include /boot/menusets.4th
+
+only forth definitions
+
+variable kernel_state
+variable root_state
+0 kernel_state !
+0 root_state !
+
+also menu-namespace also menu-command-helpers
+
+\
+\ 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 ( N -- NOTREACHED )
+ 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
+ s" loader.acpi_disabled_by_user" unsetenv
+;
+
+: acpi_disable ( -- )
+ s" acpi_load" unsetenv \ XXX deprecated but harmless
+ s" set hint.acpi.0.disabled=1" evaluate
+ s" set loader.acpi_disabled_by_user=1" evaluate
+;
+
+: toggle_acpi ( N -- N TRUE )
+
+ \ Make changes effective _before_ calling menu-redraw
+
+ acpienabled? if
+ acpi_disable
+ else
+ acpi_enable
+ then
+
+ menu-redraw
+
+ 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
+
+ dup toggle_stateN @ 0= if
+ safemode_disable
+ else
+ safemode_enable
+ then
+
+ menu-redraw
+
+ 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
+
+ dup toggle_stateN @ 0= if
+ singleuser_disable
+ else
+ 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
+
+ dup toggle_stateN @ 0= if
+ verbose_disable
+ else
+ verbose_enable
+ then
+
+ TRUE \ loop menu again
+;
+
+\
+\ Escape to Prompt
+\
+
+: goto_prompt ( N -- N FALSE )
+
+ s" set autoboot_delay=NO" evaluate
+
+ cr
+ ." To get back to the menu, type `menu' and press ENTER" cr
+ ." or type `boot' and press ENTER to start FreeBSD." cr
+ cr
+
+ 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 )
+;
+
+: activate_kernel ( N -- N )
+ dup cycle_stateN @ ( n -- n n2 )
+ dup kernel_state ! ( n n2 -- n n2 ) \ copy for re-initialization
+ 48 + ( n n2 -- n n2' ) \ kernel_state to ASCII num
+
+ s" set kernel=${kernel_prefix}${kernel[N]}${kernel_suffix}"
+ 36 +c! ( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num
+ evaluate ( n c-addr/u -- n ) \ sets $kernel to full kernel-path
+;
+
+: cycle_kernel ( N -- N TRUE )
+ cycle_menuitem \ cycle cycle_stateN to next value
+ activate_kernel \ apply current cycle_stateN
+ menu-redraw \ redraw menu
+ TRUE \ loop menu again
+;
+
+\
+\ Root
+\
+
+: init_root ( N -- N )
+ root_state @ ( n -- n k )
+ init_cyclestate ( n k -- n )
+;
+
+: activate_root ( N -- N )
+ dup cycle_stateN @ ( n -- n n2 )
+ dup root_state ! ( n n2 -- n n2 ) \ copy for re-initialization
+ 48 + ( n n2 -- n n2' ) \ root_state to ASCII num
+
+ s" set root=${root_prefix}${root[N]}${root_suffix}"
+ 30 +c! ( n n2 c-addr/u -- n c-addr/u ) \ 'N' to ASCII num
+ evaluate ( n c-addr/u -- n ) \ sets $root to full kernel-path
+;
+
+: cycle_root ( N -- N TRUE )
+ cycle_menuitem \ cycle cycle_stateN to next value
+ activate_root \ apply current cycle_stateN
+ menu-redraw \ redraw menu
+ 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
+;
+
+\
+\ Set boot environment defaults
+\
+
+: init_bootenv ( -- )
+ s" set menu_caption[1]=${bemenu_current}${vfs.root.mountfrom}" evaluate
+ s" set ansi_caption[1]=${beansi_current}${vfs.root.mountfrom}" evaluate
+ s" set menu_caption[2]=${bemenu_bootfs}${zfs_be_active}" evaluate
+ s" set ansi_caption[2]=${beansi_bootfs}${zfs_be_active}" evaluate
+ s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
+ s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
+;
+
+\
+\ Redraw the entire screen. A long BE name can corrupt the menu
+\
+
+: be_draw_screen
+ clear \ Clear the screen (in screen.4th)
+ print_version \ print version string (bottom-right; see version.4th)
+ draw-beastie \ Draw FreeBSD logo at right (in beastie.4th)
+ draw-brand \ Draw brand.4th logo at top (in brand.4th)
+ menu-init \ Initialize menu and draw bounding box (in menu.4th)
+;
+
+\
+\ Select a boot environment
+\
+
+: set_bootenv ( N -- N TRUE )
+ dup s" set vfs.root.mountfrom=${bootenv_root[E]}" 38 +c! evaluate
+ s" set currdev=${vfs.root.mountfrom}:" evaluate
+ s" unload" evaluate
+ free-module-options
+ s" /boot/defaults/loader.conf" read-conf
+ s" /boot/loader.conf" read-conf
+ s" /boot/loader.conf.local" read-conf
+ init_bootenv
+ be_draw_screen
+ menu-redraw
+ TRUE
+;
+
+\
+\ Switch to the next page of boot environments
+\
+
+: set_be_page ( N -- N TRUE )
+ s" zfs_be_currpage" getenv dup -1 = if
+ drop s" 1"
+ else
+ 0 s>d 2swap
+ >number ( ud caddr/u -- ud' caddr'/u' ) \ convert string to numbers
+ 2drop \ drop the string
+ 1 um/mod ( ud u1 -- u2 u3 ) \ convert double ud' to single u3' and remainder u2
+ swap drop ( ud2 u3 -- u3 ) \ drop the remainder u2
+ 1+ \ increment the page number
+ s>d <# #s #> \ convert back to a string
+ then
+ s" zfs_be_currpage" setenv
+ s" reloadbe" evaluate
+ 3 goto_menu
+;
+
+only forth definitions
diff --git a/stand/forth/menu.4th b/stand/forth/menu.4th
new file mode 100644
index 000000000000..e3fe0f7d776e
--- /dev/null
+++ b/stand/forth/menu.4th
@@ -0,0 +1,1319 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
+\ Copyright (c) 2006-2015 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-menu.4th
+
+\ Frame drawing
+include /boot/frames.4th
+
+vocabulary menu-infrastructure
+vocabulary menu-namespace
+vocabulary menu-command-helpers
+
+only forth also menu-infrastructure definitions
+
+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)
+
+\ Customize the following values with care
+
+ 1 constant menu_start \ Numerical prefix of first menu item
+dot constant bullet \ Menu bullet (appears after numerical prefix)
+ 5 constant menu_x \ Row position of the menu (from the top)
+ 10 constant menu_y \ Column position of the menu (from left side)
+
+\ Menu Appearance
+variable menuidx \ Menu item stack for number prefixes
+variable menurow \ Menu item stack for positioning
+variable menubllt \ Menu item bullet
+
+\ Menu Positioning
+variable menuX \ Menu X offset (columns)
+variable menuY \ Menu Y offset (rows)
+
+\ Menu-item elements
+variable menurebootadded
+
+\ Parsing of kernels into menu-items
+variable kernidx
+variable kernlen
+variable kernmenuidx
+
+\ Menu timer [count-down] variables
+variable menu_timeout_enabled \ timeout state (internal use only)
+variable menu_time \ variable for tracking the passage of time
+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
+
+\ Containers for parsing kernels into menu-items
+create kerncapbuf 64 allot
+create kerndefault 64 allot
+create kernelsbuf 256 allot
+
+only forth also menu-namespace definitions
+
+\ Menu-item key association/detection
+variable menukey1
+variable menukey2
+variable menukey3
+variable menukey4
+variable menukey5
+variable menukey6
+variable menukey7
+variable menukey8
+variable menureboot
+variable menuacpi
+variable menuoptions
+variable menukernel
+
+\ 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
+variable toggle_state3
+variable toggle_state4
+variable toggle_state5
+variable toggle_state6
+variable toggle_state7
+variable toggle_state8
+
+\ Array option status variables
+variable cycle_state1
+variable cycle_state2
+variable cycle_state3
+variable cycle_state4
+variable cycle_state5
+variable cycle_state6
+variable cycle_state7
+variable cycle_state8
+
+\ Containers for storing the initial caption text
+create init_text1 64 allot
+create init_text2 64 allot
+create init_text3 64 allot
+create init_text4 64 allot
+create init_text5 64 allot
+create init_text6 64 allot
+create init_text7 64 allot
+create init_text8 64 allot
+
+only forth definitions
+
+: arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise.
+ s" arch-i386" environment? dup if
+ drop
+ then
+;
+
+: acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise
+ s" hint.acpi.0.rsdp" getenv
+ dup -1 = if
+ drop false exit
+ then
+ 2drop
+ true
+;
+
+: acpienabled? ( -- flag ) \ Returns TRUE if ACPI is enabled, FALSE otherwise
+ s" hint.acpi.0.disabled" getenv
+ dup -1 <> if
+ s" 0" compare 0<> if
+ false exit
+ then
+ else
+ drop
+ then
+ true
+;
+
+: +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 )
+;
+
+only forth also menu-namespace definitions
+
+\ Forth variables
+: namespace ( C-ADDR/U N -- ) also menu-namespace +c! evaluate previous ;
+: menukeyN ( N -- ADDR ) s" menukeyN" 7 namespace ;
+: init_stateN ( N -- ADDR ) s" init_stateN" 10 namespace ;
+: toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 namespace ;
+: cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 namespace ;
+: init_textN ( N -- C-ADDR ) s" init_textN" 9 namespace ;
+
+\ Environment variables
+: kernel[x] ( N -- C-ADDR/U ) s" kernel[x]" 7 +c! ;
+: menu_init[x] ( N -- C-ADDR/U ) s" menu_init[x]" 10 +c! ;
+: menu_command[x] ( N -- C-ADDR/U ) s" menu_command[x]" 13 +c! ;
+: menu_caption[x] ( N -- C-ADDR/U ) s" menu_caption[x]" 13 +c! ;
+: ansi_caption[x] ( N -- C-ADDR/U ) s" ansi_caption[x]" 13 +c! ;
+: menu_keycode[x] ( N -- C-ADDR/U ) s" menu_keycode[x]" 13 +c! ;
+: toggled_text[x] ( N -- C-ADDR/U ) s" toggled_text[x]" 13 +c! ;
+: toggled_ansi[x] ( N -- C-ADDR/U ) s" toggled_ansi[x]" 13 +c! ;
+: menu_caption[x][y] ( N M -- C-ADDR/U ) s" menu_caption[x][y]" 16 +c! 13 +c! ;
+: ansi_caption[x][y] ( N M -- C-ADDR/U ) s" ansi_caption[x][y]" 16 +c! 13 +c! ;
+
+also menu-infrastructure definitions
+
+\ This function prints a menu item at menuX (row) and menuY (column), returns
+\ the incremental decimal ASCII value associated with the menu item, and
+\ increments the cursor position to the next row for the creation of the next
+\ menu item. This function is called by the menu-create function. You need not
+\ call it directly.
+\
+: printmenuitem ( menu_item_str -- ascii_keycode )
+
+ loader_color? if [char] ^ escc! then
+
+ menurow dup @ 1+ swap ! ( increment menurow )
+ menuidx dup @ 1+ swap ! ( increment menuidx )
+
+ \ Calculate the menuitem row position
+ menurow @ menuY @ +
+
+ \ Position the cursor at the menuitem position
+ dup menuX @ swap at-xy
+
+ \ Print the value of menuidx
+ loader_color? dup ( -- bool bool )
+ if b then
+ menuidx @ .
+ if me then
+
+ \ Move the cursor forward 1 column
+ dup menuX @ 1+ swap at-xy
+
+ menubllt @ emit \ Print the menu bullet using the emit function
+
+ \ Move the cursor to the 3rd column from the current position
+ \ to allow for a space between the numerical prefix and the
+ \ text caption
+ menuX @ 3 + swap at-xy
+
+ \ Print the menu caption (we expect a string to be on the stack
+ \ prior to invoking this function)
+ type
+
+ \ Here we will add the ASCII decimal of the numerical prefix
+ \ to the stack (decimal ASCII for `1' is 49) as a "return value"
+ menuidx @ 48 +
+;
+
+\ This function prints the appropriate menuitem basename to the stack if an
+\ 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/U | -1 )
+
+ arch-i386? if
+ acpipresent? if
+ acpienabled? if
+ loader_color? if
+ s" toggled_ansi[x]"
+ else
+ s" toggled_text[x]"
+ then
+ else
+ loader_color? if
+ s" ansi_caption[x]"
+ else
+ s" menu_caption[x]"
+ then
+ then
+ else
+ menuidx dup @ 1+ swap ! ( increment menuidx )
+ -1
+ then
+ else
+ -1
+ then
+;
+
+: delim? ( C -- BOOL )
+ dup 32 = ( c -- c bool ) \ [sp] space
+ over 9 = or ( c bool -- c bool ) \ [ht] horizontal tab
+ over 10 = or ( c bool -- c bool ) \ [nl] newline
+ over 13 = or ( c bool -- c bool ) \ [cr] carriage return
+ over [char] , = or ( c bool -- c bool ) \ comma
+ swap drop ( c bool -- bool ) \ return boolean
+;
+
+\ This function parses $kernels into variables that are used by the menu to
+\ display which kernel to boot when the [overloaded] `boot' word is interpreted.
+\ Used internally by menu-create, you need not (nor should you) call this
+\ directly.
+\
+: parse-kernels ( N -- ) \ kernidx
+ kernidx ! ( n -- ) \ store provided `x' value
+ [char] 0 kernmenuidx ! \ initialize `y' value for menu_caption[x][y]
+
+ \ Attempt to get a list of kernels, fall back to sensible default
+ s" kernels" getenv dup -1 = if
+ drop ( cruft )
+ s" kernel kernel.old"
+ then ( -- c-addr/u )
+
+ \ Check to see if the user has altered $kernel by comparing it against
+ \ $kernel[N] where N is kernel_state (the actively displayed kernel).
+ s" kernel_state" evaluate @ 48 + s" kernel[N]" 7 +c! getenv
+ dup -1 <> if
+ s" kernel" getenv dup -1 = if
+ drop ( cruft ) s" "
+ then
+ 2swap 2over compare 0= if
+ 2drop FALSE ( skip below conditional )
+ else \ User has changed $kernel
+ TRUE ( slurp in new value )
+ then
+ else \ We haven't yet parsed $kernels into $kernel[N]
+ drop ( getenv cruft )
+ s" kernel" getenv dup -1 = if
+ drop ( cruft ) s" "
+ then
+ TRUE ( slurp in initial value )
+ then ( c-addr/u -- c-addr/u c-addr/u,-1 | 0 )
+ if \ slurp new value into kerndefault
+ kerndefault 1+ 0 2swap strcat swap 1- c!
+ then
+
+ \ Clear out existing parsed-kernels
+ kernidx @ [char] 0
+ begin
+ dup kernel[x] unsetenv
+ 2dup menu_caption[x][y] unsetenv
+ 2dup ansi_caption[x][y] unsetenv
+ 1+ dup [char] 8 >
+ until
+ 2drop
+
+ \ Step through the string until we find the end
+ begin
+ 0 kernlen ! \ initialize length of value
+
+ \ Skip leading whitespace and/or comma delimiters
+ begin
+ dup 0<> if
+ over c@ delim? ( c-addr/u -- c-addr/u bool )
+ else
+ false ( c-addr/u -- c-addr/u bool )
+ then
+ while
+ 1- swap 1+ swap ( c-addr/u -- c-addr'/u' )
+ repeat
+ ( c-addr/u -- c-addr'/u' )
+
+ dup 0= if \ end of string while eating whitespace
+ 2drop ( c-addr/u -- )
+ kernmenuidx @ [char] 0 <> if \ found at least one
+ exit \ all done
+ then
+
+ \ No entries in $kernels; use $kernel instead
+ s" kernel" getenv dup -1 = if
+ drop ( cruft ) s" "
+ then ( -- c-addr/u )
+ dup kernlen ! \ store entire value length as kernlen
+ else
+ \ We're still within $kernels parsing toward the end;
+ \ find delimiter/end to determine kernlen
+ 2dup ( c-addr/u -- c-addr/u c-addr/u )
+ begin dup 0<> while
+ over c@ delim? if
+ drop 0 ( break ) \ found delimiter
+ else
+ kernlen @ 1+ kernlen ! \ incrememnt
+ 1- swap 1+ swap \ c-addr++ u--
+ then
+ repeat
+ 2drop ( c-addr/u c-addr'/u' -- c-addr/u )
+
+ \ If this is the first entry, compare it to $kernel
+ \ If different, then insert $kernel beforehand
+ kernmenuidx @ [char] 0 = if
+ over kernlen @ kerndefault count compare if
+ kernelsbuf 0 kerndefault count strcat
+ s" ," strcat 2swap strcat
+ kerndefault count swap drop kernlen !
+ then
+ then
+ then
+ ( c-addr/u -- c-addr'/u' )
+
+ \ At this point, we should have something on the stack to store
+ \ as the next kernel menu option; start assembling variables
+
+ over kernlen @ ( c-addr/u -- c-addr/u c-addr/u2 )
+
+ \ Assign first to kernel[x]
+ 2dup kernmenuidx @ kernel[x] setenv
+
+ \ Assign second to menu_caption[x][y]
+ kerncapbuf 0 s" [K]ernel: " strcat
+ 2over strcat
+ kernidx @ kernmenuidx @ menu_caption[x][y]
+ setenv
+
+ \ Assign third to ansi_caption[x][y]
+ kerncapbuf 0 s" @[1mK@[37mernel: " [char] @ escc! strcat
+ kernmenuidx @ [char] 0 = if
+ s" default/@[32m"
+ else
+ s" @[34;1m"
+ then
+ [char] @ escc! strcat
+ 2over strcat
+ s" @[37m" [char] @ escc! strcat
+ kernidx @ kernmenuidx @ ansi_caption[x][y]
+ setenv
+
+ 2drop ( c-addr/u c-addr/u2 -- c-addr/u )
+
+ kernmenuidx @ 1+ dup kernmenuidx ! [char] 8 > if
+ 2drop ( c-addr/u -- ) exit
+ then
+
+ kernlen @ - swap kernlen @ + swap ( c-addr/u -- c-addr'/u' )
+ again
+;
+
+\ This function goes through the kernels that were discovered by the
+\ parse-kernels function [above], adding " (# of #)" text to the end of each
+\ caption.
+\
+: tag-kernels ( -- )
+ kernidx @ ( -- x ) dup 0= if exit then
+ [char] 0 s" (Y of Z)" ( x -- x y c-addr/u )
+ kernmenuidx @ -rot 7 +c! \ Replace 'Z' with number of kernels parsed
+ begin
+ 2 pick 1+ -rot 2 +c! \ Replace 'Y' with current ASCII num
+
+ 2over menu_caption[x][y] getenv dup -1 <> if
+ 2dup + 1- c@ [char] ) = if
+ 2drop \ Already tagged
+ else
+ kerncapbuf 0 2swap strcat
+ 2over strcat
+ 5 pick 5 pick menu_caption[x][y] setenv
+ then
+ else
+ drop ( getenv cruft )
+ then
+
+ 2over ansi_caption[x][y] getenv dup -1 <> if
+ 2dup + 1- c@ [char] ) = if
+ 2drop \ Already tagged
+ else
+ kerncapbuf 0 2swap strcat
+ 2over strcat
+ 5 pick 5 pick ansi_caption[x][y] setenv
+ then
+ else
+ drop ( getenv cruft )
+ then
+
+ rot 1+ dup [char] 8 > if
+ -rot 2drop TRUE ( break )
+ else
+ -rot FALSE
+ then
+ until
+ 2drop ( x y -- )
+;
+
+\ This function creates the list of menu items. This function is called by the
+\ menu-display function. You need not call it directly.
+\
+: menu-create ( -- )
+
+ \ Print the frame caption at (x,y)
+ s" loader_menu_title" getenv dup -1 = if
+ drop s" Welcome to FreeBSD"
+ then
+ TRUE ( use default alignment )
+ s" 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).
+ \
+ s" 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
+ \ numerical prefix to the stack. We store the value left on the stack
+ \ to the key binding variable for later testing against a character
+ \ captured by the `getkey' function.
+
+ \ Note that any menu item beyond 9 will have a numerical prefix on the
+ \ screen consisting of the first digit (ie. 1 for the tenth menu item)
+ \ and the key required to activate that menu item will be the decimal
+ \ ASCII of 48 plus the menu item (ie. 58 for the tenth item, aka. `:')
+ \ which is misleading and not desirable.
+ \
+ \ Thus, we do not allow more than 8 configurable items on the menu
+ \ (with "Reboot" as the optional ninth and highest numbered item).
+
+ \
+ \ Initialize the ACPI option status.
+ \
+ 0 menuacpi !
+ s" menu_acpi" getenv -1 <> if
+ c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
+ menuacpi !
+ arch-i386? if acpipresent? if
+ \
+ \ Set menu toggle state to active state
+ \ (required by generic toggle_menuitem)
+ \
+ acpienabled? menuacpi @ toggle_stateN !
+ then then
+ else
+ drop
+ then
+ then
+
+ \
+ \ Initialize kernel captions after parsing $kernels
+ \
+ 0 menukernel !
+ s" menu_kernel" getenv -1 <> if
+ c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
+ dup menukernel !
+ dup parse-kernels tag-kernels
+
+ \ Get the current cycle state (entry to use)
+ s" kernel_state" evaluate @ 48 + ( n -- n y )
+
+ \ If state is invalid, reset
+ dup kernmenuidx @ 1- > if
+ drop [char] 0 ( n y -- n 48 )
+ 0 s" kernel_state" evaluate !
+ over s" init_kernel" evaluate drop
+ then
+
+ \ Set the current non-ANSI caption
+ 2dup swap dup ( n y -- n y y n n )
+ s" set menu_caption[x]=$menu_caption[x][y]"
+ 17 +c! 34 +c! 37 +c! evaluate
+ ( n y y n n c-addr/u -- n y )
+
+ \ Set the current ANSI caption
+ 2dup swap dup ( n y -- n y y n n )
+ s" set ansi_caption[x]=$ansi_caption[x][y]"
+ 17 +c! 34 +c! 37 +c! evaluate
+ ( n y y n n c-addr/u -- n y )
+
+ \ Initialize cycle state from stored value
+ 48 - ( n y -- n k )
+ s" init_cyclestate" evaluate ( n k -- n )
+
+ \ Set $kernel to $kernel[y]
+ s" activate_kernel" evaluate ( n -- n )
+ then
+ drop
+ then
+
+ \
+ \ Initialize the menu_options visual separator.
+ \
+ 0 menuoptions !
+ s" menu_options" getenv -1 <> if
+ c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
+ menuoptions !
+ else
+ drop
+ then
+ then
+
+ \ 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
+ drop
+ s" Reboot" printmenuitem menureboot !
+ true menurebootadded !
+ then
+
+ menuX @
+ menurow @ 2 + menurow !
+ menurow @ menuY @ +
+ at-xy
+ s" menu_optionstext" getenv dup -1 <> if
+ type
+ else
+ drop ." Options:"
+ then
+ then
+
+ \ If this is the ACPI menu option, act accordingly.
+ dup menuacpi @ = if
+ 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
+ ansi_caption[x]
+ else
+ menu_caption[x]
+ then
+ then
+
+ dup -1 <> if
+ \ test for environment variable
+ getenv dup -1 <> if
+ printmenuitem ( c-addr/u -- n )
+ dup menukeyN !
+ else
+ drop
+ then
+ else
+ drop
+ then
+
+ 1+ dup 56 > \ add 1 to iterator, continue if less than 57
+ until
+ drop \ iterator
+
+ \ Optionally add a reboot option to the menu
+ menurebootadded @ true <> if
+ s" menu_reboot" getenv -1 <> if
+ drop \ no need for the value
+ s" Reboot" \ menu caption (required by printmenuitem)
+
+ printmenuitem
+ menureboot !
+ else
+ 0 menureboot !
+ then
+ then
+;
+
+\ Takes a single integer on the stack and updates the timeout display. The
+\ integer must be between 0 and 9 (we will only update a single digit in the
+\ source message).
+\
+: menu-timeout-update ( N -- )
+
+ \ Enforce minimum/maximum
+ dup 9 > if drop 9 then
+ dup 0 < if drop 0 then
+
+ s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u )
+
+ 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 )
+;
+
+\ This function blocks program flow (loops forever) until a key is pressed.
+\ The key that was pressed is added to the top of the stack in the form of its
+\ decimal ASCII representation. This function is called by the menu-display
+\ function. You need not call it directly.
+\
+: getkey ( -- ascii_keycode )
+
+ begin \ loop forever
+
+ menu_timeout_enabled @ 1 = if
+ ( -- )
+ seconds ( get current time: -- N )
+ dup menu_time @ <> if ( has time elapsed?: N N N -- N )
+
+ \ At least 1 second has elapsed since last loop
+ \ so we will decrement our "timeout" (really a
+ \ counter, insuring that we do not proceed too
+ \ fast) and update our timeout display.
+
+ menu_time ! ( update time record: N -- )
+ menu_timeout @ ( "time" remaining: -- N )
+ dup 0> if ( greater than 0?: N N 0 -- N )
+ 1- ( decrement counter: N -- N )
+ dup menu_timeout !
+ ( re-assign: N N Addr -- N )
+ then
+ ( -- N )
+
+ dup 0= swap 0< or if ( N <= 0?: N N -- )
+ \ halt the timer
+ 0 menu_timeout ! ( 0 Addr -- )
+ 0 menu_timeout_enabled ! ( 0 Addr -- )
+ then
+
+ \ update the timer display ( N -- )
+ menu_timeout @ menu-timeout-update
+
+ menu_timeout @ 0= if
+ \ We've reached the end of the timeout
+ \ (user did not cancel by pressing ANY
+ \ key)
+
+ s" menu_timeout_command" getenv dup
+ -1 = if
+ drop \ clean-up
+ else
+ evaluate
+ then
+ then
+
+ else ( -- N )
+ \ No [detectable] time has elapsed (in seconds)
+ drop ( N -- )
+ then
+ ( -- )
+ then
+
+ key? if \ Was a key pressed? (see loader(8))
+
+ \ An actual key was pressed (if the timeout is running,
+ \ kill it regardless of which key was pressed)
+ menu_timeout @ 0<> if
+ 0 menu_timeout !
+ 0 menu_timeout_enabled !
+
+ \ clear screen of timeout message
+ 0 menu-timeout-update
+ then
+
+ \ get the key that was pressed and exit (if we
+ \ get a non-zero ASCII code)
+ key dup 0<> if
+ exit
+ else
+ drop
+ then
+ then
+ 50 ms \ sleep for 50 milliseconds (see loader(8))
+
+ again
+;
+
+: menu-erase ( -- ) \ Erases menu and resets positioning variable to position 1.
+
+ \ Clear the screen area associated with the interactive menu
+ menuX @ menuY @
+ 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
+ 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
+ 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
+ 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
+ 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
+ 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces
+ 2drop
+
+ \ Reset the starting index and position for the menu
+ menu_start 1- menuidx !
+ 0 menurow !
+;
+
+only forth
+also menu-infrastructure
+also menu-namespace
+also menu-command-helpers definitions
+
+: toggle_menuitem ( N -- N ) \ toggles caption text and internal menuitem state
+
+ \ 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.
+
+ 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
+ \ called if the caption was NULL.
+
+ \ base name of environment variable
+ dup ( n -- n n ) \ key pressed
+ loader_color? if
+ ansi_caption[x]
+ else
+ menu_caption[x]
+ then
+ getenv dup -1 <> if
+
+ 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 )
+
+ \ Copy the current caption into our buffer
+ 2dup c! -rot \ store strlen at first byte
+ begin
+ rot 1+ \ bring alt addr to top and increment
+ -rot -rot \ bring buffer addr to top
+ 2dup c@ swap c! \ copy current character
+ 1+ \ increment buffer addr
+ rot 1- \ bring buffer len to top and decrement
+ dup 0= \ exit loop if buffer len is zero
+ until
+ 2drop \ buffer len/addr
+ drop \ alt addr
+
+ else
+ drop
+ then
+ then
+
+ \ Now we are certain to have init_textN populated with the initial
+ \ value of menu_caption[x] (ansi_caption[x] with loader_color enabled).
+ \ We can now use init_textN as the untoggled caption and
+ \ toggled_text[x] (toggled_ansi[x] with loader_color enabled) as the
+ \ toggled caption and store the appropriate value into menu_caption[x]
+ \ (again, ansi_caption[x] with loader_color enabled). Last, we'll
+ \ negate the toggled state so that we reverse the flow on subsequent
+ \ calls.
+
+ dup toggle_stateN @ 0= if
+ \ state is OFF, toggle to ON
+
+ dup ( n -- n n ) \ key pressed
+ loader_color? if
+ toggled_ansi[x]
+ else
+ toggled_text[x]
+ then
+ getenv dup -1 <> if
+ \ Assign toggled text to menu caption
+ 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
+ loader_color? if
+ ansi_caption[x]
+ else
+ menu_caption[x]
+ then
+ setenv
+ else
+ \ No toggled text, keep the same caption
+ 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
+
+ dup init_textN count ( n -- n c-addr/u )
+
+ \ Assign init_textN text to menu caption
+ 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
+ loader_color? if
+ ansi_caption[x]
+ else
+ menu_caption[x]
+ then
+ setenv
+
+ false \ new value of toggle state var (to be stored below)
+ then
+
+ \ now we'll store the new toggle state (on top of stack)
+ over toggle_stateN !
+;
+
+: cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem
+
+ \ 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.
+
+ 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 + ( n addr k -- n addr k k' )
+ \ duplicate array index and convert to ASCII numeral
+
+ 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y)
+ loader_color? if
+ ansi_caption[x][y]
+ else
+ menu_caption[x][y]
+ then
+ ( 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
+ \ enabled) as set in loader.rc(5), et. al.
+
+ getenv dup -1 = if
+ \ No caption set for this array index. Loop back to zero.
+
+ drop ( n addr k -1 -- n addr k ) \ getenv cruft
+ drop 0 ( n addr k -- n addr 0 ) \ new value to store later
+
+ 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y)
+ loader_color? if
+ ansi_caption[x][y]
+ else
+ menu_caption[x][y]
+ then
+ ( n addr 0 n 48 -- n addr 0 c-addr/u )
+ getenv dup -1 = if
+ \ Highly unlikely to occur, but to ensure things move
+ \ along smoothly, allocate a temporary NULL string
+ drop ( cruft ) s" "
+ 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
+ \ 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.
+
+ \ 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
+ ansi_caption[x]
+ else
+ menu_caption[x]
+ then
+ setenv
+
+ swap ! ( n addr k -- n ) \ update array state variable
+;
+
+only forth definitions also menu-infrastructure
+
+\ Erase and redraw the menu. Useful if you change a caption and want to
+\ update the menu to reflect the new value.
+\
+: menu-redraw ( -- )
+ menu-erase
+ menu-create
+;
+
+\ This function initializes the menu. Call this from your `loader.rc' file
+\ before calling any other menu-related functions.
+\
+: menu-init ( -- )
+ menu_start
+ 1- menuidx ! \ Initialize the starting index for the menu
+ 0 menurow ! \ Initialize the starting position for the menu
+
+ \ Assign configuration values
+ s" 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 !
+ s" 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 )
+ s" 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
+;
+
+also menu-namespace
+
+\ Main function. Call this from your `loader.rc' file.
+\
+: menu-display ( -- )
+
+ 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 )
+ drop ( just testing existence right now: Addr -- )
+
+ \ initialize state variables
+ seconds menu_time ! ( store the time we started )
+ 1 menu_timeout_enabled ! ( enable automatic timeout )
+
+ \ read custom time-duration (if set)
+ s" autoboot_delay" getenv dup -1 = if
+ drop \ no custom duration (remove dup'd bunk -1)
+ menu_timeout_default \ use default setting
+ else
+ 2dup ?number 0= if ( if not a number )
+ \ disable timeout if "NO", else use default
+ s" NO" compare-insensitive 0= if
+ 0 menu_timeout_enabled !
+ 0 ( assigned to menu_timeout below )
+ else
+ menu_timeout_default
+ then
+ else
+ -rot 2drop
+
+ \ boot immediately if less than zero
+ dup 0< if
+ drop
+ menu-create
+ 0 25 at-xy
+ 0 boot
+ then
+ then
+ then
+ menu_timeout ! ( store value on stack from above )
+
+ menu_timeout_enabled @ 1 = if
+ \ read custom column position (if set)
+ s" loader_menu_timeout_x" getenv dup -1 = if
+ drop \ no custom column position
+ menu_timeout_default_x \ use default setting
+ else
+ \ make sure custom position is a number
+ ?number 0= if
+ menu_timeout_default_x \ or use default
+ then
+ then
+ menu_timeout_x ! ( store value on stack from above )
+
+ \ read custom row position (if set)
+ s" loader_menu_timeout_y" getenv dup -1 = if
+ drop \ no custom row position
+ menu_timeout_default_y \ use default setting
+ else
+ \ make sure custom position is a number
+ ?number 0= if
+ menu_timeout_default_y \ or use default
+ then
+ then
+ menu_timeout_y ! ( store value on stack from above )
+ then
+ then
+
+ menu-create
+
+ begin \ Loop forever
+
+ 0 25 at-xy \ Move cursor to the bottom for output
+ getkey \ Block here, waiting for a key to be pressed
+
+ dup -1 = if
+ drop exit \ Caught abort (abnormal return)
+ then
+
+ \ Boot if the user pressed Enter/Ctrl-M (13) or
+ \ Ctrl-Enter/Ctrl-J (10)
+ dup over 13 = swap 10 = or if
+ drop ( no longer needed )
+ s" boot" evaluate
+ 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
+ dup menukeyN @
+ rot tuck = if
+
+ \ Adjust for missing ACPI menuitem on non-i386
+ arch-i386? true <> menuacpi @ 0<> and if
+ menuacpi @ over 2dup < -rot = or
+ over 58 < and if
+ ( key >= menuacpi && key < 58: N -- N )
+ 1+
+ then
+ then
+
+ \ Test for the environment variable
+ dup menu_command[x]
+ getenv dup -1 <> if
+ \ Execute the stored procedure
+ evaluate
+
+ \ We expect there to be a non-zero
+ \ value left on the stack after
+ \ executing the stored procedure.
+ \ If so, continue to run, else exit.
+
+ 0= if
+ drop \ key pressed
+ drop \ loop iterator
+ exit
+ else
+ swap \ need iterator on top
+ then
+ then
+
+ \ Re-adjust for missing ACPI menuitem
+ arch-i386? true <> menuacpi @ 0<> and if
+ swap
+ menuacpi @ 1+ over 2dup < -rot = or
+ over 59 < and if
+ 1-
+ then
+ swap
+ then
+ else
+ swap \ need iterator on top
+ then
+
+ \
+ \ Check for menu keycode shortcut(s)
+ \
+ dup menu_keycode[x]
+ getenv dup -1 = if
+ drop
+ else
+ ?number 0<> if
+ rot tuck = if
+ swap
+ dup menu_command[x]
+ getenv dup -1 <> if
+ evaluate
+ 0= if
+ 2drop
+ exit
+ then
+ else
+ drop
+ then
+ else
+ swap
+ then
+ then
+ then
+
+ 1+ dup 56 > \ increment iterator
+ \ continue if less than 57
+ until
+ drop \ loop iterator
+ drop \ key pressed
+
+ again \ Non-operational key was pressed; repeat
+;
+
+\ This function unsets all the possible environment variables associated with
+\ creating the interactive menu.
+\
+: menu-unset ( -- )
+
+ 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
+ begin
+ 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
+ \ cycle_menuitem caption and ANSI caption
+ 2dup menu_caption[x][y] unsetenv
+ 2dup ansi_caption[x][y] unsetenv
+ 1+ dup 57 >
+ until
+ drop \ inner iterator
+
+ 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
+
+ s" menu_timeout_command" unsetenv \ menu timeout command
+ s" menu_reboot" unsetenv \ Reboot menu option flag
+ s" menu_acpi" unsetenv \ ACPI menu option flag
+ s" menu_kernel" unsetenv \ Kernel menu option flag
+ s" menu_options" unsetenv \ Options separator flag
+ s" menu_optionstext" unsetenv \ separator display text
+ s" menu_init" unsetenv \ menu initializer
+
+ 0 menureboot !
+ 0 menuacpi !
+ 0 menuoptions !
+;
+
+only forth definitions also menu-infrastructure
+
+\ This function both unsets menu variables and visually erases the menu area
+\ in-preparation for another menu.
+\
+: menu-clear ( -- )
+ menu-unset
+ menu-erase
+;
+
+bullet menubllt !
+
+also menu-namespace
+
+\ 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 !
+0 toggle_state2 !
+0 toggle_state3 !
+0 toggle_state4 !
+0 toggle_state5 !
+0 toggle_state6 !
+0 toggle_state7 !
+0 toggle_state8 !
+
+\ Initialize our array state variables
+0 cycle_state1 !
+0 cycle_state2 !
+0 cycle_state3 !
+0 cycle_state4 !
+0 cycle_state5 !
+0 cycle_state6 !
+0 cycle_state7 !
+0 cycle_state8 !
+
+\ Initialize string containers
+0 init_text1 c!
+0 init_text2 c!
+0 init_text3 c!
+0 init_text4 c!
+0 init_text5 c!
+0 init_text6 c!
+0 init_text7 c!
+0 init_text8 c!
+
+only forth definitions
diff --git a/stand/forth/menu.4th.8 b/stand/forth/menu.4th.8
new file mode 100644
index 000000000000..3673eec74aa7
--- /dev/null
+++ b/stand/forth/menu.4th.8
@@ -0,0 +1,352 @@
+.\" Copyright (c) 2011-2013 Devin Teske
+.\" 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$
+.\"
+.Dd August 6, 2013
+.Dt MENU.4TH 8
+.Os
+.Sh NAME
+.Nm menu.4th
+.Nd FreeBSD dynamic menu boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to display a dynamic menu system managed through
+a system of carefully named environment variables.
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include menu.4th
+.Pp
+This line is present in the default
+.Pa /boot/menu.rc
+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 menu-init
+Draws the menu bounding box and initializes some internal state variables.
+This should be called before any other menu-related functions.
+.It Ic menu-display
+Displays the menu (configured via the below documented environment variables)
+and blocks on keyboard input, awaiting user action.
+.It Ic menu-erase
+Clears the screen area within the menu bounding box.
+.It Ic menu-redraw
+Calls
+.Ic menu-erase
+and then redraws the menu.
+.It Ic menu-unset
+Unsets the environment variables associated with individual menu items,
+clearing the way for a new menu.
+.It Ic menu-clear
+Calls
+.Ic menu-unset
+and then
+.Ic menu-erase .
+.El
+.Pp
+The environment variables that effect its behavior are:
+.Bl -tag -width bootfile -offset indent
+.It Va loader_color
+If set to
+.Dq Li NO
+(case-insensitive) or
+.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
+Number of seconds
+.Ic menu-display
+will wait before executing
+.Va menu_timeout_command
+.Ic ( boot
+by default) unless a key is pressed.
+If set to
+.Dq Li NO
+(case-insensitive)
+.Ic menu-display
+will wait for user input and never execute
+.Ic menu_timeout_command .
+If set to
+.Dq Li -1 ,
+.Ic menu-display
+will boot immediately, preventing both interruption of the
+.Ic autoboot
+process and escaping to the loader prompt.
+Default is
+.Dq Li 10 .
+See
+.Xr loader 8
+for additional information.
+.It Va menu_timeout_command
+The command to be executed after
+.Va autoboot_delay
+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.
+.It Va loader_menu_timeout_y
+Sets the desired row position of the timeout countdown text.
+Default is 23.
+.It Va loader_menu_title
+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 .
+.It Va menu_command[x]
+The command to be executed when the number associated with menuitem
+.Dq Li x
+is pressed.
+See the list of included FICL words below for some ideas.
+.It Va menu_keycode[x]
+An optional decimal ASCII keycode to be associated with menuitem
+.Dq Li x .
+When pressed, will cause the execution of
+.Va menu_command[x] .
+.It Va ansi_caption[x]
+If
+.Va loader_color
+is set
+.Pq enabled by default ,
+use this caption for menuitem
+.Dq Li x
+instead of
+.Va menu_caption[x] .
+.It Va toggled_text[x]
+For menuitems where
+.Va menu_command[x]
+is set to
+.Dq Li toggle_menuitem
+(or a derivative thereof), the text displayed
+will toggle between this and
+.Va menu_caption[x] .
+.It Va toggled_ansi[x]
+Like
+.Va toggled_text[x]
+except used when
+.Va loader_color
+is enabled
+.Pq default .
+.It Va menu_caption[x][y]
+For menuitems where
+.Va menu_command[x]
+is set to
+.Dq Li cycle_menuitem
+(or a derivative thereof), the text displayed will cycle between this and other
+.Va menu_caption[x][y]
+entries.
+.It Va ansi_caption[x][y]
+Like
+.Va menu_caption[x][y]
+except used when
+.Va loader_color
+is enabled
+.Pq default .
+.It Va menu_acpi
+When set to a number
+.Dq Li x
+associated with a given menuitem, that menuitem will only appear when
+running on i386-compatible hardware,
+.Va hint.acpi.0.rsdp
+is set (indicating the presence of hardware ACPI support as detected by
+.Xr loader 8 ) ,
+and
+.Va hint.acpi.0.disabled
+is not set.
+On non-i386 hardware, menuitems configured after the
+.Dq Li menu_acpi
+menuitem will use a lower number (to compensate for the missing ACPI menuitem)
+but continue to function as expected.
+On i386-compatible hardware lacking ACPI support (as detected by
+.Xr loader 8 ) ,
+subsequent menuitems will retain their associated numbers.
+.It Va hint.acpi.0.rsdp
+Set automatically by
+.Xr loader 8
+on i386-compatible hardware when ACPI support is detected at boot time.
+Effects the display of the
+.Dq Li menu_acpi
+menuitem (if configured).
+.It Va hint.acpi.0.disabled
+Effects the display of the
+.Va menu_acpi
+menuitem.
+If set, the menuitem will display
+.Va toggled_text[x]
+.Va ( toggled_ansi[x]
+if
+.Va loader_color
+is set), otherwise
+.Va menu_caption[x]
+.Va ( ansi_caption[x]
+if
+.Va loader_color
+is set).
+.It Va menu_options
+When set to a number
+.Dq Li x ,
+a single blank-line and an
+.Dq Li Options
+header are inserted between
+.Va menu_caption[x-1]
+and
+.Va menu_caption[x]
+(if configured).
+.It Va menu_reboot
+If set, adds a built-in
+.Dq Li Reboot
+menuitem to the end of the last configured menuitem.
+If
+.Va menu_options
+is configured, the
+.Dq Li Reboot
+menuitem will be inserted before the
+.Dq Options
+separator.
+.El
+.Pp
+In addition, it provides the following FICL words:
+.Pp
+.Bl -tag -width disable-module_module -compact -offset indent
+.It Ic arch-i386? ( -- BOOL )
+Returns true (-1) on i386 and false (0) otherwise.
+.It Ic acpipresent? ( -- BOOL )
+Returns true (-1) if ACPI is present and false (0) otherwise.
+.It Ic acpienabled? ( -- BOOL )
+Returns true (-1) if ACPI is enabled and false (0) otherwise.
+.It Ic toggle_menuitem ( N -- N )
+Toggles menuitem
+.Dq Li N
+between
+.Va menu_caption[x]
+and
+.Va toggled_text[x]
+(where
+.Dq Li N
+represents the ASCII decimal value for
+.Dq Li x ) .
+.It Ic cycle_menuitem ( N -- N )
+Cycles menuitem
+.Dq Li N
+between
+.Va menu_caption[x][y]
+entries (where
+.Va N
+represents the ASCII decimal value for
+.Va x ) .
+.El
+.Pp
+For all values of
+.Dq Li x
+above, use any number between 1 through 9. Sorry, double-digits are not
+currently supported.
+.Sh FILES
+.Bl -tag -width /boot/loader.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/menu.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+A simple boot menu:
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/menu.4th
+menu-init
+set menu_caption[1]="Boot"
+set menu_command[1]="boot"
+set menu_options=2
+set menu_caption[2]="Option: NO"
+set toggled_text[2]="Option: YES"
+set menu_command[2]="toggle_menuitem"
+set menu_timeout_command="boot"
+set menu_reboot
+menu-display
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr beastie.4th 8 ,
+.Xr loader 8 ,
+.Xr loader.4th 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/menu.rc b/stand/forth/menu.rc
new file mode 100644
index 000000000000..6fe3dfe14281
--- /dev/null
+++ b/stand/forth/menu.rc
@@ -0,0 +1,202 @@
+\ Menu.rc
+\ $FreeBSD$
+\
+\ You should not edit this file! Put any overrides in menu.rc.local
+\ instead as this file can be replaced during system updates.
+\
+\ Load required Forth modules
+include /boot/version.4th
+include /boot/brand.4th
+include /boot/menu.4th
+include /boot/menu-commands.4th
+include /boot/shortcuts.4th
+
+\ Screen prep
+clear \ clear the screen (see `screen.4th')
+print_version \ print version string (bottom-right; see `version.4th')
+draw-beastie \ draw freebsd mascot (on right; see `beastie.4th')
+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 `non-ansi' variants, add `loader_color=0' to loader.conf(5)
+\ NOTE: ANSI variants can use `^' in place of literal `Esc' (ASCII 27)
+
+\
+\ 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]="^[1mB^[moot Multi User ^[1m[Enter]^[m"
+set maintoggled_ansi[1]="Boot ^[1mS^[mingle User ^[1m[Enter]^[m"
+\ 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 ^[1mS^[mingle User"
+set maintoggled_ansi[2]="Boot ^[1mM^[multi User"
+\ keycode set by init_altboot
+
+set mainmenu_caption[3]="[Esc]ape to loader prompt"
+set mainmenu_command[3]="goto_prompt"
+set mainmenu_keycode[3]=27
+set mainansi_caption[3]="^[1mEsc^[mape to loader prompt"
+
+\ Enable built-in "Reboot" trailing menuitem
+\ NOTE: appears before menu_options if configured
+\
+set mainmenu_reboot
+
+\ Enable "Options:" separator. When set to a numerical value (1-8), a visual
+\ separator is inserted before that menuitem number.
+\
+set mainmenu_options=5
+
+set mainmenu_kernel=5
+set mainmenu_command[5]="cycle_kernel"
+set mainmenu_keycode[5]=107
+
+set mainmenu_caption[6]="Configure Boot [O]ptions..."
+set mainmenu_command[6]="2 goto_menu"
+set mainmenu_keycode[6]=111
+set mainansi_caption[6]="Configure Boot ^[1mO^[mptions..."
+
+s" currdev" getenv dup 0> [if] drop 4 s" zfs:" compare 0= [if]
+ set mainmenu_caption[7]="Select Boot [E]nvironment..."
+ set mainmenu_command[7]="3 goto_menu"
+ set mainmenu_keycode[7]=101
+ set mainansi_caption[7]="Select Boot ^[1mE^[37mnvironment..."
+
+ s" chain_disk" getenv? [if]
+ set mainmenu_caption[8]="Chain[L]oad ${chain_disk}"
+ set mainmenu_command[8]="chain ${chain_disk}"
+ set mainmenu_keycode[8]=108
+ set mainansi_caption[8]="Chain^[1mL^[moad ${chain_disk}"
+ [then]
+[else]
+ s" chain_disk" getenv? [if]
+ set mainmenu_caption[7]="Chain[L]oad ${chain_disk}"
+ set mainmenu_command[7]="chain ${chain_disk}"
+ set mainmenu_keycode[7]=108
+ set mainansi_caption[7]="Chain^[1mL^[moad ${chain_disk}"
+ [then]
+[then] [else] drop [then]
+
+
+\
+\ 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 ^[1m[Backspace]^[m"
+
+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 ^[1mD^[mefaults"
+
+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]="^[1mA^[mCPI Support ^[34;1mOff^[m"
+set optionstoggled_ansi[3]="^[1mA^[mCPI Support ^[32;7mOn^[m"
+
+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 ^[1mM^[mode... ^[34;1mOff^[m"
+set optionstoggled_ansi[4]="Safe ^[1mM^[mode... ^[32;7mOn^[m"
+
+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]="^[1mS^[mingle User. ^[34;1mOff^[m"
+set optionstoggled_ansi[5]="^[1mS^[mingle User. ^[32;7mOn^[m"
+
+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]="^[1mV^[merbose..... ^[34;1mOff^[m"
+set optionstoggled_ansi[6]="^[1mV^[merbose..... ^[32;7mOn^[m"
+
+\
+\ BOOT ENVIRONMENT MENU
+\
+
+set menuset_name3="bootenv"
+
+set bemenu_current="Active: "
+set beansi_current="^[1m${bemenu_current}^[m"
+set bemenu_bootfs="bootfs: "
+set beansi_bootfs="^[1m${bemenu_bootfs}^[m"
+set bemenu_page="[P]age: "
+set beansi_page="^[1mP^[mage: "
+set bemenu_pageof=" of "
+set beansi_pageof="${bemenu_pageof}"
+set zfs_be_currpage=1
+
+set bootenvmenu_init="init_bootenv"
+
+set bootenvmenu_command[1]="be_draw_screen 1 goto_menu"
+set bootenvmenu_keycode[1]=8
+
+set bootenvmenu_command[2]="set_bootenv"
+set bootenvmenu_keycode[2]=97
+set bootenv_root[2]="${zfs_be_active}"
+
+set bootenvmenu_command[3]="set_be_page"
+set bootenvmenu_keycode[3]=112
+
+set bootenvmenu_options=4
+set bootenvmenu_optionstext="Boot Environments:"
+
+\ Enable automatic booting (add ``autoboot_delay=N'' to loader.conf(5) to
+\ customize the timeout; default is 10-seconds)
+\
+set menu_timeout_command="boot"
+
+\ Include optional elements defined in a local file
+\
+try-include /boot/menu.rc.local
+
+\ Initialize boot environment variables
+\
+s" reloadbe" sfind ( xt|0 bool ) [if]
+ s" bootenv_autolist" getenv dup -1 = [if]
+ drop s" execute" evaluate \ Use evaluate to avoid passing
+ \ reloadbe an optional parameter
+ [else]
+ s" YES" compare-insensitive 0= [if]
+ s" execute" evaluate
+ [then]
+ [then]
+[else]
+ drop ( xt=0 )
+[then]
+
+\ Display the main menu (see `menu.4th')
+set menuset_initial=1
+menuset-loadinitial
+menu-display
diff --git a/stand/forth/menusets.4th b/stand/forth/menusets.4th
new file mode 100644
index 000000000000..9335b80d511a
--- /dev/null
+++ b/stand/forth/menusets.4th
@@ -0,0 +1,624 @@
+\ 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
+
+vocabulary menusets-infrastructure
+only forth also menusets-infrastructure definitions
+
+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_kernel -> menu_kernel
+ \ 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_kernel -> menu_kernel
+ \ {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
+;
+
+only forth definitions also menusets-infrastructure
+
+: 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 menuset_y tuck c! 1 s" y" setenv
+ \ set inner loop iterator and $y
+
+ \ ... menu_caption[x][y] ...
+ menuset-loadmenuxyvar
+
+ \ ... ansi_caption[x][y] ...
+ menuset-loadansixyvar
+
+ 1+ dup 57 > ( x y -- y' 0|-1 ) \ increment and test
+ until
+ drop ( x y -- x )
+
+ \ ... menu_command[x] ...
+ s" set var=command" evaluate
+ menuset-loadmenuxvar
+
+ \ ... menu_init[x] ...
+ s" set var=init" evaluate
+ menuset-loadmenuxvar
+
+ \ ... menu_keycode[x] ...
+ s" set var=keycode" evaluate
+ menuset-loadmenuxvar
+
+ \ ... toggled_text[x] ...
+ s" set var=text" evaluate
+ menuset-loadtoggledxvar
+
+ \ ... toggled_ansi[x] ...
+ s" set var=ansi" evaluate
+ menuset-loadtoggledxvar
+
+ 1+ dup 56 > ( x -- x' 0|-1 ) \ increment iterator
+ \ continue if less than 57
+ until
+ drop ( x -- ) \ loop iterator
+
+ \ ... menu_reboot ...
+ s" set var=reboot" evaluate
+ menuset-loadmenuvar
+
+ \ ... menu_acpi ...
+ s" set var=acpi" evaluate
+ menuset-loadmenuvar
+
+ \ ... menu_kernel ...
+ s" set var=kernel" evaluate
+ menuset-loadmenuvar
+
+ \ ... menu_options ...
+ s" set var=options" evaluate
+ menuset-loadmenuvar
+
+ \ ... menu_optionstext ...
+ s" set var=optionstext" evaluate
+ menuset-loadmenuvar
+
+ menuset-cleanup
+;
+
+: menusets-unset ( -- )
+
+ s" menuset_initial" unsetenv
+
+ 1 begin
+ dup menuset-checksetnum ( n n -- n )
+
+ dup menuset-setnum-namevar ( n n -- n )
+ unsetenv
+
+ \ If the current menuset does not populate the first menuitem,
+ \ we stop completely.
+
+ menuset_use_name @ true = if
+ s" set buf=${affix}menu_caption[1]"
+ else
+ s" set buf=menuset${affix}_caption[1]"
+ then
+ evaluate s" buf" getenv getenv -1 = if
+ drop ( n -- )
+ s" buf" unsetenv
+ menuset-cleanup
+ exit
+ else
+ drop ( n c-addr2 -- n ) \ unused
+ then
+
+ [char] 1 ( n -- n x ) \ Loop range ASCII '1' (49) to '8' (56)
+ begin
+ dup menuset_x tuck c! 1 s" x" setenv \ set $x to x
+
+ s" set var=caption" evaluate
+ menuset-unloadmenuxvar
+ menuset-unloadmenuxvar
+ menuset-unloadansixvar
+ [char] 0 ( n x -- n x y ) \ Inner loop '0' to '9'
+ begin
+ dup menuset_y tuck c! 1 s" y" setenv
+ \ sets $y to y
+ menuset-unloadmenuxyvar
+ menuset-unloadansixyvar
+ 1+ dup 57 > ( n x y -- n x y' 0|-1 )
+ until
+ drop ( n x y -- n x )
+ s" set var=command" evaluate menuset-unloadmenuxvar
+ s" set var=init" evaluate menuset-unloadmenuxvar
+ s" set var=keycode" evaluate menuset-unloadmenuxvar
+ s" set var=text" evaluate menuset-unloadtoggledxvar
+ s" set var=ansi" evaluate menuset-unloadtoggledxvar
+
+ 1+ dup 56 > ( x -- x' 0|-1 ) \ increment and test
+ until
+ drop ( n x -- n ) \ loop iterator
+
+ s" set var=acpi" evaluate menuset-unloadmenuvar
+ s" set var=init" evaluate menuset-unloadmenuvar
+ s" set var=kernel" evaluate menuset-unloadmenuvar
+ s" set var=options" evaluate menuset-unloadmenuvar
+ s" set var=optionstext" evaluate menuset-unloadmenuvar
+ s" set var=reboot" evaluate menuset-unloadmenuvar
+
+ 1+ dup 65535 > ( n -- n' 0|-1 ) \ increment and test
+ until
+ drop ( n' -- ) \ loop iterator
+
+ s" buf" unsetenv
+ menuset-cleanup
+;
+
+only forth definitions
+
+: menuset-loadinitial ( -- )
+ s" menuset_initial" getenv dup -1 <> if
+ ?number 0<> if
+ menuset-loadsetnum
+ then
+ else
+ drop \ cruft
+ then
+;
diff --git a/stand/forth/menusets.4th.8 b/stand/forth/menusets.4th.8
new file mode 100644
index 000000000000..f785ae18eabe
--- /dev/null
+++ b/stand/forth/menusets.4th.8
@@ -0,0 +1,372 @@
+.\" Copyright (c) 2012 Devin Teske
+.\" 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$
+.\"
+.Dd November 5, 2012
+.Dt MENUSETS.4TH 8
+.Os
+.Sh NAME
+.Nm menusets.4th
+.Nd FreeBSD dynamic submenu boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to add submenu functionality to the dynamic menu
+system provided by
+.Xr menu.4th 8 .
+Submenus are managed through a system of carefully named environment variables.
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the examples below for the most common situations, and to
+.Xr menu.4th 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include menusets.4th
+.Pp
+This line is present in the default
+.Pa /boot/menu-commands.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 menuset-loadinitial -compact -offset indent
+.It Ic menuset-loadsetnum
+Takes a single integer on the stack to identify the menuset environment
+variables to be activated (see environment variables below).
+.It Ic menuset-loadinitial
+If $menuset_initial is set, passes the value to menuset-loadsetnum.
+The value must be a number.
+.It Ic menusets-unset
+Unsets the environment variables associated with all menusets.
+Increments starting at 1 and stops at the first unconfigured menuset.
+A menuset is considered configured if the caption for item 1 is set.
+.El
+.Pp
+The environment variables that effect its behavior are:
+.Bl -tag -width bootfile -offset indent
+.It Va menuset_initial
+Number to pass to menuset-loadsetnum when menuset-loadinitial is called.
+.It Va menuset_nameN
+Used to give a name to a menuset.
+.El
+.Pp
+When a menuset is NOT given a name (the default),
+menuset N is comprised of the following environment variables:
+.Pp
+.Bl -tag -width menusetN_caption[x][y] -compact -offset indent
+.It Va ansisetN_caption[x]
+-> ansi_caption[x]
+.It Va ansisetN_caption[x][y]
+-> ansi_caption[x][y]
+.It Va menusetN_acpi
+-> menu_acpi
+.It Va menusetN_caption[x]
+-> menu_caption[x]
+.It Va menusetN_caption[x][y]
+-> menu_caption[x][y]
+.It Va menusetN_command[x]
+-> menu_command[x]
+.It Va menusetN_init
+->
+.Dq Li evaluated
+.It Va menusetN_init[x]
+-> menu_init[x]
+.It Va menusetN_keycode[x]
+-> menu_keycode[x]
+.It Va menusetN_options
+-> menu_options
+.It Va menusetN_optionstext
+-> menu_optionstext
+.It Va menusetN_reboot
+-> menu_reboot
+.It Va toggledsetN_ansi[x]
+-> toggled_ansi[x]
+.It Va toggledsetN_text[x]
+-> toggled_text[x]
+.El
+.Pp
+When you choose to give a menuset a name (by setting $menuset_nameN),
+menuset N is instead comprised of the following environment variables:
+.Pp
+.Bl -tag -width NAMEmenu_caption[x][y] -compact -offset indent
+.It Va NAMEansi_caption[x]
+-> ansi_caption[x]
+.It Va NAMEansi_caption[x][y]
+-> ansi_caption[x][y]
+.It Va NAMEmenu_acpi
+-> menu_acpi
+.It Va NAMEmenu_caption[x]
+-> menu_caption[x]
+.It Va NAMEmenu_caption[x][y]
+-> menu_caption[x][y]
+.It Va NAMEmenu_command[x]
+-> menu_command[x]
+.It Va NAMEmenu_init
+->
+.Dq Li evaluated
+.It Va NAMEmenu_init[x]
+-> menu_init[x]
+.It Va NAMEmenu_keycode[x]
+-> menu_keycode[x]
+.It Va NAMEmenu_options
+-> menu_options
+.It Va NAMEmenu_optionstext
+-> menu_optionstext
+.It Va NAMEmenu_reboot
+-> menu_reboot
+.It Va NAMEtoggled_ansi[x]
+-> toggled_ansi[x]
+.It Va NAMEtoggled_text[x]
+-> toggled_text[x]
+.El
+.Pp
+where
+.Dq Li NAME
+is the value of $menuset_nameN.
+In the case of $NAMEmenu_init ($menusetN_init when $menuset_nameN is unset),
+the value is evaluated as an FICL statement.
+This can be used to dynamically adjust the menuset variables right before the
+menu is activated.
+.Pp
+In addition,
+.Nm
+provides the following FICL words:
+.Pp
+.Bl -tag -width menuset -compact -offset indent
+.It Ic menuset-checksetnum ( N -- )
+Given a single integer on the stack, sets a global variable
+.Va menuset_use_name
+to a boolean based on whether $menuset_nameN is set (true) or not (false).
+Also sets $affix temporary variable (prefix or infix depending on
+menuset_use_name).
+Automatically called by menuset-loadsetnum and menusets-unset.
+.It Ic menuset-loadvar ( -- )
+Used indirectly to shorten syntax and mitigate dictionary size.
+Requires the following temporary environment variables:
+.Pp
+.Bl -tag -width affix -compact -offset indent
+.It Va type
+should be set to one of: menu toggled ansi
+.It Va var
+should be set to one of: caption command keycode text ...
+.It Va affix
+either a prefix (menuset_use_name is true) or infix (menuset_use_name is false)
+.El
+.Pp
+If the global
+.Va menuset_use_name
+is true, the variable ${type}_${var} is made to
+equal the value of the variable ${affix}${type}_${var}
+(note: in this case menuset-checksetnum has set $affix to $menuset_nameN).
+Otherwise (when
+.Va menuset_use_name
+is false), the variable ${type}_${var} is made to
+equal the value of the variable ${type}set${affix}_${var}
+(note: in this case menuset-checksetnum has set $affix to N).
+.Pp
+Both the global variable
+.Va menuset_use_name
+and the environment variable $affix are automatically handled by
+menuset-checksetnum above (which is automatically called by
+menuset-loadsetnum).
+.It Ic menuset-unloadvar ( -- )
+Used indirectly to shorten syntax and mitigate dictionary size.
+Like menuset-loadvar except it unsets the menuset variable.
+If global
+.Va menuset_use_name
+is true ($affix is $menuset_nameN),
+variable ${affix}${type}_${var} is unset.
+Otherwise, $affix is N and variable ${type}set${affix}_${var} is unset.
+.It Ic menuset-loadmenuvar ( -- )
+Sets $type to
+.Dq menu
+and calls menuset-loadvar.
+.It Ic menuset-unloadmenuvar ( -- )
+Sets $type to
+.Dq menu
+and calls menuset-unloadvar.
+.It Ic menuset-loadxvar ( -- )
+Like menuset-loadvar except it takes an additional temporary variable $x.
+If the global
+.Va menuset_use_name
+is true (making $affix equal $menuset_nameN),
+sets variable ${type}_${var}[${x}] to variable ${affix}${type}_${var}[${x}].
+Otherwise ($affix being N), sets the same variable to instead
+${type}set{affix}_${var}[${x}].
+.It Ic menuset-unloadxvar ( -- )
+Like menuset-loadxvar except it unsets the menuset variable.
+If global
+.Va menuset_use_name
+is true, unsets ${affix}${type}_${var}[${x}].
+Otherwise, unsets ${type}set${affix}_${var}[${x}].
+.It Ic menuset-loadansixvar ( -- )
+Sets $type to
+.Dq ansi
+and calls menuset-loadxvar
+.It Ic menuset-unloadansixvar ( -- )
+Sets $type to
+.Dq ansi
+and calls menuset-unloadxvar
+.It Ic menuset-loadmenuxvar ( -- )
+Sets $type to
+.Dq ansi
+and calls menuset-loadxvar
+.It Ic menuset-unloadmenuxvar ( -- )
+Sets $type to
+.Dq ansi
+and calls menuset-unloadxvar
+.It Ic menuset-loadtoggledxvar ( -- )
+Sets $type to
+.Dq toggled
+and calls menuset-loadxvar
+.It Ic menuset-unloadtoggledxvar ( -- )
+Sets $type to
+.Dq toggled
+and calls menuset-unloadxvar
+.It Ic menuset-loadxyvar ( -- )
+Like menuset-loadxvar except it takes an additional temporary variable $y.
+If the global
+.Va menuset_use_name
+is true ($affix is $menuset_nameN),
+sets variable ${type}_${var}[${x}][${y}] to ${affix}${type}_${var}[${x}][${y}].
+Otherwise ($affix is N) sets the same variable to instead
+${type}set${affix}_${var}[${x}][${y}].
+.It Ic menuset-unloadxyvar ( -- )
+Like menuset-loadxyvar except it unsets the menuset variable.
+If the global
+.Va menuset_use_name
+is true, unsets ${affix}${type}_${var}[${x}][${y}].
+Otherwise, unsets ${type}set${affix}_${var}[${x}][${y}].
+.It Ic menuset-loadansixyvar ( -- )
+Sets $type to
+.Dq ansi
+and calls menuset-loadxyvar.
+.It Ic menuset-unloadansixyvar ( -- )
+Sets $type to
+.Dq ansi
+and calls menuset-unloadxyvar.
+.It Ic menuset-loadmenuxyvar ( -- )
+Sets $type to
+.Dq menu
+and calls menuset-loadxyvar.
+.It Ic menuset-unloadmenuxyvar ( -- )
+Sets $type to
+.Dq menu
+and calls menuset-unloadxyvar.
+.It Ic menuset-setnum-namevar ( N -- C-Addr/U )
+Takes a single integer on the stack and replaces it with a string (in c-addr/u
+format) whose value is
+.Dq menuset_nameN .
+For example, if given 1 returns
+.Dq menuset_name1 .
+.It Ic menuset-cleanup ( N -- )
+Unsets all the various temporary variables, currently
+.Va type ,
+.Va var ,
+.Va x ,
+.Va y ,
+and
+.Va affix .
+.El
+.Pp
+For all values of
+.Dq Li x
+above, use any number between 1 through 9. Sorry, double-digits are not
+currently supported.
+For all values of
+.Dq Li N
+above, use any number between 1 and 65535.
+.Sh FILES
+.Bl -tag -width /boot/menu-commands.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/menu.4th
+Dynamic menu module.
+.It Pa /boot/menu-commands.4th
+Contains the goto_menu command.
+.It Pa /boot/menusets.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+A simple boot menu with a submenu:
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/menu.4th
+include /boot/menu-commands.4th
+menu-init
+set menuset1_caption[1]="Boot"
+set menuset1_command[1]="boot"
+set menuset1_caption[2]="Submenu..."
+set menuset1_command[2]="2 goto_menu"
+set menuset2_caption[1]="Back"
+set menuset2_command[1]="1 goto_menu"
+set menuset_initial=2
+menuset-loadinitial
+menu-display
+.Ed
+.Pp
+The same boot menu with named menusets:
+.Pp
+.Bd -literal -offset indent -compact
+include /boot/menu.4th
+include /boot/menu-commands.4th
+menu-init
+set menuset_name1=main
+set mainmenu_caption[1]="Boot"
+set mainmenu_command[1]="boot"
+set mainmenu_caption[2]="Submenu..."
+set mainmenu_command[2]="2 goto_menu"
+set menuset_name2=sub
+set submenu_caption[1]="Back"
+set submenu_command[1]="1 goto_menu"
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr beastie.4th 8 ,
+.Xr loader 8 ,
+.Xr loader.4th 8 ,
+.Xr menu.4th 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .
diff --git a/stand/forth/pcibios.4th b/stand/forth/pcibios.4th
new file mode 100644
index 000000000000..71702dad8a0c
--- /dev/null
+++ b/stand/forth/pcibios.4th
@@ -0,0 +1,47 @@
+\ Copyright (c) 2014 M. Warner Losh <imp@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$
+
+only forth also support-functions also builtins definitions
+
+\ pci-device-count pci-id
+\
+\ Counts the number of instances of pci-id in the system and reports
+\ it to the user.
+: pci-device-count
+ 0= if ( interpreted ) get_arguments then
+
+ 0= if ." Need an argument" cr abort then
+ \ First argument is 0 when we're interprated. See support.4th
+ \ for get_arguments reading the rest of the line and parsing it
+ \ stack: argN lenN ... arg1 len1 N
+ hex ?number decimal
+ 0= if ." Bad pci-id given (must be legal hex value)" cr abort then
+ dup pcibios-device-count ." Found " . ." instances of " hex . decimal cr
+;
+
+also forth definitions also builtins
+
+builtin: pci-device-count
diff --git a/stand/forth/pnp.4th b/stand/forth/pnp.4th
new file mode 100644
index 000000000000..4aa4bcf2ac21
--- /dev/null
+++ b/stand/forth/pnp.4th
@@ -0,0 +1,205 @@
+\ Copyright (c) 2000 Daniel C. Sobral <dcs@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$
+
+
+\ The following pnp code is used in pnp.4th and pnp.c
+structure: STAILQ_HEAD
+ ptr stqh_first \ type*
+ ptr stqh_last \ type**
+;structure
+
+structure: STAILQ_ENTRY
+ ptr stqe_next \ type*
+;structure
+
+structure: pnphandler
+ ptr pnph.name
+ ptr pnph.enumerate
+;structure
+
+structure: pnpident
+ ptr pnpid.ident \ char*
+ sizeof STAILQ_ENTRY cells member: pnpid.link \ pnpident
+;structure
+
+structure: pnpinfo \ sync with stand/common/bootstrap.h
+ ptr pnpi.desc
+ int pnpi.revision
+ ptr pnpi.module \ (char*) module args
+ int pnpi.argc
+ ptr pnpi.argv
+ ptr pnpi.handler \ pnphandler
+ sizeof STAILQ_HEAD member: pnpi.ident \ pnpident
+ sizeof STAILQ_ENTRY member: pnpi.link \ pnpinfo
+;structure
+\ end of pnp support
+
+pnpdevices drop
+
+: enumerate
+ pnphandlers begin
+ dup @
+ while
+ ." Probing " dup @ pnph.name @ dup strlen type ." ..." cr
+ 0 over @ pnph.enumerate @ ccall drop
+ cell+
+ repeat
+;
+
+: summary
+ ." PNP scan summary:" cr
+ pnpdevices stqh_first @
+ begin
+ dup
+ while
+ dup pnpi.ident stqh_first @ pnpid.ident @ dup strlen type
+ dup pnpi.desc @ ?dup if
+ ." : "
+ dup strlen type
+ then
+ cr
+ pnpi.link stqe_next @
+ repeat
+ drop
+;
+
+: compare-pnpid ( addr addr' -- flag )
+ begin
+ over c@ over c@ <> if drop drop false exit then
+ over c@ over c@ and
+ while
+ char+ swap char+ swap
+ repeat
+ c@ swap c@ or 0=
+;
+
+: search-pnpid ( id -- flag )
+ >r
+ pnpdevices stqh_first @
+ begin ( pnpinfo )
+ dup
+ while
+ dup pnpi.ident stqh_first @
+ begin ( pnpinfo pnpident )
+ dup pnpid.ident @ r@ compare-pnpid
+ if
+ r> drop
+ \ XXX Temporary debugging message
+ ." Found " pnpid.ident @ dup strlen type
+ pnpi.desc @ ?dup if
+ ." : " dup strlen type
+ then cr
+ \ drop drop
+ true
+ exit
+ then
+ pnpid.link stqe_next @
+ ?dup 0=
+ until
+ pnpi.link stqe_next @
+ repeat
+ r> drop
+ drop
+ false
+;
+
+: skip-space ( addr -- addr' )
+ begin
+ dup c@ bl =
+ over c@ 9 = or
+ while
+ char+
+ repeat
+;
+
+: skip-to-space ( addr -- addr' )
+ begin
+ dup c@ bl <>
+ over c@ 9 <> and
+ over c@ and
+ while
+ char+
+ repeat
+;
+
+: premature-end? ( addr -- addr flag )
+ postpone dup postpone c@ postpone 0=
+ postpone if postpone exit postpone then
+; immediate
+
+0 value filename
+0 value timestamp
+0 value id
+
+only forth also support-functions
+
+: (load) load ;
+
+: check-pnpid ( -- )
+ line_buffer .addr @
+ \ Search for filename
+ skip-space premature-end?
+ dup to filename
+ \ Search for end of filename
+ skip-to-space premature-end?
+ 0 over c! char+
+ \ Search for timestamp
+ skip-space premature-end?
+ dup to timestamp
+ skip-to-space premature-end?
+ 0 over c! char+
+ \ Search for ids
+ begin
+ skip-space premature-end?
+ dup to id
+ skip-to-space dup c@ >r
+ 0 over c! char+
+ id search-pnpid if
+ filename dup strlen 1 ['] (load) catch if
+ drop drop drop
+ ." Error loading " filename dup strlen type cr
+ then
+ r> drop exit
+ then
+ r> 0=
+ until
+;
+
+: load-pnp
+ 0 to end_of_file?
+ reset_line_reading
+ s" /boot/pnpid.conf" O_RDONLY fopen fd !
+ fd @ -1 <> if
+ begin
+ end_of_file? 0=
+ while
+ read_line
+ check-pnpid
+ repeat
+ fd @ fclose
+ then
+;
+
diff --git a/stand/forth/screen.4th b/stand/forth/screen.4th
new file mode 100644
index 000000000000..e0af82b3a8b8
--- /dev/null
+++ b/stand/forth/screen.4th
@@ -0,0 +1,74 @@
+\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
+\ Copyright (c) 2015 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-screen.4th
+
+\ emit Esc-[
+: escc ( -- ) 27 emit [char] [ emit ;
+
+\ Home cursor ( Esc-[H )
+: ho ( -- ) escc [char] H emit ;
+
+\ Clear from current position to end of display ( Esc-[J )
+: cld ( -- ) escc [char] J emit ;
+
+\ clear screen
+: clear ( -- ) ho cld ;
+
+\ move cursor to x rows, y cols (1-based coords) ( Esc-[%d;%dH )
+: at-xy ( x y -- ) escc .# [char] ; emit .# [char] H emit ;
+
+\ Set foreground color ( Esc-[3%dm )
+: fg ( x -- ) escc 3 .# .# [char] m emit ;
+
+\ Set background color ( Esc-[4%dm )
+: bg ( x -- ) escc 4 .# .# [char] m emit ;
+
+\ Mode end (clear attributes)
+: me ( -- ) escc [char] m emit ;
+
+\ Enable bold mode ( Esc-[1m )
+: b ( -- ) escc 1 .# [char] m emit ;
+
+\ Disable bold mode ( Esc-[22m )
+: -b ( -- ) escc 22 .# [char] m emit ;
+
+\ Enable inverse foreground/background mode ( Esc-[7m )
+: inv ( -- ) escc 7 .# [char] m emit ;
+
+\ Disable inverse foreground/background mode ( Esc-[27m )
+: -inv ( -- ) escc 27 .# [char] m emit ;
+
+\ Convert all occurrences of given character (c) in string (c-addr/u) to Esc
+: escc! ( c-addr/u c -- c-addr/u )
+ 2 pick 2 pick
+ begin dup 0> while
+ over c@ 3 pick = if over 27 swap c! then
+ 1- swap 1+ swap
+ repeat
+ 2drop drop
+;
diff --git a/stand/forth/shortcuts.4th b/stand/forth/shortcuts.4th
new file mode 100644
index 000000000000..33a1cf678988
--- /dev/null
+++ b/stand/forth/shortcuts.4th
@@ -0,0 +1,50 @@
+\ Copyright (c) 2008-2011 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$
+
+\ FICL words intended to be used as shortcuts for carrying out common tasks or
+\ producing common results. Generally, words defined here are simply groupings
+\ of other custom words that pull from multiple libraries (for example, if you
+\ want to define a custom word that uses words defined in three different
+\ libraries, this is a good place to define such a word).
+\
+\ This script should be included after you have included any/all other
+\ libraries. This will prevent calling a word defined here before any required
+\ words have been defined.
+
+marker task-shortcuts.4th
+
+\ This "shortcut" word will not be used directly, but is defined here to
+\ offer the user a quick way to get back into the interactive PXE menu
+\ after they have escaped to the shell (perhaps by accident).
+\
+: menu ( -- )
+ clear \ Clear the screen (in screen.4th)
+ print_version \ print version string (bottom-right; see version.4th)
+ draw-beastie \ Draw FreeBSD logo at right (in beastie.4th)
+ draw-brand \ Draw FIS logo at top (in brand.4th)
+ menu-init \ Initialize menu and draw bounding box (in menu.4th)
+ menu-display \ Launch interactive menu (in menu.4th)
+;
diff --git a/stand/forth/support.4th b/stand/forth/support.4th
new file mode 100644
index 000000000000..aa50b3bb3a9d
--- /dev/null
+++ b/stand/forth/support.4th
@@ -0,0 +1,1606 @@
+\ Copyright (c) 1999 Daniel C. Sobral <dcs@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$
+
+\ Loader.rc support functions:
+\
+\ initialize ( addr len -- ) as above, plus load_conf_files
+\ load_conf ( addr len -- ) load conf file given
+\ include_conf_files ( -- ) load all conf files in load_conf_files
+\ print_syntax_error ( -- ) print line and marker of where a syntax
+\ error was detected
+\ print_line ( -- ) print last line processed
+\ load_kernel ( -- ) load kernel
+\ load_modules ( -- ) load modules flagged
+\
+\ Exported structures:
+\
+\ string counted string structure
+\ cell .addr string address
+\ cell .len string length
+\ module module loading information structure
+\ cell module.flag should we load it?
+\ string module.name module's name
+\ string module.loadname name to be used in loading the module
+\ string module.type module's type
+\ string module.args flags to be passed during load
+\ string module.beforeload command to be executed before load
+\ string module.afterload command to be executed after load
+\ string module.loaderror command to be executed if load fails
+\ cell module.next list chain
+\
+\ Exported global variables;
+\
+\ string conf_files configuration files to be loaded
+\ cell modules_options pointer to first module information
+\ value verbose? indicates if user wants a verbose loading
+\ value any_conf_read? indicates if a conf file was successfully read
+\
+\ Other exported words:
+\ note, strlen is internal
+\ strdup ( addr len -- addr' len) similar to strdup(3)
+\ strcat ( addr len addr' len' -- addr len+len' ) similar to strcat(3)
+\ s' ( | string' -- addr len | ) similar to s"
+\ rudimentary structure support
+
+\ Exception values
+
+1 constant ESYNTAX
+2 constant ENOMEM
+3 constant EFREE
+4 constant ESETERROR \ error setting environment variable
+5 constant EREAD \ error reading
+6 constant EOPEN
+7 constant EEXEC \ XXX never catched
+8 constant EBEFORELOAD
+9 constant EAFTERLOAD
+
+\ I/O constants
+
+0 constant SEEK_SET
+1 constant SEEK_CUR
+2 constant SEEK_END
+
+0 constant O_RDONLY
+1 constant O_WRONLY
+2 constant O_RDWR
+
+\ Crude structure support
+
+: structure:
+ create here 0 , ['] drop , 0
+ does> create here swap dup @ allot cell+ @ execute
+;
+: member: create dup , over , + does> cell+ @ + ;
+: ;structure swap ! ;
+: constructor! >body cell+ ! ;
+: constructor: over :noname ;
+: ;constructor postpone ; swap cell+ ! ; immediate
+: sizeof ' >body @ state @ if postpone literal then ; immediate
+: offsetof ' >body cell+ @ state @ if postpone literal then ; immediate
+: ptr 1 cells member: ;
+: int 1 cells member: ;
+
+\ String structure
+
+structure: string
+ ptr .addr
+ int .len
+ constructor:
+ 0 over .addr !
+ 0 swap .len !
+ ;constructor
+;structure
+
+
+\ Module options linked list
+
+structure: module
+ int module.flag
+ sizeof string member: module.name
+ sizeof string member: module.loadname
+ sizeof string member: module.type
+ sizeof string member: module.args
+ sizeof string member: module.beforeload
+ sizeof string member: module.afterload
+ sizeof string member: module.loaderror
+ ptr module.next
+;structure
+
+\ Internal loader structures (preloaded_file, kernel_module, file_metadata)
+\ must be in sync with the C struct in stand/common/bootstrap.h
+structure: preloaded_file
+ ptr pf.name
+ ptr pf.type
+ ptr pf.args
+ ptr pf.metadata \ file_metadata
+ int pf.loader
+ int pf.addr
+ int pf.size
+ ptr pf.modules \ kernel_module
+ ptr pf.next \ preloaded_file
+;structure
+
+structure: kernel_module
+ ptr km.name
+ \ ptr km.args
+ ptr km.fp \ preloaded_file
+ ptr km.next \ kernel_module
+;structure
+
+structure: file_metadata
+ int md.size
+ 2 member: md.type \ this is not ANS Forth compatible (XXX)
+ ptr md.next \ file_metadata
+ 0 member: md.data \ variable size
+;structure
+
+\ end of structures
+
+\ Global variables
+
+string conf_files
+string nextboot_conf_file
+create module_options sizeof module.next allot 0 module_options !
+create last_module_option sizeof module.next allot 0 last_module_option !
+0 value verbose?
+0 value nextboot?
+
+\ Support string functions
+: strdup { addr len -- addr' len' }
+ len allocate if ENOMEM throw then
+ addr over len move len
+;
+
+: strcat { addr len addr' len' -- addr len+len' }
+ addr' addr len + len' move
+ addr len len' +
+;
+
+: strchr { addr len c -- addr' len' }
+ begin
+ len
+ while
+ addr c@ c = if addr len exit then
+ addr 1 + to addr
+ len 1 - to len
+ repeat
+ 0 0
+;
+
+: s' \ same as s", allows " in the string
+ [char] ' parse
+ state @ if postpone sliteral then
+; immediate
+
+: 2>r postpone >r postpone >r ; immediate
+: 2r> postpone r> postpone r> ; immediate
+: 2r@ postpone 2r> postpone 2dup postpone 2>r ; immediate
+
+: getenv? getenv -1 = if false else drop true then ;
+
+\ determine if a word appears in a string, case-insensitive
+: contains? ( addr1 len1 addr2 len2 -- 0 | -1 )
+ 2 pick 0= if 2drop 2drop true exit then
+ dup 0= if 2drop 2drop false exit then
+ begin
+ begin
+ swap dup c@ dup 32 = over 9 = or over 10 = or
+ over 13 = or over 44 = or swap drop
+ while 1+ swap 1- repeat
+ swap 2 pick 1- over <
+ while
+ 2over 2over drop over compare-insensitive 0= if
+ 2 pick over = if 2drop 2drop true exit then
+ 2 pick tuck - -rot + swap over c@ dup 32 =
+ over 9 = or over 10 = or over 13 = or over 44 = or
+ swap drop if 2drop 2drop true exit then
+ then begin
+ swap dup c@ dup 32 = over 9 = or over 10 = or
+ over 13 = or over 44 = or swap drop
+ if false else true then 2 pick 0> and
+ while 1+ swap 1- repeat
+ swap
+ repeat
+ 2drop 2drop false
+;
+
+: boot_serial? ( -- 0 | -1 )
+ s" console" getenv dup -1 <> if
+ s" comconsole" 2swap contains?
+ else drop false then
+ s" boot_serial" getenv dup -1 <> if
+ swap drop 0>
+ else drop false then
+ or \ console contains comconsole ( or ) boot_serial
+ s" boot_multicons" getenv dup -1 <> if
+ swap drop 0>
+ else drop false then
+ or \ previous boolean ( or ) boot_multicons
+;
+
+\ Private definitions
+
+vocabulary support-functions
+only forth also support-functions definitions
+
+\ Some control characters constants
+
+7 constant bell
+8 constant backspace
+9 constant tab
+10 constant lf
+13 constant <cr>
+
+\ Read buffer size
+
+80 constant read_buffer_size
+
+\ Standard suffixes
+
+: load_module_suffix s" _load" ;
+: module_loadname_suffix s" _name" ;
+: module_type_suffix s" _type" ;
+: module_args_suffix s" _flags" ;
+: module_beforeload_suffix s" _before" ;
+: module_afterload_suffix s" _after" ;
+: module_loaderror_suffix s" _error" ;
+
+\ Support operators
+
+: >= < 0= ;
+: <= > 0= ;
+
+\ Assorted support functions
+
+: free-memory free if EFREE throw then ;
+
+: strget { var -- addr len } var .addr @ var .len @ ;
+
+\ assign addr len to variable.
+: strset { addr len var -- } addr var .addr ! len var .len ! ;
+
+\ free memory and reset fields
+: strfree { var -- } var .addr @ ?dup if free-memory 0 0 var strset then ;
+
+\ free old content, make a copy of the string and assign to variable
+: string= { addr len var -- } var strfree addr len strdup var strset ;
+
+: strtype ( str -- ) strget type ;
+
+\ assign a reference to what is on the stack
+: strref { addr len var -- addr len }
+ addr var .addr ! len var .len ! addr len
+;
+
+\ unquote a string
+: unquote ( addr len -- addr len )
+ over c@ [char] " = if 2 chars - swap char+ swap then
+;
+
+\ Assignment data temporary storage
+
+string name_buffer
+string value_buffer
+
+\ Line by line file reading functions
+\
+\ exported:
+\ line_buffer
+\ end_of_file?
+\ fd
+\ read_line
+\ reset_line_reading
+
+vocabulary line-reading
+also line-reading definitions
+
+\ File data temporary storage
+
+string read_buffer
+0 value read_buffer_ptr
+
+\ File's line reading function
+
+get-current ( -- wid ) previous definitions
+
+string line_buffer
+0 value end_of_file?
+variable fd
+
+>search ( wid -- ) definitions
+
+: skip_newlines
+ begin
+ read_buffer .len @ read_buffer_ptr >
+ while
+ read_buffer .addr @ read_buffer_ptr + c@ lf = if
+ read_buffer_ptr char+ to read_buffer_ptr
+ else
+ exit
+ then
+ repeat
+;
+
+: scan_buffer ( -- addr len )
+ read_buffer_ptr >r
+ begin
+ read_buffer .len @ r@ >
+ while
+ read_buffer .addr @ r@ + c@ lf = if
+ read_buffer .addr @ read_buffer_ptr + ( -- addr )
+ r@ read_buffer_ptr - ( -- len )
+ r> to read_buffer_ptr
+ exit
+ then
+ r> char+ >r
+ repeat
+ read_buffer .addr @ read_buffer_ptr + ( -- addr )
+ r@ read_buffer_ptr - ( -- len )
+ r> to read_buffer_ptr
+;
+
+: line_buffer_resize ( len -- len )
+ >r
+ line_buffer .len @ if
+ line_buffer .addr @
+ line_buffer .len @ r@ +
+ resize if ENOMEM throw then
+ else
+ r@ allocate if ENOMEM throw then
+ then
+ line_buffer .addr !
+ r>
+;
+
+: append_to_line_buffer ( addr len -- )
+ line_buffer strget
+ 2swap strcat
+ line_buffer .len !
+ drop
+;
+
+: read_from_buffer
+ scan_buffer ( -- addr len )
+ line_buffer_resize ( len -- len )
+ append_to_line_buffer ( addr len -- )
+;
+
+: refill_required?
+ read_buffer .len @ read_buffer_ptr =
+ end_of_file? 0= and
+;
+
+: refill_buffer
+ 0 to read_buffer_ptr
+ read_buffer .addr @ 0= if
+ read_buffer_size allocate if ENOMEM throw then
+ read_buffer .addr !
+ then
+ fd @ read_buffer .addr @ read_buffer_size fread
+ dup -1 = if EREAD throw then
+ dup 0= if true to end_of_file? then
+ read_buffer .len !
+;
+
+get-current ( -- wid ) previous definitions >search ( wid -- )
+
+: reset_line_reading
+ 0 to read_buffer_ptr
+;
+
+: read_line
+ line_buffer strfree
+ skip_newlines
+ begin
+ read_from_buffer
+ refill_required?
+ while
+ refill_buffer
+ repeat
+;
+
+only forth also support-functions definitions
+
+\ Conf file line parser:
+\ <line> ::= <spaces><name><spaces>'='<spaces><value><spaces>[<comment>] |
+\ <spaces>[<comment>]
+\ <name> ::= <letter>{<letter>|<digit>|'_'}
+\ <value> ::= '"'{<character_set>|'\'<anything>}'"' | <name>
+\ <character_set> ::= ASCII 32 to 126, except '\' and '"'
+\ <comment> ::= '#'{<anything>}
+\
+\ exported:
+\ line_pointer
+\ process_conf
+
+0 value line_pointer
+
+vocabulary file-processing
+also file-processing definitions
+
+\ parser functions
+\
+\ exported:
+\ get_assignment
+
+vocabulary parser
+also parser definitions
+
+0 value parsing_function
+0 value end_of_line
+
+: end_of_line? line_pointer end_of_line = ;
+
+\ classifiers for various character classes in the input line
+
+: letter?
+ line_pointer c@ >r
+ r@ [char] A >=
+ r@ [char] Z <= and
+ r@ [char] a >=
+ r> [char] z <= and
+ or
+;
+
+: digit?
+ line_pointer c@ >r
+ r@ [char] - =
+ r@ [char] 0 >=
+ r> [char] 9 <= and
+ or
+;
+
+: quote? line_pointer c@ [char] " = ;
+
+: assignment_sign? line_pointer c@ [char] = = ;
+
+: comment? line_pointer c@ [char] # = ;
+
+: space? line_pointer c@ bl = line_pointer c@ tab = or ;
+
+: backslash? line_pointer c@ [char] \ = ;
+
+: underscore? line_pointer c@ [char] _ = ;
+
+: dot? line_pointer c@ [char] . = ;
+
+\ manipulation of input line
+: skip_character line_pointer char+ to line_pointer ;
+
+: skip_to_end_of_line end_of_line to line_pointer ;
+
+: eat_space
+ begin
+ end_of_line? if 0 else space? then
+ while
+ skip_character
+ repeat
+;
+
+: parse_name ( -- addr len )
+ line_pointer
+ begin
+ end_of_line? if 0 else letter? digit? underscore? dot? or or or then
+ while
+ skip_character
+ repeat
+ line_pointer over -
+ strdup
+;
+
+: remove_backslashes { addr len | addr' len' -- addr' len' }
+ len allocate if ENOMEM throw then
+ to addr'
+ addr >r
+ begin
+ addr c@ [char] \ <> if
+ addr c@ addr' len' + c!
+ len' char+ to len'
+ then
+ addr char+ to addr
+ r@ len + addr =
+ until
+ r> drop
+ addr' len'
+;
+
+: parse_quote ( -- addr len )
+ line_pointer
+ skip_character
+ end_of_line? if ESYNTAX throw then
+ begin
+ quote? 0=
+ while
+ backslash? if
+ skip_character
+ end_of_line? if ESYNTAX throw then
+ then
+ skip_character
+ end_of_line? if ESYNTAX throw then
+ repeat
+ skip_character
+ line_pointer over -
+ remove_backslashes
+;
+
+: read_name
+ parse_name ( -- addr len )
+ name_buffer strset
+;
+
+: read_value
+ quote? if
+ parse_quote ( -- addr len )
+ else
+ parse_name ( -- addr len )
+ then
+ value_buffer strset
+;
+
+: comment
+ skip_to_end_of_line
+;
+
+: white_space_4
+ eat_space
+ comment? if ['] comment to parsing_function exit then
+ end_of_line? 0= if ESYNTAX throw then
+;
+
+: variable_value
+ read_value
+ ['] white_space_4 to parsing_function
+;
+
+: white_space_3
+ eat_space
+ letter? digit? quote? or or if
+ ['] variable_value to parsing_function exit
+ then
+ ESYNTAX throw
+;
+
+: assignment_sign
+ skip_character
+ ['] white_space_3 to parsing_function
+;
+
+: white_space_2
+ eat_space
+ assignment_sign? if ['] assignment_sign to parsing_function exit then
+ ESYNTAX throw
+;
+
+: variable_name
+ read_name
+ ['] white_space_2 to parsing_function
+;
+
+: white_space_1
+ eat_space
+ letter? if ['] variable_name to parsing_function exit then
+ comment? if ['] comment to parsing_function exit then
+ end_of_line? 0= if ESYNTAX throw then
+;
+
+get-current ( -- wid ) previous definitions >search ( wid -- )
+
+: get_assignment
+ line_buffer strget + to end_of_line
+ line_buffer .addr @ to line_pointer
+ ['] white_space_1 to parsing_function
+ begin
+ end_of_line? 0=
+ while
+ parsing_function execute
+ repeat
+ parsing_function ['] comment =
+ parsing_function ['] white_space_1 =
+ parsing_function ['] white_space_4 =
+ or or 0= if ESYNTAX throw then
+;
+
+only forth also support-functions also file-processing definitions
+
+\ Process line
+
+: assignment_type? ( addr len -- flag )
+ name_buffer strget
+ compare 0=
+;
+
+: suffix_type? ( addr len -- flag )
+ name_buffer .len @ over <= if 2drop false exit then
+ name_buffer .len @ over - name_buffer .addr @ +
+ over compare 0=
+;
+
+: loader_conf_files? s" loader_conf_files" assignment_type? ;
+
+: nextboot_flag? s" nextboot_enable" assignment_type? ;
+
+: nextboot_conf? s" nextboot_conf" assignment_type? ;
+
+: verbose_flag? s" verbose_loading" assignment_type? ;
+
+: execute? s" exec" assignment_type? ;
+
+: module_load? load_module_suffix suffix_type? ;
+
+: module_loadname? module_loadname_suffix suffix_type? ;
+
+: module_type? module_type_suffix suffix_type? ;
+
+: module_args? module_args_suffix suffix_type? ;
+
+: module_beforeload? module_beforeload_suffix suffix_type? ;
+
+: module_afterload? module_afterload_suffix suffix_type? ;
+
+: module_loaderror? module_loaderror_suffix suffix_type? ;
+
+\ build a 'set' statement and execute it
+: set_environment_variable
+ name_buffer .len @ value_buffer .len @ + 5 chars + \ size of result string
+ allocate if ENOMEM throw then
+ dup 0 \ start with an empty string and append the pieces
+ s" set " strcat
+ name_buffer strget strcat
+ s" =" strcat
+ value_buffer strget strcat
+ ['] evaluate catch if
+ 2drop free drop
+ ESETERROR throw
+ else
+ free-memory
+ then
+;
+
+: set_conf_files
+ set_environment_variable
+ s" loader_conf_files" getenv conf_files string=
+;
+
+: set_nextboot_conf
+ value_buffer strget unquote nextboot_conf_file string=
+;
+
+: append_to_module_options_list ( addr -- )
+ module_options @ 0= if
+ dup module_options !
+ last_module_option !
+ else
+ dup last_module_option @ module.next !
+ last_module_option !
+ then
+;
+
+: set_module_name { addr -- } \ check leaks
+ name_buffer strget addr module.name string=
+;
+
+: yes_value?
+ value_buffer strget \ XXX could use unquote
+ 2dup s' "YES"' compare >r
+ 2dup s' "yes"' compare >r
+ 2dup s" YES" compare >r
+ s" yes" compare r> r> r> and and and 0=
+;
+
+: find_module_option ( -- addr | 0 ) \ return ptr to entry matching name_buffer
+ module_options @
+ begin
+ dup
+ while
+ dup module.name strget
+ name_buffer strget
+ compare 0= if exit then
+ module.next @
+ repeat
+;
+
+: new_module_option ( -- addr )
+ sizeof module allocate if ENOMEM throw then
+ dup sizeof module erase
+ dup append_to_module_options_list
+ dup set_module_name
+;
+
+: get_module_option ( -- addr )
+ find_module_option
+ ?dup 0= if new_module_option then
+;
+
+: set_module_flag
+ name_buffer .len @ load_module_suffix nip - name_buffer .len !
+ yes_value? get_module_option module.flag !
+;
+
+: set_module_args
+ name_buffer .len @ module_args_suffix nip - name_buffer .len !
+ value_buffer strget unquote
+ get_module_option module.args string=
+;
+
+: set_module_loadname
+ name_buffer .len @ module_loadname_suffix nip - name_buffer .len !
+ value_buffer strget unquote
+ get_module_option module.loadname string=
+;
+
+: set_module_type
+ name_buffer .len @ module_type_suffix nip - name_buffer .len !
+ value_buffer strget unquote
+ get_module_option module.type string=
+;
+
+: set_module_beforeload
+ name_buffer .len @ module_beforeload_suffix nip - name_buffer .len !
+ value_buffer strget unquote
+ get_module_option module.beforeload string=
+;
+
+: set_module_afterload
+ name_buffer .len @ module_afterload_suffix nip - name_buffer .len !
+ value_buffer strget unquote
+ get_module_option module.afterload string=
+;
+
+: set_module_loaderror
+ name_buffer .len @ module_loaderror_suffix nip - name_buffer .len !
+ value_buffer strget unquote
+ get_module_option module.loaderror string=
+;
+
+: set_nextboot_flag
+ yes_value? to nextboot?
+;
+
+: set_verbose
+ yes_value? to verbose?
+;
+
+: execute_command
+ value_buffer strget unquote
+ ['] evaluate catch if EEXEC throw then
+;
+
+: process_assignment
+ name_buffer .len @ 0= if exit then
+ loader_conf_files? if set_conf_files exit then
+ nextboot_flag? if set_nextboot_flag exit then
+ nextboot_conf? if set_nextboot_conf exit then
+ verbose_flag? if set_verbose exit then
+ execute? if execute_command exit then
+ module_load? if set_module_flag exit then
+ module_loadname? if set_module_loadname exit then
+ module_type? if set_module_type exit then
+ module_args? if set_module_args exit then
+ module_beforeload? if set_module_beforeload exit then
+ module_afterload? if set_module_afterload exit then
+ module_loaderror? if set_module_loaderror exit then
+ set_environment_variable
+;
+
+\ free_buffer ( -- )
+\
+\ Free some pointers if needed. The code then tests for errors
+\ in freeing, and throws an exception if needed. If a pointer is
+\ not allocated, it's value (0) is used as flag.
+
+: free_buffers
+ name_buffer strfree
+ value_buffer strfree
+;
+
+\ Higher level file processing
+
+get-current ( -- wid ) previous definitions >search ( wid -- )
+
+: process_conf
+ begin
+ end_of_file? 0=
+ while
+ free_buffers
+ read_line
+ get_assignment
+ ['] process_assignment catch
+ ['] free_buffers catch
+ swap throw throw
+ repeat
+;
+
+: peek_file ( addr len -- )
+ 0 to end_of_file?
+ reset_line_reading
+ O_RDONLY fopen fd !
+ fd @ -1 = if EOPEN throw then
+ free_buffers
+ read_line
+ get_assignment
+ ['] process_assignment catch
+ ['] free_buffers catch
+ fd @ fclose
+ swap throw throw
+;
+
+only forth also support-functions definitions
+
+\ Interface to loading conf files
+
+: load_conf ( addr len -- )
+ 0 to end_of_file?
+ reset_line_reading
+ O_RDONLY fopen fd !
+ fd @ -1 = if EOPEN throw then
+ ['] process_conf catch
+ fd @ fclose
+ throw
+;
+
+: print_line line_buffer strtype cr ;
+
+: print_syntax_error
+ line_buffer strtype cr
+ line_buffer .addr @
+ begin
+ line_pointer over <>
+ while
+ bl emit char+
+ repeat
+ drop
+ ." ^" cr
+;
+
+
+\ Debugging support functions
+
+only forth definitions also support-functions
+
+: test-file
+ ['] load_conf catch dup .
+ ESYNTAX = if cr print_syntax_error then
+;
+
+\ find a module name, leave addr on the stack (0 if not found)
+: find-module ( <module> -- ptr | 0 )
+ bl parse ( addr len )
+ module_options @ >r ( store current pointer )
+ begin
+ r@
+ while
+ 2dup ( addr len addr len )
+ r@ module.name strget
+ compare 0= if drop drop r> exit then ( found it )
+ r> module.next @ >r
+ repeat
+ type ." was not found" cr r>
+;
+
+: show-nonempty ( addr len mod -- )
+ strget dup verbose? or if
+ 2swap type type cr
+ else
+ drop drop drop drop
+ then ;
+
+: show-one-module { addr -- addr }
+ ." Name: " addr module.name strtype cr
+ s" Path: " addr module.loadname show-nonempty
+ s" Type: " addr module.type show-nonempty
+ s" Flags: " addr module.args show-nonempty
+ s" Before load: " addr module.beforeload show-nonempty
+ s" After load: " addr module.afterload show-nonempty
+ s" Error: " addr module.loaderror show-nonempty
+ ." Status: " addr module.flag @ if ." Load" else ." Don't load" then cr
+ cr
+ addr
+;
+
+: show-module-options
+ module_options @
+ begin
+ ?dup
+ while
+ show-one-module
+ module.next @
+ repeat
+;
+
+: free-one-module { addr -- addr }
+ addr module.name strfree
+ addr module.loadname strfree
+ addr module.type strfree
+ addr module.args strfree
+ addr module.beforeload strfree
+ addr module.afterload strfree
+ addr module.loaderror strfree
+ addr
+;
+
+: free-module-options
+ module_options @
+ begin
+ ?dup
+ while
+ free-one-module
+ dup module.next @
+ swap free-memory
+ repeat
+ 0 module_options !
+ 0 last_module_option !
+;
+
+only forth also support-functions definitions
+
+\ Variables used for processing multiple conf files
+
+string current_file_name_ref \ used to print the file name
+
+\ Indicates if any conf file was successfully read
+
+0 value any_conf_read?
+
+\ loader_conf_files processing support functions
+
+: get_conf_files ( -- addr len ) \ put addr/len on stack, reset var
+ conf_files strget 0 0 conf_files strset
+;
+
+: skip_leading_spaces { addr len pos -- addr len pos' }
+ begin
+ pos len = if 0 else addr pos + c@ bl = then
+ while
+ pos char+ to pos
+ repeat
+ addr len pos
+;
+
+\ return the file name at pos, or free the string if nothing left
+: get_file_name { addr len pos -- addr len pos' addr' len' || 0 }
+ pos len = if
+ addr free abort" Fatal error freeing memory"
+ 0 exit
+ then
+ pos >r
+ begin
+ \ stay in the loop until have chars and they are not blank
+ pos len = if 0 else addr pos + c@ bl <> then
+ while
+ pos char+ to pos
+ repeat
+ addr len pos addr r@ + pos r> -
+;
+
+: get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 )
+ skip_leading_spaces
+ get_file_name
+;
+
+: print_current_file
+ current_file_name_ref strtype
+;
+
+: process_conf_errors
+ dup 0= if true to any_conf_read? drop exit then
+ >r 2drop r>
+ dup ESYNTAX = if
+ ." Warning: syntax error on file " print_current_file cr
+ print_syntax_error drop exit
+ then
+ dup ESETERROR = if
+ ." Warning: bad definition on file " print_current_file cr
+ print_line drop exit
+ then
+ dup EREAD = if
+ ." Warning: error reading file " print_current_file cr drop exit
+ then
+ dup EOPEN = if
+ verbose? if ." Warning: unable to open file " print_current_file cr then
+ drop exit
+ then
+ dup EFREE = abort" Fatal error freeing memory"
+ dup ENOMEM = abort" Out of memory"
+ throw \ Unknown error -- pass ahead
+;
+
+\ Process loader_conf_files recursively
+\ Interface to loader_conf_files processing
+
+: include_conf_files
+ get_conf_files 0 ( addr len offset )
+ begin
+ get_next_file ?dup ( addr len 1 | 0 )
+ while
+ current_file_name_ref strref
+ ['] load_conf catch
+ process_conf_errors
+ conf_files .addr @ if recurse then
+ repeat
+;
+
+: get_nextboot_conf_file ( -- addr len )
+ nextboot_conf_file strget
+;
+
+: rewrite_nextboot_file ( -- )
+ get_nextboot_conf_file
+ O_WRONLY fopen fd !
+ fd @ -1 = if EOPEN throw then
+ fd @ s' nextboot_enable="NO" ' fwrite ( fd buf len -- nwritten ) drop
+ fd @ fclose
+;
+
+: include_nextboot_file ( -- )
+ get_nextboot_conf_file
+ ['] peek_file catch if 2drop then
+ nextboot? if
+ get_nextboot_conf_file
+ current_file_name_ref strref
+ ['] load_conf catch
+ process_conf_errors
+ ['] rewrite_nextboot_file catch if 2drop then
+ then
+;
+
+\ Module loading functions
+
+: load_parameters { addr -- addr addrN lenN ... addr1 len1 N }
+ addr
+ addr module.args strget
+ addr module.loadname .len @ if
+ addr module.loadname strget
+ else
+ addr module.name strget
+ then
+ addr module.type .len @ if
+ addr module.type strget
+ s" -t "
+ 4 ( -t type name flags )
+ else
+ 2 ( name flags )
+ then
+;
+
+: before_load ( addr -- addr )
+ dup module.beforeload .len @ if
+ dup module.beforeload strget
+ ['] evaluate catch if EBEFORELOAD throw then
+ then
+;
+
+: after_load ( addr -- addr )
+ dup module.afterload .len @ if
+ dup module.afterload strget
+ ['] evaluate catch if EAFTERLOAD throw then
+ then
+;
+
+: load_error ( addr -- addr )
+ dup module.loaderror .len @ if
+ dup module.loaderror strget
+ evaluate \ This we do not intercept so it can throw errors
+ then
+;
+
+: pre_load_message ( addr -- addr )
+ verbose? if
+ dup module.name strtype
+ ." ..."
+ then
+;
+
+: load_error_message verbose? if ." failed!" cr then ;
+
+: load_successful_message verbose? if ." ok" cr then ;
+
+: load_module
+ load_parameters load
+;
+
+: process_module ( addr -- addr )
+ pre_load_message
+ before_load
+ begin
+ ['] load_module catch if
+ dup module.loaderror .len @ if
+ load_error \ Command should return a flag!
+ else
+ load_error_message true \ Do not retry
+ then
+ else
+ after_load
+ load_successful_message true \ Successful, do not retry
+ then
+ until
+;
+
+: process_module_errors ( addr ior -- )
+ dup EBEFORELOAD = if
+ drop
+ ." Module "
+ dup module.name strtype
+ dup module.loadname .len @ if
+ ." (" dup module.loadname strtype ." )"
+ then
+ cr
+ ." Error executing "
+ dup module.beforeload strtype cr \ XXX there was a typo here
+ abort
+ then
+
+ dup EAFTERLOAD = if
+ drop
+ ." Module "
+ dup module.name .addr @ over module.name .len @ type
+ dup module.loadname .len @ if
+ ." (" dup module.loadname strtype ." )"
+ then
+ cr
+ ." Error executing "
+ dup module.afterload strtype cr
+ abort
+ then
+
+ throw \ Don't know what it is all about -- pass ahead
+;
+
+\ Module loading interface
+
+\ scan the list of modules, load enabled ones.
+: load_modules ( -- ) ( throws: abort & user-defined )
+ module_options @ ( list_head )
+ begin
+ ?dup
+ while
+ dup module.flag @ if
+ ['] process_module catch
+ process_module_errors
+ then
+ module.next @
+ repeat
+;
+
+\ h00h00 magic used to try loading either a kernel with a given name,
+\ or a kernel with the default name in a directory of a given name
+\ (the pain!)
+
+: bootpath s" /boot/" ;
+: modulepath s" module_path" ;
+
+\ Functions used to save and restore module_path's value.
+: saveenv ( addr len | -1 -- addr' len | 0 -1 )
+ dup -1 = if 0 swap exit then
+ strdup
+;
+: freeenv ( addr len | 0 -1 )
+ -1 = if drop else free abort" Freeing error" then
+;
+: restoreenv ( addr len | 0 -1 -- )
+ dup -1 = if ( it wasn't set )
+ 2drop
+ modulepath unsetenv
+ else
+ over >r
+ modulepath setenv
+ r> free abort" Freeing error"
+ then
+;
+
+: clip_args \ Drop second string if only one argument is passed
+ 1 = if
+ 2swap 2drop
+ 1
+ else
+ 2
+ then
+;
+
+also builtins
+
+\ Parse filename from a semicolon-separated list
+
+\ replacement, not working yet
+: newparse-; { addr len | a1 -- a' len-x addr x }
+ addr len [char] ; strchr dup if ( a1 len1 )
+ swap to a1 ( store address )
+ 1 - a1 @ 1 + swap ( remove match )
+ addr a1 addr -
+ else
+ 0 0 addr len
+ then
+;
+
+: parse-; ( addr len -- addr' len-x addr x )
+ over 0 2swap ( addr 0 addr len )
+ begin
+ dup 0 <> ( addr 0 addr len )
+ while
+ over c@ [char] ; <> ( addr 0 addr len flag )
+ while
+ 1- swap 1+ swap
+ 2swap 1+ 2swap
+ repeat then
+ dup 0 <> if
+ 1- swap 1+ swap
+ then
+ 2swap
+;
+
+\ Try loading one of multiple kernels specified
+
+: try_multiple_kernels ( addr len addr' len' args -- flag )
+ >r
+ begin
+ parse-; 2>r
+ 2over 2r>
+ r@ clip_args
+ s" DEBUG" getenv? if
+ s" echo Module_path: ${module_path}" evaluate
+ ." Kernel : " >r 2dup type r> cr
+ dup 2 = if ." Flags : " >r 2over type r> cr then
+ then
+ 1 load
+ while
+ dup 0=
+ until
+ 1 >r \ Failure
+ else
+ 0 >r \ Success
+ then
+ 2drop 2drop
+ r>
+ r> drop
+;
+
+\ Try to load a kernel; the kernel name is taken from one of
+\ the following lists, as ordered:
+\
+\ 1. The "bootfile" environment variable
+\ 2. The "kernel" environment variable
+\
+\ Flags are passed, if available. If not, dummy values must be given.
+\
+\ The kernel gets loaded from the current module_path.
+
+: load_a_kernel ( flags len 1 | x x 0 -- flag )
+ local args
+ 2local flags
+ 0 0 2local kernel
+ end-locals
+
+ \ Check if a default kernel name exists at all, exits if not
+ s" bootfile" getenv dup -1 <> if
+ to kernel
+ flags kernel args 1+ try_multiple_kernels
+ dup 0= if exit then
+ then
+ drop
+
+ s" kernel" getenv dup -1 <> if
+ to kernel
+ else
+ drop
+ 1 exit \ Failure
+ then
+
+ \ Try all default kernel names
+ flags kernel args 1+ try_multiple_kernels
+;
+
+\ Try to load a kernel; the kernel name is taken from one of
+\ the following lists, as ordered:
+\
+\ 1. The "bootfile" environment variable
+\ 2. The "kernel" environment variable
+\
+\ Flags are passed, if provided.
+\
+\ The kernel will be loaded from a directory computed from the
+\ path given. Two directories will be tried in the following order:
+\
+\ 1. /boot/path
+\ 2. path
+\
+\ The module_path variable is overridden if load is successful, by
+\ prepending the successful path.
+
+: load_from_directory ( path len 1 | flags len' path len 2 -- flag )
+ local args
+ 2local path
+ args 1 = if 0 0 then
+ 2local flags
+ 0 0 2local oldmodulepath \ like a string
+ 0 0 2local newmodulepath \ like a string
+ end-locals
+
+ \ Set the environment variable module_path, and try loading
+ \ the kernel again.
+ modulepath getenv saveenv to oldmodulepath
+
+ \ Try prepending /boot/ first
+ bootpath nip path nip + \ total length
+ oldmodulepath nip dup -1 = if
+ drop
+ else
+ 1+ + \ add oldpath -- XXX why the 1+ ?
+ then
+ allocate if ( out of memory ) 1 exit then \ XXX throw ?
+
+ 0
+ bootpath strcat
+ path strcat
+ 2dup to newmodulepath
+ modulepath setenv
+
+ \ Try all default kernel names
+ flags args 1- load_a_kernel
+ 0= if ( success )
+ oldmodulepath nip -1 <> if
+ newmodulepath s" ;" strcat
+ oldmodulepath strcat
+ modulepath setenv
+ newmodulepath drop free-memory
+ oldmodulepath drop free-memory
+ then
+ 0 exit
+ then
+
+ \ Well, try without the prepended /boot/
+ path newmodulepath drop swap move
+ newmodulepath drop path nip
+ 2dup to newmodulepath
+ modulepath setenv
+
+ \ Try all default kernel names
+ flags args 1- load_a_kernel
+ if ( failed once more )
+ oldmodulepath restoreenv
+ newmodulepath drop free-memory
+ 1
+ else
+ oldmodulepath nip -1 <> if
+ newmodulepath s" ;" strcat
+ oldmodulepath strcat
+ modulepath setenv
+ newmodulepath drop free-memory
+ oldmodulepath drop free-memory
+ then
+ 0
+ then
+;
+
+\ Try to load a kernel; the kernel name is taken from one of
+\ the following lists, as ordered:
+\
+\ 1. The "bootfile" environment variable
+\ 2. The "kernel" environment variable
+\ 3. The "path" argument
+\
+\ Flags are passed, if provided.
+\
+\ The kernel will be loaded from a directory computed from the
+\ path given. Two directories will be tried in the following order:
+\
+\ 1. /boot/path
+\ 2. path
+\
+\ Unless "path" is meant to be kernel name itself. In that case, it
+\ will first be tried as a full path, and, next, search on the
+\ directories pointed by module_path.
+\
+\ The module_path variable is overridden if load is successful, by
+\ prepending the successful path.
+
+: load_directory_or_file ( path len 1 | flags len' path len 2 -- flag )
+ local args
+ 2local path
+ args 1 = if 0 0 then
+ 2local flags
+ end-locals
+
+ \ First, assume path is an absolute path to a directory
+ flags path args clip_args load_from_directory
+ dup 0= if exit else drop then
+
+ \ Next, assume path points to the kernel
+ flags path args try_multiple_kernels
+;
+
+: initialize ( addr len -- )
+ strdup conf_files strset
+;
+
+: kernel_options ( -- addr len 1 | 0 )
+ s" kernel_options" getenv
+ dup -1 = if drop 0 else 1 then
+;
+
+: standard_kernel_search ( flags 1 | 0 -- flag )
+ local args
+ args 0= if 0 0 then
+ 2local flags
+ s" kernel" getenv
+ dup -1 = if 0 swap then
+ 2local path
+ end-locals
+
+ path nip -1 = if ( there isn't a "kernel" environment variable )
+ flags args load_a_kernel
+ else
+ flags path args 1+ clip_args load_directory_or_file
+ then
+;
+
+: load_kernel ( -- ) ( throws: abort )
+ kernel_options standard_kernel_search
+ abort" Unable to load a kernel!"
+;
+
+: load_xen ( -- flag )
+ s" xen_kernel" getenv dup -1 <> if
+ 1 1 load ( c-addr/u flag N -- flag )
+ else
+ drop
+ 0 ( -1 -- flag )
+ then
+;
+
+: load_xen_throw ( -- ) ( throws: abort )
+ load_xen
+ abort" Unable to load Xen!"
+;
+
+: set_defaultoptions ( -- )
+ s" kernel_options" getenv dup -1 = if
+ drop
+ else
+ s" temp_options" setenv
+ then
+;
+
+\ pick the i-th argument, i starts at 0
+: argv[] ( aN uN ... a1 u1 N i -- aN uN ... a1 u1 N ai+1 ui+1 )
+ 2dup = if 0 0 exit then \ out of range
+ dup >r
+ 1+ 2* ( skip N and ui )
+ pick
+ r>
+ 1+ 2* ( skip N and ai )
+ pick
+;
+
+: drop_args ( aN uN ... a1 u1 N -- )
+ 0 ?do 2drop loop
+;
+
+: argc
+ dup
+;
+
+: queue_argv ( aN uN ... a1 u1 N a u -- a u aN uN ... a1 u1 N+1 )
+ >r
+ over 2* 1+ -roll
+ r>
+ over 2* 1+ -roll
+ 1+
+;
+
+: unqueue_argv ( aN uN ... a1 u1 N -- aN uN ... a2 u2 N-1 a1 u1 )
+ 1- -rot
+;
+
+\ compute the length of the buffer including the spaces between words
+: strlen(argv) ( aN uN .. a1 u1 N -- aN uN .. a1 u1 N len )
+ dup 0= if 0 exit then
+ 0 >r \ Size
+ 0 >r \ Index
+ begin
+ argc r@ <>
+ while
+ r@ argv[]
+ nip
+ r> r> rot + 1+
+ >r 1+ >r
+ repeat
+ r> drop
+ r>
+;
+
+: concat_argv ( aN uN ... a1 u1 N -- a u )
+ strlen(argv) allocate if ENOMEM throw then
+ 0 2>r ( save addr 0 on return stack )
+
+ begin
+ dup
+ while
+ unqueue_argv ( ... N a1 u1 )
+ 2r> 2swap ( old a1 u1 )
+ strcat
+ s" " strcat ( append one space ) \ XXX this gives a trailing space
+ 2>r ( store string on the result stack )
+ repeat
+ drop_args
+ 2r>
+;
+
+: set_tempoptions ( addrN lenN ... addr1 len1 N -- addr len 1 | 0 )
+ \ Save the first argument, if it exists and is not a flag
+ argc if
+ 0 argv[] drop c@ [char] - <> if
+ unqueue_argv 2>r \ Filename
+ 1 >r \ Filename present
+ else
+ 0 >r \ Filename not present
+ then
+ else
+ 0 >r \ Filename not present
+ then
+
+ \ If there are other arguments, assume they are flags
+ ?dup if
+ concat_argv
+ 2dup s" temp_options" setenv
+ drop free if EFREE throw then
+ else
+ set_defaultoptions
+ then
+
+ \ Bring back the filename, if one was provided
+ r> if 2r> 1 else 0 then
+;
+
+: get_arguments ( -- addrN lenN ... addr1 len1 N )
+ 0
+ begin
+ \ Get next word on the command line
+ parse-word
+ ?dup while
+ queue_argv
+ repeat
+ drop ( empty string )
+;
+
+: load_kernel_and_modules ( args -- flag )
+ set_tempoptions
+ argc >r
+ s" temp_options" getenv dup -1 <> if
+ queue_argv
+ else
+ drop
+ then
+ load_xen
+ ?dup 0= if ( success )
+ r> if ( a path was passed )
+ load_directory_or_file
+ else
+ standard_kernel_search
+ then
+ ?dup 0= if ['] load_modules catch then
+ then
+;
+
+only forth definitions
diff --git a/stand/forth/version.4th b/stand/forth/version.4th
new file mode 100644
index 000000000000..a5311b4442ac
--- /dev/null
+++ b/stand/forth/version.4th
@@ -0,0 +1,96 @@
+\ Copyright (c) 2006-2015 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-version.4th
+
+vocabulary version-processing
+only forth also version-processing definitions
+
+variable versionX
+variable versionY
+
+\ Default $loader_version value if not overridden or using tribute screen
+: str_loader_version ( -- C-ADDR/U|-1 ) -1 ;
+
+\ Initialize text placement to defaults
+80 versionX ! \ NOTE: this is the ending column (text is right-justified)
+24 versionY !
+
+only forth definitions also version-processing
+
+: print_version ( -- )
+
+ \ Get the text placement position (if set)
+ s" loader_version_x" getenv dup -1 <> if
+ ?number drop versionX ! -1
+ then drop
+ s" loader_version_y" getenv dup -1 <> if
+ ?number drop versionY ! -1
+ then drop
+
+ \ Default version if none was set
+ s" loader_version" getenv dup -1 = if
+ drop
+ \ Use above default if no logo is requested
+ s" loader_logo" getenv dup -1 = if
+ drop str_loader_version
+ else
+ \ For tributes, do nothing (defer to logo-*.4th)
+ 2dup s" tribute" compare-insensitive 0= if
+ 2drop
+ s" logo" sfind if
+ drop exit \ see logo-tribute.4th
+ else
+ drop str_loader_version
+ then
+ else 2dup s" tributebw" compare-insensitive 0= if
+ 2drop
+ s" logo" sfind if
+ drop exit \ see logo-tributebw.4th
+ else
+ drop str_loader_version
+ then
+ else
+ 2drop str_loader_version
+ then then
+ then
+ then dup -1 = if
+ drop exit \ default version (above) is disabled
+ then
+
+ \ Right justify the text
+ dup versionX @ swap - versionY @ at-xy
+
+ \ Print the version (optionally in cyan)
+ loader_color? dup ( c-addr/u -- c-addr/u bool bool )
+ if 6 fg then
+ -rot type
+ if me then
+
+ 0 25 at-xy
+;
+
+only forth definitions
diff --git a/stand/forth/version.4th.8 b/stand/forth/version.4th.8
new file mode 100644
index 000000000000..256df1ee5f87
--- /dev/null
+++ b/stand/forth/version.4th.8
@@ -0,0 +1,128 @@
+.\" Copyright (c) 2011-2013 Devin Teske
+.\" 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$
+.\"
+.Dd August 6, 2013
+.Dt VERSION.4TH 8
+.Os
+.Sh NAME
+.Nm version.4th
+.Nd FreeBSD version string boot module
+.Sh DESCRIPTION
+The file that goes by the name of
+.Nm
+is a set of commands designed to draw the boot loader
+version at the bottom-right of the screen.
+The commands of
+.Nm
+by themselves are not enough for most uses.
+Please refer to the
+examples below for the most common situations, and to
+.Xr loader 8
+for additional commands.
+.Pp
+Before using any of the commands provided in
+.Nm ,
+it must be included
+through the command:
+.Pp
+.Dl include version.4th
+.Pp
+This line is present in the default
+.Pa /boot/menu.rc
+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 print_version
+Prints the contents of the
+.Va loader_version
+environment variable right-justified at the column
+.Va loader_version_x
+and row
+.Va loader_version_y .
+.El
+.Pp
+The environment variables that effect its behavior are:
+.Bl -tag -width bootfile -offset indent
+.It Va loader_version
+Set automatically by
+.Xr loader 8 ,
+but you can override it by setting in
+.Xr loader.conf 5 .
+This should be the version of boot loader used.
+.It Va loader_version_x
+Sets the desired ending column position of
+.Va loader_version .
+Default is 80.
+.It Va loader_version_y
+Sets the desired ending row position of
+.Va loader_version .
+Default is 24.
+.It Va loader_color
+If set to
+.Dq Li NO
+(case-insensitive) or
+.Dq Li 0 ,
+causes the version to be printed without color
+.Pq default is ANSI Cyan .
+.El
+.Sh FILES
+.Bl -tag -width /boot/version.4th -compact
+.It Pa /boot/loader
+The
+.Xr loader 8 .
+.It Pa /boot/version.4th
+.Nm
+itself.
+.It Pa /boot/loader.rc
+.Xr loader 8
+bootstrapping script.
+.El
+.Sh EXAMPLES
+Override
+.Xr loader 8
+version in
+.Xr loader.conf 5 :
+.Pp
+.Bd -literal -offset indent -compact
+loader_version="loader 1.1"
+.Ed
+.Sh SEE ALSO
+.Xr loader.conf 5 ,
+.Xr color.4th 8 ,
+.Xr loader 8
+.Sh HISTORY
+The
+.Nm
+set of commands first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+set of commands was written by
+.An -nosplit
+.An Devin Teske Aq dteske@FreeBSD.org .