Ver código fonte

[menu] Add menu commands

Allow iPXE scripts to create menus.  For example:

    #!ipxe

    menu iSCSI boot demonstration
    item install         Install Fedora to ${root-path}
    item --default boot  Boot from ${root-path}
    item shell           Enter iPXE shell
    item exit            Exit to BIOS
    choose label && goto ${label}

    :boot
    sanboot ${root-path}

    :install
    sanhook ${root-path}
    chain http://${next-server}/fedora.ipxe

    :shell
    shell

    :exit

Inspired-by: Robin Smidsrød <robin@smidsrod.no>
Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 anos atrás
pai
commit
3425726cf3

+ 3
- 0
src/config/config.c Ver arquivo

@@ -223,6 +223,9 @@ REQUIRE_OBJECT ( dhcp_cmd );
223 223
 #ifdef SANBOOT_CMD
224 224
 REQUIRE_OBJECT ( sanboot_cmd );
225 225
 #endif
226
+#ifdef MENU_CMD
227
+REQUIRE_OBJECT ( menu_cmd );
228
+#endif
226 229
 #ifdef LOGIN_CMD
227 230
 REQUIRE_OBJECT ( login_cmd );
228 231
 #endif

+ 1
- 0
src/config/general.h Ver arquivo

@@ -119,6 +119,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
119 119
 #define IMAGE_CMD		/* Image management commands */
120 120
 #define DHCP_CMD		/* DHCP management commands */
121 121
 #define SANBOOT_CMD		/* SAN boot commands */
122
+#define MENU_CMD		/* Menu commands */
122 123
 #define LOGIN_CMD		/* Login command */
123 124
 //#define TIME_CMD		/* Time commands */
124 125
 //#define DIGEST_CMD		/* Image crypto digest commands */

+ 24
- 0
src/core/parseopt.c Ver arquivo

@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
26 26
 #include <errno.h>
27 27
 #include <getopt.h>
28 28
 #include <ipxe/netdevice.h>
29
+#include <ipxe/menu.h>
29 30
 #include <ipxe/parseopt.h>
30 31
 
