2 * Acess2 Logical Volume Manager
3 * - By John Hodge (thePowersGang)
14 int LVM_MBR_CountSubvolumes(tLVM_Vol *Volume, void *FirstSector);
15 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector);
16 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length);
19 tLVM_Format gLVM_MBRType = {
21 .CountSubvolumes = LVM_MBR_CountSubvolumes,
22 .PopulateSubvolumes = LVM_MBR_PopulateSubvolumes
27 * \brief Initialise a volume as
29 int LVM_MBR_CountSubvolumes(tLVM_Vol *Volume, void *FirstSector)
31 tMBR *MBR = FirstSector;
35 int numPartitions = 0;
37 ENTER("pVolume pFirstSector", Volume, FirstSector);
42 for( i = 0; i < 4; i ++ )
44 if( MBR->Parts[i].SystemID == 0 ) continue;
46 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 ) // LBA 28
48 base = MBR->Parts[i].LBAStart;
50 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 ) // LBA 48
52 base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
55 continue ; // Invalid, so don't count
57 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 )
59 LOG("Extended Partition at 0x%llx", base);
60 if(extendedLBA != 0) {
63 "Volume %p has multiple extended partitions, ignoring all but first",
72 LOG("Primary Partition at 0x%llx", base);
76 while(extendedLBA != 0)
78 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
79 if( extendedLBA == (Uint64)-1 )
83 LOG("numPartitions = %i", numPartitions);
85 LEAVE('i', numPartitions);
89 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector)
94 tMBR *MBR = FirstSector;
96 ENTER("pVolume pFirstSector", Volume, FirstSector);
98 // --- Fill Partition Info ---
100 for( j = 0, i = 0; i < 4; i ++ )
102 LOG("MBR->Parts[%i].SystemID = 0x%02x", i, MBR->Parts[i].SystemID);
103 if( MBR->Parts[i].SystemID == 0 ) continue;
104 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 ) // LBA 28
106 base = MBR->Parts[i].LBAStart;
107 len = MBR->Parts[i].LBALength;
109 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 ) // LBA 48
111 base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
112 len = (MBR->Parts[i].LengthHi << 16) | MBR->Parts[i].LBALength;
117 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
123 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
127 // Scan extended partitions
128 while(extendedLBA != 0)
130 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
131 if(extendedLBA == (Uint64)-1)
133 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
141 * \brief Reads an extended partition
142 * \return LBA of next Extended, -1 on error, 0 for last
144 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length)
152 // TODO: Handle non-512 byte sectors
153 if( LVM_int_ReadVolume( Volume, Addr, 1, &mbr ) != 0 )
154 return -1; // Stop on Errors
156 for( i = 0; i < 4; i ++ )
158 if( mbr.Parts[i].SystemID == 0 ) continue;
161 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
162 base = mbr.Parts[i].LBAStart;
163 len = mbr.Parts[i].LBALength;
166 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) {
167 base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
168 len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
171 Log_Warning("LVM MBR",
172 "Unknown partition type 0x%x, Volume %p Ext 0x%llx Part %i",
173 mbr.Parts[i].Boot, Volume, Addr, i
178 switch(mbr.Parts[i].SystemID)
183 Log_Warning("LVM MBR",
184 "Volume %p has two forward links in the extended partition",
194 "Volume %p has more than one partition in the extended partition at 0x%llx",
200 *Base = Addr + base; // Extended partitions are based off the sub-mbr
207 Log_Warning("LVM MBR",
208 "No partition in extended partiton, Volume %p 0x%llx",