All of lore.kernel.org
 help / color / mirror / Atom feed
From: phcoder <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [PATCH] Preboot support
Date: Sun, 12 Apr 2009 19:19:07 +0200	[thread overview]
Message-ID: <49E2228B.7040600@gmail.com> (raw)
In-Reply-To: <49E0BAC7.2030503@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 634 bytes --]

What about this one?
phcoder wrote:
>> - Using an int value for the priority is quetionable. Very often, this 
>> style of priority system leads to chaos, because everyone picks up 
>> arbitrary numbers randomly. I prefer to define enums with a careful 
>> analysis.
> I will think about it. But the analysis is difficult because we don't 
> know in advance all the possible use cases of this feature
>>
>> Regards,
>> Okuji
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
> 
> 


-- 

Regards
Vladimir 'phcoder' Serbinenko

[-- Attachment #2: preboot.patch --]
[-- Type: text/x-diff, Size: 5118 bytes --]

diff --git a/ChangeLog b/ChangeLog
index 401a374..a6dd8f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-04-06  Vladimir Serbinenko <phcoder@gmail.com>
+
+	Preboot hooks support
+
+	* commands/boot.c (struct grub_preboot_t): new declaration
+	(preboots_head): new variable
+	(preboots_tail): likewise
+	(grub_loader_add_preboot): new function
+	(grub_loader_remove_preboot): likewise
+	(grub_loader_set): launch preboot hooks
+	* include/grub/loader.h (grub_loader_add_preboot): new declaration
+	(grub_loader_remove_preboot): likewise
+
 2009-03-22  Vladimir Serbinenko <phcoder@gmail.com>
 
 	Move loader out of the kernel
diff --git a/commands/boot.c b/commands/boot.c
index 1cc98eb..e47ae55 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -22,12 +22,24 @@
 #include <grub/misc.h>
 #include <grub/loader.h>
 #include <grub/kernel.h>
+#include <grub/mm.h>
 
 static grub_err_t (*grub_loader_boot_func) (void);
 static grub_err_t (*grub_loader_unload_func) (void);
 static int grub_loader_noreturn;
 
+struct grub_preboot_t
+{
+  grub_err_t (*preboot_func) (int);
+  grub_err_t (*preboot_rest_func) (void);
+  int prio;
+  struct grub_preboot_t *next;
+  struct grub_preboot_t *prev;
+};
+
 static int grub_loader_loaded;
+static struct grub_preboot_t *preboots_head = 0, 
+  *preboots_tail = 0;
 
 int
 grub_loader_is_loaded (void)
@@ -35,6 +47,68 @@ grub_loader_is_loaded (void)
   return grub_loader_loaded;
 }
 
+/* Register a preboot hook. */
+void *
+grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
+				   grub_err_t (*preboot_rest_func) (void),
+				   grub_loader_preboot_hook_prio_t prio)
+{
+  struct grub_preboot_t *cur, *new_preboot;
+
+  if (! preboot_func && ! preboot_rest_func)
+    return 0;
+
+  new_preboot = (struct grub_preboot_t *) 
+    grub_malloc (sizeof (struct grub_preboot_t));
+  if (! new_preboot)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
+      return 0;
+    }
+
+  new_preboot->preboot_func = preboot_func;
+  new_preboot->preboot_rest_func = preboot_rest_func;
+  new_preboot->prio = prio;
+
+  for (cur = preboots_head; cur && cur->prio > prio; cur = cur->next);
+
+  if (cur)
+    {
+      new_preboot->next = cur;
+      new_preboot->prev = cur->prev;
+      cur->prev = new_preboot;
+    }
+  else
+    {
+      new_preboot->next = 0;
+      new_preboot->prev = preboots_tail;
+      preboots_tail = new_preboot;
+    }
+  if (new_preboot->prev)
+    new_preboot->prev->next = new_preboot;
+  else
+    preboots_head = new_preboot;
+
+  return new_preboot;
+}
+
+void 
+grub_loader_remove_preboot (void *hnd)
+{
+  struct grub_preboot_t *preb = hnd;
+
+  if (preb->next)
+    preb->next->prev = preb->prev;
+  else
+    preboots_tail = preb->prev;
+  if (preb->prev)
+    preb->prev->next = preb->next;
+  else
+    preboots_head = preb->next;
+
+  grub_free (preb);
+}
+
 void
 grub_loader_set (grub_err_t (*boot) (void),
 		 grub_err_t (*unload) (void),
@@ -65,13 +139,32 @@ grub_loader_unset(void)
 grub_err_t
 grub_loader_boot (void)
 {
+  grub_err_t err = GRUB_ERR_NONE;
+  struct grub_preboot_t *cur;
+
   if (! grub_loader_loaded)
     return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
 
   if (grub_loader_noreturn)
     grub_machine_fini ();
+
+  for (cur = preboots_head; cur; cur = cur->next)
+    if (err = cur->preboot_func (grub_loader_noreturn))
+      {
+	for (cur = cur->prev; cur; cur = cur->prev)
+	  cur->preboot_rest_func ();
+	return err;
+      }
   
-  return (grub_loader_boot_func) ();
+  err = (grub_loader_boot_func) ();
+
+  for (cur = preboots_tail; cur; cur = cur->prev)
+    if (! err) 
+      err = cur->preboot_rest_func ();
+    else
+      cur->preboot_rest_func ();
+
+  return err;
 }
 
 /* boot */
diff --git a/include/grub/loader.h b/include/grub/loader.h
index 185d297..319f3c5 100644
--- a/include/grub/loader.h
+++ b/include/grub/loader.h
@@ -41,4 +41,26 @@ void grub_loader_unset (void);
    depending on the setting by grub_loader_set.  */
 grub_err_t grub_loader_boot (void);
 
+/* The space between numbers is intentional for the simplicity of adding new
+   values even if external modules use them. */
+typedef enum {
+  /* A preboot hook which can use everything and turns nothing off. */
+  GRUB_LOADER_PREBOOT_HOOK_PRIO_NORMAL = 400,
+  /* A preboot hook which can't use disks and may stop disks. */
+  GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK = 300,
+  /* A preboot hook which can't use disks or console and may stop console. */
+  GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE = 200,
+  /* A preboot hook which can't use disks or console, can't modify memory map
+     and may stop memory services or finalize memory map. */
+  GRUB_LOADER_PREBOOT_HOOK_PRIO_MEMORY = 100,
+} grub_loader_preboot_hook_prio_t;
+
+/* Register a preboot hook. */
+void *grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noret),
+					 grub_err_t (*preboot_rest_func) (void),
+					 grub_loader_preboot_hook_prio_t prio);
+
+/* Unregister given preboot hook. */
+void grub_loader_unregister_preboot_hook (void *hnd);
+
 #endif /* ! GRUB_LOADER_HEADER */

  reply	other threads:[~2009-04-12 17:19 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-10 23:48 [PATCH] Preboot support phcoder
2009-04-11 10:16 ` Yoshinori K. Okuji
2009-04-11 15:44   ` phcoder
2009-04-12 17:19     ` phcoder [this message]
2009-04-14 14:42       ` Yoshinori K. Okuji
2009-04-15  8:23         ` phcoder
2009-04-15  8:40           ` John Stanley
2009-04-26 14:38             ` Vladimir 'phcoder' Serbinenko
2009-04-27 16:49               ` Vladimir 'phcoder' Serbinenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49E2228B.7040600@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.