Blob Blame History Raw
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Sun, 15 Sep 2019 09:37:45 +0200
Subject: [PATCH] blscfg: Add support for the devicetree field

The BootLoaderSpec mentions that a devicetree field can be used to pass a
Device Tree (DT) to the kernel, for the platforms that use it to describe
information about the hardware.

Allow the blscfg module to parse this field and call the grub2 devicetree
command in that case. If there is a devicetree grub2 environment variable
defined, this will be used if the field is not defined in the BLS snippet.

Resolves: rhbz#1751307

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
 grub-core/commands/blscfg.c | 60 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 57 insertions(+), 3 deletions(-)

diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index 54458b14518..1ec89870483 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -698,6 +698,8 @@ static void create_entry (struct bls_entry *entry)
   const char *early_initrd = NULL;
   char **early_initrds = NULL;
   char *initrd_prefix = NULL;
+  char *devicetree = NULL;
+  char *dt = NULL;
   char *id = entry->filename;
   char *dotconf = id;
   char *hotkey = NULL;
@@ -709,6 +711,7 @@ static void create_entry (struct bls_entry *entry)
 
   char *src = NULL;
   int i, index;
+  bool add_dt_prefix = false;
 
   grub_dprintf("blscfg", "%s got here\n", __func__);
   clinux = bls_get_val (entry, "linux", NULL);
@@ -736,6 +739,14 @@ static void create_entry (struct bls_entry *entry)
 
   initrds = bls_make_list (entry, "initrd", NULL);
 
+  devicetree = expand_val (bls_get_val (entry, "devicetree", NULL));
+
+  if (!devicetree)
+    {
+      devicetree = expand_val (grub_env_get("devicetree"));
+      add_dt_prefix = true;
+    }
+
   hotkey = bls_get_val (entry, "grub_hotkey", NULL);
   users = expand_val (bls_get_val (entry, "grub_users", NULL));
   classes = bls_make_list (entry, "grub_class", NULL);
@@ -801,7 +812,6 @@ static void create_entry (struct bls_entry *entry)
 	  goto finish;
 	}
 
-
       tmp = grub_stpcpy(initrd, "initrd");
       for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
 	{
@@ -821,21 +831,65 @@ static void create_entry (struct bls_entry *entry)
       tmp = grub_stpcpy (tmp, "\n");
     }
 
+  if (devicetree)
+    {
+      char *prefix = NULL;
+      int dt_size;
+
+      if (add_dt_prefix)
+	{
+	  prefix = grub_strrchr (clinux, '/');
+	  prefix = grub_strndup(clinux, prefix - clinux + 1);
+	  if (!prefix)
+	    {
+	      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+	      goto finish;
+	    }
+	}
+
+      dt_size = sizeof("devicetree " GRUB_BOOT_DEVICE) + grub_strlen(devicetree) + 1;
+
+      if (add_dt_prefix)
+	{
+	  dt_size += grub_strlen(prefix);
+	}
+
+      dt = grub_malloc (dt_size);
+      if (!dt)
+        {
+          grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+        goto finish;
+        }
+      char *tmp = dt;
+      tmp = grub_stpcpy (dt, "devicetree");
+      tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
+      if (add_dt_prefix)
+        tmp = grub_stpcpy (tmp, prefix);
+      tmp = grub_stpcpy (tmp, devicetree);
+      tmp = grub_stpcpy (tmp, "\n");
+
+      grub_free(prefix);
+    }
+
+  grub_dprintf ("blscfg2", "devicetree %s for id:\"%s\"\n", dt, id);
+
   src = grub_xasprintf ("load_video\n"
 			"set gfxpayload=keep\n"
 			"insmod gzio\n"
 			"linux %s%s%s%s\n"
-			"%s",
+			"%s%s",
 			GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
-			initrd ? initrd : "");
+			initrd ? initrd : "", dt ? dt : "");
 
   grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, &index, entry);
   grub_dprintf ("blscfg", "Added entry %d id:\"%s\"\n", index, id);
 
 finish:
+  grub_free (dt);
   grub_free (initrd);
   grub_free (initrd_prefix);
   grub_free (early_initrds);
+  grub_free (devicetree);
   grub_free (initrds);
   grub_free (options);
   grub_free (classes);