Usermode/libaxwin4 - Handle demarshal failure
[tpg/acess2.git] / KernelLand / Modules / Storage / LVM / mbr.c
1 /*
2  * Acess2 Logical Volume Manager
3  * - By John Hodge (thePowersGang)
4  * 
5  * mbr.c
6  * - MBR Parsing Code
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include "lvm.h"
11 #include "mbr.h"
12
13 // === PROTOTYPES ===
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);
18
19 // === GLOBALS ===
20 tLVM_Format     gLVM_MBRType = {
21         .Name = "MBR",
22         .CountSubvolumes = LVM_MBR_CountSubvolumes,
23         .PopulateSubvolumes = LVM_MBR_PopulateSubvolumes
24 };
25
26 // === CODE ===
27 int LVM_MBR_Detect(tLVM_Vol *Volume)
28 {
29         tMBR    mbr;
30         // TODO: handle non-512 byte sectors
31         if( LVM_int_ReadVolume( Volume, 0, 1, &mbr ) != 0 )
32                 return -1;      // Stop on Errors
33
34         if( mbr.BootFlag != LittleEndian16(0xAA55) )
35                 return 0;
36
37         return 1;
38 }
39
40 /**
41  * \brief Initialise a volume as 
42  */
43 int LVM_MBR_CountSubvolumes(tLVM_Vol *Volume, void *FirstSector)
44 {
45         tMBR    *MBR = FirstSector;
46         Uint64  extendedLBA;
47         Uint64  base, len;
48          int    numPartitions = 0;
49         
50         ENTER("pVolume pFirstSector", Volume, FirstSector);
51         
52         // Count Partitions
53         numPartitions = 0;
54         extendedLBA = 0;
55         for( int i = 0; i < 4; i ++ )
56         {
57                 if( MBR->Parts[i].SystemID == 0 )       continue;
58         
59                 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 )   // LBA 28
60                 {
61                         base = MBR->Parts[i].LBAStart;
62                 }
63                 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 )      // LBA 48
64                 {
65                         base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
66                 }
67                 else
68                         continue ;      // Invalid, so don't count
69                 
70                 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 )
71                 {
72                         LOG("Extended Partition at 0x%llx", base);
73                         if(extendedLBA != 0) {
74                                 Log_Warning(
75                                         "LBA MBR",
76                                         "Volume %p has multiple extended partitions, ignoring all but first",
77                                         Volume
78                                         );
79                                 continue;
80                         }
81                         extendedLBA = base;
82                 }
83                 else
84                 {
85                         LOG("Primary Partition at 0x%llx", base);
86                         numPartitions ++;
87                 }
88         }
89         // Detect the GPT protector
90         if( extendedLBA == 0 && numPartitions == 1 && MBR->Parts[0].SystemID == 0xEE )
91         {
92                 // TODO: Hand off to GPT parsing code
93                 Log_Warning("LBA MBR", "TODO: Hand off to GPT");
94         }
95         
96         // Handle extended partions
97         while(extendedLBA != 0)
98         {
99                 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
100                 if( extendedLBA == (Uint64)-1 )
101                         break;
102                 numPartitions ++;
103         }
104         LOG("numPartitions = %i", numPartitions);
105
106         LEAVE('i', numPartitions);
107         return numPartitions;   
108 }
109
110 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector)
111 {
112         Uint64  extendedLBA;
113         Uint64  base, len;
114          int    i, j;
115         tMBR    *MBR = FirstSector;
116
117         ENTER("pVolume pFirstSector", Volume, FirstSector);
118         
119         // --- Fill Partition Info ---
120         extendedLBA = 0;
121         for( j = 0, i = 0; i < 4; i ++ )
122         {
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
126                 {
127                         base = MBR->Parts[i].LBAStart;
128                         len = MBR->Parts[i].LBALength;
129                 }
130                 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 )      // LBA 48
131                 {
132                         base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
133                         len = (MBR->Parts[i].LengthHi << 16) | MBR->Parts[i].LBALength;
134                 }
135                 else
136                         continue;
137                 
138                 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
139                         if(extendedLBA == 0)
140                                 extendedLBA = base;
141                         continue;
142                 }
143                 // Create Partition
144                 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
145                 j ++;
146                 
147         }
148         // Scan extended partitions
149         while(extendedLBA != 0)
150         {
151                 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
152                 if(extendedLBA == (Uint64)-1)
153                         break;
154                 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
155                 j ++ ;
156         }
157         
158         LEAVE('-');
159 }
160
161 /**
162  * \brief Reads an extended partition
163  * \return LBA of next Extended, -1 on error, 0 for last
164  */
165 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length)
166 {
167         Uint64  link = 0;
168          int    bFoundPart = 0;;
169          int    i;
170         tMBR    mbr;
171         Uint64  base, len;
172         
173         // TODO: Handle non-512 byte sectors
174         if( LVM_int_ReadVolume( Volume, Addr, 1, &mbr ) != 0 )
175                 return -1;      // Stop on Errors
176         
177         for( i = 0; i < 4; i ++ )
178         {
179                 if( mbr.Parts[i].SystemID == 0 )        continue;
180                 
181                 // LBA 24
182                 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
183                         base = mbr.Parts[i].LBAStart;
184                         len = mbr.Parts[i].LBALength;
185                 }
186                 // LBA 48
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;
190                 }
191                 else {
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
195                                 );
196                         return -1;
197                 }
198                 
199                 switch(mbr.Parts[i].SystemID)
200                 {
201                 case 0xF:
202                 case 0x5:
203                         if(link != 0) {
204                                 Log_Warning("LVM MBR",
205                                         "Volume %p has two forward links in the extended partition",
206                                         Volume
207                                         );
208                                 return -1;
209                         }
210                         link = base;
211                         break;
212                 default:
213                         if(bFoundPart) {
214                                 Warning("LVM MBR",
215                                         "Volume %p has more than one partition in the extended partition at 0x%llx",
216                                         Volume, Addr
217                                         );
218                                 return -1;
219                         }
220                         bFoundPart = 1;
221                         *Base = Addr + base;    // Extended partitions are based off the sub-mbr
222                         *Length = len;
223                         break;
224                 }
225         }
226         
227         if(!bFoundPart) {
228                 Log_Warning("LVM MBR",
229                         "No partition in extended partiton, Volume %p 0x%llx",
230                         Volume, Addr
231                         );
232                 return -1;
233         }
234         
235         return link;
236 }

UCC git Repository :: git.ucc.asn.au