grub-devel
[Top][All Lists]
Advanced

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

[PATCH] Preboot support


From: phcoder
Subject: [PATCH] Preboot support
Date: Sat, 11 Apr 2009 01:48:07 +0200
User-agent: Thunderbird 2.0.0.21 (X11/20090318)

Hello, here is the preboot hooks support. Apply on top of my bootmove patch. They are very useful for patches like sendkey (my old patch that I'll rediff), badram, acpi (2 patches in separate threads) or drivemap
--

Regards
Vladimir 'phcoder' Serbinenko
diff --git a/ChangeLog b/ChangeLog
index a69e381..2b37e04 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-04-06  Vladimir Serbinenko <address@hidden>
+
+       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 <address@hidden>
 
        Move loader out of the kernel
diff --git a/commands/boot.c b/commands/boot.c
index 9a08fea..3eaf111 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -22,12 +22,25 @@
 #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 +48,69 @@ grub_loader_is_loaded (void)
   return grub_loader_loaded;
 }
 
+/*Add a preboot function*/
+void *
+grub_loader_add_preboot (grub_err_t (*preboot_func) (int noreturn),
+                        grub_err_t (*preboot_rest_func) (void),
+                        int 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 +141,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;
 }
 
 
diff --git a/include/grub/loader.h b/include/grub/loader.h
index 185d297..f701569 100644
--- a/include/grub/loader.h
+++ b/include/grub/loader.h
@@ -41,4 +41,12 @@ void grub_loader_unset (void);
    depending on the setting by grub_loader_set.  */
 grub_err_t grub_loader_boot (void);
 
+/* Add a preboot function */
+void *grub_loader_add_preboot (grub_err_t (*preboot_func) (int noreturn),
+                              grub_err_t (*preboot_rest_func) (void),
+                              int prio);
+
+/* Remove given preboot function */
+void grub_loader_remove_preboot (void *hnd);
+
 #endif /* ! GRUB_LOADER_HEADER */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]