1c1dac77fSApple OSS Distributions /* 2e13b1fa5SApple OSS Distributions * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3c1dac77fSApple OSS Distributions * 4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5c1dac77fSApple OSS Distributions * 6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement. 14c1dac77fSApple OSS Distributions * 15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at 16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17e13b1fa5SApple OSS Distributions * 18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are 19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and 24e13b1fa5SApple OSS Distributions * limitations under the License. 25c1dac77fSApple OSS Distributions * 26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27c1dac77fSApple OSS Distributions */ 28c1dac77fSApple OSS Distributions /* OSSerialize.cpp created by rsulack on Wen 25-Nov-1998 */ 29c1dac77fSApple OSS Distributions 30*bb611c8fSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR 31*bb611c8fSApple OSS Distributions 32fad439e7SApple OSS Distributions #include <sys/cdefs.h> 33fad439e7SApple OSS Distributions 34fad439e7SApple OSS Distributions __BEGIN_DECLS 35fad439e7SApple OSS Distributions #include <vm/vm_kern.h> 36fad439e7SApple OSS Distributions __END_DECLS 37fad439e7SApple OSS Distributions 38c1dac77fSApple OSS Distributions #include <libkern/c++/OSContainers.h> 39c1dac77fSApple OSS Distributions #include <libkern/c++/OSLib.h> 40c1dac77fSApple OSS Distributions #include <libkern/c++/OSDictionary.h> 41*bb611c8fSApple OSS Distributions #include <libkern/c++/OSSharedPtr.h> 42a3bb9fccSApple OSS Distributions #include <libkern/OSSerializeBinary.h> 43cc9a6355SApple OSS Distributions #include <libkern/Block.h> 440f3703acSApple OSS Distributions #include <IOKit/IOLib.h> 45c1dac77fSApple OSS Distributions 46c1dac77fSApple OSS Distributions #define super OSObject 47c1dac77fSApple OSS Distributions 48c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(OSSerialize, OSObject) 49c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 0); 50c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 1); 51c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 2); 52c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 3); 53c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 4); 54c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 5); 55c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 6); 56c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 7); 57c1dac77fSApple OSS Distributions 58c1dac77fSApple OSS Distributions 59a5e72196SApple OSS Distributions char * 60a5e72196SApple OSS Distributions OSSerialize::text() const 61c1dac77fSApple OSS Distributions { 62c1dac77fSApple OSS Distributions return data; 63c1dac77fSApple OSS Distributions } 64c1dac77fSApple OSS Distributions 65a5e72196SApple OSS Distributions void 66a5e72196SApple OSS Distributions OSSerialize::clearText() 67c1dac77fSApple OSS Distributions { 68a5e72196SApple OSS Distributions if (binary) { 69a3bb9fccSApple OSS Distributions length = sizeof(kOSSerializeBinarySignature); 70a3bb9fccSApple OSS Distributions bzero(&data[length], capacity - length); 71a3bb9fccSApple OSS Distributions endCollection = true; 72a5e72196SApple OSS Distributions } else { 73c1dac77fSApple OSS Distributions bzero((void *)data, capacity); 74c1dac77fSApple OSS Distributions length = 1; 75a3bb9fccSApple OSS Distributions } 76c1dac77fSApple OSS Distributions tags->flushCollection(); 77c1dac77fSApple OSS Distributions } 78c1dac77fSApple OSS Distributions 79a5e72196SApple OSS Distributions bool 80a5e72196SApple OSS Distributions OSSerialize::previouslySerialized(const OSMetaClassBase *o) 81c1dac77fSApple OSS Distributions { 82c1dac77fSApple OSS Distributions char temp[16]; 8388cc0b97SApple OSS Distributions unsigned int tagIdx; 84c1dac77fSApple OSS Distributions 85a5e72196SApple OSS Distributions if (binary) { 86a5e72196SApple OSS Distributions return binarySerialize(o); 87a5e72196SApple OSS Distributions } 88a3bb9fccSApple OSS Distributions 89c1dac77fSApple OSS Distributions // look it up 9088cc0b97SApple OSS Distributions tagIdx = tags->getNextIndexOfObject(o, 0); 91c1dac77fSApple OSS Distributions 923ca3bd55SApple OSS Distributions // xx-review: no error checking here for addString calls! 93c1dac77fSApple OSS Distributions // does it exist? 9488cc0b97SApple OSS Distributions if (tagIdx != -1U) { 95c1dac77fSApple OSS Distributions addString("<reference IDREF=\""); 9688cc0b97SApple OSS Distributions snprintf(temp, sizeof(temp), "%u", tagIdx); 9788cc0b97SApple OSS Distributions addString(temp); 98c1dac77fSApple OSS Distributions addString("\"/>"); 99c1dac77fSApple OSS Distributions return true; 100c1dac77fSApple OSS Distributions } 101c1dac77fSApple OSS Distributions 10288cc0b97SApple OSS Distributions // add to tag array 10388cc0b97SApple OSS Distributions tags->setObject(o);// XXX check return 104c1dac77fSApple OSS Distributions 105c1dac77fSApple OSS Distributions return false; 106c1dac77fSApple OSS Distributions } 107c1dac77fSApple OSS Distributions 108a5e72196SApple OSS Distributions bool 109a5e72196SApple OSS Distributions OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString) 110c1dac77fSApple OSS Distributions { 11188cc0b97SApple OSS Distributions char temp[16]; 11288cc0b97SApple OSS Distributions unsigned int tagIdx; 11388cc0b97SApple OSS Distributions 114a5e72196SApple OSS Distributions if (binary) { 115a3bb9fccSApple OSS Distributions printf("class %s: xml serialize\n", o->getMetaClass()->getClassName()); 116a5e72196SApple OSS Distributions return false; 117a3bb9fccSApple OSS Distributions } 118c1dac77fSApple OSS Distributions 119a5e72196SApple OSS Distributions if (!addChar('<')) { 120a5e72196SApple OSS Distributions return false; 121a5e72196SApple OSS Distributions } 122a5e72196SApple OSS Distributions if (!addString(tagString)) { 123a5e72196SApple OSS Distributions return false; 124a5e72196SApple OSS Distributions } 125a5e72196SApple OSS Distributions if (!addString(" ID=\"")) { 126a5e72196SApple OSS Distributions return false; 127a5e72196SApple OSS Distributions } 12888cc0b97SApple OSS Distributions tagIdx = tags->getNextIndexOfObject(o, 0); 12988cc0b97SApple OSS Distributions assert(tagIdx != -1U); 13088cc0b97SApple OSS Distributions snprintf(temp, sizeof(temp), "%u", tagIdx); 131a5e72196SApple OSS Distributions if (!addString(temp)) { 132c1dac77fSApple OSS Distributions return false; 133a5e72196SApple OSS Distributions } 134a5e72196SApple OSS Distributions if (!addChar('\"')) { 135a5e72196SApple OSS Distributions return false; 136a5e72196SApple OSS Distributions } 137a5e72196SApple OSS Distributions if (!addChar('>')) { 138a5e72196SApple OSS Distributions return false; 139a5e72196SApple OSS Distributions } 140c1dac77fSApple OSS Distributions return true; 141c1dac77fSApple OSS Distributions } 142c1dac77fSApple OSS Distributions 143a5e72196SApple OSS Distributions bool 144a5e72196SApple OSS Distributions OSSerialize::addXMLEndTag(const char *tagString) 145c1dac77fSApple OSS Distributions { 146a5e72196SApple OSS Distributions if (!addChar('<')) { 147a5e72196SApple OSS Distributions return false; 148a5e72196SApple OSS Distributions } 149a5e72196SApple OSS Distributions if (!addChar('/')) { 150a5e72196SApple OSS Distributions return false; 151a5e72196SApple OSS Distributions } 152a5e72196SApple OSS Distributions if (!addString(tagString)) { 153a5e72196SApple OSS Distributions return false; 154a5e72196SApple OSS Distributions } 155a5e72196SApple OSS Distributions if (!addChar('>')) { 156a5e72196SApple OSS Distributions return false; 157a5e72196SApple OSS Distributions } 158c1dac77fSApple OSS Distributions return true; 159c1dac77fSApple OSS Distributions } 160c1dac77fSApple OSS Distributions 161a5e72196SApple OSS Distributions bool 162a5e72196SApple OSS Distributions OSSerialize::addChar(const char c) 163c1dac77fSApple OSS Distributions { 164a5e72196SApple OSS Distributions if (binary) { 165a3bb9fccSApple OSS Distributions printf("xml serialize\n"); 166a5e72196SApple OSS Distributions return false; 167a3bb9fccSApple OSS Distributions } 168a3bb9fccSApple OSS Distributions 169c1dac77fSApple OSS Distributions // add char, possibly extending our capacity 170a5e72196SApple OSS Distributions if (length >= capacity && length >= ensureCapacity(capacity + capacityIncrement)) { 171c1dac77fSApple OSS Distributions return false; 172a5e72196SApple OSS Distributions } 173c1dac77fSApple OSS Distributions 174c1dac77fSApple OSS Distributions data[length - 1] = c; 175c1dac77fSApple OSS Distributions length++; 176c1dac77fSApple OSS Distributions 177c1dac77fSApple OSS Distributions return true; 178c1dac77fSApple OSS Distributions } 179c1dac77fSApple OSS Distributions 180a5e72196SApple OSS Distributions bool 181a5e72196SApple OSS Distributions OSSerialize::addString(const char *s) 182c1dac77fSApple OSS Distributions { 183c1dac77fSApple OSS Distributions bool rc = false; 184c1dac77fSApple OSS Distributions 185a5e72196SApple OSS Distributions while (*s && (rc = addChar(*s++))) { 186a5e72196SApple OSS Distributions ; 187a5e72196SApple OSS Distributions } 188c1dac77fSApple OSS Distributions 189c1dac77fSApple OSS Distributions return rc; 190c1dac77fSApple OSS Distributions } 191c1dac77fSApple OSS Distributions 192a5e72196SApple OSS Distributions bool 193a5e72196SApple OSS Distributions OSSerialize::initWithCapacity(unsigned int inCapacity) 194c1dac77fSApple OSS Distributions { 195a5e72196SApple OSS Distributions if (!super::init()) { 196c1dac77fSApple OSS Distributions return false; 197a5e72196SApple OSS Distributions } 198c1dac77fSApple OSS Distributions 19988cc0b97SApple OSS Distributions tags = OSArray::withCapacity(256); 200c1dac77fSApple OSS Distributions if (!tags) { 201c1dac77fSApple OSS Distributions return false; 202c1dac77fSApple OSS Distributions } 203c1dac77fSApple OSS Distributions 204c1dac77fSApple OSS Distributions length = 1; 20588cc0b97SApple OSS Distributions 20688cc0b97SApple OSS Distributions if (!inCapacity) { 20788cc0b97SApple OSS Distributions inCapacity = 1; 20888cc0b97SApple OSS Distributions } 20988cc0b97SApple OSS Distributions if (round_page_overflow(inCapacity, &capacity)) { 210*bb611c8fSApple OSS Distributions tags.reset(); 21188cc0b97SApple OSS Distributions return false; 21288cc0b97SApple OSS Distributions } 21388cc0b97SApple OSS Distributions 214fad439e7SApple OSS Distributions capacityIncrement = capacity; 215c1dac77fSApple OSS Distributions 216fad439e7SApple OSS Distributions // allocate from the kernel map so that we can safely map this data 217fad439e7SApple OSS Distributions // into user space (the primary use of the OSSerialize object) 218fad439e7SApple OSS Distributions 2190f3703acSApple OSS Distributions kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity, IOMemoryTag(kernel_map)); 220fad439e7SApple OSS Distributions if (rc) { 221c1dac77fSApple OSS Distributions return false; 222c1dac77fSApple OSS Distributions } 223c1dac77fSApple OSS Distributions bzero((void *)data, capacity); 224c1dac77fSApple OSS Distributions 225c1dac77fSApple OSS Distributions 2260f3703acSApple OSS Distributions OSCONTAINER_ACCUMSIZE(capacity); 227c1dac77fSApple OSS Distributions 228c1dac77fSApple OSS Distributions return true; 229c1dac77fSApple OSS Distributions } 230c1dac77fSApple OSS Distributions 231*bb611c8fSApple OSS Distributions OSSharedPtr<OSSerialize> 232a5e72196SApple OSS Distributions OSSerialize::withCapacity(unsigned int inCapacity) 233c1dac77fSApple OSS Distributions { 234*bb611c8fSApple OSS Distributions OSSharedPtr<OSSerialize> me = OSMakeShared<OSSerialize>(); 235c1dac77fSApple OSS Distributions 236c1dac77fSApple OSS Distributions if (me && !me->initWithCapacity(inCapacity)) { 237*bb611c8fSApple OSS Distributions return nullptr; 238c1dac77fSApple OSS Distributions } 239c1dac77fSApple OSS Distributions 240c1dac77fSApple OSS Distributions return me; 241c1dac77fSApple OSS Distributions } 242c1dac77fSApple OSS Distributions 243a5e72196SApple OSS Distributions unsigned int 244a5e72196SApple OSS Distributions OSSerialize::getLength() const 245a5e72196SApple OSS Distributions { 246a5e72196SApple OSS Distributions return length; 247a5e72196SApple OSS Distributions } 248a5e72196SApple OSS Distributions unsigned int 249a5e72196SApple OSS Distributions OSSerialize::getCapacity() const 250a5e72196SApple OSS Distributions { 251a5e72196SApple OSS Distributions return capacity; 252a5e72196SApple OSS Distributions } 253a5e72196SApple OSS Distributions unsigned int 254a5e72196SApple OSS Distributions OSSerialize::getCapacityIncrement() const 255a5e72196SApple OSS Distributions { 256a5e72196SApple OSS Distributions return capacityIncrement; 257a5e72196SApple OSS Distributions } 258a5e72196SApple OSS Distributions unsigned int 259a5e72196SApple OSS Distributions OSSerialize::setCapacityIncrement(unsigned int increment) 260c1dac77fSApple OSS Distributions { 261c1dac77fSApple OSS Distributions capacityIncrement = (increment)? increment : 256; 262c1dac77fSApple OSS Distributions return capacityIncrement; 263c1dac77fSApple OSS Distributions } 264c1dac77fSApple OSS Distributions 265a5e72196SApple OSS Distributions unsigned int 266a5e72196SApple OSS Distributions OSSerialize::ensureCapacity(unsigned int newCapacity) 267c1dac77fSApple OSS Distributions { 268c1dac77fSApple OSS Distributions char *newData; 269c1dac77fSApple OSS Distributions 270a5e72196SApple OSS Distributions if (newCapacity <= capacity) { 271c1dac77fSApple OSS Distributions return capacity; 272a5e72196SApple OSS Distributions } 273c1dac77fSApple OSS Distributions 27488cc0b97SApple OSS Distributions if (round_page_overflow(newCapacity, &newCapacity)) { 27588cc0b97SApple OSS Distributions return capacity; 27688cc0b97SApple OSS Distributions } 277c1dac77fSApple OSS Distributions 278fad439e7SApple OSS Distributions kern_return_t rc = kmem_realloc(kernel_map, 279fad439e7SApple OSS Distributions (vm_offset_t)data, 280fad439e7SApple OSS Distributions capacity, 281fad439e7SApple OSS Distributions (vm_offset_t *)&newData, 2820f3703acSApple OSS Distributions newCapacity, 2830f3703acSApple OSS Distributions VM_KERN_MEMORY_IOKIT); 284fad439e7SApple OSS Distributions if (!rc) { 2850f3703acSApple OSS Distributions OSCONTAINER_ACCUMSIZE(newCapacity); 286c1dac77fSApple OSS Distributions 287fad439e7SApple OSS Distributions // kmem realloc does not free the old address range 288fad439e7SApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity); 2890f3703acSApple OSS Distributions OSCONTAINER_ACCUMSIZE(-((size_t)capacity)); 290fad439e7SApple OSS Distributions 291fad439e7SApple OSS Distributions // kmem realloc does not zero out the new memory 292fad439e7SApple OSS Distributions // and this could end up going to user land 293fad439e7SApple OSS Distributions bzero(&newData[capacity], newCapacity - capacity); 294fad439e7SApple OSS Distributions 295c1dac77fSApple OSS Distributions data = newData; 296c1dac77fSApple OSS Distributions capacity = newCapacity; 297c1dac77fSApple OSS Distributions } 298c1dac77fSApple OSS Distributions 299c1dac77fSApple OSS Distributions return capacity; 300c1dac77fSApple OSS Distributions } 301c1dac77fSApple OSS Distributions 302a5e72196SApple OSS Distributions void 303a5e72196SApple OSS Distributions OSSerialize::free() 304c1dac77fSApple OSS Distributions { 305c1dac77fSApple OSS Distributions if (data) { 306fad439e7SApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity); 3070f3703acSApple OSS Distributions OSCONTAINER_ACCUMSIZE( -((size_t)capacity)); 308c1dac77fSApple OSS Distributions } 309c1dac77fSApple OSS Distributions super::free(); 310c1dac77fSApple OSS Distributions } 311c1dac77fSApple OSS Distributions 312c1dac77fSApple OSS Distributions 313c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(OSSerializer, OSObject) 314c1dac77fSApple OSS Distributions 315*bb611c8fSApple OSS Distributions OSSharedPtr<OSSerializer> 316*bb611c8fSApple OSS Distributions OSSerializer::forTarget( void * target, 317368ad365SApple OSS Distributions OSSerializerCallback callback, void * ref ) 318c1dac77fSApple OSS Distributions { 319*bb611c8fSApple OSS Distributions OSSharedPtr<OSSerializer> thing = OSMakeShared<OSSerializer>(); 320c1dac77fSApple OSS Distributions 321c1dac77fSApple OSS Distributions if (thing && !thing->init()) { 322*bb611c8fSApple OSS Distributions thing.reset(); 323c1dac77fSApple OSS Distributions } 324c1dac77fSApple OSS Distributions 325c1dac77fSApple OSS Distributions if (thing) { 326c1dac77fSApple OSS Distributions thing->target = target; 327c1dac77fSApple OSS Distributions thing->ref = ref; 328c1dac77fSApple OSS Distributions thing->callback = callback; 329c1dac77fSApple OSS Distributions } 330a5e72196SApple OSS Distributions return thing; 331c1dac77fSApple OSS Distributions } 332c1dac77fSApple OSS Distributions 333a5e72196SApple OSS Distributions bool 334a5e72196SApple OSS Distributions OSSerializer::callbackToBlock(void * target __unused, void * ref, 335cc9a6355SApple OSS Distributions OSSerialize * serializer) 336cc9a6355SApple OSS Distributions { 337cc9a6355SApple OSS Distributions return ((OSSerializerBlock)ref)(serializer); 338cc9a6355SApple OSS Distributions } 339cc9a6355SApple OSS Distributions 340*bb611c8fSApple OSS Distributions OSSharedPtr<OSSerializer> 341a5e72196SApple OSS Distributions OSSerializer::withBlock( 342cc9a6355SApple OSS Distributions OSSerializerBlock callback) 343cc9a6355SApple OSS Distributions { 344*bb611c8fSApple OSS Distributions OSSharedPtr<OSSerializer> serializer; 345cc9a6355SApple OSS Distributions OSSerializerBlock block; 346cc9a6355SApple OSS Distributions 347cc9a6355SApple OSS Distributions block = Block_copy(callback); 348a5e72196SApple OSS Distributions if (!block) { 349a5e72196SApple OSS Distributions return NULL; 350a5e72196SApple OSS Distributions } 351cc9a6355SApple OSS Distributions 352cc9a6355SApple OSS Distributions serializer = (OSSerializer::forTarget(NULL, &OSSerializer::callbackToBlock, block)); 353cc9a6355SApple OSS Distributions 354a5e72196SApple OSS Distributions if (!serializer) { 355a5e72196SApple OSS Distributions Block_release(block); 356cc9a6355SApple OSS Distributions } 357cc9a6355SApple OSS Distributions 358a5e72196SApple OSS Distributions return serializer; 359a5e72196SApple OSS Distributions } 360a5e72196SApple OSS Distributions 361a5e72196SApple OSS Distributions void 362a5e72196SApple OSS Distributions OSSerializer::free(void) 363cc9a6355SApple OSS Distributions { 364a5e72196SApple OSS Distributions if (callback == &callbackToBlock) { 365a5e72196SApple OSS Distributions Block_release(ref); 366a5e72196SApple OSS Distributions } 367cc9a6355SApple OSS Distributions 368cc9a6355SApple OSS Distributions super::free(); 369cc9a6355SApple OSS Distributions } 370cc9a6355SApple OSS Distributions 371a5e72196SApple OSS Distributions bool 372a5e72196SApple OSS Distributions OSSerializer::serialize( OSSerialize * s ) const 373c1dac77fSApple OSS Distributions { 374a5e72196SApple OSS Distributions return (*callback)(target, ref, s); 375c1dac77fSApple OSS Distributions } 376