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
);
112 static int g_ventoy_hook_root
= 0;
113 void ventoy_env_hook_root(int hook
)
115 g_ventoy_hook_root
= hook
;
119 ventoy_env_write_root (struct grub_env_var
*var
__attribute__ ((unused
)),
122 const char *pos
= val
;
125 if (g_ventoy_hook_root
== 0)
127 return grub_env_write_root(var
, val
);
135 if (grub_strncmp(pos
, "vtimghd", 7) == 0)
137 return grub_env_write_root(var
, val
);
140 pos
= grub_strchr(val
, ',');
143 return grub_env_write_root(var
, val
);
148 grub_snprintf(buf
, sizeof(buf
), "(vtimghd%s", pos
);
152 grub_snprintf(buf
, sizeof(buf
), "vtimghd%s", pos
);
155 return grub_env_write_root(var
, buf
);
159 grub_set_prefix_and_root (void)
163 char *fwdevice
= NULL
;
166 struct grub_module_header
*header
;
169 if (header
->type
== OBJ_TYPE_PREFIX
)
170 prefix
= (char *) header
+ sizeof (struct grub_module_header
);
172 grub_register_variable_hook ("root", 0, ventoy_env_write_root
);
174 grub_machine_get_bootlocation (&fwdevice
, &fwpath
);
180 cmdpath
= grub_xasprintf ("(%s)%s", fwdevice
, fwpath
? : "");
183 grub_env_set ("cmdpath", cmdpath
);
184 grub_env_export ("cmdpath");
192 if (prefix
[0] == '(')
194 pptr
= grub_strrchr (prefix
, ')');
197 device
= grub_strndup (prefix
+ 1, pptr
- prefix
- 1);
204 path
= grub_strdup (pptr
);
207 if (!device
&& fwdevice
)
209 else if (fwdevice
&& (device
[0] == ',' || !device
[0]))
211 /* We have a partition, but still need to fill in the drive. */
212 char *comma
, *new_device
;
214 for (comma
= fwdevice
; *comma
; )
216 if (comma
[0] == '\\' && comma
[1] == ',')
227 char *drive
= grub_strndup (fwdevice
, comma
- fwdevice
);
228 new_device
= grub_xasprintf ("%s%s", drive
, device
);
232 new_device
= grub_xasprintf ("%s%s", fwdevice
, device
);
234 grub_free (fwdevice
);
239 grub_free (fwdevice
);
242 grub_size_t len
= grub_strlen (fwpath
);
243 while (len
> 1 && fwpath
[len
- 1] == '/')
245 if (len
>= sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1
246 && grub_memcmp (fwpath
+ len
- (sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1), GRUB_TARGET_CPU
"-" GRUB_PLATFORM
,
247 sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1) == 0)
248 fwpath
[len
- (sizeof (GRUB_TARGET_CPU
"-" GRUB_PLATFORM
) - 1)] = 0;
257 prefix_set
= grub_xasprintf ("(%s)%s", device
, path
? : "");
260 grub_env_set ("prefix", prefix_set
);
261 grub_free (prefix_set
);
263 grub_env_set ("root", device
);
271 /* Load the normal mode module and execute the normal mode if possible. */
273 grub_load_normal_mode (void)
275 /* Load the module. */
276 grub_dl_load ("normal");
278 /* Print errors if any. */
282 grub_command_execute ("normal", 0, 0);
286 reclaim_module_space (void)
288 grub_addr_t modstart
, modend
;
293 #ifdef GRUB_MACHINE_PCBIOS
294 modstart
= GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
;
296 modstart
= grub_modbase
;
298 modend
= grub_modules_get_end ();
301 #if GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
302 grub_mm_init_region ((void *) modstart
, modend
- modstart
);
309 #ifndef GRUB_MACHINE_EFI
310 static int ventoy_legacy_limit_workaround(void)
316 root
= grub_strdup(grub_env_get("root"));
322 pos
= grub_strchr(root
, ',');
325 grub_snprintf(buf
, sizeof(buf
), "(%s,1)/ventoy/ventoy.disk.img.xz", root
);
326 file
= grub_file_open(buf
, GRUB_FILE_TYPE_NONE
);
329 pos
= grub_malloc(file
->size
);
332 grub_file_read(file
, pos
, file
->size
);
333 grub_snprintf(buf
, sizeof(buf
), "loopback ventoydisk mem:0x%lx:size:%lu",
334 (unsigned long)pos
, (unsigned long)file
->size
);
336 grub_parser_execute(buf
);
337 grub_env_set("prefix", "(ventoydisk)/grub");
340 grub_file_close(file
);
348 /* The main routine. */
349 void __attribute__ ((noreturn
))
352 /* First of all, initialize the machine. */
353 grub_machine_init ();
355 grub_boot_time ("After machine init.");
358 grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT
);
359 //grub_printf ("Welcome to GRUB!\n\n");
360 grub_setcolorstate (GRUB_TERM_COLOR_STANDARD
);
364 grub_boot_time ("Before loading embedded modules.");
366 /* Load pre-loaded modules and free the space. */
367 grub_register_exported_symbols ();
368 #ifdef GRUB_LINKER_HAVE_INIT
369 grub_arch_dl_init_linker ();
371 grub_load_modules ();
373 grub_boot_time ("After loading embedded modules.");
375 /* It is better to set the root device as soon as possible,
377 grub_set_prefix_and_root ();
378 grub_env_export ("root");
379 grub_env_export ("prefix");
381 #ifndef GRUB_MACHINE_EFI
382 if (0 == ventoy_check_file_exist("%s/grub.cfg", grub_env_get("prefix"))) {
383 ventoy_legacy_limit_workaround();
387 /* Reclaim space used for modules. */
388 reclaim_module_space ();
390 grub_boot_time ("After reclaiming module space.");
392 grub_register_core_commands ();
394 grub_boot_time ("Before execution of embedded config.");
397 grub_parser_execute (load_config
);
399 grub_boot_time ("After execution of embedded config. Attempt to go to normal mode");
401 grub_load_normal_mode ();