31 32
 /** @file
@@ -113,6 +114,29 @@ int parse_netdev ( const char *text, struct net_device **netdev ) {
113 114
 	return 0;
114 115
 }
115 116
 
117
+/**
118
+ * Parse menu name
119
+ *
120
+ * @v text		Text
121
+ * @ret menu		Menu
122
+ * @ret rc		Return status code
123
+ */
124
+int parse_menu ( const char *text, struct menu **menu ) {
125
+
126
+	/* Find menu */
127
+	*menu = find_menu ( text );
128
+	if ( ! *menu ) {
129
+		if ( text ) {
130
+			printf ( "\"%s\": no such menu\n", text );
131
+		} else {
132
+			printf ( "No default menu\n" );
133
+		}
134
+		return -ENOENT;
135
+	}
136
+
137
+	return 0;
138
+}
139
+
116 140
 /**
117 141
  * Parse flag
118 142
  *

+ 280
- 0
src/hci/commands/menu_cmd.c Ver arquivo

@@ -0,0 +1,280 @@
1
+/*
2
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+/** @file
22
+ *
23
+ * Menu commands
24
+ *
25
+ */
26
+
27
+#include <stdio.h>
28
+#include <stdlib.h>
29
+#include <string.h>
30
+#include <errno.h>
31
+#include <getopt.h>
32
+#include <ipxe/menu.h>
33
+#include <ipxe/command.h>
34
+#include <ipxe/parseopt.h>
35
+#include <ipxe/settings.h>
36
+#include <ipxe/features.h>
37
+
38
+FEATURE ( FEATURE_MISC, "Menu", DHCP_EB_FEATURE_MENU, 1 );
39
+
40
+/** "menu" options */
41
+struct menu_options {
42
+	/** Name */
43
+	const char *name;
44
+	/** Delete */
45
+	int delete;
46
+};
47
+
48
+/** "menu" option list */
49
+static struct option_descriptor menu_opts[] = {
50
+	OPTION_DESC ( "name", 'n', required_argument,
51
+		      struct menu_options, name, parse_string ),
52
+	OPTION_DESC ( "delete", 'd', no_argument,
53
+		      struct menu_options, delete, parse_flag ),
54
+};
55
+
56
+/** "menu" command descriptor */
57
+static struct command_descriptor menu_cmd =
58
+	COMMAND_DESC ( struct menu_options, menu_opts, 0, MAX_ARGUMENTS,
59
+		       "[--name <name>] [--delete] [<title>]" );
60
+
61
+/**
62
+ * The "menu" command
63
+ *
64
+ * @v argc		Argument count
65
+ * @v argv		Argument list
66
+ * @ret rc		Return status code
67
+ */
68
+static int menu_exec ( int argc, char **argv ) {
69
+	struct menu_options opts;
70
+	struct menu *menu;
71
+	char *title;
72
+	int rc;
73
+
74
+	/* Parse options */
75
+	if ( ( rc = parse_options ( argc, argv, &menu_cmd, &opts ) ) != 0 )
76
+		goto err_parse_options;
77
+
78
+	/* Parse title */
79
+	title = concat_args ( &argv[optind] );
80
+	if ( ! title ) {
81
+		rc = -ENOMEM;
82
+		goto err_parse_title;
83
+	}
84
+
85
+	/* Create menu */
86
+	menu = create_menu ( opts.name, title );
87
+	if ( ! menu ) {
88
+		rc = -ENOMEM;
89
+		goto err_create_menu;
90
+	}
91
+
92
+	/* Destroy menu, if applicable */
93
+	if ( opts.delete )
94
+		destroy_menu ( menu );
95
+
96
+	/* Success */
97
+	rc = 0;
98
+
99
+ err_create_menu:
100
+	free ( title );
101
+ err_parse_title:
102
+ err_parse_options:
103
+	return rc;
104
+}
105
+
106
+/** "item" options */
107
+struct item_options {
108
+	/** Menu name */
109
+	const char *menu;
110
+	/** Shortcut key */
111
+	unsigned int key;
112
+	/** Use as default */
113
+	int is_default;
114
+	/** Use as a separator */
115
+	int is_gap;
116
+};
117
+
118
+/** "item" option list */
119
+static struct option_descriptor item_opts[] = {
120
+	OPTION_DESC ( "menu", 'm', required_argument,
121
+		      struct item_options, menu, parse_string ),
122
+	OPTION_DESC ( "key", 'k', required_argument,
123
+		      struct item_options, key, parse_key ),
124
+	OPTION_DESC ( "default", 'd', no_argument,
125
+		      struct item_options, is_default, parse_flag ),
126
+	OPTION_DESC ( "gap", 'g', no_argument,
127
+		      struct item_options, is_gap, parse_flag ),
128
+};
129
+
130
+/** "item" command descriptor */
131
+static struct command_descriptor item_cmd =
132
+	COMMAND_DESC ( struct item_options, item_opts, 0, MAX_ARGUMENTS,
133
+		       "[--menu <menu>] [--key <key>] [--default] "
134
+		       "[<label>|--gap [<text>]]" );
135
+
136
+/**
137
+ * The "item" command
138
+ *
139
+ * @v argc		Argument count
140
+ * @v argv		Argument list
141
+ * @ret rc		Return status code
142
+ */
143
+static int item_exec ( int argc, char **argv ) {
144
+	struct item_options opts;
145
+	struct menu *menu;
146
+	struct menu_item *item;
147
+	char *label = NULL;
148
+	char *text = NULL;
149
+	int rc;
150
+
151
+	/* Parse options */
152
+	if ( ( rc = parse_options ( argc, argv, &item_cmd, &opts ) ) != 0 )
153
+		goto err_parse_options;
154
+
155
+	/* Parse label, if present */
156
+	if ( ! opts.is_gap )
157
+		label = argv[optind++]; /* May be NULL */
158
+
159
+	/* Parse text, if present */
160
+	if ( optind < argc ) {
161
+		text = concat_args ( &argv[optind] );
162
+		if ( ! text ) {
163
+			rc = -ENOMEM;
164
+			goto err_parse_text;
165
+		}
166
+	}
167
+
168
+	/* Identify menu */
169
+	if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
170
+		goto err_parse_menu;
171
+
172
+	/* Add menu item */
173
+	item = add_menu_item ( menu, label, ( text ? text : "" ),
174
+			       opts.key, opts.is_default );
175
+	if ( ! item ) {
176
+		rc = -ENOMEM;
177
+		goto err_add_menu_item;
178
+	}
179
+
180
+	/* Success */
181
+	rc = 0;
182
+
183
+ err_add_menu_item:
184
+ err_parse_menu:
185
+	free ( text );
186
+ err_parse_text:
187
+ err_parse_options:
188
+	return rc;
189
+}
190
+
191
+/** "choose" options */
192
+struct choose_options {
193
+	/** Menu name */
194
+	const char *menu;
195
+	/** Timeout */
196
+	unsigned int timeout;
197
+	/** Keep menu */
198
+	int keep;
199
+};
200
+
201
+/** "choose" option list */
202
+static struct option_descriptor choose_opts[] = {
203
+	OPTION_DESC ( "menu", 'm', required_argument,
204
+		      struct choose_options, menu, parse_string ),
205
+	OPTION_DESC ( "timeout", 't', required_argument,
206
+		      struct choose_options, timeout, parse_integer ),
207
+	OPTION_DESC ( "keep", 'k', no_argument,
208
+		      struct choose_options, keep, parse_flag ),
209
+};
210
+
211
+/** "choose" command descriptor */
212
+static struct command_descriptor choose_cmd =
213
+	COMMAND_DESC ( struct choose_options, choose_opts, 1, 1,
214
+		       "[--menu <menu>] [--timeout <timeout>] [--keep] "
215
+		       "<setting>" );
216
+
217
+/**
218
+ * The "choose" command
219
+ *
220
+ * @v argc		Argument count
221
+ * @v argv		Argument list
222
+ * @ret rc		Return status code
223
+ */
224
+static int choose_exec ( int argc, char **argv ) {
225
+	struct choose_options opts;
226
+	struct menu *menu;
227
+	struct menu_item *item;
228
+	const char *setting;
229
+	int rc;
230
+
231
+	/* Parse options */
232
+	if ( ( rc = parse_options ( argc, argv, &choose_cmd, &opts ) ) != 0 )
233
+		goto err_parse_options;
234
+
235
+	/* Parse setting name */
236
+	setting = argv[optind];
237
+
238
+	/* Identify menu */
239
+	if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
240
+		goto err_parse_menu;
241
+
242
+	/* Show menu */
243
+	if ( ( rc = show_menu ( menu, opts.timeout, &item ) ) != 0 )
244
+		goto err_show_menu;
245
+
246
+	/* Store setting */
247
+	if ( ( rc = storef_named_setting ( setting, item->label ) ) != 0 ) {
248
+		printf ( "Could not store \"%s\": %s\n",
249
+			 setting, strerror ( rc ) );
250
+		goto err_store;
251
+	}
252
+
253
+	/* Success */
254
+	rc = 0;
255
+
256
+ err_store:
257
+ err_show_menu:
258
+	/* Destroy menu, if applicable */
259
+	if ( ! opts.keep )
260
+		destroy_menu ( menu );
261
+ err_parse_menu:
262
+ err_parse_options:
263
+	return rc;
264
+}
265
+
266
+/** Menu commands */
267
+struct command menu_commands[] __command = {
268
+	{
269
+		.name = "menu",
270
+		.exec = menu_exec,
271
+	},
272
+	{
273
+		.name = "item",
274
+		.exec = item_exec,
275
+	},
276
+	{
277
+		.name = "choose",
278
+		.exec = choose_exec,
279
+	},
280
+};

