loader.4th revision 65621
1\ Copyright (c) 1999 Daniel C. Sobral <dcs@freebsd.org>
2\ All rights reserved.
3\
4\ Redistribution and use in source and binary forms, with or without
5\ modification, are permitted provided that the following conditions
6\ are met:
7\ 1. Redistributions of source code must retain the above copyright
8\    notice, this list of conditions and the following disclaimer.
9\ 2. Redistributions in binary form must reproduce the above copyright
10\    notice, this list of conditions and the following disclaimer in the
11\    documentation and/or other materials provided with the distribution.
12\
13\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16\ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23\ SUCH DAMAGE.
24\
25\ $FreeBSD: head/sys/boot/forth/loader.4th 65621 2000-09-08 21:11:57Z dcs $
26
27s" arch-alpha" environment? [if] [if]
28	s" loader_version" environment?  [if]
29		3 < [if]
30			.( Loader version 0.3+ required) cr
31			abort
32		[then]
33	[else]
34		.( Could not get loader version!) cr
35		abort
36	[then]
37[then] [then]
38
39s" arch-i386" environment? [if] [if]
40	s" loader_version" environment?  [if]
41		8 < [if]
42			.( Loader version 0.8+ required) cr
43			abort
44		[then]
45	[else]
46		.( Could not get loader version!) cr
47		abort
48	[then]
49[then] [then]
50
51include /boot/support.4th
52
53only forth definitions also support-functions
54
55\ ***** boot-conf
56\
57\	Prepares to boot as specified by loaded configuration files.
58
59also support-functions definitions
60
61: bootpath s" /boot/" ;
62: modulepath s" module_path" ;
63
64: saveenv ( addr len | 0 -1 -- addr' len | 0 -1 )
65  dup -1 = if exit then
66  dup allocate abort" Out of memory"
67  swap 2dup 2>r
68  move
69  2r>
70;
71
72: freeenv ( addr len | 0 -1 )
73  -1 = if drop else free abort" Freeing error" then
74;
75
76: restoreenv  ( addr len | 0 -1 -- )
77  dup -1 = if ( it wasn't set )
78    2drop
79    modulepath unsetenv
80  else
81    over >r
82    modulepath setenv
83    r> free abort" Freeing error"
84  then
85;
86
87: set-tempoptions  ( addrN lenN ... addr1 len1 N -- addr len 1 | 0 )
88  \ No options, set the default ones
89  dup 0= if
90    s" kernel_options" getenv dup -1 = if
91      drop
92    else
93      s" temp_options" setenv
94    then
95    exit
96  then
97
98  \ Skip filename
99  2 pick
100  c@
101  [char] - <> if
102    swap >r swap >r
103    1 >r  \ Filename present
104    1 -   \ One less argument
105  else
106    0 >r  \ Filename not present
107  then
108
109  \ If no other arguments exist, use default options
110  ?dup 0= if
111    s" kernel_options" getenv dup -1 = if
112      drop
113    else
114      s" temp_options" setenv
115    then
116    \ Put filename back on the stack, if necessary
117    r> if r> r> 1 else 0 then
118    exit
119  then
120
121  \ Concatenate remaining arguments into a single string
122  >r strdup r>
123  1 ?do
124    \ Allocate new buffer
125    2over nip over + 1+
126    allocate if out_of_memory throw then
127    \ Copy old buffer over
128    0 2swap over >r strcat
129    \ Free old buffer
130    r> free if free_error throw then
131    \ Copy a space
132    s"  " strcat
133    \ Copy next string (do not free)
134    2swap strcat
135  loop
136
137  \ Set temp_options variable, free whatever memory that needs freeing
138  over >r
139  s" temp_options" setenv
140  r> free if free_error throw then
141
142  \ Put filename back on the stack, if necessary
143  r> if r> r> 1 else 0 then
144;
145
146: get-arguments ( -- addrN lenN ... addr1 len1 N )
147  0
148  begin
149    \ Get next word on the command line
150    parse-word
151  ?dup while
152    2>r ( push to the rstack, so we can retrieve in the correct order )
153    1+
154  repeat
155  drop ( empty string )
156  dup
157  begin
158    dup
159  while
160    2r> rot
161    >r rot r>
162    1 -
163  repeat
164  drop
165;
166
167also builtins
168
169: load-kernel ( addr len -- addr len error? )
170  s" temp_options" getenv dup -1 = if
171    drop 2dup 1
172  else
173    2over 2
174  then
175
176  1 load
177;
178
179: load-conf  ( args 1 | 0 "args" -- flag )
180  0 1 unload drop
181
182  0= if ( interpreted ) get-arguments then
183  set-tempoptions
184
185  if ( there are arguments )
186    load-kernel if ( load command failed )
187      \ Set the environment variable module_path, and try loading
188      \ the kernel again.
189
190      \ First, save module_path value
191      modulepath getenv saveenv dup -1 = if 0 swap then 2>r
192
193      \ Sets the new value
194      2dup modulepath setenv
195
196      \ Try to load the kernel
197      s" load ${kernel} ${temp_options}" ['] evaluate catch
198      if ( load failed yet again )
199	\ Remove garbage from the stack
200	2drop
201
202	\ Try prepending /boot/
203	bootpath 2over nip over + allocate
204	if ( out of memory )
205	  2drop 2drop
206	  2r> restoreenv
207	  100 exit
208	then
209
210	0 2swap strcat 2swap strcat
211	2dup modulepath setenv
212
213	drop free if ( freeing memory error )
214	  2drop
215	  2r> restoreenv
216	  100 exit
217	then
218 
219	\ Now, once more, try to load the kernel
220	s" load ${kernel} ${temp_options}" ['] evaluate catch
221	if ( failed once more )
222	  2drop
223	  2r> restoreenv
224	  100 exit
225	then
226
227      else ( we found the kernel on the path passed )
228
229	2drop ( discard command line arguments )
230
231      then ( could not load kernel from directory passed )
232
233      \ Load the remaining modules, if the kernel was loaded at all
234      ['] load_modules catch if 2r> restoreenv 100 exit then
235
236      \ Return 0 to indicate success
237      0
238
239      \ Keep new module_path
240      2r> freeenv
241
242      exit
243    then ( could not load kernel with name passed )
244
245    2drop ( discard command line arguments )
246
247  else ( try just a straight-forward kernel load )
248    s" load ${kernel} ${temp_options}" ['] evaluate catch
249    if ( kernel load failed ) 2drop 100 exit then
250
251  then ( there are command line arguments )
252
253  \ Load the remaining modules, if the kernel was loaded at all
254  ['] load_modules catch if 100 exit then
255
256  \ Return 0 to indicate success
257  0
258;
259
260only forth also support-functions also builtins definitions
261
262: boot
263  load-conf
264  ?dup 0= if 0 1 boot then
265;
266
267: boot-conf
268  load-conf
269  ?dup 0= if 0 1 autoboot then
270;
271
272also forth definitions also builtins
273builtin: boot
274builtin: boot-conf
275only forth definitions also support-functions
276
277\ ***** check-password
278\
279\	If a password was defined, execute autoboot and ask for
280\	password if autoboot returns.
281
282: check-password
283  password .addr @ if
284    0 autoboot
285    false >r
286    begin
287      bell emit bell emit
288      ." Password: "
289      password .len @ read-password
290      dup password .len @ = if
291        2dup password .addr @ password .len @
292        compare 0= if r> drop true >r then
293      then
294      drop free drop
295      r@
296    until
297    r> drop
298  then
299;
300
301\ ***** start
302\
303\       Initializes support.4th global variables, sets loader_conf_files,
304\       process conf files, and, if any one such file was succesfully
305\       read to the end, load kernel and modules.
306
307: start  ( -- ) ( throws: abort & user-defined )
308  s" /boot/defaults/loader.conf" initialize
309  include_conf_files
310  \ Will *NOT* try to load kernel and modules if no configuration file
311  \ was succesfully loaded!
312  any_conf_read? if
313    load_kernel
314    load_modules
315  then
316;
317
318\ ***** initialize
319\
320\	Overrides support.4th initialization word with one that does
321\	everything start one does, short of loading the kernel and
322\	modules. Returns a flag
323
324: initialize ( -- flag )
325  s" /boot/defaults/loader.conf" initialize
326  include_conf_files
327  any_conf_read?
328;
329
330\ ***** read-conf
331\
332\	Read a configuration file, whose name was specified on the command
333\	line, if interpreted, or given on the stack, if compiled in.
334
335: (read-conf)  ( addr len -- )
336  conf_files .addr @ ?dup if free abort" Fatal error freeing memory" then
337  strdup conf_files .len ! conf_files .addr !
338  include_conf_files \ Will recurse on new loader_conf_files definitions
339;
340
341: read-conf  ( <filename> | addr len -- ) ( throws: abort & user-defined )
342  state @ if
343    \ Compiling
344    postpone (read-conf)
345  else
346    \ Interpreting
347    bl parse (read-conf)
348  then
349; immediate
350
351\ ***** enable-module
352\
353\       Turn a module loading on.
354
355: enable-module ( <module> -- )
356  bl parse module_options @ >r
357  begin
358    r@
359  while
360    2dup
361    r@ module.name dup .addr @ swap .len @
362    compare 0= if
363      2drop
364      r@ module.name dup .addr @ swap .len @ type
365      true r> module.flag !
366      ."  will be loaded." cr
367      exit
368    then
369    r> module.next @ >r
370  repeat
371  r> drop
372  type ."  wasn't found." cr
373;
374
375\ ***** disable-module
376\
377\       Turn a module loading off.
378
379: disable-module ( <module> -- )
380  bl parse module_options @ >r
381  begin
382    r@
383  while
384    2dup
385    r@ module.name dup .addr @ swap .len @
386    compare 0= if
387      2drop
388      r@ module.name dup .addr @ swap .len @ type
389      false r> module.flag !
390      ."  will not be loaded." cr
391      exit
392    then
393    r> module.next @ >r
394  repeat
395  r> drop
396  type ."  wasn't found." cr
397;
398
399\ ***** toggle-module
400\
401\       Turn a module loading on/off.
402
403: toggle-module ( <module> -- )
404  bl parse module_options @ >r
405  begin
406    r@
407  while
408    2dup
409    r@ module.name dup .addr @ swap .len @
410    compare 0= if
411      2drop
412      r@ module.name dup .addr @ swap .len @ type
413      r@ module.flag @ 0= dup r> module.flag !
414      if
415        ."  will be loaded." cr
416      else
417        ."  will not be loaded." cr
418      then
419      exit
420    then
421    r> module.next @ >r
422  repeat
423  r> drop
424  type ."  wasn't found." cr
425;
426
427\ ***** show-module
428\
429\	Show loading information about a module.
430
431: show-module ( <module> -- )
432  bl parse module_options @ >r
433  begin
434    r@
435  while
436    2dup
437    r@ module.name dup .addr @ swap .len @
438    compare 0= if
439      2drop
440      ." Name: " r@ module.name dup .addr @ swap .len @ type cr
441      ." Path: " r@ module.loadname dup .addr @ swap .len @ type cr
442      ." Type: " r@ module.type dup .addr @ swap .len @ type cr
443      ." Flags: " r@ module.args dup .addr @ swap .len @ type cr
444      ." Before load: " r@ module.beforeload dup .addr @ swap .len @ type cr
445      ." After load: " r@ module.afterload dup .addr @ swap .len @ type cr
446      ." Error: " r@ module.loaderror dup .addr @ swap .len @ type cr
447      ." Status: " r> module.flag @ if ." Load" else ." Don't load" then cr
448      exit
449    then
450    r> module.next @ >r
451  repeat
452  r> drop
453  type ."  wasn't found." cr
454;
455
456\ Words to be used inside configuration files
457
458: retry false ;         \ For use in load error commands
459: ignore true ;         \ For use in load error commands
460
461\ Return to strict forth vocabulary
462
463only forth also
464
465