diff --git a/Makefile.in b/Makefile.in index b24ee2e..06478af 100644 --- a/Makefile.in +++ b/Makefile.in @@ -139,11 +139,9 @@ include $(srcdir)/conf/$(target_cpu)-$(platform).mk ### General targets. CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) -pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst handler.lst -moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk - cat $(DEFSYMFILES) /dev/null \ - | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \ - || (rm -f $@; exit 1) +pkglib_DATA += modsym.lst command.lst fs.lst partmap.lst handler.lst +modsym.lst: $(MODFILES) grub-symdb + ./grub-symdb -d . update $? command.lst: $(COMMANDFILES) cat $^ /dev/null | sort > $@ diff --git a/conf/common.rmk b/conf/common.rmk index 0e63da6..20a1b89 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -23,6 +23,10 @@ grub_probe_SOURCES = util/grub-probe.c \ kern/fs.c kern/env.c fs/fshelp.c \ disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c +# For grub-symdb +bin_UTILITIES += grub-symdb +grub_symdb_SOURCES = util/grub-symdb.c util/misc.c util/resolve.c + ifeq ($(enable_grub_fstest), yes) bin_UTILITIES += grub-fstest endif diff --git a/genmk.rb b/genmk.rb index b619421..c119fad 100644 --- a/genmk.rb +++ b/genmk.rb @@ -99,18 +99,10 @@ class PModule pre_obj = 'pre-' + @name.suffix('o') mod_src = 'mod-' + @name.suffix('c') mod_obj = mod_src.suffix('o') - defsym = 'def-' + @name.suffix('lst') - undsym = 'und-' + @name.suffix('lst') mod_name = File.basename(@name, '.mod') symbolic_name = mod_name.sub(/\.[^\.]*$/, '') - "CLEANFILES += address@hidden #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{undsym} -ifneq ($(#{prefix}_EXPORTS),no) -CLEANFILES += #{defsym} -DEFSYMFILES += #{defsym} -endif -MOSTLYCLEANFILES += #{deps_str} -UNDSYMFILES += #{undsym} + "CLEANFILES += address@hidden #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} address@hidden: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF) -rm -f $@ @@ -125,17 +117,10 @@ UNDSYMFILES += #{undsym} #{mod_obj}: #{mod_src} $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -c -o $@ $< -#{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh - sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1) - -ifneq ($(#{prefix}_EXPORTS),no) -#{defsym}: #{pre_obj} - $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@ -endif +#{mod_src}: $(srcdir)/genmodsrc.sh + sh $(srcdir)/genmodsrc.sh '#{mod_name}' > $@ || (rm -f $@; exit 1) -#{undsym}: #{pre_obj} - echo '#{mod_name}' > $@ - $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ +MODFILES += address@hidden " + objs.collect_with_index do |obj, i| src = sources[i] diff --git a/genmodsrc.sh b/genmodsrc.sh index 2d42055..b334c7e 100644 --- a/genmodsrc.sh +++ b/genmodsrc.sh @@ -41,7 +41,4 @@ cat <. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define _GNU_SOURCE 1 +#include + +#if GRUB_TARGET_SIZEOF_VOID_P == 4 + +typedef Elf32_Word Elf_Word; +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Half Elf_Half; +typedef Elf32_Off Elf_Off; +typedef Elf32_Section Elf_Section; + +#define ELF_ST_BIND ELF32_ST_BIND +#define grub_target_to_host grub_target_to_host32 +#define grub_host_to_target grub_host_to_target32 + +#elif GRUB_TARGET_SIZEOF_VOID_P == 8 + +typedef Elf64_Word Elf_Word; +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Half Elf_Half; +typedef Elf64_Off Elf_Off; +typedef Elf64_Section Elf_Section; + +#define ELF_ST_BIND ELF64_ST_BIND +#define grub_target_to_host grub_target_to_host64 +#define grub_host_to_target grub_host_to_target64 + +#endif + +struct grub_symbol_list +{ + struct grub_symbol_list *next; + char *name; + struct grub_named_list *defs; + struct grub_named_list *unds; +}; + +static struct grub_symbol_list *symbol_list; + +struct grub_update_list +{ + struct grub_update_list *next; + char *name; + struct grub_named_list *add_mods; + struct grub_named_list *del_mods; + struct grub_named_list *cur_mods; +}; + +static struct grub_update_list *update_list; + +struct grub_mod_syms +{ + struct grub_named_list *defs; + struct grub_named_list *unds; +}; + +static void * +insert_named_list (grub_named_list_t *head, grub_named_list_t item) +{ + grub_named_list_t *p, q; + + for (p = head, q = *p; q; p = &(q->next), q = q->next) + { + int r; + + r = strcmp (item->name, q->name); + if (! r) + return q; + + if (r < 0) + break; + } + + *p = item; + item->next = q; + + return item; +} + +static void +free_named_list (grub_named_list_t *head) +{ + grub_named_list_t cur = *head; + + while (cur) + { + grub_named_list_t tmp; + + tmp = cur; + cur = cur->next; + free ((char *) tmp->name); + free (tmp); + } + + *head = 0; +} + +static int +remove_string (grub_named_list_t *head, char *name) +{ + grub_named_list_t *p, q; + + for (p = head, q = *p; q; p = &(q->next), q = q->next) + { + int r; + + r = strcmp (name, q->name); + if (! r) + { + *p = q->next; + free ((char *) q->name); + free (q); + + return 1; + } + + if (r < 0) + break; + } + + return 0; +} + +static int +insert_string (grub_named_list_t *head, char *name) +{ + struct grub_named_list *item, *n; + + item = xmalloc (sizeof (struct grub_named_list)); + item->name = xstrdup (name); + + n = insert_named_list (head, item); + if (n != item) + { + free ((char *) item->name); + free (item); + + return 0; + } + + return 1; +} + +static struct grub_symbol_list * +insert_symbol (char *name) +{ + struct grub_symbol_list *s, *n; + + s = xmalloc (sizeof (struct grub_symbol_list)); + s->name = xstrdup (name); + s->defs = 0; + s->unds = 0; + + n = insert_named_list (GRUB_AS_NAMED_LIST_P (&symbol_list), + GRUB_AS_NAMED_LIST (s)); + + if (n != s) + { + free (s->name); + free (s); + } + + return n; +} + +static struct grub_update_list * +insert_update (char *name) +{ + struct grub_update_list *u, *n; + + u = xmalloc (sizeof (struct grub_update_list)); + u->name = xstrdup (name); + u->add_mods = 0; + u->del_mods = 0; + u->cur_mods = 0; + + n = insert_named_list (GRUB_AS_NAMED_LIST_P (&update_list), + GRUB_AS_NAMED_LIST (u)); + + if (n != u) + { + free (u->name); + free (u); + } + + return n; +} + +static void +add_update (char *m1, char *m2, int is_add) +{ + struct grub_update_list *u; + + u = insert_update (m2); + if (is_add) + { + remove_string (&u->del_mods, m1); + insert_string (&u->add_mods, m1); + } + else + insert_string (&u->del_mods, m1); +} + +static void +read_symdb (char *path) +{ + FILE *fp; + char line[512]; + struct grub_symbol_list *sym = 0; + + fp = fopen (path, "r"); + if (! fp) + return; + + while (fgets (line, sizeof (line), fp)) + { + char *p; + + p = line + strlen (line) - 1; + while ((p >= line) && ((*p == '\r') || (*p == '\n') || (*p == ' '))) + p--; + + if (p < line) + continue; + + *(p + 1) = 0; + + p = line; + while (*p == ' ') + p++; + + if (*p == '#') + continue; + + if ((*p == '+') || (*p == '-')) + { + if (! sym) + grub_util_error ("No current symbol."); + + insert_string ((*p == '+') ? &sym->defs : &sym->unds, p + 1); + } + else + sym = insert_symbol (p); + } + + fclose (fp); +} + +static void +write_symdb (char *path) +{ + FILE *fp; + struct grub_symbol_list *sym; + + fp = fopen (path, "w"); + if (! fp) + grub_util_error ("Can\'t write to ", path); + + sym = symbol_list; + while (sym) + { + struct grub_named_list *mod; + + fprintf (fp, "%s\n", sym->name); + mod = sym->defs; + while (mod) + { + fprintf (fp, "+%s\n", mod->name); + mod = mod->next; + } + mod = sym->unds; + while (mod) + { + fprintf (fp, "-%s\n", mod->name); + mod = mod->next; + } + + sym = sym->next; + } + + fclose (fp); +} + +static void +check_symdb (void) +{ + struct grub_symbol_list *sym; + + sym = symbol_list; + while (sym) + { + if (! sym->defs) + printf ("undefined: %s\n", sym->name); + else if (sym->defs->next) + printf ("duplicate: %s\n", sym->name); + + sym = sym->next; + } +} + +/* Return if the ELF header is valid. */ +static int +check_elf_header (Elf_Ehdr *e, size_t size) +{ + if (size < sizeof (*e) + || e->e_ident[EI_MAG0] != ELFMAG0 + || e->e_ident[EI_MAG1] != ELFMAG1 + || e->e_ident[EI_MAG2] != ELFMAG2 + || e->e_ident[EI_MAG3] != ELFMAG3 + || e->e_ident[EI_VERSION] != EV_CURRENT + || e->e_version != EV_CURRENT) + return 0; + + return 1; +} + +/* Return the symbol table section, if any. */ +static Elf_Shdr * +find_symtab_section (Elf_Shdr *sections, + Elf_Half section_entsize, Elf_Half num_sections) +{ + int i; + Elf_Shdr *s; + + for (i = 0, s = sections; + i < num_sections; + i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) + if (s->sh_type == grub_target_to_host32 (SHT_SYMTAB)) + return s; + + return 0; +} + +/* Return the address of the string table. */ +static char * +find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize) +{ + Elf_Shdr *s; + char *strtab; + + s = (Elf_Shdr *) ((char *) sections + + grub_target_to_host16 (e->e_shstrndx) * section_entsize); + strtab = (char *) e + grub_target_to_host (s->sh_offset); + return strtab; +} + +static Elf_Shdr * +find_moddep_section (Elf_Shdr *sections, + Elf_Half section_entsize, Elf_Half num_sections, + char *strtab) +{ + int i; + Elf_Shdr *s; + + for (i = 0, s = sections; + i < num_sections; + i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) + { + char *name = strtab + grub_target_to_host32 (s->sh_name); + + if (! strcmp (name, ".moddeps")) + return s; + } + + return 0; +} + +static void +read_elf_symbols (struct grub_mod_syms *mod_syms, + Elf_Ehdr *e, Elf_Shdr *sections, + Elf_Shdr *symtab_section, Elf_Half section_entsize, + Elf_Half num_sections) +{ + Elf_Word symtab_size, sym_size, num_syms; + Elf_Off symtab_offset; + Elf_Word i; + Elf_Sym *sym; + Elf_Shdr *strtab_section; + const char *strtab; + + strtab_section + = (Elf_Shdr *) ((char *) sections + + (grub_target_to_host32 (symtab_section->sh_link) + * section_entsize)); + strtab = (char *) e + grub_target_to_host32 (strtab_section->sh_offset); + + symtab_size = grub_target_to_host32 (symtab_section->sh_size); + sym_size = grub_target_to_host32 (symtab_section->sh_entsize); + symtab_offset = grub_target_to_host (symtab_section->sh_offset); + num_syms = symtab_size / sym_size; + + for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset); + i < num_syms; + i++, sym = (Elf_Sym *) ((char *) sym + sym_size)) + { + Elf_Section index; + struct grub_named_list **p = &mod_syms->defs; + + if (ELF_ST_BIND (sym->st_info) == STB_LOCAL) + continue; + + index = grub_target_to_host16 (sym->st_shndx); + if (index == STN_ABS) + { + continue; + } + else if (index == STN_UNDEF) + { + p = &mod_syms->unds; + } + else if (index >= num_sections) + grub_util_error ("section %d does not exist", index); + + insert_string (p, + (char *) (strtab + grub_target_to_host32 (sym->st_name))); + } +} + +static void +read_mod_syms (struct grub_mod_syms *mod_syms, char *path) +{ + size_t size; + char *image; + Elf_Ehdr *e; + Elf_Off section_offset; + Elf_Half section_entsize; + Elf_Half num_sections; + Elf_Shdr *sections; + Elf_Shdr *symtab_section; + + mod_syms->defs = 0; + mod_syms->unds = 0; + + size = grub_util_get_image_size (path); + image = grub_util_read_image (path); + + e = (Elf_Ehdr *) image; + if (! check_elf_header (e, size)) + grub_util_error ("invalid ELF header"); + + section_offset = grub_target_to_host (e->e_shoff); + section_entsize = grub_target_to_host16 (e->e_shentsize); + num_sections = grub_target_to_host16 (e->e_shnum); + + if (size < section_offset + section_entsize * num_sections) + grub_util_error ("invalid ELF format"); + + sections = (Elf_Shdr *) (image + section_offset); + symtab_section = find_symtab_section (sections, + section_entsize, num_sections); + if (! symtab_section) + grub_util_error ("no symbol table"); + + read_elf_symbols (mod_syms, e, sections, symtab_section, section_entsize, + num_sections); + + free (image); +} + +static void +update_mods (char *mods[], const char *dir) +{ + for (; mods[0]; mods++) + { + char *mod_name, *mod_path; + struct grub_mod_syms mod_syms; + struct grub_named_list *m; + + mod_name = grub_util_get_module_name (mods[0]); + mod_path = grub_util_get_module_path (dir, mod_name); + + if (! strcmp (mod_name, "grub-symdb")) + { + free (mod_name); + free (mod_path); + continue; + } + + read_mod_syms (&mod_syms, mod_path); + + m = mod_syms.defs; + while (m) + { + struct grub_symbol_list *sym; + struct grub_named_list *n; + + sym = insert_symbol ((char *) m->name); + insert_string (&sym->defs, mod_name); + + n = sym->unds; + while (n) + { + add_update ((char *) mod_name, (char *) n->name, 1); + n = n->next; + } + + m = m->next; + } + + m = mod_syms.unds; + while (m) + { + struct grub_symbol_list *sym; + struct grub_named_list *n; + + sym = insert_symbol ((char *) m->name); + insert_string (&sym->unds, mod_name); + + n = sym->defs; + while (n) + { + add_update ((char *) n->name, (char *) mod_name, 1); + n = n->next; + } + + m = m->next; + } + + free (mod_name); + free (mod_path); + } +} + +static void +remove_mods (char *mods[]) +{ + for (; mods[0]; mods++) + { + char *mod_name; + struct grub_symbol_list *sym; + + mod_name = grub_util_get_module_name (mods[0]); + + sym = symbol_list; + while (sym) + { + struct grub_named_list *m, *n; + + m = sym->defs; + while (m) + { + int r; + + r = strcmp (mod_name, m->name); + if (! r) + break; + + if (r < 0) + { + m = 0; + break; + } + + m = m->next; + } + + n = sym->unds; + while (n) + { + if (m) + { + add_update ((char *) m->name, (char *) n->name, 0); + } + else + { + int r; + + r = strcmp (mod_name, n->name); + if (! r) + { + m = sym->defs; + while (m) + { + add_update ((char *) m->name, (char *) n->name, 0); + m = m->next; + } + + break; + } + + if (r < 0) + break; + } + + n = n->next; + } + + sym = sym->next; + } + + free (mod_name); + } +} + +static void +dump_update (void) +{ + struct grub_update_list *u; + + u = update_list; + while (u) + { + struct grub_named_list *n; + + printf ("%s:" , u->name); + n = u->add_mods; + while (n) + { + printf (" +%s", n->name); + n = n->next; + } + + n = u->del_mods; + while (n) + { + printf (" -%s", n->name); + n = n->next; + } + + printf ("\n"); + u = u->next; + } +} + +static void +update_deps (struct grub_update_list *u, char *path) +{ + size_t size; + char *image; + Elf_Ehdr *e; + Elf_Off section_offset; + Elf_Half section_entsize; + Elf_Half num_sections; + Elf_Shdr *sections; + Elf_Shdr *moddep_section; + char *strtab, *pb, *pe; + struct grub_named_list *n; + int modified; + + size = grub_util_get_image_size (path); + image = grub_util_read_image (path); + + e = (Elf_Ehdr *) image; + if (! check_elf_header (e, size)) + grub_util_error ("invalid ELF header"); + + section_offset = grub_target_to_host (e->e_shoff); + section_entsize = grub_target_to_host16 (e->e_shentsize); + num_sections = grub_target_to_host16 (e->e_shnum); + + if (size < section_offset + section_entsize * num_sections) + grub_util_error ("invalid ELF format"); + + sections = (Elf_Shdr *) (image + section_offset); + strtab = find_strtab (e, sections, section_entsize); + + moddep_section = find_moddep_section (sections, section_entsize, + num_sections, strtab); + if (! moddep_section) + grub_util_error ("no .moddeps section"); + + pb = (char *) e + grub_target_to_host (moddep_section->sh_offset); + pe = pb + grub_target_to_host32 (moddep_section->sh_size); + while (pb < pe) + { + if (! *pb) + break; + + insert_string (&u->cur_mods, pb); + pb += strlen (pb) + 1; + } + + modified = 0; + n = u->del_mods; + while (n) + { + modified += remove_string (&u->cur_mods, (char *) n->name); + n = n->next; + } + n = u->add_mods; + while (n) + { + modified += insert_string (&u->cur_mods, (char *) n->name); + n = n->next; + } + + if (modified) + { + char *new_image, *p; + int old_size, new_size, delta, ofs; + Elf_Shdr *s; + int i; + FILE *fp; + + new_size = 0; + n = u->cur_mods; + while (n) + { + new_size += strlen (n->name) + 1; + n = n->next; + } + + old_size = (int) grub_target_to_host32 (moddep_section->sh_size); + delta = new_size - old_size ; + + ofs = grub_target_to_host (moddep_section->sh_offset); + new_image = xmalloc ((int) size + delta); + e = (Elf_Ehdr *) new_image; + + memcpy (new_image, image, ofs); + + p = new_image + ofs; + n = u->cur_mods; + while (n) + { + strcpy (p, n->name); + p += strlen (p) + 1; + n = n->next; + } + + if (ofs + old_size < (int) size) + memcpy (p, image + ofs + old_size, (int) size - ofs - old_size); + + if ((int) section_offset > ofs) + { + section_offset = (int) section_offset + delta; + e->e_shoff = grub_host_to_target (section_offset); + } + + sections = (Elf_Shdr *) (new_image + section_offset); + moddep_section = find_moddep_section (sections, section_entsize, + num_sections, strtab); + if (! moddep_section) + grub_util_error ("no .moddeps section"); + + moddep_section->sh_size = grub_host_to_target32 (new_size); + + for (i = 0, s = sections; + i < num_sections; + i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) + { + Elf_Off off; + + off = grub_target_to_host (s->sh_offset); + if ((int) off > ofs) + { + off = (int) off + delta; + s->sh_offset = grub_host_to_target (off); + } + } + + fp = fopen (path, "wb"); + if (! fp) + grub_util_error ("Can\'t write to %s", path); + + grub_util_write_image (new_image, (int) size + delta, fp); + + fclose (fp); + + free (new_image); + } + + free (image); +} + +static void +write_moddep (struct grub_update_list *u, FILE *fp) +{ + struct grub_named_list *n; + + if (! u->cur_mods) + return; + + fprintf (fp, "%s:", u->name); + n = u->cur_mods; + while (n) + { + fprintf (fp, " %s", n->name); + n = n->next; + } + + fprintf (fp, "\n"); + free_named_list (&u->cur_mods); +} + +static void +update_moddep (char *dir) +{ + FILE *fp; + struct stat st; + char *path, *image; + struct grub_update_list *u; + + path = grub_util_get_path (dir, "moddep.lst"); + image = (stat (path, &st) == 0) ? grub_util_read_image (path) : 0; + + fp = fopen (path, "w"); + if (! fp) + grub_util_error ("Can\'t write to ", path); + + if (image) + { + char *line; + + line = image; + while (*line) + { + char *p, *c; + int n; + + n = strcspn (line, "\r\n"); + p = line; + + line += n; + while ((*line == '\r') || (*line == '\n')) + line++; + + *(p + n) = 0; + + c = strchr (p, ':'); + if (! c) + continue; + + *c = 0; + u = update_list; + while (u) + { + int r; + + r = strcmp (p, u->name); + if (! r) + break; + + if (r < 0) + { + u = 0; + break; + } + + u = u->next; + } + *c = ':'; + + if (u) + write_moddep (u, fp); + else + fprintf (fp, "%s\n", p); + } + } + + + u = update_list; + while (u) + { + write_moddep (u, fp); + u = u->next; + } + + fclose (fp); + free (path); + free (image); +} + +static void +apply_update (char *dir) +{ + struct grub_update_list *u; + + u = update_list; + while (u) + { + char *mod_path; + + mod_path = grub_util_get_module_path (dir, u->name); + update_deps (u, mod_path); + free (mod_path); + u = u->next; + } + + update_moddep (dir); +} + +static struct option options[] = + { + {"directory", required_argument, 0, 'd'}, + {"test", no_argument, 0, 't'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} + }; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try ``grub-symdb --help'' for more information.\n"); + else + printf ("\ +Usage: grub-symdb [OPTION]... COMMAND\n\ +\n\ +Manage the symbol database of GRUB.\n\ +\nCommands:\n\ + update MODULES add/update modules to the symbol database\n\ + remove MODULES remove modules from the symbol databsae\n\ + check check for duplicate and unresolved symbols\n\ +\n\ + -d, --directory=DIR use images and modules under DIR [default=%s]\n\ + -t, --test test mode\n\ + -h, --help display this message and exit\n\ + -V, --version print version information and exit\n\ + -v, --verbose print verbose messages\n\ +\n\ +Report bugs to <%s>.\n\ +", GRUB_LIBDIR, PACKAGE_BUGREPORT); + + exit (status); +} + +int +main (int argc, char *argv[]) +{ + char *dir = NULL; + char *path; + int test_mode = 0; + + progname = "grub-symdb"; + + while (1) + { + int c = getopt_long (argc, argv, "d:thVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'd': + if (dir) + free (dir); + + dir = xstrdup (optarg); + break; + + case 't': + test_mode++; + break; + + case 'h': + usage (0); + break; + + case 'V': + printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + if (! dir) + dir = xstrdup (GRUB_LIBDIR); + + path = grub_util_get_path (dir, "modsym.lst"); + + argv += optind; + argc -= optind; + if (argc == 0) + grub_util_error ("No command specified."); + + read_symdb (path); + if (! strcmp (argv[0], "update")) + { + remove_mods (argv + 1); + update_mods (argv + 1, dir); + if (test_mode) + dump_update (); + else + { + apply_update (dir); + write_symdb (path); + } + } + else if (! strcmp (argv[0], "remove")) + { + remove_mods (argv + 1); + if (test_mode) + dump_update (); + else + { + apply_update (dir); + write_symdb (path); + } + } + else if (! strcmp (argv[0], "check")) + { + check_symdb (); + } + else + grub_util_error ("Unkown command %s.", argv[0]); + + free (path); + free (dir); + + return 0; +} diff --git a/util/resolve.c b/util/resolve.c index 85aec72..37ee020 100644 --- a/util/resolve.c +++ b/util/resolve.c @@ -126,8 +126,8 @@ read_dep_list (FILE *fp) return dep_list; } -static char * -get_module_name (const char *str) +char * +grub_util_get_module_name (const char *str) { char *base; char *ext; @@ -152,8 +152,8 @@ get_module_name (const char *str) return xstrdup (base); } -static char * -get_module_path (const char *prefix, const char *str) +char * +grub_util_get_module_path (const char *prefix, const char *str) { char *dir; char *base; @@ -190,7 +190,7 @@ add_module (const char *dir, struct mod_list *mod; struct dep_list *dep; - mod_name = get_module_name (name); + mod_name = grub_util_get_module_name (name); /* Check if the module has already been added. */ for (mod = *mod_head; mod; mod = mod->next) @@ -218,7 +218,7 @@ add_module (const char *dir, /* Add this path. */ path = (struct grub_util_path_list *) xmalloc (sizeof (*path)); - path->name = get_module_path (dir, name); + path->name = grub_util_get_module_path (dir, name); path->next = *path_head; *path_head = path; }