Javier Martín wrote: > But you negate any performance gain when you _do_ traverse the list to > add an entry to it instead of just make it the new head as I do. > Besides, even for that, double indirection should be avoided in the > structure previous pointer because it makes things oh-so-incredibly > confusing. I was thinking about code size then about performance or easy of understanding. On my system this code results in 91 addition bytes in core image (63 if I remove grub_error). Do you have any idea how it would be possible to do an error message without description or put some generic description? > > Besides, I think the "user" (i.e. module) visible type returned by _add > and taken by _remove should be a "blank hidden type", i.e. you don't > need to declare "struct grub_preboot_t" in loader.h because the public > interface only uses _pointers_ to it, whose size is known. This is all > the C compiler requires and you avoid polluting the namespace with > internal implementation details. I recommend the following typedefs: > > typedef struct grub_preboot_t* grub_preboot_hnd; > typedef grub_err_t *(grub_preboot_func)(int noreturn); > > So that the prototypes would look > > grub_preboot_hnd add(grub_preboot_func f); > void remove(grub_preboot_hnd handle); I noticed that actually no code needs the size of grub_preoot_hnd. So I changed it to void * Vladimir Serbinenko
Index: kern/loader.c =================================================================== --- kern/loader.c (revision 1845) +++ kern/loader.c (working copy) @@ -22,12 +22,54 @@ #include <grub/err.h> #include <grub/kernel.h> +#define PREBOOT_HND(x) (((struct grub_preboot_t *)x)) + +struct grub_preboot_t +{ + grub_err_t (*preboot_func) (int); + struct grub_preboot_t *next; + struct grub_preboot_t **prev_pointer; +}; + static grub_err_t (*grub_loader_boot_func) (void); static grub_err_t (*grub_loader_unload_func) (void); static int grub_loader_noreturn; static int grub_loader_loaded; +static struct grub_preboot_t *grub_loader_preboots=0; + +void * +grub_loader_add_preboot (grub_err_t (*preboot_func) (int)) +{ + struct grub_preboot_t *cur; + if (!preboot_func) + return 0; + cur=(struct grub_preboot_t *)grub_malloc (sizeof (struct grub_preboot_t)); + if (!cur) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added"); + return 0; + } + cur->next=grub_loader_preboots; + cur->prev_pointer=0; + cur->next->prev_pointer=&(cur->next); + cur->preboot_func=preboot_func; + grub_loader_preboots=cur; + return cur; +} + +void +grub_loader_remove_preboot (void *p) +{ + if (!p) + return; + *(PREBOOT_HND(p)->prev_pointer)=PREBOOT_HND(p)->next; + if (PREBOOT_HND(p)->next) + PREBOOT_HND(p)->next->prev_pointer=PREBOOT_HND(p)->prev_pointer; + grub_free (p); +} + int grub_loader_is_loaded (void) { @@ -64,12 +106,18 @@ grub_err_t grub_loader_boot (void) { + struct grub_preboot_t *iter=grub_loader_preboots; if (! grub_loader_loaded) return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel"); if (grub_loader_noreturn) grub_machine_fini (); - + while (iter) + { + if (iter->preboot_func) + iter->preboot_func (grub_loader_noreturn); + iter=iter->next; + } return (grub_loader_boot_func) (); } Index: include/grub/loader.h =================================================================== --- include/grub/loader.h (revision 1845) +++ include/grub/loader.h (working copy) @@ -25,6 +25,7 @@ #include <grub/err.h> #include <grub/types.h> + /* Check if a loader is loaded. */ int EXPORT_FUNC(grub_loader_is_loaded) (void); @@ -37,6 +38,12 @@ /* Unset current loader, if any. */ void EXPORT_FUNC(grub_loader_unset) (void); +/*Add a preboot function*/ +void *EXPORT_FUNC(grub_loader_add_preboot) (grub_err_t (*preboot_func) (int noreturn)); + +/*Remove given preboot function*/ +void EXPORT_FUNC(grub_loader_remove_preboot) (void *hnd); + /* Call the boot hook in current loader. This may or may not return, depending on the setting by grub_loader_set. */ grub_err_t EXPORT_FUNC(grub_loader_boot) (void);
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel