boot.c 4.4 KB
Newer Older
1 2
/* boot.c - command to boot an operating system */
/*
3
 *  GRUB  --  GRand Unified Bootloader
4
 *  Copyright (C) 2002,2003,2004,2005,2007,2009  Free Software Foundation, Inc.
5
 *
6
 *  GRUB is free software: you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation, either version 3 of the License, or
9 10
 *  (at your option) any later version.
 *
11
 *  GRUB is distributed in the hope that it will be useful,
12 13 14 15 16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18 19
 */

20 21 22 23
#include <grub/normal.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/loader.h>
24
#include <grub/kernel.h>
25
#include <grub/mm.h>
26
#include <grub/i18n.h>
27

28 29
GRUB_MOD_LICENSE ("GPLv3+");

30 31
static grub_err_t (*grub_loader_boot_func) (void);
static grub_err_t (*grub_loader_unload_func) (void);
32
static int grub_loader_flags;
33

34
struct grub_preboot
35 36 37 38
{
  grub_err_t (*preboot_func) (int);
  grub_err_t (*preboot_rest_func) (void);
  grub_loader_preboot_hook_prio_t prio;
39 40
  struct grub_preboot *next;
  struct grub_preboot *prev;
41 42
};

43
static int grub_loader_loaded;
44
static struct grub_preboot *preboots_head = 0,
45
  *preboots_tail = 0;
46 47 48 49 50 51 52

int
grub_loader_is_loaded (void)
{
  return grub_loader_loaded;
}

53
/* Register a preboot hook. */
54
struct grub_preboot *
55
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int flags),
56 57 58
				   grub_err_t (*preboot_rest_func) (void),
				   grub_loader_preboot_hook_prio_t prio)
{
59
  struct grub_preboot *cur, *new_preboot;
60 61 62 63

  if (! preboot_func && ! preboot_rest_func)
    return 0;

64 65
  new_preboot = (struct grub_preboot *)
    grub_malloc (sizeof (struct grub_preboot));
66
  if (! new_preboot)
67
    return 0;
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

  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;
}

95
void
96
grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
97
{
98
  struct grub_preboot *preb = hnd;
99 100 101 102 103 104 105 106 107 108 109 110 111

  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);
}

112 113 114
void
grub_loader_set (grub_err_t (*boot) (void),
		 grub_err_t (*unload) (void),
115
		 int flags)
116 117 118
{
  if (grub_loader_loaded && grub_loader_unload_func)
    grub_loader_unload_func ();
119

120 121
  grub_loader_boot_func = boot;
  grub_loader_unload_func = unload;
122
  grub_loader_flags = flags;
123

124 125 126 127 128
  grub_loader_loaded = 1;
}

void
grub_loader_unset(void)
129
{
130 131
  if (grub_loader_loaded && grub_loader_unload_func)
    grub_loader_unload_func ();
132

133 134 135 136 137 138 139 140 141
  grub_loader_boot_func = 0;
  grub_loader_unload_func = 0;

  grub_loader_loaded = 0;
}

grub_err_t
grub_loader_boot (void)
{
142
  grub_err_t err = GRUB_ERR_NONE;
143
  struct grub_preboot *cur;
144

145
  if (! grub_loader_loaded)
146 147
    return grub_error (GRUB_ERR_NO_KERNEL,
		       N_("you need to load the kernel first"));
148

149
  grub_machine_fini (grub_loader_flags);
150

151 152
  for (cur = preboots_head; cur; cur = cur->next)
    {
153
      err = cur->preboot_func (grub_loader_flags);
154 155 156 157 158 159 160 161 162 163
      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)
164
    if (! err)
165 166 167 168 169 170
      err = cur->preboot_rest_func ();
    else
      cur->preboot_rest_func ();

  return err;
}
171 172 173 174 175 176 177 178

/* boot */
static grub_err_t
grub_cmd_boot (struct grub_command *cmd __attribute__ ((unused)),
		    int argc __attribute__ ((unused)),
		    char *argv[] __attribute__ ((unused)))
{
  return grub_loader_boot ();
179 180 181
}


182

183 184
static grub_command_t cmd_boot;

185
GRUB_MOD_INIT(boot)
186
{
187 188
  cmd_boot =
    grub_register_command ("boot", grub_cmd_boot,
189
			   0, N_("Boot an operating system."));
190 191
}

192
GRUB_MOD_FINI(boot)
193
{
194
  grub_unregister_command (cmd_boot);
195
}