2 * Acess2 Logical Volume Manager
3 * - By John Hodge (thePowersGang)
14 int LVM_MBR_Detect(tLVM_Vol *Volume);
15 int LVM_MBR_CountSubvolumes(tLVM_Vol *Volume, void *FirstSector);
16 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector);
17 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length);
20 tLVM_Format gLVM_MBRType = {
22 .CountSubvolumes = LVM_MBR_CountSubvolumes,
23 .PopulateSubvolumes = LVM_MBR_PopulateSubvolumes
27 int LVM_MBR_Detect(tLVM_Vol *Volume)
30 // TODO: handle non-512 byte sectors
31 if( LVM_int_ReadVolume( Volume, 0, 1, &mbr ) != 0 )
32 return -1; // Stop on Errors
34 if( mbr.BootFlag != LittleEndian16(0xAA55) )
41 * \brief Initialise a volume as
43 int LVM_MBR_CountSubvolumes(tLVM_Vol *Volume, void *FirstSector)
45 tMBR *MBR = FirstSector;
48 int numPartitions = 0;
50 ENTER("pVolume pFirstSector", Volume, FirstSector);
55 for( int i = 0; i < 4; i ++ )
57 if( MBR->Parts[i].SystemID == 0 ) continue;
59 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 ) // LBA 28
61 base = MBR->Parts[i].LBAStart;
63 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 ) // LBA 48
65 base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
68 continue ; // Invalid, so don't count
70 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 )
72 LOG("Extended Partition at 0x%llx", base);
73 if(extendedLBA != 0) {
76 "Volume %p has multiple extended partitions, ignoring all but first",
85 LOG("Primary Partition at 0x%llx", base);
89 // Detect the GPT protector
90 if( extendedLBA == 0 && numPartitions == 1 && MBR->Parts[0].SystemID == 0xEE )
92 // TODO: Hand off to GPT parsing code
93 Log_Warning("LBA MBR", "TODO: Hand off to GPT");
96 // Handle extended partions
97 while(extendedLBA != 0)
99 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
100 if( extendedLBA == (Uint64)-1 )
104 LOG("numPartitions = %i", numPartitions);
106 LEAVE('i', numPartitions);
107 return numPartitions;
110 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector)
115 tMBR *MBR = FirstSector;
117 ENTER("pVolume pFirstSector", Volume, FirstSector);
119 // --- Fill Partition Info ---
121 for( j = 0, i = 0; i < 4; i ++ )
123 LOG("MBR->Parts[%i].SystemID = 0x%02x", i, MBR->Parts[i].SystemID);
124 if( MBR->Parts[i].SystemID == 0 ) continue;
125 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 ) // LBA 28
127 base = MBR->Parts[i].LBAStart;
128 len = MBR->Parts[i].LBALength;
130 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 ) // LBA 48
132 base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
133 len = (MBR->Parts[i].LengthHi << 16) | MBR->Parts[i].LBALength;
138 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
144 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
148 // Scan extended partitions
149 while(extendedLBA != 0)
151 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
152 if(extendedLBA == (Uint64)-1)
154 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
162 * \brief Reads an extended partition
163 * \return LBA of next Extended, -1 on error, 0 for last
165 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length)
173 // TODO: Handle non-512 byte sectors
174 if( LVM_int_ReadVolume( Volume, Addr, 1, &mbr ) != 0 )
175 return -1; // Stop on Errors
177 for( i = 0; i < 4; i ++ )
179 if( mbr.Parts[i].SystemID == 0 ) continue;
182 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
183 base = mbr.Parts[i].LBAStart;
184 len = mbr.Parts[i].LBALength;
187 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) {
188 base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
189 len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
192 Log_Warning("LVM MBR",
193 "Unknown partition type 0x%x, Volume %p Ext 0x%llx Part %i",
194 mbr.Parts[i].Boot, Volume, Addr, i
199 switch(mbr.Parts[i].SystemID)
204 Log_Warning("LVM MBR",
205 "Volume %p has two forward links in the extended partition",
215 "Volume %p has more than one partition in the extended partition at 0x%llx",
221 *Base = Addr + base; // Extended partitions are based off the sub-mbr
228 Log_Warning("LVM MBR",
229 "No partition in extended partiton, Volume %p 0x%llx",