1 /* main.c - the kernel main routine */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2003,2005,2006,2008,2009 Free Software Foundation, Inc.
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 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/kernel.h>
21 #include <grub/misc.h>
22 #include <grub/symbol.h>
24 #include <grub/term.h>
25 #include <grub/file.h>
26 #include <grub/device.h>
29 #include <grub/command.h>
30 #include <grub/reader.h>
31 #include <grub/parser.h>
33 #ifdef GRUB_MACHINE_PCBIOS
34 #include <grub/machine/memory.h>
38 grub_modules_get_end (void)
40 struct grub_module_info
*modinfo
;
42 modinfo
= (struct grub_module_info
*) grub_modbase
;
44 /* Check if there are any modules. */
45 if ((modinfo
== 0) || modinfo
->magic
!= GRUB_MODULE_MAGIC
)
48 return grub_modbase
+ modinfo
->size
;
51 /* Load all modules in core. */
53 grub_load_modules (void)
55 struct grub_module_header
*header
;
58 /* Not an ELF module, skip. */
59 if (header
->type
!= OBJ_TYPE_ELF
)
62 if (! grub_dl_load_core ((char *) header
+ sizeof (struct grub_module_header
),
63 (header
->size
- sizeof (struct grub_module_header
))))
64 grub_fatal ("%s", grub_errmsg
);
71 static char *load_config
;
74 grub_load_config (void)
76 struct grub_module_header
*header
;
79 /* Not an embedded config, skip. */
80 if (header
->type
!= OBJ_TYPE_CONFIG
)
83 load_config
= grub_malloc (header
->size
- sizeof (struct grub_module_header
) + 1);
89 grub_memcpy (load_config
, (char *) header
+
90 sizeof (struct grub_module_header
),
91 header
->size
- sizeof (struct grub_module_header
));
92 load_config
[header
->size
- sizeof (struct grub_module_header
)] = 0;
97 /* Write hook for the environment variables of root. Remove surrounding
98 parentheses, if any. */
100 grub_env_write_root (struct grub_env_var
*var
__attribute__ ((unused
)),
103 /* XXX Is it better to check the existence of the device? */
104 grub_size_t len
= grub_strlen (val
);
106 if (val
[0] == '(' && val
[len
- 1] == ')')
107 return grub_strndup (val
+ 1, len
- 2);
109 return grub_strdup (val
);
113 grub_set_prefix_and_root (void)
117 char *fwdevice
= NULL
;
120 struct grub_module_header
*header
;
123 if (header
->type
== OBJ_TYPE_PREFIX
)
124 prefix
= (char *) header
+ sizeof (struct grub_module_header
);
126 grub_register_variable_hook ("root", 0, grub_env_write_root
);
128 grub_machine_get_bootlocation (&fwdevice
, &fwpath
);
134 cmdpath
= grub_xasprintf ("(%s)%s", fwdevice
, fwpath
? : "");
137 grub_env_set ("cmdpath", cmdpath
);
138 grub_env_export ("cmdpath");
146 if (prefix
[0] == '(')
148 pptr
= grub_strrchr (prefix
, ')');
151 device
= grub_strndup (prefix
+ 1, pptr
- prefix
- 1);
158 path
= grub_strdup (pptr
);
161 if (!device
&& fwdevice
)
163 else if (fwdevice
&& (device
[0] == ',' || !device
[0]))
165 /* We have a partition, but still need to fill in the drive. */
166 char *comma
, *new_device
;
168 for (comma
= fwdevice
; *comma
; )
170 if (comma
[0] == '\\' && comma
[1] == ',')
181 char *drive
= grub_strndup (fwdevice
, comma
- fwdevice
);
182 new_device
= grub_xasprintf ("%s%s", drive
, device
);
186 new_device
= grub_xasprintf ("%s%s", fwdevice
, device
);
188 grub_free (fwdevice
);
193 grub_free (fwdevice
);
196 grub_size_t len
= grub_strlen (fwpath
);
197 while (len
> 1 && fwpath
[len
- 1] == '/')
199 if (len
>= sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1
200 && grub_memcmp (fwpath
+ len
- (sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1), GRUB_TARGET_CPU
"-" GRUB_PLATFORM
,
201 sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1) == 0)
202 fwpath
[len
- (sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1)] = 0;
211 prefix_set
= grub_xasprintf ("(%s)%s", device
, path
? : "");
214 grub_env_set ("prefix", prefix_set
);
215 grub_free (prefix_set
);
217 grub_env_set ("root", device
);
225 /* Load the normal mode module and execute the normal mode if possible. */
227 grub_load_normal_mode (void)
229 /* Load the module. */
230 grub_dl_load ("normal");
232 /* Print errors if any. */
236 grub_command_execute ("normal", 0, 0);
240 reclaim_module_space (void)
242 grub_addr_t modstart
, modend
;
247 #ifdef GRUB_MACHINE_PCBIOS
248 modstart
= GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
;
250 modstart
= grub_modbase
;
252 modend
= grub_modules_get_end ();
255 #if GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
256 grub_mm_init_region ((void *) modstart
, modend
- modstart
);
263 /* The main routine. */
264 void __attribute__ ((noreturn
))
267 /* First of all, initialize the machine. */
268 grub_machine_init ();
270 grub_boot_time ("After machine init.");
273 grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT
);
274 grub_printf ("Welcome to GRUB!\n\n");
275 grub_setcolorstate (GRUB_TERM_COLOR_STANDARD
);
279 grub_boot_time ("Before loading embedded modules.");
281 /* Load pre-loaded modules and free the space. */
282 grub_register_exported_symbols ();
283 #ifdef GRUB_LINKER_HAVE_INIT
284 grub_arch_dl_init_linker ();
286 grub_load_modules ();
288 grub_boot_time ("After loading embedded modules.");
290 /* It is better to set the root device as soon as possible,
292 grub_set_prefix_and_root ();
293 grub_env_export ("root");
294 grub_env_export ("prefix");
296 /* Reclaim space used for modules. */
297 reclaim_module_space ();
299 grub_boot_time ("After reclaiming module space.");
301 grub_register_core_commands ();
303 grub_boot_time ("Before execution of embedded config.");
306 grub_parser_execute (load_config
);
308 grub_boot_time ("After execution of embedded config. Attempt to go to normal mode");
310 grub_load_normal_mode ();