mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-29 12:35:53 +01:00
321 lines
8.6 KiB
C
321 lines
8.6 KiB
C
|
/** @file
|
|||
|
|
|||
|
APFS Driver Loader - loads apfs.efi from EfiBootRecord block
|
|||
|
|
|||
|
Copyright (c) 2017-2018, savvas
|
|||
|
|
|||
|
All rights reserved.
|
|||
|
|
|||
|
This program and the accompanying materials
|
|||
|
are licensed and made available under the terms and conditions of the BSD License
|
|||
|
which accompanies this distribution. The full text of the license may be found at
|
|||
|
http://opensource.org/licenses/bsd-license.php
|
|||
|
|
|||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
|
|||
|
**/
|
|||
|
|
|||
|
#ifndef APFS_DRIVER_LOADER_H_
|
|||
|
#define APFS_DRIVER_LOADER_H_
|
|||
|
|
|||
|
#define APFS_DRIVER_INFO_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('A', 'F', 'J', 'S')
|
|||
|
|
|||
|
//
|
|||
|
// Container Superblock definitions
|
|||
|
//
|
|||
|
#define APFS_CSB_SIGNATURE SIGNATURE_32 ('N', 'X', 'S', 'B')
|
|||
|
#define APFS_CSB_MAX_FILE_SYSTEMS 100
|
|||
|
#define APFS_CSB_EPH_INFO_COUNT 4
|
|||
|
#define APFS_CSB_EPH_MIN_BLOCK_COUNT 8
|
|||
|
#define APFS_CSB_MAX_FILE_SYSTEM_EPH_STRUCTS 4
|
|||
|
#define APFS_CSB_TX_MIN_CHECKPOINT_COUNT 4
|
|||
|
#define APFS_CSB_EPH_INFO_VERSION_1 1
|
|||
|
#define APFS_CSB_NUM_COUNTERS 32
|
|||
|
|
|||
|
//
|
|||
|
// Volume Superblock definitions
|
|||
|
//
|
|||
|
#define APFS_VSB_SIGNATURE SIGNATURE_32 ('A', 'P', 'S', 'B')
|
|||
|
|
|||
|
//
|
|||
|
// EfiBootRecord block definitions
|
|||
|
//
|
|||
|
#define APFS_EFIBOOTRECORD_SIGNATURE SIGNATURE_32 ('J', 'S', 'D', 'R')
|
|||
|
#define APFS_EFIBOOTRECORD_VERSION 1
|
|||
|
|
|||
|
typedef struct PhysicalRange_ {
|
|||
|
INT64 StartPhysicalAddr;
|
|||
|
UINT64 BlockCount;
|
|||
|
} PhysicalRange;
|
|||
|
|
|||
|
typedef struct UNKNOWNFIELD_
|
|||
|
{
|
|||
|
UINT32 Unknown1;
|
|||
|
EFI_HANDLE Handle;
|
|||
|
EFI_HANDLE AgentHandle;
|
|||
|
UINT8 Unknown2[88];
|
|||
|
UINT64 Unknown3;
|
|||
|
} UNKNOWNFIELD;
|
|||
|
|
|||
|
//
|
|||
|
// Private ApfsJumpStart structure
|
|||
|
//
|
|||
|
typedef struct _APFS_DRIVER_INFO_PRIVATE_DATA
|
|||
|
{
|
|||
|
UINT32 Magic;
|
|||
|
EFI_HANDLE ControllerHandle;
|
|||
|
EFI_HANDLE DriverBindingHandle;
|
|||
|
APFS_EFIBOOTRECORD_LOCATION_INFO EfiBootRecordLocationInfo;
|
|||
|
UINT8 Unknown1[24];
|
|||
|
EFI_EVENT NotifyEvent;
|
|||
|
VOID *ApfsDriverPtr;
|
|||
|
UINT32 ApfsDriverSize;
|
|||
|
UINT32 ContainerBlockSize;
|
|||
|
UINT64 ContainerTotalBlocks;
|
|||
|
UINT8 Unknown2[4];
|
|||
|
UINT32 Unknown3;
|
|||
|
EFI_BLOCK_IO_PROTOCOL *BlockIoInterface;
|
|||
|
UNKNOWNFIELD *Unknown4;
|
|||
|
UINT64 UnknownAddress;
|
|||
|
} APFS_DRIVER_INFO_PRIVATE_DATA;
|
|||
|
|
|||
|
#define APFS_EFIBOOTRECORD_INFO_PRIVATE_DATA_FROM_THIS(a) \
|
|||
|
CR(a, APFS_DRIVER_INFO_PRIVATE_DATA, EfiBootRecordLocationInfo, APFS_DRIVER_INFO_PRIVATE_DATA_SIGNATURE)
|
|||
|
|
|||
|
#pragma pack(push, 1)
|
|||
|
typedef struct APFS_BLOCK_HEADER_
|
|||
|
{
|
|||
|
//
|
|||
|
// Fletcher checksum, 64-bit. All metadata blocks
|
|||
|
//
|
|||
|
UINT64 Checksum;
|
|||
|
//
|
|||
|
// The object's identifier
|
|||
|
// Probably plays a role in the Btree structure NXSB=01 00
|
|||
|
// APSB=02 04, 06 04 and 08 04
|
|||
|
// nid
|
|||
|
//
|
|||
|
UINT64 ObjectOid;
|
|||
|
//
|
|||
|
// The identifier of the most recent transaction that this object
|
|||
|
// was modified in.
|
|||
|
//
|
|||
|
UINT64 ObjectXid;
|
|||
|
//
|
|||
|
// The objectʼs type and flags.
|
|||
|
// #define OBJ_VIRTUAL 0x00000000
|
|||
|
// #define OBJ_EPHEMERAL 0x80000000
|
|||
|
// #define OBJ_PHYSICAL 0x40000000
|
|||
|
// #define OBJ_NOHEADER 0x20000000
|
|||
|
// #define OBJ_ENCRYPTED 0x10000000
|
|||
|
// #define OBJ_NONPERSISTENT 0x08000000
|
|||
|
//
|
|||
|
UINT32 ObjectType;
|
|||
|
//
|
|||
|
// The objectʼs subtype
|
|||
|
// Subtypes indicate the type of data stored in a data structure such as a
|
|||
|
// B-tree. For example, a node in a B-tree that contains volume records has
|
|||
|
// a type of OBJECT_TYPE_BTREE_NODE and a subtype of OBJECT_TYPE_FS.
|
|||
|
//
|
|||
|
UINT32 ObjectSubType;
|
|||
|
} APFS_BLOCK_HEADER;
|
|||
|
#pragma pack(pop)
|
|||
|
|
|||
|
/**
|
|||
|
NXSB Container Superblock
|
|||
|
The container superblock is the entry point to the filesystem.
|
|||
|
Because of the structure with containers and flexible volumes,
|
|||
|
allocation needs to handled on a container level.
|
|||
|
The container superblock contains information on the blocksize,
|
|||
|
the number of blocks and pointers to the spacemanager for this task.
|
|||
|
Additionally the block IDs of all volumes are stored in the superblock.
|
|||
|
To map block IDs to block offsets a pointer to a block map b-tree is stored.
|
|||
|
This b-tree contains entries for each volume with its ID and offset.
|
|||
|
**/
|
|||
|
#pragma pack(push, 1)
|
|||
|
typedef struct APFS_CSB_
|
|||
|
{
|
|||
|
APFS_BLOCK_HEADER BlockHeader;
|
|||
|
//
|
|||
|
// Magic: NXSB
|
|||
|
//
|
|||
|
UINT32 Magic;
|
|||
|
//
|
|||
|
// Size of each allocation unit: 4096 bytes
|
|||
|
// (by default)
|
|||
|
//
|
|||
|
UINT32 BlockSize;
|
|||
|
//
|
|||
|
// Number of blocks in the container
|
|||
|
//
|
|||
|
UINT64 TotalBlocks;
|
|||
|
UINT64 Features;
|
|||
|
UINT64 ReadOnlyCompatibleFeatures;
|
|||
|
UINT64 IncompatibleFeatures;
|
|||
|
EFI_GUID Uuid;
|
|||
|
UINT64 NextOid;
|
|||
|
UINT64 NextXid;
|
|||
|
UINT32 XpDescBlocks;
|
|||
|
UINT32 XpDataBlocks;
|
|||
|
INT64 XpDescBase;
|
|||
|
INT64 XpDataBase;
|
|||
|
UINT32 XpDescNext;
|
|||
|
UINT32 XpDataNext;
|
|||
|
UINT32 XpDescIndex;
|
|||
|
UINT32 XpDescLen;
|
|||
|
UINT32 XpDataIndex;
|
|||
|
UINT32 XpDataLen;
|
|||
|
UINT64 SpacemanOid;
|
|||
|
UINT64 ObjectMapOid;
|
|||
|
UINT64 ReaperOid;
|
|||
|
UINT32 TestType;
|
|||
|
UINT32 MaxFileSystems;
|
|||
|
UINT64 FileSystemOid[APFS_CSB_MAX_FILE_SYSTEMS];
|
|||
|
UINT64 Counters[APFS_CSB_NUM_COUNTERS];
|
|||
|
PhysicalRange BlockedOutPhysicalRange;
|
|||
|
UINT64 EvictMappingTreeOid;
|
|||
|
UINT64 Flags;
|
|||
|
//
|
|||
|
// Pointer to JSDR block (EfiBootRecordBlock)
|
|||
|
//
|
|||
|
UINT64 EfiBootRecordBlock;
|
|||
|
EFI_GUID FusionUuid;
|
|||
|
PhysicalRange KeyLocker;
|
|||
|
UINT64 EphermalInfo[APFS_CSB_EPH_INFO_COUNT];
|
|||
|
UINT64 TestOid;
|
|||
|
UINT64 FusionMtIod;
|
|||
|
UINT64 FusionWbcOid;
|
|||
|
PhysicalRange FusionWbc;
|
|||
|
} APFS_CSB;
|
|||
|
#pragma pack(pop)
|
|||
|
|
|||
|
//
|
|||
|
// APSB volume header structure
|
|||
|
//
|
|||
|
#pragma pack(push, 1)
|
|||
|
typedef struct APFS_APSB_
|
|||
|
{
|
|||
|
APFS_BLOCK_HEADER BlockHeader;
|
|||
|
//
|
|||
|
// Volume Superblock magic
|
|||
|
// Magic: APSB
|
|||
|
//
|
|||
|
UINT32 Magic;
|
|||
|
//
|
|||
|
// Volume#. First volume start with 0, (0x00)
|
|||
|
//
|
|||
|
UINT32 VolumeNumber;
|
|||
|
UINT8 Reserved_1[20];
|
|||
|
//
|
|||
|
// Case setting of the volume.
|
|||
|
// 1 = Not case sensitive
|
|||
|
// 8 = Case sensitive (0x01, Not C.S)
|
|||
|
//
|
|||
|
UINT32 CaseSetting;
|
|||
|
UINT8 Reserved_2[12];
|
|||
|
//
|
|||
|
// Size of volume in Blocks. Last volume has no
|
|||
|
// size set and has available the rest of the blocks
|
|||
|
//
|
|||
|
UINT64 VolumeSize;
|
|||
|
UINT64 Reserved_3;
|
|||
|
//
|
|||
|
// Blocks in use in this volumes
|
|||
|
//
|
|||
|
UINT64 BlocksInUseCount;
|
|||
|
UINT8 Reserved_4[32];
|
|||
|
//
|
|||
|
// Block# to initial block of catalog B-Tree Object
|
|||
|
// Map (BTOM)
|
|||
|
//
|
|||
|
UINT64 BlockNumberToInitialBTOM;
|
|||
|
//
|
|||
|
// Node Id of root-node
|
|||
|
//
|
|||
|
UINT64 RootNodeId;
|
|||
|
//
|
|||
|
// Block# to Extents B-Tree,block#
|
|||
|
//
|
|||
|
UINT64 BlockNumberToEBTBlockNumber;
|
|||
|
//
|
|||
|
// Block# to list of Snapshots
|
|||
|
//
|
|||
|
UINT64 BlockNumberToListOfSnapshots;
|
|||
|
UINT8 Reserved_5[16];
|
|||
|
//
|
|||
|
// Next CNID
|
|||
|
//
|
|||
|
UINT64 NextCnid;
|
|||
|
//
|
|||
|
// Number of files on the volume
|
|||
|
//
|
|||
|
UINT64 NumberOfFiles;
|
|||
|
//
|
|||
|
// Number of folders on the volume
|
|||
|
//
|
|||
|
UINT64 NumberOfFolder;
|
|||
|
UINT8 Reserved_6[40];
|
|||
|
//
|
|||
|
// Volume UUID
|
|||
|
//
|
|||
|
EFI_GUID VolumeUuid;
|
|||
|
//
|
|||
|
// Time Volume last written/modified
|
|||
|
//
|
|||
|
UINT64 ModificationTimestamp;
|
|||
|
UINT64 Reserved_7;
|
|||
|
//
|
|||
|
// Creator/APFS-version
|
|||
|
// Ex. (hfs_convert (apfs- 687.0.0.1.7))
|
|||
|
//
|
|||
|
UINT8 CreatorVersionInfo[32];
|
|||
|
//
|
|||
|
// Time Volume created
|
|||
|
//
|
|||
|
UINT64 CreationTimestamp;
|
|||
|
//
|
|||
|
// ???
|
|||
|
//
|
|||
|
} APFS_APSB;
|
|||
|
#pragma pack(pop)
|
|||
|
|
|||
|
//
|
|||
|
// JSDR block structure
|
|||
|
//
|
|||
|
#pragma pack(push, 1)
|
|||
|
typedef struct APFS_EFI_BOOT_RECORD_
|
|||
|
{
|
|||
|
APFS_BLOCK_HEADER BlockHeader;
|
|||
|
//
|
|||
|
// A number that can be used to verify that youʼre reading an instance of
|
|||
|
// APFS_EFI_BOOT_RECORD
|
|||
|
//
|
|||
|
UINT32 Magic;
|
|||
|
//
|
|||
|
// The version of this data structure
|
|||
|
//
|
|||
|
UINT32 Version;
|
|||
|
//
|
|||
|
// The length in bytes, of the embedded EFI driver
|
|||
|
//
|
|||
|
UINT32 EfiFileLen;
|
|||
|
//
|
|||
|
// Num of extents in the array
|
|||
|
//
|
|||
|
UINT32 NumOfExtents;
|
|||
|
//
|
|||
|
// Reserved
|
|||
|
// Populate this field with 0 when you create a new instance,
|
|||
|
// and preserve its value when you modify an existing instance.
|
|||
|
//
|
|||
|
UINT64 Reserved[16];
|
|||
|
//
|
|||
|
// Apfs driver physical range location
|
|||
|
//
|
|||
|
PhysicalRange RecordExtents[];
|
|||
|
} APFS_EFI_BOOT_RECORD;
|
|||
|
#pragma pack(pop)
|
|||
|
|
|||
|
#endif // APFS_DRIVER_LOADER_H_
|