ffb6ecefcb5ab13a166cbdab8a0092db85a81ccd
[petitboot] / discover / grub2 / grub2.c
1
2 #include <assert.h>
3
4 #include <talloc/talloc.h>
5 #include <url/url.h>
6
7 #include <discover/resource.h>
8 #include <discover/parser.h>
9 #include <discover/parser-utils.h>
10
11 #include "grub2.h"
12 #include "parser.h"
13 #include "lexer.h"
14
15 static const char *const grub2_conf_files[] = {
16         "/grub.cfg",
17         "/menu.lst",
18         "/grub/grub.cfg",
19         "/grub2/grub.cfg",
20         "/grub/menu.lst",
21         "/boot/grub/grub.cfg",
22         "/boot/grub2/grub.cfg",
23         "/boot/grub/menu.lst",
24         "/GRUB.CFG",
25         "/MENU.LST",
26         "/GRUB/GRUB.CFG",
27         "/GRUB2/GRUB.CFG",
28         "/GRUB/MENU.LST",
29         "/BOOT/GRUB/GRUB.CFG",
30         "/BOOT/GRUB/MENU.LST",
31         NULL
32 };
33
34 struct grub2_resource_info {
35         char *root;
36         char *path;
37 };
38
39 /* we use slightly different resources for grub2 */
40 struct resource *create_grub2_resource(struct discover_boot_option *opt,
41                 struct discover_device *orig_device,
42                 const char *root, const char *path)
43 {
44         struct grub2_resource_info *info;
45         struct resource *res;
46
47         if (strstr(path, "://")) {
48                 struct pb_url *url = pb_url_parse(opt, path);
49                 if (url)
50                         return create_url_resource(opt, url);
51         }
52
53         res = talloc(opt, struct resource);
54
55         if (root) {
56                 info = talloc(res, struct grub2_resource_info);
57                 talloc_reference(info, root);
58                 info->root = talloc_strdup(info, root);
59                 info->path = talloc_strdup(info, path);
60
61                 res->resolved = false;
62                 res->info = info;
63
64         } else
65                 resolve_resource_against_device(res, orig_device, path);
66
67         return res;
68 }
69
70 bool resolve_grub2_resource(struct device_handler *handler,
71                 struct resource *res)
72 {
73         struct grub2_resource_info *info = res->info;
74         struct discover_device *dev;
75
76         assert(!res->resolved);
77
78         dev = device_lookup_by_uuid(handler, info->root);
79
80         if (!dev)
81                 return false;
82
83         resolve_resource_against_device(res, dev, info->path);
84         talloc_free(info);
85
86         return true;
87 }
88
89 static int grub2_parse(struct discover_context *dc)
90 {
91         const char * const *filename;
92         struct grub2_parser *parser;
93         int len, rc;
94         char *buf;
95
96         /* Support block device boot only at present */
97         if (dc->event)
98                 return -1;
99
100         for (filename = grub2_conf_files; *filename; filename++) {
101                 rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
102                 if (rc)
103                         continue;
104
105                 parser = grub2_parser_create(dc);
106                 grub2_parser_parse(parser, buf, len);
107                 talloc_free(buf);
108                 talloc_free(parser);
109                 break;
110         }
111
112
113         return 0;
114 }
115
116 static struct parser grub2_parser = {
117         .name                   = "grub2",
118         .parse                  = grub2_parse,
119         .resolve_resource       = resolve_grub2_resource,
120 };
121
122 register_parser(grub2_parser);