~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grub4dos/util/.svn/text-base/mbchk.c.svn-base

  • Committer: Howard Chan
  • Date: 2012-11-20 10:16:05 UTC
  • Revision ID: smartboyhw@gmail.com-20121120101605-qfmjfsdynpzg9an9
Added images

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* mbchk - a simple checker for the format of a Multiboot kernel */
2
 
/*
3
 
 *  Copyright (C) 1999,2001,2002  Free Software Foundation, Inc.
4
 
 *
5
 
 *  This program is free software; you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation; either version 2 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 
 */
19
 
 
20
 
#include <config.h>
21
 
 
22
 
#include <stdio.h>
23
 
#include <stdlib.h>
24
 
#include <getopt.h>
25
 
#include <multiboot.h>
26
 
 
27
 
static int quiet = 0;
28
 
static char *optstring = "hvq";
29
 
static struct option longopts[] =
30
 
{
31
 
  {"help", no_argument, 0, 'h'},
32
 
  {"version", no_argument, 0, 'v'},
33
 
  {"quiet", no_argument, 0, 'q'},
34
 
  {0}
35
 
};
36
 
 
37
 
static void
38
 
usage (int status)
39
 
{
40
 
  if (status)
41
 
    fprintf (stderr, "Try ``mbchk --help'' for more information.\n");
42
 
  else
43
 
    printf ("Usage: mbchk [OPTION]... [FILE]...\n"
44
 
            "Check if the format of FILE complies with the Multiboot Specification.\n"
45
 
            "\n"
46
 
            "-q, --quiet                suppress all normal output\n"
47
 
            "-h, --help                 display this help and exit\n"
48
 
            "-v, --version              output version information and exit.\n"
49
 
            "\n"
50
 
            "Report bugs to <bug-grub@gnu.org>.\n");
51
 
 
52
 
  exit (status);
53
 
}
54
 
 
55
 
static int
56
 
check_multiboot (const char *filename, FILE *fp)
57
 
