2 * Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Ingo Weinhold, bonefish@cs.tu-berlin.de
7 * Tomas Kucera, kucerat@centrum.cz
12 \brief partitioning system module for "intel" style partitions.
15 // TODO: The implementation is very strict right now. It rejects a partition
16 // completely, if it finds an error in its partition tables. We should see,
17 // what error can be handled gracefully, e.g. by ignoring the partition
18 // descriptor or the whole partition table sector.
27 #include <KernelExport.h>
29 #include <AutoDeleter.h>
30 #include <disk_device_manager/ddm_modules.h>
33 #include "PartitionLocker.h"
34 #include "PartitionMap.h"
35 #include "PartitionMapParser.h"
38 # include <DiskDeviceTypes.h>
39 # include "write_support.h"
40 # define TRACE(x) dprintf x
42 # include <boot/partitions.h>
43 # include <util/kernel_cpp.h>
49 #define INTEL_PARTITION_MODULE_NAME "partitioning_systems/intel/map/v1"
50 #define INTEL_EXTENDED_PARTITION_MODULE_NAME \
51 "partitioning_systems/intel/extended/v1"
59 // get_type_for_content_type (for both pm_* and ep_*)
61 get_type_for_content_type(const char* contentType
, char* type
)
63 TRACE(("intel: get_type_for_content_type(%s)\n",
66 if (!contentType
|| !type
)
70 ptype
.SetContentType(contentType
);
72 return B_NAME_NOT_FOUND
;
74 ptype
.GetTypeString(type
);
81 // #pragma mark - Intel Partition Map Module
86 pm_std_ops(int32 op
, ...)
88 TRACE(("intel: pm_std_ops(0x%" B_PRIx32
")\n", op
));
98 // pm_identify_partition
100 pm_identify_partition(int fd
, partition_data
* partition
, void** cookie
)
103 if (fd
< 0 || !partition
|| !cookie
)
106 TRACE(("intel: pm_identify_partition(%d, %" B_PRId32
": %" B_PRId64
", "
107 "%" B_PRId64
", %" B_PRId32
")\n", fd
, partition
->id
, partition
->offset
,
108 partition
->size
, partition
->block_size
));
109 // reject extended partitions
111 && !strcmp(partition
->type
, kPartitionTypeIntelExtended
)) {
115 // allocate a PartitionMap
116 PartitionMapCookie
* map
= new(nothrow
) PartitionMapCookie
;
120 // read the partition structure
121 PartitionMapParser
parser(fd
, 0, partition
->size
, partition
->block_size
);
122 status_t error
= parser
.Parse(NULL
, map
);
124 // cleanup, if not detected
131 // Depending on whether we actually have recognized child partitions and
132 // whether we are installed directly on a device (the by far most common
133 // setup), we determine the priority.
134 bool hasChildren
= (map
->CountNonEmptyPartitions() > 0);
135 bool hasParent
= (get_parent_partition(partition
->id
) != NULL
);
139 // This value overrides BFS.
143 // No children -- might be a freshly initialized disk. But it could
144 // also be an image file. So we give BFS a chance to override us.
148 // NOTE: It seems supporting nested partition maps makes more trouble than it
149 // has useful applications ATM. So it is disabled for the time being.
151 // We have a parent. That's a very unlikely setup.
155 // No children. Extremely unlikely, that this is desired. But if no one
156 // else claims the partition, we take it anyway.
165 pm_scan_partition(int fd
, partition_data
* partition
, void* cookie
)
168 if (fd
< 0 || !partition
|| !cookie
)
171 TRACE(("intel: pm_scan_partition(%d, %" B_PRId32
": %" B_PRId64
", "
172 "%" B_PRId64
", %" B_PRId32
")\n", fd
, partition
->id
, partition
->offset
,
173 partition
->size
, partition
->block_size
));
175 PartitionMapCookie
* map
= (PartitionMapCookie
*)cookie
;
176 // fill in the partition_data structure
177 partition
->status
= B_PARTITION_VALID
;
178 partition
->flags
|= B_PARTITION_PARTITIONING_SYSTEM
;
179 partition
->content_size
= partition
->size
;
180 // (no content_name and content_parameters)
181 // (content_type is set by the system)
183 partition
->content_cookie
= map
;
185 status_t error
= B_OK
;
187 for (int32 i
= 0; i
< 4; i
++) {
188 PrimaryPartition
* primary
= map
->PrimaryPartitionAt(i
);
189 if (!primary
->IsEmpty()) {
190 partition_data
* child
= create_child_partition(partition
->id
,
191 index
, partition
->offset
+ primary
->Offset(), primary
->Size(),
195 // something went wrong
200 child
->block_size
= partition
->block_size
;
203 char type
[B_FILE_NAME_LENGTH
];
204 primary
->GetTypeString(type
);
205 child
->type
= strdup(type
);
208 sprintf(buffer
, "type = %u ; active = %d", primary
->Type(),
210 child
->parameters
= strdup(buffer
);
211 child
->cookie
= primary
;
212 // check for allocation problems
213 if (!child
->type
|| !child
->parameters
) {
220 // keep map on success or cleanup on error
222 atomic_add(&map
->ref_count
, 1);
224 partition
->content_cookie
= NULL
;
225 for (int32 i
= 0; i
< partition
->child_count
; i
++) {
226 if (partition_data
* child
= get_child_partition(partition
->id
, i
))
227 child
->cookie
= NULL
;
235 // pm_free_identify_partition_cookie
237 pm_free_identify_partition_cookie(partition_data*/
* partition*/
, void* cookie
)
240 PartitionMapCookie
* map
= (PartitionMapCookie
*)cookie
;
241 if (atomic_add(&map
->ref_count
, -1) == 1)
247 // pm_free_partition_cookie
249 pm_free_partition_cookie(partition_data
* partition
)
251 // called for the primary partitions: the PrimaryPartition is allocated
252 // by the partition containing the partition map
254 partition
->cookie
= NULL
;
258 // pm_free_partition_content_cookie
260 pm_free_partition_content_cookie(partition_data
* partition
)
262 if (partition
&& partition
->content_cookie
) {
263 pm_free_identify_partition_cookie(partition
, partition
->content_cookie
);
264 partition
->content_cookie
= NULL
;
269 // #pragma mark - Intel Extended Partition Module
274 ep_std_ops(int32 op
, ...)
276 TRACE(("intel: ep_std_ops(0x%" B_PRIx32
")\n", op
));
279 case B_MODULE_UNINIT
:
286 // ep_identify_partition
288 ep_identify_partition(int fd
, partition_data
* partition
, void** cookie
)
291 if (fd
< 0 || !partition
|| !cookie
|| !partition
->cookie
)
294 TRACE(("intel: ep_identify_partition(%d, %" B_PRId64
", %" B_PRId64
", "
295 "%" B_PRId32
")\n", fd
, partition
->offset
, partition
->size
,
296 partition
->block_size
));
298 // our parent must be a intel partition map partition and we must have
299 // extended partition type
301 || strcmp(partition
->type
, kPartitionTypeIntelExtended
)) {
304 partition_data
* parent
= get_parent_partition(partition
->id
);
305 if (!parent
|| !parent
->content_type
306 || strcmp(parent
->content_type
, kPartitionTypeIntel
)) {
310 // things seem to be in order
317 ep_scan_partition(int fd
, partition_data
* partition
, void* cookie
)
320 if (fd
< 0 || !partition
|| !partition
->cookie
)
323 TRACE(("intel: ep_scan_partition(%d, %" B_PRId64
", %" B_PRId64
", "
324 "%" B_PRId32
")\n", fd
, partition
->offset
, partition
->size
,
325 partition
->block_size
));
327 partition_data
* parent
= get_parent_partition(partition
->id
);
331 PrimaryPartition
* primary
= (PrimaryPartition
*)partition
->cookie
;
332 // fill in the partition_data structure
333 partition
->status
= B_PARTITION_VALID
;
334 partition
->flags
|= B_PARTITION_PARTITIONING_SYSTEM
;
335 partition
->content_size
= partition
->size
;
336 // (no content_name and content_parameters)
337 // (content_type is set by the system)
339 partition
->content_cookie
= primary
;
341 status_t error
= B_OK
;
343 for (int32 i
= 0; i
< primary
->CountLogicalPartitions(); i
++) {
344 LogicalPartition
* logical
= primary
->LogicalPartitionAt(i
);
345 partition_data
* child
= create_child_partition(partition
->id
, index
,
346 parent
->offset
+ logical
->Offset(), logical
->Size(), -1);
349 // something went wrong
350 TRACE(("intel: ep_scan_partition(): failed to create child "
355 child
->block_size
= partition
->block_size
;
358 char type
[B_FILE_NAME_LENGTH
];
359 logical
->GetTypeString(type
);
360 child
->type
= strdup(type
);
364 sprintf(buffer
, "active %s ;\npartition_table_offset %" B_PRId64
" ;\n",
365 logical
->Active() ? "true" : "false",
366 logical
->PartitionTableOffset());
367 child
->parameters
= strdup(buffer
);
368 child
->cookie
= logical
;
369 // check for allocation problems
370 if (!child
->type
|| !child
->parameters
) {
371 TRACE(("intel: ep_scan_partition(): failed to allocation type "
380 partition
->content_cookie
= NULL
;
381 for (int32 i
= 0; i
< partition
->child_count
; i
++) {
382 if (partition_data
* child
= get_child_partition(partition
->id
, i
))
383 child
->cookie
= NULL
;
390 // ep_free_identify_partition_cookie
392 ep_free_identify_partition_cookie(partition_data
* partition
, void* cookie
)
398 // ep_free_partition_cookie
400 ep_free_partition_cookie(partition_data
* partition
)
402 // the logical partition's cookie belongs to the partition map partition
404 partition
->cookie
= NULL
;
408 // ep_free_partition_content_cookie
410 ep_free_partition_content_cookie(partition_data
* partition
)
412 // the extended partition's cookie belongs to the partition map partition
414 partition
->content_cookie
= NULL
;
418 // #pragma mark - modules
422 partition_module_info gIntelPartitionMapModule
=
424 static partition_module_info intel_partition_map_module
=
428 INTEL_PARTITION_MODULE_NAME
,
432 "intel", // short_name
433 INTEL_PARTITION_NAME
, // pretty_name
437 // | B_DISK_SYSTEM_SUPPORTS_CHECKING
438 // | B_DISK_SYSTEM_SUPPORTS_REPAIRING
439 | B_DISK_SYSTEM_SUPPORTS_RESIZING
440 | B_DISK_SYSTEM_SUPPORTS_MOVING
441 // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
442 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
443 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
444 // | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
446 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
447 | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
448 // | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME
449 | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
450 // | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS
451 | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD
452 | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD
453 // | B_DISK_SYSTEM_SUPPORTS_NAME
457 pm_identify_partition
, // identify_partition
458 pm_scan_partition
, // scan_partition
459 pm_free_identify_partition_cookie
, // free_identify_partition_cookie
460 pm_free_partition_cookie
, // free_partition_cookie
461 pm_free_partition_content_cookie
, // free_partition_content_cookie
465 pm_get_supported_operations
, // get_supported_operations
466 pm_get_supported_child_operations
, // get_supported_child_operations
467 NULL
, // supports_initializing_child
468 pm_is_sub_system_for
, // is_sub_system_for
470 pm_validate_resize
, // validate_resize
471 pm_validate_resize_child
, // validate_resize_child
472 pm_validate_move
, // validate_move
473 pm_validate_move_child
, // validate_move_child
474 NULL
, // validate_set_name
475 NULL
, // validate_set_content_name
476 pm_validate_set_type
, // validate_set_type
477 NULL
, // validate_set_parameters
478 NULL
, // validate_set_content_parameters
479 pm_validate_initialize
, // validate_initialize
480 pm_validate_create_child
, // validate_create_child
481 pm_get_partitionable_spaces
, // get_partitionable_spaces
482 pm_get_next_supported_type
, // get_next_supported_type
483 get_type_for_content_type
, // get_type_for_content_type
485 // shadow partition modification
486 pm_shadow_changed
, // shadow_changed
491 pm_resize_child
, // resize_child
493 pm_move_child
, // move_child
495 NULL
, // set_content_name
496 pm_set_type
, // set_type
497 NULL
, // set_parameters
498 NULL
, // set_content_parameters
499 pm_initialize
, // initialize
500 pm_uninitialize
, // uninitialize
501 pm_create_child
, // create_child
502 pm_delete_child
, // delete_child
510 partition_module_info gIntelExtendedPartitionModule
=
512 static partition_module_info intel_extended_partition_module
=
516 INTEL_EXTENDED_PARTITION_MODULE_NAME
,
520 "intel_extended", // short_name
521 INTEL_EXTENDED_PARTITION_NAME
, // pretty_name
525 // | B_DISK_SYSTEM_SUPPORTS_CHECKING
526 // | B_DISK_SYSTEM_SUPPORTS_REPAIRING
527 | B_DISK_SYSTEM_SUPPORTS_RESIZING
528 | B_DISK_SYSTEM_SUPPORTS_MOVING
529 // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
530 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
531 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
532 // | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
534 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
535 | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
536 // | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME
537 | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
538 // | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS
539 | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD
540 | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD
541 // | B_DISK_SYSTEM_SUPPORTS_NAME
545 ep_identify_partition
, // identify_partition
546 ep_scan_partition
, // scan_partition
547 ep_free_identify_partition_cookie
, // free_identify_partition_cookie
548 ep_free_partition_cookie
, // free_partition_cookie
549 ep_free_partition_content_cookie
, // free_partition_content_cookie
553 ep_get_supported_operations
, // get_supported_operations
554 ep_get_supported_child_operations
, // get_supported_child_operations
555 NULL
, // supports_initializing_child
556 ep_is_sub_system_for
, // is_sub_system_for
558 ep_validate_resize
, // validate_resize
559 ep_validate_resize_child
, // validate_resize_child
560 ep_validate_move
, // validate_move
561 ep_validate_move_child
, // validate_move_child
562 NULL
, // validate_set_name
563 NULL
, // validate_set_content_name
564 ep_validate_set_type
, // validate_set_type
565 NULL
, // validate_set_parameters
566 NULL
, // validate_set_content_parameters
567 ep_validate_initialize
, // validate_initialize
568 ep_validate_create_child
, // validate_create_child
569 ep_get_partitionable_spaces
, // get_partitionable_spaces
570 ep_get_next_supported_type
, // get_next_supported_type
571 get_type_for_content_type
, // get_type_for_content_type
573 // shadow partition modification
574 ep_shadow_changed
, // shadow_changed
579 ep_resize_child
, // resize_child
581 ep_move_child
, // move_child
583 NULL
, // set_content_name
584 ep_set_type
, // set_type
585 NULL
, // set_parameters
586 NULL
, // set_content_parameters
587 ep_initialize
, // initialize
588 NULL
, // uninitialize
589 ep_create_child
, // create_child
590 ep_delete_child
, // delete_child
598 extern "C" partition_module_info
* modules
[];
599 _EXPORT partition_module_info
* modules
[] =
601 &intel_partition_map_module
,
602 &intel_extended_partition_module
,