1 /* 2 * Copyright (c) 2022 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #include <IOKit/IOExtensiblePaniclog.h> 30 #include <IOKit/IOLib.h> 31 #include <IOKit/IOBSD.h> 32 #include <IOKit/IOBufferMemoryDescriptor.h> 33 34 #include <libkern/c++/OSAllocation.h> 35 #include <libkern/c++/OSKext.h> 36 37 __BEGIN_DECLS 38 #include <os/log.h> 39 __END_DECLS 40 41 #define super OSObject 42 OSDefineMetaClassAndStructors(IOExtensiblePaniclog, OSObject) 43 44 bool 45 IOExtensiblePaniclog::init(void) 46 { 47 extPaniclogHandle = NULL; 48 49 if (!super::init()) { 50 os_log_error(OS_LOG_DEFAULT, "EXT_PANICLOG: Super init failed\n"); 51 return false; 52 } 53 54 return true; 55 } 56 57 bool 58 IOExtensiblePaniclog::createWithUUID(uuid_t uuid, const char *data_id, uint32_t len, 59 ext_paniclog_create_options_t options, IOExtensiblePaniclog **out) 60 { 61 IOExtensiblePaniclog *inst = OSTypeAlloc(IOExtensiblePaniclog); 62 if (!inst) { 63 os_log_error(OS_LOG_DEFAULT, "EXT_PANICLOG: instance is NULL\n"); 64 return false; 65 } 66 67 if (!inst->init()) { 68 os_log_error(OS_LOG_DEFAULT, "EXT_PANICLOG: init failed\n"); 69 OSSafeReleaseNULL(inst); 70 return false; 71 } 72 73 inst->extPaniclogHandle = ext_paniclog_handle_alloc_with_uuid(uuid, data_id, 74 len, options); 75 if (inst->extPaniclogHandle == NULL) { 76 os_log(OS_LOG_DEFAULT, "EXT_PANICLOG: Handle alloc failed\n"); 77 OSSafeReleaseNULL(inst); 78 return false; 79 } 80 81 *out = inst; 82 83 return true; 84 } 85 86 void 87 IOExtensiblePaniclog::free(void) 88 { 89 if (extPaniclogHandle != NULL) { 90 ext_paniclog_handle_free(extPaniclogHandle); 91 } 92 93 if (iomd != NULL) { 94 iomd->release(); 95 } 96 97 super::free(); 98 } 99 100 int 101 IOExtensiblePaniclog::setActive() 102 { 103 return ext_paniclog_handle_set_active(extPaniclogHandle); 104 } 105 106 int 107 IOExtensiblePaniclog::setInactive() 108 { 109 return ext_paniclog_handle_set_inactive(extPaniclogHandle); 110 } 111 112 int 113 IOExtensiblePaniclog::insertData(void *addr, uint32_t len) 114 { 115 return ext_paniclog_insert_data(extPaniclogHandle, addr, len); 116 } 117 118 int 119 IOExtensiblePaniclog::appendData(void *addr, uint32_t len) 120 { 121 return ext_paniclog_append_data(extPaniclogHandle, addr, len); 122 } 123 124 void * 125 IOExtensiblePaniclog::claimBuffer() 126 { 127 return ext_paniclog_claim_buffer(extPaniclogHandle); 128 } 129 130 int 131 IOExtensiblePaniclog::yieldBuffer(uint32_t used_len) 132 { 133 return ext_paniclog_yield_buffer(extPaniclogHandle, used_len); 134 } 135 136 int 137 IOExtensiblePaniclog::setUsedLen(uint32_t used_len) 138 { 139 return ext_paniclog_set_used_len(extPaniclogHandle, used_len); 140 } 141 142 /********************************************************************************* 143 * * 144 * Driver Kit functions * 145 * * 146 *********************************************************************************/ 147 148 kern_return_t 149 IOExtensiblePaniclog::Create_Impl(OSData *uuid, OSString *data_id, uint32_t max_len, 150 uint32_t options, IOExtensiblePaniclog **out) 151 { 152 IOExtensiblePaniclog * inst = NULL; 153 uuid_t uuid_copy; 154 uint32_t mem_options = 0; 155 156 if (!IOCurrentTaskHasEntitlement(EXTPANICLOG_ENTITLEMENT)) { 157 return kIOReturnNotPrivileged; 158 } 159 160 if ((uuid == nullptr) || (uuid->getLength() > sizeof(uuid_t))) { 161 return kIOReturnBadArgument; 162 } 163 164 if ((data_id == nullptr) || (data_id->getLength() > MAX_DATA_ID_SIZE)) { 165 return kIOReturnBadArgument; 166 } 167 168 memcpy(&uuid_copy, uuid->getBytesNoCopy(), uuid->getLength()); 169 170 inst = OSTypeAlloc(IOExtensiblePaniclog); 171 if (!inst->init()) { 172 OSSafeReleaseNULL(inst); 173 return kIOReturnNoMemory; 174 } 175 176 mem_options = kIOMemoryKernelUserShared | kIOMemoryThreadSafe | kIODirectionInOut; 177 inst->iomd = IOBufferMemoryDescriptor::withOptions(mem_options, max_len); 178 if (inst->iomd == NULL) { 179 IOLog("EXT_PANICLOG IOKIT: Failed to create iobmd"); 180 OSSafeReleaseNULL(inst); 181 return kIOReturnNoMemory; 182 } 183 184 inst->extPaniclogHandle = ext_paniclog_handle_alloc_with_buffer(uuid_copy, 185 data_id->getCStringNoCopy(), max_len, inst->iomd->getBytesNoCopy(), 186 (ext_paniclog_create_options_t)(options | EXT_PANICLOG_OPTIONS_WITH_BUFFER)); 187 if (inst->extPaniclogHandle == NULL) { 188 OSSafeReleaseNULL(inst); 189 return kIOReturnNoMemory; 190 } 191 192 *out = inst; 193 194 return kIOReturnSuccess; 195 } 196 197 kern_return_t 198 IOExtensiblePaniclog::SetActive_Impl() 199 { 200 if (ext_paniclog_handle_set_active(extPaniclogHandle) != 0) { 201 return kIOReturnBadArgument; 202 } 203 204 return kIOReturnSuccess; 205 } 206 207 kern_return_t 208 IOExtensiblePaniclog::SetInactive_Impl() 209 { 210 if (ext_paniclog_handle_set_inactive(extPaniclogHandle) != 0) { 211 return kIOReturnBadArgument; 212 } 213 214 return kIOReturnSuccess; 215 } 216 217 kern_return_t 218 IOExtensiblePaniclog::InsertData_Impl(OSData *data) 219 { 220 if (data == nullptr) { 221 return kIOReturnBadArgument; 222 } 223 224 void *addr = (void *)data->getBytesNoCopy(); 225 226 if (ext_paniclog_insert_data(extPaniclogHandle, addr, data->getLength()) != 0) { 227 return kIOReturnBadArgument; 228 } 229 230 return kIOReturnSuccess; 231 } 232 233 kern_return_t 234 IOExtensiblePaniclog::AppendData_Impl(OSData *data) 235 { 236 if (data == nullptr) { 237 return kIOReturnBadArgument; 238 } 239 240 void *addr = (void *)data->getBytesNoCopy(); 241 242 if (ext_paniclog_append_data(extPaniclogHandle, addr, data->getLength()) != 0) { 243 return kIOReturnBadArgument; 244 } 245 246 return kIOReturnSuccess; 247 } 248 249 kern_return_t 250 IOExtensiblePaniclog::CopyMemoryDescriptor_Impl(IOBufferMemoryDescriptor **mem) 251 { 252 (void) ext_paniclog_claim_buffer(extPaniclogHandle); 253 254 iomd->retain(); 255 *mem = iomd; 256 return kIOReturnSuccess; 257 } 258 259 kern_return_t 260 IOExtensiblePaniclog::SetUsedLen_Impl(uint32_t used_len) 261 { 262 return ext_paniclog_set_used_len(extPaniclogHandle, used_len); 263 } 264