48d9c83dbee2188ef008a611452aa1cc160da316
[tpg/acess2.git] / Modules / ATA / mbr.c
1 /*
2  * Acess2 IDE Harddisk Driver
3  * - MBR Parsing Code
4  * mbr.c
5  */
6 #define DEBUG   0
7 #include <acess.h>
8 #include "common.h"
9
10 // == GLOBALS ===
11
12 // === CODE ===
13 /**
14  * \fn void ATA_ParseMBR(int Disk)
15  */
16 void ATA_ParseMBR(int Disk)
17 {
18          int    i, j = 0, k = 4;
19         tMBR    mbr;
20         Uint64  extendedLBA;
21         Uint64  base, len;
22         
23         ENTER("iDisk", Disk);
24         
25         // Read Boot Sector
26         ATA_ReadDMA( Disk, 0, 1, &mbr );
27         
28         // Count Partitions
29         gATA_Disks[Disk].NumPartitions = 0;
30         extendedLBA = 0;
31         for( i = 0; i < 4; i ++ )
32         {
33                 if( mbr.Parts[i].SystemID == 0 )        continue;
34                 if(
35                         mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80   // LBA 28
36                 ||      mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81   // LBA 48
37                         )
38                 {
39                         if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) {
40                                 LOG("Extended Partition");
41                                 if(extendedLBA != 0) {
42                                         Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
43                                         continue;
44                                 }
45                                 extendedLBA = mbr.Parts[i].LBAStart;
46                                 continue;
47                         }
48                         LOG("Primary Partition");
49                         
50                         gATA_Disks[Disk].NumPartitions ++;
51                         continue;
52                 }
53                 // Invalid Partition, so don't count it
54         }
55         while(extendedLBA != 0)
56         {
57                 extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len);
58                 if( extendedLBA == -1 ) return ;
59                 gATA_Disks[Disk].NumPartitions ++;
60         }
61         LOG("gATA_Disks[Disk].NumPartitions = %i", gATA_Disks[Disk].NumPartitions);
62         
63         // Create patition array
64         gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) );
65         
66         // --- Fill Partition Info ---
67         extendedLBA = 0;
68         for( j = 0, i = 0; i < 4; i ++ )
69         {
70                 Log("mbr.Parts[%i].SystemID = 0x%02x", i, mbr.Parts[i].SystemID);
71                 if( mbr.Parts[i].SystemID == 0 )        continue;
72                 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 )     // LBA 28
73                 {
74                         base = mbr.Parts[i].LBAStart;
75                         len = mbr.Parts[i].LBALength;
76                 }
77                 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 )        // LBA 58
78                 {
79                         base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
80                         len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
81                 }
82                 else
83                         continue;
84                 
85                 if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) {
86                         if(extendedLBA != 0) {
87                                 Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
88                                 continue;
89                         }
90                         extendedLBA = base;
91                         continue;
92                 }
93                 // Create Partition
94                 ATA_int_MakePartition(
95                         &gATA_Disks[Disk].Partitions[j], Disk, j,
96                         base, len
97                         );
98                 j ++;
99                 
100         }
101         // Scan extended partitions
102         while(extendedLBA != 0)
103         {
104                 extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len);
105                 ATA_int_MakePartition(
106                         &gATA_Disks[Disk].Partitions[j], Disk, k, base, len
107                         );
108         }
109         
110         LEAVE('-');
111 }
112
113 /**
114  * \brief Reads an extended partition
115  * \return LBA of next Extended, -1 on error, 0 for last
116  */
117 Uint64 ATA_MBR_int_ReadExt(int Disk, Uint64 Addr, Uint64 *Base, Uint64 *Length)
118 {
119         Uint64  link = 0;
120          int    bFoundPart = 0;;
121          int    i;
122         tMBR    mbr;
123         Uint64  base, len;
124         
125         if( ATA_ReadDMA( Disk, Addr, 1, &mbr ) != 0 )
126                 return -1;      // Stop on Errors
127         
128         
129         for( i = 0; i < 4; i ++ )
130         {
131                 if( mbr.Parts[i].SystemID == 0 )        continue;
132                 
133                 // LBA 24
134                 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
135                         base = mbr.Parts[i].LBAStart;
136                         len = mbr.Parts[i].LBALength;
137                 }
138                 // LBA 48
139                 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) {
140                         base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
141                         len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
142                 }
143                 else {
144                         Warning("Unknown partition type, Disk %i 0x%llx Part %i",
145                                 Disk, Addr, i);
146                         return -1;
147                 }
148                 
149                 switch(mbr.Parts[i].SystemID)
150                 {
151                 case 0xF:
152                 case 0x5:
153                         if(link != 0) {
154                                 Warning("Disk %i has two forward links in the extended partition",
155                                         Disk);
156                                 return -1;
157                         }
158                         link = base;
159                         break;
160                 default:
161                         if(bFoundPart) {
162                                 Warning("Disk %i has more than one partition in the extended partition at 0x%llx",
163                                         Disk, Addr);
164                                 return -1;
165                         }
166                         bFoundPart = 1;
167                         *Base = base;
168                         *Length = len;
169                         break;
170                 }
171         }
172         
173         if(!bFoundPart) {
174                 Warning("No partition in extended partiton, Disk %i 0x%llx",
175                         Disk, Addr);
176                 return -1;
177         }
178         
179         return link;
180 }

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