a294ca81f8f70023a87070627588e93d33d9cfaa
[tpg/acess2.git] / Modules / Storage / 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 // === PROTOTYPES ===
11 void    ATA_ParseMBR(int Disk, tMBR *MBR);
12 Uint64  ATA_MBR_int_ReadExt(int Disk, Uint64 Addr, Uint64 *Base, Uint64 *Length);
13
14 // === GLOBALS ===
15
16 // === CODE ===
17 /**
18  * \fn void ATA_ParseMBR(int Disk, tMBR *MBR)
19  */
20 void ATA_ParseMBR(int Disk, tMBR *MBR)
21 {
22          int    i, j = 0, k = 4;
23         Uint64  extendedLBA;
24         Uint64  base, len;
25         
26         ENTER("iDisk", Disk);
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(     MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 // LBA 28
35                 ||      MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 // LBA 48
36                         )
37                 {
38                         if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
39                                 LOG("Extended Partition at 0x%llx", MBR->Parts[i].LBAStart);
40                                 if(extendedLBA != 0) {
41                                         Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
42                                         continue;
43                                 }
44                                 extendedLBA = MBR->Parts[i].LBAStart;
45                                 continue;
46                         }
47                         LOG("Primary Partition at 0x%llx", MBR->Parts[i].LBAStart);
48                         
49                         gATA_Disks[Disk].NumPartitions ++;
50                         continue;
51                 }
52                 // Invalid Partition, so don't count it
53         }
54         while(extendedLBA != 0)
55         {
56                 extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len);
57                 if( extendedLBA == -1 ) break;
58                 gATA_Disks[Disk].NumPartitions ++;
59         }
60         LOG("gATA_Disks[Disk].NumPartitions = %i", gATA_Disks[Disk].NumPartitions);
61         
62         // Create patition array
63         gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) );
64         
65         // --- Fill Partition Info ---
66         extendedLBA = 0;
67         for( j = 0, i = 0; i < 4; i ++ )
68         {
69                 LOG("MBR->Parts[%i].SystemID = 0x%02x", i, MBR->Parts[i].SystemID);
70                 if( MBR->Parts[i].SystemID == 0 )       continue;
71                 if( MBR->Parts[i].Boot == 0x0 || MBR->Parts[i].Boot == 0x80 )   // LBA 28
72                 {
73                         base = MBR->Parts[i].LBAStart;
74                         len = MBR->Parts[i].LBALength;
75                 }
76                 else if( MBR->Parts[i].Boot == 0x1 || MBR->Parts[i].Boot == 0x81 )      // LBA 58
77                 {
78                         base = (MBR->Parts[i].StartHi << 16) | MBR->Parts[i].LBAStart;
79                         len = (MBR->Parts[i].LengthHi << 16) | MBR->Parts[i].LBALength;
80                 }
81                 else
82                         continue;
83                 
84                 if( MBR->Parts[i].SystemID == 0xF || MBR->Parts[i].SystemID == 5 ) {
85                         if(extendedLBA != 0) {
86                                 Log_Warning("ATA", "Disk %i has multiple extended partitions, ignoring rest", Disk);
87                                 continue;
88                         }
89                         extendedLBA = base;
90                         continue;
91                 }
92                 // Create Partition
93                 ATA_int_MakePartition(
94                         &gATA_Disks[Disk].Partitions[j], Disk, j,
95                         base, len
96                         );
97                 j ++;
98                 
99         }
100         // Scan extended partitions
101         while(extendedLBA != 0)
102         {
103                 extendedLBA = ATA_MBR_int_ReadExt(Disk, extendedLBA, &base, &len);
104                 if(extendedLBA == -1)   break;
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         for( i = 0; i < 4; i ++ )
129         {
130                 if( mbr.Parts[i].SystemID == 0 )        continue;
131                 
132                 // LBA 24
133                 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) {
134                         base = mbr.Parts[i].LBAStart;
135                         len = mbr.Parts[i].LBALength;
136                 }
137                 // LBA 48
138                 else if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) {
139                         base = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
140                         len = (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength;
141                 }
142                 else {
143                         Log_Warning("ATA MBR",
144                                 "Unknown partition type 0x%x, Disk %i Ext 0x%llx Part %i",
145                                 mbr.Parts[i].Boot, Disk, Addr, i
146                                 );
147                         return -1;
148                 }
149                 
150                 switch(mbr.Parts[i].SystemID)
151                 {
152                 case 0xF:
153                 case 0x5:
154                         if(link != 0) {
155                                 Log_Warning("ATA MBR",
156                                         "Disk %i has two forward links in the extended partition",
157                                         Disk
158                                         );
159                                 return -1;
160                         }
161                         link = base;
162                         break;
163                 default:
164                         if(bFoundPart) {
165                                 Warning("ATA MBR",
166                                         "Disk %i has more than one partition in the extended partition at 0x%llx",
167                                         Disk, Addr
168                                         );
169                                 return -1;
170                         }
171                         bFoundPart = 1;
172                         *Base = base;
173                         *Length = len;
174                         break;
175                 }
176         }
177         
178         if(!bFoundPart) {
179                 Log_Warning("ATA MBR",
180                         "No partition in extended partiton, Disk %i 0x%llx",
181                         Disk, Addr);
182                 return -1;
183         }
184         
185         return link;
186 }

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