vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / partitioning_systems / intel / intel.cpp
blob6591c4b9c8d95e35feaf9221559769a22c47ce52
1 /*
2 * Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ingo Weinhold, bonefish@cs.tu-berlin.de
7 * Tomas Kucera, kucerat@centrum.cz
8 */
10 /*!
11 \file intel.cpp
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.
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include <new>
27 #include <KernelExport.h>
29 #include <AutoDeleter.h>
30 #include <disk_device_manager/ddm_modules.h>
32 #include "intel.h"
33 #include "PartitionLocker.h"
34 #include "PartitionMap.h"
35 #include "PartitionMapParser.h"
37 #ifndef _BOOT_MODE
38 # include <DiskDeviceTypes.h>
39 # include "write_support.h"
40 # define TRACE(x) dprintf x
41 #else
42 # include <boot/partitions.h>
43 # include <util/kernel_cpp.h>
44 # define TRACE(x) ;
45 #endif
48 // module names
49 #define INTEL_PARTITION_MODULE_NAME "partitioning_systems/intel/map/v1"
50 #define INTEL_EXTENDED_PARTITION_MODULE_NAME \
51 "partitioning_systems/intel/extended/v1"
54 using std::nothrow;
57 #ifndef _BOOT_MODE
59 // get_type_for_content_type (for both pm_* and ep_*)
60 static status_t
61 get_type_for_content_type(const char* contentType, char* type)
63 TRACE(("intel: get_type_for_content_type(%s)\n",
64 contentType));
66 if (!contentType || !type)
67 return B_BAD_VALUE;
69 PartitionType ptype;
70 ptype.SetContentType(contentType);
71 if (!ptype.IsValid())
72 return B_NAME_NOT_FOUND;
74 ptype.GetTypeString(type);
75 return B_OK;
78 #endif
81 // #pragma mark - Intel Partition Map Module
84 // pm_std_ops
85 static status_t
86 pm_std_ops(int32 op, ...)
88 TRACE(("intel: pm_std_ops(0x%" B_PRIx32 ")\n", op));
89 switch(op) {
90 case B_MODULE_INIT:
91 case B_MODULE_UNINIT:
92 return B_OK;
94 return B_ERROR;
98 // pm_identify_partition
99 static float
100 pm_identify_partition(int fd, partition_data* partition, void** cookie)
102 // check parameters
103 if (fd < 0 || !partition || !cookie)
104 return -1;
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
110 if (partition->type
111 && !strcmp(partition->type, kPartitionTypeIntelExtended)) {
112 return -1;
115 // allocate a PartitionMap
116 PartitionMapCookie* map = new(nothrow) PartitionMapCookie;
117 if (!map)
118 return -1;
120 // read the partition structure
121 PartitionMapParser parser(fd, 0, partition->size, partition->block_size);
122 status_t error = parser.Parse(NULL, map);
123 if (error != B_OK) {
124 // cleanup, if not detected
125 delete map;
126 return -1;
129 *cookie = map;
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);
137 if (!hasParent) {
138 if (hasChildren) {
139 // This value overrides BFS.
140 return 0.81;
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.
145 return 0.5;
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.
150 #if 0
151 // We have a parent. That's a very unlikely setup.
152 if (hasChildren)
153 return 0.4;
155 // No children. Extremely unlikely, that this is desired. But if no one
156 // else claims the partition, we take it anyway.
157 return 0.1;
158 #endif
159 return -1;
163 // pm_scan_partition
164 static status_t
165 pm_scan_partition(int fd, partition_data* partition, void* cookie)
167 // check parameters
168 if (fd < 0 || !partition || !cookie)
169 return B_ERROR;
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;
184 // children
185 status_t error = B_OK;
186 int32 index = 0;
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(),
192 -1);
193 index++;
194 if (!child) {
195 // something went wrong
196 error = B_ERROR;
197 break;
200 child->block_size = partition->block_size;
202 // (no name)
203 char type[B_FILE_NAME_LENGTH];
204 primary->GetTypeString(type);
205 child->type = strdup(type);
206 // parameters
207 char buffer[128];
208 sprintf(buffer, "type = %u ; active = %d", primary->Type(),
209 primary->Active());
210 child->parameters = strdup(buffer);
211 child->cookie = primary;
212 // check for allocation problems
213 if (!child->type || !child->parameters) {
214 error = B_NO_MEMORY;
215 break;
220 // keep map on success or cleanup on error
221 if (error == B_OK) {
222 atomic_add(&map->ref_count, 1);
223 } else {
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;
231 return error;
235 // pm_free_identify_partition_cookie
236 static void
237 pm_free_identify_partition_cookie(partition_data*/* partition*/, void* cookie)
239 if (cookie) {
240 PartitionMapCookie* map = (PartitionMapCookie*)cookie;
241 if (atomic_add(&map->ref_count, -1) == 1)
242 delete map;
247 // pm_free_partition_cookie
248 static void
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
253 if (partition)
254 partition->cookie = NULL;
258 // pm_free_partition_content_cookie
259 static void
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
272 // ep_std_ops
273 static status_t
274 ep_std_ops(int32 op, ...)
276 TRACE(("intel: ep_std_ops(0x%" B_PRIx32 ")\n", op));
277 switch(op) {
278 case B_MODULE_INIT:
279 case B_MODULE_UNINIT:
280 return B_OK;
282 return B_ERROR;
286 // ep_identify_partition
287 static float
288 ep_identify_partition(int fd, partition_data* partition, void** cookie)
290 // check parameters
291 if (fd < 0 || !partition || !cookie || !partition->cookie)
292 return -1;
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
300 if (!partition->type
301 || strcmp(partition->type, kPartitionTypeIntelExtended)) {
302 return -1;
304 partition_data* parent = get_parent_partition(partition->id);
305 if (!parent || !parent->content_type
306 || strcmp(parent->content_type, kPartitionTypeIntel)) {
307 return -1;
310 // things seem to be in order
311 return 0.95;
315 // ep_scan_partition
316 static status_t
317 ep_scan_partition(int fd, partition_data* partition, void* cookie)
319 // check parameters
320 if (fd < 0 || !partition || !partition->cookie)
321 return B_ERROR;
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);
328 if (!parent)
329 return B_ERROR;
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;
340 // children
341 status_t error = B_OK;
342 int32 index = 0;
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);
347 index++;
348 if (!child) {
349 // something went wrong
350 TRACE(("intel: ep_scan_partition(): failed to create child "
351 "partition\n"));
352 error = B_ERROR;
353 break;
355 child->block_size = partition->block_size;
357 // (no name)
358 char type[B_FILE_NAME_LENGTH];
359 logical->GetTypeString(type);
360 child->type = strdup(type);
362 // parameters
363 char buffer[128];
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 "
372 "or parameters\n"));
373 error = B_NO_MEMORY;
374 break;
378 // cleanup on error
379 if (error != B_OK) {
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;
386 return error;
390 // ep_free_identify_partition_cookie
391 static void
392 ep_free_identify_partition_cookie(partition_data* partition, void* cookie)
394 // nothing to do
398 // ep_free_partition_cookie
399 static void
400 ep_free_partition_cookie(partition_data* partition)
402 // the logical partition's cookie belongs to the partition map partition
403 if (partition)
404 partition->cookie = NULL;
408 // ep_free_partition_content_cookie
409 static void
410 ep_free_partition_content_cookie(partition_data* partition)
412 // the extended partition's cookie belongs to the partition map partition
413 if (partition)
414 partition->content_cookie = NULL;
418 // #pragma mark - modules
421 #ifdef _BOOT_MODE
422 partition_module_info gIntelPartitionMapModule =
423 #else
424 static partition_module_info intel_partition_map_module =
425 #endif
428 INTEL_PARTITION_MODULE_NAME,
430 pm_std_ops
432 "intel", // short_name
433 INTEL_PARTITION_NAME, // pretty_name
435 // flags
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
456 // scanning
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
463 #ifndef _BOOT_MODE
464 // querying
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
488 // writing
489 NULL, // repair
490 pm_resize, // resize
491 pm_resize_child, // resize_child
492 pm_move, // move
493 pm_move_child, // move_child
494 NULL, // set_name
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
503 #else
504 NULL
505 #endif // _BOOT_MODE
509 #ifdef _BOOT_MODE
510 partition_module_info gIntelExtendedPartitionModule =
511 #else
512 static partition_module_info intel_extended_partition_module =
513 #endif
516 INTEL_EXTENDED_PARTITION_MODULE_NAME,
518 ep_std_ops
520 "intel_extended", // short_name
521 INTEL_EXTENDED_PARTITION_NAME, // pretty_name
523 // flags
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
544 // scanning
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
551 #ifndef _BOOT_MODE
552 // querying
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
576 // writing
577 NULL, // repair
578 ep_resize, // resize
579 ep_resize_child, // resize_child
580 ep_move, // move
581 ep_move_child, // move_child
582 NULL, // set_name
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
591 #else // _BOOT_MODE
592 NULL
593 #endif // _BOOT_MODE
597 #ifndef _BOOT_MODE
598 extern "C" partition_module_info* modules[];
599 _EXPORT partition_module_info* modules[] =
601 &intel_partition_map_module,
602 &intel_extended_partition_module,
603 NULL
605 #endif