* [PATCH] Preboot support
@ 2009-04-10 23:48 phcoder
2009-04-11 10:16 ` Yoshinori K. Okuji
0 siblings, 1 reply; 9+ messages in thread
From: phcoder @ 2009-04-10 23:48 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 258 bytes --]
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
[-- Attachment #2: preboot.patch --]
[-- Type: text/x-diff, Size: 4301 bytes --]
diff --git a/ChangeLog b/ChangeLog
index a69e381..2b37e04 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 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 */
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] Preboot support
2009-04-10 23:48 [PATCH] Preboot support phcoder
@ 2009-04-11 10:16 ` Yoshinori K. Okuji
2009-04-11 15:44 ` phcoder
0 siblings, 1 reply; 9+ messages in thread
From: Yoshinori K. Okuji @ 2009-04-11 10:16 UTC (permalink / raw)
To: The development of GRUB 2
On Saturday 11 April 2009 08:48:07 phcoder wrote:
> 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
Some comments about the design.
- register/unregister is more appropriate than add/remove.
- preboot is ambigous. preboot_hook is better.
- 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.
Regards,
Okuji
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Preboot support
2009-04-11 10:16 ` Yoshinori K. Okuji
@ 2009-04-11 15:44 ` phcoder
2009-04-12 17:19 ` phcoder
0 siblings, 1 reply; 9+ messages in thread
From: phcoder @ 2009-04-11 15:44 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 575 bytes --]
> - 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: 4336 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..ef4913b 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),
+ 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 +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..72d1894 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);
+/* Register a preboot hook. */
+void *grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noret),
+ grub_err_t (*preboot_rest_func) (void),
+ int prio);
+
+/* Unregister given preboot hook. */
+void grub_loader_unregister_preboot_hook (void *hnd);
+
#endif /* ! GRUB_LOADER_HEADER */
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] Preboot support
2009-04-11 15:44 ` phcoder
@ 2009-04-12 17:19 ` phcoder
2009-04-14 14:42 ` Yoshinori K. Okuji
0 siblings, 1 reply; 9+ messages in thread
From: phcoder @ 2009-04-12 17:19 UTC (permalink / raw)
To: The development of GRUB 2
[-- 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 */
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] Preboot support
2009-04-12 17:19 ` phcoder
@ 2009-04-14 14:42 ` Yoshinori K. Okuji
2009-04-15 8:23 ` phcoder
0 siblings, 1 reply; 9+ messages in thread
From: Yoshinori K. Okuji @ 2009-04-14 14:42 UTC (permalink / raw)
To: The development of GRUB 2
On Monday 13 April 2009 02:19:07 phcoder wrote:
> What about this one?
- ChangeLog, loader.h and loader.c are not consistent. For example, loader.h
declares grub_loader_unregister_preboot_hook, but loader.c defines
grub_loader_remove_preboot.
- I don't understand how preboot_func and preboot_rest_func are different. At
least, not obvious. Can you elaborate on them?
- This part:
+
+ 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;
+ }
You should not set ERR inside the "if" clause. This is against the GNU Coding
Standards. The main reason is that it is not friendly to debuggers (as you
may not "step" between the assignment and the conditional jump).
Regards,
Okuji
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH] Preboot support
2009-04-14 14:42 ` Yoshinori K. Okuji
@ 2009-04-15 8:23 ` phcoder
2009-04-15 8:40 ` John Stanley
0 siblings, 1 reply; 9+ messages in thread
From: phcoder @ 2009-04-15 8:23 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 538 bytes --]
Yoshinori K. Okuji wrote:
> - I don't understand how preboot_func and preboot_rest_func are different. At
> least, not obvious. Can you elaborate on them?
preboot_rest_func is a function which should undo any action taken by
preboot_func. It's used if either loader aborts due to an error or
returns (which is possible on some platforms)
>
> _______________________________________________
> 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-patch, Size: 5192 bytes --]
diff --git a/ChangeLog b/ChangeLog
index dd28915..1b2bbda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+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_register_preboot_hook): new function
+ (grub_loader_unregister_preboot_hook): likewise
+ (grub_loader_set): launch preboot hooks
+ * include/grub/loader.h (grub_loader_register_preboot_hook):
+ new declaration
+ (grub_loader_unregister_preboot_hook): 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..b417798 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_unregister_preboot_hook (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,34 @@ 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 ();
-
- return (grub_loader_boot_func) ();
+
+ for (cur = preboots_head; cur; cur = cur->next)
+ {
+ err = cur->preboot_func (grub_loader_noreturn);
+ if (err)
+ {
+ for (cur = cur->prev; cur; cur = cur->prev)
+ cur->preboot_rest_func ();
+ return err;
+ }
+ }
+ 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 */
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] Preboot support
2009-04-15 8:23 ` phcoder
@ 2009-04-15 8:40 ` John Stanley
2009-04-26 14:38 ` Vladimir 'phcoder' Serbinenko
0 siblings, 1 reply; 9+ messages in thread
From: John Stanley @ 2009-04-15 8:40 UTC (permalink / raw)
To: The development of GRUB 2
The way it looks to me is that preboot_func is the function to be
executed a preboot time, whereas preboot_rest_func is a cleanup
function to be called to "restore" things to the pre-preboot_func state.
Something like this anyway.. its not yet real clear to me either.
phcoder wrote:
> Yoshinori K. Okuji wrote:
>
>> - I don't understand how preboot_func and preboot_rest_func are
>> different. At least, not obvious. Can you elaborate on them?
> preboot_rest_func is a function which should undo any action taken by
> preboot_func. It's used if either loader aborts due to an error or
> returns (which is possible on some platforms)
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Preboot support
2009-04-15 8:40 ` John Stanley
@ 2009-04-26 14:38 ` Vladimir 'phcoder' Serbinenko
2009-04-27 16:49 ` Vladimir 'phcoder' Serbinenko
0 siblings, 1 reply; 9+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-04-26 14:38 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1.1: Type: text/plain, Size: 1414 bytes --]
Warning fixed in the patch. If nobody objects I commit it tomorrow
On Wed, Apr 15, 2009 at 10:40 AM, John Stanley <jpsinthemix@verizon.net>wrote:
> The way it looks to me is that preboot_func is the function to be executed
> a preboot time, whereas preboot_rest_func is a cleanup function to be
> called to "restore" things to the pre-preboot_func state. Something like
> this anyway.. its not yet real clear to me either.
>
> phcoder wrote:
>
>> Yoshinori K. Okuji wrote:
>>
>> - I don't understand how preboot_func and preboot_rest_func are
>>> different. At least, not obvious. Can you elaborate on them?
>>>
>> preboot_rest_func is a function which should undo any action taken by
>> preboot_func. It's used if either loader aborts due to an error or returns
>> (which is possible on some platforms)
>>
>>>
>>> _______________________________________________
>>> Grub-devel mailing list
>>> Grub-devel@gnu.org
>>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
--
Regards
Vladimir 'phcoder' Serbinenko
[-- Attachment #1.2: Type: text/html, Size: 2714 bytes --]
[-- Attachment #2: preboot.patch --]
[-- Type: text/x-diff, Size: 5268 bytes --]
diff --git a/ChangeLog b/ChangeLog
index e5b3086..2f2afc2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2009-04-26 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_register_preboot_hook): new function
+ (grub_loader_unregister_preboot_hook): likewise
+ (grub_loader_set): launch preboot hooks
+ * include/grub/loader.h (grub_loader_register_preboot_hook):
+ new declaration
+ (grub_loader_unregister_preboot_hook): likewise
+
2009-04-26 David S. Miller <davem@davemloft.net>
* util/grub-mkdevicemap.c (make_device_map): Add missing
diff --git a/commands/boot.c b/commands/boot.c
index 9a08fea..c8bd030 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);
+ grub_loader_preboot_hook_prio_t 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_unregister_preboot_hook (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,15 +139,35 @@ 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 ();
-
- return (grub_loader_boot_func) ();
-}
+ for (cur = preboots_head; cur; cur = cur->next)
+ {
+ err = cur->preboot_func (grub_loader_noreturn);
+ if (err)
+ {
+ for (cur = cur->prev; cur; cur = cur->prev)
+ cur->preboot_rest_func ();
+ return err;
+ }
+ }
+ 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 */
static grub_err_t
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 */
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] Preboot support
2009-04-26 14:38 ` Vladimir 'phcoder' Serbinenko
@ 2009-04-27 16:49 ` Vladimir 'phcoder' Serbinenko
0 siblings, 0 replies; 9+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2009-04-27 16:49 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1617 bytes --]
Commited
On Sun, Apr 26, 2009 at 4:38 PM, Vladimir 'phcoder' Serbinenko <
phcoder@gmail.com> wrote:
> Warning fixed in the patch. If nobody objects I commit it tomorrow
>
>
> On Wed, Apr 15, 2009 at 10:40 AM, John Stanley <jpsinthemix@verizon.net>wrote:
>
>> The way it looks to me is that preboot_func is the function to be executed
>> a preboot time, whereas preboot_rest_func is a cleanup function to be
>> called to "restore" things to the pre-preboot_func state. Something like
>> this anyway.. its not yet real clear to me either.
>>
>> phcoder wrote:
>>
>>> Yoshinori K. Okuji wrote:
>>>
>>> - I don't understand how preboot_func and preboot_rest_func are
>>>> different. At least, not obvious. Can you elaborate on them?
>>>>
>>> preboot_rest_func is a function which should undo any action taken by
>>> preboot_func. It's used if either loader aborts due to an error or returns
>>> (which is possible on some platforms)
>>>
>>>>
>>>> _______________________________________________
>>>> Grub-devel mailing list
>>>> Grub-devel@gnu.org
>>>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>>>
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> _______________________________________________
>>> Grub-devel mailing list
>>> Grub-devel@gnu.org
>>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>>
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
>
> --
> Regards
> Vladimir 'phcoder' Serbinenko
>
--
Regards
Vladimir 'phcoder' Serbinenko
[-- Attachment #2: Type: text/html, Size: 3219 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-04-27 16:49 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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
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.