Modules/IPStack - Moving to reduction of memcpy usage
[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_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);
17
18 // === GLOBALS ===
19
20 // === CODE ===
21 /**
22  * \brief Initialise a volume as 
23  */
24 int LVM_MBR_CountSubvolumes(tLVM_Vol *Volume, void *FirstSector)
25 {
26         tMBR    *MBR = FirstSector;
27          int    i;
28         Uint64  extendedLBA;
29         Uint64  base, len;
30          int    numPartitions = 0;
31         
32         ENTER("pVolume pFirstSector", Volume, FirstSector);
33         
34         // Count Partitions
35         numPartitions = 0;
36         extendedLBA = 0;
37         for( i = 0; i < 4; i ++ )
38         {
39                 if( MBR->Parts[i].SystemID == 0 )       continue;
40         
41                 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 )   // LBA 28
42                 {
43                         base = MBR->Parts[i].LBAStart;
44                 }
45                 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 )      // LBA 48
46                 {
47                         base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
48                 }
49                 else
50                         continue ;      // Invalid, so don't count
51                 
52                 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 )
53                 {
54                         LOG("Extended Partition at 0x%llx", base);
55                         if(extendedLBA != 0) {
56                                 Log_Warning(
57                                         "LBA MBR",
58                                         "Volume %p has multiple extended partitions, ignoring all but first",
59                                         Volume
60                                         );
61                                 continue;
62                         }
63                         extendedLBA = base;
64                 }
65                 else
66                 {
67                         LOG("Primary Partition at 0x%llx", base);
68                         numPartitions ++;
69                 }
70         }
71         while(extendedLBA != 0)
72         {
73                 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
74                 if( extendedLBA == -1 ) break;
75                 numPartitions ++;
76         }
77         LOG("numPartitions = %i", numPartitions);
78
79         LEAVE('i', numPartitions);
80         return numPartitions;   
81 }
82
83 void LVM_MBR_PopulateSubvolumes(tLVM_Vol *Volume, void *FirstSector)
84 {
85         Uint64  extendedLBA;
86         Uint64  base, len;
87          int    i, j;
88         tMBR    *MBR = FirstSector;
89
90         ENTER("pVolume pFirstSector", Volume, FirstSector);
91         
92         // --- Fill Partition Info ---
93         extendedLBA = 0;
94         for( j = 0, i = 0; i < 4; i ++ )
95         {
96                 LOG("MBR->Parts[%i].SystemID = 0x%02x", i, MBR->Parts[i].SystemID);
97                 if( MBR->Parts[i].SystemID == 0 )       continue;
98                 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 )   // LBA 28
99                 {
100                         base = MBR->Parts[i].LBAStart;
101                         len = MBR->Parts[i].LBALength;
102                 }
103                 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 )      // LBA 48
104                 {
105                         base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
106                         len = (MBR->Parts[i].LengthHi << 16) | MBR->Parts[i].LBALength;
107                 }
108                 else
109                         continue;
110                 
111                 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
112                         if(extendedLBA == 0)
113                                 extendedLBA = base;
114                         continue;
115                 }
116                 // Create Partition
117                 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
118                 j ++;
119                 
120         }
121         // Scan extended partitions
122         while(extendedLBA != 0)
123         {
124                 extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
125                 if(extendedLBA == -1)   break;
126                 LVM_int_SetSubvolume_Anon( Volume, j, base, len );
127                 j ++ ;
128         }
129         
130         LEAVE('-');
131 }
132
133 /**
134  * \brief Reads an extended partition
135  * \return LBA of next Extended, -1 on error, 0 for last
136  */
137 Uint64 LVM_MBR_int_ReadExt(tLVM_Vol *Volume, Uint64 Addr, Uint64 *Base, Uint64 *Length)
138 {
139         Uint64  link = 0;
140          int    bFoundPart = 0;;
141          int    i;
142         tMBR    mbr;
143         Uint64  base, len;
144         
145         // TODO: Handle non-512 byte sectors
146         if( LVM_int_ReadVolume( Volume, Addr, 1, &mbr ) != 0 )
147                 return -1;      // Stop on Errors
148         
149         for( i = 0; i < 4; i ++ )
150         {
151                 if( mbr.Parts[i].SystemID == 0 )        continue;
152                 
153                 // LBA 24
154                 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
155                         base = mbr.Parts[i].LBAStart;
156                         len = mbr.Parts[i].LBALength;
157                 }
158                 // LBA 48
159                 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) {
160                         base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
161                         len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
162                 }
163                 else {
164                         Log_Warning("LVM MBR",
165                                 "Unknown partition type 0x%x, Volume %p Ext 0x%llx Part %i",
166                                 mbr.Parts[i].Boot, Volume, Addr, i
167                                 );
168                         return -1;
169                 }
170                 
171                 switch(mbr.Parts[i].SystemID)
172                 {
173                 case 0xF:
174                 case 0x5:
175                         if(link != 0) {
176                                 Log_Warning("LVM MBR",
177                                         "Volume %p has two forward links in the extended partition",
178                                         Volume
179                                         );
180                                 return -1;
181                         }
182                         link = base;
183                         break;
184                 default:
185                         if(bFoundPart) {
186                                 Warning("LVM MBR",
187                                         "Volume %p has more than one partition in the extended partition at 0x%llx",
188                                         Volume, Addr
189                                         );
190                                 return -1;
191                         }
192                         bFoundPart = 1;
193                         *Base = Addr + base;    // Extended partitions are based off the sub-mbr
194                         *Length = len;
195                         break;
196                 }
197         }
198         
199         if(!bFoundPart) {
200                 Log_Warning("LVM MBR",
201                         "No partition in extended partiton, Volume %p 0x%llx",
202                         Volume, Addr
203                         );
204                 return -1;
205         }
206         
207         return link;
208 }

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