2 * Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Bryce Groff, brycegroff@gmail.com
9 #include "PartitionMapWriter.h"
23 # include <KernelExport.h>
26 #include "PartitionMap.h"
34 # define TRACE(x) printf x
36 # define TRACE(x) dprintf x
41 #if defined(__INTEL__) || defined(__x86_64__)
43 # define MBR_HEADER "MBR.h"
50 check_logical_location(const LogicalPartition
* child
,
51 const PrimaryPartition
* parent
)
53 if (child
->PartitionTableOffset() % child
->BlockSize() != 0) {
54 TRACE(("check_logical_location() - PartitionTableOffset: %" B_PRId64
" "
55 "not a multiple of media's block size: %" B_PRId32
"\n",
56 child
->PartitionTableOffset(), child
->BlockSize()));
59 if (child
->Offset() % child
->BlockSize() != 0) {
60 TRACE(("check_logical_location() - Parition offset: %" B_PRId64
" "
61 "is not a multiple of block size: %" B_PRId32
"\n", child
->Offset(),
65 if (child
->Size() % child
->BlockSize() != 0) {
66 TRACE(("check_logical_location() - Size: (%" B_PRId64
") is not a "
67 "multiple of block size: (%" B_PRId32
")\n", child
->Size(),
71 if (child
->PartitionTableOffset() < parent
->Offset()
72 || child
->PartitionTableOffset() >= parent
->Offset()
74 TRACE(("check_logical_location() - Partition table: (%" B_PRId64
") not"
75 " within extended partition (start: %" B_PRId64
"), (end: "
76 "%" B_PRId64
")\n", child
->PartitionTableOffset(), parent
->Offset(),
77 parent
->Offset() + parent
->Size()));
80 if (child
->Offset() + child
->Size() > parent
->Offset() + parent
->Size()) {
81 TRACE(("check_logical_location() - logical paritition does not lie "
82 "within extended partition\n"));
89 PartitionMapWriter::PartitionMapWriter(int deviceFD
, uint32 blockSize
)
97 PartitionMapWriter::~PartitionMapWriter()
103 PartitionMapWriter::WriteMBR(const PartitionMap
* map
, bool writeBootCode
)
108 partition_table partitionTable
;
109 status_t error
= _ReadBlock(0, partitionTable
);
114 // the boot code must be small enough to fit in the code area
115 STATIC_ASSERT(kMBRSize
<= sizeof(partitionTable
.code_area
));
116 partitionTable
.clear_code_area();
117 partitionTable
.fill_code_area(kMBR
, kMBRSize
);
121 partitionTable
.signature
= kPartitionTableSectorSignature
;
123 for (int i
= 0; i
< 4; i
++) {
124 partition_descriptor
* descriptor
= &partitionTable
.table
[i
];
125 const PrimaryPartition
* partition
= map
->PrimaryPartitionAt(i
);
127 partition
->GetPartitionDescriptor(descriptor
);
130 error
= _WriteBlock(0, partitionTable
);
136 PartitionMapWriter::WriteLogical(const LogicalPartition
* logical
,
137 const PrimaryPartition
* primary
, bool clearCode
)
139 if (logical
== NULL
|| primary
== NULL
)
142 if (!check_logical_location(logical
, primary
))
145 partition_table partitionTable
;
147 partitionTable
.clear_code_area();
149 status_t error
= _ReadBlock(logical
->PartitionTableOffset(),
155 partitionTable
.signature
= kPartitionTableSectorSignature
;
157 partition_descriptor
* descriptor
= &partitionTable
.table
[0];
158 logical
->GetPartitionDescriptor(descriptor
);
160 descriptor
= &partitionTable
.table
[1];
161 if (logical
->Next() != NULL
)
162 logical
->Next()->GetPartitionDescriptor(descriptor
, true);
164 memset(descriptor
, 0, sizeof(partition_descriptor
));
166 // last two descriptors are empty
167 for (int32 i
= 2; i
< 4; i
++) {
168 descriptor
= &partitionTable
.table
[i
];
169 memset(descriptor
, 0, sizeof(partition_descriptor
));
172 status_t error
= _WriteBlock(logical
->PartitionTableOffset(),
179 PartitionMapWriter::WriteExtendedHead(const LogicalPartition
* logical
,
180 const PrimaryPartition
* primary
, bool clearCode
)
185 partition_table partitionTable
;
187 partitionTable
.clear_code_area();
189 status_t error
= _ReadBlock(primary
->Offset(), partitionTable
);
194 partitionTable
.signature
= kPartitionTableSectorSignature
;
195 partition_descriptor
* descriptor
;
196 if (logical
== NULL
) {
197 for (int32 i
= 0; i
< 4; i
++) {
198 descriptor
= &partitionTable
.table
[i
];
199 memset(descriptor
, 0, sizeof(partition_descriptor
));
202 LogicalPartition partition
;
203 partition
.SetPartitionTableOffset(primary
->Offset());
204 partition
.SetBlockSize(logical
->BlockSize());
205 partition
.SetOffset(logical
->Offset());
206 partition
.SetSize(logical
->Size());
207 partition
.SetType(logical
->Type());
209 // set the logicals partition table to the correct location
210 descriptor
= &partitionTable
.table
[0];
211 partition
.GetPartitionDescriptor(descriptor
);
213 descriptor
= &partitionTable
.table
[1];
214 LogicalPartition
* next
= logical
->Next();
216 next
->GetPartitionDescriptor(descriptor
, true);
218 memset(descriptor
, 0, sizeof(partition_descriptor
));
220 // last two descriptors are empty
221 for (int32 i
= 2; i
< 4; i
++) {
222 descriptor
= &partitionTable
.table
[i
];
223 memset(descriptor
, 0, sizeof(partition_descriptor
));
227 status_t error
= _WriteBlock(primary
->Offset(), partitionTable
);
237 PartitionMapWriter::ClearExtendedHead(const PrimaryPartition
* primary
)
242 partition_table partitionTable
;
243 partitionTable
.clear_code_area();
244 partitionTable
.signature
= kPartitionTableSectorSignature
;
246 partition_descriptor
* descriptor
;
247 for (int32 i
= 0; i
< 4; i
++) {
248 descriptor
= &partitionTable
.table
[i
];
249 memset(descriptor
, 0, sizeof(partition_descriptor
));
252 status_t error
= _WriteBlock(primary
->Offset(), partitionTable
);
261 PartitionMapWriter::_ReadBlock(off_t partitionOffset
,
262 partition_table
& partitionTable
)
264 if (partitionOffset
< 0)
266 // TODO: If fBlockSize > sizeof(partition_table) then stop/read NULL after
267 if (read_pos(fDeviceFD
, partitionOffset
, &partitionTable
,
268 sizeof(partitionTable
)) != sizeof(partitionTable
)) {
269 status_t error
= errno
;
281 PartitionMapWriter::_WriteBlock(off_t partitionOffset
,
282 const partition_table
& partitionTable
)
284 if (partitionOffset
< 0)
286 // TODO: maybe clear the rest of the block if
287 // fBlockSize > sizeof(partition_table)?
288 if (write_pos(fDeviceFD
, partitionOffset
, &partitionTable
,
289 sizeof(partitionTable
)) != sizeof(partitionTable
)) {
290 status_t error
= errno
;