summaryrefslogtreecommitdiffstats
path: root/discover/grub2
diff options
context:
space:
mode:
Diffstat (limited to 'discover/grub2')
-rw-r--r--discover/grub2/grub2.h10
-rw-r--r--discover/grub2/parser.y14
-rw-r--r--discover/grub2/script.c33
3 files changed, 57 insertions, 0 deletions
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
index 4949f3c..5b83fad 100644
--- a/discover/grub2/grub2.h
+++ b/discover/grub2/grub2.h
@@ -71,6 +71,11 @@ struct grub2_statement_block {
struct grub2_statements *statements;
};
+struct grub2_statement_function {
+ struct grub2_statement st;
+ struct grub2_word *name;
+ struct grub2_statements *body;
+};
struct grub2_script {
struct grub2_statements *statements;
@@ -105,6 +110,9 @@ struct grub2_statement *create_statement_if(struct grub2_parser *parser,
struct grub2_statement *create_statement_block(struct grub2_parser *parser,
struct grub2_statements *stmts);
+struct grub2_statement *create_statement_function(struct grub2_parser *parser,
+ struct grub2_word *name, struct grub2_statements *body);
+
struct grub2_word *create_word_text(struct grub2_parser *parser,
const char *text);
@@ -129,6 +137,8 @@ int statement_if_execute(struct grub2_script *script,
struct grub2_statement *statement);
int statement_menuentry_execute(struct grub2_script *script,
struct grub2_statement *statement);
+int statement_function_execute(struct grub2_script *script,
+ struct grub2_statement *statement);
struct grub2_script *create_script(struct grub2_parser *parser,
struct discover_context *ctx);
diff --git a/discover/grub2/parser.y b/discover/grub2/parser.y
index 550c374..bcf5935 100644
--- a/discover/grub2/parser.y
+++ b/discover/grub2/parser.y
@@ -95,6 +95,9 @@ statement: TOKEN_EOL {
"fi" TOKEN_EOL {
$$ = create_statement_if(parser, $3, $6, $9);
}
+ | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' {
+ $$ = create_statement_function(parser, $3, $6);
+ }
| "menuentry" TOKEN_DELIM words TOKEN_DELIM
'{' statements '}'
TOKEN_EOL {
@@ -181,6 +184,17 @@ struct grub2_statement *create_statement_block(struct grub2_parser *parser,
return &stmt->st;
}
+struct grub2_statement *create_statement_function(struct grub2_parser *parser,
+ struct grub2_word *name, struct grub2_statements *body)
+{
+ struct grub2_statement_function *stmt =
+ talloc(parser, struct grub2_statement_function);
+ stmt->st.exec = statement_function_execute;
+ stmt->name = name;
+ stmt->body = body;
+ return &stmt->st;
+}
+
void statement_append(struct grub2_statements *stmts,
struct grub2_statement *stmt)
{
diff --git a/discover/grub2/script.c b/discover/grub2/script.c
index ec37fbb..9c08737 100644
--- a/discover/grub2/script.c
+++ b/discover/grub2/script.c
@@ -13,6 +13,8 @@
container_of(stmt, struct grub2_statement_if, st)
#define to_stmt_menuentry(stmt) \
container_of(stmt, struct grub2_statement_menuentry, st)
+#define to_stmt_function(stmt) \
+ container_of(stmt, struct grub2_statement_function, st)
struct env_entry {
const char *name;
@@ -297,6 +299,37 @@ int statement_menuentry_execute(struct grub2_script *script,
return 0;
}
+static int function_invoke(struct grub2_script *script,
+ void *data, int argc, char **argv)
+{
+ struct grub2_statement_function *fn = data;
+ char *name;
+ int i;
+
+ /* set positional parameters */
+ for (i = 0; i < argc; i++) {
+ name = talloc_asprintf(script, "$%d", i);
+ script_env_set(script, name, argv[i]);
+ }
+
+ return statements_execute(script, fn->body);
+}
+
+int statement_function_execute(struct grub2_script *script,
+ struct grub2_statement *statement)
+{
+ struct grub2_statement_function *st = to_stmt_function(statement);
+ const char *name;
+
+ if (st->name->type == GRUB2_WORD_VAR)
+ expand_var(script, st->name);
+
+ name = st->name->text;
+ script_register_function(script, name, function_invoke, st);
+
+ return 0;
+}
+
static void init_env(struct grub2_script *script)
{
struct env_entry *env;
OpenPOWER on IntegriCloud