ReactOS 0.4.16-dev-2610-ge2c92c0
part_mbr.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: MBR partitioning scheme support
5 * COPYRIGHT: Copyright 2002-2003 Brian Palmer <brianp@sginet.com>
6 * Copyright 2016 Wim Hueskes
7 */
8
9#ifndef _M_ARM
10// #include <freeldr.h>
11#include "part_mbr.h"
12
13// #include <debug.h>
14// DBG_DEFAULT_CHANNEL(DISK);
15
16static BOOLEAN
18 _In_ PMASTER_BOOT_RECORD MasterBootRecord,
19 _Out_ PPARTITION_TABLE_ENTRY* pPartitionTableEntry)
20{
22
23 for (Index = 0; Index < 4; Index++)
24 {
25 /* Check the system indicator. If it's not an extended or unused partition then we're done. */
26 if ((MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_ENTRY_UNUSED) &&
27 (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_EXTENDED) &&
28 (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_XINT13_EXTENDED))
29 {
30 *pPartitionTableEntry = &MasterBootRecord->PartitionTable[Index];
31 return TRUE;
32 }
33 }
34
35 return FALSE;
36}
37
38static BOOLEAN
40 _In_ PMASTER_BOOT_RECORD MasterBootRecord,
41 _Out_ PPARTITION_TABLE_ENTRY* pPartitionTableEntry)
42{
44
45 for (Index = 0; Index < 4; Index++)
46 {
47 /* Check the system indicator. If it an extended partition then we're done. */
48 if ((MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_EXTENDED) ||
49 (MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_XINT13_EXTENDED))
50 {
51 *pPartitionTableEntry = &MasterBootRecord->PartitionTable[Index];
52 return TRUE;
53 }
54 }
55
56 return FALSE;
57}
58
59static VOID
61 _Out_ PPARTITION_INFORMATION PartitionEntry,
62 _In_ PPARTITION_TABLE_ENTRY PartitionTableEntry,
65{
66 PartitionEntry->StartingOffset.QuadPart = (ULONGLONG)PartitionTableEntry->SectorCountBeforePartition * SectorSize;
67 PartitionEntry->PartitionLength.QuadPart = (ULONGLONG)PartitionTableEntry->PartitionSectorCount * SectorSize;
68 PartitionEntry->HiddenSectors = 0;
69 PartitionEntry->PartitionNumber = PartitionNumber;
70 PartitionEntry->PartitionType = PartitionTableEntry->SystemIndicator;
71 PartitionEntry->BootIndicator = (PartitionTableEntry->BootIndicator == 0x80); // or "& 0x80"
72 PartitionEntry->RecognizedPartition = TRUE;
73 PartitionEntry->RewritePartition = FALSE;
74}
75
78 _In_ UCHAR DriveNumber,
80 _Out_opt_ PPARTITION_INFORMATION PartitionEntry,
81 _Out_ PULONG ActivePartition)
82{
83 MASTER_BOOT_RECORD MasterBootRecord;
84 ULONG BootablePartitionCount = 0;
85 ULONG CurrentPartitionNumber;
87
88 ASSERT(SectorSize >= 512);
89
90 *ActivePartition = 0;
91
92 /* Read master boot record */
93 if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
94 return FALSE;
95
96 CurrentPartitionNumber = 0;
97 for (Index = 0; Index < 4; Index++)
98 {
99 PPARTITION_TABLE_ENTRY PartitionTableEntry = &MasterBootRecord.PartitionTable[Index];
100
101 if (PartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED &&
102 PartitionTableEntry->SystemIndicator != PARTITION_EXTENDED &&
103 PartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED)
104 {
105 CurrentPartitionNumber++;
106
107 /* Test if this is the bootable partition */
108 if (PartitionTableEntry->BootIndicator == 0x80)
109 {
110 BootablePartitionCount++;
111 *ActivePartition = CurrentPartitionNumber;
112
113 /* Copy the partition table entry */
114 if (PartitionEntry)
115 {
116 DiskMbrPartitionTableEntryToInformation(PartitionEntry, PartitionTableEntry,
117 *ActivePartition, SectorSize);
118 }
119 }
120 }
121 }
122
123 /* Make sure there was only one bootable partition */
124 if (BootablePartitionCount == 0)
125 {
126 ERR("No bootable (active) partitions found.\n");
127 return FALSE;
128 }
129 else if (BootablePartitionCount != 1)
130 {
131 ERR("Too many bootable (active) partitions found.\n");
132 return FALSE;
133 }
134
135 return TRUE;
136}
137
140 _In_ UCHAR DriveNumber,
143 _Out_ PPARTITION_INFORMATION PartitionEntry)
144{
145 MASTER_BOOT_RECORD MasterBootRecord;
146 PPARTITION_TABLE_ENTRY PartitionTableEntry;
147 ULONG ExtendedPartitionNumber;
148 ULONG ExtendedPartitionOffset;
149 ULONG Index;
150 ULONG CurrentPartitionNumber;
151
152 ASSERT(SectorSize >= 512);
153
154 /* Validate partition number */
155 if (PartitionNumber < 1) //if (PartitionNumber == 0)
156 return FALSE;
157
158 /* Read master boot record */
159 if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord))
160 return FALSE;
161
162 CurrentPartitionNumber = 0;
163 for (Index = 0; Index < 4; Index++)
164 {
165 PartitionTableEntry = &MasterBootRecord.PartitionTable[Index];
166
167 if (PartitionTableEntry->SystemIndicator != PARTITION_ENTRY_UNUSED &&
168 PartitionTableEntry->SystemIndicator != PARTITION_EXTENDED &&
169 PartitionTableEntry->SystemIndicator != PARTITION_XINT13_EXTENDED)
170 {
171 CurrentPartitionNumber++;
172 }
173
174 if (PartitionNumber == CurrentPartitionNumber)
175 {
176 DiskMbrPartitionTableEntryToInformation(PartitionEntry, PartitionTableEntry,
178 return TRUE;
179 }
180 }
181
182 /*
183 * They want an extended partition entry so we will need
184 * to loop through all the extended partitions on the disk
185 * and return the one they want.
186 */
187 ExtendedPartitionNumber = PartitionNumber - CurrentPartitionNumber - 1;
188
189 /*
190 * Set the initial relative starting sector to 0.
191 * This is because extended partition starting
192 * sectors a numbered relative to their parent.
193 */
194 ExtendedPartitionOffset = 0;
195
196 for (Index = 0; Index <= ExtendedPartitionNumber; Index++)
197 {
198 PPARTITION_TABLE_ENTRY ExtendedPartitionTableEntry;
199 ULONG SectorCountBeforePartition;
200
201 /* Get the extended partition table entry */
202 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry))
203 return FALSE;
204
205 /* Adjust the relative starting sector of the partition */
206 ExtendedPartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionOffset;
207 if (ExtendedPartitionOffset == 0)
208 {
209 /* Set the start of the parent extended partition */
210 ExtendedPartitionOffset = ExtendedPartitionTableEntry->SectorCountBeforePartition;
211 }
212 SectorCountBeforePartition = ExtendedPartitionTableEntry->SectorCountBeforePartition;
213
214 /* Read the partition boot record */
215 if (!DiskReadBootRecord(DriveNumber, SectorCountBeforePartition, &MasterBootRecord))
216 return FALSE;
217
218 /* Get the first real partition table entry */
219 if (!DiskGetFirstPartitionEntry(&MasterBootRecord, &PartitionTableEntry))
220 return FALSE;
221
222 /* Now correct the start sector of the partition */
223 PartitionTableEntry->SectorCountBeforePartition += SectorCountBeforePartition;
224 }
225
226 /* When we get here we should have the correct entry already
227 * stored in PartitionTableEntry, so just return TRUE. */
228 DiskMbrPartitionTableEntryToInformation(PartitionEntry, PartitionTableEntry,
230 return TRUE;
231}
232
233#endif
unsigned char BOOLEAN
Definition: actypes.h:127
#define ERR(fmt,...)
Definition: precomp.h:57
BOOLEAN DiskReadBootRecord(IN UCHAR DriveNumber, IN ULONGLONG LogicalSectorNumber, OUT PMASTER_BOOT_RECORD BootRecord)
Definition: partition.c:23
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ASSERT(a)
Definition: mode.c:44
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
BOOLEAN DiskGetMbrPartitionEntry(_In_ UCHAR DriveNumber, _In_ ULONG SectorSize, _In_ ULONG PartitionNumber, _Out_ PPARTITION_INFORMATION PartitionEntry)
Definition: part_mbr.c:139
static BOOLEAN DiskGetFirstExtendedPartitionEntry(_In_ PMASTER_BOOT_RECORD MasterBootRecord, _Out_ PPARTITION_TABLE_ENTRY *pPartitionTableEntry)
Definition: part_mbr.c:39
static BOOLEAN DiskGetFirstPartitionEntry(_In_ PMASTER_BOOT_RECORD MasterBootRecord, _Out_ PPARTITION_TABLE_ENTRY *pPartitionTableEntry)
Definition: part_mbr.c:17
static VOID DiskMbrPartitionTableEntryToInformation(_Out_ PPARTITION_INFORMATION PartitionEntry, _In_ PPARTITION_TABLE_ENTRY PartitionTableEntry, _In_ ULONG PartitionNumber, _In_ ULONG SectorSize)
Definition: part_mbr.c:60
BOOLEAN DiskGetActivePartitionEntry(_In_ UCHAR DriveNumber, _In_ ULONG SectorSize, _Out_opt_ PPARTITION_INFORMATION PartitionEntry, _Out_ PULONG ActivePartition)
Definition: part_mbr.c:77
#define PARTITION_ENTRY_UNUSED
Definition: part_mbr.h:50
#define PARTITION_EXTENDED
Definition: part_mbr.h:55
#define PARTITION_XINT13_EXTENDED
Definition: part_mbr.h:62
PARTITION_TABLE_ENTRY PartitionTable[4]
Definition: parttest.c:92
Definition: part_mbr.h:16
ULONG SectorCountBeforePartition
Definition: part_mbr.h:26
UCHAR BootIndicator
Definition: part_mbr.h:17
UCHAR SystemIndicator
Definition: part_mbr.h:22
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ ULONG SectorSize
Definition: halfuncs.h:291
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061