blob: e052bdccd62bb59261766996835e8a8b2e83fce4 [file] [log] [blame]
Klaus Heinrich Kiwid1cd8c52020-02-27 12:43:47 -03001From ecc3b2ee3645e2a79236856783d3f803121874b8 Mon Sep 17 00:00:00 2001
2From: Jeremy Kerr <jk@ozlabs.org>
3Date: Mon, 11 Nov 2019 19:30:41 +0800
4Subject: [PATCH 11/18] discover/grub2: Allow (device)/path references in
5 general script usage
6
7Currently, we have support for grub2 (device)/path syntax for boot
8resources. This change allows this syntax for general paths in grub2
9scripts (for example, -f tests).
10
11This involves exposing grub2_lookup_device, to allow the script
12execution code to resolve pathnames.
13
14Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
15(cherry picked from commit b22445748f44ed6965f31f45b39abb690d24ec47)
16Signed-off-by: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
17---
18 discover/grub2/builtins.c | 50 ++++++++++++++++---
19 discover/grub2/grub2.c | 4 +-
20 discover/grub2/grub2.h | 2 +
21 test/parser/Makefile.am | 1 +
22 test/parser/test-grub2-devpath-scripting.c | 56 ++++++++++++++++++++++
23 5 files changed, 104 insertions(+), 9 deletions(-)
24 create mode 100644 test/parser/test-grub2-devpath-scripting.c
25
26diff --git a/discover/grub2/builtins.c b/discover/grub2/builtins.c
27index 765c4d7..c726216 100644
28--- a/discover/grub2/builtins.c
29+++ b/discover/grub2/builtins.c
30@@ -197,6 +197,32 @@ static int builtin_search(struct grub2_script *script,
31 return 0;
32 }
33
34+static int parse_to_device_path(struct grub2_script *script,
35+ const char *desc, struct discover_device **devp,
36+ char **pathp)
37+{
38+ struct discover_device *dev;
39+ struct grub2_file *file;
40+
41+ file = grub2_parse_file(script, desc);
42+ if (!file)
43+ return -1;
44+
45+ dev = script->ctx->device;
46+ if (file->dev)
47+ dev = grub2_lookup_device(script->ctx->handler, file->dev);
48+
49+ if (!dev)
50+ return -1;
51+
52+ *devp = dev;
53+ *pathp = talloc_strdup(script, file->path);
54+
55+ talloc_free(file);
56+
57+ return 0;
58+}
59+
60 /* Note that GRUB does not follow symlinks in evaluating all file
61 * tests but -s, unlike below. However, it seems like a bad idea to
62 * emulate GRUB's behavior (e.g., it would take extra work), so we
63@@ -204,12 +230,17 @@ static int builtin_search(struct grub2_script *script,
64 static bool builtin_test_op_file(struct grub2_script *script, char op,
65 const char *file)
66 {
67+ struct discover_device *dev;
68+ struct stat statbuf;
69 bool result;
70+ char *path;
71 int rc;
72- struct stat statbuf;
73
74- rc = parser_stat_path(script->ctx, script->ctx->device,
75- file, &statbuf);
76+ rc = parse_to_device_path(script, file, &dev, &path);
77+ if (rc)
78+ return false;
79+
80+ rc = parser_stat_path(script->ctx, dev, path, &statbuf);
81 if (rc)
82 return false;
83
84@@ -237,16 +268,21 @@ static bool builtin_test_op_file(struct grub2_script *script, char op,
85 static bool builtin_test_op_dir(struct grub2_script *script, char op,
86 const char *dir)
87 {
88- int rc;
89+ struct discover_device *dev;
90 struct stat statbuf;
91+ char *path;
92+ int rc;
93
94 if (op != 'd')
95 return false;
96
97- rc = parser_stat_path(script->ctx, script->ctx->device, dir, &statbuf);
98- if (rc) {
99+ rc = parse_to_device_path(script, dir, &dev, &path);
100+ if (rc)
101+ return false;
102+
103+ rc = parser_stat_path(script->ctx, dev, path, &statbuf);
104+ if (rc)
105 return false;
106- }
107
108 return S_ISDIR(statbuf.st_mode);
109 }
110diff --git a/discover/grub2/grub2.c b/discover/grub2/grub2.c
111index a08a320..a8d115f 100644
112--- a/discover/grub2/grub2.c
113+++ b/discover/grub2/grub2.c
114@@ -33,8 +33,8 @@ static const char *const grub2_conf_files[] = {
115 NULL
116 };
117
118-static struct discover_device *grub2_lookup_device(
119- struct device_handler *handler, const char *desc)
120+struct discover_device *grub2_lookup_device(struct device_handler *handler,
121+ const char *desc)
122 {
123 struct discover_device *dev;
124
125diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
126index ef32d4b..eabd6d6 100644
127--- a/discover/grub2/grub2.h
128+++ b/discover/grub2/grub2.h
129@@ -200,6 +200,8 @@ bool resolve_grub2_resource(struct device_handler *handler,
130 /* grub-style device+path parsing */
131 struct grub2_file *grub2_parse_file(struct grub2_script *script,
132 const char *str);
133+struct discover_device *grub2_lookup_device(struct device_handler *handler,
134+ const char *desc);
135
136 /* external parser api */
137 struct grub2_parser *grub2_parser_create(struct discover_context *ctx);
138diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am
139index 0378317..c8e059b 100644
140--- a/test/parser/Makefile.am
141+++ b/test/parser/Makefile.am
142@@ -33,6 +33,7 @@ parser_TESTS = \
143 test/parser/test-grub2-search-uuid \
144 test/parser/test-grub2-search-label \
145 test/parser/test-grub2-devpath \
146+ test/parser/test-grub2-devpath-scripting \
147 test/parser/test-grub2-load-env \
148 test/parser/test-grub2-save-env \
149 test/parser/test-grub2-save-env-dash-f \
150diff --git a/test/parser/test-grub2-devpath-scripting.c b/test/parser/test-grub2-devpath-scripting.c
151new file mode 100644
152index 0000000..9046ab6
153--- /dev/null
154+++ b/test/parser/test-grub2-devpath-scripting.c
155@@ -0,0 +1,56 @@
156+/* check grub2 device+path string parsing, as used in scripts */
157+
158+#include "parser-test.h"
159+
160+#if 0 /* PARSER_EMBEDDED_CONFIG */
161+
162+v=
163+
164+# local device, file present
165+if [ -f "/1-present" ]; then v=${v}a; fi
166+
167+# local device, file absent
168+if [ -f "/1-absent" ]; then v=${v}b; fi;
169+
170+# local device by UUID, file present
171+if [ -f "(00000000-0000-0000-0000-000000000001)/1-present" ]; then v=${v}c; fi;
172+
173+# remote device by UUID, file present
174+if [ -f "(00000000-0000-0000-0000-000000000002)/2-present" ]; then v=${v}d; fi;
175+
176+# non-existent device
177+if [ -f "(00000000-0000-0000-0000-000000000003)/present" ]; then v=${v}e; fi;
178+
179+menuentry $v {
180+ linux /vmlinux
181+}
182+
183+#endif
184+
185+void run_test(struct parser_test *test)
186+{
187+ struct discover_device *dev1, *dev2;
188+ struct discover_boot_option *opt;
189+ struct discover_context *ctx;
190+
191+ ctx = test->ctx;
192+
193+ /* set local uuid */
194+ dev1 = test->ctx->device;
195+ dev1->uuid = "00000000-0000-0000-0000-000000000001";
196+
197+ dev2 = test_create_device(test, "extdev");
198+ dev2->uuid = "00000000-0000-0000-0000-000000000002";
199+ device_handler_add_device(ctx->handler, dev2);
200+
201+ test_add_file_data(test, dev1, "/1-present", "x", 1);
202+ test_add_file_data(test, dev2, "/2-present", "x", 1);
203+
204+ test_read_conf_embedded(test, "/grub/grub.cfg");
205+
206+ test_run_parser(test, "grub2");
207+
208+ check_boot_option_count(ctx, 1);
209+ opt = get_boot_option(ctx, 0);
210+ check_name(opt, "acd");
211+}
212--
2132.17.1
214