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