file.c 17 KB

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