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 10 struct UserDataWriter::RelocationEntryList : Vector<addr_t*> {}; 11 12 13 UserDataWriter::UserDataWriter() 14 : fBuffer(NULL), 15 fBufferSize(0), 16 fAllocatedSize(0), 17 fRelocationEntries(NULL) 18 { 19 } 20 21 22 UserDataWriter::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 33 UserDataWriter::~UserDataWriter() 34 { 35 delete fRelocationEntries; 36 } 37 38 39 status_t 40 UserDataWriter::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(std::nothrow) RelocationEntryList; 48 if (!fRelocationEntries) 49 return B_NO_MEMORY; 50 } 51 return B_OK; 52 } 53 54 55 void 56 UserDataWriter::Unset() 57 { 58 delete fRelocationEntries; 59 fBuffer = NULL; 60 fBufferSize = 0; 61 fAllocatedSize = 0; 62 fRelocationEntries = NULL; 63 } 64 65 66 void * 67 UserDataWriter::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 84 user_partition_data * 85 UserDataWriter::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 94 user_disk_device_data * 95 UserDataWriter::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 104 char * 105 UserDataWriter::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 117 size_t 118 UserDataWriter::AllocatedSize() const 119 { 120 return fAllocatedSize; 121 } 122 123 124 status_t 125 UserDataWriter::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 135 status_t 136 UserDataWriter::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