On Thu, 12 Aug 2010, Robert Millan wrote:
> 2010/8/10, Scott Moser <scott.mo...@canonical.com>:
> > Hi all,
> > I've been playing around with multiboot images, and found grub 0.97's
> > 'mbchk' to be very useful. Its really nice from a shell script or other
> > to easily answer "is this file a multiboot image?".
> >
> > The attached patch basically copies mbchk.c from grub-0.97 to current
> > bzr with minimal changes.
> > Is that something that could be carried in grub2 ?
>
> I think it would make more sense in multiboot itself (multiboot package
> doesn't just include documentation, there's also sample C code and
> such).
Well, I would prefer it in grub, but admittedly, that is for reasons other
than "its the best place for it". Being part of the grub package means it
would be likely installed on systems and easy to use. I won't disagree
that 'multiboot' is probably a better place, but will suggest that it is
less discoverable.
Attached is a patch against multiboot-0.6.96 to add a 'tools/' subdir and
'mbchk.c' to that. The reason for the tools/ dir rather than putting it
into examples was to allow to examples/ dir to continue using '-m32' on
all c files. I couldn't see an easy way to work around that otherwise.
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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <multiboot.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+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>", stdin))
+ exit (1);
+ }
+ return 0;
+}
+
+
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel