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) { if (data) {
data->device_flags = DeviceFlags(); data->device_flags = DeviceFlags();
data->path = path; data->path = path;
writer.AddRelocationEntry(&data->path);
partition->WriteUserData(writer, &data->device_partition_data); partition->WriteUserData(writer, &data->device_partition_data);
} else } else
partition->WriteUserData(writer, NULL); partition->WriteUserData(writer, NULL);
@@ -938,13 +938,22 @@ KPartition::WriteUserData(UserDataWriter &writer, user_partition_data *data)
data->parameters = parameters; data->parameters = parameters;
data->content_parameters = contentParameters; data->content_parameters = contentParameters;
data->child_count = CountChildren(); 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 // children
for (int32 i = 0; KPartition *child = ChildAt(i); i++) { for (int32 i = 0; KPartition *child = ChildAt(i); i++) {
user_partition_data *childData user_partition_data *childData
= writer.AllocatePartitionData(child->CountChildren()); = writer.AllocatePartitionData(child->CountChildren());
if (data) if (data) {
data->children[i] = childData; data->children[i] = childData;
writer.AddRelocationEntry(&data->children[i]);
}
child->WriteUserData(writer, childData); child->WriteUserData(writer, childData);
} }
} }
@@ -1,43 +1,87 @@
// UserDataWriter.cpp // UserDataWriter.cpp
#include <new>
#include <ddm_userland_interface.h> #include <ddm_userland_interface.h>
#include <Vector.h>
#include "UserDataWriter.h" #include "UserDataWriter.h"
using namespace std;
typedef uint8 *addr;
// RelocationEntryList
struct UserDataWriter::RelocationEntryList : Vector<addr*> {};
// constructor // constructor
UserDataWriter::UserDataWriter() UserDataWriter::UserDataWriter()
: fBuffer(NULL), : fBuffer(NULL),
fBufferSize(0), fBufferSize(0),
fAllocatedSize(0) fAllocatedSize(0),
fRelocationEntries(NULL)
{ {
} }
// constructor // constructor
UserDataWriter::UserDataWriter(user_disk_device_data *buffer, UserDataWriter::UserDataWriter(user_disk_device_data *buffer,
size_t bufferSize) size_t bufferSize)
: fBuffer(buffer), : fBuffer(NULL),
fBufferSize(bufferSize), fBufferSize(0),
fAllocatedSize(0) fAllocatedSize(0),
fRelocationEntries(NULL)
{ {
SetTo(buffer, bufferSize);
} }
// destructor // destructor
UserDataWriter::~UserDataWriter() 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 // AllocateData
void * void *
UserDataWriter::AllocateData(size_t size, size_t align = 1) UserDataWriter::AllocateData(size_t size, size_t align = 1)
{ {
if (size == 0) // handles size == 0 gracefully
return NULL; // get a properly aligned offset
size_t offset = fAllocatedSize;
if (align > 1) if (align > 1)
fAllocatedSize = (fAllocatedSize + align - 1) / align * align; offset = (fAllocatedSize + align - 1) / align * align;
// get the result pointer
void *result = NULL; void *result = NULL;
if (fAllocatedSize + size <= fBufferSize) if (fBuffer && offset + size <= fBufferSize)
result = (uint8*)fBuffer + fAllocatedSize; result = (uint8*)fBuffer + offset;
fAllocatedSize += size; // always update the allocated size, even if there wasn't enough space
fAllocatedSize = offset + size;
return result; return result;
} }
@@ -81,3 +125,29 @@ UserDataWriter::AllocatedSize() const
return fAllocatedSize; 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(user_disk_device_data *buffer, size_t bufferSize);
~UserDataWriter(); ~UserDataWriter();
status_t SetTo(user_disk_device_data *buffer, size_t bufferSize);
void Unset();
void *AllocateData(size_t size, size_t align = 1); void *AllocateData(size_t size, size_t align = 1);
user_partition_data *AllocatePartitionData(size_t childCount); user_partition_data *AllocatePartitionData(size_t childCount);
user_disk_device_data *AllocateDeviceData(size_t childCount); user_disk_device_data *AllocateDeviceData(size_t childCount);
@@ -25,10 +28,16 @@ public:
size_t AllocatedSize() const; size_t AllocatedSize() const;
status_t AddRelocationEntry(void *address);
status_t Relocate(void *address);
private: private:
struct RelocationEntryList;
user_disk_device_data *fBuffer; user_disk_device_data *fBuffer;
size_t fBufferSize; size_t fBufferSize;
size_t fAllocatedSize; size_t fAllocatedSize;
RelocationEntryList *fRelocationEntries;
}; };
} // namespace DiskDevice } // namespace DiskDevice