1*fdd8201dSApple OSS Distributions /*
2*fdd8201dSApple OSS Distributions * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3*fdd8201dSApple OSS Distributions *
4*fdd8201dSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*fdd8201dSApple OSS Distributions *
6*fdd8201dSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*fdd8201dSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*fdd8201dSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*fdd8201dSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*fdd8201dSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*fdd8201dSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*fdd8201dSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*fdd8201dSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*fdd8201dSApple OSS Distributions *
15*fdd8201dSApple OSS Distributions * Please obtain a copy of the License at
16*fdd8201dSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*fdd8201dSApple OSS Distributions *
18*fdd8201dSApple OSS Distributions * The Original Code and all software distributed under the License are
19*fdd8201dSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*fdd8201dSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*fdd8201dSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*fdd8201dSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*fdd8201dSApple OSS Distributions * Please see the License for the specific language governing rights and
24*fdd8201dSApple OSS Distributions * limitations under the License.
25*fdd8201dSApple OSS Distributions *
26*fdd8201dSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*fdd8201dSApple OSS Distributions */
28*fdd8201dSApple OSS Distributions /* IOData.m created by rsulack on Thu 25-Sep-1997 */
29*fdd8201dSApple OSS Distributions
30*fdd8201dSApple OSS Distributions #include <string.h>
31*fdd8201dSApple OSS Distributions
32*fdd8201dSApple OSS Distributions #include <vm/vm_kern.h>
33*fdd8201dSApple OSS Distributions
34*fdd8201dSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
35*fdd8201dSApple OSS Distributions
36*fdd8201dSApple OSS Distributions #include <libkern/c++/OSData.h>
37*fdd8201dSApple OSS Distributions #include <libkern/c++/OSSerialize.h>
38*fdd8201dSApple OSS Distributions #include <libkern/c++/OSLib.h>
39*fdd8201dSApple OSS Distributions #include <libkern/c++/OSString.h>
40*fdd8201dSApple OSS Distributions #include <IOKit/IOLib.h>
41*fdd8201dSApple OSS Distributions
42*fdd8201dSApple OSS Distributions #define super OSObject
43*fdd8201dSApple OSS Distributions
44*fdd8201dSApple OSS Distributions OSDefineMetaClassAndStructorsWithZone(OSData, OSObject, ZC_ZFREE_CLEARMEM)
45*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUsedX86(OSData, 0); // setDeallocFunction
46*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 1);
47*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 2);
48*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 3);
49*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 4);
50*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 5);
51*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 6);
52*fdd8201dSApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 7);
53*fdd8201dSApple OSS Distributions
54*fdd8201dSApple OSS Distributions #define EXTERNAL ((unsigned int) -1)
55*fdd8201dSApple OSS Distributions
56*fdd8201dSApple OSS Distributions bool
initWithCapacity(unsigned int inCapacity)57*fdd8201dSApple OSS Distributions OSData::initWithCapacity(unsigned int inCapacity)
58*fdd8201dSApple OSS Distributions {
59*fdd8201dSApple OSS Distributions void *_data = NULL;
60*fdd8201dSApple OSS Distributions
61*fdd8201dSApple OSS Distributions if (data) {
62*fdd8201dSApple OSS Distributions OSCONTAINER_ACCUMSIZE(-((size_t)capacity));
63*fdd8201dSApple OSS Distributions if (!inCapacity || (capacity < inCapacity)) {
64*fdd8201dSApple OSS Distributions // clean out old data's storage if it isn't big enough
65*fdd8201dSApple OSS Distributions if (capacity < page_size) {
66*fdd8201dSApple OSS Distributions kfree_data_container(data, capacity);
67*fdd8201dSApple OSS Distributions } else {
68*fdd8201dSApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity);
69*fdd8201dSApple OSS Distributions }
70*fdd8201dSApple OSS Distributions data = NULL;
71*fdd8201dSApple OSS Distributions capacity = 0;
72*fdd8201dSApple OSS Distributions }
73*fdd8201dSApple OSS Distributions }
74*fdd8201dSApple OSS Distributions
75*fdd8201dSApple OSS Distributions if (!super::init()) {
76*fdd8201dSApple OSS Distributions return false;
77*fdd8201dSApple OSS Distributions }
78*fdd8201dSApple OSS Distributions
79*fdd8201dSApple OSS Distributions if (inCapacity && !data) {
80*fdd8201dSApple OSS Distributions if (inCapacity < page_size) {
81*fdd8201dSApple OSS Distributions data = (void *)kalloc_data_container(inCapacity, Z_WAITOK);
82*fdd8201dSApple OSS Distributions } else {
83*fdd8201dSApple OSS Distributions kern_return_t kr;
84*fdd8201dSApple OSS Distributions if (round_page_overflow(inCapacity, &inCapacity)) {
85*fdd8201dSApple OSS Distributions kr = KERN_RESOURCE_SHORTAGE;
86*fdd8201dSApple OSS Distributions } else {
87*fdd8201dSApple OSS Distributions kr = kernel_memory_allocate(kernel_map,
88*fdd8201dSApple OSS Distributions (vm_offset_t *)&_data, inCapacity,
89*fdd8201dSApple OSS Distributions 0, (kma_flags_t) (KMA_ATOMIC | KMA_DATA),
90*fdd8201dSApple OSS Distributions IOMemoryTag(kernel_map));
91*fdd8201dSApple OSS Distributions data = _data;
92*fdd8201dSApple OSS Distributions }
93*fdd8201dSApple OSS Distributions if (KERN_SUCCESS != kr) {
94*fdd8201dSApple OSS Distributions data = NULL;
95*fdd8201dSApple OSS Distributions }
96*fdd8201dSApple OSS Distributions }
97*fdd8201dSApple OSS Distributions if (!data) {
98*fdd8201dSApple OSS Distributions return false;
99*fdd8201dSApple OSS Distributions }
100*fdd8201dSApple OSS Distributions capacity = inCapacity;
101*fdd8201dSApple OSS Distributions }
102*fdd8201dSApple OSS Distributions OSCONTAINER_ACCUMSIZE(capacity);
103*fdd8201dSApple OSS Distributions
104*fdd8201dSApple OSS Distributions length = 0;
105*fdd8201dSApple OSS Distributions if (inCapacity < 16) {
106*fdd8201dSApple OSS Distributions capacityIncrement = 16;
107*fdd8201dSApple OSS Distributions } else {
108*fdd8201dSApple OSS Distributions capacityIncrement = inCapacity;
109*fdd8201dSApple OSS Distributions }
110*fdd8201dSApple OSS Distributions
111*fdd8201dSApple OSS Distributions return true;
112*fdd8201dSApple OSS Distributions }
113*fdd8201dSApple OSS Distributions
114*fdd8201dSApple OSS Distributions bool
initWithBytes(const void * bytes,unsigned int inLength)115*fdd8201dSApple OSS Distributions OSData::initWithBytes(const void *bytes, unsigned int inLength)
116*fdd8201dSApple OSS Distributions {
117*fdd8201dSApple OSS Distributions if ((inLength && !bytes) || !initWithCapacity(inLength)) {
118*fdd8201dSApple OSS Distributions return false;
119*fdd8201dSApple OSS Distributions }
120*fdd8201dSApple OSS Distributions
121*fdd8201dSApple OSS Distributions if (bytes != data) {
122*fdd8201dSApple OSS Distributions bcopy(bytes, data, inLength);
123*fdd8201dSApple OSS Distributions }
124*fdd8201dSApple OSS Distributions length = inLength;
125*fdd8201dSApple OSS Distributions
126*fdd8201dSApple OSS Distributions return true;
127*fdd8201dSApple OSS Distributions }
128*fdd8201dSApple OSS Distributions
129*fdd8201dSApple OSS Distributions bool
initWithBytesNoCopy(void * bytes,unsigned int inLength)130*fdd8201dSApple OSS Distributions OSData::initWithBytesNoCopy(void *bytes, unsigned int inLength)
131*fdd8201dSApple OSS Distributions {
132*fdd8201dSApple OSS Distributions if (!super::init()) {
133*fdd8201dSApple OSS Distributions return false;
134*fdd8201dSApple OSS Distributions }
135*fdd8201dSApple OSS Distributions
136*fdd8201dSApple OSS Distributions length = inLength;
137*fdd8201dSApple OSS Distributions capacity = EXTERNAL;
138*fdd8201dSApple OSS Distributions data = bytes;
139*fdd8201dSApple OSS Distributions
140*fdd8201dSApple OSS Distributions return true;
141*fdd8201dSApple OSS Distributions }
142*fdd8201dSApple OSS Distributions
143*fdd8201dSApple OSS Distributions bool
initWithData(const OSData * inData)144*fdd8201dSApple OSS Distributions OSData::initWithData(const OSData *inData)
145*fdd8201dSApple OSS Distributions {
146*fdd8201dSApple OSS Distributions return initWithBytes(inData->data, inData->length);
147*fdd8201dSApple OSS Distributions }
148*fdd8201dSApple OSS Distributions
149*fdd8201dSApple OSS Distributions bool
initWithData(const OSData * inData,unsigned int start,unsigned int inLength)150*fdd8201dSApple OSS Distributions OSData::initWithData(const OSData *inData,
151*fdd8201dSApple OSS Distributions unsigned int start, unsigned int inLength)
152*fdd8201dSApple OSS Distributions {
153*fdd8201dSApple OSS Distributions const void *localData = inData->getBytesNoCopy(start, inLength);
154*fdd8201dSApple OSS Distributions
155*fdd8201dSApple OSS Distributions if (localData) {
156*fdd8201dSApple OSS Distributions return initWithBytes(localData, inLength);
157*fdd8201dSApple OSS Distributions } else {
158*fdd8201dSApple OSS Distributions return false;
159*fdd8201dSApple OSS Distributions }
160*fdd8201dSApple OSS Distributions }
161*fdd8201dSApple OSS Distributions
162*fdd8201dSApple OSS Distributions OSSharedPtr<OSData>
withCapacity(unsigned int inCapacity)163*fdd8201dSApple OSS Distributions OSData::withCapacity(unsigned int inCapacity)
164*fdd8201dSApple OSS Distributions {
165*fdd8201dSApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
166*fdd8201dSApple OSS Distributions
167*fdd8201dSApple OSS Distributions if (me && !me->initWithCapacity(inCapacity)) {
168*fdd8201dSApple OSS Distributions return nullptr;
169*fdd8201dSApple OSS Distributions }
170*fdd8201dSApple OSS Distributions
171*fdd8201dSApple OSS Distributions return me;
172*fdd8201dSApple OSS Distributions }
173*fdd8201dSApple OSS Distributions
174*fdd8201dSApple OSS Distributions OSSharedPtr<OSData>
withBytes(const void * bytes,unsigned int inLength)175*fdd8201dSApple OSS Distributions OSData::withBytes(const void *bytes, unsigned int inLength)
176*fdd8201dSApple OSS Distributions {
177*fdd8201dSApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
178*fdd8201dSApple OSS Distributions
179*fdd8201dSApple OSS Distributions if (me && !me->initWithBytes(bytes, inLength)) {
180*fdd8201dSApple OSS Distributions return nullptr;
181*fdd8201dSApple OSS Distributions }
182*fdd8201dSApple OSS Distributions return me;
183*fdd8201dSApple OSS Distributions }
184*fdd8201dSApple OSS Distributions
185*fdd8201dSApple OSS Distributions OSSharedPtr<OSData>
withBytesNoCopy(void * bytes,unsigned int inLength)186*fdd8201dSApple OSS Distributions OSData::withBytesNoCopy(void *bytes, unsigned int inLength)
187*fdd8201dSApple OSS Distributions {
188*fdd8201dSApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
189*fdd8201dSApple OSS Distributions
190*fdd8201dSApple OSS Distributions if (me && !me->initWithBytesNoCopy(bytes, inLength)) {
191*fdd8201dSApple OSS Distributions return nullptr;
192*fdd8201dSApple OSS Distributions }
193*fdd8201dSApple OSS Distributions
194*fdd8201dSApple OSS Distributions return me;
195*fdd8201dSApple OSS Distributions }
196*fdd8201dSApple OSS Distributions
197*fdd8201dSApple OSS Distributions OSSharedPtr<OSData>
withData(const OSData * inData)198*fdd8201dSApple OSS Distributions OSData::withData(const OSData *inData)
199*fdd8201dSApple OSS Distributions {
200*fdd8201dSApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
201*fdd8201dSApple OSS Distributions
202*fdd8201dSApple OSS Distributions if (me && !me->initWithData(inData)) {
203*fdd8201dSApple OSS Distributions return nullptr;
204*fdd8201dSApple OSS Distributions }
205*fdd8201dSApple OSS Distributions
206*fdd8201dSApple OSS Distributions return me;
207*fdd8201dSApple OSS Distributions }
208*fdd8201dSApple OSS Distributions
209*fdd8201dSApple OSS Distributions OSSharedPtr<OSData>
withData(const OSData * inData,unsigned int start,unsigned int inLength)210*fdd8201dSApple OSS Distributions OSData::withData(const OSData *inData,
211*fdd8201dSApple OSS Distributions unsigned int start, unsigned int inLength)
212*fdd8201dSApple OSS Distributions {
213*fdd8201dSApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
214*fdd8201dSApple OSS Distributions
215*fdd8201dSApple OSS Distributions if (me && !me->initWithData(inData, start, inLength)) {
216*fdd8201dSApple OSS Distributions return nullptr;
217*fdd8201dSApple OSS Distributions }
218*fdd8201dSApple OSS Distributions
219*fdd8201dSApple OSS Distributions return me;
220*fdd8201dSApple OSS Distributions }
221*fdd8201dSApple OSS Distributions
222*fdd8201dSApple OSS Distributions void
free()223*fdd8201dSApple OSS Distributions OSData::free()
224*fdd8201dSApple OSS Distributions {
225*fdd8201dSApple OSS Distributions if ((capacity != EXTERNAL) && data && capacity) {
226*fdd8201dSApple OSS Distributions if (capacity < page_size) {
227*fdd8201dSApple OSS Distributions kfree_data_container(data, capacity);
228*fdd8201dSApple OSS Distributions } else {
229*fdd8201dSApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity);
230*fdd8201dSApple OSS Distributions }
231*fdd8201dSApple OSS Distributions OSCONTAINER_ACCUMSIZE( -((size_t)capacity));
232*fdd8201dSApple OSS Distributions } else if (capacity == EXTERNAL) {
233*fdd8201dSApple OSS Distributions DeallocFunction freemem = reserved ? reserved->deallocFunction : NULL;
234*fdd8201dSApple OSS Distributions if (freemem && data && length) {
235*fdd8201dSApple OSS Distributions freemem(data, length);
236*fdd8201dSApple OSS Distributions }
237*fdd8201dSApple OSS Distributions }
238*fdd8201dSApple OSS Distributions if (reserved) {
239*fdd8201dSApple OSS Distributions kfree_type(ExpansionData, reserved);
240*fdd8201dSApple OSS Distributions }
241*fdd8201dSApple OSS Distributions super::free();
242*fdd8201dSApple OSS Distributions }
243*fdd8201dSApple OSS Distributions
244*fdd8201dSApple OSS Distributions unsigned int
getLength() const245*fdd8201dSApple OSS Distributions OSData::getLength() const
246*fdd8201dSApple OSS Distributions {
247*fdd8201dSApple OSS Distributions return length;
248*fdd8201dSApple OSS Distributions }
249*fdd8201dSApple OSS Distributions unsigned int
getCapacity() const250*fdd8201dSApple OSS Distributions OSData::getCapacity() const
251*fdd8201dSApple OSS Distributions {
252*fdd8201dSApple OSS Distributions return capacity;
253*fdd8201dSApple OSS Distributions }
254*fdd8201dSApple OSS Distributions
255*fdd8201dSApple OSS Distributions unsigned int
getCapacityIncrement() const256*fdd8201dSApple OSS Distributions OSData::getCapacityIncrement() const
257*fdd8201dSApple OSS Distributions {
258*fdd8201dSApple OSS Distributions return capacityIncrement;
259*fdd8201dSApple OSS Distributions }
260*fdd8201dSApple OSS Distributions
261*fdd8201dSApple OSS Distributions unsigned int
setCapacityIncrement(unsigned increment)262*fdd8201dSApple OSS Distributions OSData::setCapacityIncrement(unsigned increment)
263*fdd8201dSApple OSS Distributions {
264*fdd8201dSApple OSS Distributions return capacityIncrement = increment;
265*fdd8201dSApple OSS Distributions }
266*fdd8201dSApple OSS Distributions
267*fdd8201dSApple OSS Distributions // xx-review: does not check for capacity == EXTERNAL
268*fdd8201dSApple OSS Distributions
269*fdd8201dSApple OSS Distributions unsigned int
ensureCapacity(unsigned int newCapacity)270*fdd8201dSApple OSS Distributions OSData::ensureCapacity(unsigned int newCapacity)
271*fdd8201dSApple OSS Distributions {
272*fdd8201dSApple OSS Distributions unsigned char * newData;
273*fdd8201dSApple OSS Distributions unsigned int finalCapacity;
274*fdd8201dSApple OSS Distributions void * copydata;
275*fdd8201dSApple OSS Distributions kern_return_t kr;
276*fdd8201dSApple OSS Distributions
277*fdd8201dSApple OSS Distributions if (newCapacity <= capacity) {
278*fdd8201dSApple OSS Distributions return capacity;
279*fdd8201dSApple OSS Distributions }
280*fdd8201dSApple OSS Distributions
281*fdd8201dSApple OSS Distributions finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
282*fdd8201dSApple OSS Distributions * capacityIncrement;
283*fdd8201dSApple OSS Distributions
284*fdd8201dSApple OSS Distributions // integer overflow check
285*fdd8201dSApple OSS Distributions if (finalCapacity < newCapacity) {
286*fdd8201dSApple OSS Distributions return capacity;
287*fdd8201dSApple OSS Distributions }
288*fdd8201dSApple OSS Distributions
289*fdd8201dSApple OSS Distributions copydata = data;
290*fdd8201dSApple OSS Distributions
291*fdd8201dSApple OSS Distributions if (finalCapacity >= page_size) {
292*fdd8201dSApple OSS Distributions // round up
293*fdd8201dSApple OSS Distributions finalCapacity = round_page_32(finalCapacity);
294*fdd8201dSApple OSS Distributions // integer overflow check
295*fdd8201dSApple OSS Distributions if (finalCapacity < newCapacity) {
296*fdd8201dSApple OSS Distributions return capacity;
297*fdd8201dSApple OSS Distributions }
298*fdd8201dSApple OSS Distributions if (capacity >= page_size) {
299*fdd8201dSApple OSS Distributions copydata = NULL;
300*fdd8201dSApple OSS Distributions kr = kmem_realloc(kernel_map,
301*fdd8201dSApple OSS Distributions (vm_offset_t)data,
302*fdd8201dSApple OSS Distributions capacity,
303*fdd8201dSApple OSS Distributions (vm_offset_t *)&newData,
304*fdd8201dSApple OSS Distributions finalCapacity,
305*fdd8201dSApple OSS Distributions IOMemoryTag(kernel_map));
306*fdd8201dSApple OSS Distributions } else {
307*fdd8201dSApple OSS Distributions kr = kernel_memory_allocate(kernel_map, (vm_offset_t *)&newData,
308*fdd8201dSApple OSS Distributions finalCapacity, 0, (kma_flags_t) (KMA_ATOMIC | KMA_DATA),
309*fdd8201dSApple OSS Distributions IOMemoryTag(kernel_map));
310*fdd8201dSApple OSS Distributions }
311*fdd8201dSApple OSS Distributions if (KERN_SUCCESS != kr) {
312*fdd8201dSApple OSS Distributions newData = NULL;
313*fdd8201dSApple OSS Distributions }
314*fdd8201dSApple OSS Distributions } else {
315*fdd8201dSApple OSS Distributions newData = (unsigned char *)kalloc_data_container(finalCapacity, Z_WAITOK);
316*fdd8201dSApple OSS Distributions }
317*fdd8201dSApple OSS Distributions
318*fdd8201dSApple OSS Distributions if (newData) {
319*fdd8201dSApple OSS Distributions bzero(newData + capacity, finalCapacity - capacity);
320*fdd8201dSApple OSS Distributions if (copydata) {
321*fdd8201dSApple OSS Distributions bcopy(copydata, newData, capacity);
322*fdd8201dSApple OSS Distributions }
323*fdd8201dSApple OSS Distributions if (data) {
324*fdd8201dSApple OSS Distributions if (capacity < page_size) {
325*fdd8201dSApple OSS Distributions kfree_data_container(data, capacity);
326*fdd8201dSApple OSS Distributions } else {
327*fdd8201dSApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity);
328*fdd8201dSApple OSS Distributions }
329*fdd8201dSApple OSS Distributions }
330*fdd8201dSApple OSS Distributions OSCONTAINER_ACCUMSIZE(((size_t)finalCapacity) - ((size_t)capacity));
331*fdd8201dSApple OSS Distributions data = (void *) newData;
332*fdd8201dSApple OSS Distributions capacity = finalCapacity;
333*fdd8201dSApple OSS Distributions }
334*fdd8201dSApple OSS Distributions
335*fdd8201dSApple OSS Distributions return capacity;
336*fdd8201dSApple OSS Distributions }
337*fdd8201dSApple OSS Distributions
338*fdd8201dSApple OSS Distributions bool
clipForCopyout()339*fdd8201dSApple OSS Distributions OSData::clipForCopyout()
340*fdd8201dSApple OSS Distributions {
341*fdd8201dSApple OSS Distributions unsigned int newCapacity = (uint32_t)round_page(length);
342*fdd8201dSApple OSS Distributions
343*fdd8201dSApple OSS Distributions /*
344*fdd8201dSApple OSS Distributions * OSData allocations are atomic, which means that if copyoutkdata()
345*fdd8201dSApple OSS Distributions * is used on them, and that there are fully unused pages at the end
346*fdd8201dSApple OSS Distributions * of the OSData buffer, then vm_map_copyin() will try to clip the VM
347*fdd8201dSApple OSS Distributions * entry which will panic.
348*fdd8201dSApple OSS Distributions *
349*fdd8201dSApple OSS Distributions * In order to avoid this, trim down the unused pages.
350*fdd8201dSApple OSS Distributions */
351*fdd8201dSApple OSS Distributions if (length >= msg_ool_size_small && newCapacity < capacity) {
352*fdd8201dSApple OSS Distributions kmem_realloc_down(kernel_map, (vm_offset_t)data,
353*fdd8201dSApple OSS Distributions capacity, newCapacity);
354*fdd8201dSApple OSS Distributions OSCONTAINER_ACCUMSIZE(((size_t)newCapacity) - ((size_t)capacity));
355*fdd8201dSApple OSS Distributions capacity = newCapacity;
356*fdd8201dSApple OSS Distributions }
357*fdd8201dSApple OSS Distributions return true;
358*fdd8201dSApple OSS Distributions }
359*fdd8201dSApple OSS Distributions
360*fdd8201dSApple OSS Distributions bool
appendBytes(const void * bytes,unsigned int inLength)361*fdd8201dSApple OSS Distributions OSData::appendBytes(const void *bytes, unsigned int inLength)
362*fdd8201dSApple OSS Distributions {
363*fdd8201dSApple OSS Distributions unsigned int newSize;
364*fdd8201dSApple OSS Distributions
365*fdd8201dSApple OSS Distributions if (!inLength) {
366*fdd8201dSApple OSS Distributions return true;
367*fdd8201dSApple OSS Distributions }
368*fdd8201dSApple OSS Distributions
369*fdd8201dSApple OSS Distributions if (capacity == EXTERNAL) {
370*fdd8201dSApple OSS Distributions return false;
371*fdd8201dSApple OSS Distributions }
372*fdd8201dSApple OSS Distributions
373*fdd8201dSApple OSS Distributions if (os_add_overflow(length, inLength, &newSize)) {
374*fdd8201dSApple OSS Distributions return false;
375*fdd8201dSApple OSS Distributions }
376*fdd8201dSApple OSS Distributions
377*fdd8201dSApple OSS Distributions if ((newSize > capacity) && newSize > ensureCapacity(newSize)) {
378*fdd8201dSApple OSS Distributions return false;
379*fdd8201dSApple OSS Distributions }
380*fdd8201dSApple OSS Distributions
381*fdd8201dSApple OSS Distributions if (bytes) {
382*fdd8201dSApple OSS Distributions bcopy(bytes, &((unsigned char *)data)[length], inLength);
383*fdd8201dSApple OSS Distributions } else {
384*fdd8201dSApple OSS Distributions bzero(&((unsigned char *)data)[length], inLength);
385*fdd8201dSApple OSS Distributions }
386*fdd8201dSApple OSS Distributions
387*fdd8201dSApple OSS Distributions length = newSize;
388*fdd8201dSApple OSS Distributions
389*fdd8201dSApple OSS Distributions return true;
390*fdd8201dSApple OSS Distributions }
391*fdd8201dSApple OSS Distributions
392*fdd8201dSApple OSS Distributions bool
appendByte(unsigned char byte,unsigned int inLength)393*fdd8201dSApple OSS Distributions OSData::appendByte(unsigned char byte, unsigned int inLength)
394*fdd8201dSApple OSS Distributions {
395*fdd8201dSApple OSS Distributions unsigned int newSize;
396*fdd8201dSApple OSS Distributions
397*fdd8201dSApple OSS Distributions if (!inLength) {
398*fdd8201dSApple OSS Distributions return true;
399*fdd8201dSApple OSS Distributions }
400*fdd8201dSApple OSS Distributions
401*fdd8201dSApple OSS Distributions if (capacity == EXTERNAL) {
402*fdd8201dSApple OSS Distributions return false;
403*fdd8201dSApple OSS Distributions }
404*fdd8201dSApple OSS Distributions
405*fdd8201dSApple OSS Distributions if (os_add_overflow(length, inLength, &newSize)) {
406*fdd8201dSApple OSS Distributions return false;
407*fdd8201dSApple OSS Distributions }
408*fdd8201dSApple OSS Distributions
409*fdd8201dSApple OSS Distributions if ((newSize > capacity) && newSize > ensureCapacity(newSize)) {
410*fdd8201dSApple OSS Distributions return false;
411*fdd8201dSApple OSS Distributions }
412*fdd8201dSApple OSS Distributions
413*fdd8201dSApple OSS Distributions memset(&((unsigned char *)data)[length], byte, inLength);
414*fdd8201dSApple OSS Distributions length = newSize;
415*fdd8201dSApple OSS Distributions
416*fdd8201dSApple OSS Distributions return true;
417*fdd8201dSApple OSS Distributions }
418*fdd8201dSApple OSS Distributions
419*fdd8201dSApple OSS Distributions bool
appendBytes(const OSData * other)420*fdd8201dSApple OSS Distributions OSData::appendBytes(const OSData *other)
421*fdd8201dSApple OSS Distributions {
422*fdd8201dSApple OSS Distributions return appendBytes(other->data, other->length);
423*fdd8201dSApple OSS Distributions }
424*fdd8201dSApple OSS Distributions
425*fdd8201dSApple OSS Distributions const void *
getBytesNoCopy() const426*fdd8201dSApple OSS Distributions OSData::getBytesNoCopy() const
427*fdd8201dSApple OSS Distributions {
428*fdd8201dSApple OSS Distributions if (!length) {
429*fdd8201dSApple OSS Distributions return NULL;
430*fdd8201dSApple OSS Distributions } else {
431*fdd8201dSApple OSS Distributions return data;
432*fdd8201dSApple OSS Distributions }
433*fdd8201dSApple OSS Distributions }
434*fdd8201dSApple OSS Distributions
435*fdd8201dSApple OSS Distributions const void *
getBytesNoCopy(unsigned int start,unsigned int inLength) const436*fdd8201dSApple OSS Distributions OSData::getBytesNoCopy(unsigned int start,
437*fdd8201dSApple OSS Distributions unsigned int inLength) const
438*fdd8201dSApple OSS Distributions {
439*fdd8201dSApple OSS Distributions const void *outData = NULL;
440*fdd8201dSApple OSS Distributions
441*fdd8201dSApple OSS Distributions if (length
442*fdd8201dSApple OSS Distributions && start < length
443*fdd8201dSApple OSS Distributions && (start + inLength) >= inLength // overflow check
444*fdd8201dSApple OSS Distributions && (start + inLength) <= length) {
445*fdd8201dSApple OSS Distributions outData = (const void *) ((char *) data + start);
446*fdd8201dSApple OSS Distributions }
447*fdd8201dSApple OSS Distributions
448*fdd8201dSApple OSS Distributions return outData;
449*fdd8201dSApple OSS Distributions }
450*fdd8201dSApple OSS Distributions
451*fdd8201dSApple OSS Distributions bool
isEqualTo(const OSData * aData) const452*fdd8201dSApple OSS Distributions OSData::isEqualTo(const OSData *aData) const
453*fdd8201dSApple OSS Distributions {
454*fdd8201dSApple OSS Distributions unsigned int len;
455*fdd8201dSApple OSS Distributions
456*fdd8201dSApple OSS Distributions len = aData->length;
457*fdd8201dSApple OSS Distributions if (length != len) {
458*fdd8201dSApple OSS Distributions return false;
459*fdd8201dSApple OSS Distributions }
460*fdd8201dSApple OSS Distributions
461*fdd8201dSApple OSS Distributions return isEqualTo(aData->data, len);
462*fdd8201dSApple OSS Distributions }
463*fdd8201dSApple OSS Distributions
464*fdd8201dSApple OSS Distributions bool
isEqualTo(const void * someData,unsigned int inLength) const465*fdd8201dSApple OSS Distributions OSData::isEqualTo(const void *someData, unsigned int inLength) const
466*fdd8201dSApple OSS Distributions {
467*fdd8201dSApple OSS Distributions return (length >= inLength) && (bcmp(data, someData, inLength) == 0);
468*fdd8201dSApple OSS Distributions }
469*fdd8201dSApple OSS Distributions
470*fdd8201dSApple OSS Distributions bool
isEqualTo(const OSMetaClassBase * obj) const471*fdd8201dSApple OSS Distributions OSData::isEqualTo(const OSMetaClassBase *obj) const
472*fdd8201dSApple OSS Distributions {
473*fdd8201dSApple OSS Distributions OSData * otherData;
474*fdd8201dSApple OSS Distributions OSString * str;
475*fdd8201dSApple OSS Distributions
476*fdd8201dSApple OSS Distributions if ((otherData = OSDynamicCast(OSData, obj))) {
477*fdd8201dSApple OSS Distributions return isEqualTo(otherData);
478*fdd8201dSApple OSS Distributions } else if ((str = OSDynamicCast(OSString, obj))) {
479*fdd8201dSApple OSS Distributions return isEqualTo(str);
480*fdd8201dSApple OSS Distributions } else {
481*fdd8201dSApple OSS Distributions return false;
482*fdd8201dSApple OSS Distributions }
483*fdd8201dSApple OSS Distributions }
484*fdd8201dSApple OSS Distributions
485*fdd8201dSApple OSS Distributions bool
isEqualTo(const OSString * obj) const486*fdd8201dSApple OSS Distributions OSData::isEqualTo(const OSString *obj) const
487*fdd8201dSApple OSS Distributions {
488*fdd8201dSApple OSS Distributions const char * aCString;
489*fdd8201dSApple OSS Distributions char * dataPtr;
490*fdd8201dSApple OSS Distributions unsigned int checkLen = length;
491*fdd8201dSApple OSS Distributions unsigned int stringLen;
492*fdd8201dSApple OSS Distributions
493*fdd8201dSApple OSS Distributions if (!obj) {
494*fdd8201dSApple OSS Distributions return false;
495*fdd8201dSApple OSS Distributions }
496*fdd8201dSApple OSS Distributions
497*fdd8201dSApple OSS Distributions stringLen = obj->getLength();
498*fdd8201dSApple OSS Distributions
499*fdd8201dSApple OSS Distributions dataPtr = (char *)data;
500*fdd8201dSApple OSS Distributions
501*fdd8201dSApple OSS Distributions if (stringLen != checkLen) {
502*fdd8201dSApple OSS Distributions // check for the fact that OSData may be a buffer that
503*fdd8201dSApple OSS Distributions // that includes a termination byte and will thus have
504*fdd8201dSApple OSS Distributions // a length of the actual string length PLUS 1. In this
505*fdd8201dSApple OSS Distributions // case we verify that the additional byte is a terminator
506*fdd8201dSApple OSS Distributions // and if so count the two lengths as being the same.
507*fdd8201dSApple OSS Distributions
508*fdd8201dSApple OSS Distributions if ((checkLen - stringLen) == 1) {
509*fdd8201dSApple OSS Distributions if (dataPtr[checkLen - 1] != 0) { // non-zero means not a terminator and thus not likely the same
510*fdd8201dSApple OSS Distributions return false;
511*fdd8201dSApple OSS Distributions }
512*fdd8201dSApple OSS Distributions checkLen--;
513*fdd8201dSApple OSS Distributions } else {
514*fdd8201dSApple OSS Distributions return false;
515*fdd8201dSApple OSS Distributions }
516*fdd8201dSApple OSS Distributions }
517*fdd8201dSApple OSS Distributions
518*fdd8201dSApple OSS Distributions aCString = obj->getCStringNoCopy();
519*fdd8201dSApple OSS Distributions
520*fdd8201dSApple OSS Distributions for (unsigned int i = 0; i < checkLen; i++) {
521*fdd8201dSApple OSS Distributions if (*dataPtr++ != aCString[i]) {
522*fdd8201dSApple OSS Distributions return false;
523*fdd8201dSApple OSS Distributions }
524*fdd8201dSApple OSS Distributions }
525*fdd8201dSApple OSS Distributions
526*fdd8201dSApple OSS Distributions return true;
527*fdd8201dSApple OSS Distributions }
528*fdd8201dSApple OSS Distributions
529*fdd8201dSApple OSS Distributions //this was taken from CFPropertyList.c
530*fdd8201dSApple OSS Distributions static const char __CFPLDataEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
531*fdd8201dSApple OSS Distributions
532*fdd8201dSApple OSS Distributions bool
serialize(OSSerialize * s) const533*fdd8201dSApple OSS Distributions OSData::serialize(OSSerialize *s) const
534*fdd8201dSApple OSS Distributions {
535*fdd8201dSApple OSS Distributions unsigned int i;
536*fdd8201dSApple OSS Distributions const unsigned char *p;
537*fdd8201dSApple OSS Distributions unsigned char c;
538*fdd8201dSApple OSS Distributions unsigned int serializeLength;
539*fdd8201dSApple OSS Distributions
540*fdd8201dSApple OSS Distributions if (s->previouslySerialized(this)) {
541*fdd8201dSApple OSS Distributions return true;
542*fdd8201dSApple OSS Distributions }
543*fdd8201dSApple OSS Distributions
544*fdd8201dSApple OSS Distributions if (!s->addXMLStartTag(this, "data")) {
545*fdd8201dSApple OSS Distributions return false;
546*fdd8201dSApple OSS Distributions }
547*fdd8201dSApple OSS Distributions
548*fdd8201dSApple OSS Distributions serializeLength = length;
549*fdd8201dSApple OSS Distributions if (reserved && reserved->disableSerialization) {
550*fdd8201dSApple OSS Distributions serializeLength = 0;
551*fdd8201dSApple OSS Distributions }
552*fdd8201dSApple OSS Distributions
553*fdd8201dSApple OSS Distributions for (i = 0, p = (unsigned char *)data; i < serializeLength; i++, p++) {
554*fdd8201dSApple OSS Distributions /* 3 bytes are encoded as 4 */
555*fdd8201dSApple OSS Distributions switch (i % 3) {
556*fdd8201dSApple OSS Distributions case 0:
557*fdd8201dSApple OSS Distributions c = __CFPLDataEncodeTable[((p[0] >> 2) & 0x3f)];
558*fdd8201dSApple OSS Distributions if (!s->addChar(c)) {
559*fdd8201dSApple OSS Distributions return false;
560*fdd8201dSApple OSS Distributions }
561*fdd8201dSApple OSS Distributions break;
562*fdd8201dSApple OSS Distributions case 1:
563*fdd8201dSApple OSS Distributions c = __CFPLDataEncodeTable[((((p[-1] << 8) | p[0]) >> 4) & 0x3f)];
564*fdd8201dSApple OSS Distributions if (!s->addChar(c)) {
565*fdd8201dSApple OSS Distributions return false;
566*fdd8201dSApple OSS Distributions }
567*fdd8201dSApple OSS Distributions break;
568*fdd8201dSApple OSS Distributions case 2:
569*fdd8201dSApple OSS Distributions c = __CFPLDataEncodeTable[((((p[-1] << 8) | p[0]) >> 6) & 0x3f)];
570*fdd8201dSApple OSS Distributions if (!s->addChar(c)) {
571*fdd8201dSApple OSS Distributions return false;
572*fdd8201dSApple OSS Distributions }
573*fdd8201dSApple OSS Distributions c = __CFPLDataEncodeTable[(p[0] & 0x3f)];
574*fdd8201dSApple OSS Distributions if (!s->addChar(c)) {
575*fdd8201dSApple OSS Distributions return false;
576*fdd8201dSApple OSS Distributions }
577*fdd8201dSApple OSS Distributions break;
578*fdd8201dSApple OSS Distributions }
579*fdd8201dSApple OSS Distributions }
580*fdd8201dSApple OSS Distributions switch (i % 3) {
581*fdd8201dSApple OSS Distributions case 0:
582*fdd8201dSApple OSS Distributions break;
583*fdd8201dSApple OSS Distributions case 1:
584*fdd8201dSApple OSS Distributions c = __CFPLDataEncodeTable[((p[-1] << 4) & 0x30)];
585*fdd8201dSApple OSS Distributions if (!s->addChar(c)) {
586*fdd8201dSApple OSS Distributions return false;
587*fdd8201dSApple OSS Distributions }
588*fdd8201dSApple OSS Distributions if (!s->addChar('=')) {
589*fdd8201dSApple OSS Distributions return false;
590*fdd8201dSApple OSS Distributions }
591*fdd8201dSApple OSS Distributions if (!s->addChar('=')) {
592*fdd8201dSApple OSS Distributions return false;
593*fdd8201dSApple OSS Distributions }
594*fdd8201dSApple OSS Distributions break;
595*fdd8201dSApple OSS Distributions case 2:
596*fdd8201dSApple OSS Distributions c = __CFPLDataEncodeTable[((p[-1] << 2) & 0x3c)];
597*fdd8201dSApple OSS Distributions if (!s->addChar(c)) {
598*fdd8201dSApple OSS Distributions return false;
599*fdd8201dSApple OSS Distributions }
600*fdd8201dSApple OSS Distributions if (!s->addChar('=')) {
601*fdd8201dSApple OSS Distributions return false;
602*fdd8201dSApple OSS Distributions }
603*fdd8201dSApple OSS Distributions break;
604*fdd8201dSApple OSS Distributions }
605*fdd8201dSApple OSS Distributions
606*fdd8201dSApple OSS Distributions return s->addXMLEndTag("data");
607*fdd8201dSApple OSS Distributions }
608*fdd8201dSApple OSS Distributions
609*fdd8201dSApple OSS Distributions void
setDeallocFunction(DeallocFunction func)610*fdd8201dSApple OSS Distributions OSData::setDeallocFunction(DeallocFunction func)
611*fdd8201dSApple OSS Distributions {
612*fdd8201dSApple OSS Distributions if (!reserved) {
613*fdd8201dSApple OSS Distributions reserved = (typeof(reserved))kalloc_type(ExpansionData, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
614*fdd8201dSApple OSS Distributions if (!reserved) {
615*fdd8201dSApple OSS Distributions return;
616*fdd8201dSApple OSS Distributions }
617*fdd8201dSApple OSS Distributions }
618*fdd8201dSApple OSS Distributions reserved->deallocFunction = func;
619*fdd8201dSApple OSS Distributions }
620*fdd8201dSApple OSS Distributions
621*fdd8201dSApple OSS Distributions void
setSerializable(bool serializable)622*fdd8201dSApple OSS Distributions OSData::setSerializable(bool serializable)
623*fdd8201dSApple OSS Distributions {
624*fdd8201dSApple OSS Distributions if (!reserved) {
625*fdd8201dSApple OSS Distributions reserved = (typeof(reserved))kalloc_type(ExpansionData, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
626*fdd8201dSApple OSS Distributions if (!reserved) {
627*fdd8201dSApple OSS Distributions return;
628*fdd8201dSApple OSS Distributions }
629*fdd8201dSApple OSS Distributions }
630*fdd8201dSApple OSS Distributions reserved->disableSerialization = (!serializable);
631*fdd8201dSApple OSS Distributions }
632*fdd8201dSApple OSS Distributions
633*fdd8201dSApple OSS Distributions bool
isSerializable(void)634*fdd8201dSApple OSS Distributions OSData::isSerializable(void)
635*fdd8201dSApple OSS Distributions {
636*fdd8201dSApple OSS Distributions return !reserved || !reserved->disableSerialization;
637*fdd8201dSApple OSS Distributions }
638