+ 1
- 0
src/include/ipxe/errfile.h Ver arquivo

@@ -252,6 +252,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
252 252
 #define ERRFILE_cms		      ( ERRFILE_OTHER | 0x002a0000 )
253 253
 #define ERRFILE_imgtrust	      ( ERRFILE_OTHER | 0x002b0000 )
254 254
 #define ERRFILE_menu_ui		      ( ERRFILE_OTHER | 0x002c0000 )
255
+#define ERRFILE_menu_cmd	      ( ERRFILE_OTHER | 0x002d0000 )
255 256
 
256 257
 /** @} */
257 258
 

+ 1
- 0
src/include/ipxe/features.h Ver arquivo

@@ -52,6 +52,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
52 52
 #define DHCP_EB_FEATURE_EFI		0x24 /**< EFI format */
53 53
 #define DHCP_EB_FEATURE_FCOE		0x25 /**< FCoE protocol */
54 54
 #define DHCP_EB_FEATURE_VLAN		0x26 /**< VLAN support */
55
+#define DHCP_EB_FEATURE_MENU		0x27 /**< Menu support */
55 56
 
56 57
 /** @} */
57 58
 

+ 2
- 0
src/include/ipxe/parseopt.h Ver arquivo

@@ -13,6 +13,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
13 13
 #include <stddef.h>
14 14
 
15 15
 struct net_device;
16
+struct menu;
16 17
 
17 18
 /** A command-line option descriptor */
18 19
 struct option_descriptor {
@@ -116,6 +117,7 @@ struct command_descriptor {
116 117
 extern int parse_string ( const char *text, const char **value );
117 118
 extern int parse_integer ( const char *text, unsigned int *value );
118 119
 extern int parse_netdev ( const char *text, struct net_device **netdev );
120
+extern int parse_menu ( const char *text, struct menu **menu );
119 121
 extern int parse_flag ( const char *text __unused, int *flag );
120 122
 extern int parse_key ( const char *text, unsigned int *key );
121 123
 extern void print_usage ( struct command_descriptor *cmd, char **argv );

Carregando…
Cancelar
Salvar