// // Copyright (c) 2009-2019 Apple Inc. All rights reserved. // // lf_cs_disk_format.h - Defines on disk format for Apple_CoreStorage physical // volumes for livefiles Apple_CoreStorage plugin. // // This header is copied from CoreStorage project. // #ifndef _LF_CS_DISK_FORMAT_H #define _LF_CS_DISK_FORMAT_H #define MAX_CKSUM_NBYTES 8 #define CORESTORAGE_FORMAT_VERSION 1 // // The 'dl_lvg.lvg_signature' in a DiskLabel (mimics 'CORESTOR') // #define CORE_STORAGE_SIGNATURE 0xC07E5707 // // The 'mh_endianness' used to check endianness (non-palindromic 'CS') // #define BYTE_ORDER_MARK 0x5343 // // Metadata block header. // struct metadata_header { // // Block cksum. // uint8_t mh_cksum[MAX_CKSUM_NBYTES]; // // The on-disk format version of CoreStorage. // uint16_t mh_format_version; // // Enum metadata_blk_type (BLK_TYPE_*). // uint8_t mh_blk_type; // // Enum metadata_blk_subtype (BLK_SUBTYPE_*), for b-tree/fsck. // uint8_t mh_blk_subtype; // // The version of CoreStorage software that wrote this block. // uint32_t mh_bundle_version; // // Transaction identification. // uint64_t mh_txg_id; uint64_t mh_vaddr; uint64_t mh_laddr; // // Records the owner of the block. The owner of any blocks in a B-Tree // is the root of the tree. The owner of any blocks in a list like // structure (DSD list, attribute blocks) is the first block in the // list. This field can be used for crash recovery by fsck_cs. For // example, if this field has the B-Tree root vaddr that this block // belongs, fsck_cs could reconstruct the B-Tree based on all leaf // nodes. // uint64_t mh_blk_owner; // // Block size (LVG MLV blksz). // uint32_t mh_blk_size; // // Flags (BLK_FLAG_*). // uint8_t mh_blk_flags; // // Reserved for future extensions // make blk header 64 bytes (crypto alignment) // uint8_t mh_reserved1; uint16_t mh_reserved2; uint64_t mh_reserved8; }; typedef struct metadata_header metadata_header_t; int check_dk_metadata_header_size[sizeof(metadata_header_t) == 64 ? 1 : -1]; #define NUM_VOL_HEADERS 2 #define VOL_HEADER_NBYTES 512 #define MAX_DISK_LABELS 4 #define MAX_WIPEKEY_NBYTES 64 // // This structure is padded such that it is of correct size. // struct dk_vol_header { union { struct { metadata_header_t vh_header; // // PV size in bytes, rounded down to VOL_HEADER_NBYTES // boundary. // uint64_t vh_pv_nbytes; // // If this is not 0, it records a PV resize operation // uint64_t vh_pv_resize; // // If this is not 0, it records the old Volume Header // location before the PV resize started; it is again 0 // after completion. // uint64_t vh_old_pv_nbytes; // // The cpu-platform endian that formatted this LVG. // uint16_t vh_endianness; // // Checksum algorithm of VolHdr metadata header. // uint16_t vh_cksum_alg; // // Reserved. // uint16_t vh_reserved2; // // Number of disk labels. // uint16_t vh_num_labels; // // Label address uses this block size. // uint32_t vh_blksz; // // Maximum disk label size. // uint32_t vh_label_max_nbytes; // // (Physical) Location of the new/old disk labels. // uint64_t vh_label_addr[MAX_DISK_LABELS]; uint64_t vh_move_label_addr[MAX_DISK_LABELS]; // // PV MLV/plist wipe keys ([0] is active, [1] future // re-key). // uint16_t vh_wipe_key_nbytes[2]; uint16_t vh_wipe_key_alg[2]; uint8_t vh_wipe_key[2][MAX_WIPEKEY_NBYTES]; // // UUID of this PV and its LVG (for bootstrap/multi-PV) // uint8_t vh_pv_uuid[16]; uint8_t vh_lvg_uuid[16]; }; uint8_t vh_padding[VOL_HEADER_NBYTES]; }; }; typedef struct dk_vol_header dk_vol_header_t; int check_dk_vol_header_size[sizeof(dk_vol_header_t) == VOL_HEADER_NBYTES ? 1 : -1]; // // Existing block types cannot be changed! // enum metadata_blk_type { // // The values of the B-Tree types are important. They are the results // of the bit operations of BTREE_ROOT, BTREE_NODE, and BTREE_LEAF in // B-Tree code. // BLK_TYPE_BTREE_NODE = 2, // A B-Tree node that is not a leaf. BLK_TYPE_BTREE_ROOT_NODE = 3, // A non-leaf B-Tree node that is also root. BLK_TYPE_BTREE_LEAF = 4, // A B-Tree leaf node that is not a root. BLK_TYPE_BTREE_ROOT_LEAF = 5, // A B-Tree leaf node that is also root. BLK_TYPE_VOL_HEADER = 16, // // Fixed part of disk label (first MLV block size). // BLK_TYPE_DISK_LABEL = 17, BLK_TYPE_DISK_LABEL_CONT = 18, // Variable part of disk label. // // LFS related blocks // // // MLV Partial Segment (PS) header block, first block of the first // PS in a Group of Partial Segments (GPS). // BLK_TYPE_PS_HEADER = 19, // // MLV Continuation Partial Segment block, first block of a Partial // Segment (PS) in a Group of Partial Segments (GPS), where the PS // is not the first PS in the GPS. // BLK_TYPE_PS_CONT_HDR = 20, // // MLV Partial Segment (PS) Overflow header block, which holds // information about added or deleted virtual blocks. // BLK_TYPE_PS_OVERFLOW_HDR = 21, // // MLV Virtual Address Table (VAT) blocks, which holds VAT information. // BLK_TYPE_VAT = 22, // // MLV Segment Usage Table (SUT) blocks, which holds SUT information. // BLK_TYPE_SUT = 23, // // Metadata in MLV. // // MLV super block, the starting point of all MLV metadata. // BLK_TYPE_MLV_SUPERBLOCK = 24, // // Logical Volume Family (LVF) super block. // BLK_TYPE_LV_FAMILY_SUPERBLOCK = 25, // // Logical Volume (LV) super block. // BLK_TYPE_LV_SUPERBLOCK = 26, // // Hold more LV attributes when they don't fit in the LV superblock. // BLK_TYPE_LV_XATTR = 27, // // Holds the Physical Volume (PV) information. // BLK_TYPE_PV_TABLE = 28, // // Holds the Physical Volume (PV) Freespace Log (FLOG) table // information. // BLK_TYPE_PV_FLOG_TABLE = 29, BLK_TYPE_UNUSED_1 = 30, BLK_TYPE_UNUSED_2 = 31, BLK_TYPE_UNUSED_3 = 32, // // Used for space sharing, records the amount of free space not used by // the file system inside the Logical Volume. // BLK_TYPE_LV_FREE_SPACE_SUMMARY_DEPRECATED = 33, // // Used for Physical Volume (PV) free space management, records the // amount of free space in each chunk of the PV and has pointers to // the Freespace Log (FLOG). // BLK_TYPE_PV_SUMMARY_TABLE = 34, BLK_TYPE_UNUSED_4 = 35, // // Hold more LV Family attributes when they don't fit in the // LVF superblock. // BLK_TYPE_LV_FAMILY_XATTR = 36, // // Hold more Delayed Secure Deletion (DSD) list entries when // they cannot fit in the LVF superblock. // BLK_TYPE_DSD_LIST = 37, // // This block type is used to record information about bad sectors // encountered during background encryption/decryption. // BLK_TYPE_BAD_SECTOR_LIST = 38, // // For debugging: block is in dummy tree. // BLK_TYPE_DUMMY = 39, // // New types are added here to preserve compatible on-disk format. // NUM_BLK_TYPES, BLK_TYPE_UNKNOWN = 255, // Not used for on-disk blocks. }; // // Existing block subtypes cannot be changed! // enum metadata_blk_subtype { // // Metadata in MLV. // BLK_SUBTYPE_NO_SUBTYPE = 0, BLK_SUBTYPE_LV_FAMILY_TREE, BLK_SUBTYPE_LV_SNAPSHOT_TREE, BLK_SUBTYPE_LV_ADDR_MAP_TREE, BLK_SUBTYPE_PV_REFCOUNT_TREE, BLK_SUBTYPE_LV_UNUSED_SPACE_TREE, BLK_SUBTYPE_LVF_REFCOUNT_TREE, // // The b-tree that holds blocks to populate MLV for testing. // BLK_SUBTYPE_DUMMY_TREE, // // New types are added here to preserve compatible on-disk format. // NUM_BLK_SUBTYPES, BLK_SUBTYPE_UNKNOWN = 255, // Not used for on-disk blocks. }; typedef enum metadata_blk_subtype metadata_blk_subtype_t; // // This block should be in the DSD List. It is not in the DSD list when it // is first created. But when it is modified or killed, it will be included // in the DSD list. // #define BLK_FLAG_IN_DSD_LIST 0x02 // // On-disk information of LVG. // struct lvg_info { uint32_t lvg_signature; // A signature that CoreStorage recognizes. // // Version numbers can help diagnose problems. // // // The version of CoreStorage that created the LVG. // uint32_t lvg_creator_version; // // The version of CoreStorage that modified the LVG the last time. // uint32_t lvg_writer_version; // // The interval to sync MLV metadata in milliseconds. // uint16_t lvg_sync_interval_ms; // // Checksum algorithm used for all metadata blocks and data blocks. // uint8_t lvg_metadata_cksum_alg; // // Do not punch hole in the LVs on trim, so that the sparse LVs can become // less and less sparse over time. // uint8_t lvg_no_punch_hole_on_trim; // // These fields control our forwards/backwards compatibility. // Features fall into three categories: compatible, read-only // compatible, and incompatible. For any given version of the // file system code, you can mount a file-system with any set // of compatible features. If the file system encounters bits // that are set in the read-only compatible features field and // it does not know about those features then it must only mount // the file system read-only. If the file system encounters // any bits set in the incompatible features field that it does // not know about, then it must not mount or modify the file // system in any way. // // The idea for these compatibility fields is rather shamelessly // stolen from rocky and ext2. // // uint64_t lvg_compatible_features; uint64_t lvg_read_only_compatible_features; uint64_t lvg_incompatible_features; // // When Soft Snapshot is enabled, this is the minimum granularity the // extents will be updated with new timestamp. This is OK to be 0, so a // predefined constant will be used. // uint64_t lvg_soft_snapshot_granularity_nbytes; // // When LV checksum is enabled, this is the minimum granularity of data // being checksummed. This is OK to be 0, so a predefined constant will // be used. // uint64_t lvg_checksum_granularity_nbytes; // // The min/max versions of CoreStorage that ever wrote to the LVG. // uint32_t lvg_min_writer_version; uint32_t lvg_max_writer_version; // // The following unused fields are reserved so we don't need to break // format compatibility too often if we need more per-LVG fields. // uint64_t lvg_unused1; uint64_t lvg_unused2; uint64_t lvg_unused3; }; typedef struct lvg_info lvg_info_t; #endif /* _LF_CS_DISK_FORMAT_H */