{
58
 
  multiboot_header_t *mbh = 0;
59
 
  int i;
60
 
  char buf[8192];
61
 
 
62
 
  if (fread (buf, 1, 8192, fp) < 0)
63
 
    {
64
 
      fprintf (stderr, "%s: Read error.\n", filename);
65
 
      return 0;
66
 
    }
67
 
 
68
 
  for (i = 0; i < 8192 - sizeof (multiboot_header_t); i++)
69
 
    {
70
 
      unsigned long magic = *((unsigned long *) (buf + i));
71
 
 
72
 
      if (magic == MULTIBOOT_HEADER_MAGIC)
73
 
        {
74
 
          mbh = (multiboot_header_t *) (buf + i);
75
 
          break;
76
 
        }
77
 
    }
78
 
 
79
 
  if (! mbh)
80
 
    {
81
 
      fprintf (stderr, "%s: No Multiboot header.\n", filename);
82
 
      return 0;
83
 
    }
84
 
 
85
 
  if (! quiet)
86
 
    printf ("%s: The Multiboot header is found at the offset %d.\n",
87
 
            filename, i);
88
 
 
89
 
  /* Check for the checksum.  */
90
 
  if (mbh->magic + mbh->flags + mbh->checksum != 0)
91
 
    {
92
 
      fprintf (stderr,
93
 
               "%s: Bad checksum (0x%lx).\n",
94
 
               filename, mbh->checksum);
95
 
      return 0;
96
 
    }
97
 
 
98
 
  /* Reserved flags must be zero.  */
99
 
  if (mbh->flags & ~0x00010003)
100
 
    {
101
 
      fprintf (stderr,
102
 
               "%s: Non-zero is found in reserved flags (0x%lx).\n",
103
 
               filename, mbh->flags);
104
 
      return 0;
105
 
    }
106
 
 
107
 
  if (! quiet)
108
 
    {
109
 
      printf ("%s: Page alignment is turned %s.\n",
110
 
              filename, (mbh->flags & 0x1)? "on" : "off");
111
 
      printf ("%s: Memory information is turned %s.\n",
112
 
              filename, (mbh->flags & 0x2)? "on" : "off");
113
 
      printf ("%s: Address fields is turned %s.\n",
114
 
              filename, (mbh->flags & 0x10000)? "on" : "off");
115
 
    }
116
 
 
117
 
  /* Check for the address fields.  */
118
 
  if (mbh->flags & 0x10000)
119
 
    {
120
 
      if (mbh->header_addr < mbh->load_addr)
121
 
        {
122
 
          fprintf (stderr,
123
 
                   "%s: header_addr is less than "
124
 
                   "load_addr (0x%lx > 0x%lx).\n",
125
 
                   filename, mbh->header_addr, mbh->load_addr);
126
 
          return 0;
127
 
        }
128
 
 
129
 
      if (mbh->load_end_addr && mbh->load_addr >= mbh->load_end_addr)
130
 
        {
131
 
          fprintf (stderr,
132
 
                   "%s: load_addr is not less than load_end_addr"
133
 
                   " (0x%lx >= 0x%lx).\n",
134
 
                   filename, mbh->load_addr, mbh->load_end_addr);
135
 
          return 0;
136
 
        }
137
 
 
138
 
      if (mbh->bss_end_addr && mbh->load_end_addr > mbh->bss_end_addr)
139
 
        {
140
 
          fprintf (stderr,
141
 
                   "%s: load_end_addr is greater than bss_end_addr"
142
 
                   " (0x%lx > 0x%lx).\n",
143
 
                   filename, mbh->load_end_addr, mbh->bss_end_addr);
144
 
          return 0;
145
 
        }
146
 
 
147
 
      if (mbh->load_addr > mbh->entry_addr)
148
 
        {
149
 
          fprintf (stderr,
150
 
                   "%s: load_addr is greater than entry_addr"
151
 
                   " (0x%lx > 0x%lx).\n",
152
 
                   filename, mbh->load_addr, mbh->entry_addr);
153
 
          return 0;
154
 
        }
155
 
 
156
 
      /* FIXME: It is better to check if the entry address is within the
157
 
         file, especially when the load end address is zero.  */
158
 
      if (mbh->load_end_addr && mbh->load_end_addr <= mbh->entry_addr)
159
 
        {
160
 
          fprintf (stderr,
161
 
                   "%s: load_end_addr is not greater than entry_addr"
162
 
                   " (0x%lx <= 0x%lx).\n",
163
 
                   filename, mbh->load_end_addr, mbh->entry_addr);
164
 
          return 0;
165
 
        }
166
 
 
167
 
      /* This is a GRUB-specific limitation.  */
168
 
      if (mbh->load_addr < 0x100000)
169
 
        {
170
 
          fprintf (stderr,
171
 
                   "%s: Cannot be loaded at less than 1MB by GRUB"
172
 
                   " (0x%lx).\n",
173
 
                   filename, mbh->load_addr);
174
 
          return 0;
175
 
        }
176
 
    }
177
 
 
178
 
  if (! quiet)
179
 
    printf ("%s: All checks passed.\n", filename);
180
 
 
181
 
  return 1;
182
 
}
183
 
 
184
 
int
185
 
main (int argc, char *argv[])
186
 
{
187
 
  int c;
188
 
 
189
 
  do
190
 
    {
191
 
      c = getopt_long (argc, argv, optstring, longopts, 0);
192
 
      switch (c)
193
 
        {
194
 
        case EOF:
195
 
          break;
196
 
 
197
 
        case 'h':
198
 
          usage (0);
199
 
          break;
200
 
 
201
 
        case 'v':
202
 
          printf ("mbchk (GNU GRUB " VERSION ")\n");
203
 
          exit (0);
204
 
          break;
205
 
 
206
 
        case 'q':
207
 
          quiet = 1;
208
 
          break;
209
 
 
210
 
        default:
211
 
          usage (1);
212
 
          break;
213
 
        }
214
 
    }
215
 
  while (c != EOF);
216
 
 
217
 
  if (optind < argc)
218
 
    {
219
 
      while (optind < argc)
220
 
        {
221
 
          FILE *fp;
222
 
 
223
 
          fp = fopen (argv[optind], "r");
224
 
          if (! fp)
225
 
            {
226
 
              fprintf (stderr, "%s: No such file.\n", argv[optind]);
227
 
              exit (1);
228
 
            }
229
 
 
230
 
          if (! check_multiboot (argv[optind], fp))
231
 
            exit (1);
232
 
 
233
 
          fclose (fp);
234
 
          optind++;
235
 
        }
236
 
    }
237
 
  else
238
 
    {
239
 
      if (! check_multiboot ("<stdin>", stdin))
240
 
        exit (1);
241
 
    }
242
 
 
243
 
  return 0;
244
 
}