summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authordcs <dcs@FreeBSD.org>2000-09-09 04:52:34 +0000
committerdcs <dcs@FreeBSD.org>2000-09-09 04:52:34 +0000
commit3fa988b3957e914ad876116d4dd6531bf41d5743 (patch)
treee6813cf3ef71c90f1ebb08b8675577f72d782754 /sys/boot
parente02c3d5c171cde15a56287fe8330da2857ee380a (diff)
downloadFreeBSD-src-3fa988b3957e914ad876116d4dd6531bf41d5743.zip
FreeBSD-src-3fa988b3957e914ad876116d4dd6531bf41d5743.tar.gz
First tackle at trying to handle the New Deal on kernels.
Load the first of the following kernels to be found: ${kernel} if ${kernel} is an absolute path /boot/${kernel}/${kernel} /boot/${kernel}/${bootfile} ${kernel}/${kernel} ${kernel}/${bootfile} ${kernel} ${bootfile} The last instance of ${kernel} and ${bootfile} will be treated as a list of semicolon separated file names, and each will be tried in turn, from left to right. Also, for each filename loader(8) will try filename, filename.ko, filename.gz, filename.ko.gz, in that order, but that's not related to this code. This resulted in a major reorganization of the code, and much of what was accumulating on loader.4th was rightly transfered to support.4th. The semantics of boot-conf and boot also changed. Both will try to load a kernel the same as above. After a kernel was loaded, the variable module_path may get changed. Such change will happen if the kernel was found with a directory prefix. In that case, the module path will be set to ${directory};${module_path}. Next, the modules are loaded as usual. This is intended so kernel="xyzzy" in /boot/loader.conf will load /boot/xyzzy/kernel.ko, load system modules from /boot/xyzzy/, and load third party modules from /boot/modules or /modules. If that doesn't work, it's a bug. Also, fix a breakage of "boot" which was recently introduced. Boot without any arguments would fail. No longer. Also, boot will only unload/reload if the first argument is a path. If no argument exists or the first argument is a flag, boot will use whatever is already loaded. I hope this is POLA. That behavior is markedly different from that of boot-conf, which will always unload/reload. The semantics introduced here are experimental. Even if the code works, we might decide this is not the prefered behavior. If you feel so, send your feedback. (Yeah, this belongs in a HEADS UP or something, but I've been working for the past 16 hours on this stuff, so gimme a break.)
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/forth/loader.4th126
-rw-r--r--sys/boot/forth/loader.conf4
-rw-r--r--sys/boot/forth/support.4th268
3 files changed, 280 insertions, 118 deletions
diff --git a/sys/boot/forth/loader.4th b/sys/boot/forth/loader.4th
index ef956e8..7a4dbcd 100644
--- a/sys/boot/forth/loader.4th
+++ b/sys/boot/forth/loader.4th
@@ -58,32 +58,6 @@ only forth definitions also support-functions
also support-functions definitions
-: bootpath s" /boot/" ;
-: modulepath s" module_path" ;
-
-: saveenv ( addr len | 0 -1 -- addr' len | 0 -1 )
- dup -1 = if exit then
- dup allocate abort" Out of memory"
- swap 2dup 2>r
- move
- 2r>
-;
-
-: 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
-;
-
: set-tempoptions ( addrN lenN ... addr1 len1 N -- addr len 1 | 0 )
\ No options, set the default ones
dup 0= if
@@ -166,105 +140,33 @@ also support-functions definitions
also builtins
-: load-kernel ( addr len -- addr len error? )
- s" temp_options" getenv dup -1 = if
- drop 2dup 1
- else
- 2over 2
- then
-
- 1 load
-;
-
: load-conf ( args 1 | 0 "args" -- flag )
- 0 1 unload drop
-
0= if ( interpreted ) get-arguments then
set-tempoptions
-
- if ( there are arguments )
- load-kernel if ( load command failed )
- \ Set the environment variable module_path, and try loading
- \ the kernel again.
-
- \ First, save module_path value
- modulepath getenv saveenv dup -1 = if 0 swap then 2>r
-
- \ Sets the new value
- 2dup modulepath setenv
-
- \ Try to load the kernel
- s" load ${kernel} ${temp_options}" ['] evaluate catch
- if ( load failed yet again )
- \ Remove garbage from the stack
- 2drop
-
- \ Try prepending /boot/
- bootpath 2over nip over + allocate
- if ( out of memory )
- 2drop 2drop
- 2r> restoreenv
- 100 exit
- then
-
- 0 2swap strcat 2swap strcat
- 2dup modulepath setenv
-
- drop free if ( freeing memory error )
- 2drop
- 2r> restoreenv
- 100 exit
- then
-
- \ Now, once more, try to load the kernel
- s" load ${kernel} ${temp_options}" ['] evaluate catch
- if ( failed once more )
- 2drop
- 2r> restoreenv
- 100 exit
- then
-
- else ( we found the kernel on the path passed )
-
- 2drop ( discard command line arguments )
-
- then ( could not load kernel from directory passed )
-
- \ Load the remaining modules, if the kernel was loaded at all
- ['] load_modules catch if 2r> restoreenv 100 exit then
-
- \ Return 0 to indicate success
- 0
-
- \ Keep new module_path
- 2r> freeenv
-
- exit
- then ( could not load kernel with name passed )
-
- 2drop ( discard command line arguments )
-
- else ( try just a straight-forward kernel load )
- s" load ${kernel} ${temp_options}" ['] evaluate catch
- if ( kernel load failed ) 2drop 100 exit then
-
- then ( there are command line arguments )
-
- \ Load the remaining modules, if the kernel was loaded at all
- ['] load_modules catch if 100 exit then
-
- \ Return 0 to indicate success
- 0
+ s" temp_options" getenv -1 <> if 2swap 2 else 1 then
+ load_kernel_and_modules
;
only forth also support-functions also builtins definitions
: boot
+ \ Unload only if a path was passed
+ >in @ parse-word rot >in !
+ if
+ c@ [char] - <> if
+ 0 1 unload drop
+ else
+ get-arguments 1 boot exit
+ then
+ else
+ 0 1 boot exit
+ then
load-conf
?dup 0= if 0 1 boot then
;
: boot-conf
+ 0 1 unload drop
load-conf
?dup 0= if 0 1 autoboot then
;
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 897eb40..916a491 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -43,10 +43,10 @@ bitmap_type="splash_image_data"
##############################################################
#autoboot_delay="10" # Delay in seconds before autobooting
-#bootfile="kernel,kernel.old" # Set the default boot file set
+bootfile="kernel" # Set the default boot file set
#console="vidconsole" # Set the current console
#currdev="disk1s1a" # Set the current device
-#module_path="/boot/modules;/modules;/boot/kernel" # Set the module search path
+module_path="/boot/modules;/modules;/boot/kernel" # 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
diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th
index 814e522..e3feb05 100644
--- a/sys/boot/forth/support.4th
+++ b/sys/boot/forth/support.4th
@@ -1218,17 +1218,277 @@ variable current_conf_files
repeat
;
-\ Additional functions used in "start"
+\ 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 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 "kernel" environment variable
+\ 2. The "bootfile" environment variable
+\
+\ Flags are passed, if available. The parameter args must be 2
+\ if flags are being passed, or 1 if they should be ignored.
+\ Dummy flags and len must be passed in the latter case.
+\
+\ The kernel gets loaded from the current module_path.
+
+: load_a_kernel ( flags len args -- flag )
+ local args
+ 2local flags
+ 0 0 2local kernel
+ end-locals
+
+ \ Check if a default kernel name exists at all, exits if not
+ s" kernel" getenv dup -1 <> if
+ to kernel
+ flags kernel args try_multiple_kernels
+ dup 0= if exit then
+ then
+ drop
+
+ s" bootfile" getenv dup -1 <> if
+ to kernel
+ else
+ drop
+ 1 exit \ Failure
+ then
+
+ \ Try all default kernel names
+ flags kernel args try_multiple_kernels
+;
+
+\ Try to load a kernel; the kernel name is taken from one of
+\ the following lists, as ordered:
+\
+\ 1. The "kernel" environment variable
+\ 2. The "bootfile" 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 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
+ path nip
+ 2dup to newmodulepath
+ modulepath setenv
+
+ \ Try all default kernel names
+ flags args 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 "kernel" environment variable
+\ 2. The "bootfile" 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
+;
+
+: load_kernel_and_modules ( flags len path len' 2 | path len' 1 -- flag )
+ load_directory_or_file
+ 0= if ['] load_modules catch then
+;
: initialize ( addr len -- )
strdup conf_files .len ! conf_files .addr !
;
-: load_kernel ( -- ) ( throws: abort )
- s" load ${kernel} ${kernel_options}" ['] evaluate catch
- if s" echo Unable to load kernel: ${kernel}" evaluate abort then
+: kernel_options ( -- addr len 2 | 0 0 1 )
+ s" kernel_options" getenv
+ dup -1 = if 0 0 1 else 2 then
+;
+
+: kernel_and_options
+ kernel_options
+ s" kernel" getenv
+ rot
;
+: load_kernel ( -- ) ( throws: abort )
+ s" kernel" getenv
+ dup -1 = if
+ \ If unset, try any kernel
+ drop
+ kernel_options load_a_kernel
+ else
+ \ If set, try first directory, next file name
+ kernel_options >r 2swap r> clip_args load_from_directory
+ dup if
+ drop
+ kernel_and_options try_multiple_kernels
+ then
+ then
+ abort" Unable to load a kernel!"
+;
+
: read-password { size | buf len -- }
size allocate if out_of_memory throw then
to buf
OpenPOWER on IntegriCloud