]> git.ozlabs.org Git - petitboot/blob - discover/grub2/builtins.c
discover/grub2: Implement 'linux' & 'initrd' commands
[petitboot] / discover / grub2 / builtins.c
1
2 #include <stdio.h>
3 #include <string.h>
4
5 #include <log/log.h>
6 #include <types/types.h>
7 #include <talloc/talloc.h>
8 #include <array-size/array-size.h>
9
10 #include "grub2.h"
11
12
13 static int builtin_set(struct grub2_script *script,
14                 void *data __attribute__((unused)),
15                 int argc, char *argv[])
16 {
17         char *name, *value, *p;
18         int i;
19
20         if (argc < 2)
21                 return -1;
22
23         p = strchr(argv[1], '=');
24         if (!p)
25                 return -1;
26
27         name = talloc_strndup(script, argv[1], p - argv[1]);
28         value = talloc_strdup(script, p+1);
29
30         for (i = 2; i < argc; i++)
31                 value = talloc_asprintf_append(value, " %s", argv[i]);
32
33         script_env_set(script, name, value);
34
35         return 0;
36 }
37
38 static int builtin_linux(struct grub2_script *script,
39                 void *data __attribute__((unused)),
40                 int argc, char *argv[])
41 {
42         struct discover_boot_option *opt = script->opt;
43         const char *root;
44         int i;
45
46         if (!opt) {
47                 pb_log("grub2 syntax error: 'linux' statement outside "
48                                 "a menuentry.\n");
49                 return -1;
50         }
51
52         if (argc < 2) {
53                 pb_log("grub2 syntax error: no filename provided to "
54                                 "linux statement\n");
55                 return -1;
56         }
57
58         root = script_env_get(script, "root");
59
60         opt->boot_image = create_grub2_resource(opt, script->ctx->device,
61                                                 root, argv[1]);
62         opt->option->boot_args = NULL;
63
64         if (argc > 2)
65                 opt->option->boot_args = talloc_strdup(opt, argv[2]);
66
67         for (i = 3; i < argc; i++)
68                 opt->option->boot_args = talloc_asprintf_append(
69                                                 opt->option->boot_args,
70                                                 " %s", argv[i]);
71         return 0;
72 }
73
74 static int builtin_initrd(struct grub2_script *script,
75                 void *data __attribute__((unused)),
76                 int argc, char *argv[])
77 {
78         struct discover_boot_option *opt = script->opt;
79         const char *root;
80
81         if (!opt) {
82                 pb_log("grub2 syntax error: 'initrd' statement outside "
83                                 "a menuentry.\n");
84                 return -1;
85         }
86
87         if (argc < 2) {
88                 pb_log("grub2 syntax error: no filename provided to "
89                                 "initrd statement\n");
90                 return -1;
91         }
92
93         root = script_env_get(script, "root");
94         opt->initrd = create_grub2_resource(opt, script->ctx->device,
95                                                 root, argv[1]);
96
97         return 0;
98 }
99
100 static struct {
101         const char *name;
102         grub2_function fn;
103 } builtins[] = {
104         {
105                 .name = "set",
106                 .fn = builtin_set,
107         },
108         {
109                 .name = "linux",
110                 .fn = builtin_linux,
111         },
112         {
113                 .name = "initrd",
114                 .fn = builtin_initrd,
115         }
116 };
117
118 void register_builtins(struct grub2_script *script)
119 {
120         unsigned int i;
121
122         for (i = 0; i < ARRAY_SIZE(builtins); i++)
123                 script_register_function(script, builtins[i].name,
124                                 builtins[i].fn, NULL);
125 }