Added support for relocation.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4839 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2003-09-28 15:15:20 +00:00
parent ce8cfdb8a6
commit f3a589c2ce
4 changed files with 100 additions and 11 deletions
@@ -344,6 +344,7 @@ KDiskDevice::WriteUserData(UserDataWriter &writer, bool shadow)
if (data) {
data->device_flags = DeviceFlags();
data->path = path;
writer.AddRelocationEntry(&data->path);
partition->WriteUserData(writer, &data->device_partition_data);
} else
partition->WriteUserData(writer, NULL);
@@ -938,13 +938,22 @@ KPartition::WriteUserData(UserDataWriter &writer, user_partition_data *data)
data->parameters = parameters;
data->content_parameters = contentParameters;
data->child_count = CountChildren();
// make buffer relocatable
writer.AddRelocationEntry(&data->name);
writer.AddRelocationEntry(&data->content_name);
writer.AddRelocationEntry(&data->type);
writer.AddRelocationEntry(&data->content_type);
writer.AddRelocationEntry(&data->parameters);
writer.AddRelocationEntry(&data->content_parameters);
}
// children
for (int32 i = 0; KPartition *child = ChildAt(i); i++) {
user_partition_data *childData
= writer.AllocatePartitionData(child->CountChildren());
if (data)
if (data) {
data->children[i] = childData;
writer.AddRelocationEntry(&data->children[i]);
}
child->WriteUserData(writer, childData);
}
}
@@ -1,43 +1,87 @@
// UserDataWriter.cpp
#include <new>
#include <ddm_userland_interface.h>
#include <Vector.h>
#include "UserDataWriter.h"
using namespace std;
typedef uint8 *addr;
// RelocationEntryList
struct UserDataWriter::RelocationEntryList : Vector<addr*> {};
// constructor
UserDataWriter::UserDataWriter()
: fBuffer(NULL),
fBufferSize(0),
fAllocatedSize(0)
fAllocatedSize(0),
fRelocationEntries(NULL)
{
}
// constructor
UserDataWriter::UserDataWriter(user_disk_device_data *buffer,
size_t bufferSize)
: fBuffer(buffer),
fBufferSize(bufferSize),
fAllocatedSize(0)
: fBuffer(NULL),
fBufferSize(0),
fAllocatedSize(0),
fRelocationEntries(NULL)
{
SetTo(buffer, bufferSize);
}
// destructor
UserDataWriter::~UserDataWriter()
{
delete fRelocationEntries;
}
// SetTo
status_t
UserDataWriter::SetTo(user_disk_device_data *buffer, size_t bufferSize)
{
Unset();
fBuffer = buffer;
fBufferSize = bufferSize;
fAllocatedSize = 0;
if (fBuffer && fBufferSize > 0) {
fRelocationEntries = new(nothrow) RelocationEntryList;
if (!fRelocationEntries)
return B_NO_MEMORY;
}
return B_OK;
}
// Unset
void
UserDataWriter::Unset()
{
delete fRelocationEntries;
fBuffer = NULL;
fBufferSize = 0;
fAllocatedSize = 0;
fRelocationEntries = NULL;
}
// AllocateData
void *
UserDataWriter::AllocateData(size_t size, size_t align = 1)
{
if (size == 0)
return NULL;
// handles size == 0 gracefully
// get a properly aligned offset
size_t offset = fAllocatedSize;
if (align > 1)
fAllocatedSize = (fAllocatedSize + align - 1) / align * align;
offset = (fAllocatedSize + align - 1) / align * align;
// get the result pointer
void *result = NULL;
if (fAllocatedSize + size <= fBufferSize)
result = (uint8*)fBuffer + fAllocatedSize;
fAllocatedSize += size;
if (fBuffer && offset + size <= fBufferSize)
result = (uint8*)fBuffer + offset;
// always update the allocated size, even if there wasn't enough space
fAllocatedSize = offset + size;
return result;
}
@@ -81,3 +125,29 @@ UserDataWriter::AllocatedSize() const
return fAllocatedSize;
}
// AddRelocationEntry
status_t
UserDataWriter::AddRelocationEntry(void *address)
{
if (fRelocationEntries && (addr)address >= (addr)fBuffer
&& (addr)address < (addr)fBuffer + fBufferSize - sizeof(void*)) {
return fRelocationEntries->PushBack((addr*)address);
}
return B_ERROR;
}
// Relocate
status_t
UserDataWriter::Relocate(void *address)
{
if (!fRelocationEntries || !fBuffer)
return B_BAD_VALUE;
int32 count = fRelocationEntries->Count();
for (int32 i = 0; i < count; i++) {
addr *entry = fRelocationEntries->ElementAt(i);
if (*entry)
*entry += (addr)address - (addr)fBuffer;
}
return B_OK;
}
@@ -17,6 +17,9 @@ public:
UserDataWriter(user_disk_device_data *buffer, size_t bufferSize);
~UserDataWriter();
status_t SetTo(user_disk_device_data *buffer, size_t bufferSize);
void Unset();
void *AllocateData(size_t size, size_t align = 1);
user_partition_data *AllocatePartitionData(size_t childCount);
user_disk_device_data *AllocateDeviceData(size_t childCount);
@@ -25,10 +28,16 @@ public:
size_t AllocatedSize() const;
status_t AddRelocationEntry(void *address);
status_t Relocate(void *address);
private:
struct RelocationEntryList;
user_disk_device_data *fBuffer;
size_t fBufferSize;
size_t fAllocatedSize;
RelocationEntryList *fRelocationEntries;
};
} // namespace DiskDevice