Refactored a bit -- pulled the partition map parser out. Userland add-on disabled for the time being, due to build problems.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9158 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2004-10-02 15:34:50 +00:00
parent 373fe20212
commit 569750e57f
4 changed files with 319 additions and 263 deletions

View File

@ -1,22 +1,25 @@
SubDir OBOS_TOP src add-ons kernel partitioning_systems intel ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName storage ] ;
UsePrivateHeaders kernel ;
UsePrivateHeaders shared ;
UsePrivateHeaders storage ;
KernelAddon intel : kernel partitioning_systems :
intel.cpp
PartitionMap.cpp
PartitionMapParser.cpp
;
# Also build a userland version
# ToDo: it's probably not a good idea to build them into the same directory
Addon <partitioning_system>intel : userland partitioning_systems :
intel.cpp
PartitionMap.cpp
;
#Addon <partitioning_system>intel : userland partitioning_systems :
# intel.cpp
# PartitionMap.cpp
# PartitionMapParser.cpp
#;
LinkSharedOSLibs <partitioning_system>intel :
libkernelland_emu.so
libdisk_device_manager.so
;
#LinkSharedOSLibs <partitioning_system>intel :
# libkernelland_emu.so
# libdisk_device_manager.so
#;

View File

@ -0,0 +1,217 @@
// PartitionMapParser.cpp
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <new>
#include "PartitionMap.h"
#include "PartitionMapParser.h"
#define TRACE(x) ;
//#define TRACE(x) dprintf x
// Maximal number of logical partitions per extended partition we allow.
static const int32 kMaxLogicalPartitionCount = 128;
// constructor
PartitionMapParser::PartitionMapParser(int deviceFD, off_t sessionOffset,
off_t sessionSize, int32 blockSize)
: fDeviceFD(deviceFD),
fSessionOffset(sessionOffset),
fSessionSize(sessionSize),
fBlockSize(blockSize),
fPTS(NULL),
fMap(NULL)
{
}
// destructor
PartitionMapParser::~PartitionMapParser()
{
}
// Parse
status_t
PartitionMapParser::Parse(const uint8 *block, PartitionMap *map)
{
status_t error = (map ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
fMap = map;
fMap->Unset();
if (block) {
const partition_table_sector *pts
= (const partition_table_sector*)block;
error = _ParsePrimary(pts);
} else {
partition_table_sector pts;
error = _ReadPTS(0, &pts);
if (error == B_OK)
error = _ParsePrimary(&pts);
}
if (error == B_OK && !fMap->Check(fSessionSize, fBlockSize))
error = B_BAD_DATA;
fMap = NULL;
}
return error;
}
// _ParsePrimary
status_t
PartitionMapParser::_ParsePrimary(const partition_table_sector *pts)
{
status_t error = (pts ? B_OK : B_BAD_VALUE);
// check the signature
if (error == B_OK && pts->signature != kPartitionTableSectorSignature) {
TRACE(("intel: _ParsePrimary(): invalid PTS signature\n"));
error = B_BAD_DATA;
}
// examine the table
if (error == B_OK) {
for (int32 i = 0; i < 4; i++) {
const partition_descriptor *descriptor = &pts->table[i];
PrimaryPartition *partition = fMap->PrimaryPartitionAt(i);
partition->SetTo(descriptor, 0, fBlockSize);
// fail, if location is bad
if (!partition->CheckLocation(fSessionSize, fBlockSize)) {
error = B_BAD_DATA;
break;
}
}
}
// allocate a PTS buffer
if (error == B_OK) {
fPTS = new(nothrow) partition_table_sector;
if (!fPTS)
error = B_NO_MEMORY;
}
// parse extended partitions
if (error == B_OK) {
for (int32 i = 0; error == B_OK && i < 4; i++) {
PrimaryPartition *primary = fMap->PrimaryPartitionAt(i);
if (primary->IsExtended())
error = _ParseExtended(primary, primary->Offset());
}
}
// cleanup
if (fPTS) {
delete fPTS;
fPTS = NULL;
}
return error;
}
// _ParseExtended
status_t
PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
{
status_t error = B_OK;
int32 partitionCount = 0;
while (error == B_OK) {
// check for cycles
if (++partitionCount > kMaxLogicalPartitionCount) {
TRACE(("intel: _ParseExtended(): Maximal number of logical "
"partitions for extended partition reached. Cycle?\n"));
error = B_BAD_DATA;
}
// read the PTS
if (error == B_OK)
error = _ReadPTS(offset);
// check the signature
if (error == B_OK
&& fPTS->signature != kPartitionTableSectorSignature) {
TRACE(("intel: _ParseExtended(): invalid PTS signature\n"));
error = B_BAD_DATA;
}
// ignore the PTS, if any error occured till now
if (error != B_OK) {
TRACE(("intel: _ParseExtended(): ignoring this PTS\n"));
error = B_OK;
break;
}
// examine the table
LogicalPartition extended;
LogicalPartition nonExtended;
if (error == B_OK) {
for (int32 i = 0; error == B_OK && i < 4; i++) {
const partition_descriptor *descriptor = &fPTS->table[i];
LogicalPartition *partition = NULL;
if (!descriptor->is_empty()) {
if (descriptor->is_extended()) {
if (extended.IsEmpty()) {
extended.SetTo(descriptor, offset, fBlockSize,
primary);
partition = &extended;
} else {
// only one extended partition allowed
error = B_BAD_DATA;
TRACE(("intel: _ParseExtended(): "
"only one extended partition allowed\n"));
}
} else {
if (nonExtended.IsEmpty()) {
nonExtended.SetTo(descriptor, offset, fBlockSize,
primary);
partition = &nonExtended;
} else {
// only one non-extended partition allowed
error = B_BAD_DATA;
TRACE(("intel: _ParseExtended(): only one "
"non-extended partition allowed\n"));
}
}
// check the partition's location
if (partition && !partition->CheckLocation(fSessionSize,
fBlockSize)) {
error = B_BAD_DATA;
}
}
}
}
// add non-extended partition to list
if (error == B_OK && !nonExtended.IsEmpty()) {
LogicalPartition *partition
= new(nothrow) LogicalPartition(nonExtended);
if (partition)
primary->AddLogicalPartition(partition);
else
error = B_NO_MEMORY;
}
// prepare to parse next extended partition
if (error == B_OK && !extended.IsEmpty())
offset = extended.Offset();
else
break;
}
return error;
}
// _ReadPTS
status_t
PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts)
{
status_t error = B_OK;
if (!pts)
pts = fPTS;
int32 toRead = sizeof(partition_table_sector);
// check the offset
if (offset < 0 || offset + toRead > fSessionSize) {
error = B_BAD_VALUE;
TRACE(("intel: _ReadPTS(): bad offset: %Ld\n", offset));
// read
} else if (read_pos(fDeviceFD, fSessionOffset + offset, pts, toRead)
!= toRead) {
#ifndef _BOOT_MODE
error = errno;
if (error == B_OK)
error = B_IO_ERROR;
#else
error = B_IO_ERROR;
#endif
TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n",
strerror(error)));
}
return error;
}

View File

@ -0,0 +1,38 @@
// PartitionMapParser.h
#ifndef PARTITION_MAP_PARSER_H
#define PARTITION_MAP_PARSER_H
#include <SupportDefs.h>
class Partition;
class PartitionMap;
class PrimaryPartition;
struct partition_table_sector;
class PartitionMapParser {
public:
PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize,
int32 blockSize);
~PartitionMapParser();
status_t Parse(const uint8 *block, PartitionMap *map);
int32 CountPartitions() const;
const Partition *PartitionAt(int32 index) const;
private:
status_t _ParsePrimary(const partition_table_sector *pts);
status_t _ParseExtended(PrimaryPartition *primary, off_t offset);
status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL);
private:
int fDeviceFD;
off_t fSessionOffset;
off_t fSessionSize;
int32 fBlockSize;
partition_table_sector *fPTS; // while parsing
PartitionMap *fMap; //
};
#endif // PARTITION_MAP_PARSER_H

View File

@ -16,18 +16,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util/kernel_cpp.h>
#include <AutoDeleter.h>
#include <ddm_modules.h>
#ifndef _BOOT_MODE
# include <DiskDeviceTypes.h>
#else
# include <boot/partitions.h>
//# include "DiskDeviceUtils.h"
#endif
#include <KernelExport.h>
#include "PartitionMap.h"
#include "PartitionMapParser.h"
#define TRACE(x) ;
//#define TRACE(x) dprintf x
@ -40,251 +42,6 @@
#define INTEL_PARTITION_NAME "Intel Partition Map"
#define INTEL_EXTENDED_PARTITION_NAME "Intel Extended Partition"
// Maximal number of logical partitions per extended partition we allow.
static const int32 kMaxLogicalPartitionCount = 128;
// AutoDeleter
template<typename C>
class AutoDeleter {
public:
AutoDeleter(C *object) : fObject(object) {}
~AutoDeleter() { delete fObject; }
void SetObject(C *object) { fObject = object; }
private:
C *fObject;
};
// PartitionMapParser
class PartitionMapParser {
public:
PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize,
int32 blockSize);
~PartitionMapParser();
status_t Parse(const uint8 *block, PartitionMap *map);
int32 CountPartitions() const;
const Partition *PartitionAt(int32 index) const;
private:
status_t _ParsePrimary(const partition_table_sector *pts);
status_t _ParseExtended(PrimaryPartition *primary, off_t offset);
status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL);
private:
int fDeviceFD;
off_t fSessionOffset;
off_t fSessionSize;
int32 fBlockSize;
partition_table_sector *fPTS; // while parsing
PartitionMap *fMap; //
};
// constructor
PartitionMapParser::PartitionMapParser(int deviceFD, off_t sessionOffset,
off_t sessionSize, int32 blockSize)
: fDeviceFD(deviceFD),
fSessionOffset(sessionOffset),
fSessionSize(sessionSize),
fBlockSize(blockSize),
fPTS(NULL),
fMap(NULL)
{
}
// destructor
PartitionMapParser::~PartitionMapParser()
{
}
// Parse
status_t
PartitionMapParser::Parse(const uint8 *block, PartitionMap *map)
{
status_t error = (map ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
fMap = map;
fMap->Unset();
if (block) {
const partition_table_sector *pts
= (const partition_table_sector*)block;
error = _ParsePrimary(pts);
} else {
partition_table_sector pts;
error = _ReadPTS(0, &pts);
if (error == B_OK)
error = _ParsePrimary(&pts);
}
if (error == B_OK && !fMap->Check(fSessionSize, fBlockSize))
error = B_BAD_DATA;
fMap = NULL;
}
return error;
}
// _ParsePrimary
status_t
PartitionMapParser::_ParsePrimary(const partition_table_sector *pts)
{
status_t error = (pts ? B_OK : B_BAD_VALUE);
// check the signature
if (error == B_OK && pts->signature != kPartitionTableSectorSignature) {
TRACE(("intel: _ParsePrimary(): invalid PTS signature\n"));
error = B_BAD_DATA;
}
// examine the table
if (error == B_OK) {
for (int32 i = 0; i < 4; i++) {
const partition_descriptor *descriptor = &pts->table[i];
PrimaryPartition *partition = fMap->PrimaryPartitionAt(i);
partition->SetTo(descriptor, 0, fBlockSize);
// fail, if location is bad
if (!partition->CheckLocation(fSessionSize, fBlockSize)) {
error = B_BAD_DATA;
break;
}
}
}
// allocate a PTS buffer
if (error == B_OK) {
fPTS = new(nothrow) partition_table_sector;
if (!fPTS)
error = B_NO_MEMORY;
}
// parse extended partitions
if (error == B_OK) {
for (int32 i = 0; error == B_OK && i < 4; i++) {
PrimaryPartition *primary = fMap->PrimaryPartitionAt(i);
if (primary->IsExtended())
error = _ParseExtended(primary, primary->Offset());
}
}
// cleanup
if (fPTS) {
delete fPTS;
fPTS = NULL;
}
return error;
}
// _ParseExtended
status_t
PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset)
{
status_t error = B_OK;
int32 partitionCount = 0;
while (error == B_OK) {
// check for cycles
if (++partitionCount > kMaxLogicalPartitionCount) {
TRACE(("intel: _ParseExtended(): Maximal number of logical "
"partitions for extended partition reached. Cycle?\n"));
error = B_BAD_DATA;
}
// read the PTS
if (error == B_OK)
error = _ReadPTS(offset);
// check the signature
if (error == B_OK
&& fPTS->signature != kPartitionTableSectorSignature) {
TRACE(("intel: _ParseExtended(): invalid PTS signature\n"));
error = B_BAD_DATA;
}
// ignore the PTS, if any error occured till now
if (error != B_OK) {
TRACE(("intel: _ParseExtended(): ignoring this PTS\n"));
error = B_OK;
break;
}
// examine the table
LogicalPartition extended;
LogicalPartition nonExtended;
if (error == B_OK) {
for (int32 i = 0; error == B_OK && i < 4; i++) {
const partition_descriptor *descriptor = &fPTS->table[i];
LogicalPartition *partition = NULL;
if (!descriptor->is_empty()) {
if (descriptor->is_extended()) {
if (extended.IsEmpty()) {
extended.SetTo(descriptor, offset, fBlockSize,
primary);
partition = &extended;
} else {
// only one extended partition allowed
error = B_BAD_DATA;
TRACE(("intel: _ParseExtended(): "
"only one extended partition allowed\n"));
}
} else {
if (nonExtended.IsEmpty()) {
nonExtended.SetTo(descriptor, offset, fBlockSize,
primary);
partition = &nonExtended;
} else {
// only one non-extended partition allowed
error = B_BAD_DATA;
TRACE(("intel: _ParseExtended(): only one "
"non-extended partition allowed\n"));
}
}
// check the partition's location
if (partition && !partition->CheckLocation(fSessionSize,
fBlockSize)) {
error = B_BAD_DATA;
}
}
}
}
// add non-extended partition to list
if (error == B_OK && !nonExtended.IsEmpty()) {
LogicalPartition *partition
= new(nothrow) LogicalPartition(nonExtended);
if (partition)
primary->AddLogicalPartition(partition);
else
error = B_NO_MEMORY;
}
// prepare to parse next extended partition
if (error == B_OK && !extended.IsEmpty())
offset = extended.Offset();
else
break;
}
return error;
}
// _ReadPTS
status_t
PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts)
{
status_t error = B_OK;
if (!pts)
pts = fPTS;
int32 toRead = sizeof(partition_table_sector);
// check the offset
if (offset < 0 || offset + toRead > fSessionSize) {
error = B_BAD_VALUE;
TRACE(("intel: _ReadPTS(): bad offset: %Ld\n", offset));
// read
} else if (read_pos(fDeviceFD, fSessionOffset + offset, pts, toRead)
!= toRead) {
#ifndef _BOOT_MODE
error = errno;
if (error == B_OK)
error = B_IO_ERROR;
#else
error = B_IO_ERROR;
#endif
TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n",
strerror(error)));
}
return error;
}
// intel partition map module
@ -308,13 +65,18 @@ static bool pm_supports_resizing_child(partition_data *partition,
static bool pm_validate_resize_child(partition_data *partition,
partition_data *child, off_t *size);
// writing
static status_t pm_resize_child(int fd, partition_id partition, off_t size,
disk_job_id job);
#endif
#ifdef _BOOT_MODE
partition_module_info gIntelPartitionMapModule = {
partition_module_info gIntelPartitionMapModule =
#else
static partition_module_info intel_partition_map_module = {
static partition_module_info intel_partition_map_module =
#endif
{
{
INTEL_PARTITION_MODULE_NAME,
0,
@ -369,7 +131,7 @@ static partition_module_info intel_partition_map_module = {
// writing
NULL, // repair
NULL, // resize
NULL, // resize_child
pm_resize_child, // resize_child
NULL, // move
NULL, // move_child
NULL, // set_name
@ -402,10 +164,11 @@ static void ep_free_partition_cookie(partition_data *partition);
static void ep_free_partition_content_cookie(partition_data *partition);
#ifdef _BOOT_MODE
partition_module_info gIntelExtendedPartitionModule = {
partition_module_info gIntelExtendedPartitionModule =
#else
static partition_module_info intel_extended_partition_module = {
static partition_module_info intel_extended_partition_module =
#endif
{
{
INTEL_EXTENDED_PARTITION_MODULE_NAME,
0,
@ -548,7 +311,7 @@ static
status_t
pm_scan_partition(int fd, partition_data *partition, void *cookie)
{
AutoDeleter<PartitionMap> deleter((PartitionMap*)cookie);
ObjectDeleter<PartitionMap> deleter((PartitionMap*)cookie);
// check parameters
if (fd < 0 || !partition || !cookie)
return B_ERROR;
@ -603,7 +366,7 @@ TRACE(("Creating child at index %ld failed\n", index - 1));
}
// keep map on success or cleanup on error
if (error == B_OK) {
deleter.SetObject(NULL);
deleter.Detach();
} else {
partition->content_cookie = NULL;
for (int32 i = 0; i < partition->child_count; i++) {
@ -693,6 +456,41 @@ pm_validate_resize_child(partition_data *partition, partition_data *child,
*size = *size / partition->block_size * partition->block_size;
return true;
}
// pm_resize_child
static
status_t
pm_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job)
{
/*
disk_device_data *device = read_lock_disk_device(partitionID);
if (!device)
return B_BAD_VALUE;
DeviceStructWriteLocker locker(device, true);
// get partition and child and out partition map structure
partition_data *partition = get_parent_partition(partitionID);
partition_data *child = get_partition(partitionID);
if (!partition || !child)
return B_BAD_VALUE;
PartitionMap *map = (PartitionMap*)partition->content_cookie;
PrimaryPartition *primary = child->cookie;
if (!map || !primary)
return B_BAD_VALUE;
// validate the new size
off_t validatedSize = size;
if (!pm_validate_resize_child(partition, child, validatedSize)
return B_BAD_VALUE;
if (child->size == validatedSize)
return B_OK;
// write the changes to disk
primary->SetSize(validatedSize);
// TODO: Write...
// TODO: PartitionMapParser into separate file,
// implement PartitionMapWriter
*/
set_disk_device_job_error_message(job, "Resize not implemented yet.");
return B_ERROR;
}
#endif // _BOOT_MODE