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 // Detect the GPT protector
77 if( extendedLBA == 0 && numPartitions == 1 && MBR->Parts[0].SystemID == 0xEE )
79 // TODO: Hand off to GPT parsing code
80 Log_Warning("LBA MBR", "TODO: Hand off to GPT");
83 // Handle extended partions
84 while(extendedLBA != 0)
86 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
87 if( extendedLBA == (Uint64)-1 )
91 LOG("numPartitions = %i", numPartitions);
93 LEAVE('i', numPartitions);
97 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector)
102 tMBR *MBR = FirstSector;
104 ENTER("pVolume pFirstSector", Volume, FirstSector);
106 // --- Fill Partition Info ---
108 for( j = 0, i = 0; i < 4; i ++ )
110 LOG("MBR->Parts[%i].SystemID = 0x%02x", i, MBR->Parts[i].SystemID);
111 if( MBR->Parts[i].SystemID == 0 ) continue;
112 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 ) // LBA 28
114 base = MBR->Parts[i].LBAStart;
115 len = MBR->Parts[i].LBALength;
117 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 ) // LBA 48
119 base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
120 len = (MBR->Parts[i].LengthHi << 16) | MBR->Parts[i].LBALength;
125 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
131 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
135 // Scan extended partitions
136 while(extendedLBA != 0)
138 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
139 if(extendedLBA == (Uint64)-1)
141 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
149 * \brief Reads an extended partition
150 * \return LBA of next Extended, -1 on error, 0 for last
152 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length)
160 // TODO: Handle non-512 byte sectors
161 if( LVM_int_ReadVolume( Volume, Addr, 1, &mbr ) != 0 )
162 return -1; // Stop on Errors
164 for( i = 0; i < 4; i ++ )
166 if( mbr.Parts[i].SystemID == 0 ) continue;
169 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
170 base = mbr.Parts[i].LBAStart;
171 len = mbr.Parts[i].LBALength;
174 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) {
175 base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
176 len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
179 Log_Warning("LVM MBR",
180 "Unknown partition type 0x%x, Volume %p Ext 0x%llx Part %i",
181 mbr.Parts[i].Boot, Volume, Addr, i
186 switch(mbr.Parts[i].SystemID)
191 Log_Warning("LVM MBR",
192 "Volume %p has two forward links in the extended partition",
202 "Volume %p has more than one partition in the extended partition at 0x%llx",
208 *Base = Addr + base; // Extended partitions are based off the sub-mbr
215 Log_Warning("LVM MBR",
216 "No partition in extended partiton, Volume %p 0x%llx",