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/beadm.4th
+++ new/usr/src/boot/sys/boot/forth/beadm.4th
1 1 \
2 2 \ This file and its contents are supplied under the terms of the
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 \ Common Development and Distribution License ("CDDL"), version 1.0.
4 4 \ You may only use this file in accordance with the terms of version
5 5 \ 1.0 of the CDDL.
6 6 \
7 7 \ A full copy of the text of the CDDL should have accompanied this
8 8 \ source. A copy of the CDDL is also available via the Internet at
9 9 \ http://www.illumos.org/license/CDDL.
10 10
11 11 \ Copyright 2017 Toomas Soome <tsoome@me.com>
12 12 \ Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
13 +\ Copyright 2019 Joyent, Inc.
13 14
14 15 \ This module is implementing the beadm user command to support listing
15 16 \ and switching Boot Environments (BE) from command line and
16 17 \ support words to provide data for BE menu in loader menu system.
17 18 \ Note: this module needs an update to provide proper BE vocabulary.
18 19
19 20 only forth also support-functions also file-processing
20 21 also file-processing definitions also parser
21 22 also line-reading definitions also builtins definitions
22 23
23 24 variable page_count
24 25 variable page_remainder
25 26 0 page_count !
26 27 0 page_remainder !
27 28
28 29 \ from menu.4th
29 30 : +c! ( N C-ADDR/U K -- C-ADDR/U )
30 31 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr )
31 32 rot + c! ( n c-addr/u k n c-addr -- n c-addr/u )
32 33 rot drop ( n c-addr/u -- c-addr/u )
33 34 ;
34 35
35 36 : get_value ( -- )
36 37 eat_space
37 38 line_pointer
38 39 skip_to_end_of_line
39 40 line_pointer over -
40 41 strdup value_buffer strset
41 42 ['] exit to parsing_function
42 43 ;
43 44
44 45 : get_name ( -- )
45 46 read_name
46 47 ['] get_value to parsing_function
47 48 ;
48 49
49 50 : get_name_value
50 51 line_buffer strget + to end_of_line
51 52 line_buffer .addr @ to line_pointer
52 53 ['] get_name to parsing_function
53 54 begin
54 55 end_of_line? 0=
55 56 while
56 57 parsing_function execute
57 58 repeat
58 59 ;
59 60
60 61 \ beadm support
61 62 : beadm_longest_title ( addr len -- width )
62 63 0 to end_of_file?
63 64 O_RDONLY fopen fd !
64 65 reset_line_reading
65 66 fd @ -1 = if EOPEN throw then
66 67 0 >r \ length into return stack
67 68 begin
68 69 end_of_file? 0=
69 70 while
70 71 free_buffers
71 72 read_line
72 73 get_name_value
73 74 value_buffer .len @ r@ > if r> drop value_buffer .len @ >r then
74 75 free_buffers
75 76 read_line
76 77 repeat
77 78 fd @ fclose
78 79 r> 1 + \ space between columns
79 80 ;
80 81
81 82 \ Pretty print BE list
82 83 : beadm_list ( width addr len -- )
83 84 0 to end_of_file?
84 85 O_RDONLY fopen fd !
85 86 reset_line_reading
86 87 fd @ -1 = if EOPEN throw then
87 88 ." BE" dup 2 - spaces ." Type Device" cr
88 89 begin
89 90 end_of_file? 0=
90 91 while
91 92 free_buffers
92 93 read_line
93 94 get_name_value
94 95 value_buffer strget type
95 96 dup value_buffer .len @ - spaces
96 97 free_buffers
97 98 read_line
98 99 get_name_value
99 100 name_buffer strget type
100 101 name_buffer strget s" bootfs" compare 0= if 2 spaces then
101 102 name_buffer strget s" chain" compare 0= if 3 spaces then
102 103 value_buffer strget type cr
103 104 free_buffers
104 105 repeat
105 106 fd @ fclose
106 107 drop
107 108 ;
108 109
109 110 \ we are called with strings be_name menu_file, to simplify the stack
110 111 \ management, we open the menu and free the menu_file.
111 112 : beadm_bootfs ( be_addr be_len maddr mlen -- addr len taddr tlen flag | flag )
112 113 0 to end_of_file?
113 114 2dup O_RDONLY fopen fd !
114 115 drop free-memory
115 116 fd @ -1 = if EOPEN throw then
116 117 reset_line_reading
117 118 begin
118 119 end_of_file? 0=
119 120 while
120 121 free_buffers
121 122 read_line
122 123 get_name_value
123 124 2dup value_buffer strget compare
124 125 0= if ( title == be )
125 126 2drop \ drop be_name
126 127 free_buffers
127 128 read_line
128 129 get_name_value
129 130 value_buffer strget strdup
130 131 name_buffer strget strdup -1
131 132 free_buffers
132 133 1 to end_of_file? \ mark end of file to skip the rest
133 134 else
134 135 read_line \ skip over next line
135 136 then
136 137 repeat
137 138 fd @ fclose
138 139 line_buffer strfree
139 140 read_buffer strfree
140 141 dup -1 > if ( be_addr be_len )
141 142 2drop
142 143 0
143 144 then
144 145 ;
145 146
146 147 : current-dev ( -- addr len ) \ return current dev
147 148 s" currdev" getenv
148 149 2dup [char] / strchr nip
149 150 dup 0> if ( strchr '/' != NULL ) - else drop then
150 151 \ we have now zfs:pool or diskname:
151 152 ;
152 153
153 154 \ chop trailing ':'
154 155 : colon- ( addr len -- addr len - 1 | addr len )
155 156 2dup 1 - + C@ [char] : = if ( string[len-1] == ':' ) 1 - then
156 157 ;
157 158
158 159 \ add trailing ':'
159 160 : colon+ ( addr len -- addr len+1 )
160 161 2dup + \ addr len -- addr+len
161 162 [char] : swap c! \ save ':' at the end of the string
162 163 1+ \ addr len -- addr len+1
163 164 ;
164 165
165 166 \ make menu.lst path
166 167 : menu.lst ( addr len -- addr' len' )
167 168 colon-
168 169 \ need to allocate space for len + 16
169 170 dup 16 + allocate if ENOMEM throw then
170 171 swap 2dup 2>R \ copy of new addr len to return stack
171 172 move 2R>
172 173 s" :/boot/menu.lst" strcat
173 174 ;
174 175
175 176 \ list be's on device
176 177 : list-dev ( addr len -- )
177 178 menu.lst 2dup 2>R
178 179 beadm_longest_title
179 180 line_buffer strfree
180 181 read_buffer strfree
181 182 R@ swap 2R> \ addr width addr len
182 183 beadm_list free-memory
183 184 ." Current boot device: " s" currdev" getenv type cr
184 185 line_buffer strfree
185 186 read_buffer strfree
186 187 ;
187 188
188 189 \ activate be on device.
189 190 \ if be name was not given, set currdev
190 191 \ otherwize, we query device:/boot/menu.lst for bootfs and
191 192 \ if found, and bootfs type is chain, attempt chainload.
192 193 \ set currdev to bootfs.
193 194 \ if we were able to set currdev, reload the config
194 195
195 196 : activate-dev ( dev.addr dev.len be.addr be.len -- )
196 197
197 198 dup 0= if
198 199 2drop
199 200 colon- \ remove : at the end of the dev name
200 201 dup 1+ allocate if ENOMEM throw then
201 202 dup 2swap 0 -rot strcat
202 203 colon+
203 204 s" currdev" setenv \ setenv currdev = device
204 205 free-memory
205 206 else
206 207 2swap menu.lst
207 208 beadm_bootfs if ( addr len taddr tlen )
208 209 2dup s" chain" compare 0= if
209 210 drop free-memory \ free type
210 211 2dup
211 212 dup 6 + allocate if ENOMEM throw then
212 213 dup >R
213 214 0 s" chain " strcat
214 215 2swap strcat ['] evaluate catch drop
215 216 \ We are still there?
216 217 R> free-memory \ free chain command
217 218 drop free-memory \ free addr
218 219 exit
219 220 then
220 221 drop free-memory \ free type
221 222 \ check last char in the name
222 223 2dup + c@ [char] : <> if
223 224 \ have dataset and need to get zfs:pool/ROOT/be:
224 225 dup 5 + allocate if ENOMEM throw then
225 226 0 s" zfs:" strcat
226 227 2swap strcat
227 228 colon+
228 229 then
229 230 2dup s" currdev" setenv
230 231 drop free-memory
231 232 else
232 233 ." No such BE in menu.lst or menu.lst is missing." cr
233 234 exit
234 235 then
235 236 then
236 237
237 238 \ reset BE menu
238 239 0 page_count !
↓ open down ↓ |
216 lines elided |
↑ open up ↑ |
239 240 \ need to do:
240 241 0 unload drop
241 242 free-module-options
242 243 \ unset the env variables with kernel arguments
243 244 s" acpi-user-options" unsetenv
244 245 s" boot-args" unsetenv
245 246 s" boot_ask" unsetenv
246 247 s" boot_single" unsetenv
247 248 s" boot_verbose" unsetenv
248 249 s" boot_kmdb" unsetenv
249 - s" boot_debug" unsetenv
250 + s" boot_drop_into_kmdb" unsetenv
250 251 s" boot_reconfigure" unsetenv
251 252 start \ load config, kernel and modules
252 253 ." Current boot device: " s" currdev" getenv type cr
253 254 ;
254 255
255 256 \ beadm list [device]
256 257 \ beadm activate BE [device] | device
257 258 \
258 259 \ lists BE's from current or specified device /boot/menu.lst file
259 260 \ activates specified BE by unloading modules, setting currdev and
260 261 \ running start to load configuration.
261 262 : beadm ( -- ) ( throws: abort )
262 263 0= if ( interpreted ) get_arguments then
263 264
264 265 dup 0= if
265 266 ." Usage:" cr
266 267 ." beadm activate {beName [device] | device}" cr
267 268 ." beadm list [device]" cr
268 269 ." Use lsdev to get device names." cr
269 270 drop exit
270 271 then
271 272 \ First argument is 0 when we're interprated. See support.4th
272 273 \ for get_arguments reading the rest of the line and parsing it
273 274 \ stack: argN lenN ... arg1 len1 N
274 275 \ rotate arg1 len1, dont use argv[] as we want to get arg1 out of stack
275 276 -rot 2dup
276 277
277 278 s" list" compare-insensitive 0= if ( list )
278 279 2drop
279 280 argc 1 = if ( list currdev )
280 281 \ add dev to list of args and switch to case 2
281 282 current-dev rot 1 +
282 283 then
283 284 2 = if ( list device ) list-dev exit then
284 285 ." too many arguments" cr abort
285 286 then
286 287 s" activate" compare-insensitive 0= if ( activate )
287 288 argc 1 = if ( missing be )
288 289 drop ." missing bName" cr abort
289 290 then
290 291 argc 2 = if ( activate be )
291 292 \ need to set arg list into proper order
292 293 1+ >R \ save argc+1 to return stack
293 294
294 295 \ if the prefix is fd, cd, net or disk and we have :
295 296 \ in the name, it is device and inject empty be name
296 297 over 2 s" fd" compare 0= >R
297 298 over 2 s" cd" compare 0= R> or >R
298 299 over 3 s" net" compare 0= R> or >R
299 300 over 4 s" disk" compare 0= R> or
300 301 if ( prefix is fd or cd or net or disk )
301 302 2dup [char] : strchr nip
302 303 if ( its : in name )
303 304 true
304 305 else
305 306 false
306 307 then
307 308 else
308 309 false
309 310 then
310 311
311 312 if ( it is device name )
312 313 0 0 R>
313 314 else
314 315 \ add device, swap with be and receive argc
315 316 current-dev 2swap R>
316 317 then
317 318 then
318 319 3 = if ( activate be device ) activate-dev exit then
319 320 ." too many arguments" cr abort
320 321 then
321 322 ." Unknown argument" cr abort
322 323 ;
323 324
324 325 also forth definitions also builtins
325 326
326 327 \ make beadm available as user command.
327 328 builtin: beadm
328 329
329 330 \ count the pages of BE list
330 331 \ leave FALSE in stack in case of error
331 332 : be-pages ( -- flag )
332 333 1 local flag
333 334 0 0 2local currdev
334 335 0 0 2local title
335 336 end-locals
336 337
337 338 current-dev menu.lst 2dup 2>R
338 339 0 to end_of_file?
339 340 O_RDONLY fopen fd !
340 341 2R> drop free-memory
341 342 reset_line_reading
342 343 fd @ -1 = if FALSE else
343 344 s" currdev" getenv
344 345 over ( addr len addr )
345 346 4 s" zfs:" compare 0= if
346 347 5 - \ len -= 5
347 348 swap 4 + \ addr += 4
348 349 swap to currdev
349 350 then
350 351
351 352 0
352 353 begin
353 354 end_of_file? 0=
354 355 while
355 356 read_line
356 357 get_name_value
357 358 s" title" name_buffer strget compare
358 359 0= if 1+ then
359 360
360 361 flag if \ check for title
361 362 value_buffer strget strdup to title free_buffers
362 363 read_line \ get bootfs
363 364 get_name_value
364 365 value_buffer strget currdev compare 0= if
365 366 title s" zfs_be_active" setenv
366 367 0 to flag
367 368 then
368 369 title drop free-memory 0 0 to title
369 370 free_buffers
370 371 else
371 372 free_buffers
372 373 read_line \ get bootfs
373 374 then
374 375 repeat
375 376 fd @ fclose
376 377 line_buffer strfree
377 378 read_buffer strfree
378 379 5 /mod swap dup page_remainder ! \ save remainder
379 380 if 1+ then
380 381 dup page_count ! \ save count
381 382 n2s s" zfs_be_pages" setenv
382 383 TRUE
383 384 then
384 385 ;
385 386
386 387 : be-set-page { | entry count n device -- }
387 388 page_count @ 0= if
388 389 be-pages
389 390 page_count @ 0= if exit then
390 391 then
391 392
392 393 0 to device
393 394 1 s" zfs_be_currpage" getenvn
394 395 5 *
395 396 page_count @ 5 *
396 397 page_remainder @ if
397 398 5 page_remainder @ - -
398 399 then
399 400 swap -
400 401 dup to entry
401 402 0 < if
402 403 entry 5 + to count
403 404 0 to entry
404 405 else
405 406 5 to count
406 407 then
407 408 current-dev menu.lst 2dup 2>R
408 409 0 to end_of_file?
409 410 O_RDONLY fopen fd !
410 411 2R> drop free-memory
411 412 reset_line_reading
412 413 fd @ -1 = if EOPEN throw then
413 414 0 to n
414 415 begin
415 416 end_of_file? 0=
416 417 while
417 418 n entry < if
418 419 read_line \ skip title
419 420 read_line \ skip bootfs
420 421 n 1+ to n
421 422 else
422 423 \ Use reverse loop to display descending order
423 424 \ for BE list.
424 425 0 count 1- do
425 426 read_line \ read title line
426 427 get_name_value
427 428 value_buffer strget
428 429 52 i + \ ascii 4 + i
429 430 s" bootenvmenu_caption[4]" 20 +c! setenv
430 431 value_buffer strget
431 432 52 i + \ ascii 4 + i
432 433 s" bootenvansi_caption[4]" 20 +c! setenv
433 434
434 435 free_buffers
435 436 read_line \ read value line
436 437 get_name_value
437 438
438 439 \ set menu entry command
439 440 name_buffer strget s" chain" compare
440 441 0= if
441 442 s" set_be_chain"
442 443 else
443 444 s" set_bootenv"
444 445 then
445 446 52 i + \ ascii 4 + i
446 447 s" bootenvmenu_command[4]" 20 +c! setenv
447 448
448 449 \ set device name
449 450 name_buffer strget s" chain" compare
450 451 0= if
451 452 \ for chain, use the value as is
452 453 value_buffer strget
453 454 else
454 455 \ check last char in the name
455 456 value_buffer strget 2dup + c@
456 457 [char] : <> if
457 458 \ make zfs device name
458 459 swap drop
459 460 5 + allocate if
460 461 ENOMEM throw
461 462 then
462 463 s" zfs:" ( addr addr' len' )
463 464 2 pick swap move ( addr )
464 465 dup to device
465 466 4 value_buffer strget
466 467 strcat ( addr len )
467 468 s" :" strcat
468 469 then
469 470 then
470 471
471 472 52 i + \ ascii 4 + i
472 473 s" bootenv_root[4]" 13 +c! setenv
473 474 device free-memory 0 to device
474 475 free_buffers
475 476 -1
476 477 +loop
477 478
478 479 5 count do \ unset unused entries
479 480 52 i + \ ascii 4 + i
480 481 dup s" bootenvmenu_caption[4]" 20 +c! unsetenv
481 482 dup s" bootenvansi_caption[4]" 20 +c! unsetenv
482 483 dup s" bootenvmenu_command[4]" 20 +c! unsetenv
483 484 s" bootenv_root[4]" 13 +c! unsetenv
484 485 loop
485 486
486 487 1 to end_of_file? \ we are done
487 488 then
488 489 repeat
489 490 fd @ fclose
490 491 line_buffer strfree
491 492 read_buffer strfree
492 493 ;
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX