~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/commands/file.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2013-12-26 00:52:47 UTC
  • mto: (17.6.37 experimental)
  • mto: This revision was merged to the branch mainline in revision 184.
  • Revision ID: package-import@ubuntu.com-20131226005247-dalaa9te0g0d49kd
Tags: upstream-2.02~beta2
ImportĀ upstreamĀ versionĀ 2.02~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2013  Free Software Foundation, Inc.
 
4
 *
 
5
 *  GRUB 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 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <grub/dl.h>
 
20
#include <grub/misc.h>
 
21
#include <grub/mm.h>
 
22
#include <grub/env.h>
 
23
#include <grub/command.h>
 
24
#include <grub/extcmd.h>
 
25
#include <grub/i18n.h>
 
26
#include <grub/file.h>
 
27
#include <grub/elf.h>
 
28
#include <grub/xen_file.h>
 
29
#include <grub/efi/pe32.h>
 
30
#include <grub/i386/linux.h>
 
31
#include <grub/xnu.h>
 
32
#include <grub/machoload.h>
 
33
#include <grub/fileid.h>
 
34
 
 
35
GRUB_MOD_LICENSE ("GPLv3+");
 
36
 
 
37
static const struct grub_arg_option options[] = {
 
38
  {"is-i386-xen-pae-domu", 0, 0,
 
39
   N_("Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel"),
 
40
   0, 0},
 
41
  {"is-x86_64-xen-domu", 0, 0,
 
42
   N_("Check if FILE can be booted as x86_64 Xen unprivileged guest kernel"), 0, 0},
 
43
  {"is-x86-xen-dom0", 0, 0,
 
44
   N_("Check if FILE can be used as Xen x86 privileged guest kernel"), 0, 0},
 
45
  {"is-x86-multiboot", 0, 0,
 
46
   N_("Check if FILE can be used as x86 multiboot kernel"), 0, 0},
 
47
  {"is-x86-multiboot2", 0, 0,
 
48
   N_("Check if FILE can be used as x86 multiboot2 kernel"), 0, 0},
 
49
  {"is-arm-linux", 0, 0,
 
50
   N_("Check if FILE is ARM Linux"), 0, 0},
 
51
  {"is-arm64-linux", 0, 0,
 
52
   N_("Check if FILE is ARM64 Linux"), 0, 0},
 
53
  {"is-ia64-linux", 0, 0,
 
54
   N_("Check if FILE is IA64 Linux"), 0, 0},
 
55
  {"is-mips-linux", 0, 0,
 
56
   N_("Check if FILE is MIPS Linux"), 0, 0},
 
57
  {"is-mipsel-linux", 0, 0,
 
58
   N_("Check if FILE is MIPSEL Linux"), 0, 0},
 
59
  {"is-sparc64-linux", 0, 0,
 
60
   N_("Check if FILE is SPARC64 Linux"), 0, 0},
 
61
  {"is-powerpc-linux", 0, 0,
 
62
   N_("Check if FILE is POWERPC Linux"), 0, 0},
 
63
  {"is-x86-linux", 0, 0,
 
64
   N_("Check if FILE is x86 Linux"), 0, 0},
 
65
  {"is-x86-linux32", 0, 0,
 
66
   N_("Check if FILE is x86 Linux supporting 32-bit protocol"), 0, 0},
 
67
  {"is-x86-kfreebsd", 0, 0,
 
68
   N_("Check if FILE is x86 kFreeBSD"), 0, 0},
 
69
  {"is-i386-kfreebsd", 0, 0,
 
70
   N_("Check if FILE is i386 kFreeBSD"), 0, 0},
 
71
  {"is-x86_64-kfreebsd", 0, 0,
 
72
   N_("Check if FILE is x86_64 kFreeBSD"), 0, 0},
 
73
 
 
74
  {"is-x86-knetbsd", 0, 0,
 
75
   N_("Check if FILE is x86 kNetBSD"), 0, 0},
 
76
  {"is-i386-knetbsd", 0, 0,
 
77
   N_("Check if FILE is i386 kNetBSD"), 0, 0},
 
78
  {"is-x86_64-knetbsd", 0, 0,
 
79
   N_("Check if FILE is x86_64 kNetBSD"), 0, 0},
 
80
 
 
81
  {"is-i386-efi", 0, 0,
 
82
   N_("Check if FILE is i386 EFI file"), 0, 0},
 
83
  {"is-x86_64-efi", 0, 0,
 
84
   N_("Check if FILE is x86_64 EFI file"), 0, 0},
 
85
  {"is-ia64-efi", 0, 0,
 
86
   N_("Check if FILE is IA64 EFI file"), 0, 0},
 
87
  {"is-arm64-efi", 0, 0,
 
88
   N_("Check if FILE is ARM64 EFI file"), 0, 0},
 
89
  {"is-arm-efi", 0, 0,
 
90
   N_("Check if FILE is ARM EFI file"), 0, 0},
 
91
  {"is-hibernated-hiberfil", 0, 0,
 
92
   N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0},
 
93
  {"is-x86_64-xnu", 0, 0,
 
94
   N_("Check if FILE is x86_64 XNU (Mac OS X kernel)"), 0, 0},
 
95
  {"is-i386-xnu", 0, 0,
 
96
   N_("Check if FILE is i386 XNU (Mac OS X kernel)"), 0, 0},
 
97
  {"is-xnu-hibr", 0, 0,
 
98
   N_("Check if FILE is XNU (Mac OS X kernel) hibernated image"), 0, 0},
 
99
  {"is-x86-bios-bootsector", 0, 0,
 
100
   N_("Check if FILE is BIOS bootsector"), 0, 0},
 
101
  {0, 0, 0, 0, 0, 0}
 
102
};
 
103
 
 
104
enum
 
105
{
 
106
  IS_PAE_DOMU,
 
107
  IS_64_DOMU,
 
108
  IS_DOM0,
 
109
  IS_MULTIBOOT,
 
110
  IS_MULTIBOOT2,
 
111
  IS_ARM_LINUX,
 
112
  IS_ARM64_LINUX,
 
113
  IS_IA64_LINUX,
 
114
  IS_MIPS_LINUX,
 
115
  IS_MIPSEL_LINUX,
 
116
  IS_SPARC64_LINUX,
 
117
  IS_POWERPC_LINUX,
 
118
  IS_X86_LINUX,
 
119
  IS_X86_LINUX32,
 
120
  IS_X86_KFREEBSD,
 
121
  IS_X86_KFREEBSD32,
 
122
  IS_X86_KFREEBSD64,
 
123
  IS_X86_KNETBSD,
 
124
  IS_X86_KNETBSD32,
 
125
  IS_X86_KNETBSD64,
 
126
  IS_32_EFI,
 
127
  IS_64_EFI,
 
128
  IS_IA_EFI,
 
129
  IS_ARM64_EFI,
 
130
  IS_ARM_EFI,
 
131
  IS_HIBERNATED,
 
132
  IS_XNU64,
 
133
  IS_XNU32,
 
134
  IS_XNU_HIBR,
 
135
  IS_BIOS_BOOTSECTOR,
 
136
  OPT_TYPE_MIN = IS_PAE_DOMU,
 
137
  OPT_TYPE_MAX = IS_BIOS_BOOTSECTOR
 
138
};
 
139
 
 
140
 
 
141
static grub_err_t
 
142
grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
 
143
{
 
144
  grub_file_t file = 0;
 
145
  grub_elf_t elf = 0;
 
146
  grub_err_t err;
 
147
  int type = -1, i;
 
148
  int ret = 0;
 
149
  grub_macho_t macho = 0;
 
150
 
 
151
  if (argc == 0)
 
152
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
 
153
  for (i = OPT_TYPE_MIN; i <= OPT_TYPE_MAX; i++)
 
154
    if (ctxt->state[i].set)
 
155
      {
 
156
        if (type == -1)
 
157
          {
 
158
            type = i;
 
159
            continue;
 
160
          }
 
161
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple types specified");
 
162
      }
 
163
  if (type == -1)
 
164
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no type specified");
 
165
 
 
166
  file = grub_file_open (args[0]);
 
167
  if (!file)
 
168
    return grub_errno;
 
169
  switch (type)
 
170
    {
 
171
    case IS_BIOS_BOOTSECTOR:
 
172
      {
 
173
        grub_uint16_t sig;
 
174
        if (grub_file_size (file) != 512)
 
175
          break;
 
176
        if (grub_file_seek (file, 510) == (grub_size_t) -1)
 
177
          break;
 
178
        if (grub_file_read (file, &sig, 2) != 2)
 
179
          break;
 
180
        if (sig != grub_cpu_to_le16_compile_time (0xaa55))
 
181
          break;
 
182
        ret = 1;
 
183
        break;
 
184
      }
 
185
    case IS_IA64_LINUX:
 
186
      {
 
187
        Elf64_Ehdr ehdr;
 
188
 
 
189
        if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
 
190
          break;
 
191
 
 
192
        if (ehdr.e_ident[EI_MAG0] != ELFMAG0
 
193
            || ehdr.e_ident[EI_MAG1] != ELFMAG1
 
194
            || ehdr.e_ident[EI_MAG2] != ELFMAG2
 
195
            || ehdr.e_ident[EI_MAG3] != ELFMAG3
 
196
            || ehdr.e_ident[EI_VERSION] != EV_CURRENT
 
197
            || ehdr.e_version != EV_CURRENT)
 
198
          break;
 
199
 
 
200
        if (ehdr.e_ident[EI_CLASS] != ELFCLASS64
 
201
            || ehdr.e_ident[EI_DATA] != ELFDATA2LSB
 
202
            || ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_IA_64))
 
203
          break;
 
204
 
 
205
        ret = 1;
 
206
 
 
207
        break;
 
208
      }
 
209
 
 
210
    case IS_SPARC64_LINUX:
 
211
      {
 
212
        Elf64_Ehdr ehdr;
 
213
 
 
214
        if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
 
215
          break;
 
216
 
 
217
        if (ehdr.e_ident[EI_MAG0] != ELFMAG0
 
218
            || ehdr.e_ident[EI_MAG1] != ELFMAG1
 
219
            || ehdr.e_ident[EI_MAG2] != ELFMAG2
 
220
            || ehdr.e_ident[EI_MAG3] != ELFMAG3
 
221
            || ehdr.e_ident[EI_VERSION] != EV_CURRENT
 
222
            || ehdr.e_version != EV_CURRENT)
 
223
          break;
 
224
 
 
225
        if (ehdr.e_ident[EI_CLASS] != ELFCLASS64
 
226
            || ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
 
227
          break;
 
228
 
 
229
        if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_SPARCV9)
 
230
            || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC))
 
231
          break;
 
232
 
 
233
        ret = 1;
 
234
 
 
235
        break;
 
236
      }
 
237
 
 
238
    case IS_POWERPC_LINUX:
 
239
      {
 
240
        Elf32_Ehdr ehdr;
 
241
 
 
242
        if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
 
243
          break;
 
244
 
 
245
        if (ehdr.e_ident[EI_MAG0] != ELFMAG0
 
246
            || ehdr.e_ident[EI_MAG1] != ELFMAG1
 
247
            || ehdr.e_ident[EI_MAG2] != ELFMAG2
 
248
            || ehdr.e_ident[EI_MAG3] != ELFMAG3
 
249
            || ehdr.e_ident[EI_VERSION] != EV_CURRENT
 
250
            || ehdr.e_version != EV_CURRENT)
 
251
          break;
 
252
 
 
253
        if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB
 
254
            || (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_PPC)
 
255
                && ehdr.e_machine !=
 
256
                grub_cpu_to_le16_compile_time (EM_PPC64)))
 
257
          break;
 
258
 
 
259
        if (ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)
 
260
            && ehdr.e_type != grub_cpu_to_be16_compile_time (ET_DYN))
 
261
          break;
 
262
 
 
263
        ret = 1;
 
264
 
 
265
        break;
 
266
      }
 
267
 
 
268
    case IS_MIPS_LINUX:
 
269
      {
 
270
        Elf32_Ehdr ehdr;
 
271
 
 
272
        if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
 
273
          break;
 
274
 
 
275
        if (ehdr.e_ident[EI_MAG0] != ELFMAG0
 
276
            || ehdr.e_ident[EI_MAG1] != ELFMAG1
 
277
            || ehdr.e_ident[EI_MAG2] != ELFMAG2
 
278
            || ehdr.e_ident[EI_MAG3] != ELFMAG3
 
279
            || ehdr.e_ident[EI_VERSION] != EV_CURRENT
 
280
            || ehdr.e_version != EV_CURRENT)
 
281
          break;
 
282
 
 
283
        if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB
 
284
            || ehdr.e_machine != grub_cpu_to_be16_compile_time (EM_MIPS)
 
285
            || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC))
 
286
          break;
 
287
 
 
288
        ret = 1;
 
289
 
 
290
        break;
 
291
      }
 
292
 
 
293
    case IS_X86_KNETBSD:
 
294
    case IS_X86_KNETBSD32:
 
295
    case IS_X86_KNETBSD64:
 
296
      {
 
297
        int is32, is64;
 
298
 
 
299
        elf = grub_elf_file (file, file->name);
 
300
 
 
301
        if (elf->ehdr.ehdr32.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)
 
302
            || elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB)
 
303
          break;
 
304
 
 
305
        is32 = grub_elf_is_elf32 (elf);
 
306
        is64 = grub_elf_is_elf64 (elf);
 
307
        if (!is32 && !is64)
 
308
          break;
 
309
        if (!is32 && type == IS_X86_KNETBSD32)
 
310
          break;
 
311
        if (!is64 && type == IS_X86_KNETBSD64)
 
312
          break;
 
313
        if (is64)
 
314
          ret = grub_file_check_netbsd64 (elf);
 
315
        if (is32)
 
316
          ret = grub_file_check_netbsd32 (elf);
 
317
        break;
 
318
      }
 
319
 
 
320
    case IS_X86_KFREEBSD:
 
321
    case IS_X86_KFREEBSD32:
 
322
    case IS_X86_KFREEBSD64:
 
323
      {
 
324
        Elf32_Ehdr ehdr;
 
325
        int is32, is64;
 
326
 
 
327
        if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
 
328
          break;
 
329
 
 
330
        if (ehdr.e_ident[EI_MAG0] != ELFMAG0
 
331
            || ehdr.e_ident[EI_MAG1] != ELFMAG1
 
332
            || ehdr.e_ident[EI_MAG2] != ELFMAG2
 
333
            || ehdr.e_ident[EI_MAG3] != ELFMAG3
 
334
            || ehdr.e_ident[EI_VERSION] != EV_CURRENT
 
335
            || ehdr.e_version != EV_CURRENT)
 
336
          break;
 
337
 
 
338
        if (ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)
 
339
            || ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
 
340
          break;
 
341
 
 
342
        if (ehdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
 
343
          break;
 
344
 
 
345
        is32 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_386)
 
346
                && ehdr.e_ident[EI_CLASS] == ELFCLASS32);
 
347
        is64 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_X86_64)
 
348
                && ehdr.e_ident[EI_CLASS] == ELFCLASS64);
 
349
        if (!is32 && !is64)
 
350
          break;
 
351
        if (!is32 && (type == IS_X86_KFREEBSD32 || type == IS_X86_KNETBSD32))
 
352
          break;
 
353
        if (!is64 && (type == IS_X86_KFREEBSD64 || type == IS_X86_KNETBSD64))
 
354
          break;
 
355
        ret = 1;
 
356
 
 
357
        break;
 
358
      }
 
359
 
 
360
 
 
361
    case IS_MIPSEL_LINUX:
 
362
      {
 
363
        Elf32_Ehdr ehdr;
 
364
 
 
365
        if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
 
366
          break;
 
367
 
 
368
        if (ehdr.e_ident[EI_MAG0] != ELFMAG0
 
369
            || ehdr.e_ident[EI_MAG1] != ELFMAG1
 
370
            || ehdr.e_ident[EI_MAG2] != ELFMAG2
 
371
            || ehdr.e_ident[EI_MAG3] != ELFMAG3
 
372
            || ehdr.e_ident[EI_VERSION] != EV_CURRENT
 
373
            || ehdr.e_version != EV_CURRENT)
 
374
          break;
 
375
 
 
376
        if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_MIPS)
 
377
            || ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC))
 
378
          break;
 
379
 
 
380
        ret = 1;
 
381
 
 
382
        break;
 
383
      }
 
384
    case IS_ARM_LINUX:
 
385
      {
 
386
        grub_uint32_t sig, sig_pi;
 
387
        if (grub_file_read (file, &sig_pi, 4) != 4)
 
388
          break;
 
389
        /* Raspberry pi.  */
 
390
        if (sig_pi == grub_cpu_to_le32_compile_time (0xea000006))
 
391
          {
 
392
            ret = 1;
 
393
            break;
 
394
          }
 
395
 
 
396
        if (grub_file_seek (file, 0x24) == (grub_size_t) -1)
 
397
          break;
 
398
        if (grub_file_read (file, &sig, 4) != 4)
 
399
          break;
 
400
        if (sig == grub_cpu_to_le32_compile_time (0x016f2818))
 
401
          {
 
402
            ret = 1;
 
403
            break;
 
404
          }
 
405
        break;
 
406
      }
 
407
    case IS_ARM64_LINUX:
 
408
      {
 
409
        grub_uint32_t sig;
 
410
 
 
411
        if (grub_file_seek (file, 0x38) == (grub_size_t) -1)
 
412
          break;
 
413
        if (grub_file_read (file, &sig, 4) != 4)
 
414
          break;
 
415
        if (sig == grub_cpu_to_le32_compile_time (0x644d5241))
 
416
          {
 
417
            ret = 1;
 
418
            break;
 
419
          }
 
420
        break;
 
421
      }
 
422
    case IS_PAE_DOMU ... IS_DOM0:
 
423
      {
 
424
        struct grub_xen_file_info xen_inf;
 
425
        elf = grub_xen_file (file);
 
426
        if (!elf)
 
427
          break;
 
428
        err = grub_xen_get_info (elf, &xen_inf);
 
429
        if (err)
 
430
          break;
 
431
        /* Unfortuntely no way to check if kernel supports dom0.  */
 
432
        if (type == IS_DOM0)
 
433
          ret = 1;
 
434
        if (type == IS_PAE_DOMU)
 
435
          ret = (xen_inf.arch == GRUB_XEN_FILE_I386_PAE
 
436
                 || xen_inf.arch == GRUB_XEN_FILE_I386_PAE_BIMODE);
 
437
        if (type == IS_64_DOMU)
 
438
          ret = (xen_inf.arch == GRUB_XEN_FILE_X86_64);
 
439
        break;
 
440
      }
 
441
    case IS_MULTIBOOT:
 
442
    case IS_MULTIBOOT2:
 
443
      {
 
444
        grub_uint32_t *buffer;
 
445
        grub_ssize_t len;
 
446
        grub_size_t search_size;
 
447
        grub_uint32_t *header;
 
448
        grub_uint32_t magic;
 
449
        grub_size_t step;
 
450
 
 
451
        if (type == IS_MULTIBOOT2)
 
452
          {
 
453
            search_size = 32768;
 
454
            magic = grub_cpu_to_le32_compile_time (0xe85250d6);
 
455
            step = 2;
 
456
          }
 
457
        else
 
458
          {
 
459
            search_size = 8192;
 
460
            magic = grub_cpu_to_le32_compile_time (0x1BADB002);
 
461
            step = 1;
 
462
          }
 
463
 
 
464
        buffer = grub_malloc (search_size);
 
465
        if (!buffer)
 
466
          break;
 
467
 
 
468
        len = grub_file_read (file, buffer, search_size);
 
469
        if (len < 32)
 
470
          {
 
471
            grub_free (buffer);
 
472
            break;
 
473
          }
 
474
 
 
475
        /* Look for the multiboot header in the buffer.  The header should
 
476
           be at least 12 bytes and aligned on a 4-byte boundary.  */
 
477
        for (header = buffer;
 
478
             ((char *) header <=
 
479
              (char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12))
 
480
             || (header = 0); header += step)
 
481
          {
 
482
            if (header[0] == magic
 
483
                && !(grub_le_to_cpu32 (header[0])
 
484
                     + grub_le_to_cpu32 (header[1])
 
485
                     + grub_le_to_cpu32 (header[2])
 
486
                     + (type == IS_MULTIBOOT2
 
487
                        ? grub_le_to_cpu32 (header[3]) : 0)))
 
488
              break;
 
489
          }
 
490
 
 
491
        if (header != 0)
 
492
          ret = 1;
 
493
        grub_free (buffer);
 
494
        break;
 
495
      }
 
496
    case IS_X86_LINUX32:
 
497
    case IS_X86_LINUX:
 
498
      {
 
499
        struct linux_kernel_header lh;
 
500
        if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
 
501
          break;
 
502
        if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
 
503
          break;
 
504
 
 
505
        if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
 
506
          break;
 
507
 
 
508
        /* FIXME: some really old kernels (< 1.3.73) will fail this.  */
 
509
        if (lh.header !=
 
510
            grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
 
511
            || grub_le_to_cpu16 (lh.version) < 0x0200)
 
512
          break;
 
513
 
 
514
        if (type == IS_X86_LINUX)
 
515
          {
 
516
            ret = 1;
 
517
            break;
 
518
          }
 
519
 
 
520
        /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
 
521
           still not support 32-bit boot.  */
 
522
        if (lh.header !=
 
523
            grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
 
524
            || grub_le_to_cpu16 (lh.version) < 0x0203)
 
525
          break;
 
526
 
 
527
        if (!(lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
 
528
          break;
 
529
        ret = 1;
 
530
        break;
 
531
      }
 
532
    case IS_HIBERNATED:
 
533
      {
 
534
        grub_uint8_t hibr_file_magic[4];
 
535
        if (grub_file_read (file, &hibr_file_magic, sizeof (hibr_file_magic))
 
536
            != sizeof (hibr_file_magic))
 
537
          break;
 
538
        if (grub_memcmp ("hibr", hibr_file_magic, sizeof (hibr_file_magic)) ==
 
539
            0
 
540
            || grub_memcmp ("HIBR", hibr_file_magic,
 
541
                            sizeof (hibr_file_magic)) == 0)
 
542
          ret = 1;
 
543
        break;
 
544
      }
 
545
    case IS_XNU64:
 
546
    case IS_XNU32:
 
547
      {
 
548
        macho = grub_macho_open (args[0], (type == IS_XNU64));
 
549
        if (!macho)
 
550
          break;
 
551
        /* FIXME: more checks?  */
 
552
        ret = 1;
 
553
        break;
 
554
      }
 
555
    case IS_XNU_HIBR:
 
556
      {
 
557
        struct grub_xnu_hibernate_header hibhead;
 
558
        if (grub_file_read (file, &hibhead, sizeof (hibhead))
 
559
            != sizeof (hibhead))
 
560
          break;
 
561
        if (hibhead.magic !=
 
562
            grub_cpu_to_le32_compile_time (GRUB_XNU_HIBERNATE_MAGIC))
 
563
          break;
 
564
        ret = 1;
 
565
        break;
 
566
      }
 
567
    case IS_32_EFI:
 
568
    case IS_64_EFI:
 
569
    case IS_IA_EFI:
 
570
    case IS_ARM64_EFI:
 
571
    case IS_ARM_EFI:
 
572
      {
 
573
        char signature[4];
 
574
        grub_uint32_t pe_offset;
 
575
        struct grub_pe32_coff_header coff_head;
 
576
 
 
577
        if (grub_file_read (file, signature, 2) != 2)
 
578
          break;
 
579
        if (signature[0] != 'M' || signature[1] != 'Z')
 
580
          break;
 
581
        if ((grub_ssize_t) grub_file_seek (file, 0x3c) == -1)
 
582
          break;
 
583
        if (grub_file_read (file, &pe_offset, 4) != 4)
 
584
          break;
 
585
        if ((grub_ssize_t) grub_file_seek (file, grub_le_to_cpu32 (pe_offset))
 
586
            == -1)
 
587
          break;
 
588
        if (grub_file_read (file, signature, 4) != 4)
 
589
          break;
 
590
        if (signature[0] != 'P' || signature[1] != 'E'
 
591
            || signature[2] != '\0' || signature[3] != '\0')
 
592
          break;
 
593
 
 
594
        if (grub_file_read (file, &coff_head, sizeof (coff_head))
 
595
            != sizeof (coff_head))
 
596
          break;
 
597
        if (type == IS_32_EFI
 
598
            && coff_head.machine !=
 
599
            grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_I386))
 
600
          break;
 
601
        if (type == IS_64_EFI
 
602
            && coff_head.machine !=
 
603
            grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_X86_64))
 
604
          break;
 
605
        if (type == IS_IA_EFI
 
606
            && coff_head.machine !=
 
607
            grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_IA64))
 
