[FREELDR]: Do not build Disk/Partition support for ARM, we use ram disks.
[reactos.git] / reactos / boot / freeldr / freeldr / disk / partition.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef _M_ARM
21 #include <freeldr.h>
22 #include <debug.h>
23
24 BOOLEAN DiskGetActivePartitionEntry(ULONG DriveNumber,
25 PPARTITION_TABLE_ENTRY PartitionTableEntry,
26 ULONG *ActivePartition)
27 {
28 ULONG BootablePartitionCount = 0;
29 MASTER_BOOT_RECORD MasterBootRecord;
30
31 *ActivePartition = 0;
32 // Read master boot record
33 if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
34 {
35 return FALSE;
36 }
37
38 // Count the bootable partitions
39 if (MasterBootRecord.PartitionTable[0].BootIndicator == 0x80)
40 {
41 BootablePartitionCount++;
42 *ActivePartition = 1;
43 }
44 if (MasterBootRecord.PartitionTable[1].BootIndicator == 0x80)
45 {
46 BootablePartitionCount++;
47 *ActivePartition = 2;
48 }
49 if (MasterBootRecord.PartitionTable[2].BootIndicator == 0x80)
50 {
51 BootablePartitionCount++;
52 *ActivePartition = 3;
53 }
54 if (MasterBootRecord.PartitionTable[3].BootIndicator == 0x80)
55 {
56 BootablePartitionCount++;
57 *ActivePartition = 4;
58 }
59
60 // Make sure there was only one bootable partition
61 if (BootablePartitionCount == 0)
62 {
63 DPRINTM(DPRINT_DISK, "No bootable (active) partitions found.\n");
64 return FALSE;
65 }
66 else if (BootablePartitionCount != 1)
67 {
68 DPRINTM(DPRINT_DISK, "Too many bootable (active) partitions found.\n");
69 return FALSE;
70 }
71
72 // Copy the partition table entry
73 RtlCopyMemory(PartitionTableEntry,
74 &MasterBootRecord.PartitionTable[*ActivePartition - 1],
75 sizeof(PARTITION_TABLE_ENTRY));
76
77 return TRUE;
78 }
79
80 BOOLEAN DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
81 {
82 MASTER_BOOT_RECORD MasterBootRecord;
83 PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry;
84 ULONG ExtendedPartitionNumber;
85 ULONG ExtendedPartitionOffset;
86 ULONG Index;
87
88 // Read master boot record
89 if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
90 {
91 return FALSE;
92 }
93
94 // If they are asking for a primary
95 // partition then things are easy
96 if (PartitionNumber < 5)
97 {
98 // PartitionNumber is one-based and we need it zero-based
99 PartitionNumber--;
100
101 // Copy the partition table entry
102 RtlCopyMemory(PartitionTableEntry, &MasterBootRecord.PartitionTable[PartitionNumber], sizeof(PARTITION_TABLE_ENTRY));
103
104 return TRUE;
105 }
106 else
107 {
108 // They want an extended partition entry so we will need
109 // to loop through all the extended partitions on the disk
110 // and return the one they want.
111
112 ExtendedPartitionNumber = PartitionNumber - 5;
113
114 // Set the initial relative starting sector to 0
115 // This is because extended partition starting
116 // sectors a numbered relative to their parent
117 ExtendedPartitionOffset = 0;
118
119 for (Index=0; Index<=ExtendedPartitionNumber; Index++)
120 {
121 // Get the extended partition table entry
122 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry))
123 {
124 return FALSE;
125 }
126
127 // Adjust the relative starting sector of the partition
128 ExtendedPartitionTableEntry.SectorCountBeforePartition += ExtendedPartitionOffset;
129 if (ExtendedPartitionOffset == 0)
130 {
131 // Set the start of the parrent extended partition
132 ExtendedPartitionOffset = ExtendedPartitionTableEntry.SectorCountBeforePartition;
133 }
134 // Read the partition boot record
135 if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionTableEntry.SectorCountBeforePartition, &MasterBootRecord))
136 {
137 return FALSE;
138 }
139
140 // Get the first real partition table entry
141 if (!DiskGetFirstPartitionEntry(&MasterBootRecord, PartitionTableEntry))
142 {
143 return FALSE;
144 }
145
146 // Now correct the start sector of the partition
147 PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionTableEntry.SectorCountBeforePartition;
148 }
149
150 // When we get here we should have the correct entry
151 // already stored in PartitionTableEntry
152 // so just return TRUE
153 return TRUE;
154 }
155
156 }
157
158 BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry)
159 {
160 ULONG Index;
161
162 for (Index=0; Index<4; Index++)
163 {
164 // Check the system indicator
165 // If it's not an extended or unused partition
166 // then we're done
167 if ((MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_ENTRY_UNUSED) &&
168 (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_EXTENDED) &&
169 (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_XINT13_EXTENDED))
170 {
171 RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY));
172 return TRUE;
173 }
174 }
175
176 return FALSE;
177 }
178
179 BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry)
180 {
181 ULONG Index;
182
183 for (Index=0; Index<4; Index++)
184 {
185 // Check the system indicator
186 // If it an extended partition then we're done
187 if ((MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_EXTENDED) ||
188 (MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_XINT13_EXTENDED))
189 {
190 RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY));
191 return TRUE;
192 }
193 }
194
195 return FALSE;
196 }
197
198 BOOLEAN DiskReadBootRecord(ULONG DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord)
199 {
200 char ErrMsg[64];
201 ULONG Index;
202
203 // Read master boot record
204 if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, (PVOID)DISKREADBUFFER))
205 {
206 return FALSE;
207 }
208 RtlCopyMemory(BootRecord, (PVOID)DISKREADBUFFER, sizeof(MASTER_BOOT_RECORD));
209
210
211 DPRINTM(DPRINT_DISK, "Dumping partition table for drive 0x%x:\n", DriveNumber);
212 DPRINTM(DPRINT_DISK, "Boot record logical start sector = %d\n", LogicalSectorNumber);
213 DPRINTM(DPRINT_DISK, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD));
214
215 for (Index=0; Index<4; Index++)
216 {
217 DPRINTM(DPRINT_DISK, "-------------------------------------------\n");
218 DPRINTM(DPRINT_DISK, "Partition %d\n", (Index + 1));
219 DPRINTM(DPRINT_DISK, "BootIndicator: 0x%x\n", BootRecord->PartitionTable[Index].BootIndicator);
220 DPRINTM(DPRINT_DISK, "StartHead: 0x%x\n", BootRecord->PartitionTable[Index].StartHead);
221 DPRINTM(DPRINT_DISK, "StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].StartSector);
222 DPRINTM(DPRINT_DISK, "StartCylinder: 0x%x\n", BootRecord->PartitionTable[Index].StartCylinder);
223 DPRINTM(DPRINT_DISK, "SystemIndicator: 0x%x\n", BootRecord->PartitionTable[Index].SystemIndicator);
224 DPRINTM(DPRINT_DISK, "EndHead: 0x%x\n", BootRecord->PartitionTable[Index].EndHead);
225 DPRINTM(DPRINT_DISK, "EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].EndSector);
226 DPRINTM(DPRINT_DISK, "EndCylinder: 0x%x\n", BootRecord->PartitionTable[Index].EndCylinder);
227 DPRINTM(DPRINT_DISK, "SectorCountBeforePartition: 0x%x\n", BootRecord->PartitionTable[Index].SectorCountBeforePartition);
228 DPRINTM(DPRINT_DISK, "PartitionSectorCount: 0x%x\n", BootRecord->PartitionTable[Index].PartitionSectorCount);
229 }
230
231 // Check the partition table magic value
232 if (BootRecord->MasterBootRecordMagic != 0xaa55)
233 {
234 sprintf(ErrMsg, "Invalid partition table magic 0x%x found on drive 0x%lx",
235 BootRecord->MasterBootRecordMagic, DriveNumber);
236 DiskError(ErrMsg, 0);
237 return FALSE;
238 }
239
240 return TRUE;
241 }
242
243 #endif