1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by ./scripts/Create-CopyPatch.
4 # T2 SDE: package/.../grub/grub-0.97-ext4extents.patch
5 # Copyright (C) 2009 The T2 SDE Project
7 # More information can be found in the files COPYING and README.
9 # This patch file is dual-licensed. It is available under the license the
10 # patched project is licensed under, as long as it is an OpenSource license
11 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
12 # of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
15 # --- T2-COPYRIGHT-NOTE-END ---
17 --- grub-0.97.orig/stage2/fsys_ext2fs.c
18 +++ grub-0.97/stage2/fsys_ext2fs.c
19 @@ -41,6 +41,7 @@ typedef __signed__ short __s16;
20 typedef unsigned short __u16;
21 typedef __signed__ int __s32;
22 typedef unsigned int __u32;
23 +typedef unsigned long long __u64;
26 * Constants relative to the data blocks, from ext2_fs.h
27 @@ -61,9 +62,9 @@ struct ext2_super_block
28 __u32 s_free_inodes_count; /* Free inodes count */
29 __u32 s_first_data_block; /* First Data Block */
30 __u32 s_log_block_size; /* Block size */
31 - __s32 s_log_frag_size; /* Fragment size */
32 + __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */
33 __u32 s_blocks_per_group; /* # Blocks per group */
34 - __u32 s_frags_per_group; /* # Fragments per group */
35 + __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */
36 __u32 s_inodes_per_group; /* # Inodes per group */
37 __u32 s_mtime; /* Mount time */
38 __u32 s_wtime; /* Write time */
39 @@ -72,7 +73,7 @@ struct ext2_super_block
40 __u16 s_magic; /* Magic signature */
41 __u16 s_state; /* File system state */
42 __u16 s_errors; /* Behaviour when detecting errors */
44 + __u16 s_minor_rev_level; /* minor revision level */
45 __u32 s_lastcheck; /* time of last check */
46 __u32 s_checkinterval; /* max. time between checks */
47 __u32 s_creator_os; /* OS */
48 @@ -119,7 +120,7 @@ struct ext2_super_block
49 __u32 s_hash_seed[4]; /* HTREE hash seed */
50 __u8 s_def_hash_version; /* Default hash version to use */
51 __u8 s_jnl_backup_type; /* Default type of journal backup */
52 - __u16 s_reserved_word_pad;
53 + __u16 s_desc_size; /* size of group descriptor */
54 __u32 s_default_mount_opts;
55 __u32 s_first_meta_bg; /* First metablock group */
56 __u32 s_mkfs_time; /* When the filesystem was created */
57 @@ -127,7 +128,7 @@ struct ext2_super_block
58 __u32 s_reserved[172]; /* Padding to the end of the block */
61 -struct ext2_group_desc
62 +struct ext4_group_desc
64 __u32 bg_block_bitmap; /* Blocks bitmap block */
65 __u32 bg_inode_bitmap; /* Inodes bitmap block */
66 @@ -135,8 +136,18 @@ struct ext2_group_desc
67 __u16 bg_free_blocks_count; /* Free blocks count */
68 __u16 bg_free_inodes_count; /* Free inodes count */
69 __u16 bg_used_dirs_count; /* Directories count */
71 - __u32 bg_reserved[3];
72 + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
73 + __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
74 + __u16 bg_itable_unused; /* Unused inodes count */
75 + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
76 + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
77 + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
78 + __u32 bg_inode_table_hi; /* Inodes table block MSB */
79 + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
80 + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
81 + __u16 bg_used_dirs_count_hi; /* Directories count MSB */
82 + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
83 + __u32 bg_reserved2[3];
87 @@ -174,22 +185,22 @@ struct ext2_inode
88 __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
89 __u32 i_version; /* File version (for NFS) */
90 __u32 i_file_acl; /* File ACL */
91 - __u32 i_dir_acl; /* Directory ACL */
92 - __u32 i_faddr; /* Fragment address */
94 + __u32 i_obso_faddr; /* Obsoleted fragment address */
99 - __u8 l_i_frag; /* Fragment number */
100 - __u8 l_i_fsize; /* Fragment size */
102 - __u32 l_i_reserved2[2];
103 + __u16 l_i_blocks_high; /* were l_i_reserved1 */
104 + __u16 l_i_file_acl_high;
105 + __u16 l_i_uid_high; /* these 2 fields */
106 + __u16 l_i_gid_high; /* were reserved2[0] */
107 + __u32 l_i_reserved2;
112 - __u8 h_i_frag; /* Fragment number */
113 - __u8 h_i_fsize; /* Fragment size */
114 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
118 @@ -198,16 +209,36 @@ struct ext2_inode
122 - __u8 m_i_frag; /* Fragment number */
123 - __u8 m_i_fsize; /* Fragment size */
125 + __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
126 + __u16 m_i_file_acl_high;
127 __u32 m_i_reserved2[2];
131 osd2; /* OS dependent 2 */
132 + __u16 i_extra_isize;
134 + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
135 + __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
136 + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
137 + __u32 i_crtime; /* File Creation time */
138 + __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
139 + __u32 i_version_hi; /* high 32 bits for 64-bit version */
142 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
143 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
144 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
145 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
147 +#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
148 + ( sb->s_feature_incompat & mask )
150 +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
151 +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
153 +#define EXT4_MIN_DESC_SIZE 32
156 #define NAME_MAX 255 /* # chars in a file name */
158 @@ -225,6 +256,57 @@ struct ext2_dir_entry
159 char name[EXT2_NAME_LEN]; /* File name */
162 +/* linux/ext4_fs_extents.h */
163 +/* This is the extent on-disk structure.
164 + * It's used at the bottom of the tree.
168 + __u32 ee_block; /* first logical block extent covers */
169 + __u16 ee_len; /* number of blocks covered by extent */
170 + __u16 ee_start_hi; /* high 16 bits of physical block */
171 + __u32 ee_start_lo; /* low 32 bits of physical block */
175 + * This is index on-disk structure.
176 + * It's used at all the levels except the bottom.
178 +struct ext4_extent_idx
180 + __u32 ei_block; /* index covers logical blocks from 'block' */
181 + __u32 ei_leaf_lo; /* pointer to the physical block of the next *
182 + * level. leaf or next index could be there */
183 + __u16 ei_leaf_hi; /* high 16 bits of physical block */
188 + * Each block (leaves and indexes), even inode-stored has header.
190 +struct ext4_extent_header
192 + __u16 eh_magic; /* probably will support different formats */
193 + __u16 eh_entries; /* number of valid entries */
194 + __u16 eh_max; /* capacity of store in entries */
195 + __u16 eh_depth; /* has tree real underlying blocks? */
196 + __u32 eh_generation; /* generation of the tree */
199 +#define EXT4_EXT_MAGIC (0xf30a)
200 +#define EXT_FIRST_EXTENT(__hdr__) \
201 + ((struct ext4_extent *) (((char *) (__hdr__)) + \
202 + sizeof(struct ext4_extent_header)))
203 +#define EXT_FIRST_INDEX(__hdr__) \
204 + ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
205 + sizeof(struct ext4_extent_header)))
206 +#define EXT_LAST_EXTENT(__hdr__) \
207 + (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
208 +#define EXT_LAST_INDEX(__hdr__) \
209 + (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
215 * EXT2_DIR_PAD defines the directory entries boundaries
216 @@ -276,8 +358,17 @@ struct ext2_dir_entry
217 /* kind of from ext2/super.c */
218 #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
220 +/* sizeof(struct ext2_group_desc) is changed in ext4
221 + * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate
222 + * number of desc per block, while ext4 uses superblock->s_desc_size in stead
223 + * superblock->s_desc_size is not available in ext2/3
225 +#define EXT2_DESC_SIZE(s) \
226 + (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \
227 + s->s_desc_size : EXT4_MIN_DESC_SIZE)
228 #define EXT2_DESC_PER_BLOCK(s) \
229 - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
230 + (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
233 #define S_IFMT 00170000
234 #define S_IFLNK 0120000
235 @@ -439,6 +530,122 @@ ext2fs_block_map (int logical_block)
236 [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
239 +/* extent binary search index
240 + * find closest index in the current level extent tree
241 + * kind of from ext4_ext_binsearch_idx in ext4/extents.c
243 +static struct ext4_extent_idx*
244 +ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
246 + struct ext4_extent_idx *r, *l, *m;
247 + l = EXT_FIRST_INDEX(eh) + 1;
248 + r = EXT_LAST_INDEX(eh);
251 + m = l + (r - l) / 2;
252 + if (logical_block < m->ei_block)
257 + return (struct ext4_extent_idx*)(l - 1);
260 +/* extent binary search
261 + * find closest extent in the leaf level
262 + * kind of from ext4_ext_binsearch in ext4/extents.c
264 +static struct ext4_extent*
265 +ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
267 + struct ext4_extent *r, *l, *m;
268 + l = EXT_FIRST_EXTENT(eh) + 1;
269 + r = EXT_LAST_EXTENT(eh);
272 + m = l + (r - l) / 2;
273 + if (logical_block < m->ee_block)
278 + return (struct ext4_extent*)(l - 1);
281 +/* Maps extents enabled logical block into physical block via an inode.
282 + * EXT4_HUGE_FILE_FL should be checked before calling this.
285 +ext4fs_block_map (int logical_block)
287 + struct ext4_extent_header *eh;
288 + struct ext4_extent *ex, *extent;
289 + struct ext4_extent_idx *ei, *index;
295 + for (i = (unsigned char *) INODE;
296 + i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
299 + printf ("%c", "0123456789abcdef"[*i >> 4]);
300 + printf ("%c", "0123456789abcdef"[*i % 16]);
301 + if (!((i + 1 - (unsigned char *) INODE) % 16))
310 + printf ("logical block %d\n", logical_block);
311 +#endif /* E2DEBUG */
312 + eh = (struct ext4_extent_header*)INODE->i_block;
313 + if (eh->eh_magic != EXT4_EXT_MAGIC)
315 + errnum = ERR_FSYS_CORRUPT;
318 + while((depth = eh->eh_depth) != 0)
319 + { /* extent index */
320 + if (eh->eh_magic != EXT4_EXT_MAGIC)
322 + errnum = ERR_FSYS_CORRUPT;
325 + ei = ext4_ext_binsearch_idx(eh, logical_block);
326 + if (ei->ei_leaf_hi)
327 + {/* 64bit physical block number not supported */
328 + errnum = ERR_FILELENGTH;
331 + if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
333 + errnum = ERR_FSYS_CORRUPT;
336 + eh = (struct ext4_extent_header*)DATABLOCK1;
339 + /* depth==0, we come to the leaf */
340 + ex = ext4_ext_binsearch(eh, logical_block);
341 + if (ex->ee_start_hi)
342 + {/* 64bit physical block number not supported */
343 + errnum = ERR_FILELENGTH;
346 + if ((ex->ee_block + ex->ee_len) < logical_block)
348 + errnum = ERR_FSYS_CORRUPT;
351 + return ex->ee_start_lo + logical_block - ex->ee_block;
355 /* preconditions: all preconds of ext2fs_block_map */
357 ext2fs_read (char *buf, int len)
358 @@ -473,6 +680,11 @@ ext2fs_read (char *buf, int len)
359 /* find the (logical) block component of our location */
360 logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
361 offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
362 + /* map extents enabled logical block number to physical fs on-dick block number */
363 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
364 + && INODE->i_flags & EXT4_EXTENTS_FL)
365 + map = ext4fs_block_map (logical_block);
367 map = ext2fs_block_map (logical_block);
369 printf ("map=%d\n", map);
370 @@ -557,7 +769,7 @@ ext2fs_dir (char *dirname)
371 int desc; /* index within that group */
372 int ino_blk; /* fs pointer of the inode's information */
373 int str_chk = 0; /* used to hold the results of a string compare */
374 - struct ext2_group_desc *gdp;
375 + struct ext4_group_desc *ext4_gdp;
376 struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
378 char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
379 @@ -603,8 +815,15 @@ ext2fs_dir (char *dirname)
384 - ino_blk = gdp[desc].bg_inode_table +
385 + ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
386 + desc * EXT2_DESC_SIZE(SUPERBLOCK));
387 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
388 + && (! ext4_gdp->bg_inode_table_hi))
389 + {/* 64bit itable not supported */
390 + errnum = ERR_FILELENGTH;
393 + ino_blk = ext4_gdp->bg_inode_table +
394 (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
395 >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
397 @@ -681,7 +900,10 @@ ext2fs_dir (char *dirname)
399 linkbuf[filemax + len] = '\0';
401 - /* Read the symlink data. */
402 + /* Read the symlink data.
403 + * Slow symlink is extents enabled
404 + * But since grub_read invokes ext2fs_read, nothing to change here
406 if (! ext2_is_fast_symlink ())
408 /* Read the necessary blocks, and reset the file pointer. */
409 @@ -692,7 +914,9 @@ ext2fs_dir (char *dirname)
413 - /* Copy the data directly from the inode. */
414 + /* Copy the data directly from the inode.
415 + * Fast symlink is not extents enabled
418 memmove (linkbuf, (char *) INODE->i_block, len);
420 @@ -726,6 +950,13 @@ ext2fs_dir (char *dirname)
421 errnum = ERR_BAD_FILETYPE;
424 + /* if file is too large, just stop and report an error*/
425 + if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
427 + /* file too large, stop reading */
428 + errnum = ERR_FILELENGTH;
432 filemax = (INODE->i_size);
434 @@ -780,17 +1011,28 @@ ext2fs_dir (char *dirname)
437 /* else, find the (logical) block component of our location */
438 + /* ext4 logical block number the same as ext2/3 */
439 blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
441 /* we know which logical block of the directory entry we are looking
442 for, now we have to translate that to the physical (fs) block on
444 + /* map extents enabled logical block number to physical fs on-dick block number */
445 + if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
446 + && INODE->i_flags & EXT4_EXTENTS_FL)
447 + map = ext4fs_block_map (blk);
449 map = ext2fs_block_map (blk);
451 printf ("fs block=%d\n", map);
454 - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
460 + if (!ext2_rdfsb (map, DATABLOCK2))
462 errnum = ERR_FSYS_CORRUPT;