Index: multiboot-0.6.96/Makefile =================================================================== --- multiboot-0.6.96.orig/Makefile 2010-08-16 11:23:31.577581150 -0400 +++ multiboot-0.6.96/Makefile 2010-08-16 11:23:50.000000000 -0400 @@ -188,7 +188,7 @@ # Do not change this order if you don't know what you are doing. AUTOMAKE_OPTIONS = 1.7 gnu -SUBDIRS = docs +SUBDIRS = docs tools all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive Index: multiboot-0.6.96/Makefile.am =================================================================== --- multiboot-0.6.96.orig/Makefile.am 2010-08-16 11:20:26.017581151 -0400 +++ multiboot-0.6.96/Makefile.am 2010-08-16 11:23:43.247581150 -0400 @@ -1,3 +1,3 @@ # Do not change this order if you don't know what you are doing. AUTOMAKE_OPTIONS = 1.7 gnu -SUBDIRS = docs +SUBDIRS = docs tools Index: multiboot-0.6.96/configure.ac =================================================================== --- multiboot-0.6.96.orig/configure.ac 2010-08-16 11:20:25.957581151 -0400 +++ multiboot-0.6.96/configure.ac 2010-08-16 11:22:24.807581151 -0400 @@ -18,7 +18,7 @@ AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE -CFLAGS="-m32 $CFLAGS" +CFLAGS="$CFLAGS" # # Programs @@ -46,5 +46,5 @@ dnl Output. -AC_CONFIG_FILES([Makefile docs/Makefile]) +AC_CONFIG_FILES([Makefile docs/Makefile tools/Makefile]) AC_OUTPUT Index: multiboot-0.6.96/docs/Makefile.am =================================================================== --- multiboot-0.6.96.orig/docs/Makefile.am 2010-08-16 11:20:26.027581151 -0400 +++ multiboot-0.6.96/docs/Makefile.am 2010-08-16 11:21:48.057581151 -0400 @@ -1,3 +1,5 @@ +AM_CFLAGS = -m32 + info_TEXINFOS = multiboot.texi EXAMPLES = boot.S kernel.c multiboot.h multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi Index: multiboot-0.6.96/tools/Makefile.am =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ multiboot-0.6.96/tools/Makefile.am 2010-08-16 11:21:28.000000000 -0400 @@ -0,0 +1,5 @@ +bin_PROGRAMS = mbchk + +AM_CPPFLAGS = -I$(top_builddir)/docs + +mbchk_SOURCES = mbchk.c multiboot.h Index: multiboot-0.6.96/tools/mbchk.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ multiboot-0.6.96/tools/mbchk.c 2010-08-16 11:21:28.000000000 -0400 @@ -0,0 +1,257 @@ +/* mbchk.c - a simple checker for the format of a Multiboot kernel */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2001,2002,2010 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +#include +#include +#include +#include +#include + +const char *program_name = NULL; + +static int quiet = 0; +static char *optstring = "hvq"; +static struct option options[] = +{ + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"quiet", no_argument, 0, 'q'}, + {0, 0, 0, 0} +}; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + else + printf ("\ +Usage: %s [OPTION]... [FILENAME]...\n\ +Check if the format of FILENAME complies with the Multiboot Specification.\n\ +\n\ +\nOptions:\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\ +If not given explicitly, FILENAME defaults to standard input.\n\ +\n\ +Report bugs to <%s>.\n", +program_name, PACKAGE_BUGREPORT); + exit (status); +} + +static int +check_multiboot (const char *filename, FILE *fp) +{ + struct multiboot_header *mbh = 0; + unsigned int i; + char buf[8192]; + + memset(buf, 0, 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++) + { + multiboot_uint32_t magic = *((multiboot_uint32_t *) (buf + i)); + + if (magic == MULTIBOOT_HEADER_MAGIC) + { + mbh = (struct multiboot_header *) (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%x).\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%x).\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%x > 0x%x).\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%x >= 0x%x).\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%x > 0x%x).\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%x > 0x%x).\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%x <= 0x%x).\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%x).\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; + + program_name = "mbchk"; + + do + { + c = getopt_long (argc, argv, optstring, options, 0); + switch (c) + { + case EOF: + break; + + case 'h': + usage (0); + break; + + case 'V': + printf ("%s (GNU GRUB " VERSION ")\n", program_name); + 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; +} + +