ext2.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. /* ext2.c - Second Extended filesystem */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2003,2004,2005,2007,2008,2009 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. /* Magic value used to identify an ext2 filesystem. */
  20. #define EXT2_MAGIC 0xEF53
  21. /* Amount of indirect blocks in an inode. */
  22. #define INDIRECT_BLOCKS 12
  23. /* The good old revision and the default inode size. */
  24. #define EXT2_GOOD_OLD_REVISION 0
  25. #define EXT2_GOOD_OLD_INODE_SIZE 128
  26. /* Filetype used in directory entry. */
  27. #define FILETYPE_UNKNOWN 0
  28. #define FILETYPE_REG 1
  29. #define FILETYPE_DIRECTORY 2
  30. #define FILETYPE_SYMLINK 7
  31. /* Filetype information as used in inodes. */
  32. #define FILETYPE_INO_MASK 0170000
  33. #define FILETYPE_INO_REG 0100000
  34. #define FILETYPE_INO_DIRECTORY 0040000
  35. #define FILETYPE_INO_SYMLINK 0120000
  36. #include <grub/err.h>
  37. #include <grub/file.h>
  38. #include <grub/mm.h>
  39. #include <grub/misc.h>
  40. #include <grub/disk.h>
  41. #include <grub/dl.h>
  42. #include <grub/types.h>
  43. #include <grub/fshelp.h>
  44. #include <grub/safemath.h>
  45. GRUB_MOD_LICENSE ("GPLv3+");
  46. /* Log2 size of ext2 block in 512 blocks. */
  47. #define LOG2_EXT2_BLOCK_SIZE(data) \
  48. (grub_le_to_cpu32 (data->sblock.log2_block_size) + 1)
  49. /* Log2 size of ext2 block in bytes. */
  50. #define LOG2_BLOCK_SIZE(data) \
  51. (grub_le_to_cpu32 (data->sblock.log2_block_size) + 10)
  52. /* The size of an ext2 block in bytes. */
  53. #define EXT2_BLOCK_SIZE(data) (1U << LOG2_BLOCK_SIZE (data))
  54. /* The revision level. */
  55. #define EXT2_REVISION(data) grub_le_to_cpu32 (data->sblock.revision_level)
  56. /* The inode size. */
  57. #define EXT2_INODE_SIZE(data) \
  58. (data->sblock.revision_level \
  59. == grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) \
  60. ? EXT2_GOOD_OLD_INODE_SIZE \
  61. : grub_le_to_cpu16 (data->sblock.inode_size))
  62. /* Superblock filesystem feature flags (RW compatible)
  63. * A filesystem with any of these enabled can be read and written by a driver
  64. * that does not understand them without causing metadata/data corruption. */
  65. #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
  66. #define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
  67. #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
  68. #define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
  69. #define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
  70. #define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
  71. /* Superblock filesystem feature flags (RO compatible)
  72. * A filesystem with any of these enabled can be safely read by a driver that
  73. * does not understand them, but should not be written to, usually because
  74. * additional metadata is required. */
  75. #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
  76. #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
  77. #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
  78. #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
  79. #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
  80. #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
  81. /* Superblock filesystem feature flags (back-incompatible)
  82. * A filesystem with any of these enabled should not be attempted to be read
  83. * by a driver that does not understand them, since they usually indicate
  84. * metadata format changes that might confuse the reader. */
  85. #define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
  86. #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
  87. #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
  88. #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Volume is journal device */
  89. #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
  90. #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* Extents used */
  91. #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
  92. #define EXT4_FEATURE_INCOMPAT_MMP 0x0100
  93. #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
  94. #define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000
  95. #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3 level htree */
  96. #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000
  97. /* The set of back-incompatible features this driver DOES support. Add (OR)
  98. * flags here as the related features are implemented into the driver. */
  99. #define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \
  100. | EXT4_FEATURE_INCOMPAT_EXTENTS \
  101. | EXT4_FEATURE_INCOMPAT_FLEX_BG \
  102. | EXT2_FEATURE_INCOMPAT_META_BG \
  103. | EXT4_FEATURE_INCOMPAT_64BIT \
  104. | EXT4_FEATURE_INCOMPAT_ENCRYPT)
  105. /* List of rationales for the ignored "incompatible" features:
  106. * needs_recovery: Not really back-incompatible - was added as such to forbid
  107. * ext2 drivers from mounting an ext3 volume with a dirty
  108. * journal because they will ignore the journal, but the next
  109. * ext3 driver to mount the volume will find the journal and
  110. * replay it, potentially corrupting the metadata written by
  111. * the ext2 drivers. Safe to ignore for this RO driver.
  112. * mmp: Not really back-incompatible - was added as such to
  113. * avoid multiple read-write mounts. Safe to ignore for this
  114. * RO driver.
  115. * checksum seed: Not really back-incompatible - was added to allow tools
  116. * such as tune2fs to change the UUID on a mounted metadata
  117. * checksummed filesystem. Safe to ignore for now since the
  118. * driver doesn't support checksum verification. However, it
  119. * has to be removed from this list if the support is added later.
  120. * large_dir: Not back-incompatible given that the GRUB ext2 driver does
  121. * not implement EXT2_FEATURE_COMPAT_DIR_INDEX. If the GRUB
  122. * eventually supports the htree feature (aka dir_index)
  123. * it should support 3 level htrees and then move
  124. * EXT4_FEATURE_INCOMPAT_LARGEDIR to
  125. * EXT2_DRIVER_SUPPORTED_INCOMPAT.
  126. */
  127. #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \
  128. | EXT4_FEATURE_INCOMPAT_MMP \
  129. | EXT4_FEATURE_INCOMPAT_CSUM_SEED \
  130. | EXT4_FEATURE_INCOMPAT_LARGEDIR)
  131. #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
  132. #define EXT3_JOURNAL_DESCRIPTOR_BLOCK 1
  133. #define EXT3_JOURNAL_COMMIT_BLOCK 2
  134. #define EXT3_JOURNAL_SUPERBLOCK_V1 3
  135. #define EXT3_JOURNAL_SUPERBLOCK_V2 4
  136. #define EXT3_JOURNAL_REVOKE_BLOCK 5
  137. #define EXT3_JOURNAL_FLAG_ESCAPE 1
  138. #define EXT3_JOURNAL_FLAG_SAME_UUID 2
  139. #define EXT3_JOURNAL_FLAG_DELETED 4
  140. #define EXT3_JOURNAL_FLAG_LAST_TAG 8
  141. #define EXT4_ENCRYPT_FLAG 0x800
  142. #define EXT4_EXTENTS_FLAG 0x80000
  143. /* The ext2 superblock. */
  144. struct grub_ext2_sblock
  145. {
  146. grub_uint32_t total_inodes;
  147. grub_uint32_t total_blocks;
  148. grub_uint32_t reserved_blocks;
  149. grub_uint32_t free_blocks;
  150. grub_uint32_t free_inodes;
  151. grub_uint32_t first_data_block;
  152. grub_uint32_t log2_block_size;
  153. grub_uint32_t log2_fragment_size;
  154. grub_uint32_t blocks_per_group;
  155. grub_uint32_t fragments_per_group;
  156. grub_uint32_t inodes_per_group;
  157. grub_uint32_t mtime;
  158. grub_uint32_t utime;
  159. grub_uint16_t mnt_count;
  160. grub_uint16_t max_mnt_count;
  161. grub_uint16_t magic;
  162. grub_uint16_t fs_state;
  163. grub_uint16_t error_handling;
  164. grub_uint16_t minor_revision_level;
  165. grub_uint32_t lastcheck;
  166. grub_uint32_t checkinterval;
  167. grub_uint32_t creator_os;
  168. grub_uint32_t revision_level;
  169. grub_uint16_t uid_reserved;
  170. grub_uint16_t gid_reserved;
  171. grub_uint32_t first_inode;
  172. grub_uint16_t inode_size;
  173. grub_uint16_t block_group_number;
  174. grub_uint32_t feature_compatibility;
  175. grub_uint32_t feature_incompat;
  176. grub_uint32_t feature_ro_compat;
  177. grub_uint16_t uuid[8];
  178. char volume_name[16];
  179. char last_mounted_on[64];
  180. grub_uint32_t compression_info;
  181. grub_uint8_t prealloc_blocks;
  182. grub_uint8_t prealloc_dir_blocks;
  183. grub_uint16_t reserved_gdt_blocks;
  184. grub_uint8_t journal_uuid[16];
  185. grub_uint32_t journal_inum;
  186. grub_uint32_t journal_dev;
  187. grub_uint32_t last_orphan;
  188. grub_uint32_t hash_seed[4];
  189. grub_uint8_t def_hash_version;
  190. grub_uint8_t jnl_backup_type;
  191. grub_uint16_t group_desc_size;
  192. grub_uint32_t default_mount_opts;
  193. grub_uint32_t first_meta_bg;
  194. grub_uint32_t mkfs_time;
  195. grub_uint32_t jnl_blocks[17];
  196. };
  197. /* The ext2 blockgroup. */
  198. struct grub_ext2_block_group
  199. {
  200. grub_uint32_t block_id;
  201. grub_uint32_t inode_id;
  202. grub_uint32_t inode_table_id;
  203. grub_uint16_t free_blocks;
  204. grub_uint16_t free_inodes;
  205. grub_uint16_t used_dirs;
  206. grub_uint16_t pad;
  207. grub_uint32_t reserved[3];
  208. grub_uint32_t block_id_hi;
  209. grub_uint32_t inode_id_hi;
  210. grub_uint32_t inode_table_id_hi;
  211. grub_uint16_t free_blocks_hi;
  212. grub_uint16_t free_inodes_hi;
  213. grub_uint16_t used_dirs_hi;
  214. grub_uint16_t pad2;
  215. grub_uint32_t reserved2[3];
  216. };
  217. /* The ext2 inode. */
  218. struct grub_ext2_inode
  219. {
  220. grub_uint16_t mode;
  221. grub_uint16_t uid;
  222. grub_uint32_t size;
  223. grub_uint32_t atime;
  224. grub_uint32_t ctime;
  225. grub_uint32_t mtime;
  226. grub_uint32_t dtime;
  227. grub_uint16_t gid;
  228. grub_uint16_t nlinks;
  229. grub_uint32_t blockcnt; /* Blocks of 512 bytes!! */
  230. grub_uint32_t flags;
  231. grub_uint32_t osd1;
  232. union
  233. {
  234. struct datablocks
  235. {
  236. grub_uint32_t dir_blocks[INDIRECT_BLOCKS];
  237. grub_uint32_t indir_block;
  238. grub_uint32_t double_indir_block;
  239. grub_uint32_t triple_indir_block;
  240. } blocks;
  241. char symlink[60];
  242. };
  243. grub_uint32_t version;
  244. grub_uint32_t acl;
  245. grub_uint32_t size_high;
  246. grub_uint32_t fragment_addr;
  247. grub_uint32_t osd2[3];
  248. };
  249. /* The header of an ext2 directory entry. */
  250. struct ext2_dirent
  251. {
  252. grub_uint32_t inode;
  253. grub_uint16_t direntlen;
  254. #define MAX_NAMELEN 255
  255. grub_uint8_t namelen;
  256. grub_uint8_t filetype;
  257. };
  258. struct grub_ext3_journal_header
  259. {
  260. grub_uint32_t magic;
  261. grub_uint32_t block_type;
  262. grub_uint32_t sequence;
  263. };
  264. struct grub_ext3_journal_revoke_header
  265. {
  266. struct grub_ext3_journal_header header;
  267. grub_uint32_t count;
  268. grub_uint32_t data[0];
  269. };
  270. struct grub_ext3_journal_block_tag
  271. {
  272. grub_uint32_t block;
  273. grub_uint32_t flags;
  274. };
  275. struct grub_ext3_journal_sblock
  276. {
  277. struct grub_ext3_journal_header header;
  278. grub_uint32_t block_size;
  279. grub_uint32_t maxlen;
  280. grub_uint32_t first;
  281. grub_uint32_t sequence;
  282. grub_uint32_t start;
  283. };
  284. #define EXT4_EXT_MAGIC 0xf30a
  285. struct grub_ext4_extent_header
  286. {
  287. grub_uint16_t magic;
  288. grub_uint16_t entries;
  289. grub_uint16_t max;
  290. grub_uint16_t depth;
  291. grub_uint32_t generation;
  292. };
  293. struct grub_ext4_extent
  294. {
  295. grub_uint32_t block;
  296. grub_uint16_t len;
  297. grub_uint16_t start_hi;
  298. grub_uint32_t start;
  299. };
  300. struct grub_ext4_extent_idx
  301. {
  302. grub_uint32_t block;
  303. grub_uint32_t leaf;
  304. grub_uint16_t leaf_hi;
  305. grub_uint16_t unused;
  306. };
  307. struct grub_fshelp_node
  308. {
  309. struct grub_ext2_data *data;
  310. struct grub_ext2_inode inode;
  311. int ino;
  312. int inode_read;
  313. };
  314. /* Information about a "mounted" ext2 filesystem. */
  315. struct grub_ext2_data
  316. {
  317. struct grub_ext2_sblock sblock;
  318. int log_group_desc_size;
  319. grub_disk_t disk;
  320. struct grub_ext2_inode *inode;
  321. struct grub_fshelp_node diropen;
  322. };
  323. static grub_dl_t my_mod;
  324. /* Check is a = b^x for some x. */
  325. static inline int
  326. is_power_of (grub_uint64_t a, grub_uint32_t b)
  327. {
  328. grub_uint64_t c;
  329. /* Prevent overflow assuming b < 8. */
  330. if (a >= (1LL << 60))
  331. return 0;
  332. for (c = 1; c <= a; c *= b);
  333. return (c == a);
  334. }
  335. static inline int
  336. group_has_super_block (struct grub_ext2_data *data, grub_uint64_t group)
  337. {
  338. if (!(data->sblock.feature_ro_compat
  339. & grub_cpu_to_le32_compile_time(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)))
  340. return 1;
  341. /* Algorithm looked up in Linux source. */
  342. if (group <= 1)
  343. return 1;
  344. /* Even number is never a power of odd number. */
  345. if (!(group & 1))
  346. return 0;
  347. return (is_power_of(group, 7) || is_power_of(group, 5) ||
  348. is_power_of(group, 3));
  349. }
  350. /* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
  351. the mounted filesystem DATA. */
  352. inline static grub_err_t
  353. grub_ext2_blockgroup (struct grub_ext2_data *data, grub_uint64_t group,
  354. struct grub_ext2_block_group *blkgrp)
  355. {
  356. grub_uint64_t full_offset = (group << data->log_group_desc_size);
  357. grub_uint64_t block, offset;
  358. block = (full_offset >> LOG2_BLOCK_SIZE (data));
  359. offset = (full_offset & ((1 << LOG2_BLOCK_SIZE (data)) - 1));
  360. if ((data->sblock.feature_incompat
  361. & grub_cpu_to_le32_compile_time (EXT2_FEATURE_INCOMPAT_META_BG))
  362. && block >= grub_le_to_cpu32(data->sblock.first_meta_bg))
  363. {
  364. grub_uint64_t first_block_group;
  365. /* Find the first block group for which a descriptor
  366. is stored in given block. */
  367. first_block_group = (block << (LOG2_BLOCK_SIZE (data)
  368. - data->log_group_desc_size));
  369. block = (first_block_group
  370. * grub_le_to_cpu32(data->sblock.blocks_per_group));
  371. if (group_has_super_block (data, first_block_group))
  372. block++;
  373. }
  374. else
  375. /* Superblock. */
  376. block++;
  377. return grub_disk_read (data->disk,
  378. ((grub_le_to_cpu32 (data->sblock.first_data_block)
  379. + block)
  380. << LOG2_EXT2_BLOCK_SIZE (data)), offset,
  381. sizeof (struct grub_ext2_block_group), blkgrp);
  382. }
  383. static grub_err_t
  384. grub_ext4_find_leaf (struct grub_ext2_data *data,
  385. struct grub_ext4_extent_header *ext_block,
  386. grub_uint32_t fileblock,
  387. struct grub_ext4_extent_header **leaf)
  388. {
  389. struct grub_ext4_extent_idx *index;
  390. void *buf = NULL;
  391. *leaf = NULL;
  392. while (1)
  393. {
  394. int i;
  395. grub_disk_addr_t block;
  396. index = (struct grub_ext4_extent_idx *) (ext_block + 1);
  397. if (ext_block->magic != grub_cpu_to_le16_compile_time (EXT4_EXT_MAGIC))
  398. goto fail;
  399. if (ext_block->depth == 0)
  400. {
  401. *leaf = ext_block;
  402. return GRUB_ERR_NONE;
  403. }
  404. for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++)
  405. {
  406. if (fileblock < grub_le_to_cpu32(index[i].block))
  407. break;
  408. }
  409. if (--i < 0)
  410. {
  411. grub_free (buf);
  412. return GRUB_ERR_NONE;
  413. }
  414. block = grub_le_to_cpu16 (index[i].leaf_hi);
  415. block = (block << 32) | grub_le_to_cpu32 (index[i].leaf);
  416. if (!buf)
  417. buf = grub_malloc (EXT2_BLOCK_SIZE(data));
  418. if (!buf)
  419. goto fail;
  420. if (grub_disk_read (data->disk,
  421. block << LOG2_EXT2_BLOCK_SIZE (data),
  422. 0, EXT2_BLOCK_SIZE(data), buf))
  423. goto fail;
  424. ext_block = buf;
  425. }
  426. fail:
  427. grub_free (buf);
  428. return GRUB_ERR_BAD_FS;
  429. }
  430. static grub_disk_addr_t
  431. grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
  432. {
  433. struct grub_ext2_data *data = node->data;
  434. struct grub_ext2_inode *inode = &node->inode;
  435. unsigned int blksz = EXT2_BLOCK_SIZE (data);
  436. grub_disk_addr_t blksz_quarter = blksz / 4;
  437. int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
  438. int log_perblock = log2_blksz + 9 - 2;
  439. grub_uint32_t indir;
  440. int shift;
  441. if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG))
  442. {
  443. struct grub_ext4_extent_header *leaf;
  444. struct grub_ext4_extent *ext;
  445. int i;
  446. grub_disk_addr_t ret;
  447. if (grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
  448. fileblock, &leaf) != GRUB_ERR_NONE)
  449. {
  450. grub_error (GRUB_ERR_BAD_FS, "invalid extent");
  451. return -1;
  452. }
  453. if (leaf == NULL)
  454. /* Leaf for the given block is absent (i.e. sparse) */
  455. return 0;
  456. ext = (struct grub_ext4_extent *) (leaf + 1);
  457. for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
  458. {
  459. if (fileblock < grub_le_to_cpu32 (ext[i].block))
  460. break;
  461. }
  462. if (--i >= 0)
  463. {
  464. fileblock -= grub_le_to_cpu32 (ext[i].block);
  465. if (fileblock >= grub_le_to_cpu16 (ext[i].len))
  466. ret = 0;
  467. else
  468. {
  469. grub_disk_addr_t start;
  470. start = grub_le_to_cpu16 (ext[i].start_hi);
  471. start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
  472. ret = fileblock + start;
  473. }
  474. }
  475. else
  476. {
  477. grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
  478. ret = -1;
  479. }
  480. if (leaf != (struct grub_ext4_extent_header *) inode->blocks.dir_blocks)
  481. grub_free (leaf);
  482. return ret;
  483. }
  484. /* Direct blocks. */
  485. if (fileblock < INDIRECT_BLOCKS)
  486. return grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
  487. fileblock -= INDIRECT_BLOCKS;
  488. /* Indirect. */
  489. if (fileblock < blksz_quarter)
  490. {
  491. indir = inode->blocks.indir_block;
  492. shift = 0;
  493. goto indirect;
  494. }
  495. fileblock -= blksz_quarter;
  496. /* Double indirect. */
  497. if (fileblock < blksz_quarter * blksz_quarter)
  498. {
  499. indir = inode->blocks.double_indir_block;
  500. shift = 1;
  501. goto indirect;
  502. }
  503. fileblock -= blksz_quarter * blksz_quarter;
  504. /* Triple indirect. */
  505. if (fileblock < blksz_quarter * blksz_quarter * (blksz_quarter + 1))
  506. {
  507. indir = inode->blocks.triple_indir_block;
  508. shift = 2;
  509. goto indirect;
  510. }
  511. grub_error (GRUB_ERR_BAD_FS,
  512. "ext2fs doesn't support quadruple indirect blocks");
  513. return -1;
  514. indirect:
  515. do {
  516. /* If the indirect block is zero, all child blocks are absent
  517. (i.e. filled with zeros.) */
  518. if (indir == 0)
  519. return 0;
  520. if (grub_disk_read (data->disk,
  521. ((grub_disk_addr_t) grub_le_to_cpu32 (indir))
  522. << log2_blksz,
  523. ((fileblock >> (log_perblock * shift))
  524. & ((1 << log_perblock) - 1))
  525. * sizeof (indir),
  526. sizeof (indir), &indir))
  527. return -1;
  528. } while (shift--);
  529. return grub_le_to_cpu32 (indir);
  530. }
  531. /* Read LEN bytes from the file described by DATA starting with byte
  532. POS. Return the amount of read bytes in READ. */
  533. static grub_ssize_t
  534. grub_ext2_read_file (grub_fshelp_node_t node,
  535. grub_disk_read_hook_t read_hook, void *read_hook_data,
  536. grub_off_t pos, grub_size_t len, char *buf)
  537. {
  538. return grub_fshelp_read_file (node->data->disk, node,
  539. read_hook, read_hook_data,
  540. pos, len, buf, grub_ext2_read_block,
  541. grub_cpu_to_le32 (node->inode.size)
  542. | (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
  543. LOG2_EXT2_BLOCK_SIZE (node->data), 0);
  544. }
  545. /* Read the inode INO for the file described by DATA into INODE. */
  546. static grub_err_t
  547. grub_ext2_read_inode (struct grub_ext2_data *data,
  548. int ino, struct grub_ext2_inode *inode)
  549. {
  550. struct grub_ext2_block_group blkgrp;
  551. struct grub_ext2_sblock *sblock = &data->sblock;
  552. int inodes_per_block;
  553. unsigned int blkno;
  554. unsigned int blkoff;
  555. grub_disk_addr_t base;
  556. /* It is easier to calculate if the first inode is 0. */
  557. ino--;
  558. grub_ext2_blockgroup (data,
  559. ino / grub_le_to_cpu32 (sblock->inodes_per_group),
  560. &blkgrp);
  561. if (grub_errno)
  562. return grub_errno;
  563. inodes_per_block = EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data);
  564. blkno = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
  565. / inodes_per_block;
  566. blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
  567. % inodes_per_block;
  568. base = grub_le_to_cpu32 (blkgrp.inode_table_id);
  569. if (data->log_group_desc_size >= 6)
  570. base |= (((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id_hi))
  571. << 32);
  572. /* Read the inode. */
  573. if (grub_disk_read (data->disk,
  574. ((base + blkno) << LOG2_EXT2_BLOCK_SIZE (data)),
  575. EXT2_INODE_SIZE (data) * blkoff,
  576. sizeof (struct grub_ext2_inode), inode))
  577. return grub_errno;
  578. return 0;
  579. }
  580. static struct grub_ext2_data *
  581. grub_ext2_mount (grub_disk_t disk)
  582. {
  583. struct grub_ext2_data *data;
  584. data = grub_malloc (sizeof (struct grub_ext2_data));
  585. if (!data)
  586. return 0;
  587. /* Read the superblock. */
  588. grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_ext2_sblock),
  589. &data->sblock);
  590. if (grub_errno)
  591. goto fail;
  592. /* Make sure this is an ext2 filesystem. */
  593. if (data->sblock.magic != grub_cpu_to_le16_compile_time (EXT2_MAGIC)
  594. || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16
  595. || data->sblock.inodes_per_group == 0
  596. /* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */
  597. || grub_le_to_cpu32 (data->sblock.log2_block_size) > 20
  598. || EXT2_INODE_SIZE (data) == 0
  599. || EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data) == 0)
  600. {
  601. grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
  602. goto fail;
  603. }
  604. /* Check the FS doesn't have feature bits enabled that we don't support. */
  605. if (data->sblock.revision_level != grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION)
  606. && (data->sblock.feature_incompat
  607. & grub_cpu_to_le32_compile_time (~(EXT2_DRIVER_SUPPORTED_INCOMPAT
  608. | EXT2_DRIVER_IGNORED_INCOMPAT))))
  609. {
  610. grub_error (GRUB_ERR_BAD_FS, "filesystem has unsupported incompatible features");
  611. goto fail;
  612. }
  613. if (data->sblock.revision_level != grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION)
  614. && (data->sblock.feature_incompat
  615. & grub_cpu_to_le32_compile_time (EXT4_FEATURE_INCOMPAT_64BIT))
  616. && data->sblock.group_desc_size != 0
  617. && ((data->sblock.group_desc_size & (data->sblock.group_desc_size - 1))
  618. == 0)
  619. && (data->sblock.group_desc_size & grub_cpu_to_le16_compile_time (0x1fe0)))
  620. {
  621. grub_uint16_t b = grub_le_to_cpu16 (data->sblock.group_desc_size);
  622. for (data->log_group_desc_size = 0; b != (1 << data->log_group_desc_size);
  623. data->log_group_desc_size++);
  624. }
  625. else
  626. data->log_group_desc_size = 5;
  627. data->disk = disk;
  628. data->diropen.data = data;
  629. data->diropen.ino = 2;
  630. data->diropen.inode_read = 1;
  631. data->inode = &data->diropen.inode;
  632. grub_ext2_read_inode (data, 2, data->inode);
  633. if (grub_errno)
  634. goto fail;
  635. return data;
  636. fail:
  637. if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
  638. grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
  639. grub_free (data);
  640. return 0;
  641. }
  642. static char *
  643. grub_ext2_read_symlink (grub_fshelp_node_t node)
  644. {
  645. char *symlink;
  646. struct grub_fshelp_node *diro = node;
  647. grub_size_t sz;
  648. if (! diro->inode_read)
  649. {
  650. grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
  651. if (grub_errno)
  652. return 0;
  653. if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
  654. {
  655. grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "symlink is encrypted");
  656. return 0;
  657. }
  658. }
  659. if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz))
  660. {
  661. grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
  662. return NULL;
  663. }
  664. symlink = grub_malloc (sz);
  665. if (! symlink)
  666. return 0;
  667. /*
  668. * If the filesize of the symlink is equal to or bigger than 60 the symlink
  669. * is stored in a separate block, otherwise it is stored in the inode.
  670. */
  671. if (grub_le_to_cpu32 (diro->inode.size) < sizeof (diro->inode.symlink))
  672. grub_memcpy (symlink,
  673. diro->inode.symlink,
  674. grub_le_to_cpu32 (diro->inode.size));
  675. else
  676. {
  677. grub_ext2_read_file (diro, 0, 0, 0,
  678. grub_le_to_cpu32 (diro->inode.size),
  679. symlink);
  680. if (grub_errno)
  681. {
  682. grub_free (symlink);
  683. return 0;
  684. }
  685. }
  686. symlink[grub_le_to_cpu32 (diro->inode.size)] = '\0';
  687. return symlink;
  688. }
  689. static int
  690. grub_ext2_iterate_dir (grub_fshelp_node_t dir,
  691. grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
  692. {
  693. unsigned int fpos = 0;
  694. struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
  695. if (! diro->inode_read)
  696. {
  697. grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
  698. if (grub_errno)
  699. return 0;
  700. }
  701. if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
  702. {
  703. grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "directory is encrypted");
  704. return 0;
  705. }
  706. /* Search the file. */
  707. while (fpos < grub_le_to_cpu32 (diro->inode.size))
  708. {
  709. struct ext2_dirent dirent;
  710. grub_ext2_read_file (diro, 0, 0, fpos, sizeof (struct ext2_dirent),
  711. (char *) &dirent);
  712. if (grub_errno)
  713. return 0;
  714. if (dirent.direntlen == 0)
  715. return 0;
  716. if (dirent.inode != 0 && dirent.namelen != 0)
  717. {
  718. char filename[MAX_NAMELEN + 1];
  719. struct grub_fshelp_node *fdiro;
  720. enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
  721. grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent),
  722. dirent.namelen, filename);
  723. if (grub_errno)
  724. return 0;
  725. fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
  726. if (! fdiro)
  727. return 0;
  728. fdiro->data = diro->data;
  729. fdiro->ino = grub_le_to_cpu32 (dirent.inode);
  730. filename[dirent.namelen] = '\0';
  731. if (dirent.filetype != FILETYPE_UNKNOWN)
  732. {
  733. fdiro->inode_read = 0;
  734. if (dirent.filetype == FILETYPE_DIRECTORY)
  735. type = GRUB_FSHELP_DIR;
  736. else if (dirent.filetype == FILETYPE_SYMLINK)
  737. type = GRUB_FSHELP_SYMLINK;
  738. else if (dirent.filetype == FILETYPE_REG)
  739. type = GRUB_FSHELP_REG;
  740. }
  741. else
  742. {
  743. /* The filetype can not be read from the dirent, read
  744. the inode to get more information. */
  745. grub_ext2_read_inode (diro->data,
  746. grub_le_to_cpu32 (dirent.inode),
  747. &fdiro->inode);
  748. if (grub_errno)
  749. {
  750. grub_free (fdiro);
  751. return 0;
  752. }
  753. fdiro->inode_read = 1;
  754. if ((grub_le_to_cpu16 (fdiro->inode.mode)
  755. & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
  756. type = GRUB_FSHELP_DIR;
  757. else if ((grub_le_to_cpu16 (fdiro->inode.mode)
  758. & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
  759. type = GRUB_FSHELP_SYMLINK;
  760. else if ((grub_le_to_cpu16 (fdiro->inode.mode)
  761. & FILETYPE_INO_MASK) == FILETYPE_INO_REG)
  762. type = GRUB_FSHELP_REG;
  763. }
  764. if (hook (filename, type, fdiro, hook_data))
  765. return 1;
  766. }
  767. fpos += grub_le_to_cpu16 (dirent.direntlen);
  768. }
  769. return 0;
  770. }
  771. /* Open a file named NAME and initialize FILE. */
  772. static grub_err_t
  773. grub_ext2_open (struct grub_file *file, const char *name)
  774. {
  775. struct grub_ext2_data *data;
  776. struct grub_fshelp_node *fdiro = 0;
  777. grub_err_t err;
  778. grub_dl_ref (my_mod);
  779. data = grub_ext2_mount (file->device->disk);
  780. if (! data)
  781. {
  782. err = grub_errno;
  783. goto fail;
  784. }
  785. err = grub_fshelp_find_file (name, &data->diropen, &fdiro,
  786. grub_ext2_iterate_dir,
  787. grub_ext2_read_symlink, GRUB_FSHELP_REG);
  788. if (err)
  789. goto fail;
  790. if (! fdiro->inode_read)
  791. {
  792. err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
  793. if (err)
  794. goto fail;
  795. }
  796. if (fdiro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
  797. {
  798. err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "file is encrypted");
  799. goto fail;
  800. }
  801. grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
  802. grub_free (fdiro);
  803. file->size = grub_le_to_cpu32 (data->inode->size);
  804. file->size |= ((grub_off_t) grub_le_to_cpu32 (data->inode->size_high)) << 32;
  805. file->data = data;
  806. file->offset = 0;
  807. return 0;
  808. fail:
  809. if (fdiro != &data->diropen)
  810. grub_free (fdiro);
  811. grub_free (data);
  812. grub_dl_unref (my_mod);
  813. return err;
  814. }
  815. static grub_err_t
  816. grub_ext2_close (grub_file_t file)
  817. {
  818. grub_free (file->data);
  819. grub_dl_unref (my_mod);
  820. return GRUB_ERR_NONE;
  821. }
  822. /* Read LEN bytes data from FILE into BUF. */
  823. static grub_ssize_t
  824. grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
  825. {
  826. struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
  827. return grub_ext2_read_file (&data->diropen,
  828. file->read_hook, file->read_hook_data,
  829. file->offset, len, buf);
  830. }
  831. /* Context for grub_ext2_dir. */
  832. struct grub_ext2_dir_ctx
  833. {
  834. grub_fs_dir_hook_t hook;
  835. void *hook_data;
  836. struct grub_ext2_data *data;
  837. };
  838. /* Helper for grub_ext2_dir. */
  839. static int
  840. grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
  841. grub_fshelp_node_t node, void *data)
  842. {
  843. struct grub_ext2_dir_ctx *ctx = data;
  844. struct grub_dirhook_info info;
  845. grub_memset (&info, 0, sizeof (info));
  846. if (! node->inode_read)
  847. {
  848. grub_ext2_read_inode (ctx->data, node->ino, &node->inode);
  849. if (!grub_errno)
  850. node->inode_read = 1;
  851. grub_errno = GRUB_ERR_NONE;
  852. }
  853. if (node->inode_read)
  854. {
  855. info.mtimeset = 1;
  856. info.mtime = grub_le_to_cpu32 (node->inode.mtime);
  857. }
  858. info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
  859. grub_free (node);
  860. return ctx->hook (filename, &info, ctx->hook_data);
  861. }
  862. static grub_err_t
  863. grub_ext2_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
  864. void *hook_data)
  865. {
  866. struct grub_ext2_dir_ctx ctx = {
  867. .hook = hook,
  868. .hook_data = hook_data
  869. };
  870. struct grub_fshelp_node *fdiro = 0;
  871. grub_dl_ref (my_mod);
  872. ctx.data = grub_ext2_mount (device->disk);
  873. if (! ctx.data)
  874. goto fail;
  875. grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
  876. grub_ext2_iterate_dir, grub_ext2_read_symlink,
  877. GRUB_FSHELP_DIR);
  878. if (grub_errno)
  879. goto fail;
  880. grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx);
  881. fail:
  882. if (fdiro != &ctx.data->diropen)
  883. grub_free (fdiro);
  884. grub_free (ctx.data);
  885. grub_dl_unref (my_mod);
  886. return grub_errno;
  887. }
  888. static grub_err_t
  889. grub_ext2_label (grub_device_t device, char **label)
  890. {
  891. struct grub_ext2_data *data;
  892. grub_disk_t disk = device->disk;
  893. grub_dl_ref (my_mod);
  894. data = grub_ext2_mount (disk);
  895. if (data)
  896. *label = grub_strndup (data->sblock.volume_name,
  897. sizeof (data->sblock.volume_name));
  898. else
  899. *label = NULL;
  900. grub_dl_unref (my_mod);
  901. grub_free (data);
  902. return grub_errno;
  903. }
  904. static grub_err_t
  905. grub_ext2_uuid (grub_device_t device, char **uuid)
  906. {
  907. struct grub_ext2_data *data;
  908. grub_disk_t disk = device->disk;
  909. grub_dl_ref (my_mod);
  910. data = grub_ext2_mount (disk);
  911. if (data)
  912. {
  913. *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
  914. grub_be_to_cpu16 (data->sblock.uuid[0]),
  915. grub_be_to_cpu16 (data->sblock.uuid[1]),
  916. grub_be_to_cpu16 (data->sblock.uuid[2]),
  917. grub_be_to_cpu16 (data->sblock.uuid[3]),
  918. grub_be_to_cpu16 (data->sblock.uuid[4]),
  919. grub_be_to_cpu16 (data->sblock.uuid[5]),
  920. grub_be_to_cpu16 (data->sblock.uuid[6]),
  921. grub_be_to_cpu16 (data->sblock.uuid[7]));
  922. }
  923. else
  924. *uuid = NULL;
  925. grub_dl_unref (my_mod);
  926. grub_free (data);
  927. return grub_errno;
  928. }
  929. /* Get mtime. */
  930. static grub_err_t
  931. grub_ext2_mtime (grub_device_t device, grub_int64_t *tm)
  932. {
  933. struct grub_ext2_data *data;
  934. grub_disk_t disk = device->disk;
  935. grub_dl_ref (my_mod);
  936. data = grub_ext2_mount (disk);
  937. if (!data)
  938. *tm = 0;
  939. else
  940. *tm = grub_le_to_cpu32 (data->sblock.utime);
  941. grub_dl_unref (my_mod);
  942. grub_free (data);
  943. return grub_errno;
  944. }
  945. static struct grub_fs grub_ext2_fs =
  946. {
  947. .name = "ext2",
  948. .fs_dir = grub_ext2_dir,
  949. .fs_open = grub_ext2_open,
  950. .fs_read = grub_ext2_read,
  951. .fs_close = grub_ext2_close,
  952. .fs_label = grub_ext2_label,
  953. .fs_uuid = grub_ext2_uuid,
  954. .fs_mtime = grub_ext2_mtime,
  955. #ifdef GRUB_UTIL
  956. .reserved_first_sector = 1,
  957. .blocklist_install = 1,
  958. #endif
  959. .next = 0
  960. };
  961. GRUB_MOD_INIT(ext2)
  962. {
  963. grub_fs_register (&grub_ext2_fs);
  964. my_mod = mod;
  965. }
  966. GRUB_MOD_FINI(ext2)
  967. {
  968. grub_fs_unregister (&grub_ext2_fs);
  969. }