/* * Copyright 2003-2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. * Distributed under the terms of the MIT License. */ #ifndef _INTEL_PARTITION_MAP_H #define _INTEL_PARTITION_MAP_H /*! \file PartitionMap.h \ingroup intel_module \brief Definitions for "intel" style partitions and interface definitions for related classes. */ // NOTE: #include #include #include #ifndef _USER_MODE # include #else # include #endif // partition_type struct partition_type { uint8 type; const char* name; bool used; }; // is_empty_type static inline bool is_empty_type(uint8 type) { return type == 0x00; } // is_extended_type static inline bool is_extended_type(uint8 type) { return type == 0x05 || type == 0x0f || type == 0x85; } void get_partition_type_string(uint8 type, char* buffer); // chs // NOTE: The CHS cannot express locations within larger disks (more than 8GB), // and is therefore obsolete. // However, some BIOSes still rely on it being 0 for unused partition, and some // other value for valid records. Usually they are filled with 0xFF, which is // an invalid CHS value, to notify the BIOS that LBA should be used instead. struct chs { uint8 cylinder; uint16 head_sector; // head[15:10], sector[9:0] void SetUnused() { cylinder = 0xFF; head_sector = 0xFFFF; } void Unset() { cylinder = 0; head_sector = 0; } } _PACKED; // partition_descriptor struct partition_descriptor { uint8 active; chs begin; // mostly ignored uint8 type; // empty, filesystem or extended chs end; // mostly ignored uint32 start; // in sectors uint32 size; // in sectors bool is_empty() const { return is_empty_type(type); } bool is_extended() const { return is_extended_type(type); } } _PACKED; // partition_table struct partition_table { char code_area[440]; uint32 disk_id; uint16 reserved; partition_descriptor table[4]; uint16 signature; void clear_code_area() { memset(code_area, 0, sizeof(code_area)); } void fill_code_area(const uint8* code, size_t size) { memcpy(code_area, code, min_c(sizeof(code_area), size)); } } _PACKED; static const uint16 kPartitionTableSectorSignature = 0xaa55; class Partition; class PrimaryPartition; class LogicalPartition; // PartitionType /*! \brief Class for validating partition types. To this class we can set a partition type and then we can check whether this type is valid, empty or if it represents an extended partition. We can also retrieve the name of that partition type or find the next supported type. */ class PartitionType { public: PartitionType(); bool SetType(uint8 type); bool SetType(const char* typeName); bool SetContentType(const char* contentType); bool IsValid() const { return fValid; } bool IsEmpty() const { return is_empty_type(fType); } bool IsExtended() const { return is_extended_type(fType); } uint8 Type() const { return fType; } bool FindNext(); void GetTypeString(char* buffer) const { get_partition_type_string(fType, buffer); } private: uint8 fType; bool fValid; }; // Partition class Partition { public: Partition(); Partition(const partition_descriptor* descriptor, off_t tableOffset, off_t baseOffset, uint32 blockSize); void SetTo(const partition_descriptor* descriptor, off_t tableOffset, off_t baseOffset, uint32 blockSize); void SetTo(off_t offset, off_t size, uint8 type, bool active, off_t tableOffset, uint32 blockSize); void Unset(); bool IsEmpty() const { return is_empty_type(fType); } bool IsExtended() const { return is_extended_type(fType); } // NOTE: Both PartitionTableOffset() and Offset() are absolute with regards // to the session (usually the disk). Ie, for all primary partitions, // including the primary extended partition, the PartitionTableOffset() // points to the MBR (0). // For logical partitions, the PartitionTableOffset() is located within the // primary extended partition, but again, the returned values are absolute // with regards to the session. All values are expressed in bytes. off_t PartitionTableOffset() const { return fPartitionTableOffset; } // offset of the partition table off_t Offset() const { return fOffset; } // start offset of the partition contents off_t Size() const { return fSize; } uint8 Type() const { return fType; } bool Active() const { return fActive; } uint32 BlockSize() const { return fBlockSize; } void GetTypeString(char* buffer) const { get_partition_type_string(fType, buffer); } void SetPartitionTableOffset(off_t offset) { fPartitionTableOffset = offset; } void SetOffset(off_t offset) { fOffset = offset; } void SetSize(off_t size) { fSize = size; } void SetType(uint8 type) { fType = type; } void SetActive(bool active) { fActive = active; } void SetBlockSize(uint32 blockSize) { fBlockSize = blockSize; } bool CheckLocation(off_t sessionSize) const; bool FitSizeToSession(off_t sessionSize); private: off_t fPartitionTableOffset; off_t fOffset; // relative to the start of the session off_t fSize; uint32 fBlockSize; uint8 fType; bool fActive; }; // PrimaryPartition class PrimaryPartition : public Partition { public: PrimaryPartition(); void SetTo(const partition_descriptor* descriptor, off_t tableOffset, uint32 blockSize); void SetTo(off_t offset, off_t size, uint8 type, bool active, uint32 blockSize); void Unset(); status_t Assign(const PrimaryPartition& other); int32 Index() const { return fIndex; } void SetIndex(int32 index) { fIndex = index; } void GetPartitionDescriptor( partition_descriptor* descriptor) const; // private // only if extended int32 CountLogicalPartitions() const { return fLogicalPartitionCount; } LogicalPartition* LogicalPartitionAt(int32 index) const; void AddLogicalPartition(LogicalPartition* partition); void RemoveLogicalPartition( LogicalPartition* partition); private: LogicalPartition* fHead; LogicalPartition* fTail; int32 fLogicalPartitionCount; int32 fIndex; }; // LogicalPartition class LogicalPartition : public Partition { public: LogicalPartition(); LogicalPartition( const partition_descriptor* descriptor, off_t tableOffset, PrimaryPartition* primary); void SetTo(const partition_descriptor* descriptor, off_t tableOffset, PrimaryPartition* primary); void SetTo(off_t offset, off_t size, uint8 type, bool active, off_t tableOffset, PrimaryPartition* primary); void Unset(); void GetPartitionDescriptor( partition_descriptor* descriptor, bool inner = false) const; void SetPrimaryPartition(PrimaryPartition* primary) { fPrimary = primary; } PrimaryPartition* GetPrimaryPartition() const { return fPrimary; } void SetNext(LogicalPartition* next) { fNext = next; } LogicalPartition* Next() const { return fNext; } void SetPrevious(LogicalPartition* previous) { fPrevious = previous; } LogicalPartition* Previous() const { return fPrevious; } private: PrimaryPartition* fPrimary; LogicalPartition* fNext; LogicalPartition* fPrevious; }; // PartitionMap class PartitionMap { public: PartitionMap(); ~PartitionMap(); void Unset(); status_t Assign(const PartitionMap& other); PrimaryPartition* PrimaryPartitionAt(int32 index); const PrimaryPartition* PrimaryPartitionAt(int32 index) const; int32 IndexOfPrimaryPartition( const PrimaryPartition* partition) const; int32 CountNonEmptyPrimaryPartitions() const; int32 ExtendedPartitionIndex() const; int32 CountPartitions() const; int32 CountNonEmptyPartitions() const; Partition* PartitionAt(int32 index); const Partition* PartitionAt(int32 index) const; bool Check(off_t sessionSize) const; const partition_type* GetNextSupportedPartitionType(uint32 cookie); private: PrimaryPartition fPrimaries[4]; }; #endif // _INTEL_PARTITION_MAP_H