From 2ee333d0209eb277aeb8483db1316843b05c60d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 17:15:37 +0200 Subject: [PATCH] Reimport mbchk. * util/Makefile.am: New file. * util/mbchk.c: Likewise. * Makefile.am (SUBDIRS): Add util. * configure.ac: New options --enable-mbchk. Check for HELP2MAN. (CFLAGS): Don't alter. (COND_MAN_PAGES): New conditional. (AC_CONFIG_FILES): Add util/Makefile. * doc/Makefile.am (kernel_CFLAGS): Add -m32 and -nostdlib. * doc/multiboot.texi (Invoking mbchk): New chapter. --- ChangeLog | 14 +++ Makefile.am | 2 +- configure.ac | 13 ++- doc/Makefile.am | 2 +- doc/multiboot.texi | 25 ++++- util/Makefile.am | 17 ++++ util/mbchk.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 297 insertions(+), 6 deletions(-) create mode 100644 util/Makefile.am create mode 100644 util/mbchk.c diff --git a/ChangeLog b/ChangeLog index 09068870f..1cb200f9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2010-09-03 Vladimir Serbinenko + + Reimport mbchk. + + * util/Makefile.am: New file. + * util/mbchk.c: Likewise. + * Makefile.am (SUBDIRS): Add util. + * configure.ac: New options --enable-mbchk. Check for HELP2MAN. + (CFLAGS): Don't alter. + (COND_MAN_PAGES): New conditional. + (AC_CONFIG_FILES): Add util/Makefile. + * doc/Makefile.am (kernel_CFLAGS): Add -m32 and -nostdlib. + * doc/multiboot.texi (Invoking mbchk): New chapter. + 2010-03-14 Vladimir Serbinenko * doc/kernel.c (cmain): Use padding to properly display 64-bit diff --git a/Makefile.am b/Makefile.am index 70eec9cd0..6d6f55ba3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ # Do not change this order if you don't know what you are doing. AUTOMAKE_OPTIONS = 1.7 gnu -SUBDIRS = doc +SUBDIRS = doc util .PHONY: web-manual web-manual: all diff --git a/configure.ac b/configure.ac index bf1511eba..5482aeff8 100644 --- a/configure.ac +++ b/configure.ac @@ -42,8 +42,17 @@ dnl Because recent automake complains about CCASFLAGS, set it here. CCASFLAGS='$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)' AC_SUBST(CCASFLAGS) -CFLAGS="-m32 -nostdlib $CFLAGS" +AC_ARG_ENABLE(mbchk, + [ --enable-mbchk + build the mbchk (multiboot checker)]) +AM_CONDITIONAL(BUILD_MBCHK, test "x$enable_mbchk" = xyes) + +if test "x$enable_mbchk" = xyes; then + AC_PATH_PROG(HELP2MAN, help2man) +fi + +AM_CONDITIONAL([COND_MAN_PAGES], [test x$enable_mbchk = xyes -a x$HELP2MAN != x]) dnl Output. -AC_CONFIG_FILES([Makefile doc/Makefile]) +AC_CONFIG_FILES([Makefile doc/Makefile util/Makefile]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am index 787a99eca..dd65301de 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -10,7 +10,7 @@ pkginclude_HEADERS = multiboot.h if BUILD_EXAMPLE_KERNEL noinst_PROGRAMS = kernel kernel_SOURCES = $(EXAMPLES) -kernel_CFLAGS = -fno-builtin -nostdinc -O -g -Wall \ +kernel_CFLAGS = -m32 -nostdlib -fno-builtin -nostdinc -O -g -Wall \ -imacros $(top_builddir)/config.h kernel_LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,100000 -Wl,--build-id=none diff --git a/doc/multiboot.texi b/doc/multiboot.texi index 631897a15..11e8b8c5d 100644 --- a/doc/multiboot.texi +++ b/doc/multiboot.texi @@ -77,8 +77,9 @@ sequence standard. This edition documents version @value{VERSION}. * Terminology:: * Specification:: * Examples:: -* History:: -* Index:: +* History:: +* Invoking mbchk:: How to use the Multiboot checker +* Index:: @end menu @@ -1279,6 +1280,26 @@ Major changes plus HTMLification. @end itemize @end table +@node Invoking mbchk +@chapter Invoking mbchk + +The program @command{mbchk} checks for the format of a Multiboot +kernel. We recommend using this program before booting your own kernel. + +@command{mbchk} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item --quiet +Suppress all normal output. +@end table + + @node Index @unnumbered Index diff --git a/util/Makefile.am b/util/Makefile.am new file mode 100644 index 000000000..812f118af --- /dev/null +++ b/util/Makefile.am @@ -0,0 +1,17 @@ + +HELP2MAN = @HELP2MAN@ +if COND_MAN_PAGES +man_MANS = mbchk.1 +endif + +if BUILD_MBCHK +bin_PROGRAMS = mbchk +endif + +mbchk_SOURCES = mbchk.c +mbchk_CPPFLAGS = -I$(top_srcdir)/doc + +$(srcdir)/mbchk.1: ./mbchk + $(HELP2MAN) \ + --name="check the format of a Multiboot kernel" \ + --section=1 --output=$@ ./$< diff --git a/util/mbchk.c b/util/mbchk.c new file mode 100644 index 000000000..766e2c436 --- /dev/null +++ b/util/mbchk.c @@ -0,0 +1,230 @@ +/* mbchk - a simple checker for the format of a Multiboot kernel */ +/* + * Copyright (C) 1999,2001,2002 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 +#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]...\n" + "Check if the format of FILE complies with the Multiboot Specification.\n" + "\n" + "-q, --quiet suppress all normal output\n" + "-h, --help display this help and exit\n" + "-v, --version output version information and exit.\n" + "\n" + "Report bugs to .\n"); + + exit (status); +} + +static int +check_multiboot (const char *filename, FILE *fp) +{ + struct multiboot_header *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 (struct multiboot_header); i++) + { + mbh = (struct multiboot_header *) (buf + i); + if (mbh->magic == MULTIBOOT_HEADER_MAGIC) + break; + } + + if (i == 8192 - sizeof (struct multiboot_header)) + { + 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_end_addr && 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->bss_end_addr && 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; + } + + /* FIXME: It is better to check if the entry address is within the + file, especially when the load end address is zero. */ + if (mbh->load_end_addr && mbh->load_end_addr <= mbh->entry_addr) + { + fprintf (stderr, + "%s: load_end_addr is not greater than entry_addr" + " (0x%lx <= 0x%lx).\n", + filename, mbh->load_end_addr, mbh->entry_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; +} + -- 2.47.2