Print this page
11581 'debug' loader option is a little obscure
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/boot/sys/boot/forth/menu.4th
+++ new/usr/src/boot/sys/boot/forth/menu.4th
1 1 \ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org>
2 2 \ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
3 3 \ Copyright (c) 2006-2015 Devin Teske <dteske@FreeBSD.org>
4 4 \ Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
5 5 \ All rights reserved.
6 6 \
7 7 \ Redistribution and use in source and binary forms, with or without
8 8 \ modification, are permitted provided that the following conditions
9 9 \ are met:
10 10 \ 1. Redistributions of source code must retain the above copyright
11 11 \ notice, this list of conditions and the following disclaimer.
12 12 \ 2. Redistributions in binary form must reproduce the above copyright
13 13 \ notice, this list of conditions and the following disclaimer in the
14 14 \ documentation and/or other materials provided with the distribution.
15 15 \
16 16 \ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 17 \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 18 \ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 19 \ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 20 \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 21 \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 22 \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 23 \ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 24 \ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 25 \ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 26 \ SUCH DAMAGE.
27 27
28 28 marker task-menu.4th
29 29
30 30 \ Frame drawing
31 31 include /boot/forth/frames.4th
32 32
33 33 vocabulary menu-infrastructure
34 34 vocabulary menu-namespace
35 35 vocabulary menu-command-helpers
36 36
37 37 only forth also menu-infrastructure definitions
38 38
39 39 f_double \ Set frames to double (see frames.4th). Replace with
40 40 \ f_single if you want single frames.
41 41 46 constant dot \ ASCII definition of a period (in decimal)
42 42
43 43 5 constant menu_default_x \ default column position of timeout
44 44 10 constant menu_default_y \ default row position of timeout msg
45 45 4 constant menu_timeout_default_x \ default column position of timeout
46 46 23 constant menu_timeout_default_y \ default row position of timeout msg
47 47 10 constant menu_timeout_default \ default timeout (in seconds)
48 48
49 49 \ Customize the following values with care
50 50
51 51 1 constant menu_start \ Numerical prefix of first menu item
52 52 dot constant bullet \ Menu bullet (appears after numerical prefix)
53 53 5 constant menu_x \ Row position of the menu (from the top)
54 54 10 constant menu_y \ Column position of the menu (from left side)
55 55
56 56 \ Menu Appearance
57 57 variable menuidx \ Menu item stack for number prefixes
58 58 variable menurow \ Menu item stack for positioning
59 59 variable menubllt \ Menu item bullet
60 60
61 61 \ Menu Positioning
62 62 variable menuX \ Menu X offset (columns)
63 63 variable menuY \ Menu Y offset (rows)
64 64
65 65 \ Menu-item elements
66 66 variable menurebootadded
67 67
68 68 \ Parsing of kernels into menu-items
69 69 variable kernidx
70 70 variable kernlen
71 71 variable kernmenuidx
72 72
73 73 \ Menu timer [count-down] variables
74 74 variable menu_timeout_enabled \ timeout state (internal use only)
75 75 variable menu_time \ variable for tracking the passage of time
76 76 variable menu_timeout \ determined configurable delay duration
77 77 variable menu_timeout_x \ column position of timeout message
78 78 variable menu_timeout_y \ row position of timeout message
79 79
80 80 \ Containers for parsing kernels into menu-items
81 81 create kerncapbuf 64 allot
82 82 create kerndefault 64 allot
83 83 create kernelsbuf 256 allot
84 84
85 85 only forth also menu-namespace definitions
86 86
87 87 \ Menu-item key association/detection
88 88 variable menukey1
89 89 variable menukey2
90 90 variable menukey3
91 91 variable menukey4
92 92 variable menukey5
93 93 variable menukey6
94 94 variable menukey7
95 95 variable menukey8
96 96 variable menureboot
97 97 variable menuacpi
98 98 variable menuosconsole
99 99 variable menuoptions
100 100 variable menukernel
101 101
102 102 \ Menu initialization status variables
103 103 variable init_state1
104 104 variable init_state2
105 105 variable init_state3
106 106 variable init_state4
107 107 variable init_state5
108 108 variable init_state6
109 109 variable init_state7
110 110 variable init_state8
111 111
112 112 \ Boolean option status variables
113 113 variable toggle_state1
114 114 variable toggle_state2
115 115 variable toggle_state3
116 116 variable toggle_state4
117 117 variable toggle_state5
118 118 variable toggle_state6
119 119 variable toggle_state7
120 120 variable toggle_state8
121 121
122 122 \ Array option status variables
123 123 variable cycle_state1
124 124 variable cycle_state2
125 125 variable cycle_state3
126 126 variable cycle_state4
127 127 variable cycle_state5
128 128 variable cycle_state6
129 129 variable cycle_state7
130 130 variable cycle_state8
131 131
132 132 \ Containers for storing the initial caption text
133 133 create init_text1 64 allot
134 134 create init_text2 64 allot
135 135 create init_text3 64 allot
136 136 create init_text4 64 allot
137 137 create init_text5 64 allot
138 138 create init_text6 64 allot
139 139 create init_text7 64 allot
140 140 create init_text8 64 allot
141 141
142 142 only forth definitions
143 143
144 144 : arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise.
145 145 s" arch-i386" environment? dup if
146 146 drop
147 147 then
148 148 ;
149 149
150 150 : acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise
151 151 s" hint.acpi.0.rsdp" getenv
152 152 dup -1 = if
153 153 drop false exit
154 154 then
155 155 2drop
156 156 true
157 157 ;
158 158
159 159 : acpienabled? ( -- flag ) \ Returns TRUE if ACPI is enabled, FALSE otherwise
160 160 s" hint.acpi.0.disabled" getenv
161 161 dup -1 <> if
162 162 s" 0" compare 0<> if
163 163 false exit
164 164 then
165 165 else
166 166 drop
167 167 then
168 168 true
169 169 ;
170 170
171 171 : +c! ( N C-ADDR/U K -- C-ADDR/U )
172 172 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr )
173 173 rot + c! ( n c-addr/u k n c-addr -- n c-addr/u )
174 174 rot drop ( n c-addr/u -- c-addr/u )
175 175 ;
176 176
177 177 only forth also menu-namespace definitions
178 178
179 179 \ Forth variables
180 180 : namespace ( C-ADDR/U N -- ) also menu-namespace +c! evaluate previous ;
181 181 : menukeyN ( N -- ADDR ) s" menukeyN" 7 namespace ;
182 182 : init_stateN ( N -- ADDR ) s" init_stateN" 10 namespace ;
183 183 : toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 namespace ;
184 184 : cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 namespace ;
185 185 : init_textN ( N -- C-ADDR ) s" init_textN" 9 namespace ;
186 186
187 187 \ Environment variables
188 188 : kernel[x] ( N -- C-ADDR/U ) s" kernel[x]" 7 +c! ;
189 189 : menu_init[x] ( N -- C-ADDR/U ) s" menu_init[x]" 10 +c! ;
190 190 : menu_command[x] ( N -- C-ADDR/U ) s" menu_command[x]" 13 +c! ;
191 191 : menu_caption[x] ( N -- C-ADDR/U ) s" menu_caption[x]" 13 +c! ;
192 192 : ansi_caption[x] ( N -- C-ADDR/U ) s" ansi_caption[x]" 13 +c! ;
193 193 : menu_keycode[x] ( N -- C-ADDR/U ) s" menu_keycode[x]" 13 +c! ;
194 194 : toggled_text[x] ( N -- C-ADDR/U ) s" toggled_text[x]" 13 +c! ;
195 195 : toggled_ansi[x] ( N -- C-ADDR/U ) s" toggled_ansi[x]" 13 +c! ;
196 196 : menu_caption[x][y] ( N M -- C-ADDR/U ) s" menu_caption[x][y]" 16 +c! 13 +c! ;
197 197 : ansi_caption[x][y] ( N M -- C-ADDR/U ) s" ansi_caption[x][y]" 16 +c! 13 +c! ;
198 198
199 199 also menu-infrastructure definitions
200 200
201 201 \ This function prints a menu item at menuX (row) and menuY (column), returns
202 202 \ the incremental decimal ASCII value associated with the menu item, and
203 203 \ increments the cursor position to the next row for the creation of the next
204 204 \ menu item. This function is called by the menu-create function. You need not
205 205 \ call it directly.
206 206 \
207 207 : printmenuitem ( menu_item_str -- ascii_keycode )
208 208
209 209 loader_color? if [char] ^ escc! then
210 210
211 211 menurow dup @ 1+ swap ! ( increment menurow )
212 212 menuidx dup @ 1+ swap ! ( increment menuidx )
213 213
214 214 \ Calculate the menuitem row position
215 215 menurow @ menuY @ +
216 216
217 217 \ Position the cursor at the menuitem position
218 218 dup menuX @ swap at-xy
219 219
220 220 \ Print the value of menuidx
221 221 loader_color? dup ( -- bool bool )
222 222 if b then
223 223 menuidx @ .
224 224 if me then
225 225
226 226 \ Move the cursor forward 1 column
227 227 dup menuX @ 1+ swap at-xy
228 228
229 229 menubllt @ emit \ Print the menu bullet using the emit function
230 230
231 231 \ Move the cursor to the 3rd column from the current position
232 232 \ to allow for a space between the numerical prefix and the
233 233 \ text caption
234 234 menuX @ 3 + swap at-xy
235 235
236 236 \ Print the menu caption (we expect a string to be on the stack
237 237 \ prior to invoking this function)
238 238 type
239 239
240 240 \ Here we will add the ASCII decimal of the numerical prefix
241 241 \ to the stack (decimal ASCII for `1' is 49) as a "return value"
242 242 menuidx @ 48 +
243 243 ;
244 244
245 245 : delim? ( C -- BOOL )
246 246 dup 32 = ( c -- c bool ) \ [sp] space
247 247 over 9 = or ( c bool -- c bool ) \ [ht] horizontal tab
248 248 over 10 = or ( c bool -- c bool ) \ [nl] newline
249 249 over 13 = or ( c bool -- c bool ) \ [cr] carriage return
250 250 over [char] , = or ( c bool -- c bool ) \ comma
251 251 swap drop ( c bool -- bool ) \ return boolean
252 252 ;
253 253
254 254 \ This function parses $kernels into variables that are used by the menu to
255 255 \ display which kernel to boot when the [overloaded] `boot' word is interpreted.
256 256 \ Used internally by menu-create, you need not (nor should you) call this
257 257 \ directly.
258 258 \
259 259 : parse-kernels ( N -- ) \ kernidx
260 260 kernidx ! ( n -- ) \ store provided `x' value
261 261 [char] 0 kernmenuidx ! \ initialize `y' value for menu_caption[x][y]
262 262
263 263 \ Attempt to get a list of kernels, fall back to sensible default
264 264 s" kernels" getenv dup -1 = if
265 265 drop ( cruft )
266 266 s" kernel kernel.old"
267 267 then ( -- c-addr/u )
268 268
269 269 \ Check to see if the user has altered $kernel by comparing it against
270 270 \ $kernel[N] where N is kernel_state (the actively displayed kernel).
271 271 s" kernel_state" evaluate @ 48 + s" kernel[N]" 7 +c! getenv
272 272 dup -1 <> if
273 273 s" kernel" getenv dup -1 = if
274 274 drop ( cruft ) s" "
275 275 then
276 276 2swap 2over compare 0= if
277 277 2drop FALSE ( skip below conditional )
278 278 else \ User has changed $kernel
279 279 TRUE ( slurp in new value )
280 280 then
281 281 else \ We haven't yet parsed $kernels into $kernel[N]
282 282 drop ( getenv cruft )
283 283 s" kernel" getenv dup -1 = if
284 284 drop ( cruft ) s" "
285 285 then
286 286 TRUE ( slurp in initial value )
287 287 then ( c-addr/u -- c-addr/u c-addr/u,-1 | 0 )
288 288 if \ slurp new value into kerndefault
289 289 kerndefault 1+ 0 2swap strcat swap 1- c!
290 290 then
291 291
292 292 \ Clear out existing parsed-kernels
293 293 kernidx @ [char] 0
294 294 begin
295 295 dup kernel[x] unsetenv
296 296 2dup menu_caption[x][y] unsetenv
297 297 2dup ansi_caption[x][y] unsetenv
298 298 1+ dup [char] 8 >
299 299 until
300 300 2drop
301 301
302 302 \ Step through the string until we find the end
303 303 begin
304 304 0 kernlen ! \ initialize length of value
305 305
306 306 \ Skip leading whitespace and/or comma delimiters
307 307 begin
308 308 dup 0<> if
309 309 over c@ delim? ( c-addr/u -- c-addr/u bool )
310 310 else
311 311 false ( c-addr/u -- c-addr/u bool )
312 312 then
313 313 while
314 314 1- swap 1+ swap ( c-addr/u -- c-addr'/u' )
315 315 repeat
316 316 ( c-addr/u -- c-addr'/u' )
317 317
318 318 dup 0= if \ end of string while eating whitespace
319 319 2drop ( c-addr/u -- )
320 320 kernmenuidx @ [char] 0 <> if \ found at least one
321 321 exit \ all done
322 322 then
323 323
324 324 \ No entries in $kernels; use $kernel instead
325 325 s" kernel" getenv dup -1 = if
326 326 drop ( cruft ) s" "
327 327 then ( -- c-addr/u )
328 328 dup kernlen ! \ store entire value length as kernlen
329 329 else
330 330 \ We're still within $kernels parsing toward the end;
331 331 \ find delimiter/end to determine kernlen
332 332 2dup ( c-addr/u -- c-addr/u c-addr/u )
333 333 begin dup 0<> while
334 334 over c@ delim? if
335 335 drop 0 ( break ) \ found delimiter
336 336 else
337 337 kernlen @ 1+ kernlen ! \ incrememnt
338 338 1- swap 1+ swap \ c-addr++ u--
339 339 then
340 340 repeat
341 341 2drop ( c-addr/u c-addr'/u' -- c-addr/u )
342 342
343 343 \ If this is the first entry, compare it to $kernel
344 344 \ If different, then insert $kernel beforehand
345 345 kernmenuidx @ [char] 0 = if
346 346 over kernlen @ kerndefault count compare if
347 347 kernelsbuf 0 kerndefault count strcat
348 348 s" ," strcat 2swap strcat
349 349 kerndefault count swap drop kernlen !
350 350 then
351 351 then
352 352 then
353 353 ( c-addr/u -- c-addr'/u' )
354 354
355 355 \ At this point, we should have something on the stack to store
356 356 \ as the next kernel menu option; start assembling variables
357 357
358 358 over kernlen @ ( c-addr/u -- c-addr/u c-addr/u2 )
359 359
360 360 \ Assign first to kernel[x]
361 361 2dup kernmenuidx @ kernel[x] setenv
362 362
363 363 \ Assign second to menu_caption[x][y]
364 364 kerncapbuf 0 s" [K]ernel: " strcat
365 365 2over strcat
366 366 kernidx @ kernmenuidx @ menu_caption[x][y]
367 367 setenv
368 368
369 369 \ Assign third to ansi_caption[x][y]
370 370 kerncapbuf 0 s" @[1mK@[37mernel: " [char] @ escc! strcat
371 371 kernmenuidx @ [char] 0 = if
372 372 s" default/@[32m"
373 373 else
374 374 s" @[34;1m"
375 375 then
376 376 [char] @ escc! strcat
377 377 2over strcat
378 378 s" @[37m" [char] @ escc! strcat
379 379 kernidx @ kernmenuidx @ ansi_caption[x][y]
380 380 setenv
381 381
382 382 2drop ( c-addr/u c-addr/u2 -- c-addr/u )
383 383
384 384 kernmenuidx @ 1+ dup kernmenuidx ! [char] 8 > if
385 385 2drop ( c-addr/u -- ) exit
386 386 then
387 387
388 388 kernlen @ - swap kernlen @ + swap ( c-addr/u -- c-addr'/u' )
389 389 again
390 390 ;
391 391
392 392 \ This function goes through the kernels that were discovered by the
393 393 \ parse-kernels function [above], adding " (# of #)" text to the end of each
394 394 \ caption.
395 395 \
396 396 : tag-kernels ( -- )
397 397 kernidx @ ( -- x ) dup 0= if exit then
398 398 [char] 0 s" (Y of Z)" ( x -- x y c-addr/u )
399 399 kernmenuidx @ -rot 7 +c! \ Replace 'Z' with number of kernels parsed
400 400 begin
401 401 2 pick 1+ -rot 2 +c! \ Replace 'Y' with current ASCII num
402 402
403 403 2over menu_caption[x][y] getenv dup -1 <> if
404 404 2dup + 1- c@ [char] ) = if
405 405 2drop \ Already tagged
406 406 else
407 407 kerncapbuf 0 2swap strcat
408 408 2over strcat
409 409 5 pick 5 pick menu_caption[x][y] setenv
410 410 then
411 411 else
412 412 drop ( getenv cruft )
413 413 then
414 414
415 415 2over ansi_caption[x][y] getenv dup -1 <> if
416 416 2dup + 1- c@ [char] ) = if
417 417 2drop \ Already tagged
418 418 else
419 419 kerncapbuf 0 2swap strcat
420 420 2over strcat
421 421 5 pick 5 pick ansi_caption[x][y] setenv
422 422 then
423 423 else
424 424 drop ( getenv cruft )
425 425 then
426 426
427 427 rot 1+ dup [char] 8 > if
428 428 -rot 2drop TRUE ( break )
429 429 else
430 430 -rot FALSE
431 431 then
432 432 until
433 433 2drop ( x y -- )
434 434 ;
↓ open down ↓ |
434 lines elided |
↑ open up ↑ |
435 435
436 436 \ Illumos kernel acpi-user-options has following values:
437 437 \ default: 0 - system will enable acpi based on bios date
438 438 \ on: 1 - acpi is set on
439 439 \ off: 2 - acpi is set off
440 440 \ madt: 4 - use only MADT
441 441 \ legacy: 8 - use legacy mode
442 442
443 443 : acpi-captions ( N -- )
444 444 \ first entry
445 - dup s" [A]CPI.... default" rot 48 menu_caption[x][y] setenv
446 - dup s" ^[1mA^[mCPI.... ^[32;7mdefault^[m" rot 48 ansi_caption[x][y] setenv
445 + dup s" [A]CPI.............. default" rot 48 menu_caption[x][y] setenv
446 + dup s" ^[1mA^[mCPI.............. ^[32;7mdefault^[m" rot 48 ansi_caption[x][y] setenv
447 447
448 - dup s" [A]CPI........ On" rot 49 menu_caption[x][y] setenv
449 - dup s" ^[1mA^[mCPI........ ^[34;1mOn^[m" rot 49 ansi_caption[x][y] setenv
448 + dup s" [A]CPI.............. On" rot 49 menu_caption[x][y] setenv
449 + dup s" ^[1mA^[mCPI.............. ^[34;1mOn^[m" rot 49 ansi_caption[x][y] setenv
450 450
451 - dup s" [A]CPI........ Off" rot 50 menu_caption[x][y] setenv
452 - dup s" ^[1mA^[mCPI........ ^[34;1mOff^[m" rot 50 ansi_caption[x][y] setenv
451 + dup s" [A]CPI.............. Off" rot 50 menu_caption[x][y] setenv
452 + dup s" ^[1mA^[mCPI.............. ^[34;1mOff^[m" rot 50 ansi_caption[x][y] setenv
453 453
454 - dup s" [A]CPI....... MADT" rot 51 menu_caption[x][y] setenv
455 - dup s" ^[1mA^[mCPI....... ^[34;1mMADT^[m" rot 51 ansi_caption[x][y] setenv
454 + dup s" [A]CPI.............. MADT" rot 51 menu_caption[x][y] setenv
455 + dup s" ^[1mA^[mCPI.............. ^[34;1mMADT^[m" rot 51 ansi_caption[x][y] setenv
456 456
457 - dup s" [A]CPI..... Legacy" rot 52 menu_caption[x][y] setenv
458 - s" ^[1mA^[mCPI..... ^[34;1mLegacy^[m" rot 52 ansi_caption[x][y] setenv
457 + dup s" [A]CPI.............. Legacy" rot 52 menu_caption[x][y] setenv
458 + s" ^[1mA^[mCPI.............. ^[34;1mLegacy^[m" rot 52 ansi_caption[x][y] setenv
459 459 ;
460 460
461 461 \ Illumos console has following values:
462 462 \ text, ttya, ttyb, ttyc, ttyd
463 463
464 464 : osconsole-captions ( N -- )
465 465 \ first entry
466 - dup s" Os[C]onsole.. text" rot 48 menu_caption[x][y] setenv
467 - dup s" Os^[1mC^[monsole.. ^[32;7mtext^[m" rot 48 ansi_caption[x][y] setenv
466 + dup s" Os[C]onsole............ text" rot 48 menu_caption[x][y] setenv
467 + dup s" Os^[1mC^[monsole............ ^[32;7mtext^[m" rot 48 ansi_caption[x][y] setenv
468 468
469 - dup s" Os[C]onsole.. ttya" rot 49 menu_caption[x][y] setenv
470 - dup s" Os^[1mC^[monsole.. ^[34;1mttya^[m" rot 49 ansi_caption[x][y] setenv
469 + dup s" Os[C]onsole............ ttya" rot 49 menu_caption[x][y] setenv
470 + dup s" Os^[1mC^[monsole............ ^[34;1mttya^[m" rot 49 ansi_caption[x][y] setenv
471 471
472 - dup s" Os[C]onsole.. ttyb" rot 50 menu_caption[x][y] setenv
473 - dup s" Os^[1mC^[monsole.. ^[34;1mttyb^[m" rot 50 ansi_caption[x][y] setenv
472 + dup s" Os[C]onsole............ ttyb" rot 50 menu_caption[x][y] setenv
473 + dup s" Os^[1mC^[monsole............ ^[34;1mttyb^[m" rot 50 ansi_caption[x][y] setenv
474 474
475 - dup s" Os[C]onsole.. ttyc" rot 51 menu_caption[x][y] setenv
476 - dup s" Os^[1mC^[monsole.. ^[34;1mttyc^[m" rot 51 ansi_caption[x][y] setenv
475 + dup s" Os[C]onsole............ ttyc" rot 51 menu_caption[x][y] setenv
476 + dup s" Os^[1mC^[monsole............ ^[34;1mttyc^[m" rot 51 ansi_caption[x][y] setenv
477 477
478 - dup s" Os[C]onsole.. ttyd" rot 52 menu_caption[x][y] setenv
479 - s" Os^[1mC^[monsole.. ^[34;1mttyd^[m" rot 52 ansi_caption[x][y] setenv
478 + dup s" Os[C]onsole............ ttyd" rot 52 menu_caption[x][y] setenv
479 + s" Os^[1mC^[monsole............ ^[34;1mttyd^[m" rot 52 ansi_caption[x][y] setenv
480 480 ;
481 481
482 482 \ This function creates the list of menu items. This function is called by the
483 483 \ menu-display function. You need not call it directly.
484 484 \
485 485 : menu-create ( -- )
486 486
487 487 \ Print the frame caption at (x,y)
488 488 s" loader_menu_title" getenv dup -1 = if
489 489 drop s" Welcome to illumos"
490 490 then
491 491 TRUE ( use default alignment )
492 492 s" loader_menu_title_align" getenv dup -1 <> if
493 493 2dup s" left" compare-insensitive 0= if ( 1 )
494 494 2drop ( c-addr/u ) drop ( bool )
495 495 menuX @ menuY @ 1-
496 496 FALSE ( don't use default alignment )
497 497 else ( 1 ) 2dup s" right" compare-insensitive 0= if ( 2 )
498 498 2drop ( c-addr/u ) drop ( bool )
499 499 menuX @ 42 + 4 - over - menuY @ 1-
500 500 FALSE ( don't use default alignment )
501 501 else ( 2 ) 2drop ( c-addr/u ) then ( 1 ) then
502 502 else
503 503 drop ( getenv cruft )
504 504 then
505 505 if ( use default center alignement? )
506 506 menuX @ 19 + over 2 / - menuY @ 1-
507 507 then
508 508 at-xy type
509 509
510 510 \ If $menu_init is set, evaluate it (allowing for whole menus to be
511 511 \ constructed dynamically -- as this function could conceivably set
512 512 \ the remaining environment variables to construct the menu entirely).
513 513 \
514 514 s" menu_init" getenv dup -1 <> if
515 515 evaluate
516 516 else
517 517 drop
518 518 then
519 519
520 520 \ Print our menu options with respective key/variable associations.
521 521 \ `printmenuitem' ends by adding the decimal ASCII value for the
522 522 \ numerical prefix to the stack. We store the value left on the stack
523 523 \ to the key binding variable for later testing against a character
524 524 \ captured by the `getkey' function.
525 525
526 526 \ Note that any menu item beyond 9 will have a numerical prefix on the
527 527 \ screen consisting of the first digit (ie. 1 for the tenth menu item)
528 528 \ and the key required to activate that menu item will be the decimal
529 529 \ ASCII of 48 plus the menu item (ie. 58 for the tenth item, aka. `:')
530 530 \ which is misleading and not desirable.
531 531 \
532 532 \ Thus, we do not allow more than 8 configurable items on the menu
533 533 \ (with "Reboot" as the optional ninth and highest numbered item).
534 534
535 535 \
536 536 \ Initialize the OsConsole option status.
537 537 \
538 538 0 menuosconsole !
539 539 s" menu_osconsole" getenv -1 <> if
540 540 c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
541 541 dup menuosconsole !
542 542 dup osconsole-captions
543 543
544 544 s" init_osconsole" evaluate
545 545
546 546 \ Get the current cycle state (entry to use)
547 547 s" osconsole_state" evaluate @ 48 + ( n -- n y )
548 548
549 549 \ Set the current non-ANSI caption
550 550 2dup swap dup ( n y -- n y y n n )
551 551 s" set menu_caption[x]=$menu_caption[x][y]"
552 552 17 +c! 34 +c! 37 +c! evaluate
553 553 ( n y y n n c-addr/u -- n y )
554 554
555 555 \ Set the current ANSI caption
556 556 2dup swap dup ( n y -- n y y n n )
557 557 s" set ansi_caption[x]=$ansi_caption[x][y]"
558 558 17 +c! 34 +c! 37 +c! evaluate
559 559 ( n y y n n c-addr/u -- n y )
560 560
561 561 \ Initialize cycle state from stored value
562 562 48 - ( n y -- n k )
563 563 s" init_cyclestate" evaluate ( n k -- n )
564 564
565 565 \ Set $os_console
566 566 s" activate_osconsole" evaluate ( n -- n )
567 567 then
568 568 drop
569 569 then
570 570
571 571 \
572 572 \ Initialize the ACPI option status.
573 573 \
574 574 0 menuacpi !
575 575 s" menu_acpi" getenv -1 <> if
576 576 c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
577 577 dup menuacpi !
578 578 dup acpi-captions
579 579
580 580 s" init_acpi" evaluate
581 581
582 582 \ Get the current cycle state (entry to use)
583 583 s" acpi_state" evaluate @ 48 + ( n -- n y )
584 584
585 585 \ Set the current non-ANSI caption
586 586 2dup swap dup ( n y -- n y y n n )
587 587 s" set menu_caption[x]=$menu_caption[x][y]"
588 588 17 +c! 34 +c! 37 +c! evaluate
589 589 ( n y y n n c-addr/u -- n y )
590 590
591 591 \ Set the current ANSI caption
592 592 2dup swap dup ( n y -- n y y n n )
593 593 s" set ansi_caption[x]=$ansi_caption[x][y]"
594 594 17 +c! 34 +c! 37 +c! evaluate
595 595 ( n y y n n c-addr/u -- n y )
596 596
597 597 \ Initialize cycle state from stored value
598 598 48 - ( n y -- n k )
599 599 s" init_cyclestate" evaluate ( n k -- n )
600 600
601 601 \ Set $acpi-user-options
602 602 s" activate_acpi" evaluate ( n -- n )
603 603 then
604 604 drop
605 605 then
606 606
607 607 \
608 608 \ Initialize kernel captions after parsing $kernels
609 609 \
610 610 0 menukernel !
611 611 s" menu_kernel" getenv -1 <> if
612 612 c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
613 613 dup menukernel !
614 614 dup parse-kernels tag-kernels
615 615
616 616 \ Get the current cycle state (entry to use)
617 617 s" kernel_state" evaluate @ 48 + ( n -- n y )
618 618
619 619 \ If state is invalid, reset
620 620 dup kernmenuidx @ 1- > if
621 621 drop [char] 0 ( n y -- n 48 )
622 622 0 s" kernel_state" evaluate !
623 623 over s" init_kernel" evaluate drop
624 624 then
625 625
626 626 \ Set the current non-ANSI caption
627 627 2dup swap dup ( n y -- n y y n n )
628 628 s" set menu_caption[x]=$menu_caption[x][y]"
629 629 17 +c! 34 +c! 37 +c! evaluate
630 630 ( n y y n n c-addr/u -- n y )
631 631
632 632 \ Set the current ANSI caption
633 633 2dup swap dup ( n y -- n y y n n )
634 634 s" set ansi_caption[x]=$ansi_caption[x][y]"
635 635 17 +c! 34 +c! 37 +c! evaluate
636 636 ( n y y n n c-addr/u -- n y )
637 637
638 638 \ Initialize cycle state from stored value
639 639 48 - ( n y -- n k )
640 640 s" init_cyclestate" evaluate ( n k -- n )
641 641
642 642 \ Set $kernel to $kernel[y]
643 643 s" activate_kernel" evaluate ( n -- n )
644 644 then
645 645 drop
646 646 then
647 647
648 648 \
649 649 \ Initialize the menu_options visual separator.
650 650 \
651 651 0 menuoptions !
652 652 s" menu_options" getenv -1 <> if
653 653 c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
654 654 menuoptions !
655 655 else
656 656 drop
657 657 then
658 658 then
659 659
660 660 \ Initialize "Reboot" menu state variable (prevents double-entry)
661 661 false menurebootadded !
662 662
663 663 menu_start
664 664 1- menuidx ! \ Initialize the starting index for the menu
665 665 0 menurow ! \ Initialize the starting position for the menu
666 666
667 667 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
668 668 begin
669 669 \ If the "Options:" separator, print it.
670 670 dup menuoptions @ = if
671 671 \ Optionally add a reboot option to the menu
672 672 s" menu_reboot" getenv -1 <> if
673 673 drop
674 674 s" Reboot" printmenuitem menureboot !
675 675 true menurebootadded !
676 676 then
677 677
678 678 menuX @
679 679 menurow @ 2 + menurow !
680 680 menurow @ menuY @ +
681 681 at-xy
682 682 s" menu_optionstext" getenv dup -1 <> if
683 683 type
684 684 else
685 685 drop ." Options:"
686 686 then
687 687 then
688 688
689 689 \ make sure we have not already initialized this item
690 690 dup init_stateN dup @ 0= if
691 691 1 swap !
692 692
693 693 \ If this menuitem has an initializer, run it
694 694 dup menu_init[x]
695 695 getenv dup -1 <> if
696 696 evaluate
697 697 else
698 698 drop
699 699 then
700 700 else
701 701 drop
702 702 then
703 703
704 704 dup
705 705 loader_color? if
706 706 ansi_caption[x]
707 707 else
708 708 menu_caption[x]
709 709 then
710 710
711 711 dup -1 <> if
712 712 \ test for environment variable
713 713 getenv dup -1 <> if
714 714 printmenuitem ( c-addr/u -- n )
715 715 dup menukeyN !
716 716 else
717 717 drop
718 718 then
719 719 else
720 720 drop
721 721 then
722 722
723 723 1+ dup 56 > \ add 1 to iterator, continue if less than 57
724 724 until
725 725 drop \ iterator
726 726
727 727 \ Optionally add a reboot option to the menu
728 728 menurebootadded @ true <> if
729 729 s" menu_reboot" getenv -1 <> if
730 730 drop \ no need for the value
731 731 s" Reboot" \ menu caption (required by printmenuitem)
732 732
733 733 printmenuitem
734 734 menureboot !
735 735 else
736 736 0 menureboot !
737 737 then
738 738 then
739 739 ;
740 740
741 741 \ Takes a single integer on the stack and updates the timeout display. The
742 742 \ integer must be between 0 and 9 (we will only update a single digit in the
743 743 \ source message).
744 744 \
745 745 : menu-timeout-update ( N -- )
746 746
747 747 \ Enforce minimum/maximum
748 748 dup 9 > if drop 9 then
749 749 dup 0 < if drop 0 then
750 750
751 751 s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u )
752 752
753 753 2 pick 0> if
754 754 rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to ASCII
755 755 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace 'N' above
756 756
757 757 menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
758 758 type ( c-addr/u -- ) \ print message
759 759 else
760 760 menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
761 761 spaces ( n c-addr/u -- n c-addr ) \ erase message
762 762 2drop ( n c-addr -- )
763 763 then
764 764
765 765 at-bl
766 766 ;
767 767
768 768 \ This function blocks program flow (loops forever) until a key is pressed.
769 769 \ The key that was pressed is added to the top of the stack in the form of its
770 770 \ decimal ASCII representation. This function is called by the menu-display
771 771 \ function. You need not call it directly.
772 772 \ note, the esc sequences will be dropped, this needs to be changed if
773 773 \ menu is built based on arrow keys.
774 774 \
775 775 : getkey ( -- ascii_keycode )
776 776
777 777 begin \ loop forever
778 778
779 779 menu_timeout_enabled @ 1 = if
780 780 ( -- )
781 781 seconds ( get current time: -- N )
782 782 dup menu_time @ <> if ( has time elapsed?: N N N -- N )
783 783
784 784 \ At least 1 second has elapsed since last loop
785 785 \ so we will decrement our "timeout" (really a
786 786 \ counter, insuring that we do not proceed too
787 787 \ fast) and update our timeout display.
788 788
789 789 menu_time ! ( update time record: N -- )
790 790 menu_timeout @ ( "time" remaining: -- N )
791 791 dup 0> if ( greater than 0?: N N 0 -- N )
792 792 1- ( decrement counter: N -- N )
793 793 dup menu_timeout !
794 794 ( re-assign: N N Addr -- N )
795 795 then
796 796 ( -- N )
797 797
798 798 dup 0= swap 0< or if ( N <= 0?: N N -- )
799 799 \ halt the timer
800 800 0 menu_timeout ! ( 0 Addr -- )
801 801 0 menu_timeout_enabled ! ( 0 Addr -- )
802 802 then
803 803
804 804 \ update the timer display ( N -- )
805 805 menu_timeout @ menu-timeout-update
806 806
807 807 menu_timeout @ 0= if
808 808 \ We've reached the end of the timeout
809 809 \ (user did not cancel by pressing ANY
810 810 \ key)
811 811
812 812 s" menu_timeout_command" getenv dup
813 813 -1 = if
814 814 drop \ clean-up
815 815 else
816 816 evaluate
817 817 then
818 818 then
819 819
820 820 else ( -- N )
821 821 \ No [detectable] time has elapsed (in seconds)
822 822 drop ( N -- )
823 823 then
824 824 ( -- )
825 825 then
826 826
827 827 key? if \ Was a key pressed? (see loader(8))
828 828
829 829 \ An actual key was pressed (if the timeout is running,
830 830 \ kill it regardless of which key was pressed)
831 831 menu_timeout @ 0<> if
832 832 0 menu_timeout !
833 833 0 menu_timeout_enabled !
834 834
835 835 \ clear screen of timeout message
836 836 0 menu-timeout-update
837 837 then
838 838
839 839 \ get the key that was pressed and exit (if we
840 840 \ get a non-zero ASCII code)
841 841 key dup 0<> if
842 842 dup 0x1b = if
843 843 key? if ( is it sequence? )
844 844 drop
845 845 begin
846 846 key?
847 847 while
848 848 key drop
849 849 repeat
850 850 else
851 851 exit
852 852 then
853 853 else
854 854 exit
855 855 then
856 856 else
857 857 drop
858 858 then
859 859 then
860 860 50 ms \ sleep for 50 milliseconds (see loader(8))
861 861
862 862 again
863 863 ;
864 864
865 865 : menu-erase ( -- ) \ Erases menu and resets positioning variable to position 1.
866 866
867 867 \ Clear the screen area associated with the interactive menu
868 868 menuX @ menuY @
869 869 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
870 870 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
871 871 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
872 872 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
873 873 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
874 874 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces
875 875 2drop
876 876
877 877 \ Reset the starting index and position for the menu
878 878 menu_start 1- menuidx !
879 879 0 menurow !
880 880 ;
881 881
882 882 only forth
883 883 also menu-infrastructure
884 884 also menu-namespace
885 885 also menu-command-helpers definitions
886 886
887 887 : toggle_menuitem ( N -- N ) \ toggles caption text and internal menuitem state
888 888
889 889 \ ASCII numeral equal to user-selected menu item must be on the stack.
890 890 \ We do not modify the stack, so the ASCII numeral is left on top.
891 891
892 892 dup init_textN c@ 0= if
893 893 \ NOTE: no need to check toggle_stateN since the first time we
894 894 \ are called, we will populate init_textN. Further, we don't
895 895 \ need to test whether menu_caption[x] (ansi_caption[x] when
896 896 \ loader_color?=1) is available since we would not have been
897 897 \ called if the caption was NULL.
898 898
899 899 \ base name of environment variable
900 900 dup ( n -- n n ) \ key pressed
901 901 loader_color? if
902 902 ansi_caption[x]
903 903 else
904 904 menu_caption[x]
905 905 then
906 906 getenv dup -1 <> if
907 907
908 908 2 pick ( n c-addr/u -- n c-addr/u n )
909 909 init_textN ( n c-addr/u n -- n c-addr/u c-addr )
910 910
911 911 \ now we have the buffer c-addr on top
912 912 \ ( followed by c-addr/u of current caption )
913 913
914 914 \ Copy the current caption into our buffer
915 915 2dup c! -rot \ store strlen at first byte
916 916 begin
917 917 rot 1+ \ bring alt addr to top and increment
918 918 -rot -rot \ bring buffer addr to top
919 919 2dup c@ swap c! \ copy current character
920 920 1+ \ increment buffer addr
921 921 rot 1- \ bring buffer len to top and decrement
922 922 dup 0= \ exit loop if buffer len is zero
923 923 until
924 924 2drop \ buffer len/addr
925 925 drop \ alt addr
926 926
927 927 else
928 928 drop
929 929 then
930 930 then
931 931
932 932 \ Now we are certain to have init_textN populated with the initial
933 933 \ value of menu_caption[x] (ansi_caption[x] with loader_color enabled).
934 934 \ We can now use init_textN as the untoggled caption and
935 935 \ toggled_text[x] (toggled_ansi[x] with loader_color enabled) as the
936 936 \ toggled caption and store the appropriate value into menu_caption[x]
937 937 \ (again, ansi_caption[x] with loader_color enabled). Last, we'll
938 938 \ negate the toggled state so that we reverse the flow on subsequent
939 939 \ calls.
940 940
941 941 dup toggle_stateN @ 0= if
942 942 \ state is OFF, toggle to ON
943 943
944 944 dup ( n -- n n ) \ key pressed
945 945 loader_color? if
946 946 toggled_ansi[x]
947 947 else
948 948 toggled_text[x]
949 949 then
950 950 getenv dup -1 <> if
951 951 \ Assign toggled text to menu caption
952 952 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
953 953 loader_color? if
954 954 ansi_caption[x]
955 955 else
956 956 menu_caption[x]
957 957 then
958 958 setenv
959 959 else
960 960 \ No toggled text, keep the same caption
961 961 drop ( n -1 -- n ) \ getenv cruft
962 962 then
963 963
964 964 true \ new value of toggle state var (to be stored later)
965 965 else
966 966 \ state is ON, toggle to OFF
967 967
968 968 dup init_textN count ( n -- n c-addr/u )
969 969
970 970 \ Assign init_textN text to menu caption
971 971 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
972 972 loader_color? if
973 973 ansi_caption[x]
974 974 else
975 975 menu_caption[x]
976 976 then
977 977 setenv
978 978
979 979 false \ new value of toggle state var (to be stored below)
980 980 then
981 981
982 982 \ now we'll store the new toggle state (on top of stack)
983 983 over toggle_stateN !
984 984 ;
985 985
986 986 : cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem
987 987
988 988 \ ASCII numeral equal to user-selected menu item must be on the stack.
989 989 \ We do not modify the stack, so the ASCII numeral is left on top.
990 990
991 991 dup cycle_stateN dup @ 1+ \ get value and increment
992 992
993 993 \ Before assigning the (incremented) value back to the pointer,
994 994 \ let's test for the existence of this particular array element.
995 995 \ If the element exists, we'll store index value and move on.
996 996 \ Otherwise, we'll loop around to zero and store that.
997 997
998 998 dup 48 + ( n addr k -- n addr k k' )
999 999 \ duplicate array index and convert to ASCII numeral
1000 1000
1001 1001 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y)
1002 1002 loader_color? if
1003 1003 ansi_caption[x][y]
1004 1004 else
1005 1005 menu_caption[x][y]
1006 1006 then
1007 1007 ( n addr k n k' -- n addr k c-addr/u )
1008 1008
1009 1009 \ Now test for the existence of our incremented array index in the
1010 1010 \ form of $menu_caption[x][y] ($ansi_caption[x][y] with loader_color
1011 1011 \ enabled) as set in loader.rc(5), et. al.
1012 1012
1013 1013 getenv dup -1 = if
1014 1014 \ No caption set for this array index. Loop back to zero.
1015 1015
1016 1016 drop ( n addr k -1 -- n addr k ) \ getenv cruft
1017 1017 drop 0 ( n addr k -- n addr 0 ) \ new value to store later
1018 1018
1019 1019 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y)
1020 1020 loader_color? if
1021 1021 ansi_caption[x][y]
1022 1022 else
1023 1023 menu_caption[x][y]
1024 1024 then
1025 1025 ( n addr 0 n 48 -- n addr 0 c-addr/u )
1026 1026 getenv dup -1 = if
1027 1027 \ Highly unlikely to occur, but to ensure things move
1028 1028 \ along smoothly, allocate a temporary NULL string
1029 1029 drop ( cruft ) s" "
1030 1030 then
1031 1031 then
1032 1032
1033 1033 \ At this point, we should have the following on the stack (in order,
1034 1034 \ from bottom to top):
1035 1035 \
1036 1036 \ n - Ascii numeral representing the menu choice (inherited)
1037 1037 \ addr - address of our internal cycle_stateN variable
1038 1038 \ k - zero-based number we intend to store to the above
1039 1039 \ c-addr/u - string value we intend to store to menu_caption[x]
1040 1040 \ (or ansi_caption[x] with loader_color enabled)
1041 1041 \
1042 1042 \ Let's perform what we need to with the above.
1043 1043
1044 1044 \ Assign array value text to menu caption
1045 1045 4 pick ( n addr k c-addr/u -- n addr k c-addr/u n )
1046 1046 loader_color? if
1047 1047 ansi_caption[x]
1048 1048 else
1049 1049 menu_caption[x]
1050 1050 then
1051 1051 setenv
1052 1052
1053 1053 swap ! ( n addr k -- n ) \ update array state variable
1054 1054 ;
1055 1055
1056 1056 only forth definitions also menu-infrastructure
1057 1057
1058 1058 \ Erase and redraw the menu. Useful if you change a caption and want to
1059 1059 \ update the menu to reflect the new value.
1060 1060 \
1061 1061 : menu-redraw ( -- )
1062 1062 menu-erase
1063 1063 menu-create
1064 1064 ;
1065 1065
1066 1066 \ This function initializes the menu. Call this from your `loader.rc' file
1067 1067 \ before calling any other menu-related functions.
1068 1068 \
1069 1069 : menu-init ( -- )
1070 1070 menu_start
1071 1071 1- menuidx ! \ Initialize the starting index for the menu
1072 1072 0 menurow ! \ Initialize the starting position for the menu
1073 1073
1074 1074 \ Assign configuration values
1075 1075 s" loader_menu_y" getenv dup -1 = if
1076 1076 drop \ no custom row position
1077 1077 menu_default_y
1078 1078 else
1079 1079 \ make sure custom position is a number
1080 1080 ?number 0= if
1081 1081 menu_default_y \ or use default
1082 1082 then
1083 1083 then
1084 1084 menuY !
1085 1085 s" loader_menu_x" getenv dup -1 = if
1086 1086 drop \ no custom column position
1087 1087 menu_default_x
1088 1088 else
1089 1089 \ make sure custom position is a number
1090 1090 ?number 0= if
1091 1091 menu_default_x \ or use default
1092 1092 then
1093 1093 then
1094 1094 menuX !
1095 1095
1096 1096 \ Interpret a custom frame type for the menu
1097 1097 TRUE ( draw a box? default yes, but might be altered below )
1098 1098 s" loader_menu_frame" getenv dup -1 = if ( 1 )
1099 1099 drop \ no custom frame type
1100 1100 else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 )
1101 1101 f_single ( see frames.4th )
1102 1102 else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 )
1103 1103 f_double ( see frames.4th )
1104 1104 else ( 3 ) s" none" compare-insensitive 0= if ( 4 )
1105 1105 drop FALSE \ don't draw a box
1106 1106 ( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then
1107 1107 if
1108 1108 42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y)
1109 1109 then
1110 1110
1111 1111 at-bl
1112 1112 ;
1113 1113
1114 1114 also menu-namespace
1115 1115
1116 1116 \ Main function. Call this from your `loader.rc' file.
1117 1117 \
1118 1118 : menu-display ( -- )
1119 1119
1120 1120 0 menu_timeout_enabled ! \ start with automatic timeout disabled
1121 1121
1122 1122 \ check indication that automatic execution after delay is requested
1123 1123 s" menu_timeout_command" getenv -1 <> if ( Addr C -1 -- | Addr )
1124 1124 drop ( just testing existence right now: Addr -- )
1125 1125
1126 1126 \ initialize state variables
1127 1127 seconds menu_time ! ( store the time we started )
1128 1128 1 menu_timeout_enabled ! ( enable automatic timeout )
1129 1129
1130 1130 \ read custom time-duration (if set)
1131 1131 s" autoboot_delay" getenv dup -1 = if
1132 1132 drop \ no custom duration (remove dup'd bunk -1)
1133 1133 menu_timeout_default \ use default setting
1134 1134 else
1135 1135 2dup ?number 0= if ( if not a number )
1136 1136 \ disable timeout if "NO", else use default
1137 1137 s" NO" compare-insensitive 0= if
1138 1138 0 menu_timeout_enabled !
1139 1139 0 ( assigned to menu_timeout below )
1140 1140 else
1141 1141 menu_timeout_default
1142 1142 then
1143 1143 else
1144 1144 -rot 2drop
1145 1145
1146 1146 \ boot immediately if less than zero
1147 1147 dup 0< if
1148 1148 drop
1149 1149 menu-create
1150 1150 at-bl
1151 1151 0 boot
1152 1152 then
1153 1153 then
1154 1154 then
1155 1155 menu_timeout ! ( store value on stack from above )
1156 1156
1157 1157 menu_timeout_enabled @ 1 = if
1158 1158 \ read custom column position (if set)
1159 1159 s" loader_menu_timeout_x" getenv dup -1 = if
1160 1160 drop \ no custom column position
1161 1161 menu_timeout_default_x \ use default setting
1162 1162 else
1163 1163 \ make sure custom position is a number
1164 1164 ?number 0= if
1165 1165 menu_timeout_default_x \ or use default
1166 1166 then
1167 1167 then
1168 1168 menu_timeout_x ! ( store value on stack from above )
1169 1169
1170 1170 \ read custom row position (if set)
1171 1171 s" loader_menu_timeout_y" getenv dup -1 = if
1172 1172 drop \ no custom row position
1173 1173 menu_timeout_default_y \ use default setting
1174 1174 else
1175 1175 \ make sure custom position is a number
1176 1176 ?number 0= if
1177 1177 menu_timeout_default_y \ or use default
1178 1178 then
1179 1179 then
1180 1180 menu_timeout_y ! ( store value on stack from above )
1181 1181 then
1182 1182 then
1183 1183
1184 1184 menu-create
1185 1185
1186 1186 begin \ Loop forever
1187 1187
1188 1188 at-bl
1189 1189 getkey \ Block here, waiting for a key to be pressed
1190 1190
1191 1191 dup -1 = if
1192 1192 drop exit \ Caught abort (abnormal return)
1193 1193 then
1194 1194
1195 1195 \ Boot if the user pressed Enter/Ctrl-M (13) or
1196 1196 \ Ctrl-Enter/Ctrl-J (10)
1197 1197 dup over 13 = swap 10 = or if
1198 1198 drop ( no longer needed )
1199 1199 s" boot" evaluate
1200 1200 exit ( pedantic; never reached )
1201 1201 then
1202 1202
1203 1203 dup menureboot @ = if 0 reboot then
1204 1204
1205 1205 \ Evaluate the decimal ASCII value against known menu item
1206 1206 \ key associations and act accordingly
1207 1207
1208 1208 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
1209 1209 begin
1210 1210 dup menukeyN @
1211 1211 rot tuck = if
1212 1212
1213 1213 \ Adjust for missing ACPI menuitem on non-i386
1214 1214 \ arch-i386? true <> menuacpi @ 0<> and if
1215 1215 \ menuacpi @ over 2dup < -rot = or
1216 1216 \ over 58 < and if
1217 1217 \ ( key >= menuacpi && key < 58: N -- N )
1218 1218 \ 1+
1219 1219 \ then
1220 1220 \ then
1221 1221
1222 1222 \ Test for the environment variable
1223 1223 dup menu_command[x]
1224 1224 getenv dup -1 <> if
1225 1225 \ Execute the stored procedure
1226 1226 evaluate
1227 1227
1228 1228 \ We expect there to be a non-zero
1229 1229 \ value left on the stack after
1230 1230 \ executing the stored procedure.
1231 1231 \ If so, continue to run, else exit.
1232 1232
1233 1233 0= if
1234 1234 drop \ key pressed
1235 1235 drop \ loop iterator
1236 1236 exit
1237 1237 else
1238 1238 swap \ need iterator on top
1239 1239 then
1240 1240 then
1241 1241
1242 1242 \ Re-adjust for missing ACPI menuitem
1243 1243 \ arch-i386? true <> menuacpi @ 0<> and if
1244 1244 \ swap
1245 1245 \ menuacpi @ 1+ over 2dup < -rot = or
1246 1246 \ over 59 < and if
1247 1247 \ 1-
1248 1248 \ then
1249 1249 \ swap
1250 1250 \ then
1251 1251 else
1252 1252 swap \ need iterator on top
1253 1253 then
1254 1254
1255 1255 \
1256 1256 \ Check for menu keycode shortcut(s)
1257 1257 \
1258 1258 dup menu_keycode[x]
1259 1259 getenv dup -1 = if
1260 1260 drop
1261 1261 else
1262 1262 ?number 0<> if
1263 1263 rot tuck = if
1264 1264 swap
1265 1265 dup menu_command[x]
1266 1266 getenv dup -1 <> if
1267 1267 evaluate
1268 1268 0= if
1269 1269 2drop
1270 1270 exit
1271 1271 then
1272 1272 else
1273 1273 drop
1274 1274 then
1275 1275 else
1276 1276 swap
1277 1277 then
1278 1278 then
1279 1279 then
1280 1280
1281 1281 1+ dup 56 > \ increment iterator
1282 1282 \ continue if less than 57
1283 1283 until
1284 1284 drop \ loop iterator
1285 1285 drop \ key pressed
1286 1286
1287 1287 again \ Non-operational key was pressed; repeat
1288 1288 ;
1289 1289
1290 1290 \ This function unsets all the possible environment variables associated with
1291 1291 \ creating the interactive menu.
1292 1292 \
1293 1293 : menu-unset ( -- )
1294 1294
1295 1295 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
1296 1296 begin
1297 1297 dup menu_init[x] unsetenv \ menu initializer
1298 1298 dup menu_command[x] unsetenv \ menu command
1299 1299 dup menu_caption[x] unsetenv \ menu caption
1300 1300 dup ansi_caption[x] unsetenv \ ANSI caption
1301 1301 dup menu_keycode[x] unsetenv \ menu keycode
1302 1302 dup toggled_text[x] unsetenv \ toggle_menuitem caption
1303 1303 dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI caption
1304 1304
1305 1305 48 \ Iterator start (inner range 48 to 57; ASCII '0' to '9')
1306 1306 begin
1307 1307 \ cycle_menuitem caption and ANSI caption
1308 1308 2dup menu_caption[x][y] unsetenv
1309 1309 2dup ansi_caption[x][y] unsetenv
1310 1310 1+ dup 57 >
1311 1311 until
1312 1312 drop \ inner iterator
1313 1313
1314 1314 0 over menukeyN ! \ used by menu-create, menu-display
1315 1315 0 over init_stateN ! \ used by menu-create
1316 1316 0 over toggle_stateN ! \ used by toggle_menuitem
1317 1317 0 over init_textN c! \ used by toggle_menuitem
1318 1318 0 over cycle_stateN ! \ used by cycle_menuitem
1319 1319
1320 1320 1+ dup 56 > \ increment, continue if less than 57
1321 1321 until
1322 1322 drop \ iterator
1323 1323
1324 1324 s" menu_timeout_command" unsetenv \ menu timeout command
1325 1325 s" menu_reboot" unsetenv \ Reboot menu option flag
1326 1326 s" menu_acpi" unsetenv \ ACPI menu option flag
1327 1327 s" menu_osconsole" unsetenv \ osconsole menu option flag
1328 1328 s" menu_kernel" unsetenv \ Kernel menu option flag
1329 1329 s" menu_options" unsetenv \ Options separator flag
1330 1330 s" menu_optionstext" unsetenv \ separator display text
1331 1331 s" menu_init" unsetenv \ menu initializer
1332 1332
1333 1333 0 menureboot !
1334 1334 0 menuacpi !
1335 1335 0 menuosconsole !
1336 1336 0 menuoptions !
1337 1337 ;
1338 1338
1339 1339 only forth definitions also menu-infrastructure
1340 1340
1341 1341 \ This function both unsets menu variables and visually erases the menu area
1342 1342 \ in-preparation for another menu.
1343 1343 \
1344 1344 : menu-clear ( -- )
1345 1345 menu-unset
1346 1346 menu-erase
1347 1347 ;
1348 1348
1349 1349 bullet menubllt !
1350 1350
1351 1351 also menu-namespace
1352 1352
1353 1353 \ Initialize our menu initialization state variables
1354 1354 0 init_state1 !
1355 1355 0 init_state2 !
1356 1356 0 init_state3 !
1357 1357 0 init_state4 !
1358 1358 0 init_state5 !
1359 1359 0 init_state6 !
1360 1360 0 init_state7 !
1361 1361 0 init_state8 !
1362 1362
1363 1363 \ Initialize our boolean state variables
1364 1364 0 toggle_state1 !
1365 1365 0 toggle_state2 !
1366 1366 0 toggle_state3 !
1367 1367 0 toggle_state4 !
1368 1368 0 toggle_state5 !
1369 1369 0 toggle_state6 !
1370 1370 0 toggle_state7 !
1371 1371 0 toggle_state8 !
1372 1372
1373 1373 \ Initialize our array state variables
1374 1374 0 cycle_state1 !
1375 1375 0 cycle_state2 !
1376 1376 0 cycle_state3 !
1377 1377 0 cycle_state4 !
1378 1378 0 cycle_state5 !
1379 1379 0 cycle_state6 !
1380 1380 0 cycle_state7 !
1381 1381 0 cycle_state8 !
1382 1382
1383 1383 \ Initialize string containers
1384 1384 0 init_text1 c!
1385 1385 0 init_text2 c!
1386 1386 0 init_text3 c!
1387 1387 0 init_text4 c!
1388 1388 0 init_text5 c!
1389 1389 0 init_text6 c!
1390 1390 0 init_text7 c!
1391 1391 0 init_text8 c!
1392 1392
1393 1393 only forth definitions
↓ open down ↓ |
904 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX