1
/* dl.c - loadable module support */
3
* GRUB -- GRand Unified Bootloader
4
* Copyright (C) 2002,2003,2004,2005,2007,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
/* Force native word size */
21
#define GRUB_TARGET_WORDSIZE (8 * GRUB_CPU_SIZEOF_VOID_P)
26
#include <grub/misc.h>
29
#include <grub/types.h>
30
#include <grub/symbol.h>
31
#include <grub/file.h>
33
#include <grub/cache.h>
34
#include <grub/i18n.h>
36
/* Platforms where modules are in a readonly area of memory. */
37
#if defined(GRUB_MACHINE_QEMU)
38
#define GRUB_MODULES_MACHINE_READONLY
41
#ifdef GRUB_MACHINE_EMU
47
#pragma GCC diagnostic ignored "-Wcast-align"
49
grub_dl_t grub_dl_head = 0;
52
grub_dl_add (grub_dl_t mod);
55
grub_dl_add (grub_dl_t mod)
57
if (grub_dl_get (mod->name))
58
return grub_error (GRUB_ERR_BAD_MODULE,
59
"`%s' is already loaded", mod->name);
61
mod->next = grub_dl_head;
68
grub_dl_remove (grub_dl_t mod)
72
for (p = &grub_dl_head, q = *p; q; p = &q->next, q = *p)
81
grub_dl_get (const char *name)
85
for (l = grub_dl_head; l; l = l->next)
86
if (grub_strcmp (name, l->name) == 0)
96
struct grub_symbol *next;
100
grub_dl_t mod; /* The module to which this symbol belongs. */
102
typedef struct grub_symbol *grub_symbol_t;
104
/* The size of the symbol table. */
105
#define GRUB_SYMTAB_SIZE 509
107
/* The symbol table (using an open-hash). */
108
static struct grub_symbol *grub_symtab[GRUB_SYMTAB_SIZE];
110
/* Simple hash function. */
112
grub_symbol_hash (const char *s)
117
key = key * 65599 + *s++;
119
return (key + (key >> 5)) % GRUB_SYMTAB_SIZE;
122
/* Resolve the symbol name NAME and return the address.
123
Return NULL, if not found. */
125
grub_dl_resolve_symbol (const char *name)
129
for (sym = grub_symtab[grub_symbol_hash (name)]; sym; sym = sym->next)
130
if (grub_strcmp (sym->name, name) == 0)
136
/* Register a symbol with the name NAME and the address ADDR. */
138
grub_dl_register_symbol (const char *name, void *addr, int isfunc,
144
sym = (grub_symbol_t) grub_malloc (sizeof (*sym));
150
sym->name = grub_strdup (name);
162
sym->isfunc = isfunc;
164
k = grub_symbol_hash (name);
165
sym->next = grub_symtab[k];
166
grub_symtab[k] = sym;
168
return GRUB_ERR_NONE;
171
/* Unregister all the symbols defined in the module MOD. */
173
grub_dl_unregister_symbols (grub_dl_t mod)
178
grub_fatal ("core symbols cannot be unregistered");
180
for (i = 0; i < GRUB_SYMTAB_SIZE; i++)
182
grub_symbol_t sym, *p, q;
184
for (p = &grub_symtab[i], sym = *p; sym; sym = q)
190
grub_free ((void *) sym->name);
199
/* Return the address of a section whose index is N. */
201
grub_dl_get_section_addr (grub_dl_t mod, unsigned n)
203
grub_dl_segment_t seg;
205
for (seg = mod->segment; seg; seg = seg->next)
206
if (seg->section == n)
212
/* Check if EHDR is a valid ELF header. */
214
grub_dl_check_header (void *ehdr, grub_size_t size)
219
/* Check the header size. */
220
if (size < sizeof (Elf_Ehdr))
221
return grub_error (GRUB_ERR_BAD_OS, "ELF header smaller than expected");
223
/* Check the magic numbers. */
224
if (e->e_ident[EI_MAG0] != ELFMAG0
225
|| e->e_ident[EI_MAG1] != ELFMAG1
226
|| e->e_ident[EI_MAG2] != ELFMAG2
227
|| e->e_ident[EI_MAG3] != ELFMAG3
228
|| e->e_ident[EI_VERSION] != EV_CURRENT
229
|| e->e_version != EV_CURRENT)
230
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
232
err = grub_arch_dl_check_header (ehdr);
236
return GRUB_ERR_NONE;
239
/* Load all segments from memory specified by E. */
241
grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
245
grub_size_t tsize = 0, talign = 1;
246
#if defined (__ia64__) || defined (__powerpc__)
252
for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
254
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
256
tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
257
if (talign < s->sh_addralign)
258
talign = s->sh_addralign;
261
#if defined (__ia64__) || defined (__powerpc__)
262
grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
263
tramp *= GRUB_ARCH_DL_TRAMP_SIZE;
264
got *= sizeof (grub_uint64_t);
265
tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
266
if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
267
talign = GRUB_ARCH_DL_TRAMP_ALIGN;
268
tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN);
269
if (talign < GRUB_ARCH_DL_GOT_ALIGN)
270
talign = GRUB_ARCH_DL_GOT_ALIGN;
273
#ifdef GRUB_MACHINE_EMU
274
if (talign < 8192 * 16)
276
tsize = ALIGN_UP (tsize, 8192 * 16);
279
mod->base = grub_memalign (talign, tsize);
285
#ifdef GRUB_MACHINE_EMU
286
mprotect (mod->base, tsize, PROT_READ | PROT_WRITE | PROT_EXEC);
289
for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
291
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
293
if (s->sh_flags & SHF_ALLOC)
295
grub_dl_segment_t seg;
297
seg = (grub_dl_segment_t) grub_malloc (sizeof (*seg));
305
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign);
312
grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
315
grub_memset (addr, 0, s->sh_size);
324
seg->size = s->sh_size;
326
seg->next = mod->segment;
330
#if defined (__ia64__) || defined (__powerpc__)
331
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
334
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN);
339
return GRUB_ERR_NONE;
343
grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
349
Elf_Word size, entsize;
351
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
353
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
354
if (s->sh_type == SHT_SYMTAB)
358
return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table"));
360
#ifdef GRUB_MODULES_MACHINE_READONLY
361
mod->symtab = grub_malloc (s->sh_size);
362
memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size);
364
mod->symtab = (Elf_Sym *) ((char *) e + s->sh_offset);
368
entsize = s->sh_entsize;
370
s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link);
371
str = (char *) e + s->sh_offset;
375
i++, sym = (Elf_Sym *) ((char *) sym + entsize))
377
unsigned char type = ELF_ST_TYPE (sym->st_info);
378
unsigned char bind = ELF_ST_BIND (sym->st_info);
379
const char *name = str + sym->st_name;
385
/* Resolve a global symbol. */
386
if (sym->st_name != 0 && sym->st_shndx == 0)
388
grub_symbol_t nsym = grub_dl_resolve_symbol (name);
390
return grub_error (GRUB_ERR_BAD_MODULE,
391
N_("symbol `%s' not found"), name);
392
sym->st_value = (Elf_Addr) nsym->addr;
394
sym->st_info = ELF_ST_INFO (bind, STT_FUNC);
398
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
400
if (bind != STB_LOCAL)
401
if (grub_dl_register_symbol (name, (void *) sym->st_value, 0, mod))
407
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
411
/* FIXME: free descriptor once it's not used anymore. */
413
desc = grub_malloc (2 * sizeof (char *));
416
desc[0] = (void *) sym->st_value;
418
sym->st_value = (grub_addr_t) desc;
421
if (bind != STB_LOCAL)
422
if (grub_dl_register_symbol (name, (void *) sym->st_value, 1, mod))
424
if (grub_strcmp (name, "grub_mod_init") == 0)
425
mod->init = (void (*) (grub_dl_t)) sym->st_value;
426
else if (grub_strcmp (name, "grub_mod_fini") == 0)
427
mod->fini = (void (*) (void)) sym->st_value;
431
sym->st_value = (Elf_Addr) grub_dl_get_section_addr (mod,
440
return grub_error (GRUB_ERR_BAD_MODULE,
441
"unknown symbol type `%d'", (int) type);
445
return GRUB_ERR_NONE;
449
grub_dl_call_init (grub_dl_t mod)
455
/* Me, Vladimir Serbinenko, hereby I add this module check as per new
456
GNU module policy. Note that this license check is informative only.
457
Modules have to be licensed under GPLv3 or GPLv3+ (optionally
458
multi-licensed under other licences as well) independently of the
459
presence of this check and solely by linking (module loading in GRUB
460
constitutes linking) and GRUB core being licensed under GPLv3+.
461
Be sure to understand your license obligations.
464
grub_dl_check_license (Elf_Ehdr *e)
470
s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
471
str = (char *) e + s->sh_offset;
473
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
475
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
476
if (grub_strcmp (str + s->sh_name, ".module_license") == 0)
478
if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0
479
|| grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0
480
|| grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)
481
return GRUB_ERR_NONE;
484
return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license");
488
grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e)
494
s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
495
str = (char *) e + s->sh_offset;
497
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
499
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
500
if (grub_strcmp (str + s->sh_name, ".modname") == 0)
502
mod->name = grub_strdup ((char *) e + s->sh_offset);
509
return grub_error (GRUB_ERR_BAD_MODULE, "no module name found");
511
return GRUB_ERR_NONE;
515
grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e)
521
s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
522
str = (char *) e + s->sh_offset;
524
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
526
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
527
if (grub_strcmp (str + s->sh_name, ".moddeps") == 0)
529
const char *name = (char *) e + s->sh_offset;
530
const char *max = name + s->sh_size;
532
while ((name < max) && (*name))
537
m = grub_dl_load (name);
543
dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep));
548
dep->next = mod->dep;
551
name += grub_strlen (name) + 1;
555
return GRUB_ERR_NONE;
559
grub_dl_ref (grub_dl_t mod)
566
for (dep = mod->dep; dep; dep = dep->next)
567
grub_dl_ref (dep->mod);
569
return ++mod->ref_count;
573
grub_dl_unref (grub_dl_t mod)
580
for (dep = mod->dep; dep; dep = dep->next)
581
grub_dl_unref (dep->mod);
583
return --mod->ref_count;
587
grub_dl_flush_cache (grub_dl_t mod)
589
grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
590
(unsigned long) mod->sz, mod->base);
591
grub_arch_sync_caches (mod->base, mod->sz);
594
/* Load a module from core memory. */
596
grub_dl_load_core (void *addr, grub_size_t size)
601
grub_dprintf ("modules", "module at %p, size 0x%lx\n", addr,
602
(unsigned long) size);
604
if (grub_dl_check_header (e, size))
607
if (e->e_type != ET_REL)
609
grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type"));
613
/* Make sure that every section is within the core. */
614
if (size < e->e_shoff + e->e_shentsize * e->e_shnum)
616
grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core");
620
mod = (grub_dl_t) grub_zalloc (sizeof (*mod));
626
grub_dprintf ("modules", "relocating to %p\n", mod);
627
/* Me, Vladimir Serbinenko, hereby I add this module check as per new
628
GNU module policy. Note that this license check is informative only.
629
Modules have to be licensed under GPLv3 or GPLv3+ (optionally
630
multi-licensed under other licences as well) independently of the
631
presence of this check and solely by linking (module loading in GRUB
632
constitutes linking) and GRUB core being licensed under GPLv3+.
633
Be sure to understand your license obligations.
635
if (grub_dl_check_license (e)
636
|| grub_dl_resolve_name (mod, e)
637
|| grub_dl_resolve_dependencies (mod, e)
638
|| grub_dl_load_segments (mod, e)
639
|| grub_dl_resolve_symbols (mod, e)
640
|| grub_arch_dl_relocate_symbols (mod, e))
643
grub_dl_unload (mod);
647
grub_dl_flush_cache (mod);
649
grub_dprintf ("modules", "module name: %s\n", mod->name);
650
grub_dprintf ("modules", "init function: %p\n", mod->init);
651
grub_dl_call_init (mod);
653
if (grub_dl_add (mod))
655
grub_dl_unload (mod);
662
/* Load a module from the file FILENAME. */
664
grub_dl_load_file (const char *filename)
666
grub_file_t file = NULL;
671
file = grub_file_open (filename);
675
size = grub_file_size (file);
676
core = grub_malloc (size);
679
grub_file_close (file);
683
if (grub_file_read (file, core, size) != (int) size)
685
grub_file_close (file);
690
/* We must close this before we try to process dependencies.
691
Some disk backends do not handle gracefully multiple concurrent
692
opens of the same device. */
693
grub_file_close (file);
695
mod = grub_dl_load_core (core, size);
704
/* Load a module using a symbolic name. */
706
grub_dl_load (const char *name)
710
const char *grub_dl_dir = grub_env_get ("prefix");
712
mod = grub_dl_get (name);
717
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
721
filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod",
726
mod = grub_dl_load_file (filename);
727
grub_free (filename);
732
if (grub_strcmp (mod->name, name) != 0)
733
grub_error (GRUB_ERR_BAD_MODULE, "mismatched names");
738
/* Unload the module MOD. */
740
grub_dl_unload (grub_dl_t mod)
742
grub_dl_dep_t dep, depn;
744
if (mod->ref_count > 0)
750
grub_dl_remove (mod);
751
grub_dl_unregister_symbols (mod);
753
for (dep = mod->dep; dep; dep = depn)
757
grub_dl_unload (dep->mod);
762
grub_free (mod->base);
763
grub_free (mod->name);
764
#ifdef GRUB_MODULES_MACHINE_READONLY
765
grub_free (mod->symtab);
771
/* Unload unneeded modules. */
773
grub_dl_unload_unneeded (void)
775
/* Because grub_dl_remove modifies the list of modules, this
776
implementation is tricky. */
777
grub_dl_t p = grub_dl_head;
781
if (grub_dl_unload (p))