f4c76c0
From 4b0168249752a531ddedbdc3884bc675cd24033d Mon Sep 17 00:00:00 2001
f4c76c0
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
f4c76c0
Date: Tue, 22 Jan 2013 06:31:38 +0100
f4c76c0
Subject: [PATCH 13/74] blscfg: add blscfg module to parse Boot Loader
f4c76c0
 Specification snippets
f4c76c0
f4c76c0
http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec
f4c76c0
f4c76c0
Works like this:
f4c76c0
f4c76c0
 insmod blscfg
f4c76c0
 bls_import
f4c76c0
f4c76c0
Done! You should now have menu items for your snippets in place.
f4c76c0
f4c76c0
Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
f4c76c0
---
f4c76c0
 grub-core/Makefile.core.def |   8 ++
f4c76c0
 grub-core/commands/blscfg.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
f4c76c0
 2 files changed, 209 insertions(+)
f4c76c0
 create mode 100644 grub-core/commands/blscfg.c
f4c76c0
f4c76c0
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
f4c76c0
index a056b42..98b6485 100644
f4c76c0
--- a/grub-core/Makefile.core.def
f4c76c0
+++ b/grub-core/Makefile.core.def
f4c76c0
@@ -733,6 +733,14 @@ module = {
f4c76c0
 };
f4c76c0
 
