truecrypt.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* chainloader.c - boot another boot loader */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2002,2004,2007,2009,2010 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/loader.h>
  20. #include <grub/file.h>
  21. #include <grub/err.h>
  22. #include <grub/device.h>
  23. #include <grub/disk.h>
  24. #include <grub/misc.h>
  25. #include <grub/types.h>
  26. #include <grub/partition.h>
  27. #include <grub/dl.h>
  28. #include <grub/command.h>
  29. #include <grub/machine/biosnum.h>
  30. #include <grub/i18n.h>
  31. #include <grub/video.h>
  32. #include <grub/mm.h>
  33. #include <grub/cpu/relocator.h>
  34. #include <grub/deflate.h>
  35. GRUB_MOD_LICENSE ("GPLv3+");
  36. static grub_dl_t my_mod;
  37. static struct grub_relocator *rel;
  38. static grub_uint32_t edx = 0xffffffff;
  39. static grub_uint16_t sp;
  40. static grub_uint32_t destaddr;
  41. #define GRUB_TRUECRYPT_SEGMENT 0x2000
  42. static grub_err_t
  43. grub_truecrypt_boot (void)
  44. {
  45. grub_uint16_t segment = destaddr >> 4;
  46. struct grub_relocator16_state state = {
  47. .cs = segment,
  48. .ds = segment,
  49. .es = segment,
  50. .fs = segment,
  51. .gs = segment,
  52. .ss = segment,
  53. .ip = 0x100,
  54. .sp = sp,
  55. .edx = edx,
  56. .a20 = 1
  57. };
  58. grub_video_set_mode ("text", 0, 0);
  59. return grub_relocator16_boot (rel, state);
  60. }
  61. static grub_err_t
  62. grub_truecrypt_unload (void)
  63. {
  64. grub_relocator_unload (rel);
  65. rel = NULL;
  66. grub_dl_unref (my_mod);
  67. return GRUB_ERR_NONE;
  68. }
  69. /* Information on protocol supplied by Attila Lendvai. */
  70. #define MAGIC "\0CD001\1EL TORITO SPECIFICATION"
  71. static grub_err_t
  72. grub_cmd_truecrypt (grub_command_t cmd __attribute__ ((unused)),
  73. int argc, char *argv[])
  74. {
  75. grub_file_t file = 0;
  76. grub_err_t err;
  77. void *truecrypt;
  78. grub_size_t truecryptsize;
  79. const grub_size_t truecryptmemsize = 42 * 1024;
  80. grub_uint8_t dh;
  81. grub_uint32_t catalog, rba;
  82. grub_uint8_t buf[128];
  83. char *compressed = NULL;
  84. char *uncompressed = NULL;
  85. if (argc == 0)
  86. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  87. rel = NULL;
  88. grub_dl_ref (my_mod);
  89. file = grub_file_open (argv[0], GRUB_FILE_TYPE_TRUECRYPT);
  90. if (! file)
  91. goto fail;
  92. if (grub_file_seek (file, 17 * 2048) == (grub_size_t) -1)
  93. goto fail;
  94. if (grub_file_read (file, buf, sizeof (buf))
  95. != sizeof (buf))
  96. goto fail;
  97. if (grub_memcmp (buf, MAGIC, sizeof (MAGIC)) != 0)
  98. {
  99. grub_error (GRUB_ERR_BAD_OS, "invalid eltorito signature");
  100. goto fail;
  101. }
  102. catalog = grub_get_unaligned32 (buf + 0x47);
  103. if (grub_file_seek (file, catalog * 2048) == (grub_size_t)-1)
  104. goto fail;
  105. if (grub_file_read (file, buf, sizeof (buf))
  106. != sizeof (buf))
  107. goto fail;
  108. if (buf[0] != 1 || buf[1] != 0 || buf[0x1e] != 0x55
  109. || buf[0x1f] != 0xaa || buf[0x20] != 0x88
  110. || buf[0x26] != 1 || buf[0x27] != 0)
  111. {
  112. grub_error (GRUB_ERR_BAD_OS, "invalid eltorito catalog");
  113. goto fail;
  114. }
  115. rba = grub_get_unaligned32 (buf + 0x28);
  116. if (grub_file_seek (file, rba * 2048 + 0x1b7) == (grub_size_t) -1)
  117. goto fail;
  118. if (grub_file_read (file, &dh, 1)
  119. != 1)
  120. goto fail;
  121. if (grub_file_seek (file, rba * 2048 + 512 + 2048) == (grub_size_t) -1)
  122. goto fail;
  123. compressed = grub_malloc (57 * 512);
  124. if (!compressed)
  125. goto fail;
  126. if (grub_file_read (file, compressed, 57 * 512)
  127. != 57 * 512)
  128. goto fail;
  129. uncompressed = grub_malloc (truecryptmemsize);
  130. if (!uncompressed)
  131. goto fail;
  132. /* It's actually gzip but our gzip decompressor isn't able to handle
  133. trailing garbage, hence let's use raw decompressor. */
  134. truecryptsize = grub_deflate_decompress (compressed + 10, 57 * 512 - 10,
  135. 0, uncompressed, truecryptmemsize);
  136. if ((grub_ssize_t) truecryptsize < 0)
  137. goto fail;
  138. if (truecryptmemsize <= truecryptsize + 0x100)
  139. {
  140. grub_error (GRUB_ERR_BAD_OS, "file is too big");
  141. goto fail;
  142. }
  143. rel = grub_relocator_new ();
  144. if (!rel)
  145. goto fail;
  146. edx = (dh << 8) | grub_get_root_biosnumber ();
  147. destaddr = ALIGN_DOWN (grub_min (0x90000, grub_mmap_get_lower ())
  148. - truecryptmemsize, 64 * 1024);
  149. {
  150. grub_relocator_chunk_t ch;
  151. err = grub_relocator_alloc_chunk_addr (rel, &ch, destaddr,
  152. truecryptmemsize);
  153. if (err)
  154. goto fail;
  155. truecrypt = get_virtual_current_address (ch);
  156. }
  157. grub_memset (truecrypt, 0, 0x100);
  158. grub_memcpy ((char *) truecrypt + 0x100, uncompressed, truecryptsize);
  159. grub_memset ((char *) truecrypt + truecryptsize + 0x100,
  160. 0, truecryptmemsize - truecryptsize - 0x100);
  161. sp = truecryptmemsize - 4;
  162. grub_loader_set (grub_truecrypt_boot, grub_truecrypt_unload, 1);
  163. grub_free (uncompressed);
  164. grub_free (compressed);
  165. return GRUB_ERR_NONE;
  166. fail:
  167. if (!grub_errno)
  168. grub_error (GRUB_ERR_BAD_OS, "bad truecrypt ISO");
  169. if (file)
  170. grub_file_close (file);
  171. grub_truecrypt_unload ();
  172. grub_free (uncompressed);
  173. grub_free (compressed);
  174. return grub_errno;
  175. }
  176. static grub_command_t cmd;
  177. GRUB_MOD_INIT(truecrypt)
  178. {
  179. cmd = grub_register_command ("truecrypt", grub_cmd_truecrypt,
  180. 0, N_("Load Truecrypt ISO."));
  181. my_mod = mod;
  182. }
  183. GRUB_MOD_FINI(truecrypt)
  184. {
  185. grub_unregister_command (cmd);
  186. }