xref: /haiku/src/system/kernel/disk_device_manager/UserDataWriter.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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