xref: /illumos-gate/usr/src/boot/forth/beadm.4th (revision 287031453fb1523d06a63010531ff7654f1658f6)
122028508SToomas Soome\
222028508SToomas Soome\ This file and its contents are supplied under the terms of the
322028508SToomas Soome\ Common Development and Distribution License ("CDDL"), version 1.0.
422028508SToomas Soome\ You may only use this file in accordance with the terms of version
522028508SToomas Soome\ 1.0 of the CDDL.
622028508SToomas Soome\
722028508SToomas Soome\ A full copy of the text of the CDDL should have accompanied this
822028508SToomas Soome\ source.  A copy of the CDDL is also available via the Internet at
922028508SToomas Soome\ http://www.illumos.org/license/CDDL.
1022028508SToomas Soome
1122028508SToomas Soome\ Copyright 2017 Toomas Soome <tsoome@me.com>
1222028508SToomas Soome\ Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
1322028508SToomas Soome\ Copyright 2019 Joyent, Inc.
1422028508SToomas Soome
1522028508SToomas Soome\ This module is implementing the beadm user command to support listing
1622028508SToomas Soome\ and switching Boot Environments (BE) from command line and
1722028508SToomas Soome\ support words to provide data for BE menu in loader menu system.
1822028508SToomas Soome\ Note: this module needs an update to provide proper BE vocabulary.
1922028508SToomas Soome
2022028508SToomas Soomeonly forth also support-functions also file-processing
2122028508SToomas Soomealso file-processing definitions also parser
2222028508SToomas Soomealso line-reading definitions also builtins definitions
2322028508SToomas Soome
2422028508SToomas Soomevariable page_count
2522028508SToomas Soomevariable page_remainder
2622028508SToomas Soome0 page_count !
2722028508SToomas Soome0 page_remainder !
2822028508SToomas Soome
2922028508SToomas Soome\ from menu.4th
3022028508SToomas Soome: +c! ( N C-ADDR/U K -- C-ADDR/U )
3122028508SToomas Soome	3 pick 3 pick	( n c-addr/u k -- n c-addr/u k n c-addr )
3222028508SToomas Soome	rot + c!	( n c-addr/u k n c-addr -- n c-addr/u )
3322028508SToomas Soome	rot drop	( n c-addr/u -- c-addr/u )
3422028508SToomas Soome;
3522028508SToomas Soome
3622028508SToomas Soome: get_value ( -- )
3722028508SToomas Soome	eat_space
3822028508SToomas Soome	line_pointer
3922028508SToomas Soome	skip_to_end_of_line
4022028508SToomas Soome	line_pointer over -
4122028508SToomas Soome	strdup value_buffer strset
4222028508SToomas Soome	['] exit to parsing_function
4322028508SToomas Soome;
4422028508SToomas Soome
4522028508SToomas Soome: get_name ( -- )
4622028508SToomas Soome	read_name
4722028508SToomas Soome	['] get_value to parsing_function
4822028508SToomas Soome;
4922028508SToomas Soome
5022028508SToomas Soome: get_name_value
5122028508SToomas Soome	line_buffer strget + to end_of_line
5222028508SToomas Soome	line_buffer .addr @ to line_pointer
5322028508SToomas Soome	['] get_name to parsing_function
5422028508SToomas Soome	begin
5522028508SToomas Soome		end_of_line? 0=
5622028508SToomas Soome	while
5722028508SToomas Soome		parsing_function execute
5822028508SToomas Soome	repeat
5922028508SToomas Soome;
6022028508SToomas Soome
6122028508SToomas Soome\ beadm support
6222028508SToomas Soome: beadm_longest_title ( addr len -- width )
6322028508SToomas Soome	0 to end_of_file?
6422028508SToomas Soome	O_RDONLY fopen fd !
6522028508SToomas Soome	reset_line_reading
6622028508SToomas Soome	fd @ -1 = if EOPEN throw then
6722028508SToomas Soome	0 >r		\ length into return stack
6822028508SToomas Soome	begin
6922028508SToomas Soome		end_of_file? 0=
7022028508SToomas Soome	while
7122028508SToomas Soome		free_buffers
7222028508SToomas Soome		read_line
7322028508SToomas Soome		get_name_value
7422028508SToomas Soome		value_buffer .len @ r@ > if r> drop value_buffer .len @ >r then
7522028508SToomas Soome		free_buffers
7622028508SToomas Soome		read_line
7722028508SToomas Soome	repeat
7822028508SToomas Soome	fd @ fclose
7922028508SToomas Soome	r> 1 +		\ space between columns
8022028508SToomas Soome;
8122028508SToomas Soome
8222028508SToomas Soome\ Pretty print BE list
8322028508SToomas Soome: beadm_list ( width addr len -- )
8422028508SToomas Soome	0 to end_of_file?
8522028508SToomas Soome	O_RDONLY fopen fd !
8622028508SToomas Soome	reset_line_reading
8722028508SToomas Soome	fd @ -1 = if EOPEN throw then
8822028508SToomas Soome	." BE" dup 2 - spaces ." Type    Device" cr
8922028508SToomas Soome	begin
9022028508SToomas Soome		end_of_file? 0=
9122028508SToomas Soome	while
9222028508SToomas Soome		free_buffers
9322028508SToomas Soome		read_line
9422028508SToomas Soome		get_name_value
9522028508SToomas Soome		value_buffer strget type
9622028508SToomas Soome		dup value_buffer .len @ - spaces
9722028508SToomas Soome		free_buffers
9822028508SToomas Soome		read_line
9922028508SToomas Soome		get_name_value
10022028508SToomas Soome		name_buffer strget type
10122028508SToomas Soome		name_buffer strget s" bootfs" compare 0= if 2 spaces then
10222028508SToomas Soome		name_buffer strget s" chain" compare 0= if 3 spaces then
10322028508SToomas Soome		value_buffer strget type cr
10422028508SToomas Soome		free_buffers
10522028508SToomas Soome	repeat
10622028508SToomas Soome	fd @ fclose
10722028508SToomas Soome	drop
10822028508SToomas Soome;
10922028508SToomas Soome
110*28703145SToomas Soome\ we are called with strings be_name menu_file, to simplify the stack
11122028508SToomas Soome\ management, we open the menu and free the menu_file.
11222028508SToomas Soome: beadm_bootfs ( be_addr be_len maddr mlen -- addr len taddr tlen flag | flag )
11322028508SToomas Soome	0 to end_of_file?
11422028508SToomas Soome	2dup O_RDONLY fopen fd !
11522028508SToomas Soome	drop free-memory
11622028508SToomas Soome	fd @ -1 = if EOPEN throw then
11722028508SToomas Soome	reset_line_reading
11822028508SToomas Soome	begin
11922028508SToomas Soome		end_of_file? 0=
12022028508SToomas Soome	while
12122028508SToomas Soome		free_buffers
12222028508SToomas Soome		read_line
12322028508SToomas Soome		get_name_value
12422028508SToomas Soome		2dup value_buffer strget compare
12522028508SToomas Soome		0= if ( title == be )
12622028508SToomas Soome			2drop		\ drop be_name
12722028508SToomas Soome			free_buffers
12822028508SToomas Soome			read_line
12922028508SToomas Soome			get_name_value
13022028508SToomas Soome			value_buffer strget strdup
13122028508SToomas Soome			name_buffer strget strdup -1
13222028508SToomas Soome			free_buffers
13322028508SToomas Soome			1 to end_of_file? \ mark end of file to skip the rest
13422028508SToomas Soome		else
13522028508SToomas Soome			read_line	\ skip over next line
13622028508SToomas Soome		then
13722028508SToomas Soome	repeat
13822028508SToomas Soome	fd @ fclose
13922028508SToomas Soome	line_buffer strfree
14022028508SToomas Soome	read_buffer strfree
14122028508SToomas Soome	dup -1 > if ( be_addr be_len )
14222028508SToomas Soome		2drop
14322028508SToomas Soome		0
14422028508SToomas Soome	then
14522028508SToomas Soome;
14622028508SToomas Soome
14722028508SToomas Soome: current-dev ( -- addr len ) \ return current dev
14822028508SToomas Soome	s" currdev" getenv
14922028508SToomas Soome	2dup [char] / strchr nip
15022028508SToomas Soome	dup 0> if ( strchr '/' != NULL ) - else drop then
15122028508SToomas Soome	\ we have now zfs:pool or diskname:
15222028508SToomas Soome;
15322028508SToomas Soome
15422028508SToomas Soome\ chop trailing ':'
15522028508SToomas Soome: colon- ( addr len -- addr len - 1 | addr len )
15622028508SToomas Soome	2dup 1 - + C@ [char] : = if ( string[len-1] == ':' ) 1 - then
15722028508SToomas Soome;
15822028508SToomas Soome
15922028508SToomas Soome\ add trailing ':'
16022028508SToomas Soome: colon+ ( addr len -- addr len+1 )
16122028508SToomas Soome	2dup +			\ addr len -- addr+len
16222028508SToomas Soome	[char] : swap c!	\ save ':' at the end of the string
16322028508SToomas Soome	1+			\ addr len -- addr len+1
16422028508SToomas Soome;
16522028508SToomas Soome
16622028508SToomas Soome\ make menu.lst path
16722028508SToomas Soome: menu.lst ( addr len -- addr' len' )
16822028508SToomas Soome	colon-
16922028508SToomas Soome	\ need to allocate space for len + 16
17022028508SToomas Soome	dup 16 + allocate if ENOMEM throw then
17122028508SToomas Soome	swap 2dup 2>R	\ copy of new addr len to return stack
17222028508SToomas Soome	move 2R>
17322028508SToomas Soome	s" :/boot/menu.lst" strcat
17422028508SToomas Soome;
17522028508SToomas Soome
17622028508SToomas Soome\ list be's on device
17722028508SToomas Soome: list-dev ( addr len -- )
17822028508SToomas Soome	menu.lst 2dup 2>R
17922028508SToomas Soome	beadm_longest_title
18022028508SToomas Soome	line_buffer strfree
18122028508SToomas Soome	read_buffer strfree
18222028508SToomas Soome	R@ swap 2R>	\ addr width addr len
18322028508SToomas Soome	beadm_list free-memory
18422028508SToomas Soome	." Current boot device: " s" currdev" getenv type cr
18522028508SToomas Soome	line_buffer strfree
18622028508SToomas Soome	read_buffer strfree
18722028508SToomas Soome;
18822028508SToomas Soome
18922028508SToomas Soome\ activate be on device.
19022028508SToomas Soome\ if be name was not given, set currdev
19122028508SToomas Soome\ otherwize, we query device:/boot/menu.lst for bootfs and
19222028508SToomas Soome\ if found, and bootfs type is chain, attempt chainload.
19322028508SToomas Soome\ set currdev to bootfs.
19422028508SToomas Soome\ if we were able to set currdev, reload the config
19522028508SToomas Soome
19622028508SToomas Soome: activate-dev ( dev.addr dev.len be.addr be.len -- )
19722028508SToomas Soome
19822028508SToomas Soome	dup 0= if
19922028508SToomas Soome		2drop
20022028508SToomas Soome		colon-			\ remove : at the end of the dev name
20122028508SToomas Soome		dup 1+ allocate if ENOMEM throw then
20222028508SToomas Soome		dup 2swap 0 -rot strcat
20322028508SToomas Soome		colon+
20422028508SToomas Soome		s" currdev" setenv	\ setenv currdev = device
20522028508SToomas Soome		free-memory
20622028508SToomas Soome	else
20722028508SToomas Soome		2swap menu.lst
20822028508SToomas Soome		beadm_bootfs if ( addr len taddr tlen )
20922028508SToomas Soome			2dup s" chain" compare 0= if
21022028508SToomas Soome				drop free-memory	\ free type
21122028508SToomas Soome				2dup
21222028508SToomas Soome				dup 6 + allocate if ENOMEM throw then
21322028508SToomas Soome				dup >R
21422028508SToomas Soome				0 s" chain " strcat
21522028508SToomas Soome				2swap strcat ['] evaluate catch drop
21622028508SToomas Soome				\ We are still there?
21722028508SToomas Soome				R> free-memory		\ free chain command
21822028508SToomas Soome				drop free-memory	\ free addr
21922028508SToomas Soome				exit
22022028508SToomas Soome			then
22122028508SToomas Soome			drop free-memory		\ free type
22222028508SToomas Soome			\ check last char in the name
22322028508SToomas Soome			2dup + c@ [char] : <> if
22422028508SToomas Soome				\ have dataset and need to get zfs:pool/ROOT/be:
22522028508SToomas Soome				dup 5 + allocate if ENOMEM throw then
22622028508SToomas Soome				0 s" zfs:" strcat
22722028508SToomas Soome				2swap strcat
22822028508SToomas Soome				colon+
22922028508SToomas Soome			then
23022028508SToomas Soome			2dup s" currdev" setenv
23122028508SToomas Soome			drop free-memory
23222028508SToomas Soome		else
23322028508SToomas Soome			." No such BE in menu.lst or menu.lst is missing." cr
23422028508SToomas Soome			exit
23522028508SToomas Soome		then
23622028508SToomas Soome	then
23722028508SToomas Soome
23822028508SToomas Soome	\ reset BE menu
23922028508SToomas Soome	0 page_count !
24022028508SToomas Soome	\ need to do:
24122028508SToomas Soome	0 unload drop
24222028508SToomas Soome	free-module-options
24322028508SToomas Soome	\ unset the env variables with kernel arguments
24422028508SToomas Soome	s" acpi-user-options" unsetenv
24522028508SToomas Soome	s" boot-args" unsetenv
24622028508SToomas Soome	s" boot_ask" unsetenv
24722028508SToomas Soome	s" boot_single" unsetenv
24822028508SToomas Soome	s" boot_verbose" unsetenv
24922028508SToomas Soome	s" boot_kmdb" unsetenv
25022028508SToomas Soome	s" boot_drop_into_kmdb" unsetenv
25122028508SToomas Soome	s" boot_reconfigure" unsetenv
252519c7dc9SToomas Soome	s" boot_noncluster" unsetenv
25322028508SToomas Soome	start			\ load config, kernel and modules
25422028508SToomas Soome	." Current boot device: " s" currdev" getenv type cr
25522028508SToomas Soome;
25622028508SToomas Soome
25722028508SToomas Soome\ beadm list [device]
25822028508SToomas Soome\ beadm activate BE [device] | device
25922028508SToomas Soome\
26022028508SToomas Soome\ lists BE's from current or specified device /boot/menu.lst file
26122028508SToomas Soome\ activates specified BE by unloading modules, setting currdev and
26222028508SToomas Soome\ running start to load configuration.
26322028508SToomas Soome: beadm ( -- ) ( throws: abort )
26422028508SToomas Soome	0= if ( interpreted ) get_arguments then
26522028508SToomas Soome
26622028508SToomas Soome	dup 0= if
26722028508SToomas Soome		." Usage:" cr
26822028508SToomas Soome		." beadm activate {beName [device] | device}" cr
26922028508SToomas Soome		." beadm list [device]" cr
27022028508SToomas Soome		." Use lsdev to get device names." cr
27122028508SToomas Soome		drop exit
27222028508SToomas Soome	then
27322028508SToomas Soome	\ First argument is 0 when we're interprated.  See support.4th
27422028508SToomas Soome	\ for get_arguments reading the rest of the line and parsing it
27522028508SToomas Soome	\ stack: argN lenN ... arg1 len1 N
27622028508SToomas Soome	\ rotate arg1 len1, dont use argv[] as we want to get arg1 out of stack
27722028508SToomas Soome	-rot 2dup
27822028508SToomas Soome
27922028508SToomas Soome	s" list" compare-insensitive 0= if ( list )
28022028508SToomas Soome		2drop
28122028508SToomas Soome		argc 1 = if ( list currdev )
28222028508SToomas Soome			\ add dev to list of args and switch to case 2
28322028508SToomas Soome			current-dev rot 1 +
28422028508SToomas Soome		then
28522028508SToomas Soome		2 = if ( list device ) list-dev exit then
28622028508SToomas Soome		." too many arguments" cr abort
28722028508SToomas Soome	then
28822028508SToomas Soome	s" activate" compare-insensitive 0= if ( activate )
28922028508SToomas Soome		argc 1 = if ( missing be )
29022028508SToomas Soome			drop ." missing bName" cr abort
29122028508SToomas Soome		then
29222028508SToomas Soome		argc 2 = if ( activate be )
29322028508SToomas Soome			\ need to set arg list into proper order
29422028508SToomas Soome			1+ >R	\ save argc+1 to return stack
29522028508SToomas Soome
29622028508SToomas Soome			\ if the prefix is fd, cd, net or disk and we have :
29722028508SToomas Soome			\ in the name, it is device and inject empty be name
29822028508SToomas Soome			over 2 s" fd" compare 0= >R
29922028508SToomas Soome			over 2 s" cd" compare 0= R> or >R
30022028508SToomas Soome			over 3 s" net" compare 0= R> or >R
30122028508SToomas Soome			over 4 s" disk" compare 0= R> or
30222028508SToomas Soome			if ( prefix is fd or cd or net or disk )
30322028508SToomas Soome				2dup [char] : strchr nip
30422028508SToomas Soome				if ( its : in name )
30522028508SToomas Soome					true
30622028508SToomas Soome				else
30722028508SToomas Soome					false
30822028508SToomas Soome				then
30922028508SToomas Soome			else
31022028508SToomas Soome				false
31122028508SToomas Soome			then
31222028508SToomas Soome
31322028508SToomas Soome			if ( it is device name )
31422028508SToomas Soome				0 0 R>
31522028508SToomas Soome			else
31622028508SToomas Soome				\ add device, swap with be and receive argc
31722028508SToomas Soome				current-dev 2swap R>
31822028508SToomas Soome			then
31922028508SToomas Soome		then
32022028508SToomas Soome		3 = if ( activate be device ) activate-dev exit then
32122028508SToomas Soome		." too many arguments" cr abort
32222028508SToomas Soome	then
32322028508SToomas Soome	." Unknown argument" cr abort
32422028508SToomas Soome;
32522028508SToomas Soome
32622028508SToomas Soomealso forth definitions also builtins
32722028508SToomas Soome
32822028508SToomas Soome\ make beadm available as user command.
32922028508SToomas Soomebuiltin: beadm
33022028508SToomas Soome
33122028508SToomas Soome\ count the pages of BE list
33222028508SToomas Soome\ leave FALSE in stack in case of error
33322028508SToomas Soome: be-pages ( -- flag )
33422028508SToomas Soome	1 local flag
33522028508SToomas Soome	0 0 2local currdev
33622028508SToomas Soome	0 0 2local title
33722028508SToomas Soome	end-locals
33822028508SToomas Soome
33922028508SToomas Soome	current-dev menu.lst 2dup 2>R
34022028508SToomas Soome	0 to end_of_file?
34122028508SToomas Soome	O_RDONLY fopen fd !
34222028508SToomas Soome	2R> drop free-memory
34322028508SToomas Soome	reset_line_reading
34422028508SToomas Soome	fd @ -1 = if FALSE else
34522028508SToomas Soome		s" currdev" getenv
34622028508SToomas Soome		over			( addr len addr )
34722028508SToomas Soome		4 s" zfs:" compare 0= if
34822028508SToomas Soome			5 -			\ len -= 5
34922028508SToomas Soome			swap 4 +		\ addr += 4
35022028508SToomas Soome			swap to currdev
35122028508SToomas Soome		then
35222028508SToomas Soome
35322028508SToomas Soome		0
35422028508SToomas Soome		begin
35522028508SToomas Soome			end_of_file? 0=
35622028508SToomas Soome		while
35722028508SToomas Soome			read_line
35822028508SToomas Soome			get_name_value
35922028508SToomas Soome			s" title" name_buffer strget compare
36022028508SToomas Soome			0= if 1+ then
36122028508SToomas Soome
36222028508SToomas Soome			flag if		\ check for title
36322028508SToomas Soome				value_buffer strget strdup to title free_buffers
36422028508SToomas Soome				read_line		\ get bootfs
36522028508SToomas Soome				get_name_value
36622028508SToomas Soome				value_buffer strget currdev compare 0= if
36722028508SToomas Soome					title s" zfs_be_active" setenv
36822028508SToomas Soome					0 to flag
36922028508SToomas Soome				then
37022028508SToomas Soome				title drop free-memory 0 0 to title
37122028508SToomas Soome				free_buffers
37222028508SToomas Soome			else
37322028508SToomas Soome				free_buffers
37422028508SToomas Soome				read_line		\ get bootfs
37522028508SToomas Soome			then
37622028508SToomas Soome		repeat
37722028508SToomas Soome		fd @ fclose
37822028508SToomas Soome		line_buffer strfree
37922028508SToomas Soome		read_buffer strfree
38022028508SToomas Soome		5 /mod swap dup page_remainder !		\ save remainder
38122028508SToomas Soome		if 1+ then
38222028508SToomas Soome		dup page_count !				\ save count
38322028508SToomas Soome		n2s s" zfs_be_pages" setenv
38422028508SToomas Soome		TRUE
38522028508SToomas Soome	then
38622028508SToomas Soome;
38722028508SToomas Soome
38822028508SToomas Soome: be-set-page { | entry count n device -- }
38922028508SToomas Soome	page_count @ 0= if
39022028508SToomas Soome		be-pages
39122028508SToomas Soome		page_count @ 0= if exit then
39222028508SToomas Soome	then
39322028508SToomas Soome
39422028508SToomas Soome	0 to device
39522028508SToomas Soome	1 s" zfs_be_currpage" getenvn
39622028508SToomas Soome	5 *
39722028508SToomas Soome	page_count @ 5 *
39822028508SToomas Soome	page_remainder @ if
39922028508SToomas Soome		5 page_remainder @ - -
40022028508SToomas Soome	then
40122028508SToomas Soome	swap -
40222028508SToomas Soome	dup to entry
40322028508SToomas Soome	0 < if
40422028508SToomas Soome		entry 5 + to count
40522028508SToomas Soome		0 to entry
40622028508SToomas Soome	else
40722028508SToomas Soome		5 to count
40822028508SToomas Soome	then
40922028508SToomas Soome	current-dev menu.lst 2dup 2>R
41022028508SToomas Soome	0 to end_of_file?
41122028508SToomas Soome	O_RDONLY fopen fd !
41222028508SToomas Soome	2R> drop free-memory
41322028508SToomas Soome	reset_line_reading
41422028508SToomas Soome	fd @ -1 = if EOPEN throw then
41522028508SToomas Soome	0 to n
41622028508SToomas Soome	begin
41722028508SToomas Soome		end_of_file? 0=
41822028508SToomas Soome	while
41922028508SToomas Soome		n entry < if
42022028508SToomas Soome			read_line		\ skip title
42122028508SToomas Soome			read_line		\ skip bootfs
42222028508SToomas Soome			n 1+ to n
42322028508SToomas Soome		else
42422028508SToomas Soome			\ Use reverse loop to display descending order
42522028508SToomas Soome			\ for BE list.
42622028508SToomas Soome			0 count 1- do
42722028508SToomas Soome				read_line		\ read title line
42822028508SToomas Soome				get_name_value
42922028508SToomas Soome				value_buffer strget
43022028508SToomas Soome				52 i +			\ ascii 4 + i
43122028508SToomas Soome				s" bootenvmenu_caption[4]" 20 +c! setenv
43222028508SToomas Soome				value_buffer strget
43322028508SToomas Soome				52 i +			\ ascii 4 + i
43422028508SToomas Soome				s" bootenvansi_caption[4]" 20 +c! setenv
43522028508SToomas Soome
43622028508SToomas Soome				free_buffers
43722028508SToomas Soome				read_line		\ read value line
43822028508SToomas Soome				get_name_value
43922028508SToomas Soome
44022028508SToomas Soome				\ set menu entry command
44122028508SToomas Soome				name_buffer strget s" chain" compare
44222028508SToomas Soome				0= if
44322028508SToomas Soome					s" set_be_chain"
44422028508SToomas Soome				else
44522028508SToomas Soome					s" set_bootenv"
44622028508SToomas Soome				then
44722028508SToomas Soome				52 i +			\ ascii 4 + i
44822028508SToomas Soome				s" bootenvmenu_command[4]" 20 +c! setenv
44922028508SToomas Soome
45022028508SToomas Soome				\ set device name
45122028508SToomas Soome				name_buffer strget s" chain" compare
45222028508SToomas Soome				0= if
453*28703145SToomas Soome					\ for chain, use the value as is
45422028508SToomas Soome					value_buffer strget
45522028508SToomas Soome				else
45622028508SToomas Soome					\ check last char in the name
45722028508SToomas Soome					value_buffer strget 2dup + c@
45822028508SToomas Soome					[char] : <> if
45922028508SToomas Soome						\ make zfs device name
46022028508SToomas Soome						swap drop
46122028508SToomas Soome						5 + allocate if
46222028508SToomas Soome							ENOMEM throw
46322028508SToomas Soome						then
46422028508SToomas Soome						s" zfs:" ( addr addr' len' )
46522028508SToomas Soome						2 pick swap move ( addr )
46622028508SToomas Soome						dup to device
46722028508SToomas Soome						4 value_buffer strget
46822028508SToomas Soome						strcat	( addr len )
46922028508SToomas Soome						s" :" strcat
47022028508SToomas Soome					then
47122028508SToomas Soome				then
47222028508SToomas Soome
47322028508SToomas Soome				52 i +			\ ascii 4 + i
47422028508SToomas Soome				s" bootenv_root[4]" 13 +c! setenv
47522028508SToomas Soome				device free-memory 0 to device
47622028508SToomas Soome				free_buffers
47722028508SToomas Soome				-1
47822028508SToomas Soome			+loop
47922028508SToomas Soome
48022028508SToomas Soome			5 count do		\ unset unused entries
48122028508SToomas Soome				52 i +			\ ascii 4 + i
48222028508SToomas Soome				dup s" bootenvmenu_caption[4]" 20 +c! unsetenv
48322028508SToomas Soome				dup s" bootenvansi_caption[4]" 20 +c! unsetenv
48422028508SToomas Soome				dup s" bootenvmenu_command[4]" 20 +c! unsetenv
48522028508SToomas Soome				s" bootenv_root[4]" 13 +c! unsetenv
48622028508SToomas Soome			loop
48722028508SToomas Soome
48822028508SToomas Soome			1 to end_of_file?		\ we are done
48922028508SToomas Soome		then
49022028508SToomas Soome	repeat
49122028508SToomas Soome	fd @ fclose
49222028508SToomas Soome	line_buffer strfree
49322028508SToomas Soome	read_buffer strfree
49422028508SToomas Soome;
495