1// UserDataWriter.cpp 2 3#include <util/kernel_cpp.h> 4#include <ddm_userland_interface.h> 5#include <Vector.h> 6 7#include "UserDataWriter.h" 8 9// RelocationEntryList 10struct UserDataWriter::RelocationEntryList : Vector<addr_t*> {}; 11 12// constructor 13UserDataWriter::UserDataWriter() 14 : fBuffer(NULL), 15 fBufferSize(0), 16 fAllocatedSize(0), 17 fRelocationEntries(NULL) 18{ 19} 20 21// constructor 22UserDataWriter::UserDataWriter(user_disk_device_data *buffer, 23 size_t bufferSize) 24 : fBuffer(NULL), 25 fBufferSize(0), 26 fAllocatedSize(0), 27 fRelocationEntries(NULL) 28{ 29 SetTo(buffer, bufferSize); 30} 31 32// destructor 33UserDataWriter::~UserDataWriter() 34{ 35 delete fRelocationEntries; 36} 37 38// SetTo 39status_t 40UserDataWriter::SetTo(user_disk_device_data *buffer, size_t bufferSize) 41{ 42 Unset(); 43 fBuffer = buffer; 44 fBufferSize = bufferSize; 45 fAllocatedSize = 0; 46 if (fBuffer && fBufferSize > 0) { 47 fRelocationEntries = new(nothrow) RelocationEntryList; 48 if (!fRelocationEntries) 49 return B_NO_MEMORY; 50 } 51 return B_OK; 52} 53 54// Unset 55void 56UserDataWriter::Unset() 57{ 58 delete fRelocationEntries; 59 fBuffer = NULL; 60 fBufferSize = 0; 61 fAllocatedSize = 0; 62 fRelocationEntries = NULL; 63} 64 65// AllocateData 66void * 67UserDataWriter::AllocateData(size_t size, size_t align) 68{ 69 // handles size == 0 gracefully 70 // get a properly aligned offset 71 size_t offset = fAllocatedSize; 72 if (align > 1) 73 offset = (fAllocatedSize + align - 1) / align * align; 74 // get the result pointer 75 void *result = NULL; 76 if (fBuffer && offset + size <= fBufferSize) 77 result = (uint8*)fBuffer + offset; 78 // always update the allocated size, even if there wasn't enough space 79 fAllocatedSize = offset + size; 80 return result; 81} 82 83// AllocatePartitionData 84user_partition_data * 85UserDataWriter::AllocatePartitionData(size_t childCount) 86{ 87 return (user_partition_data*)AllocateData( 88 sizeof(user_partition_data) 89 + sizeof(user_partition_data*) * ((int32)childCount - 1), 90 sizeof(int)); 91} 92 93// AllocateDeviceData 94user_disk_device_data * 95UserDataWriter::AllocateDeviceData(size_t childCount) 96{ 97 return (user_disk_device_data*)AllocateData( 98 sizeof(user_disk_device_data) 99 + sizeof(user_partition_data*) * ((int32)childCount - 1), 100 sizeof(int)); 101} 102 103// PlaceString 104char * 105UserDataWriter::PlaceString(const char *str) 106{ 107 if (!str) 108 return NULL; 109 size_t len = strlen(str) + 1; 110 char *data = (char*)AllocateData(len); 111 if (data) 112 memcpy(data, str, len); 113 return data; 114} 115 116// AllocatedSize 117size_t 118UserDataWriter::AllocatedSize() const 119{ 120 return fAllocatedSize; 121} 122 123// AddRelocationEntry 124status_t 125UserDataWriter::AddRelocationEntry(void *address) 126{ 127 if (fRelocationEntries && (addr_t)address >= (addr_t)fBuffer 128 && (addr_t)address < (addr_t)fBuffer + fBufferSize - sizeof(void*)) { 129 return fRelocationEntries->PushBack((addr_t*)address); 130 } 131 return B_ERROR; 132} 133 134// Relocate 135status_t 136UserDataWriter::Relocate(void *address) 137{ 138 if (!fRelocationEntries || !fBuffer) 139 return B_BAD_VALUE; 140 int32 count = fRelocationEntries->Count(); 141 for (int32 i = 0; i < count; i++) { 142 addr_t *entry = fRelocationEntries->ElementAt(i); 143 if (*entry) 144 *entry += (addr_t)address - (addr_t)fBuffer; 145 } 146 return B_OK; 147} 148 149