f4c76c0
 module = {
f4c76c0
+  name = blscfg;
f4c76c0
+  common = commands/blscfg.c;
f4c76c0
+  enable = i386_efi;
f4c76c0
+  enable = x86_64_efi;
f4c76c0
+  enable = i386_pc;
f4c76c0
+};
f4c76c0
+
f4c76c0
+module = {
f4c76c0
   name = boot;
f4c76c0
   common = commands/boot.c;
f4c76c0
   i386_pc = lib/i386/pc/biosnum.c;
f4c76c0
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
f4c76c0
new file mode 100644
f4c76c0
index 0000000..4274aca
f4c76c0
--- /dev/null
f4c76c0
+++ b/grub-core/commands/blscfg.c
f4c76c0
@@ -0,0 +1,201 @@
f4c76c0
+/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
f4c76c0
+
f4c76c0
+/* bls.c - implementation of the boot loader spec */
f4c76c0
+
f4c76c0
+/*
f4c76c0
+ *  GRUB  --  GRand Unified Bootloader
f4c76c0
+ *
f4c76c0
+ *  GRUB is free software: you can redistribute it and/or modify
f4c76c0
+ *  it under the terms of the GNU General Public License as published by
f4c76c0
+ *  the Free Software Foundation, either version 3 of the License, or
f4c76c0
+ *  (at your option) any later version.
f4c76c0
+ *
f4c76c0
+ *  GRUB is distributed in the hope that it will be useful,
f4c76c0
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
f4c76c0
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f4c76c0
+ *  GNU General Public License for more details.
f4c76c0
+ *
f4c76c0
+ *  You should have received a copy of the GNU General Public License
f4c76c0
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
f4c76c0
+ */
f4c76c0
+
f4c76c0
+#include <grub/types.h>
f4c76c0
+#include <grub/misc.h>
f4c76c0
+#include <grub/mm.h>
f4c76c0
+#include <grub/err.h>
f4c76c0
+#include <grub/dl.h>
f4c76c0
+#include <grub/extcmd.h>
f4c76c0
+#include <grub/i18n.h>
f4c76c0
+#include <grub/fs.h>
f4c76c0
+#include <grub/env.h>
f4c76c0
+#include <grub/file.h>
f4c76c0
+#include <grub/normal.h>
f4c76c0
+
f4c76c0
+GRUB_MOD_LICENSE ("GPLv3+");
f4c76c0
+
f4c76c0
+#ifdef GRUB_MACHINE_EFI
f4c76c0
+#define GRUB_LINUX_CMD "linuxefi"
f4c76c0
+#define GRUB_INITRD_CMD "initrdefi"
f4c76c0
+#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/"
f4c76c0
+#define GRUB_BOOT_DEVICE "($boot)"
f4c76c0
+#else
f4c76c0
+#define GRUB_LINUX_CMD "linux"
f4c76c0
+#define GRUB_INITRD_CMD "initrd"
f4c76c0
+#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
f4c76c0
+#define GRUB_BOOT_DEVICE "($root)"
f4c76c0
+#endif
f4c76c0
+
f4c76c0
+static int parse_entry (
f4c76c0
+    const char *filename,
f4c76c0
+    const struct grub_dirhook_info *info __attribute__ ((unused)),
f4c76c0
+    void *data __attribute__ ((unused)))
f4c76c0
+{
f4c76c0
+  grub_size_t n;
f4c76c0
+  char *p;
f4c76c0
+  grub_file_t f = NULL;
f4c76c0
+  grub_off_t sz;
f4c76c0
+  char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL;
f4c76c0
+  const char *args[2] = { NULL, NULL };
f4c76c0
+
f4c76c0
+  if (filename[0] == '.')
f4c76c0
+    return 0;
f4c76c0
+
f4c76c0
+  n = grub_strlen (filename);
f4c76c0
+  if (n <= 5)
f4c76c0
+    return 0;
f4c76c0
+
f4c76c0
+  if (grub_strcmp (filename + n - 5, ".conf") != 0)
f4c76c0
+    return 0;
f4c76c0
+
f4c76c0
+  p = grub_xasprintf (GRUB_BLS_CONFIG_PATH "%s", filename);
f4c76c0
+
f4c76c0
+  f = grub_file_open (p);
f4c76c0
+  if (!f)
f4c76c0
+    goto finish;
f4c76c0
+
f4c76c0
+  sz = grub_file_size (f);
f4c76c0
+  if (sz == GRUB_FILE_SIZE_UNKNOWN || sz > 1024*1024)
f4c76c0
+    goto finish;
f4c76c0
+
f4c76c0
+  for (;;)
f4c76c0
+    {
f4c76c0
+      char *buf;
f4c76c0
+
f4c76c0
+      buf = grub_file_getline (f);
f4c76c0
+      if (!buf)
f4c76c0
+	break;
f4c76c0
+
f4c76c0
+      if (grub_strncmp (buf, "title ", 6) == 0)
f4c76c0
+	{
f4c76c0
+	  grub_free (title);
f4c76c0
+	  title = grub_strdup (buf + 6);
f4c76c0
+	  if (!title)
f4c76c0
+	    goto finish;
f4c76c0
+	}
f4c76c0
+      else if (grub_strncmp (buf, "options ", 8) == 0)
f4c76c0
+	{
f4c76c0
+	  grub_free (options);
f4c76c0
+	  options = grub_strdup (buf + 8);
f4c76c0
+	  if (!options)
f4c76c0
+	    goto finish;
f4c76c0
+	}
f4c76c0
+      else if (grub_strncmp (buf, "linux ", 6) == 0)
f4c76c0
+	{
f4c76c0
+	  grub_free (clinux);
f4c76c0
+	  clinux = grub_strdup (buf + 6);
f4c76c0
+	  if (!clinux)
f4c76c0
+	    goto finish;
f4c76c0
+	}
f4c76c0
+      else if (grub_strncmp (buf, "initrd ", 7) == 0)
f4c76c0
+	{
f4c76c0
+	  grub_free (initrd);
f4c76c0
+	  initrd = grub_strdup (buf + 7);
f4c76c0
+	  if (!initrd)
f4c76c0
+	    goto finish;
f4c76c0
+	}
f4c76c0
+
f4c76c0
+      grub_free(buf);
f4c76c0
+    }
f4c76c0
+
f4c76c0
+  if (!linux)
f4c76c0
+    {
f4c76c0
+      grub_printf ("Skipping file %s with no 'linux' key.", p);
f4c76c0
+      goto finish;
f4c76c0
+    }
f4c76c0
+
f4c76c0
+  args[0] = title ? title : filename;
f4c76c0
+
f4c76c0
+  src = grub_xasprintf ("load_video\n"
f4c76c0
+			"set gfx_payload=keep\n"
f4c76c0
+			"insmod gzio\n"
f4c76c0
+			GRUB_LINUX_CMD " %s%s%s%s\n"
f4c76c0
+			"%s%s%s%s",
f4c76c0
+			GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
f4c76c0
+			initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE : "", initrd ? initrd : "", initrd ? "\n" : "");
f4c76c0
+
f4c76c0
+  grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0);
f4c76c0
+
f4c76c0
+finish:
f4c76c0
+  grub_free (p);
f4c76c0
+  grub_free (title);
f4c76c0
+  grub_free (options);
f4c76c0
+  grub_free (clinux);
f4c76c0
+  grub_free (initrd);
f4c76c0
+  grub_free (src);
f4c76c0
+
f4c76c0
+  if (f)
f4c76c0
+    grub_file_close (f);
f4c76c0
+
f4c76c0
+  return 0;
f4c76c0
+}
f4c76c0
+
f4c76c0
+static grub_err_t
f4c76c0
+grub_cmd_bls_import (grub_extcmd_context_t ctxt __attribute__ ((unused)),
f4c76c0
+		     int argc __attribute__ ((unused)),
f4c76c0
+		     char **args __attribute__ ((unused)))
f4c76c0
+{
f4c76c0
+  grub_fs_t fs;
f4c76c0
+  grub_device_t dev;
f4c76c0
+  static grub_err_t r;
f4c76c0
+  const char *devid;
f4c76c0
+
f4c76c0
+  devid = grub_env_get ("root");
f4c76c0
+  if (!devid)
f4c76c0
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "root");
f4c76c0
+
f4c76c0
+  dev = grub_device_open (devid);
f4c76c0
+  if (!dev)
f4c76c0
+    return grub_errno;
f4c76c0
+
f4c76c0
+  fs = grub_fs_probe (dev);
f4c76c0
+  if (!fs)
f4c76c0
+    {
f4c76c0
+      r = grub_errno;
f4c76c0
+      goto finish;
f4c76c0
+    }
f4c76c0
+
f4c76c0
+  r = fs->dir (dev, GRUB_BLS_CONFIG_PATH, parse_entry, NULL);
f4c76c0
+
f4c76c0
+finish:
f4c76c0
+  if (dev)
f4c76c0
+    grub_device_close (dev);
f4c76c0
+
f4c76c0
+  return r;
f4c76c0
+}
f4c76c0
+
f4c76c0
+static grub_extcmd_t cmd;
f4c76c0
+
f4c76c0
+GRUB_MOD_INIT(bls)
f4c76c0
+{
f4c76c0
+  cmd = grub_register_extcmd ("bls_import",
f4c76c0
+			      grub_cmd_bls_import,
f4c76c0
+			      0,
f4c76c0
+			      NULL,
f4c76c0
+			      N_("Import Boot Loader Specification snippets."),
f4c76c0
+			      NULL);
f4c76c0
+}
f4c76c0
+
f4c76c0
+GRUB_MOD_FINI(bls)
f4c76c0
+{
f4c76c0
+  grub_unregister_extcmd (cmd);
f4c76c0
+}
f4c76c0
-- 
f4c76c0
2.4.3
f4c76c0