]> git.pld-linux.org Git - packages/grub2.git/blame - blscfg.patch
up to 2.12
[packages/grub2.git] / blscfg.patch
CommitLineData
f1c7b511
JP
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Peter Jones <pjones@redhat.com>
36121927 3Date: Tue, 22 Jan 2013 06:31:38 +0100
f1c7b511
JP
4Subject: [PATCH] blscfg: add blscfg module to parse Boot Loader Specification
5 snippets
36121927 6
f1c7b511
JP
7The BootLoaderSpec (BLS) defines a scheme where different bootloaders can
8share a format for boot items and a configuration directory that accepts
9these common configurations as drop-in files.
36121927 10
f1c7b511
JP
11Signed-off-by: Peter Jones <pjones@redhat.com>
12Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
13[wjt: some cleanups and fixes]
14Signed-off-by: Will Thompson <wjt@endlessm.com>
36121927 15---
f1c7b511
JP
16 grub-core/Makefile.core.def | 11 +
17 grub-core/commands/blscfg.c | 1096 ++++++++++++++++++++++++++++++++++++++++
18 grub-core/commands/legacycfg.c | 5 +-
19 grub-core/commands/loadenv.c | 77 +--
20 grub-core/commands/menuentry.c | 20 +-
21 grub-core/normal/main.c | 6 +
22 grub-core/commands/loadenv.h | 93 ++++
23 include/grub/compiler.h | 2 +
24 include/grub/menu.h | 13 +
25 include/grub/normal.h | 2 +-
26 10 files changed, 1243 insertions(+), 82 deletions(-)
36121927 27 create mode 100644 grub-core/commands/blscfg.c
f1c7b511 28 create mode 100644 grub-core/commands/loadenv.h
36121927
ER
29
30diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
f1c7b511 31index 41b5e16a3ce..57e253ab1a1 100644
36121927
ER
32--- a/grub-core/Makefile.core.def
33+++ b/grub-core/Makefile.core.def
f1c7b511
JP
34@@ -811,6 +811,16 @@ module = {
35 common = commands/blocklist.c;
36121927
ER
36 };
37
f1c7b511 38+module = {
36121927
ER
39+ name = blscfg;
40+ common = commands/blscfg.c;
f1c7b511
JP
41+ common = commands/loadenv.h;
42+ enable = powerpc_ieee1275;
43+ enable = efi;
36121927 44+ enable = i386_pc;
f1c7b511 45+ enable = emu;
36121927
ER
46+};
47+
f1c7b511 48 module = {
36121927
ER
49 name = boot;
50 common = commands/boot.c;
f1c7b511
JP
51@@ -988,6 +998,7 @@ module = {
52 module = {
53 name = loadenv;
54 common = commands/loadenv.c;
55+ common = commands/loadenv.h;
56 common = lib/envblk.c;
57 };
58
36121927
ER
59diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
60new file mode 100644
f1c7b511 61index 00000000000..54458b14518
36121927
ER
62--- /dev/null
63+++ b/grub-core/commands/blscfg.c
f1c7b511 64@@ -0,0 +1,1096 @@
36121927
ER
65+/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
66+
67+/* bls.c - implementation of the boot loader spec */
68+
69+/*
70+ * GRUB -- GRand Unified Bootloader
71+ *
72+ * GRUB is free software: you can redistribute it and/or modify
73+ * it under the terms of the GNU General Public License as published by
74+ * the Free Software Foundation, either version 3 of the License, or
75+ * (at your option) any later version.
76+ *
77+ * GRUB is distributed in the hope that it will be useful,
78+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
79+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80+ * GNU General Public License for more details.
81+ *
82+ * You should have received a copy of the GNU General Public License
83+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
84+ */
85+
f1c7b511 86+#include <grub/list.h>
36121927
ER
87+#include <grub/types.h>
88+#include <grub/misc.h>
89+#include <grub/mm.h>
90+#include <grub/err.h>
91+#include <grub/dl.h>
92+#include <grub/extcmd.h>
93+#include <grub/i18n.h>
94+#include <grub/fs.h>
95+#include <grub/env.h>
96+#include <grub/file.h>
97+#include <grub/normal.h>
f1c7b511
JP
98+#include <grub/lib/envblk.h>
99+
100+#include <stdbool.h>
36121927
ER
101+
102+GRUB_MOD_LICENSE ("GPLv3+");
103+
f1c7b511
JP
104+#include "loadenv.h"
105+
36121927 106+#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
f1c7b511
JP
107+#ifdef GRUB_MACHINE_EMU
108+#define GRUB_BOOT_DEVICE "/boot"
109+#else
36121927
ER
110+#define GRUB_BOOT_DEVICE "($root)"
111+#endif
112+
f1c7b511
JP
113+struct keyval
114+{
115+ const char *key;
116+ char *val;
117+};
118+
119+static struct bls_entry *entries = NULL;
120+
121+#define FOR_BLS_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries)
122+
123+static int bls_add_keyval(struct bls_entry *entry, char *key, char *val)
124+{
125+ char *k, *v;
126+ struct keyval **kvs, *kv;
127+ int new_n = entry->nkeyvals + 1;
128+
129+ kvs = grub_realloc (entry->keyvals, new_n * sizeof (struct keyval *));
130+ if (!kvs)
131+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
132+ "couldn't find space for BLS entry");
133+ entry->keyvals = kvs;
134+
135+ kv = grub_malloc (sizeof (struct keyval));
136+ if (!kv)
137+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
138+ "couldn't find space for BLS entry");
139+
140+ k = grub_strdup (key);
141+ if (!k)
142+ {
143+ grub_free (kv);
144+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
145+ "couldn't find space for BLS entry");
146+ }
147+
148+ v = grub_strdup (val);
149+ if (!v)
150+ {
151+ grub_free (k);
152+ grub_free (kv);
153+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
154+ "couldn't find space for BLS entry");
155+ }
156+
157+ kv->key = k;
158+ kv->val = v;
159+
160+ entry->keyvals[entry->nkeyvals] = kv;
161+ grub_dprintf("blscfg", "new keyval at %p:%s:%s\n", entry->keyvals[entry->nkeyvals], k, v);
162+ entry->nkeyvals = new_n;
163+
164+ return 0;
165+}
166+
167+/* Find they value of the key named by keyname. If there are allowed to be
168+ * more than one, pass a pointer to an int set to -1 the first time, and pass
169+ * the same pointer through each time after, and it'll return them in sorted
170+ * order as defined in the BLS fragment file */
171+static char *bls_get_val(struct bls_entry *entry, const char *keyname, int *last)
172+{
173+ int idx, start = 0;
174+ struct keyval *kv = NULL;
175+
176+ if (last)
177+ start = *last + 1;
178+
179+ for (idx = start; idx < entry->nkeyvals; idx++) {
180+ kv = entry->keyvals[idx];
181+
182+ if (!grub_strcmp (keyname, kv->key))
183+ break;
184+ }
185+
186+ if (idx == entry->nkeyvals) {
187+ if (last)
188+ *last = -1;
189+ return NULL;
190+ }
191+
192+ if (last)
193+ *last = idx;
194+
195+ return kv->val;
196+}
197+
198+#define goto_return(x) ({ ret = (x); goto finish; })
199+
200+/* compare alpha and numeric segments of two versions */
201+/* return 1: a is newer than b */
202+/* 0: a and b are the same version */
203+/* -1: b is newer than a */
204+static int vercmp(const char * a, const char * b)
205+{
206+ char oldch1, oldch2;
207+ char *abuf, *bbuf;
208+ char *str1, *str2;
209+ char * one, * two;
210+ int rc;
211+ int isnum;
212+ int ret = 0;
213+
214+ grub_dprintf("blscfg", "%s comparing %s and %s\n", __func__, a, b);
215+ if (!grub_strcmp(a, b))
216+ return 0;
217+
218+ abuf = grub_malloc(grub_strlen(a) + 1);
219+ bbuf = grub_malloc(grub_strlen(b) + 1);
220+ str1 = abuf;
221+ str2 = bbuf;
222+ grub_strcpy(str1, a);
223+ grub_strcpy(str2, b);
224+
225+ one = str1;
226+ two = str2;
227+
228+ /* loop through each version segment of str1 and str2 and compare them */
229+ while (*one || *two) {
230+ while (*one && !grub_isalnum(*one) && *one != '~') one++;
231+ while (*two && !grub_isalnum(*two) && *two != '~') two++;
232+
233+ /* handle the tilde separator, it sorts before everything else */
234+ if (*one == '~' || *two == '~') {
235+ if (*one != '~') goto_return (1);
236+ if (*two != '~') goto_return (-1);
237+ one++;
238+ two++;
239+ continue;
240+ }
241+
242+ /* If we ran to the end of either, we are finished with the loop */
243+ if (!(*one && *two)) break;
244+
245+ str1 = one;
246+ str2 = two;
247+
248+ /* grab first completely alpha or completely numeric segment */
249+ /* leave one and two pointing to the start of the alpha or numeric */
250+ /* segment and walk str1 and str2 to end of segment */
251+ if (grub_isdigit(*str1)) {
252+ while (*str1 && grub_isdigit(*str1)) str1++;
253+ while (*str2 && grub_isdigit(*str2)) str2++;
254+ isnum = 1;
255+ } else {
256+ while (*str1 && grub_isalpha(*str1)) str1++;
257+ while (*str2 && grub_isalpha(*str2)) str2++;
258+ isnum = 0;
259+ }
260+
261+ /* save character at the end of the alpha or numeric segment */
262+ /* so that they can be restored after the comparison */
263+ oldch1 = *str1;
264+ *str1 = '\0';
265+ oldch2 = *str2;
266+ *str2 = '\0';
267+
268+ /* this cannot happen, as we previously tested to make sure that */
269+ /* the first string has a non-null segment */
270+ if (one == str1) goto_return(-1); /* arbitrary */
271+
272+ /* take care of the case where the two version segments are */
273+ /* different types: one numeric, the other alpha (i.e. empty) */
274+ /* numeric segments are always newer than alpha segments */
275+ /* XXX See patch #60884 (and details) from bugzilla #50977. */
276+ if (two == str2) goto_return (isnum ? 1 : -1);
277+
278+ if (isnum) {
279+ grub_size_t onelen, twolen;
280+ /* this used to be done by converting the digit segments */
281+ /* to ints using atoi() - it's changed because long */
282+ /* digit segments can overflow an int - this should fix that. */
283+
284+ /* throw away any leading zeros - it's a number, right? */
285+ while (*one == '0') one++;
286+ while (*two == '0') two++;
287+
288+ /* whichever number has more digits wins */
289+ onelen = grub_strlen(one);
290+ twolen = grub_strlen(two);
291+ if (onelen > twolen) goto_return (1);
292+ if (twolen > onelen) goto_return (-1);
293+ }
294+
295+ /* grub_strcmp will return which one is greater - even if the two */
296+ /* segments are alpha or if they are numeric. don't return */
297+ /* if they are equal because there might be more segments to */
298+ /* compare */
299+ rc = grub_strcmp(one, two);
300+ if (rc) goto_return (rc < 1 ? -1 : 1);
301+
302+ /* restore character that was replaced by null above */
303+ *str1 = oldch1;
304+ one = str1;
305+ *str2 = oldch2;
306+ two = str2;
307+ }
308+
309+ /* this catches the case where all numeric and alpha segments have */
310+ /* compared identically but the segment sepparating characters were */
311+ /* different */
312+ if ((!*one) && (!*two)) goto_return (0);
313+
314+ /* whichever version still has characters left over wins */
315+ if (!*one) goto_return (-1); else goto_return (1);
316+
317+finish:
318+ grub_free (abuf);
319+ grub_free (bbuf);
320+ return ret;
321+}
322+
323+/* returns name/version/release */
324+/* NULL string pointer returned if nothing found */
325+static void
326+split_package_string (char *package_string, char **name,
327+ char **version, char **release)
328+{
329+ char *package_version, *package_release;
330+
331+ /* Release */
332+ package_release = grub_strrchr (package_string, '-');
333+
334+ if (package_release != NULL)
335+ *package_release++ = '\0';
336+
337+ *release = package_release;
338+
339+ if (name == NULL)
340+ {
341+ *version = package_string;
342+ }
343+ else
344+ {
345+ /* Version */
346+ package_version = grub_strrchr(package_string, '-');
347+
348+ if (package_version != NULL)
349+ *package_version++ = '\0';
350+
351+ *version = package_version;
352+ /* Name */
353+ *name = package_string;
354+ }
355+
356+ /* Bubble up non-null values from release to name */
357+ if (name != NULL && *name == NULL)
358+ {
359+ *name = (*version == NULL ? *release : *version);
360+ *version = *release;
361+ *release = NULL;
362+ }
363+ if (*version == NULL)
364+ {
365+ *version = *release;
366+ *release = NULL;
367+ }
368+}
369+
370+static int
371+split_cmp(char *nvr0, char *nvr1, int has_name)
372+{
373+ int ret = 0;
374+ char *name0, *version0, *release0;
375+ char *name1, *version1, *release1;
376+
377+ split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0);
378+ split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1);
379+
380+ if (has_name)
381+ {
382+ ret = vercmp(name0 == NULL ? "" : name0,
383+ name1 == NULL ? "" : name1);
384+ if (ret != 0)
385+ return ret;
386+ }
387+
388+ ret = vercmp(version0 == NULL ? "" : version0,
389+ version1 == NULL ? "" : version1);
390+ if (ret != 0)
391+ return ret;
392+
393+ ret = vercmp(release0 == NULL ? "" : release0,
394+ release1 == NULL ? "" : release1);
395+ return ret;
396+}
397+
398+/* return 1: e0 is newer than e1 */
399+/* 0: e0 and e1 are the same version */
400+/* -1: e1 is newer than e0 */
401+static int bls_cmp(const struct bls_entry *e0, const struct bls_entry *e1)
402+{
403+ char *id0, *id1;
404+ int r;
405+
406+ id0 = grub_strdup(e0->filename);
407+ id1 = grub_strdup(e1->filename);
408+
409+ r = split_cmp(id0, id1, 1);
410+
411+ grub_free(id0);
412+ grub_free(id1);
413+
414+ return r;
415+}
416+
417+static void list_add_tail(struct bls_entry *head, struct bls_entry *item)
418+{
419+ item->next = head;
420+ if (head->prev)
421+ head->prev->next = item;
422+ item->prev = head->prev;
423+ head->prev = item;
424+}
425+
426+static int bls_add_entry(struct bls_entry *entry)
427+{
428+ struct bls_entry *e, *last = NULL;
429+ int rc;
430+
431+ if (!entries) {
432+ grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
433+ entries = entry;
434+ return 0;
435+ }
436+
437+ FOR_BLS_ENTRIES(e) {
438+ rc = bls_cmp(entry, e);
439+
440+ if (!rc)
441+ return GRUB_ERR_BAD_ARGUMENT;
442+
443+ if (rc == 1) {
444+ grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
445+ list_add_tail (e, entry);
446+ if (e == entries) {
447+ entries = entry;
448+ entry->prev = NULL;
449+ }
450+ return 0;
451+ }
452+ last = e;
453+ }
454+
455+ if (last) {
456+ grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
457+ last->next = entry;
458+ entry->prev = last;
459+ }
460+
461+ return 0;
462+}
463+
464+struct read_entry_info {
465+ const char *devid;
466+ const char *dirname;
467+ grub_file_t file;
468+};
469+
470+static int read_entry (
36121927 471+ const char *filename,
f1c7b511
JP
472+ const struct grub_dirhook_info *dirhook_info UNUSED,
473+ void *data)
36121927 474+{
f1c7b511
JP
475+ grub_size_t m = 0, n, clip = 0;
476+ int rc = 0;
477+ char *p = NULL;
36121927 478+ grub_file_t f = NULL;
f1c7b511
JP
479+ struct bls_entry *entry;
480+ struct read_entry_info *info = (struct read_entry_info *)data;
36121927 481+
f1c7b511 482+ grub_dprintf ("blscfg", "filename: \"%s\"\n", filename);
36121927
ER
483+
484+ n = grub_strlen (filename);
36121927 485+
f1c7b511
JP
486+ if (info->file)
487+ {
488+ f = info->file;
489+ }
490+ else
491+ {
492+ if (filename[0] == '.')
493+ return 0;
494+
495+ if (n <= 5)
496+ return 0;
497+
498+ if (grub_strcmp (filename + n - 5, ".conf") != 0)
499+ return 0;
36121927 500+
f1c7b511 501+ p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
36121927 502+
f1c7b511
JP
503+ f = grub_file_open (p, GRUB_FILE_TYPE_CONFIG);
504+ if (!f)
505+ goto finish;
506+ }
507+
508+ entry = grub_zalloc (sizeof (*entry));
509+ if (!entry)
36121927
ER
510+ goto finish;
511+
f1c7b511
JP
512+ if (info->file)
513+ {
514+ char *slash;
515+
516+ if (n > 5 && !grub_strcmp (filename + n - 5, ".conf") == 0)
517+ clip = 5;
518+
519+ slash = grub_strrchr (filename, '/');
520+ if (!slash)
521+ slash = grub_strrchr (filename, '\\');
522+
523+ while (*slash == '/' || *slash == '\\')
524+ slash++;
525+
526+ m = slash ? slash - filename : 0;
527+ }
528+ else
529+ {
530+ m = 0;
531+ clip = 5;
532+ }
533+ n -= m;
534+
535+ entry->filename = grub_strndup(filename + m, n - clip);
536+ if (!entry->filename)
36121927
ER
537+ goto finish;
538+
f1c7b511
JP
539+ entry->filename[n - 5] = '\0';
540+
36121927
ER
541+ for (;;)
542+ {
543+ char *buf;
f1c7b511 544+ char *separator;
36121927
ER
545+
546+ buf = grub_file_getline (f);
547+ if (!buf)
548+ break;
549+
f1c7b511
JP
550+ while (buf && buf[0] && (buf[0] == ' ' || buf[0] == '\t'))
551+ buf++;
552+ if (buf[0] == '#')
553+ continue;
554+
555+ separator = grub_strchr (buf, ' ');
556+
557+ if (!separator)
558+ separator = grub_strchr (buf, '\t');
559+
560+ if (!separator || separator[1] == '\0')
36121927 561+ {
f1c7b511
JP
562+ grub_free (buf);
563+ break;
36121927 564+ }
f1c7b511
JP
565+
566+ separator[0] = '\0';
567+
568+ do {
569+ separator++;
570+ } while (*separator == ' ' || *separator == '\t');
571+
572+ rc = bls_add_keyval (entry, buf, separator);
573+ grub_free (buf);
574+ if (rc < 0)
575+ break;
576+ }
577+
578+ if (!rc)
579+ bls_add_entry(entry);
580+
581+finish:
582+ if (p)
583+ grub_free (p);
584+
585+ if (f)
586+ grub_file_close (f);
587+
588+ return 0;
589+}
590+
591+static grub_envblk_t saved_env = NULL;
592+
593+static int UNUSED
594+save_var (const char *name, const char *value, void *whitelist UNUSED)
595+{
596+ const char *val = grub_env_get (name);
597+ grub_dprintf("blscfg", "saving \"%s\"\n", name);
598+
599+ if (val)
600+ grub_envblk_set (saved_env, name, value);
601+
602+ return 0;
603+}
604+
605+static int UNUSED
606+unset_var (const char *name, const char *value UNUSED, void *whitelist)
607+{
608+ grub_dprintf("blscfg", "restoring \"%s\"\n", name);
609+ if (! whitelist)
610+ {
611+ grub_env_unset (name);
612+ return 0;
613+ }
614+
615+ if (test_whitelist_membership (name,
616+ (const grub_env_whitelist_t *) whitelist))
617+ grub_env_unset (name);
618+
619+ return 0;
620+}
621+
622+static char **bls_make_list (struct bls_entry *entry, const char *key, int *num)
623+{
624+ int last = -1;
625+ char *val;
626+
627+ int nlist = 0;
628+ char **list = NULL;
629+
630+ list = grub_malloc (sizeof (char *));
631+ if (!list)
632+ return NULL;
633+ list[0] = NULL;
634+
635+ while (1)
636+ {
637+ char **new;
638+
639+ val = bls_get_val (entry, key, &last);
640+ if (!val)
641+ break;
642+
643+ new = grub_realloc (list, (nlist + 2) * sizeof (char *));
644+ if (!new)
645+ break;
646+
647+ list = new;
648+ list[nlist++] = val;
649+ list[nlist] = NULL;
650+ }
651+
652+ if (num)
653+ *num = nlist;
654+
655+ return list;
656+}
657+
658+static char *field_append(bool is_var, char *buffer, char *start, char *end)
659+{
660+ char *temp = grub_strndup(start, end - start + 1);
661+ const char *field = temp;
662+
663+ if (is_var) {
664+ field = grub_env_get (temp);
665+ if (!field)
666+ return buffer;
667+ }
668+
669+ if (!buffer) {
670+ buffer = grub_strdup(field);
671+ if (!buffer)
672+ return NULL;
673+ } else {
674+ buffer = grub_realloc (buffer, grub_strlen(buffer) + grub_strlen(field));
675+ if (!buffer)
676+ return NULL;
677+
678+ grub_stpcpy (buffer + grub_strlen(buffer), field);
679+ }
680+
681+ return buffer;
682+}
683+
684+static char *expand_val(char *value)
685+{
686+ char *buffer = NULL;
687+ char *start = value;
688+ char *end = value;
689+ bool is_var = false;
690+
691+ if (!value)
692+ return NULL;
693+
694+ while (*value) {
695+ if (*value == '$') {
696+ if (start != end) {
697+ buffer = field_append(is_var, buffer, start, end);
698+ if (!buffer)
699+ return NULL;
700+ }
701+
702+ is_var = true;
703+ start = value + 1;
704+ } else if (is_var) {
705+ if (!grub_isalnum(*value) && *value != '_') {
706+ buffer = field_append(is_var, buffer, start, end);
707+ is_var = false;
708+ start = value;
709+ }
710+ }
711+
712+ end = value;
713+ value++;
714+ }
715+
716+ if (start != end) {
717+ buffer = field_append(is_var, buffer, start, end);
718+ if (!buffer)
719+ return NULL;
720+ }
721+
722+ return buffer;
723+}
724+
725+static char **early_initrd_list (const char *initrd)
726+{
727+ int nlist = 0;
728+ char **list = NULL;
729+ char *separator;
730+
731+ while ((separator = grub_strchr (initrd, ' ')))
732+ {
733+ list = grub_realloc (list, (nlist + 2) * sizeof (char *));
734+ if (!list)
735+ return NULL;
736+
737+ list[nlist++] = grub_strndup(initrd, separator - initrd);
738+ list[nlist] = NULL;
739+ initrd = separator + 1;
740+ }
741+
742+ list = grub_realloc (list, (nlist + 2) * sizeof (char *));
743+ if (!list)
744+ return NULL;
745+
746+ list[nlist++] = grub_strndup(initrd, grub_strlen(initrd));
747+ list[nlist] = NULL;
748+
749+ return list;
750+}
751+
752+static void create_entry (struct bls_entry *entry)
753+{
754+ int argc = 0;
755+ const char **argv = NULL;
756+
757+ char *title = NULL;
758+ char *clinux = NULL;
759+ char *options = NULL;
760+ char **initrds = NULL;
761+ char *initrd = NULL;
762+ const char *early_initrd = NULL;
763+ char **early_initrds = NULL;
764+ char *initrd_prefix = NULL;
765+ char *id = entry->filename;
766+ char *dotconf = id;
767+ char *hotkey = NULL;
768+
769+ char *users = NULL;
770+ char **classes = NULL;
771+
772+ char **args = NULL;
773+
774+ char *src = NULL;
775+ int i, index;
776+
777+ grub_dprintf("blscfg", "%s got here\n", __func__);
778+ clinux = bls_get_val (entry, "linux", NULL);
779+ if (!clinux)
780+ {
781+ grub_dprintf ("blscfg", "Skipping file %s with no 'linux' key.\n", entry->filename);
782+ goto finish;
783+ }
784+
785+ /*
786+ * strip the ".conf" off the end before we make it our "id" field.
787+ */
788+ do
789+ {
790+ dotconf = grub_strstr(dotconf, ".conf");
791+ } while (dotconf != NULL && dotconf[5] != '\0');
792+ if (dotconf)
793+ dotconf[0] = '\0';
794+
795+ title = bls_get_val (entry, "title", NULL);
796+ options = expand_val (bls_get_val (entry, "options", NULL));
797+
798+ if (!options)
799+ options = expand_val (grub_env_get("default_kernelopts"));
800+
801+ initrds = bls_make_list (entry, "initrd", NULL);
802+
803+ hotkey = bls_get_val (entry, "grub_hotkey", NULL);
804+ users = expand_val (bls_get_val (entry, "grub_users", NULL));
805+ classes = bls_make_list (entry, "grub_class", NULL);
806+ args = bls_make_list (entry, "grub_arg", &argc);
807+
808+ argc += 1;
809+ argv = grub_malloc ((argc + 1) * sizeof (char *));
810+ argv[0] = title ? title : clinux;
811+ for (i = 1; i < argc; i++)
812+ argv[i] = args[i-1];
813+ argv[argc] = NULL;
814+
815+ early_initrd = grub_env_get("early_initrd");
816+
817+ grub_dprintf ("blscfg", "adding menu entry for \"%s\" with id \"%s\"\n",
818+ title, id);
819+ if (early_initrd)
820+ {
821+ early_initrds = early_initrd_list(early_initrd);
822+ if (!early_initrds)
823+ {
824+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
825+ goto finish;
826+ }
827+
828+ if (initrds != NULL && initrds[0] != NULL)
36121927 829+ {
f1c7b511
JP
830+ initrd_prefix = grub_strrchr (initrds[0], '/');
831+ initrd_prefix = grub_strndup(initrds[0], initrd_prefix - initrds[0] + 1);
36121927 832+ }
f1c7b511 833+ else
36121927 834+ {
f1c7b511
JP
835+ initrd_prefix = grub_strrchr (clinux, '/');
836+ initrd_prefix = grub_strndup(clinux, initrd_prefix - clinux + 1);
36121927 837+ }
f1c7b511
JP
838+
839+ if (!initrd_prefix)
36121927 840+ {
f1c7b511
JP
841+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
842+ goto finish;
36121927 843+ }
36121927
ER
844+ }
845+
f1c7b511 846+ if (early_initrds || initrds)
36121927 847+ {
f1c7b511
JP
848+ int initrd_size = sizeof ("initrd");
849+ char *tmp;
850+
851+ for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
852+ initrd_size += sizeof (" " GRUB_BOOT_DEVICE) \
853+ + grub_strlen(initrd_prefix) \
854+ + grub_strlen (early_initrds[i]) + 1;
855+
856+ for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
857+ initrd_size += sizeof (" " GRUB_BOOT_DEVICE) \
858+ + grub_strlen (initrds[i]) + 1;
859+ initrd_size += 1;
860+
861+ initrd = grub_malloc (initrd_size);
862+ if (!initrd)
863+ {
864+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
865+ goto finish;
866+ }
36121927 867+
f1c7b511
JP
868+
869+ tmp = grub_stpcpy(initrd, "initrd");
870+ for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
871+ {
872+ grub_dprintf ("blscfg", "adding early initrd %s\n", early_initrds[i]);
873+ tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
874+ tmp = grub_stpcpy (tmp, initrd_prefix);
875+ tmp = grub_stpcpy (tmp, early_initrds[i]);
876+ grub_free(early_initrds[i]);
877+ }
878+
879+ for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
880+ {
881+ grub_dprintf ("blscfg", "adding initrd %s\n", initrds[i]);
882+ tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
883+ tmp = grub_stpcpy (tmp, initrds[i]);
884+ }
885+ tmp = grub_stpcpy (tmp, "\n");
886+ }
36121927
ER
887+
888+ src = grub_xasprintf ("load_video\n"
f1c7b511 889+ "set gfxpayload=keep\n"
36121927 890+ "insmod gzio\n"
f1c7b511
JP
891+ "linux %s%s%s%s\n"
892+ "%s",
36121927 893+ GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
f1c7b511 894+ initrd ? initrd : "");
36121927 895+
f1c7b511
JP
896+ grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, &index, entry);
897+ grub_dprintf ("blscfg", "Added entry %d id:\"%s\"\n", index, id);
36121927
ER
898+
899+finish:
36121927 900+ grub_free (initrd);
f1c7b511
JP
901+ grub_free (initrd_prefix);
902+ grub_free (early_initrds);
903+ grub_free (initrds);
904+ grub_free (options);
905+ grub_free (classes);
906+ grub_free (args);
907+ grub_free (argv);
36121927 908+ grub_free (src);
f1c7b511 909+}
36121927 910+
f1c7b511
JP
911+struct find_entry_info {
912+ const char *dirname;
913+ const char *devid;
914+ grub_device_t dev;
915+ grub_fs_t fs;
916+};
917+
918+/*
919+ * info: the filesystem object the file is on.
920+ */
921+static int find_entry (struct find_entry_info *info)
922+{
923+ struct read_entry_info read_entry_info;
924+ grub_fs_t blsdir_fs = NULL;
925+ grub_device_t blsdir_dev = NULL;
926+ const char *blsdir = info->dirname;
927+ int fallback = 0;
928+ int r = 0;
929+
930+ if (!blsdir) {
931+ blsdir = grub_env_get ("blsdir");
932+ if (!blsdir)
933+ blsdir = GRUB_BLS_CONFIG_PATH;
934+ }
935+
936+ read_entry_info.file = NULL;
937+ read_entry_info.dirname = blsdir;
938+
939+ grub_dprintf ("blscfg", "scanning blsdir: %s\n", blsdir);
940+
941+ blsdir_dev = info->dev;
942+ blsdir_fs = info->fs;
943+ read_entry_info.devid = info->devid;
944+
945+read_fallback:
946+ r = blsdir_fs->fs_dir (blsdir_dev, read_entry_info.dirname, read_entry,
947+ &read_entry_info);
948+ if (r != 0) {
949+ grub_dprintf ("blscfg", "read_entry returned error\n");
950+ grub_err_t e;
951+ do
952+ {
953+ e = grub_error_pop();
954+ } while (e);
955+ }
956+
957+ if (r && !info->dirname && !fallback) {
958+ read_entry_info.dirname = "/boot" GRUB_BLS_CONFIG_PATH;
959+ grub_dprintf ("blscfg", "Entries weren't found in %s, fallback to %s\n",
960+ blsdir, read_entry_info.dirname);
961+ fallback = 1;
962+ goto read_fallback;
963+ }
36121927
ER
964+
965+ return 0;
966+}
967+
968+static grub_err_t
f1c7b511 969+bls_load_entries (const char *path)
36121927 970+{
f1c7b511 971+ grub_size_t len;
36121927
ER
972+ grub_fs_t fs;
973+ grub_device_t dev;
974+ static grub_err_t r;
f1c7b511
JP
975+ const char *devid = NULL;
976+ char *blsdir = NULL;
977+ struct find_entry_info info = {
978+ .dev = NULL,
979+ .fs = NULL,
980+ .dirname = NULL,
981+ };
982+ struct read_entry_info rei = {
983+ .devid = NULL,
984+ .dirname = NULL,
985+ };
986+
987+ if (path) {
988+ len = grub_strlen (path);
989+ if (grub_strcmp (path + len - 5, ".conf") == 0) {
990+ rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG);
991+ if (!rei.file)
992+ return grub_errno;
993+ /*
994+ * read_entry() closes the file
995+ */
996+ return read_entry(path, NULL, &rei);
997+ } else if (path[0] == '(') {
998+ devid = path + 1;
999+
1000+ blsdir = grub_strchr (path, ')');
1001+ if (!blsdir)
1002+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Filepath isn't correct"));
36121927 1003+
f1c7b511
JP
1004+ *blsdir = '\0';
1005+ blsdir = blsdir + 1;
1006+ }
1007+ }
1008+
1009+ if (!devid) {
1010+#ifdef GRUB_MACHINE_EMU
1011+ devid = "host";
1012+#elif defined(GRUB_MACHINE_EFI)
1013+ devid = grub_env_get ("root");
1014+#else
1015+ devid = grub_env_get ("boot");
1016+#endif
1017+ if (!devid)
1018+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
1019+ N_("variable `%s' isn't set"), "boot");
1020+ }
36121927 1021+
f1c7b511 1022+ grub_dprintf ("blscfg", "opening %s\n", devid);
36121927
ER
1023+ dev = grub_device_open (devid);
1024+ if (!dev)
1025+ return grub_errno;
1026+
f1c7b511 1027+ grub_dprintf ("blscfg", "probing fs\n");
36121927
ER
1028+ fs = grub_fs_probe (dev);
1029+ if (!fs)
1030+ {
1031+ r = grub_errno;
1032+ goto finish;
1033+ }
1034+
f1c7b511
JP
1035+ info.dirname = blsdir;
1036+ info.devid = devid;
1037+ info.dev = dev;
1038+ info.fs = fs;
1039+ find_entry(&info);
36121927
ER
1040+
1041+finish:
1042+ if (dev)
1043+ grub_device_close (dev);
1044+
1045+ return r;
1046+}
1047+
f1c7b511
JP
1048+static bool
1049+is_default_entry(const char *def_entry, struct bls_entry *entry, int idx)
1050+{
1051+ const char *title;
1052+ int def_idx;
1053+
1054+ if (!def_entry)
1055+ return false;
1056+
1057+ if (grub_strcmp(def_entry, entry->filename) == 0)
1058+ return true;
1059+
1060+ title = bls_get_val(entry, "title", NULL);
1061+
1062+ if (title && grub_strcmp(def_entry, title) == 0)
1063+ return true;
1064+
1065+ def_idx = (int)grub_strtol(def_entry, NULL, 0);
1066+ if (grub_errno == GRUB_ERR_BAD_NUMBER) {
1067+ grub_errno = GRUB_ERR_NONE;
1068+ return false;
1069+ }
1070+
1071+ if (def_idx == idx)
1072+ return true;
1073+
1074+ return false;
1075+}
1076+
1077+static grub_err_t
1078+bls_create_entries (bool show_default, bool show_non_default, char *entry_id)
1079+{
1080+ const char *def_entry = NULL;
1081+ struct bls_entry *entry = NULL;
1082+ int idx = 0;
1083+
1084+ def_entry = grub_env_get("default");
1085+
1086+ grub_dprintf ("blscfg", "%s Creating entries from bls\n", __func__);
1087+ FOR_BLS_ENTRIES(entry) {
1088+ if (entry->visible) {
1089+ idx++;
1090+ continue;
1091+ }
1092+
1093+ if ((show_default && is_default_entry(def_entry, entry, idx)) ||
1094+ (show_non_default && !is_default_entry(def_entry, entry, idx)) ||
1095+ (entry_id && grub_strcmp(entry_id, entry->filename) == 0)) {
1096+ create_entry(entry);
1097+ entry->visible = 1;
1098+ }
1099+ idx++;
1100+ }
1101+
1102+ return GRUB_ERR_NONE;
1103+}
1104+
1105+static grub_err_t
1106+grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
1107+ int argc, char **args)
1108+{
1109+ grub_err_t r;
1110+ char *path = NULL;
1111+ char *entry_id = NULL;
1112+ bool show_default = true;
1113+ bool show_non_default = true;
1114+
1115+ if (argc == 1) {
1116+ if (grub_strcmp (args[0], "default") == 0) {
1117+ show_non_default = false;
1118+ } else if (grub_strcmp (args[0], "non-default") == 0) {
1119+ show_default = false;
1120+ } else if (args[0][0] == '(') {
1121+ path = args[0];
1122+ } else {
1123+ entry_id = args[0];
1124+ show_default = false;
1125+ show_non_default = false;
1126+ }
1127+ }
1128+
1129+ r = bls_load_entries(path);
1130+ if (r)
1131+ return r;
1132+
1133+ return bls_create_entries(show_default, show_non_default, entry_id);
1134+}
1135+
36121927 1136+static grub_extcmd_t cmd;
f1c7b511 1137+static grub_extcmd_t oldcmd;
36121927 1138+
f1c7b511 1139+GRUB_MOD_INIT(blscfg)
36121927 1140+{
f1c7b511
JP
1141+ grub_dprintf("blscfg", "%s got here\n", __func__);
1142+ cmd = grub_register_extcmd ("blscfg",
1143+ grub_cmd_blscfg,
36121927
ER
1144+ 0,
1145+ NULL,
1146+ N_("Import Boot Loader Specification snippets."),
1147+ NULL);
f1c7b511
JP
1148+ oldcmd = grub_register_extcmd ("bls_import",
1149+ grub_cmd_blscfg,
1150+ 0,
1151+ NULL,
1152+ N_("Import Boot Loader Specification snippets."),
1153+ NULL);
36121927
ER
1154+}
1155+
f1c7b511 1156+GRUB_MOD_FINI(blscfg)
36121927
ER
1157+{
1158+ grub_unregister_extcmd (cmd);
f1c7b511 1159+ grub_unregister_extcmd (oldcmd);
36121927 1160+}
f1c7b511
JP
1161diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
1162index db7a8f00273..891eac5a33f 100644
1163--- a/grub-core/commands/legacycfg.c
1164+++ b/grub-core/commands/legacycfg.c
1165@@ -133,7 +133,7 @@ legacy_file (const char *filename)
1166 args[0] = oldname;
1167 grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
1168 NULL, NULL,
1169- entrysrc, 0);
1170+ entrysrc, 0, NULL, NULL);
1171 grub_free (args);
1172 entrysrc[0] = 0;
1173 grub_free (oldname);
1174@@ -186,7 +186,8 @@ legacy_file (const char *filename)
1175 }
1176 args[0] = entryname;
1177 grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
1178- NULL, NULL, entrysrc, 0);
1179+ NULL, NULL, entrysrc, 0, NULL,
1180+ NULL);
1181 grub_free (args);
1182 }
1183
1184diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
1185index 3fd664aac33..163b9a09042 100644
1186--- a/grub-core/commands/loadenv.c
1187+++ b/grub-core/commands/loadenv.c
1188@@ -28,6 +28,8 @@
1189 #include <grub/extcmd.h>
1190 #include <grub/i18n.h>
1191
1192+#include "loadenv.h"
1193+
1194 GRUB_MOD_LICENSE ("GPLv3+");
1195
1196 static const struct grub_arg_option options[] =
1197@@ -79,81 +81,6 @@ open_envblk_file (char *filename,
1198 return file;
1199 }
1200
1201-static grub_envblk_t
1202-read_envblk_file (grub_file_t file)
1203-{
1204- grub_off_t offset = 0;
1205- char *buf;
1206- grub_size_t size = grub_file_size (file);
1207- grub_envblk_t envblk;
1208-
1209- buf = grub_malloc (size);
1210- if (! buf)
1211- return 0;
1212-
1213- while (size > 0)
1214- {
1215- grub_ssize_t ret;
1216-
1217- ret = grub_file_read (file, buf + offset, size);
1218- if (ret <= 0)
1219- {
1220- grub_free (buf);
1221- return 0;
1222- }
1223-
1224- size -= ret;
1225- offset += ret;
1226- }
1227-
1228- envblk = grub_envblk_open (buf, offset);
1229- if (! envblk)
1230- {
1231- grub_free (buf);
1232- grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
1233- return 0;
1234- }
1235-
1236- return envblk;
1237-}
1238-
1239-struct grub_env_whitelist
1240-{
1241- grub_size_t len;
1242- char **list;
1243-};
1244-typedef struct grub_env_whitelist grub_env_whitelist_t;
1245-
1246-static int
1247-test_whitelist_membership (const char* name,
1248- const grub_env_whitelist_t* whitelist)
1249-{
1250- grub_size_t i;
1251-
1252- for (i = 0; i < whitelist->len; i++)
1253- if (grub_strcmp (name, whitelist->list[i]) == 0)
1254- return 1; /* found it */
1255-
1256- return 0; /* not found */
1257-}
1258-
1259-/* Helper for grub_cmd_load_env. */
1260-static int
1261-set_var (const char *name, const char *value, void *whitelist)
1262-{
1263- if (! whitelist)
1264- {
1265- grub_env_set (name, value);
1266- return 0;
1267- }
1268-
1269- if (test_whitelist_membership (name,
1270- (const grub_env_whitelist_t *) whitelist))
1271- grub_env_set (name, value);
1272-
1273- return 0;
1274-}
1275-
1276 static grub_err_t
1277 grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
1278 {
1279diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
1280index 2c5363da7f5..9faf2be0f64 100644
1281--- a/grub-core/commands/menuentry.c
1282+++ b/grub-core/commands/menuentry.c
1283@@ -78,7 +78,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
1284 char **classes, const char *id,
1285 const char *users, const char *hotkey,
1286 const char *prefix, const char *sourcecode,
1287- int submenu)
1288+ int submenu, int *index, struct bls_entry *bls)
1289 {
1290 int menu_hotkey = 0;
1291 char **menu_args = NULL;
1292@@ -149,9 +149,12 @@ grub_normal_add_menu_entry (int argc, const char **args,
1293 if (! menu_title)
1294 goto fail;
1295
1296+ grub_dprintf ("menu", "id:\"%s\"\n", id);
1297+ grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
1298 menu_id = grub_strdup (id ? : menu_title);
1299 if (! menu_id)
1300 goto fail;
1301+ grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
1302
1303 /* Save argc, args to pass as parameters to block arg later. */
41468086 1304 menu_args = grub_calloc (argc + 1, sizeof (char *));
f1c7b511
JP
1305@@ -170,8 +173,12 @@ grub_normal_add_menu_entry (int argc, const char **args,
1306 }
1307
1308 /* Add the menu entry at the end of the list. */
1309+ int ind=0;
1310 while (*last)
1311- last = &(*last)->next;
1312+ {
1313+ ind++;
1314+ last = &(*last)->next;
1315+ }
1316
1317 *last = grub_zalloc (sizeof (**last));
1318 if (! *last)
1319@@ -188,8 +195,11 @@ grub_normal_add_menu_entry (int argc, const char **args,
1320 (*last)->args = menu_args;
1321 (*last)->sourcecode = menu_sourcecode;
1322 (*last)->submenu = submenu;
1323+ (*last)->bls = bls;
1324
1325 menu->size++;
1326+ if (index)
1327+ *index = ind;
1328 return GRUB_ERR_NONE;
1329
1330 fail:
1331@@ -286,7 +296,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
1332 users,
1333 ctxt->state[2].arg, 0,
1334 ctxt->state[3].arg,
1335- ctxt->extcmd->cmd->name[0] == 's');
1336+ ctxt->extcmd->cmd->name[0] == 's',
1337+ NULL, NULL);
1338
1339 src = args[argc - 1];
1340 args[argc - 1] = NULL;
1341@@ -303,7 +314,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
1342 ctxt->state[0].args, ctxt->state[4].arg,
1343 users,
1344 ctxt->state[2].arg, prefix, src + 1,
1345- ctxt->extcmd->cmd->name[0] == 's');
1346+ ctxt->extcmd->cmd->name[0] == 's', NULL,
1347+ NULL);
1348
1349 src[len - 1] = ch;
1350 args[argc - 1] = src;
1351diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
1352index 9ef98481f70..a326b192c89 100644
1353--- a/grub-core/normal/main.c
1354+++ b/grub-core/normal/main.c
1355@@ -20,6 +20,7 @@
41468086 1356 #include <grub/net.h>
f1c7b511
JP
1357 #include <grub/normal.h>
1358 #include <grub/dl.h>
1359+#include <grub/menu.h>
1360 #include <grub/misc.h>
1361 #include <grub/file.h>
1362 #include <grub/mm.h>
1363@@ -70,6 +71,11 @@ grub_normal_free_menu (grub_menu_t menu)
1364 grub_free (entry->args);
1365 }
1366
1367+ if (entry->bls)
1368+ {
1369+ entry->bls->visible = 0;
1370+ }
1371+
1372 grub_free ((void *) entry->id);
1373 grub_free ((void *) entry->users);
1374 grub_free ((void *) entry->title);
1375diff --git a/grub-core/commands/loadenv.h b/grub-core/commands/loadenv.h
1376new file mode 100644
1377index 00000000000..952f46121bd
1378--- /dev/null
1379+++ b/grub-core/commands/loadenv.h
1380@@ -0,0 +1,93 @@
1381+/* loadenv.c - command to load/save environment variable. */
1382+/*
1383+ * GRUB -- GRand Unified Bootloader
1384+ * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
1385+ *
1386+ * GRUB is free software: you can redistribute it and/or modify
1387+ * it under the terms of the GNU General Public License as published by
1388+ * the Free Software Foundation, either version 3 of the License, or
1389+ * (at your option) any later version.
1390+ *
1391+ * GRUB is distributed in the hope that it will be useful,
1392+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1393+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1394+ * GNU General Public License for more details.
1395+ *
1396+ * You should have received a copy of the GNU General Public License
1397+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
1398+ */
1399+
1400+static grub_envblk_t UNUSED
1401+read_envblk_file (grub_file_t file)
1402+{
1403+ grub_off_t offset = 0;
1404+ char *buf;
1405+ grub_size_t size = grub_file_size (file);
1406+ grub_envblk_t envblk;
1407+
1408+ buf = grub_malloc (size);
1409+ if (! buf)
1410+ return 0;
1411+
1412+ while (size > 0)
1413+ {
1414+ grub_ssize_t ret;
1415+
1416+ ret = grub_file_read (file, buf + offset, size);
1417+ if (ret <= 0)
1418+ {
1419+ grub_free (buf);
1420+ return 0;
1421+ }
1422+
1423+ size -= ret;
1424+ offset += ret;
1425+ }
1426+
1427+ envblk = grub_envblk_open (buf, offset);
1428+ if (! envblk)
1429+ {
1430+ grub_free (buf);
1431+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
1432+ return 0;
1433+ }
1434+
1435+ return envblk;
1436+}
1437+
1438+struct grub_env_whitelist
1439+{
1440+ grub_size_t len;
1441+ char **list;
1442+};
1443+typedef struct grub_env_whitelist grub_env_whitelist_t;
1444+
1445+static int UNUSED
1446+test_whitelist_membership (const char* name,
1447+ const grub_env_whitelist_t* whitelist)
1448+{
1449+ grub_size_t i;
1450+
1451+ for (i = 0; i < whitelist->len; i++)
1452+ if (grub_strcmp (name, whitelist->list[i]) == 0)
1453+ return 1; /* found it */
1454+
1455+ return 0; /* not found */
1456+}
1457+
1458+/* Helper for grub_cmd_load_env. */
1459+static int UNUSED
1460+set_var (const char *name, const char *value, void *whitelist)
1461+{
1462+ if (! whitelist)
1463+ {
1464+ grub_env_set (name, value);
1465+ return 0;
1466+ }
1467+
1468+ if (test_whitelist_membership (name,
1469+ (const grub_env_whitelist_t *) whitelist))
1470+ grub_env_set (name, value);
1471+
1472+ return 0;
1473+}
1474diff --git a/include/grub/compiler.h b/include/grub/compiler.h
1475index c9e1d7a73dc..9859ff4cc79 100644
1476--- a/include/grub/compiler.h
1477+++ b/include/grub/compiler.h
1478@@ -48,4 +48,6 @@
41468086 1479 # define CLANG_PREREQ(maj,min) 0
f1c7b511
JP
1480 #endif
1481
1482+#define UNUSED __attribute__((__unused__))
1483+
1484 #endif /* ! GRUB_COMPILER_HEADER */
1485diff --git a/include/grub/menu.h b/include/grub/menu.h
1486index ee2b5e91045..0acdc2aa6bf 100644
1487--- a/include/grub/menu.h
1488+++ b/include/grub/menu.h
1489@@ -20,6 +20,16 @@
1490 #ifndef GRUB_MENU_HEADER
1491 #define GRUB_MENU_HEADER 1
1492
1493+struct bls_entry
1494+{
1495+ struct bls_entry *next;
1496+ struct bls_entry *prev;
1497+ struct keyval **keyvals;
1498+ int nkeyvals;
1499+ char *filename;
1500+ int visible;
1501+};
1502+
1503 struct grub_menu_entry_class
1504 {
1505 char *name;
1506@@ -60,6 +70,9 @@ struct grub_menu_entry
1507
1508 /* The next element. */
1509 struct grub_menu_entry *next;
1510+
1511+ /* BLS used to populate the entry */
1512+ struct bls_entry *bls;
1513 };
1514 typedef struct grub_menu_entry *grub_menu_entry_t;
1515
1516diff --git a/include/grub/normal.h b/include/grub/normal.h
1517index 218cbabccaf..8839ad85a19 100644
1518--- a/include/grub/normal.h
1519+++ b/include/grub/normal.h
1520@@ -145,7 +145,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes,
1521 const char *id,
1522 const char *users, const char *hotkey,
1523 const char *prefix, const char *sourcecode,
1524- int submenu);
1525+ int submenu, int *index, struct bls_entry *bls);
1526
1527 grub_err_t
1528 grub_normal_set_password (const char *user, const char *password);
This page took 0.607562 seconds and 4 git commands to generate.