608
          break;
 
609
        if (type == IS_ARM64_EFI
 
610
            && coff_head.machine !=
 
611
            grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARM64))
 
612
          break;
 
613
        if (type == IS_ARM_EFI
 
614
            && coff_head.machine !=
 
615
            grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARMTHUMB_MIXED))
 
616
          break;
 
617
        if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI)
 
618
          {
 
619
            struct grub_pe64_optional_header o64;
 
620
            if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64))
 
621
              break;
 
622
            if (o64.magic !=
 
623
                grub_cpu_to_le16_compile_time (GRUB_PE32_PE64_MAGIC))
 
624
              break;
 
625
            if (o64.subsystem !=
 
626
                grub_cpu_to_le16_compile_time
 
627
                (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION))
 
628
              break;
 
629
            ret = 1;
 
630
            break;
 
631
          }
 
632
        if (type == IS_32_EFI || type == IS_ARM_EFI)
 
633
          {
 
634
            struct grub_pe32_optional_header o32;
 
635
            if (grub_file_read (file, &o32, sizeof (o32)) != sizeof (o32))
 
636
              break;
 
637
            if (o32.magic !=
 
638
                grub_cpu_to_le16_compile_time (GRUB_PE32_PE32_MAGIC))
 
639
              break;
 
640
            if (o32.subsystem !=
 
641
                grub_cpu_to_le16_compile_time
 
642
                (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION))
 
643
              break;
 
644
            ret = 1;
 
645
            break;
 
646
          }
 
647
        break;
 
648
      }
 
649
    }
 
650
 
 
651
  if (elf)
 
652
    grub_elf_close (elf);
 
653
  else if (macho)
 
654
    grub_macho_close (macho);
 
655
  else if (file)
 
656
    grub_file_close (file);
 
657
 
 
658
  if (!ret && (grub_errno == GRUB_ERR_BAD_OS || grub_errno == GRUB_ERR_NONE))
 
659
    /* TRANSLATORS: it's a standalone boolean value,
 
660
       opposite of "true".  */
 
661
    grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
 
662
  return grub_errno;
 
663
}
 
664
 
 
665
static grub_extcmd_t cmd;
 
666
 
 
667
GRUB_MOD_INIT(file)
 
668
{
 
669
  cmd = grub_register_extcmd ("file", grub_cmd_file, 0,
 
670
                              N_("OPTIONS FILE"),
 
671
                              N_("Check if FILE is of specified type."),
 
672
                              options);
 
673
}
 
674
 
 
675
GRUB_MOD_FINI(file)
 
676
{
 
677
  grub_unregister_extcmd (cmd);
 
678
}