1 /* 2 * PROJECT: FreeLoader 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: BTRFS support for FreeLoader 5 * COPYRIGHT: Copyright 2018 Victor Perevertkin (victor@perevertkin.ru) 6 */ 7 8 /* Structures were taken from u-boot, https://github.com/u-boot/u-boot/tree/master/fs/btrfs */ 9 10 #pragma once 11 12 typedef UCHAR u8; 13 typedef USHORT u16; 14 typedef ULONG32 u32; 15 typedef ULONG64 u64; 16 /* type that store on disk, but it is same as cpu type for i386 arch */ 17 typedef u8 __u8; 18 typedef u16 __u16; 19 typedef u32 __u32; 20 typedef u64 __u64; 21 22 #include <fs/crc32c.h> 23 #define btrfs_crc32c(name, len) crc32c_le((u32)~1, name, len) 24 25 #define BTRFS_SUPER_INFO_OFFSET (64 * 1024) 26 #define BTRFS_SUPER_INFO_SIZE 4096 27 #define BTRFS_MAX_LEAF_SIZE 4096 28 #define BTRFS_BLOCK_SHIFT 12 29 #define BTRFS_BLOCK_SIZE (1 << BTRFS_BLOCK_SHIFT) 30 31 #define BTRFS_SUPER_MIRROR_MAX 3 32 #define BTRFS_SUPER_MIRROR_SHIFT 12 33 #define BTRFS_CSUM_SIZE 32 34 #define BTRFS_FSID_SIZE 16 35 #define BTRFS_LABEL_SIZE 256 36 #define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048 37 #define BTRFS_UUID_SIZE 16 38 39 #define BTRFS_VOL_NAME_MAX 255 40 #define BTRFS_NAME_MAX 255 41 42 #define BTRFS_MAGIC "_BHRfS_M" 43 #define BTRFS_MAGIC_L 8 44 #define BTRFS_MAGIC_N 0x4d5f53665248425fULL 45 46 #define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) 47 48 #define BTRFS_DEV_ITEM_KEY 216 49 #define BTRFS_CHUNK_ITEM_KEY 228 50 #define BTRFS_ROOT_REF_KEY 156 51 #define BTRFS_ROOT_ITEM_KEY 132 52 #define BTRFS_EXTENT_DATA_KEY 108 53 #define BTRFS_DIR_ITEM_KEY 84 54 #define BTRFS_DIR_INDEX_KEY 96 55 #define BTRFS_INODE_ITEM_KEY 1 56 #define BTRFS_INODE_REF_KEY 12 57 58 #define BTRFS_EXTENT_TREE_OBJECTID 2ULL 59 #define BTRFS_FS_TREE_OBJECTID 5ULL 60 61 #define BTRFS_FIRST_FREE_OBJECTID 256ULL 62 #define BTRFS_LAST_FREE_OBJECTID -256ULL 63 #define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL 64 65 #define BTRFS_FILE_EXTENT_INLINE 0 66 #define BTRFS_FILE_EXTENT_REG 1 67 #define BTRFS_FILE_EXTENT_PREALLOC 2 68 69 #define BTRFS_MAX_LEVEL 8 70 #define BTRFS_MAX_CHUNK_ENTRIES 256 71 72 #define BTRFS_DEV_ITEMS_OBJECTID 1ULL 73 74 #define BTRFS_FT_REG_FILE 1 75 #define BTRFS_FT_DIR 2 76 #define BTRFS_FT_SYMLINK 7 77 #define BTRFS_FT_XATTR 8 78 #define BTRFS_FT_MAX 9 79 80 #define BTRFS_COMPRESS_NONE 0 81 #define BTRFS_COMPRESS_ZLIB 1 82 #define BTRFS_COMPRESS_LZO 2 83 84 #define ROOT_DIR_WORD 0x002f 85 86 #include <pshpack1.h> 87 88 struct btrfs_disk_key { 89 __u64 objectid; 90 __u8 type; 91 __u64 offset; 92 }; 93 94 struct btrfs_header { 95 /* these first four must match the super block */ 96 __u8 csum[BTRFS_CSUM_SIZE]; 97 __u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ 98 __u64 bytenr; /* which block this node is supposed to live in */ 99 __u64 flags; 100 101 /* allowed to be different from the super from here on down */ 102 __u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; 103 __u64 generation; 104 __u64 owner; 105 __u32 nritems; 106 __u8 level; 107 }; 108 109 struct btrfs_item { 110 struct btrfs_disk_key key; 111 __u32 offset; 112 __u32 size; 113 }; 114 115 struct btrfs_leaf { 116 struct btrfs_header header; 117 struct btrfs_item items[]; 118 }; 119 120 struct btrfs_key_ptr { 121 struct btrfs_disk_key key; 122 __u64 blockptr; 123 __u64 generation; 124 }; 125 126 struct btrfs_node { 127 struct btrfs_header header; 128 struct btrfs_key_ptr ptrs[]; 129 }; 130 131 struct btrfs_dev_item { 132 /* the internal btrfs device id */ 133 __u64 devid; 134 135 /* size of the device */ 136 __u64 total_bytes; 137 138 /* bytes used */ 139 __u64 bytes_used; 140 141 /* optimal io alignment for this device */ 142 __u32 io_align; 143 144 /* optimal io width for this device */ 145 __u32 io_width; 146 147 /* minimal io size for this device */ 148 __u32 sector_size; 149 150 /* type and info about this device */ 151 __u64 type; 152 153 /* expected generation for this device */ 154 __u64 generation; 155 156 /* 157 * starting byte of this partition on the device, 158 * to allow for stripe alignment in the future 159 */ 160 __u64 start_offset; 161 162 /* grouping information for allocation decisions */ 163 __u32 dev_group; 164 165 /* seek speed 0-100 where 100 is fastest */ 166 __u8 seek_speed; 167 168 /* bandwidth 0-100 where 100 is fastest */ 169 __u8 bandwidth; 170 171 /* btrfs generated uuid for this device */ 172 __u8 uuid[BTRFS_UUID_SIZE]; 173 174 /* uuid of FS who owns this device */ 175 __u8 fsid[BTRFS_UUID_SIZE]; 176 }; 177 178 struct btrfs_stripe { 179 __u64 devid; 180 __u64 offset; 181 __u8 dev_uuid[BTRFS_UUID_SIZE]; 182 }; 183 184 struct btrfs_chunk { 185 /* size of this chunk in bytes */ 186 __u64 length; 187 188 /* objectid of the root referencing this chunk */ 189 __u64 owner; 190 191 __u64 stripe_len; 192 __u64 type; 193 194 /* optimal io alignment for this chunk */ 195 __u32 io_align; 196 197 /* optimal io width for this chunk */ 198 __u32 io_width; 199 200 /* minimal io size for this chunk */ 201 __u32 sector_size; 202 203 /* 2^16 stripes is quite a lot, a second limit is the size of a single 204 * item in the btree 205 */ 206 __u16 num_stripes; 207 208 /* sub stripes only matter for raid10 */ 209 __u16 sub_stripes; 210 struct btrfs_stripe stripe; 211 /* additional stripes go here */ 212 }; 213 214 struct btrfs_inode_ref { 215 __u64 index; 216 __u16 name_len; 217 /* name goes here */ 218 }; 219 220 struct btrfs_timespec { 221 __u64 sec; 222 __u32 nsec; 223 }; 224 225 struct btrfs_inode_item { 226 /* nfs style generation number */ 227 __u64 generation; 228 /* transid that last touched this inode */ 229 __u64 transid; 230 __u64 size; 231 __u64 nbytes; 232 __u64 block_group; 233 __u32 nlink; 234 __u32 uid; 235 __u32 gid; 236 __u32 mode; 237 __u64 rdev; 238 __u64 flags; 239 240 /* modification sequence number for NFS */ 241 __u64 sequence; 242 243 /* 244 * a little future expansion, for more than this we can 245 * just grow the inode item and version it 246 */ 247 __u64 reserved[4]; 248 struct btrfs_timespec atime; 249 struct btrfs_timespec ctime; 250 struct btrfs_timespec mtime; 251 struct btrfs_timespec otime; 252 }; 253 254 255 struct btrfs_dir_item { 256 struct btrfs_disk_key location; 257 __u64 transid; 258 __u16 data_len; 259 __u16 name_len; 260 __u8 type; 261 }; 262 263 struct btrfs_root_item { 264 struct btrfs_inode_item inode; 265 __u64 generation; 266 __u64 root_dirid; 267 __u64 bytenr; 268 __u64 byte_limit; 269 __u64 bytes_used; 270 __u64 last_snapshot; 271 __u64 flags; 272 __u32 refs; 273 struct btrfs_disk_key drop_progress; 274 __u8 drop_level; 275 __u8 level; 276 }; 277 278 struct btrfs_root_ref { 279 __u64 dirid; 280 __u64 sequence; 281 __u16 name_len; 282 }; 283 284 struct btrfs_file_extent_item { 285 /* 286 * transaction id that created this extent 287 */ 288 __u64 generation; 289 /* 290 * max number of bytes to hold this extent in ram 291 * when we split a compressed extent we can't know how big 292 * each of the resulting pieces will be. So, this is 293 * an upper limit on the size of the extent in ram instead of 294 * an exact limit. 295 */ 296 __u64 ram_bytes; 297 298 /* 299 * 32 bits for the various ways we might encode the data, 300 * including compression and encryption. If any of these 301 * are set to something a given disk format doesn't understand 302 * it is treated like an incompat flag for reading and writing, 303 * but not for stat. 304 */ 305 __u8 compression; 306 __u8 encryption; 307 __u16 other_encoding; /* spare for later use */ 308 309 /* are we inline data or a real extent? */ 310 __u8 type; 311 312 /* 313 * disk space consumed by the extent, checksum blocks are included 314 * in these numbers 315 * 316 * At this offset in the structure, the inline extent data start. 317 */ 318 __u64 disk_bytenr; 319 __u64 disk_num_bytes; 320 /* 321 * the logical offset in file blocks (no csums) 322 * this extent record is for. This allows a file extent to point 323 * into the middle of an existing extent on disk, sharing it 324 * between two snapshots (useful if some bytes in the middle of the 325 * extent have changed 326 */ 327 __u64 offset; 328 /* 329 * the logical number of file blocks (no csums included). This 330 * always reflects the size uncompressed and without encoding. 331 */ 332 __u64 num_bytes; 333 334 }; 335 336 struct btrfs_super_block { 337 __u8 csum[BTRFS_CSUM_SIZE]; 338 /* the first 4 fields must match struct btrfs_header */ 339 __u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ 340 __u64 bytenr; /* this block number */ 341 __u64 flags; 342 343 /* allowed to be different from the btrfs_header from here own down */ 344 __u64 magic; 345 __u64 generation; 346 __u64 root; 347 __u64 chunk_root; 348 __u64 log_root; 349 350 /* this will help find the new super based on the log root */ 351 __u64 log_root_transid; 352 __u64 total_bytes; 353 __u64 bytes_used; 354 __u64 root_dir_objectid; 355 __u64 num_devices; 356 __u32 sectorsize; 357 __u32 nodesize; 358 __u32 __unused_leafsize; 359 __u32 stripesize; 360 __u32 sys_chunk_array_size; 361 __u64 chunk_root_generation; 362 __u64 compat_flags; 363 __u64 compat_ro_flags; 364 __u64 incompat_flags; 365 __u16 csum_type; 366 __u8 root_level; 367 __u8 chunk_root_level; 368 __u8 log_root_level; 369 struct btrfs_dev_item dev_item; 370 371 char label[BTRFS_LABEL_SIZE]; 372 373 __u64 cache_generation; 374 __u64 uuid_tree_generation; 375 376 /* future expansion */ 377 __u64 reserved[30]; 378 __u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; 379 }; 380 381 #include <poppack.h> 382 383 union tree_buf { 384 struct btrfs_header header; 385 struct btrfs_node node; 386 struct btrfs_leaf leaf; 387 }; 388 389 /* remember how we get to a node/leaf */ 390 struct btrfs_path { 391 u64 offsets[BTRFS_MAX_LEVEL]; 392 int itemsnr[BTRFS_MAX_LEVEL]; 393 int slots[BTRFS_MAX_LEVEL]; 394 /* remember whole last leaf */ 395 union tree_buf *tree_buf; 396 }; 397 398 /* store logical offset to physical offset mapping */ 399 struct btrfs_chunk_map_item { 400 u64 logical; 401 u64 length; 402 u64 devid; 403 u64 physical; 404 }; 405 406 struct btrfs_chunk_map { 407 struct btrfs_chunk_map_item *map; 408 u32 map_length; 409 u32 cur_length; 410 }; 411 412 typedef struct _BTRFS_INFO *PBTRFS_INFO; 413 414 typedef struct { 415 u64 inr; 416 u64 position; 417 struct btrfs_inode_item inode; 418 PBTRFS_INFO Volume; 419 } btrfs_file_info, * pbtrfs_file_info; 420 421 const DEVVTBL* BtrFsMount(ULONG DeviceId); 422