diff --git a/ChangeLog b/ChangeLog index 18b20b6fc..57ed9af6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +1999-10-18 OKUJI Yoshinori + + * Makefile.am (SUBDIRS): Added util. + * configure.in: Output util/Makefile. + * util/Makefile.am: New file. + * util/mbchk.c: Likewise. + * util/Makefile.in: Likewise. Generated by automake. + 1999-10-17 OKUJI Yoshinori * docs/Makefile.am (.texi): Canceled because the dependecies can diff --git a/Makefile.am b/Makefile.am index d2bf7292a..5d96c204e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ # Do not change this order if you don't know what you are doing. -SUBDIRS = netboot stage2 stage1 lib grub docs debian +SUBDIRS = netboot stage2 stage1 lib grub util docs debian EXTRA_DIST = BUGS # We get $(PACKAGE) and $(VERSION) from debian/changelog. diff --git a/Makefile.in b/Makefile.in index 5b18e08a3..9b85d9285 100644 --- a/Makefile.in +++ b/Makefile.in @@ -84,7 +84,7 @@ install_sh = @install_sh@ # Do not change this order if you don't know what you are doing. -SUBDIRS = netboot stage2 stage1 lib grub docs debian +SUBDIRS = netboot stage2 stage1 lib grub util docs debian EXTRA_DIST = BUGS subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 diff --git a/NEWS b/NEWS index 393a40907..ff5dcd926 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ New in 0.5.94: exists. If not found, try to create it based on the guessed information. * NetBSD support in the grub shell is improved. +* A simple checker for the format of a Multiboot kernel, ``mbchk'', is + added. New in 0.5.93: * ELF format of FreeBSD kernel is supported. diff --git a/configure b/configure index 663e9bfa8..249eaa996 100644 --- a/configure +++ b/configure @@ -2436,7 +2436,8 @@ ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo "Makefile stage1/Makefile stage2/Makefile docs/Makefile \ - debian/Makefile lib/Makefile grub/Makefile netboot/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 + debian/Makefile lib/Makefile util/Makefile grub/Makefile \ + netboot/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then diff --git a/configure.in b/configure.in index afea6d9d7..5ee2766d6 100644 --- a/configure.in +++ b/configure.in @@ -283,4 +283,5 @@ AC_SUBST(NET_EXTRAFLAGS) # Output. AC_OUTPUT([Makefile stage1/Makefile stage2/Makefile docs/Makefile \ - debian/Makefile lib/Makefile grub/Makefile netboot/Makefile]) + debian/Makefile lib/Makefile util/Makefile grub/Makefile \ + netboot/Makefile]) diff --git a/docs/Makefile.in b/docs/Makefile.in index 6cd5749d0..98a8d0f89 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -402,6 +402,8 @@ distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean distclean maintainer-clean +# Cancel the rule %.texi -> %. This rule may confuse make to determine +# the dependecies. .texi: %.c.texi: %.c $(srcdir)/$(SRC2TEXI) diff --git a/util/Makefile.am b/util/Makefile.am new file mode 100644 index 000000000..5d8c83868 --- /dev/null +++ b/util/Makefile.am @@ -0,0 +1,7 @@ +bin_PROGRAMS = mbchk + +# XXX: Need to search for a header file in docs, because of multiboot.h. +AM_CFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/docs + +mbchk_SOURCES = mbchk.c +mbchk_LDADD = ../lib/libcommon.a diff --git a/util/Makefile.in b/util/Makefile.in new file mode 100644 index 000000000..f37541702 --- /dev/null +++ b/util/Makefile.in @@ -0,0 +1,335 @@ +# Makefile.in generated automatically by automake 1.4a from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_FLAG = +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AMTAR = @AMTAR@ +AMTARFLAGS = @AMTARFLAGS@ +AWK = @AWK@ +CC = @CC@ +FSYS_CFLAGS = @FSYS_CFLAGS@ +GRUB_CFLAGS = @GRUB_CFLAGS@ +GRUB_LIBS = @GRUB_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NET_CFLAGS = @NET_CFLAGS@ +NET_EXTRAFLAGS = @NET_EXTRAFLAGS@ +OBJCOPY = @OBJCOPY@ +PACKAGE = @PACKAGE@ +PERL = @PERL@ +RANLIB = @RANLIB@ +STAGE1_CFLAGS = @STAGE1_CFLAGS@ +STAGE2_CFLAGS = @STAGE2_CFLAGS@ +VERSION = @VERSION@ +host_cpu = @host_cpu@ +host_vendor = @host_vendor@ +install_sh = @install_sh@ + + +bin_PROGRAMS = mbchk + +# XXX: Need to search for a header file in docs, because of multiboot.h. +AM_CFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/docs + +mbchk_SOURCES = mbchk.c +mbchk_LDADD = ../lib/libcommon.a +subdir = util +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +am_mbchk_OBJECTS = mbchk.o +mbchk_OBJECTS = $(am_mbchk_OBJECTS) +mbchk_DEPENDENCIES = ../lib/libcommon.a +mbchk_LDFLAGS = +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CFLAGS = @CFLAGS@ +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(mbchk_SOURCES) +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +DEP_FILES = .deps/mbchk.P +SOURCES = $(mbchk_SOURCES) +OBJECTS = $(am_mbchk_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .c .o +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu util/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + f="`echo $$p|sed -e 's/$(EXEEXT)$$//' -e '$(transform)' -e 's/$$/$(EXEEXT)/'`"; \ + echo " $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/$$f"; \ + $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/$$f; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f="`echo $$p|sed -e 's/$(EXEEXT)$$//' -e '$(transform)' -e 's/$$/$(EXEEXT)/'`"; \ + echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ + rm -f $(DESTDIR)$(bindir)/$$f; \ + done + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +mbchk: $(mbchk_OBJECTS) $(mbchk_DEPENDENCIES) + @rm -f mbchk + $(LINK) $(mbchk_LDFLAGS) $(mbchk_OBJECTS) $(mbchk_LDADD) $(LIBS) +.c.o: + $(COMPILE) -c $< + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu util/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c -o $@ $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $< + @-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \ + tr ' ' '\012' < .deps/$(*D)/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*D)/$(*F).P; \ + rm .deps/$(*D)/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c -o $@ $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \ + tr ' ' '\012' < .deps/$(*D)/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*D)/$(*F).P; \ + rm -f .deps/$(*D)/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-binPROGRAMS +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-binPROGRAMS +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-binPROGRAMS clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \ + distclean-depend distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all install-strip \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/util/mbchk.c b/util/mbchk.c new file mode 100644 index 000000000..b39b29a40 --- /dev/null +++ b/util/mbchk.c @@ -0,0 +1,244 @@ +/* mbchk - a simple checker for the format of a Multiboot kernel */ +/* + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * 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 + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include + +static int quiet = 0; +static char *optstring = "hvq"; +static struct option longopts[] = +{ + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {"quiet", no_argument, 0, 'q'}, + {0} +}; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try ``mbchk --help'' for more information.\n"); + else + printf ("Usage: mbchk [OPTION]... [FILE]... +Check if the format of FILE complies with the Multiboot Specification. + + -q, --quiet suppress all normal output + -h, --help display this help and exit + -v, --version output version information and exit. + +Report bugs to . +"); + + exit (status); +} + +static int +check_multiboot (const char *filename, FILE *fp) +{ + multiboot_header_t *mbh = 0; + int i; + char buf[8192]; + + if (fread (buf, 1, 8192, fp) < 0) + { + fprintf (stderr, "%s: Read error.\n", filename); + return 0; + } + + for (i = 0; i < 8192 - sizeof (multiboot_header_t); i++) + { + unsigned long magic = *((unsigned long *) (buf + i)); + + if (magic == MULTIBOOT_HEADER_MAGIC) + { + mbh = (multiboot_header_t *) (buf + i); + break; + } + } + + if (! mbh) + { + fprintf (stderr, "%s: No Multiboot header.\n", filename); + return 0; + } + + if (! quiet) + printf ("%s: The Multiboot header is found at the offset %d.\n", + filename, i); + + /* Check for the checksum. */ + if (mbh->magic + mbh->flags + mbh->checksum != 0) + { + fprintf (stderr, + "%s: Bad checksum (0x%lx).\n", + filename, mbh->checksum); + return 0; + } + + /* Reserved flags must be zero. */ + if (mbh->flags & ~0x00010003) + { + fprintf (stderr, + "%s: Non-zero is found in reserved flags (0x%lx).\n", + filename, mbh->flags); + return 0; + } + + if (! quiet) + { + printf ("%s: Page alignment is turned %s.\n", + filename, (mbh->flags & 0x1)? "on" : "off"); + printf ("%s: Memory information is turned %s.\n", + filename, (mbh->flags & 0x2)? "on" : "off"); + printf ("%s: Address fields is turned %s.\n", + filename, (mbh->flags & 0x10000)? "on" : "off"); + } + + /* Check for the address fields. */ + if (mbh->flags & 0x10000) + { + if (mbh->header_addr < mbh->load_addr) + { + fprintf (stderr, + "%s: header_addr is less than " + "load_addr (0x%lx > 0x%lx).\n", + filename, mbh->header_addr, mbh->load_addr); + return 0; + } + + if (mbh->load_addr >= mbh->load_end_addr) + { + fprintf (stderr, + "%s: load_addr is not less than load_end_addr" + " (0x%lx >= 0x%lx).\n", + filename, mbh->load_addr, mbh->load_end_addr); + return 0; + } + + if (mbh->load_end_addr > mbh->bss_end_addr) + { + fprintf (stderr, + "%s: load_end_addr is greater than bss_end_addr" + " (0x%lx > 0x%lx).\n", + filename, mbh->load_end_addr, mbh->bss_end_addr); + return 0; + } + + if (mbh->load_addr > mbh->entry_addr) + { + fprintf (stderr, + "%s: load_addr is greater than entry_addr" + " (0x%lx > 0x%lx).\n", + filename, mbh->load_addr, mbh->entry_addr); + return 0; + } + + if (mbh->load_end_addr <= mbh->entry_addr) + { + fprintf (stderr, + "%s: load_end_addr is not less than entry_addr" + " (0x%lx <= 0x%lx).\n", + filename, mbh->load_end_addr, mbh->entry_addr); + return 0; + } + + /* This is a GRUB-specific limitation. */ + if (mbh->load_addr < 0x100000) + { + fprintf (stderr, + "%s: Cannot be loaded at less than 1MB by GRUB" + " (0x%lx).\n", + filename, mbh->load_addr); + return 0; + } + } + + if (! quiet) + printf ("%s: All checks passed.\n", filename); + + return 1; +} + +int +main (int argc, char *argv[]) +{ + int c; + + do + { + c = getopt_long (argc, argv, optstring, longopts, 0); + switch (c) + { + case EOF: + break; + + case 'h': + usage (0); + break; + + case 'v': + printf ("mbchk (GNU GRUB) " VERSION "\n"); + exit (0); + break; + + case 'q': + quiet = 1; + break; + + default: + usage (1); + break; + } + } + while (c != EOF); + + if (optind < argc) + { + while (optind < argc) + { + FILE *fp; + + fp = fopen (argv[optind], "r"); + if (! fp) + { + fprintf (stderr, "%s: No such file.\n", argv[optind]); + exit (1); + } + + if (! check_multiboot (argv[optind], fp)) + exit (1); + + fclose (fp); + optind++; + } + } + else + { + if (! check_multiboot ("", stdin)) + exit (1); + } + + return 0; +} + +