/* * Copyright (c) 2022 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include __BEGIN_DECLS #include __END_DECLS #define super OSObject OSDefineMetaClassAndStructors(IOExtensiblePaniclog, OSObject) bool IOExtensiblePaniclog::init(void) { extPaniclogHandle = NULL; if (!super::init()) { os_log_error(OS_LOG_DEFAULT, "EXT_PANICLOG: Super init failed\n"); return false; } return true; } bool IOExtensiblePaniclog::createWithUUID(uuid_t uuid, const char *data_id, uint32_t len, ext_paniclog_create_options_t options, IOExtensiblePaniclog **out) { IOExtensiblePaniclog *inst = OSTypeAlloc(IOExtensiblePaniclog); if (!inst) { os_log_error(OS_LOG_DEFAULT, "EXT_PANICLOG: instance is NULL\n"); return false; } if (!inst->init()) { os_log_error(OS_LOG_DEFAULT, "EXT_PANICLOG: init failed\n"); OSSafeReleaseNULL(inst); return false; } inst->extPaniclogHandle = ext_paniclog_handle_alloc_with_uuid(uuid, data_id, len, options); if (inst->extPaniclogHandle == NULL) { os_log(OS_LOG_DEFAULT, "EXT_PANICLOG: Handle alloc failed\n"); OSSafeReleaseNULL(inst); return false; } *out = inst; return true; } void IOExtensiblePaniclog::free(void) { if (extPaniclogHandle != NULL) { ext_paniclog_handle_free(extPaniclogHandle); } if (iomd != NULL) { iomd->release(); } super::free(); } int IOExtensiblePaniclog::setActive() { return ext_paniclog_handle_set_active(extPaniclogHandle); } int IOExtensiblePaniclog::setInactive() { return ext_paniclog_handle_set_inactive(extPaniclogHandle); } int IOExtensiblePaniclog::insertData(void *addr, uint32_t len) { return ext_paniclog_insert_data(extPaniclogHandle, addr, len); } int IOExtensiblePaniclog::appendData(void *addr, uint32_t len) { return ext_paniclog_append_data(extPaniclogHandle, addr, len); } void * IOExtensiblePaniclog::claimBuffer() { return ext_paniclog_claim_buffer(extPaniclogHandle); } int IOExtensiblePaniclog::yieldBuffer(uint32_t used_len) { return ext_paniclog_yield_buffer(extPaniclogHandle, used_len); } int IOExtensiblePaniclog::setUsedLen(uint32_t used_len) { return ext_paniclog_set_used_len(extPaniclogHandle, used_len); } /********************************************************************************* * * * Driver Kit functions * * * *********************************************************************************/ kern_return_t IOExtensiblePaniclog::Create_Impl(OSData *uuid, OSString *data_id, uint32_t max_len, uint32_t options, IOExtensiblePaniclog **out) { IOExtensiblePaniclog * inst = NULL; uuid_t uuid_copy; uint32_t mem_options = 0; if (!IOCurrentTaskHasEntitlement(EXTPANICLOG_ENTITLEMENT)) { return kIOReturnNotPrivileged; } if ((uuid == nullptr) || (uuid->getLength() > sizeof(uuid_t))) { return kIOReturnBadArgument; } if ((data_id == nullptr) || (data_id->getLength() > MAX_DATA_ID_SIZE)) { return kIOReturnBadArgument; } memcpy(&uuid_copy, uuid->getBytesNoCopy(), uuid->getLength()); inst = OSTypeAlloc(IOExtensiblePaniclog); if (!inst->init()) { OSSafeReleaseNULL(inst); return kIOReturnNoMemory; } mem_options = kIOMemoryKernelUserShared | kIOMemoryThreadSafe | kIODirectionInOut; inst->iomd = IOBufferMemoryDescriptor::withOptions(mem_options, max_len); if (inst->iomd == NULL) { IOLog("EXT_PANICLOG IOKIT: Failed to create iobmd"); OSSafeReleaseNULL(inst); return kIOReturnNoMemory; } inst->extPaniclogHandle = ext_paniclog_handle_alloc_with_buffer(uuid_copy, data_id->getCStringNoCopy(), max_len, inst->iomd->getBytesNoCopy(), (ext_paniclog_create_options_t)(options | EXT_PANICLOG_OPTIONS_WITH_BUFFER)); if (inst->extPaniclogHandle == NULL) { OSSafeReleaseNULL(inst); return kIOReturnNoMemory; } *out = inst; return kIOReturnSuccess; } kern_return_t IOExtensiblePaniclog::SetActive_Impl() { if (ext_paniclog_handle_set_active(extPaniclogHandle) != 0) { return kIOReturnBadArgument; } return kIOReturnSuccess; } kern_return_t IOExtensiblePaniclog::SetInactive_Impl() { if (ext_paniclog_handle_set_inactive(extPaniclogHandle) != 0) { return kIOReturnBadArgument; } return kIOReturnSuccess; } kern_return_t IOExtensiblePaniclog::InsertData_Impl(OSData *data) { if (data == nullptr) { return kIOReturnBadArgument; } void *addr = (void *)data->getBytesNoCopy(); if (ext_paniclog_insert_data(extPaniclogHandle, addr, data->getLength()) != 0) { return kIOReturnBadArgument; } return kIOReturnSuccess; } kern_return_t IOExtensiblePaniclog::AppendData_Impl(OSData *data) { if (data == nullptr) { return kIOReturnBadArgument; } void *addr = (void *)data->getBytesNoCopy(); if (ext_paniclog_append_data(extPaniclogHandle, addr, data->getLength()) != 0) { return kIOReturnBadArgument; } return kIOReturnSuccess; } kern_return_t IOExtensiblePaniclog::CopyMemoryDescriptor_Impl(IOBufferMemoryDescriptor **mem) { (void) ext_paniclog_claim_buffer(extPaniclogHandle); iomd->retain(); *mem = iomd; return kIOReturnSuccess; } kern_return_t IOExtensiblePaniclog::SetUsedLen_Impl(uint32_t used_len) { return ext_paniclog_set_used_len(extPaniclogHandle, used_len); }