]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
16a31cc3603737f75a3f8d774955e8068d10dd4d
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_plugin.c
1 /******************************************************************************
2 * ventoy_plugin.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20 #include <grub/types.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/err.h>
24 #include <grub/dl.h>
25 #include <grub/disk.h>
26 #include <grub/device.h>
27 #include <grub/term.h>
28 #include <grub/partition.h>
29 #include <grub/file.h>
30 #include <grub/normal.h>
31 #include <grub/extcmd.h>
32 #include <grub/datetime.h>
33 #include <grub/i18n.h>
34 #include <grub/net.h>
35 #include <grub/time.h>
36 #include <grub/ventoy.h>
37 #include "ventoy_def.h"
38
39 GRUB_MOD_LICENSE ("GPLv3+");
40
41 static char g_iso_disk_name[128];
42 static install_template *g_install_template_head = NULL;
43 static persistence_config *g_persistence_head = NULL;
44
45 static int ventoy_plugin_control_entry(VTOY_JSON *json, const char *isodisk)
46 {
47 VTOY_JSON *pNode = NULL;
48 VTOY_JSON *pChild = NULL;
49
50 (void)isodisk;
51
52 if (json->enDataType != JSON_TYPE_ARRAY)
53 {
54 debug("Not array %d\n", json->enDataType);
55 return 0;
56 }
57
58 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
59 {
60 if (pNode->enDataType == JSON_TYPE_OBJECT)
61 {
62 pChild = pNode->pstChild;
63 if (pChild->enDataType == JSON_TYPE_STRING && pChild->pcName && pChild->unData.pcStrVal)
64 {
65 ventoy_set_env(pChild->pcName, pChild->unData.pcStrVal);
66 }
67 }
68 }
69
70 return 0;
71 }
72
73 static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
74 {
75 const char *value;
76 char filepath[256];
77
78 value = vtoy_json_get_string_ex(json->pstChild, "file");
79 if (value)
80 {
81 if (value[0] == '/')
82 {
83 grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value);
84 }
85 else
86 {
87 grub_snprintf(filepath, sizeof(filepath), "%s/ventoy/%s", isodisk, value);
88 }
89
90 if (ventoy_is_file_exist(filepath) == 0)
91 {
92 debug("Theme file %s does not exist\n", filepath);
93 return 0;
94 }
95
96 debug("vtoy_theme %s\n", filepath);
97 grub_env_set("vtoy_theme", filepath);
98 }
99
100 value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
101 if (value)
102 {
103 debug("vtoy_gfxmode %s\n", value);
104 grub_env_set("vtoy_gfxmode", value);
105 }
106
107 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
108 if (value)
109 {
110 grub_env_set("VTLE_LFT", value);
111 }
112
113 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
114 if (value)
115 {
116 grub_env_set("VTLE_TOP", value);
117 }
118
119 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
120 if (value)
121 {
122 grub_env_set("VTLE_CLR", value);
123 }
124
125 return 0;
126 }
127
128
129 static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk)
130 {
131 const char *iso = NULL;
132 const char *script = NULL;
133 VTOY_JSON *pNode = NULL;
134 install_template *node = NULL;
135 install_template *next = NULL;
136
137 (void)isodisk;
138
139 if (json->enDataType != JSON_TYPE_ARRAY)
140 {
141 debug("Not array %d\n", json->enDataType);
142 return 0;
143 }
144
145 if (g_install_template_head)
146 {
147 for (node = g_install_template_head; node; node = next)
148 {
149 next = node->next;
150 grub_free(node);
151 }
152
153 g_install_template_head = NULL;
154 }
155
156 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
157 {
158 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
159 if (iso && iso[0] == '/')
160 {
161 script = vtoy_json_get_string_ex(pNode->pstChild, "template");
162 if (script && script[0] == '/')
163 {
164 node = grub_zalloc(sizeof(install_template));
165 if (node)
166 {
167 grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
168 grub_snprintf(node->templatepath, sizeof(node->templatepath), "%s", script);
169
170 if (g_install_template_head)
171 {
172 node->next = g_install_template_head;
173 }
174
175 g_install_template_head = node;
176 }
177 }
178 }
179 }
180
181 return 0;
182 }
183
184
185 static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
186 {
187 const char *iso = NULL;
188 const char *persist = NULL;
189 VTOY_JSON *pNode = NULL;
190 persistence_config *node = NULL;
191 persistence_config *next = NULL;
192
193 (void)isodisk;
194
195 if (json->enDataType != JSON_TYPE_ARRAY)
196 {
197 debug("Not array %d\n", json->enDataType);
198 return 0;
199 }
200
201 if (g_persistence_head)
202 {
203 for (node = g_persistence_head; node; node = next)
204 {
205 next = node->next;
206 grub_free(node);
207 }
208
209 g_persistence_head = NULL;
210 }
211
212 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
213 {
214 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
215 if (iso && iso[0] == '/')
216 {
217 persist = vtoy_json_get_string_ex(pNode->pstChild, "backend");
218 if (persist && persist[0] == '/')
219 {
220 node = grub_zalloc(sizeof(persistence_config));
221 if (node)
222 {
223 grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
224 grub_snprintf(node->filepath, sizeof(node->filepath), "%s", persist);
225
226 if (g_persistence_head)
227 {
228 node->next = g_persistence_head;
229 }
230
231 g_persistence_head = node;
232 }
233 }
234 }
235 }
236
237 return 0;
238 }
239
240
241 static plugin_entry g_plugin_entries[] =
242 {
243 { "control", ventoy_plugin_control_entry },
244 { "theme", ventoy_plugin_theme_entry },
245 { "auto_install", ventoy_plugin_auto_install_entry },
246 { "persistence", ventoy_plugin_persistence_entry },
247 };
248
249 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
250 {
251 int i;
252 VTOY_JSON *cur = json;
253
254 grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk);
255
256 while (cur)
257 {
258 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
259 {
260 if (grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0)
261 {
262 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
263 g_plugin_entries[i].entryfunc(cur, isodisk);
264 break;
265 }
266 }
267
268 cur = cur->pstNext;
269 }
270
271 return 0;
272 }
273
274 grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
275 {
276 int ret = 0;
277 char *buf = NULL;
278 grub_file_t file;
279 VTOY_JSON *json = NULL;
280
281 (void)ctxt;
282 (void)argc;
283
284 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s/ventoy/ventoy.json", args[0]);
285 if (!file)
286 {
287 return GRUB_ERR_NONE;
288 }
289
290 debug("json configuration file size %d\n", (int)file->size);
291
292 buf = grub_malloc(file->size + 1);
293 if (!buf)
294 {
295 grub_file_close(file);
296 return 1;
297 }
298
299 buf[file->size] = 0;
300 grub_file_read(file, buf, file->size);
301 grub_file_close(file);
302
303 json = vtoy_json_create();
304 if (!json)
305 {
306 return 1;
307 }
308
309
310
311 ret = vtoy_json_parse(json, buf);
312 if (ret)
313 {
314 debug("Failed to parse json string %d\n", ret);
315 grub_free(buf);
316 return 1;
317 }
318
319 ventoy_parse_plugin_config(json->pstChild, args[0]);
320
321 vtoy_json_destroy(json);
322
323 grub_free(buf);
324
325 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
326 }
327
328
329 void ventoy_plugin_dump_auto_install(void)
330 {
331 install_template *node = NULL;
332
333 for (node = g_install_template_head; node; node = node->next)
334 {
335 grub_printf("IMAGE:<%s>\n", node->isopath);
336 grub_printf("SCRIPT:<%s>\n\n", node->templatepath);
337 }
338
339 return;
340 }
341
342 void ventoy_plugin_dump_persistence(void)
343 {
344 int rc;
345 persistence_config *node = NULL;
346 ventoy_img_chunk_list chunk_list;
347
348 for (node = g_persistence_head; node; node = node->next)
349 {
350 grub_printf("IMAGE:<%s>\n", node->isopath);
351 grub_printf("PERSIST:<%s>", node->filepath);
352
353 rc = ventoy_plugin_get_persistent_chunklist(node->isopath, &chunk_list);
354 if (rc == 0)
355 {
356 grub_printf(" [ SUCCESS ]\n\n");
357 grub_free(chunk_list.chunk);
358 }
359 else
360 {
361 grub_printf(" [ FAILED ]\n\n");
362 }
363 }
364
365 return;
366 }
367
368
369 char * ventoy_plugin_get_install_template(const char *isopath)
370 {
371 install_template *node = NULL;
372
373 for (node = g_install_template_head; node; node = node->next)
374 {
375 if (grub_strcmp(node->isopath, isopath) == 0)
376 {
377 return node->templatepath;
378 }
379 }
380
381 return NULL;
382 }
383
384 int ventoy_plugin_get_persistent_chunklist(const char *isopath, ventoy_img_chunk_list *chunk_list)
385 {
386 int rc = 1;
387 grub_uint64_t start = 0;
388 grub_file_t file = NULL;
389 persistence_config *node = NULL;
390
391 for (node = g_persistence_head; node; node = node->next)
392 {
393 if (grub_strcmp(node->isopath, isopath) == 0)
394 {
395 break;
396 }
397 }
398
399 if (NULL == node)
400 {
401 goto end;
402 }
403
404 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, node->filepath);
405 if (!file)
406 {
407 debug("Failed to open file %s%s\n", g_iso_disk_name, node->filepath);
408 goto end;
409 }
410
411 grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
412 chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
413 if (NULL == chunk_list->chunk)
414 {
415 goto end;
416 }
417
418 chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
419 chunk_list->cur_chunk = 0;
420
421 start = file->device->disk->partition->start;
422 ventoy_get_block_list(file, chunk_list, start);
423
424 if (0 != ventoy_check_block_list(file, chunk_list, start))
425 {
426 grub_free(chunk_list->chunk);
427 chunk_list->chunk = NULL;
428 goto end;
429 }
430
431 rc = 0;
432
433 end:
434 if (file)
435 grub_file_close(file);
436
437 return rc;
438 }
439