PageRenderTime 76ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/usr/src/boot/forth/loader.4th

https://github.com/illumos/illumos-gate
Forth | 635 lines | 569 code | 58 blank | 8 comment | 59 complexity | 31a007139a154cddf10d7961a2e5e08d MD5 | raw file
  1. \ Copyright (c) 1999 Daniel C. Sobral <dcs@FreeBSD.org>
  2. \ Copyright (c) 2011-2015 Devin Teske <dteske@FreeBSD.org>
  3. \ All rights reserved.
  4. \
  5. \ Redistribution and use in source and binary forms, with or without
  6. \ modification, are permitted provided that the following conditions
  7. \ are met:
  8. \ 1. Redistributions of source code must retain the above copyright
  9. \ notice, this list of conditions and the following disclaimer.
  10. \ 2. Redistributions in binary form must reproduce the above copyright
  11. \ notice, this list of conditions and the following disclaimer in the
  12. \ documentation and/or other materials provided with the distribution.
  13. \
  14. \ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. \ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. \ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. \ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. \ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. \ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. \ SUCH DAMAGE.
  25. \
  26. \ $FreeBSD$
  27. only forth definitions
  28. s" arch-i386" environment? [if] [if]
  29. s" loader_version" environment? [if]
  30. 11 < [if]
  31. .( Loader version 1.1+ required) cr
  32. abort
  33. [then]
  34. [else]
  35. .( Could not get loader version!) cr
  36. abort
  37. [then]
  38. [then] [then]
  39. include /boot/forth/support.4th
  40. include /boot/forth/color.4th
  41. include /boot/forth/delay.4th
  42. include /boot/forth/check-password.4th
  43. efi? [if]
  44. include /boot/forth/efi.4th
  45. [then]
  46. only forth definitions
  47. : bootmsg ( -- )
  48. loader_color? dup ( -- bool bool )
  49. if 7 fg 4 bg then
  50. ." Booting..."
  51. if me then
  52. cr
  53. ;
  54. : try-menu-unset
  55. \ menu-unset may not be present
  56. s" beastie_disable" getenv
  57. dup -1 <> if
  58. s" YES" compare-insensitive 0= if
  59. exit
  60. then
  61. else
  62. drop
  63. then
  64. s" menu-unset"
  65. sfind if
  66. execute
  67. else
  68. drop
  69. then
  70. s" menusets-unset"
  71. sfind if
  72. execute
  73. else
  74. drop
  75. then
  76. ;
  77. only forth also support-functions also builtins definitions
  78. \ the boot-args was parsed to individual options while loaded
  79. \ now compose boot-args, so the boot can set kernel arguments
  80. \ note the command line switched for boot command will cause
  81. \ environment variable boot-args to be ignored
  82. \ There are 2 larger strings, acpi-user-options and existing boot-args
  83. \ other switches are 1 byte each, so allocate boot-args+acpi + extra bytes
  84. \ for rest. Be sure to review this, if more options are to be added into
  85. \ environment.
  86. : set-boot-args { | addr len baddr blen aaddr alen -- }
  87. s" boot-args" getenv dup -1 <> if
  88. to blen to baddr
  89. else
  90. drop
  91. then
  92. s" acpi-user-options" getenv dup -1 <> if
  93. to alen to aaddr
  94. else
  95. drop
  96. then
  97. \ allocate temporary space. max is:
  98. \ 7 kernel switches
  99. \ 26 for acpi, so use 40 for safety
  100. blen alen 40 + + allocate abort" out of memory"
  101. to addr
  102. \ boot-addr may have file name before options, copy it to addr
  103. baddr 0<> if
  104. baddr c@ [char] - <> if
  105. baddr blen [char] - strchr ( addr len )
  106. dup 0= if \ no options, copy all
  107. 2drop
  108. baddr addr blen move
  109. blen to len
  110. 0 to blen
  111. 0 to baddr
  112. else ( addr len )
  113. dup blen
  114. swap -
  115. to len ( addr len )
  116. to blen ( addr )
  117. baddr addr len move ( addr )
  118. to baddr \ baddr points now to first option
  119. then
  120. then
  121. then
  122. \ now add kernel switches
  123. len 0<> if
  124. bl addr len + c! len 1+ to len
  125. then
  126. [char] - addr len + c! len 1+ to len
  127. s" boot_single" getenv dup -1 <> if
  128. s" YES" compare-insensitive 0= if
  129. [char] s addr len + c! len 1+ to len
  130. then
  131. else
  132. drop
  133. then
  134. s" boot_verbose" getenv dup -1 <> if
  135. s" YES" compare-insensitive 0= if
  136. [char] v addr len + c! len 1+ to len
  137. then
  138. else
  139. drop
  140. then
  141. s" boot_kmdb" getenv dup -1 <> if
  142. s" YES" compare-insensitive 0= if
  143. [char] k addr len + c! len 1+ to len
  144. then
  145. else
  146. drop
  147. then
  148. s" boot_drop_into_kmdb" getenv dup -1 <> if
  149. s" YES" compare-insensitive 0= if
  150. [char] d addr len + c! len 1+ to len
  151. then
  152. else
  153. drop
  154. then
  155. s" boot_reconfigure" getenv dup -1 <> if
  156. s" YES" compare-insensitive 0= if
  157. [char] r addr len + c! len 1+ to len
  158. then
  159. else
  160. drop
  161. then
  162. s" boot_ask" getenv dup -1 <> if
  163. s" YES" compare-insensitive 0= if
  164. [char] a addr len + c! len 1+ to len
  165. then
  166. else
  167. drop
  168. then
  169. \ now add remining boot args if blen != 0.
  170. \ baddr[0] is '-', if baddr[1] != 'B' append to addr,
  171. \ otherwise add space then copy
  172. blen 0<> if
  173. baddr 1+ c@ [char] B = if
  174. addr len + 1- c@ [char] - = if \ if addr[len -1] == '-'
  175. baddr 1+ to baddr
  176. blen 1- to blen
  177. else
  178. bl addr len + c! len 1+ to len
  179. then
  180. else
  181. baddr 1+ to baddr
  182. blen 1- to blen
  183. then
  184. baddr addr len + blen move
  185. len blen + to len
  186. 0 to baddr
  187. 0 to blen
  188. then
  189. \ last part - add acpi.
  190. alen 0<> if
  191. addr len + 1- c@ [char] - <> if
  192. bl addr len + c! len 1+ to len
  193. [char] - addr len + c! len 1+ to len
  194. then
  195. s" B acpi-user-options=" dup -rot ( len addr len )
  196. addr len + swap move ( len )
  197. len + to len
  198. aaddr addr len + alen move
  199. len alen + to len
  200. then
  201. \ check for left over '-'
  202. addr len 1- + c@ [char] - = if
  203. len 1- to len
  204. \ but now we may also have left over ' '
  205. len if ( len <> 0 )
  206. addr len 1- + c@ bl = if
  207. len 1- to len
  208. then
  209. then
  210. then
  211. \ if len != 0, set boot-args
  212. len 0<> if
  213. addr len s" boot-args" setenv
  214. then
  215. addr free drop
  216. ;
  217. : boot
  218. 0= if ( interpreted ) get_arguments then
  219. set-boot-args
  220. \ Unload only if a path was passed. Paths start with /
  221. dup if
  222. >r over r> swap
  223. c@ [char] / = if
  224. 0 1 unload drop
  225. else
  226. s" kernelname" getenv? if ( a kernel has been loaded )
  227. try-menu-unset
  228. bootmsg 1 boot exit
  229. then
  230. load_kernel_and_modules
  231. ?dup if exit then
  232. try-menu-unset
  233. bootmsg 0 1 boot exit
  234. then
  235. else
  236. s" kernelname" getenv? if ( a kernel has been loaded )
  237. try-menu-unset
  238. bootmsg 1 boot exit
  239. then
  240. load_kernel_and_modules
  241. ?dup if exit then
  242. try-menu-unset
  243. bootmsg 0 1 boot exit
  244. then
  245. load_kernel_and_modules
  246. ?dup 0= if bootmsg 0 1 boot then
  247. ;
  248. \ ***** boot-conf
  249. \
  250. \ Prepares to boot as specified by loaded configuration files.
  251. : boot-conf
  252. 0= if ( interpreted ) get_arguments then
  253. 0 1 unload drop
  254. load_kernel_and_modules
  255. ?dup 0= if 0 1 autoboot then
  256. ;
  257. also forth definitions previous
  258. builtin: boot
  259. builtin: boot-conf
  260. only forth definitions also support-functions
  261. \
  262. \ in case the boot-args is set, parse it and extract following options:
  263. \ -a to boot_ask=YES
  264. \ -s to boot_single=YES
  265. \ -v to boot_verbose=YES
  266. \ -k to boot_kmdb=YES
  267. \ -d to boot_drop_into_kmdb=YES
  268. \ -r to boot_reconfigure=YES
  269. \ -B acpi-user-options=X to acpi-user-options=X
  270. \
  271. \ This is needed so that the menu can manage these options. Unfortunately, this
  272. \ also means that boot-args will override previously set options, but we have no
  273. \ way to control the processing order here. boot-args will be rebuilt at boot.
  274. \
  275. \ NOTE: The best way to address the order is to *not* set any above options
  276. \ in boot-args.
  277. : parse-boot-args { | baddr blen -- }
  278. s" boot-args" getenv dup -1 = if drop exit then
  279. to blen
  280. to baddr
  281. baddr blen
  282. \ loop over all instances of switch blocks, starting with '-'
  283. begin
  284. [char] - strchr
  285. 2dup to blen to baddr
  286. dup 0<>
  287. while ( addr len ) \ points to -
  288. \ block for switch B. keep it on top of the stack for case
  289. \ the property list will get empty.
  290. over 1+ c@ [char] B = if
  291. 2dup \ save "-B ...." in case options is empty
  292. 2 - swap 2 + ( addr len len-2 addr+2 ) \ skip -B
  293. begin \ skip spaces
  294. dup c@ bl =
  295. while
  296. 1+ swap 1- swap
  297. repeat
  298. ( addr len len' addr' )
  299. \ its 3 cases now: end of string, -switch, or option list
  300. over 0= if \ end of string, remove trailing -B
  301. 2drop ( addr len )
  302. swap 0 swap c! \ store 0 at -B
  303. blen swap ( blen len )
  304. - ( rem )
  305. baddr swap ( addr rem )
  306. dup 0= if
  307. s" boot-args" unsetenv
  308. 2drop
  309. exit
  310. then
  311. \ trailing space(s)
  312. begin
  313. over ( addr rem addr )
  314. over + 1- ( addr rem addr+rem-1 )
  315. c@ bl =
  316. while
  317. 1- swap ( rem-1 addr )
  318. over ( rem-1 addr rem-1 )
  319. over + ( rem-1 addr addr+rem-1 )
  320. 0 swap c!
  321. swap
  322. repeat
  323. s" boot-args" setenv
  324. recurse \ restart
  325. exit
  326. then
  327. ( addr len len' addr' )
  328. dup c@ [char] - = if \ it is switch. set to boot-args
  329. swap s" boot-args" setenv
  330. 2drop
  331. recurse \ restart
  332. exit
  333. then
  334. ( addr len len' addr' )
  335. \ its options string "option1,option2,... -..."
  336. \ cut acpi-user-options=xxx and restart the parser
  337. \ or skip to next option block
  338. begin
  339. dup c@ dup 0<> swap bl <> and \ stop if space or 0
  340. while
  341. dup 18 s" acpi-user-options=" compare 0= if \ matched
  342. ( addr len len' addr' )
  343. \ addr' points to acpi options, find its end [',' or ' ' or 0 ]
  344. \ set it as acpi-user-options and move remaining to addr'
  345. 2dup ( addr len len' addr' len' addr' )
  346. \ skip to next option in list
  347. \ loop to first , or bl or 0
  348. begin
  349. dup c@ [char] , <> >r
  350. dup c@ bl <> >r
  351. dup c@ 0<> r> r> and and
  352. while
  353. 1+ swap 1- swap
  354. repeat
  355. ( addr len len' addr' len" addr" )
  356. >r >r ( addr len len' addr' R: addr" len" )
  357. over r@ - ( addr len len' addr' proplen R: addr" len" )
  358. dup 5 + ( addr len len' addr' proplen proplen+5 )
  359. allocate abort" out of memory"
  360. 0 s" set " strcat ( addr len len' addr' proplen caddr clen )
  361. >r >r 2dup r> r> 2swap strcat ( addr len len' addr' proplen caddr clen )
  362. 2dup + 0 swap c! \ terminate with 0
  363. 2dup evaluate drop free drop
  364. ( addr len len' addr' proplen R: addr" len" )
  365. \ acpi-user-options is set, now move remaining string to its place.
  366. \ addr: -B, addr': acpi... addr": reminder
  367. swap ( addr len len' proplen addr' )
  368. r> r> ( addr len len' proplen addr' len" addr" )
  369. dup c@ [char] , = if
  370. \ skip , and move addr" to addr'
  371. 1+ swap 1- ( addr len len' proplen addr' addr" len" )
  372. rot swap 1+ move ( addr len len' proplen )
  373. else \ its bl or 0 ( addr len len' proplen addr' len" addr" )
  374. \ for both bl and 0 we need to copy to addr'-1 to remove
  375. \ comma, then reset boot-args, and recurse will clear -B
  376. \ if there are no properties left.
  377. dup c@ 0= if
  378. 2drop ( addr len len' proplen addr' )
  379. 1- 0 swap c! ( addr len len' proplen )
  380. else
  381. >r >r ( addr len len' proplen addr' R: addr" len" )
  382. 1- swap 1+ swap
  383. r> r> ( addr len len' proplen addr' len" addr" )
  384. rot rot move ( addr len len' proplen )
  385. then
  386. then
  387. 2swap 2drop ( len' proplen )
  388. nip ( proplen )
  389. baddr blen rot -
  390. s" boot-args" setenv
  391. recurse
  392. exit
  393. else
  394. ( addr len len' addr' )
  395. \ not acpi option, skip to next option in list
  396. \ loop to first , or bl or 0
  397. begin
  398. dup c@ [char] , <> >r
  399. dup c@ bl <> >r
  400. dup c@ 0<> r> r> and and
  401. while
  402. 1+ swap 1- swap
  403. repeat
  404. \ if its ',', skip over
  405. dup c@ [char] , = if
  406. 1+ swap 1- swap
  407. then
  408. then
  409. repeat
  410. ( addr len len' addr' )
  411. \ this block is done, remove addr and len from stack
  412. 2swap 2drop swap
  413. then
  414. over c@ [char] - = if ( addr len )
  415. 2dup 1- swap 1+ ( addr len len' addr' )
  416. begin \ loop till ' ' or 0
  417. dup c@ dup 0<> swap bl <> and
  418. while
  419. dup c@ [char] s = if
  420. s" set boot_single=YES" evaluate TRUE
  421. else dup c@ [char] v = if
  422. s" set boot_verbose=YES" evaluate TRUE
  423. else dup c@ [char] k = if
  424. s" set boot_kmdb=YES" evaluate TRUE
  425. else dup c@ [char] d = if
  426. s" set boot_drop_into_kmdb=YES" evaluate TRUE
  427. else dup c@ [char] r = if
  428. s" set boot_reconfigure=YES" evaluate TRUE
  429. else dup c@ [char] a = if
  430. s" set boot_ask=YES" evaluate TRUE
  431. then then then then then then
  432. dup TRUE = if
  433. drop
  434. dup >r ( addr len len' addr' R: addr' )
  435. 1+ swap 1- ( addr len addr'+1 len'-1 R: addr' )
  436. r> swap move ( addr len )
  437. 2drop baddr blen 1-
  438. \ check if we have space after '-', if so, drop '- '
  439. swap dup 1+ c@ bl = if
  440. 2 + swap 2 -
  441. else
  442. swap
  443. then
  444. dup dup 0= swap 1 = or if \ empty or only '-' is left.
  445. 2drop
  446. s" boot-args" unsetenv
  447. exit
  448. else
  449. s" boot-args" setenv
  450. then
  451. recurse
  452. exit
  453. then
  454. 1+ swap 1- swap
  455. repeat
  456. 2swap 2drop
  457. dup c@ 0= if \ end of string
  458. 2drop
  459. exit
  460. else
  461. swap
  462. then
  463. then
  464. repeat
  465. 2drop
  466. ;
  467. \ ***** start
  468. \
  469. \ Initializes support.4th global variables, sets loader_conf_files,
  470. \ processes conf files, and, if any one such file was successfully
  471. \ read to the end, loads kernel and modules.
  472. : start ( -- ) ( throws: abort & user-defined )
  473. s" /boot/defaults/loader.conf" initialize
  474. include_bootenv
  475. include_conf_files
  476. include_transient
  477. \ If the user defined a post-initialize hook, call it now
  478. s" post-initialize" sfind if execute else drop then
  479. parse-boot-args
  480. \ Will *NOT* try to load kernel and modules if no configuration file
  481. \ was successfully loaded!
  482. any_conf_read? if
  483. s" loader_delay" getenv -1 = if
  484. load_xen_throw
  485. load_kernel
  486. load_modules
  487. else
  488. drop
  489. ." Loading Kernel and Modules (Ctrl-C to Abort)" cr
  490. s" also support-functions" evaluate
  491. s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate
  492. s" set delay_showdots" evaluate
  493. delay_execute
  494. then
  495. then
  496. ;
  497. \ ***** initialize
  498. \
  499. \ Overrides support.4th initialization word with one that does
  500. \ everything start one does, short of loading the kernel and
  501. \ modules. Returns a flag.
  502. : initialize ( -- flag )
  503. s" /boot/defaults/loader.conf" initialize
  504. include_bootenv
  505. include_conf_files
  506. include_transient
  507. \ If the user defined a post-initialize hook, call it now
  508. s" post-initialize" sfind if execute else drop then
  509. parse-boot-args
  510. any_conf_read?
  511. ;
  512. \ ***** read-conf
  513. \
  514. \ Read a configuration file, whose name was specified on the command
  515. \ line, if interpreted, or given on the stack, if compiled in.
  516. : (read-conf) ( addr len -- )
  517. conf_files string=
  518. include_conf_files \ Will recurse on new loader_conf_files definitions
  519. ;
  520. : read-conf ( <filename> | addr len -- ) ( throws: abort & user-defined )
  521. state @ if
  522. \ Compiling
  523. postpone (read-conf)
  524. else
  525. \ Interpreting
  526. bl parse (read-conf)
  527. then
  528. ; immediate
  529. \ show, enable, disable, toggle module loading. They all take module from
  530. \ the next word
  531. : set-module-flag ( module_addr val -- ) \ set and print flag
  532. over module.flag !
  533. dup module.name strtype
  534. module.flag @ if ." will be loaded" else ." will not be loaded" then cr
  535. ;
  536. : enable-module find-module ?dup if true set-module-flag then ;
  537. : disable-module find-module ?dup if false set-module-flag then ;
  538. : toggle-module find-module ?dup if dup module.flag @ 0= set-module-flag then ;
  539. \ ***** show-module
  540. \
  541. \ Show loading information about a module.
  542. : show-module ( <module> -- ) find-module ?dup if show-one-module then ;
  543. : set-module-path ( addr len <module> -- )
  544. find-module ?dup if
  545. module.loadname string=
  546. then
  547. ;
  548. \ Words to be used inside configuration files
  549. : retry false ; \ For use in load error commands
  550. : ignore true ; \ For use in load error commands
  551. \ Return to strict forth vocabulary
  552. : #type
  553. over - >r
  554. type
  555. r> spaces
  556. ;
  557. : .? 2 spaces 2swap 15 #type 2 spaces type cr ;
  558. : ?
  559. ['] ? execute
  560. s" boot-conf" s" load kernel and modules, then autoboot" .?
  561. s" read-conf" s" read a configuration file" .?
  562. s" enable-module" s" enable loading of a module" .?
  563. s" disable-module" s" disable loading of a module" .?
  564. s" toggle-module" s" toggle loading of a module" .?
  565. s" show-module" s" show module load data" .?
  566. s" try-include" s" try to load/interpret files" .?
  567. s" beadm" s" list or activate Boot Environments" .?
  568. ;
  569. : try-include ( -- ) \ see loader.4th(8)
  570. ['] include ( -- xt ) \ get the execution token of `include'
  571. catch ( xt -- exception# | 0 ) if \ failed
  572. LF parse ( c -- s-addr/u ) 2drop \ advance >in to EOL (drop data)
  573. \ ... prevents words unused by `include' from being interpreted
  574. then
  575. ; immediate \ interpret immediately for access to `source' (aka tib)
  576. include /boot/forth/beadm.4th
  577. only forth definitions