mbr.hpp
00001 #if !defined(__MBR_HPP__)
00002 #define __MBR_HPP__
00003
00004
00005
00006
00007 #include "core/common.hpp"
00008
00012 struct __packed(mbr)
00013 {
00014 static const uint16_t SIGNATURE = 0xaa55;
00015
00019 struct __packed(entry)
00020 {
00021 enum attributes_constants
00022 {
00024 BOOTABLE = 0x80
00025 };
00026
00027 uint8_t attributes;
00028 uint8_t start_chs[3];
00029 uint8_t type;
00030 uint8_t end_chs[3];
00031 le_uint32_t start_lba;
00032 le_uint32_t size_lba;
00033
00037 inline entry(void)
00038 {
00039 memset(this, 0, sizeof(entry));
00040 }
00041
00045 inline entry(uint8_t type, uint32_t start_lba, uint32_t size_lba, uint8_t attributes=0)
00046 {
00047
00048 this->attributes=attributes;
00049 this->start_chs[0]=0xfe;
00050 this->start_chs[1]=this->start_chs[2]=0xff;
00051 this->type=type;
00052 this->end_chs[0]=0xfe;
00053 this->end_chs[1]=this->end_chs[2]=0xff;
00054 this->start_lba=start_lba;
00055 this->size_lba=size_lba;
00056 }
00057
00058 inline bool is_used(void) const
00059 {
00060
00061 return type && size_lba;
00062 }
00063
00064 inline bool is_valid(const uint32_t disk_size) const
00065 {
00066
00067 return (start_lba < disk_size) && (start_lba + size_lba <= disk_size);
00068 }
00069
00070 inline bool overlaps(const entry &other) const
00071 {
00072 const uint64_t end_lba=static_cast<uint64_t>(start_lba) + size_lba - 1,
00073 other_end_lba=static_cast<uint64_t>(other.start_lba) + other.size_lba - 1;
00074 return (start_lba <= other_end_lba) && (other.start_lba <= end_lba);
00075 }
00076 };
00077
00078
00079 static_assert(sizeof(entry) == 16, "entry's size must be 16");
00080
00081 uint8_t boot_code[440];
00082 le_uint32_t uid;
00083 le_uint16_t unknown;
00084 entry partitions[4];
00085 le_uint16_t signature;
00086
00090 inline mbr(void)
00091 {
00092 memset(this, 0, sizeof(mbr));
00093 }
00094
00098 inline mbr(uint32_t uid, const uint8_t *boot_code=nullptr)
00099 {
00100
00101 memset(this, 0, sizeof(mbr));
00102
00103 if (boot_code) memcpy(this->boot_code, boot_code, sizeof(this->boot_code));
00104 this->uid=uid;
00105 this->signature=SIGNATURE;
00106 }
00107
00108 inline bool is_valid(void) const
00109 {
00110 return signature == SIGNATURE;
00111 }
00112
00113 inline bool is_consistent(const uint64_t disk_size) const
00114 {
00115 for (int i=0; i < 4; i++)
00116 if (partitions[i].is_used()) {
00117 if (!partitions[i].is_valid(disk_size)) return false;
00118
00119 for (int j=0; j < i; j++)
00120 if (partitions[j].is_used() && partitions[i].overlaps(partitions[j]))
00121 return false;
00122 }
00123
00124 return true;
00125 }
00126
00127 inline bool matches(const mbr &other) const
00128 {
00129 return (uid == other.uid) &&
00130 (signature == other.signature) &&
00131 !memcmp(partitions, other.partitions, sizeof(partitions));
00132 }
00133 };
00134
00135
00136 static_assert(sizeof(mbr) == 512, "mbr's size must be 512");
00137
00138 #endif
00139
00140
00141