From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1Lu0PS-0003Ik-0W for mharc-grub-devel@gnu.org; Wed, 15 Apr 2009 04:23:54 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lu0PO-0003IC-Tz for grub-devel@gnu.org; Wed, 15 Apr 2009 04:23:50 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lu0PK-0003Hl-Cw for grub-devel@gnu.org; Wed, 15 Apr 2009 04:23:50 -0400 Received: from [199.232.76.173] (port=47410 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lu0PK-0003Hi-2i for grub-devel@gnu.org; Wed, 15 Apr 2009 04:23:46 -0400 Received: from mail-fx0-f166.google.com ([209.85.220.166]:48566) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Lu0PJ-0001yG-GT for grub-devel@gnu.org; Wed, 15 Apr 2009 04:23:45 -0400 Received: by fxm10 with SMTP id 10so3066662fxm.42 for ; Wed, 15 Apr 2009 01:23:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:references:in-reply-to :content-type; bh=IEtW1WPwCq8aDe8HNHGtUg2KQcjuHtDS/9QqKWszrMc=; b=OEatbUdnN+6XBBkMHCzLBB0cI5Q4O3KG/YDD4XrY+BuFap32N5Z6NIy1cMSOTpUnfH i/s2xPVgWZzbj/tam6VKttnwe24DY5PAWsdmnKu63qZLMokxFV8Mmn1ISzNyV4vHYZ4m ZKvfNkH/z7bHu9lAzrNnjCZ83wzNWFbynaUoM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type; b=jqalCvBHKSp7lRjxjiOGzyN0UcRDnt4Czk58ObfgaTtj2yDNqZl9NkShLhdsmQJcwA 2HCSvSE5DORhJVUmMFVLq2Si92RUKhBbEl+qw9192QBCdvxIzMfzBLKByEDAtx7LNHZq UCDIz5H3nR4UMaRZNCGQcUkVd+9WesIswdTMw= Received: by 10.204.120.70 with SMTP id c6mr2219306bkr.144.1239783823511; Wed, 15 Apr 2009 01:23:43 -0700 (PDT) Received: from ?192.168.1.100? (121.88.202.62.cust.bluewin.ch [62.202.88.121]) by mx.google.com with ESMTPS id h2sm7898869fkh.29.2009.04.15.01.23.41 (version=SSLv3 cipher=RC4-MD5); Wed, 15 Apr 2009 01:23:42 -0700 (PDT) Message-ID: <49E5998C.7030200@gmail.com> Date: Wed, 15 Apr 2009 10:23:40 +0200 From: phcoder User-Agent: Thunderbird 2.0.0.21 (X11/20090409) MIME-Version: 1.0 To: The development of GRUB 2 References: <49DFDAB7.1080009@gmail.com> <49E0BAC7.2030503@gmail.com> <49E2228B.7040600@gmail.com> <200904142342.52968.okuji@enbug.org> In-Reply-To: <200904142342.52968.okuji@enbug.org> Content-Type: multipart/mixed; boundary="------------010601050602020305020201" X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: Re: [PATCH] Preboot support X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Apr 2009 08:23:51 -0000 This is a multi-part message in MIME format. --------------010601050602020305020201 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit 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 --------------010601050602020305020201 Content-Type: text/x-patch; name="preboot.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="preboot.patch" diff --git a/ChangeLog b/ChangeLog index dd28915..1b2bbda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2009-04-06 Vladimir Serbinenko + + 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 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 #include #include +#include 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 */ --------------010601050602020305020201--