[ostree/wip/grub2] WIP: grub2 support



commit d7903e11eb1d02a159d4c109c610abac8989370b
Author: Colin Walters <walters verbum org>
Date:   Sat Oct 11 08:59:06 2014 -0400

    WIP: grub2 support
    
    Very, very hacky...

 Makefile-libostree.am                   |    2 +
 src/libostree/ostree-bootloader-grub2.c |  257 +++++++++++++++++++++++++++++++
 src/libostree/ostree-bootloader-grub2.h |   38 +++++
 src/libostree/ostree-sysroot.c          |    6 +
 4 files changed, 303 insertions(+), 0 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index fbe173d..0a67ea7 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -74,6 +74,8 @@ libostree_1_la_SOURCES = \
        src/libostree/ostree-deployment.c \
        src/libostree/ostree-bootloader.h \
        src/libostree/ostree-bootloader.c \
+       src/libostree/ostree-bootloader-grub2.h \
+       src/libostree/ostree-bootloader-grub2.c \
        src/libostree/ostree-bootloader-syslinux.h \
        src/libostree/ostree-bootloader-syslinux.c \
        src/libostree/ostree-bootloader-uboot.h \
diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c
new file mode 100644
index 0000000..621db5e
--- /dev/null
+++ b/src/libostree/ostree-bootloader-grub2.c
@@ -0,0 +1,257 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters verbum org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ostree-sysroot-private.h"
+#include "ostree-bootloader-grub2.h"
+#include "otutil.h"
+#include <gio/gfiledescriptorbased.h>
+#include "libgsystem.h"
+
+#include <string.h>
+
+#define GRUB2_CONFIG_PATH "boot/grub2/grub.cfg"
+#define OSTREE_GRUB2_CONFIG_PATH "etc/grub.d/15_ostree"
+
+struct _OstreeBootloaderGrub2
+{
+  GObject       parent_instance;
+
+  OstreeSysroot  *sysroot;
+  GFile          *config_path;
+};
+
+typedef GObjectClass OstreeBootloaderGrub2Class;
+
+static void _ostree_bootloader_grub2_bootloader_iface_init (OstreeBootloaderInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderGrub2, _ostree_bootloader_grub2, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, 
_ostree_bootloader_grub2_bootloader_iface_init));
+
+static gboolean
+_ostree_bootloader_grub2_query (OstreeBootloader *bootloader)
+{
+  OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
+
+  return g_file_query_exists (self->config_path, NULL);
+}
+
+static const char *
+_ostree_bootloader_grub2_get_name (OstreeBootloader *bootloader)
+{
+  return "grub2";
+}
+
+static gboolean
+_ostree_bootloader_grub2_write_config (OstreeBootloader      *bootloader,
+                                       int                    bootversion,
+                                       GCancellable          *cancellable,
+                                       GError               **error)
+{
+  gboolean ret = FALSE;
+  OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
+  gs_unref_object GFile *subconfdir = NULL;
+  gs_unref_object GFile *tmp_subconf_path = NULL;
+  gs_unref_object GFile *ostree_subconf_path = NULL;
+  gs_unref_object GOutputStream *out_stream = NULL;
+  gs_unref_object GDataOutputStream *dataout = NULL;
+  gs_unref_ptrarray GPtrArray *loader_configs = NULL;
+  guint i;
+  int fd;
+  gs_free char *kernel_arg = NULL;
+  static const char prelude[] = "#!/bin/sh\n"
+    ". /usr/share/grub/grub-mkconfig_lib\n"
+    "boot_device_id=\"$(grub_get_device_id \"${GRUB_DEVICE}\")\"\n"
+    "prepare_root_cache=\"$(prepare_grub_to_access_device \"${GRUB_DEVICE_BOOT}\")\"\n"
+    "cat << EOF\n";
+  /* So... yeah.  Just going to hardcode these. */
+  static const char hardcoded_video[] = "load_video\n"
+    "set gfxpayload=keep\n";
+  static const char hardcoded_insmods[] = "insmod gzio\n"
+    "insmod part_msdos\n"
+    "insmod xfs\n";
+
+  ostree_subconf_path = g_file_resolve_relative_path (self->sysroot->path, OSTREE_GRUB2_CONFIG_PATH);
+  subconfdir = g_file_get_parent (ostree_subconf_path);
+
+  if (!gs_file_open_in_tmpdir (subconfdir, 0755, &tmp_subconf_path, &out_stream,
+                               cancellable, error))
+    goto out;
+  
+  dataout = g_data_output_stream_new (out_stream);
+
+  fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (out_stream));
+
+  if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion,
+                                                 &loader_configs,
+                                                 cancellable, error))
+    goto out;
+
+  if (!g_data_output_stream_put_string (dataout, prelude, cancellable, error))
+    goto out;
+
+  for (i = 0; i < loader_configs->len; i++)
+    {
+      OstreeBootconfigParser *config = loader_configs->pdata[i];
+      const char *title;
+      const char *options;
+      const char *kernel;
+      const char *initrd;
+      char *line = NULL;
+      char *quoted_title = NULL;
+      char *uuid = NULL;
+      char *quoted_uuid = NULL;
+
+      title = ostree_bootconfig_parser_get (config, "title");
+      if (!title)
+        title = "(Untitled)";
+
+      kernel = ostree_bootconfig_parser_get (config, "linux");
+
+      quoted_title = g_shell_quote (title);
+      uuid = g_strdup_printf ("ostree-%u-${boot_device_id}", (guint)i);
+      quoted_uuid = g_shell_quote (uuid);
+      line = g_strdup_printf ("menuentry %s --class gnu-linux --class gnu --class os --unrestricted %s {\n", 
quoted_title, quoted_uuid);
+      g_free (quoted_title);
+      g_free (quoted_uuid);
+
+      if (!g_data_output_stream_put_string (dataout, line, cancellable, error))
+        goto out;
+
+      /* Hardcoded sections */
+      if (!g_data_output_stream_put_string (dataout, hardcoded_video, cancellable, error))
+        goto out;
+      if (!g_data_output_stream_put_string (dataout, hardcoded_insmods, cancellable, error))
+        goto out;
+      if (!g_data_output_stream_put_string (dataout, "${prepare_root_cache}\n", cancellable, error))
+        goto out;
+      
+      if (!kernel)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "No \"linux\" key in bootloader config");
+          goto out;
+        }
+      if (!g_data_output_stream_put_string (dataout, "linux16 ", cancellable, error))
+        goto out;
+      if (!g_data_output_stream_put_string (dataout, kernel, cancellable, error))
+        goto out;
+
+      options = ostree_bootconfig_parser_get (config, "options ");
+      if (options)
+        {
+          if (!g_data_output_stream_put_string (dataout, options, cancellable, error))
+            goto out;
+        }
+      if (!g_data_output_stream_put_byte (dataout, '\n', cancellable, error))
+        goto out;
+
+      initrd = ostree_bootconfig_parser_get (config, "initrd");
+      if (initrd)
+        {
+          if (!g_data_output_stream_put_string (dataout, "initrd16 ", cancellable, error))
+            goto out;
+          if (!g_data_output_stream_put_string (dataout, initrd, cancellable, error))
+            goto out;
+          if (!g_data_output_stream_put_byte (dataout, '\n', cancellable, error))
+            goto out;
+        }
+
+      if (!g_data_output_stream_put_string (dataout, "}\n", cancellable, error))
+        goto out;
+    }
+
+  if (!g_data_output_stream_put_string (dataout, "EOF\n", cancellable, error))
+    goto out;
+
+  if (!g_output_stream_flush ((GOutputStream*)dataout, cancellable, error))
+    goto out;
+
+  if (fsync (fd) != 0)
+    {
+      ot_util_set_error_from_errno (error, errno);
+      goto out;
+    }
+
+  if (!g_output_stream_close ((GOutputStream*)dataout, cancellable, error))
+    goto out;
+
+  if (!gs_file_rename (tmp_subconf_path, ostree_subconf_path, cancellable, error))
+    goto out;
+
+  /* From what I can see, this script doesn't even try to be atomic;
+     it just does:
+
+cat ${grub_cfg}.new > ${grub_cfg}
+rm -f ${grub_cfg}.new
+
+    Ugh.  Well, we'll dive into this later...
+  */
+  if (!gs_subprocess_simple_run_sync (NULL,
+                                      GS_SUBPROCESS_STREAM_DISPOSITION_NULL,
+                                      cancellable, error,
+                                      "grub2-mkconfig", "-o", gs_file_get_path_cached (self->config_path), 
NULL))
+    goto out;
+  
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+static void
+_ostree_bootloader_grub2_finalize (GObject *object)
+{
+  OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (object);
+
+  g_clear_object (&self->sysroot);
+  g_clear_object (&self->config_path);
+
+  G_OBJECT_CLASS (_ostree_bootloader_grub2_parent_class)->finalize (object);
+}
+
+void
+_ostree_bootloader_grub2_init (OstreeBootloaderGrub2 *self)
+{
+}
+
+static void
+_ostree_bootloader_grub2_bootloader_iface_init (OstreeBootloaderInterface *iface)
+{
+  iface->query = _ostree_bootloader_grub2_query;
+  iface->get_name = _ostree_bootloader_grub2_get_name;
+  iface->write_config = _ostree_bootloader_grub2_write_config;
+}
+
+void
+_ostree_bootloader_grub2_class_init (OstreeBootloaderGrub2Class *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = _ostree_bootloader_grub2_finalize;
+}
+
+OstreeBootloaderGrub2 *
+_ostree_bootloader_grub2_new (OstreeSysroot *sysroot)
+{
+  OstreeBootloaderGrub2 *self = g_object_new (OSTREE_TYPE_BOOTLOADER_GRUB2, NULL);
+  self->sysroot = g_object_ref (sysroot);
+  self->config_path = g_file_resolve_relative_path (self->sysroot->path, GRUB2_CONFIG_PATH);
+  return self;
+}
diff --git a/src/libostree/ostree-bootloader-grub2.h b/src/libostree/ostree-bootloader-grub2.h
new file mode 100644
index 0000000..5cbfba6
--- /dev/null
+++ b/src/libostree/ostree-bootloader-grub2.h
@@ -0,0 +1,38 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2014 Colin Walters <walters verbum org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include "ostree-bootloader.h"
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_BOOTLOADER_GRUB2 (_ostree_bootloader_grub2_get_type ())
+#define OSTREE_BOOTLOADER_GRUB2(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_BOOTLOADER_GRUB2, 
OstreeBootloaderGrub2))
+#define OSTREE_IS_BOOTLOADER_GRUB2(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_BOOTLOADER_GRUB2))
+
+typedef struct _OstreeBootloaderGrub2 OstreeBootloaderGrub2;
+
+GType _ostree_bootloader_grub2_get_type (void) G_GNUC_CONST;
+
+OstreeBootloaderGrub2 * _ostree_bootloader_grub2_new (OstreeSysroot *sysroot);
+
+G_END_DECLS
+
diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c
index c88c6d4..160fc07 100644
--- a/src/libostree/ostree-sysroot.c
+++ b/src/libostree/ostree-sysroot.c
@@ -26,6 +26,7 @@
 #include "ostree-sysroot-private.h"
 #include "ostree-bootloader-uboot.h"
 #include "ostree-bootloader-syslinux.h"
+#include "ostree-bootloader-grub2.h"
 
 static gboolean
 find_booted_deployment (OstreeSysroot       *self,
@@ -853,11 +854,16 @@ _ostree_sysroot_query_bootloader (OstreeSysroot *self)
 {
   OstreeBootloaderSyslinux *syslinux;
   OstreeBootloaderUboot    *uboot;
+  OstreeBootloaderGrub2    *grub2;
 
   syslinux = _ostree_bootloader_syslinux_new (self);
   if (_ostree_bootloader_query ((OstreeBootloader*)syslinux))
     return (OstreeBootloader*) (syslinux);
 
+  grub2 = _ostree_bootloader_grub2_new (self);
+  if (_ostree_bootloader_query ((OstreeBootloader*)grub2))
+    return (OstreeBootloader*) (grub2);
+
   uboot = _ostree_bootloader_uboot_new (self);
   if (_ostree_bootloader_query ((OstreeBootloader*)uboot))
     return (OstreeBootloader*) (uboot);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]