summaryrefslogtreecommitdiffstats
path: root/sys/boot/forth
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/forth')
-rw-r--r--sys/boot/forth/beastie.4th255
-rw-r--r--sys/boot/forth/frames.4th90
-rw-r--r--sys/boot/forth/loader.4th311
-rw-r--r--sys/boot/forth/loader.4th.8222
-rw-r--r--sys/boot/forth/loader.conf344
-rw-r--r--sys/boot/forth/loader.conf.5212
-rw-r--r--sys/boot/forth/loader.rc14
-rw-r--r--sys/boot/forth/pnp.4th172
-rw-r--r--sys/boot/forth/screen.4th36
-rw-r--r--sys/boot/forth/support.4th1713
10 files changed, 3369 insertions, 0 deletions
diff --git a/sys/boot/forth/beastie.4th b/sys/boot/forth/beastie.4th
new file mode 100644
index 0000000..76578c3
--- /dev/null
+++ b/sys/boot/forth/beastie.4th
@@ -0,0 +1,255 @@
+\ Copyright (c) 2003 Scott Long <scottl@freebsd.org>
+\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
+\ 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
+
+include /boot/screen.4th
+include /boot/frames.4th
+
+hide
+
+variable menuidx
+variable menubllt
+variable menuX
+variable menuY
+variable promptwidth
+
+variable bootkey
+variable bootacpikey
+variable bootsafekey
+variable bootverbosekey
+variable bootsinglekey
+variable escapekey
+variable rebootkey
+
+46 constant dot
+
+\ The BSD Daemon. He is 19 rows high and 34 columns wide
+: technicolor-beastie ( x y -- )
+2dup at-xy ." , ," 1+
+2dup at-xy ." /( )`" 1+
+2dup at-xy ." \ \___ / |" 1+
+2dup at-xy ." /- _ `-/ '" 1+
+2dup at-xy ." (/\/ \ \ /\" 1+
+2dup at-xy ." / / | ` \" 1+
+2dup at-xy ." O O ) / |" 1+
+2dup at-xy ." `-^--'`< '" 1+
+2dup at-xy ." (_.) _ ) /" 1+
+2dup at-xy ." `.___/` / " 1+
+2dup at-xy ." `-----' /" 1+
+2dup at-xy ." <----. __ / __ \" 1+
+2dup at-xy ." <----|====O)))==) \) /====|" 1+
+2dup at-xy ." <----' `--' `.__,' \" 1+
+2dup at-xy ." | |" 1+
+2dup at-xy ." \ / /\" 1+
+2dup at-xy ." ______( (_ / \______/" 1+
+2dup at-xy ." ,' ,-----' |" 1+
+at-xy ." `--{__________) " 1+
+;
+
+: boring-beastie ( x y -- )
+ 2dup at-xy ." , ," 1+
+ 2dup at-xy ." /( )`" 1+
+ 2dup at-xy ." \ \___ / |" 1+
+ 2dup at-xy ." /- _ `-/ '" 1+
+ 2dup at-xy ." (/\/ \ \ /\" 1+
+ 2dup at-xy ." / / | ` \" 1+
+ 2dup at-xy ." O O ) / |" 1+
+ 2dup at-xy ." `-^--'`< '" 1+
+ 2dup at-xy ." (_.) _ ) /" 1+
+ 2dup at-xy ." `.___/` /" 1+
+ 2dup at-xy ." `-----' /" 1+
+ 2dup at-xy ." <----. __ / __ \" 1+
+ 2dup at-xy ." <----|====O)))==) \) /====" 1+
+ 2dup at-xy ." <----' `--' `.__,' \" 1+
+ 2dup at-xy ." | |" 1+
+ 2dup at-xy ." \ / /\" 1+
+ 2dup at-xy ." ______( (_ / \______/" 1+
+ 2dup at-xy ." ,' ,-----' |" 1+
+ at-xy ." `--{__________)"
+;
+
+: print-beastie ( x y -- )
+ s" loader_color" getenv
+ dup -1 = if
+ drop
+ boring-beastie
+ exit
+ then
+ s" YES" compare-insensitive 0<> if
+ boring-beastie
+ exit
+ then
+ technicolor-beastie
+;
+
+: acpienabled? ( -- flag )
+ s" acpi_load" getenv
+ dup -1 = if
+ drop false exit
+ then
+ s" YES" compare-insensitive 0<> if
+ false exit
+ then
+ s" hint.acpi.0.disabled" getenv
+ dup -1 <> if
+ s" 0" compare 0<> if
+ false exit
+ then
+ then
+ true
+;
+
+: printmenuitem ( -- n )
+ menuidx @
+ 1+ dup
+ menuidx !
+ menuY @ + dup menuX @ swap at-xy
+ menuidx @ .
+ menuX @ 1+ swap at-xy
+ menubllt @ emit
+ menuidx @ 48 +
+;
+
+: beastie-menu ( -- )
+ 0 menuidx !
+ dot menubllt !
+ 8 menuY !
+ 5 menuX !
+ clear
+ 46 4 print-beastie
+ 42 20 2 2 box
+ 13 6 at-xy ." Welcome to FreeBSD!"
+ printmenuitem ." Boot FreeBSD [default]" bootkey !
+ s" arch-i386" environment? if
+ printmenuitem ." Boot FreeBSD with ACPI " bootacpikey !
+ acpienabled? if
+ ." disabled"
+ else
+ ." enabled"
+ then
+ else
+ -2 bootacpikey !
+ then
+ printmenuitem ." Boot FreeBSD in Safe Mode" bootsafekey !
+ printmenuitem ." Boot FreeBSD in single user mode" bootsinglekey !
+ printmenuitem ." Boot FreeBSD with verbose logging" bootverbosekey !
+ printmenuitem ." Escape to loader prompt" escapekey !
+ printmenuitem ." Reboot" rebootkey !
+ menuX @ 20 at-xy
+ ." Select option, [Enter] for default"
+ menuX @ 21 at-xy
+ s" or [Space] to pause timer " dup 2 - promptwidth !
+ type
+;
+
+: tkey
+ dup
+ seconds +
+ begin 1 while
+ over 0<> if
+ dup seconds u< if
+ drop
+ -1
+ exit
+ then
+ menuX @ promptwidth @ + 21 at-xy dup seconds - .
+ then
+ key? if
+ drop
+ key
+ exit
+ then
+ 50 ms
+ repeat
+;
+
+set-current
+
+: beastie-start
+ s" beastie_disable" getenv
+ dup -1 <> if
+ s" YES" compare-insensitive 0= if
+ exit
+ then
+ then
+ beastie-menu
+ s" autoboot_delay" getenv
+ dup -1 = if
+ drop
+ 10
+ else
+ 0 0 2swap >number drop drop drop
+ then
+ begin true while
+ dup tkey
+ 0 25 at-xy
+ dup 32 = if nip 0 swap then
+ dup -1 = if 0 boot then
+ dup 13 = if 0 boot then
+ dup bootkey @ = if 0 boot then
+ dup bootacpikey @ = if
+ acpienabled? if
+ s" acpi_load" unsetenv
+ s" 1" s" hint.acpi.0.disabled" setenv
+ s" 1" s" loader.acpi_disabled_by_user" setenv
+ else
+ s" YES" s" acpi_load" setenv
+ s" 0" s" hint.acpi.0.disabled" setenv
+ then
+ 0 boot
+ then
+ dup bootsafekey @ = if
+ s" arch-i386" environment? if
+ s" acpi_load" unsetenv
+ s" 1" s" hint.acpi.0.disabled" setenv
+ s" 1" s" loader.acpi_disabled_by_user" setenv
+ then
+ s" 0" s" hw.ata.ata_dma" setenv
+ s" 0" s" hw.ata.atapi_dma" setenv
+ s" 0" s" hw.ata.wc" setenv
+ s" 0" s" hw.eisa_slots" setenv
+ 0 boot
+ then
+ dup bootverbosekey @ = if
+ s" YES" s" boot_verbose" setenv
+ 0 boot
+ then
+ dup bootsinglekey @ = if
+ s" YES" s" boot_single" setenv
+ 0 boot
+ then
+ dup escapekey @ = if
+ 2drop
+ s" NO" s" autoboot_delay" setenv
+ exit
+ then
+ rebootkey @ = if 0 reboot then
+ repeat
+;
+
+previous
diff --git a/sys/boot/forth/frames.4th b/sys/boot/forth/frames.4th
new file mode 100644
index 0000000..ff91c5b
--- /dev/null
+++ b/sys/boot/forth/frames.4th
@@ -0,0 +1,90 @@
+\ Words implementing frame drawing
+\ XXX Filled boxes are left as an exercise for the reader... ;-/
+\ $FreeBSD$
+
+marker task-frames.4th
+
+variable h_el
+variable v_el
+variable lt_el
+variable lb_el
+variable rt_el
+variable rb_el
+variable fill
+
+\ 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
+
+
+: hline ( len x y -- ) \ Draw horizontal single line
+ at-xy \ move cursor
+ 0 do
+ h_el @ emit
+ loop
+;
+
+: f_single ( -- ) \ set frames to single
+ 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
+ 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 !
diff --git a/sys/boot/forth/loader.4th b/sys/boot/forth/loader.4th
new file mode 100644
index 0000000..8ffb02d
--- /dev/null
+++ b/sys/boot/forth/loader.4th
@@ -0,0 +1,311 @@
+\ 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$
+
+s" arch-alpha" environment? [if] [if]
+ s" loader_version" environment? [if]
+ 12 < [if]
+ .( Loader version 1.2+ required) cr
+ abort
+ [then]
+ [else]
+ .( Could not get loader version!) cr
+ abort
+ [then]
+[then] [then]
+
+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
+
+\ ***** boot-conf
+\
+\ Prepares to boot as specified by loaded configuration files.
+
+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 )
+ 1 boot exit
+ then
+ load_kernel_and_modules
+ ?dup if exit then
+ 0 1 boot exit
+ then
+ else
+ s" kernelname" getenv? if ( a kernel has been loaded )
+ 1 boot exit
+ then
+ load_kernel_and_modules
+ ?dup if exit then
+ 0 1 boot exit
+ then
+ load_kernel_and_modules
+ ?dup 0= if 0 1 boot then
+;
+
+: 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 also builtins
+
+builtin: boot
+builtin: boot-conf
+
+only forth definitions also support-functions
+
+\ ***** check-password
+\
+\ If a password was defined, execute autoboot and ask for
+\ password if autoboot returns.
+
+: check-password
+ password .addr @ if
+ 0 autoboot
+ false >r
+ begin
+ bell emit bell emit
+ ." Password: "
+ password .len @ read-password
+ dup password .len @ = if
+ 2dup password .addr @ password .len @
+ compare 0= if r> drop true >r then
+ then
+ drop free drop
+ r@
+ until
+ r> drop
+ then
+;
+
+\ ***** start
+\
+\ Initializes support.4th global variables, sets loader_conf_files,
+\ process conf files, and, if any one such file was succesfully
+\ read to the end, load kernel and modules.
+
+: start ( -- ) ( throws: abort & user-defined )
+ s" /boot/defaults/loader.conf" initialize
+ include_conf_files
+ include_nextboot_file
+ \ Will *NOT* try to load kernel and modules if no configuration file
+ \ was succesfully loaded!
+ any_conf_read? if
+ load_kernel
+ load_modules
+ 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
+ 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 .addr @ ?dup if free abort" Fatal error freeing memory" then
+ strdup conf_files .len ! conf_files .addr !
+ 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
+
+\ ***** enable-module
+\
+\ Turn a module loading on.
+
+: enable-module ( <module> -- )
+ bl parse module_options @ >r
+ begin
+ r@
+ while
+ 2dup
+ r@ module.name dup .addr @ swap .len @
+ compare 0= if
+ 2drop
+ r@ module.name dup .addr @ swap .len @ type
+ true r> module.flag !
+ ." will be loaded." cr
+ exit
+ then
+ r> module.next @ >r
+ repeat
+ r> drop
+ type ." wasn't found." cr
+;
+
+\ ***** disable-module
+\
+\ Turn a module loading off.
+
+: disable-module ( <module> -- )
+ bl parse module_options @ >r
+ begin
+ r@
+ while
+ 2dup
+ r@ module.name dup .addr @ swap .len @
+ compare 0= if
+ 2drop
+ r@ module.name dup .addr @ swap .len @ type
+ false r> module.flag !
+ ." will not be loaded." cr
+ exit
+ then
+ r> module.next @ >r
+ repeat
+ r> drop
+ type ." wasn't found." cr
+;
+
+\ ***** toggle-module
+\
+\ Turn a module loading on/off.
+
+: toggle-module ( <module> -- )
+ bl parse module_options @ >r
+ begin
+ r@
+ while
+ 2dup
+ r@ module.name dup .addr @ swap .len @
+ compare 0= if
+ 2drop
+ r@ module.name dup .addr @ swap .len @ type
+ r@ module.flag @ 0= dup r> module.flag !
+ if
+ ." will be loaded." cr
+ else
+ ." will not be loaded." cr
+ then
+ exit
+ then
+ r> module.next @ >r
+ repeat
+ r> drop
+ type ." wasn't found." cr
+;
+
+\ ***** show-module
+\
+\ Show loading information about a module.
+
+: show-module ( <module> -- )
+ bl parse module_options @ >r
+ begin
+ r@
+ while
+ 2dup
+ r@ module.name dup .addr @ swap .len @
+ compare 0= if
+ 2drop
+ ." Name: " r@ module.name dup .addr @ swap .len @ type cr
+ ." Path: " r@ module.loadname dup .addr @ swap .len @ type cr
+ ." Type: " r@ module.type dup .addr @ swap .len @ type cr
+ ." Flags: " r@ module.args dup .addr @ swap .len @ type cr
+ ." Before load: " r@ module.beforeload dup .addr @ swap .len @ type cr
+ ." After load: " r@ module.afterload dup .addr @ swap .len @ type cr
+ ." Error: " r@ module.loaderror dup .addr @ swap .len @ type cr
+ ." Status: " r> module.flag @ if ." Load" else ." Don't load" then cr
+ exit
+ then
+ r> module.next @ >r
+ repeat
+ r> drop
+ type ." wasn't found." cr
+;
+
+\ 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
+ 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" .?
+;
+
+only forth also
+
diff --git a/sys/boot/forth/loader.4th.8 b/sys/boot/forth/loader.4th.8
new file mode 100644
index 0000000..d5cf383
--- /dev/null
+++ b/sys/boot/forth/loader.4th.8
@@ -0,0 +1,222 @@
+.\" 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 April 25, 1999
+.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 isn't 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, and then proceeds to boot as specified in them.
+This
+is the command used in the default
+.Pa /boot/loader.rc
+file, and it uses the
+.Pa autoboot
+command (see
+.Xr loader 8 ) ,
+so it can be stopped for further interaction with
+.Xr loader 8 .
+.Pp
+.It Ic initialize
+Initialize the supporting library so commands can be used without
+executing
+.Ic start
+first.
+Like
+.Ic start ,
+reads
+.Pa /boot/defaults/loader.conf
+and all other
+.Xr loader.conf 5
+files specified in it.
+Returns a flag on the stack to indicate
+if any configuration file was 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.
+.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="/boot/kernel.old/kernel"
+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/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
new file mode 100644
index 0000000..18c34d0
--- /dev/null
+++ b/sys/boot/forth/loader.conf
@@ -0,0 +1,344 @@
+# 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=".( Loading /boot/defaults/loader.conf ) cr"
+
+kernel="kernel" # /boot sub-directory containing kernel and modules
+bootfile="kernel" # Kernel name (possibly absolute path)
+kernel_options=""
+
+userconfig_script_load="NO"
+userconfig_script_name="/boot/kernel.conf"
+userconfig_script_type="userconfig_script"
+
+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!
+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 bmp or pcx file
+bitmap_type="splash_image_data" # and place it on the module_path
+
+
+##############################################################
+### Loader settings ########################################
+##############################################################
+
+#autoboot_delay="10" # Delay in seconds before autobooting
+#beastie_disable="NO" # Turn the beastie boot menu on and off
+#console="vidconsole" # Set the current console
+#currdev="disk1s1a" # Set the current device
+module_path="/boot/kernel;/boot/modules" # 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
+
+
+##############################################################
+### Kernel settings ########################################
+##############################################################
+
+ # The following boot_ variables are enabled
+ # by setting them to any value.
+#boot_askname="" # Prompt the user for the name of the root device
+#boot_ddb="" # Instructs the kernel to start in the DDB debugger
+#boot_gdb="" # Selects gdb-remote mode for the kernel debugger
+#boot_single="" # Start system in single-user mode
+#boot_userconfig="" # Run kernel's interactive device configuration program
+#boot_verbose="" # Causes extra debugging information to be printed
+#init_path="/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall"
+ # Sets the list of init candidates
+#dumpdev="ad0s1b" # Set device for crash dumps
+
+
+##############################################################
+### Kernel tunables ########################################
+##############################################################
+
+#hw.physmem="1G" # Limit phyiscal 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.nbuf="" # Set the number of buffer headers
+#kern.ncallout="" # Set the maximum # of timer events
+#kern.sgrowsiz="" # Set the amount to grow stack
+#kern.cam.scsi_delay="2000" # Delay (in ms) before probing SCSI
+#kern.ipc.maxsockets="" # Set the maximum number of sockets avaliable
+#kern.ipc.nmbclusters="" # Set the number of mbuf clusters
+#kern.ipc.nmbufs="" # Set the maximum number of mbufs
+#kern.ipc.nsfbufs="" # Set the number of sendfile(2) bufs
+#kern.vm.kmem.size="" # Sets the size of kernel memory (bytes)
+#net.inet.tcp.tcbhashsize="" # Set the value of TCBHASHSIZE
+#vfs.root.mountfrom="" # Specify root partition in a way the
+ # kernel understands
+#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
+#net.graph.ngqfreemax="64" # Maximum number of free queue items to cache
+
+
+##############################################################
+### Filesystem and related modules #########################
+##############################################################
+
+# Filesystems
+
+cd9660_load="NO" # ISO 9660 filesystem
+coda_load="NO" # CODA filesystem
+fdescfs_load="NO" # Filedescriptors filesystem
+msdosfs_load="NO" # FAT-12/16/32
+nfs_load="NO" # NFS
+ntfs_load="NO" # NTFS
+nullfs_load="NO" # Null filesystem
+portalfs_load="NO" # Portal filesystem
+procfs_load="NO" # Process filesystem
+umapfs_load="NO" # User-id map filesystem
+unionfs_load="NO" # Union filesystem
+
+# Related stuff
+
+ccd_load="NO" # Concatenated disk driver
+vinum_load="NO" # Concatenated/mirror/raid driver
+md_load="NO" # Memory disk driver (vnode/swap/malloc)
+
+
+##############################################################
+### 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 ######################################
+##############################################################
+
+fpu_load="NO" # Floating point emulation
+gnufpu_load="NO" # GNU floating point emulation
+ibcs2_load="NO" # IBCS2 (SCO) emulation
+ibcs2_coff_load="NO"
+linux_load="NO" # Linux emulation
+svr4_load="NO" # SystemV R4 emulation
+streams_load="NO" # System V streams module
+
+
+##############################################################
+### Networking modules #####################################
+##############################################################
+
+if_disc_load="NO" # Discard device
+if_ef_load="NO" # pseudo-device providing support for multiple ethernet frame types
+if_faith_load="NO" # IPv6-to-IPv4 TCP relay capturing interface
+if_gif_load="NO" # generic tunnel interface
+if_gre_load="NO" # encapsulating network device
+if_ppp_load="NO" # Kernel ppp
+if_sl_load="NO" # SLIP
+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
+
+
+##############################################################
+### Networking drivers #####################################
+##############################################################
+
+miibus_load="NO" # miibus support, needed for some drivers
+if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs
+if_ar_load="NO" # Digi SYNC/570i
+if_awi_load="NO" # AMD PCnetMobile IEEE 802.11 wireless NICs
+if_bge_load="NO" # Broadcom BCM570x PCI gigabit ethernet
+if_cm_load="NO" # SMC (90c26, 90c56, 90c66)
+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_el_load="NO" # 3Com Etherlink 3C501
+if_em_load="NO" # Intel(R) PRO/1000 gigabit ethernet
+if_en_load="NO" # Midway-based ATM interfaces
+if_ep_load="NO" # 3Com Etherlink III (3c5x9)
+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_gx_load="NO" # Intel Pro/1000 gigabit ethernet
+if_ie_load="NO" # Intel 82586
+if_lge_load="NO" # Level 1 LXT1001 NetCellerator PCI gigabit ethernet
+if_lnc_load="NO" # AMD Lance/PCnet Ethernet
+if_my_load="NO" # Myson PCI fast ethernet
+if_nge_load="NO" # National Semiconductor PCI gigabit ethernet
+if_oltr_load="NO" # Olicom
+if_pcn_load="NO" # AMD PCnet PCI
+if_ray_load="NO" # Raytheon Raylink/Webgear Aviator PCCard
+if_rl_load="NO" # RealTek 8129/8139
+if_sbni_load="NO" # Granch SBNI12 leased line adapters
+if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire")
+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_sr_load="NO" # synchronous RISCom/N2 / WANic 400/405
+if_ste_load="NO" # Sundance Technologies ST201 fast 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_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_wx_load="NO" # Intel Gigabit Ethernet
+if_xe_load="NO" # Xircom CreditCard PCMCIA
+if_xl_load="NO" # 3Com Etherlink XL (3c900, 3c905, 3c905B)
+
+##############################################################
+### 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_ether_load="NO" # Ethernet netgraph node type
+ng_frame_relay_load="NO" # frame relay netgraph node type
+ng_hole_load="NO" # Netgraph discard node type
+ng_iface_load="NO" # interface Netgraph node type
+ng_ksocket_load="NO" # kernel socket 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_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_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
+
+##############################################################
+### Sound modules ##########################################
+##############################################################
+
+snd_pcm_load="NO" # Digital sound subsystem
+snd_ad1816_load="NO" # ad1816
+snd_cmi_load="NO" # cmi
+snd_csa_load="NO" # csa
+snd_cs4281_load="NO" # cs4281
+snd_ds1_load="NO" # ds1
+snd_emu10k1_load="NO" # Creative Sound Blaster Live
+snd_ess_load="NO" # ess
+snd_es137x_load="NO" # es137x
+snd_fm801_load="NO" # fm801
+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_sbc_load="NO" # Sbc
+snd_sb8_load="NO" # Sound Blaster Pro
+snd_sb16_load="NO" # Sound Blaster 16
+snd_solo_load="NO" # Solo
+snd_t4dwave_load="NO" # t4dwave
+snd_via8233_load="NO" # via8233
+snd_via82c686_load="NO" # via82c686
+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 ...
+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
+umodem_load="NO" # Modems
+uscanner_load="NO" # Scanners
+if_aue_load="NO" # ADMtek USB ethernet
+if_axe_load="NO" # ASIX Electronics AX88172 USB ethernet
+if_cue_load="NO" # CATC USB ethernet
+if_kue_load="NO" # Kawasaki LSI USB ethernet
+
+##############################################################
+### Other modules ##########################################
+##############################################################
+
+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_http_load="NO" # Wait for full HTTP request accept filter
+random_load="NO" # Random device
+atspeaker_load="NO" # AT speaker module
+
+##############################################################
+### 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
+
+##############################################################
+### 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/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5
new file mode 100644
index 0000000..89a803f
--- /dev/null
+++ b/sys/boot/forth/loader.conf.5
@@ -0,0 +1,212 @@
+.\" 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 April 18, 1999
+.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.
+.It Ar kernel_options
+Flags to be passed to the kernel.
+.It Ar password
+Provides a password to be required by check-password before execution is
+allowed to continue.
+.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
+.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 /boot/splash.bmp
+Name of the bitmap to be loaded. Any other name can be used.
+.It Va console
+.Pq Dq vidconsole
+.Dq comconsole
+selects serial console,
+.Dq vidconsole
+selects the video console, and
+.Dq nullconsole
+selects a mute console
+(useful for systems with neither a video console nor a serial port).
+.It Va kernel
+.Pq Dq /boot/kernel/kernel
+.It Va loader_conf_files
+.Pq Do /boot/loader.conf /boot/loader.conf.local Dc
+.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 userconfig_script_load
+.Pq Dq NO
+If set to
+.Dq YES ,
+will load the userconfig data.
+.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.
+.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 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 .
diff --git a/sys/boot/forth/loader.rc b/sys/boot/forth/loader.rc
new file mode 100644
index 0000000..9ba2f27
--- /dev/null
+++ b/sys/boot/forth/loader.rc
@@ -0,0 +1,14 @@
+\ Loader.rc
+\ $FreeBSD$
+\
+\ Includes additional commands
+include /boot/loader.4th
+
+\ Reads and processes loader.rc
+start
+
+\ Tests for password -- executes autoboot first if a password was defined
+check-password
+
+\ Unless set otherwise, autoboot is automatic at this point
+
diff --git a/sys/boot/forth/pnp.4th b/sys/boot/forth/pnp.4th
new file mode 100644
index 0000000..395164d
--- /dev/null
+++ b/sys/boot/forth/pnp.4th
@@ -0,0 +1,172 @@
+\ 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$
+
+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/sys/boot/forth/screen.4th b/sys/boot/forth/screen.4th
new file mode 100644
index 0000000..3ea79e4
--- /dev/null
+++ b/sys/boot/forth/screen.4th
@@ -0,0 +1,36 @@
+\ Screen manipulation related words.
+\ $FreeBSD$
+
+marker task-screen.4th
+
+: escc ( -- ) \ emit Esc-[
+ 91 27 emit emit
+;
+
+: ho ( -- ) \ Home cursor
+ escc 72 emit \ Esc-[H
+;
+
+: cld ( -- ) \ Clear from current position to end of display
+ escc 74 emit \ Esc-[J
+;
+
+: clear ( -- ) \ clear screen
+ ho cld
+;
+
+: at-xy ( x y -- ) \ move cursor to x rows, y cols (1-based coords)
+ escc .# 59 emit .# 72 emit \ Esc-[%d;%dH
+;
+
+: fg ( x -- ) \ Set foreground color
+ escc 3 .# .# 109 emit \ Esc-[3%dm
+;
+
+: bg ( x -- ) \ Set background color
+ escc 4 .# .# 109 emit \ Esc-[4%dm
+;
+
+: me ( -- ) \ Mode end (clear attributes)
+ escc 109 emit
+;
diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th
new file mode 100644
index 0000000..9da74b7
--- /dev/null
+++ b/sys/boot/forth/support.4th
@@ -0,0 +1,1713 @@
+\ 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_support ( -- ) initialize global variables
+\ 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
+\ string password password
+\ 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 succesfully read
+\
+\ Other exported words:
+\
+\ strdup ( addr len -- addr' len) similar to strdup(3)
+\ strcat ( addr len addr' len' -- addr len+len' ) similar to strcat(3)
+\ strlen ( addr -- len ) similar to strlen(3)
+\ s' ( | string' -- addr len | ) similar to s"
+\ rudimentary structure support
+
+\ Exception values
+
+1 constant syntax_error
+2 constant out_of_memory
+3 constant free_error
+4 constant set_error
+5 constant read_error
+6 constant open_error
+7 constant exec_error
+8 constant before_load_error
+9 constant after_load_error
+
+\ 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
+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
+
+structure: config_resource
+ ptr cf.name
+ int cf.type
+0 constant RES_INT
+1 constant RES_STRING
+2 constant RES_LONG
+ 2 cells member: u
+;structure
+
+structure: config_device
+ ptr cd.name
+ int cd.unit
+ int cd.resource_count
+ ptr cd.resources \ config_resource
+;structure
+
+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
+ 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
+
+\ Global variables
+
+string conf_files
+string nextboot_conf_file
+string password
+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 )
+ >r r@ allocate if out_of_memory throw then
+ tuck r@ move
+ r>
+;
+
+: strcat { addr len addr' len' -- addr len+len' }
+ addr' addr len + len' move
+ addr len len' +
+;
+
+: strlen ( addr -- len )
+ 0 >r
+ begin
+ dup c@ while
+ 1+ r> 1+ >r repeat
+ drop r>
+;
+
+: s'
+ [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
+;
+
+\ 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 funcitons
+
+: free-memory free if free_error throw 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 also
+
+\ File data temporary storage
+
+string read_buffer
+0 value read_buffer_ptr
+
+\ File's line reading function
+
+support-functions definitions
+
+string line_buffer
+0 value end_of_file?
+variable fd
+
+line-reading 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 out_of_memory throw then
+ else
+ r@ allocate if out_of_memory throw then
+ then
+ line_buffer .addr !
+ r>
+;
+
+: append_to_line_buffer ( addr len -- )
+ line_buffer .addr @ line_buffer .len @
+ 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 out_of_memory throw then
+ read_buffer .addr !
+ then
+ fd @ read_buffer .addr @ read_buffer_size fread
+ dup -1 = if read_error throw then
+ dup 0= if true to end_of_file? then
+ read_buffer .len !
+;
+
+: reset_line_buffer
+ line_buffer .addr @ ?dup if
+ free-memory
+ then
+ 0 line_buffer .addr !
+ 0 line_buffer .len !
+;
+
+support-functions definitions
+
+: reset_line_reading
+ 0 to read_buffer_ptr
+;
+
+: read_line
+ reset_line_buffer
+ 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 also
+
+0 value parsing_function
+0 value end_of_line
+
+: end_of_line?
+ line_pointer end_of_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] 0 >=
+ r> [char] 9 <= and
+;
+
+: 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] . =
+;
+
+: skip_character
+ line_pointer char+ to line_pointer
+;
+
+: skip_to_end_of_line
+ end_of_line to line_pointer
+;
+
+: eat_space
+ begin
+ space?
+ while
+ skip_character
+ end_of_line? if exit then
+ repeat
+;
+
+: parse_name ( -- addr len )
+ line_pointer
+ begin
+ letter? digit? underscore? dot? or or or
+ while
+ skip_character
+ end_of_line? if
+ line_pointer over -
+ strdup
+ exit
+ then
+ repeat
+ line_pointer over -
+ strdup
+;
+
+: remove_backslashes { addr len | addr' len' -- addr' len' }
+ len allocate if out_of_memory 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 syntax_error throw then
+ begin
+ quote? 0=
+ while
+ backslash? if
+ skip_character
+ end_of_line? if syntax_error throw then
+ then
+ skip_character
+ end_of_line? if syntax_error throw then
+ repeat
+ skip_character
+ line_pointer over -
+ remove_backslashes
+;
+
+: read_name
+ parse_name ( -- addr len )
+ name_buffer .len !
+ name_buffer .addr !
+;
+
+: read_value
+ quote? if
+ parse_quote ( -- addr len )
+ else
+ parse_name ( -- addr len )
+ then
+ value_buffer .len !
+ value_buffer .addr !
+;
+
+: comment
+ skip_to_end_of_line
+;
+
+: white_space_4
+ eat_space
+ comment? if ['] comment to parsing_function exit then
+ end_of_line? 0= if syntax_error 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
+ syntax_error 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
+ syntax_error 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 syntax_error throw then
+;
+
+file-processing definitions
+
+: get_assignment
+ line_buffer .addr @ line_buffer .len @ + 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 syntax_error throw then
+;
+
+only forth also support-functions also file-processing definitions also
+
+\ Process line
+
+: assignment_type? ( addr len -- flag )
+ name_buffer .addr @ name_buffer .len @
+ 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?
+;
+
+: password?
+ s" password" 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?
+;
+
+: set_conf_files
+ conf_files .addr @ ?dup if
+ free-memory
+ then
+ value_buffer .addr @ c@ [char] " = if
+ value_buffer .addr @ char+ value_buffer .len @ 2 chars -
+ else
+ value_buffer .addr @ value_buffer .len @
+ then
+ strdup
+ conf_files .len ! conf_files .addr !
+;
+
+: set_nextboot_conf
+ nextboot_conf_file .addr @ ?dup if
+ free-memory
+ then
+ value_buffer .addr @ c@ [char] " = if
+ value_buffer .addr @ char+ value_buffer .len @ 2 chars -
+ else
+ value_buffer .addr @ value_buffer .len @
+ then
+ strdup
+ nextboot_conf_file .len ! nextboot_conf_file .addr !
+;
+
+: 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 -- )
+ name_buffer .addr @ name_buffer .len @
+ strdup
+ >r over module.name .addr !
+ r> swap module.name .len !
+;
+
+: yes_value?
+ value_buffer .addr @ value_buffer .len @
+ 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 )
+ module_options @
+ begin
+ dup
+ while
+ dup module.name dup .addr @ swap .len @
+ name_buffer .addr @ name_buffer .len @
+ compare 0= if exit then
+ module.next @
+ repeat
+;
+
+: new_module_option ( -- addr )
+ sizeof module allocate if out_of_memory 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 !
+ get_module_option module.args
+ dup .addr @ ?dup if free-memory then
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 chars - swap char+ swap
+ then
+ strdup
+ >r over .addr !
+ r> swap .len !
+;
+
+: set_module_loadname
+ name_buffer .len @ module_loadname_suffix nip - name_buffer .len !
+ get_module_option module.loadname
+ dup .addr @ ?dup if free-memory then
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 chars - swap char+ swap
+ then
+ strdup
+ >r over .addr !
+ r> swap .len !
+;
+
+: set_module_type
+ name_buffer .len @ module_type_suffix nip - name_buffer .len !
+ get_module_option module.type
+ dup .addr @ ?dup if free-memory then
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 chars - swap char+ swap
+ then
+ strdup
+ >r over .addr !
+ r> swap .len !
+;
+
+: set_module_beforeload
+ name_buffer .len @ module_beforeload_suffix nip - name_buffer .len !
+ get_module_option module.beforeload
+ dup .addr @ ?dup if free-memory then
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 chars - swap char+ swap
+ then
+ strdup
+ >r over .addr !
+ r> swap .len !
+;
+
+: set_module_afterload
+ name_buffer .len @ module_afterload_suffix nip - name_buffer .len !
+ get_module_option module.afterload
+ dup .addr @ ?dup if free-memory then
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 chars - swap char+ swap
+ then
+ strdup
+ >r over .addr !
+ r> swap .len !
+;
+
+: set_module_loaderror
+ name_buffer .len @ module_loaderror_suffix nip - name_buffer .len !
+ get_module_option module.loaderror
+ dup .addr @ ?dup if free-memory then
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 chars - swap char+ swap
+ then
+ strdup
+ >r over .addr !
+ r> swap .len !
+;
+
+: set_environment_variable
+ name_buffer .len @
+ value_buffer .len @ +
+ 5 chars +
+ allocate if out_of_memory throw then
+ dup 0 ( addr -- addr addr len )
+ s" set " strcat
+ name_buffer .addr @ name_buffer .len @ strcat
+ s" =" strcat
+ value_buffer .addr @ value_buffer .len @ strcat
+ ['] evaluate catch if
+ 2drop free drop
+ set_error throw
+ else
+ free-memory
+ then
+;
+
+: set_nextboot_flag
+ yes_value? to nextboot?
+;
+
+: set_verbose
+ yes_value? to verbose?
+;
+
+: execute_command
+ value_buffer .addr @ value_buffer .len @
+ over c@ [char] " = if
+ 2 - swap char+ swap
+ then
+ ['] evaluate catch if exec_error throw then
+;
+
+: set_password
+ password .addr @ ?dup if free if free_error throw then then
+ value_buffer .addr @ c@ [char] " = if
+ value_buffer .addr @ char+ value_buffer .len @ 2 - strdup
+ value_buffer .addr @ free if free_error throw then
+ else
+ value_buffer .addr @ value_buffer .len @
+ then
+ password .len ! password .addr !
+ 0 value_buffer .addr !
+;
+
+: 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
+ password? if set_password 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 .addr @ dup if free then
+ value_buffer .addr @ dup if free then
+ or if free_error throw then
+;
+
+: reset_assignment_buffers
+ 0 name_buffer .addr !
+ 0 name_buffer .len !
+ 0 value_buffer .addr !
+ 0 value_buffer .len !
+;
+
+\ Higher level file processing
+
+support-functions definitions
+
+: process_conf
+ begin
+ end_of_file? 0=
+ while
+ reset_assignment_buffers
+ read_line
+ get_assignment
+ ['] process_assignment catch
+ ['] free_buffers catch
+ swap throw throw
+ repeat
+;
+
+: peek_file
+ 0 to end_of_file?
+ reset_line_reading
+ O_RDONLY fopen fd !
+ fd @ -1 = if open_error throw then
+ reset_assignment_buffers
+ read_line
+ get_assignment
+ ['] process_assignment catch
+ ['] free_buffers catch
+ fd @ fclose
+;
+
+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 open_error throw then
+ ['] process_conf catch
+ fd @ fclose
+ throw
+;
+
+: print_line
+ line_buffer .addr @ line_buffer .len @ type cr
+;
+
+: print_syntax_error
+ line_buffer .addr @ line_buffer .len @ type cr
+ line_buffer .addr @
+ begin
+ line_pointer over <>
+ while
+ bl emit
+ char+
+ repeat
+ drop
+ ." ^" cr
+;
+
+\ Depuration support functions
+
+only forth definitions also support-functions
+
+: test-file
+ ['] load_conf catch dup .
+ syntax_error = if cr print_syntax_error then
+;
+
+: show-module-options
+ module_options @
+ begin
+ ?dup
+ while
+ ." Name: " dup module.name dup .addr @ swap .len @ type cr
+ ." Path: " dup module.loadname dup .addr @ swap .len @ type cr
+ ." Type: " dup module.type dup .addr @ swap .len @ type cr
+ ." Flags: " dup module.args dup .addr @ swap .len @ type cr
+ ." Before load: " dup module.beforeload dup .addr @ swap .len @ type cr
+ ." After load: " dup module.afterload dup .addr @ swap .len @ type cr
+ ." Error: " dup module.loaderror dup .addr @ swap .len @ type cr
+ ." Status: " dup module.flag @ if ." Load" else ." Don't load" then cr
+ module.next @
+ repeat
+;
+
+only forth also support-functions definitions
+
+\ Variables used for processing multiple conf files
+
+string current_file_name
+variable current_conf_files
+
+\ Indicates if any conf file was succesfully read
+
+0 value any_conf_read?
+
+\ loader_conf_files processing support functions
+
+: set_current_conf_files
+ conf_files .addr @ current_conf_files !
+;
+
+: get_conf_files
+ conf_files .addr @ conf_files .len @ strdup
+;
+
+: recurse_on_conf_files?
+ current_conf_files @ conf_files .addr @ <>
+;
+
+: skip_leading_spaces { addr len pos -- addr len pos' }
+ begin
+ pos len = if addr len pos exit then
+ addr pos + c@ bl =
+ while
+ pos char+ to pos
+ repeat
+ addr len pos
+;
+
+: 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
+ addr pos + c@ bl <>
+ while
+ pos char+ to pos
+ pos len = if
+ addr len pos addr r@ + pos r> - exit
+ then
+ 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
+;
+
+: set_current_file_name
+ over current_file_name .addr !
+ dup current_file_name .len !
+;
+
+: print_current_file
+ current_file_name .addr @ current_file_name .len @ type
+;
+
+: process_conf_errors
+ dup 0= if true to any_conf_read? drop exit then
+ >r 2drop r>
+ dup syntax_error = if
+ ." Warning: syntax error on file " print_current_file cr
+ print_syntax_error drop exit
+ then
+ dup set_error = if
+ ." Warning: bad definition on file " print_current_file cr
+ print_line drop exit
+ then
+ dup read_error = if
+ ." Warning: error reading file " print_current_file cr drop exit
+ then
+ dup open_error = if
+ verbose? if ." Warning: unable to open file " print_current_file cr then
+ drop exit
+ then
+ dup free_error = abort" Fatal error freeing memory"
+ dup out_of_memory = abort" Out of memory"
+ throw \ Unknown error -- pass ahead
+;
+
+\ Process loader_conf_files recursively
+\ Interface to loader_conf_files processing
+
+: include_conf_files
+ set_current_conf_files
+ get_conf_files 0
+ begin
+ get_next_file ?dup
+ while
+ set_current_file_name
+ ['] load_conf catch
+ process_conf_errors
+ recurse_on_conf_files? if recurse then
+ repeat
+;
+
+: get_nextboot_conf_file ( -- addr len )
+ nextboot_conf_file .addr @ nextboot_conf_file .len @ strdup
+;
+
+: rewrite_nextboot_file ( -- )
+ get_nextboot_conf_file
+ O_WRONLY fopen fd !
+ fd @ -1 = if open_error throw then
+ fd @ s' nextboot_enable="NO" ' fwrite
+ fd @ fclose
+;
+
+: include_nextboot_file
+ get_nextboot_conf_file
+ ['] peek_file catch
+ nextboot? if
+ get_nextboot_conf_file
+ ['] load_conf catch
+ process_conf_errors
+ ['] rewrite_nextboot_file catch
+ then
+;
+
+\ Module loading functions
+
+: load_module?
+ module.flag @
+;
+
+: load_parameters ( addr -- addr addrN lenN ... addr1 len1 N )
+ dup >r
+ r@ module.args .addr @ r@ module.args .len @
+ r@ module.loadname .len @ if
+ r@ module.loadname .addr @ r@ module.loadname .len @
+ else
+ r@ module.name .addr @ r@ module.name .len @
+ then
+ r@ module.type .len @ if
+ r@ module.type .addr @ r@ module.type .len @
+ s" -t "
+ 4 ( -t type name flags )
+ else
+ 2 ( name flags )
+ then
+ r> drop
+;
+
+: before_load ( addr -- addr )
+ dup module.beforeload .len @ if
+ dup module.beforeload .addr @ over module.beforeload .len @
+ ['] evaluate catch if before_load_error throw then
+ then
+;
+
+: after_load ( addr -- addr )
+ dup module.afterload .len @ if
+ dup module.afterload .addr @ over module.afterload .len @
+ ['] evaluate catch if after_load_error throw then
+ then
+;
+
+: load_error ( addr -- addr )
+ dup module.loaderror .len @ if
+ dup module.loaderror .addr @ over module.loaderror .len @
+ evaluate \ This we do not intercept so it can throw errors
+ then
+;
+
+: pre_load_message ( addr -- addr )
+ verbose? if
+ dup module.name .addr @ over module.name .len @ type
+ ." ..."
+ then
+;
+
+: load_error_message verbose? if ." failed!" cr then ;
+
+: load_succesful_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_succesful_message true \ Succesful, do not retry
+ then
+ until
+;
+
+: process_module_errors ( addr ior -- )
+ dup before_load_error = if
+ drop
+ ." Module "
+ dup module.name .addr @ over module.name .len @ type
+ dup module.loadname .len @ if
+ ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )"
+ then
+ cr
+ ." Error executing "
+ dup module.beforeload .addr @ over module.afterload .len @ type cr
+ abort
+ then
+
+ dup after_load_error = if
+ drop
+ ." Module "
+ dup module.name .addr @ over module.name .len @ type
+ dup module.loadname .len @ if
+ ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )"
+ then
+ cr
+ ." Error executing "
+ dup module.afterload .addr @ over module.afterload .len @ type cr
+ abort
+ then
+
+ throw \ Don't know what it is all about -- pass ahead
+;
+
+\ Module loading interface
+
+: load_modules ( -- ) ( throws: abort & user-defined )
+ module_options @
+ begin
+ ?dup
+ while
+ dup load_module? 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 comma-separated list
+
+: parse-; ( addr len -- addr' len-x addr x )
+ over 0 2swap
+ begin
+ dup 0 <>
+ while
+ over c@ [char] ; <>
+ 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 succesful, 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
+ 0 0 2local newmodulepath
+ 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 +
+ oldmodulepath nip dup -1 = if
+ drop
+ else
+ 1+ +
+ then
+ allocate
+ if ( out of memory )
+ 1 exit
+ then
+
+ 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 succesful, 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 .len ! conf_files .addr !
+;
+
+: 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!"
+;
+
+: set_defaultoptions ( -- )
+ s" kernel_options" getenv dup -1 = if
+ drop
+ else
+ s" temp_options" setenv
+ then
+;
+
+: argv[] ( aN uN ... a1 u1 N i -- aN uN ... a1 u1 N ai+1 ui+1 )
+ 2dup = if 0 0 exit then
+ 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
+;
+
+: strlen(argv)
+ 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 out_of_memory throw then
+ 0 2>r
+
+ begin
+ argc
+ while
+ unqueue_argv
+ 2r> 2swap
+ strcat
+ s" " strcat
+ 2>r
+ 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 free_error 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
+ r> if ( a path was passed )
+ load_directory_or_file
+ else
+ standard_kernel_search
+ then
+ ?dup 0= if ['] load_modules catch then
+;
+
+: read-password { size | buf len -- }
+ size allocate if out_of_memory throw then
+ to buf
+ 0 to len
+ begin
+ key
+ dup backspace = if
+ drop
+ len if
+ backspace emit bl emit backspace emit
+ len 1 - to len
+ else
+ bell emit
+ then
+ else
+ dup <cr> = if cr drop buf len exit then
+ [char] * emit
+ len size < if
+ buf len chars + c!
+ else
+ drop
+ then
+ len 1+ to len
+ then
+ again
+;
+
+\ Go back to straight forth vocabulary
+
+only forth also definitions
+
OpenPOWER on IntegriCloud