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 using namespace std; 10 11 typedef uint8 *addr; 12 13 // RelocationEntryList 14 struct UserDataWriter::RelocationEntryList : Vector<addr*> {}; 15 16 // constructor 17 UserDataWriter::UserDataWriter() 18 : fBuffer(NULL), 19 fBufferSize(0), 20 fAllocatedSize(0), 21 fRelocationEntries(NULL) 22 { 23 } 24 25 // constructor 26 UserDataWriter::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 37 UserDataWriter::~UserDataWriter() 38 { 39 delete fRelocationEntries; 40 } 41 42 // SetTo 43 status_t 44 UserDataWriter::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 59 void 60 UserDataWriter::Unset() 61 { 62 delete fRelocationEntries; 63 fBuffer = NULL; 64 fBufferSize = 0; 65 fAllocatedSize = 0; 66 fRelocationEntries = NULL; 67 } 68 69 // AllocateData 70 void * 71 UserDataWriter::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 88 user_partition_data * 89 UserDataWriter::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 98 user_disk_device_data * 99 UserDataWriter::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 108 char * 109 UserDataWriter::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 121 size_t 122 UserDataWriter::AllocatedSize() const 123 { 124 return fAllocatedSize; 125 } 126 127 // AddRelocationEntry 128 status_t 129 UserDataWriter::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 139 status_t 140 UserDataWriter::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