xref: /xnu-11215/iokit/Kernel/IOReportLegend.cpp (revision bb611c8f)
1 /*
2  * Copyright (c) 2012-2013 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 #define IOKIT_ENABLE_SHARED_PTR
30 
31 #include <IOKit/IOKernelReportStructs.h>
32 #include <IOKit/IOKernelReporters.h>
33 
34 
35 //#define IORDEBUG_LEGEND 1
36 
37 #ifdef IORDEBUG_LEGEND
38     #define IORLEGENDLOG(fmt, args...)      \
39     do {                                    \
40 	IOLog("IOReportLegend | ");         \
41 	IOLog(fmt, ##args);                 \
42 	IOLog("\n");                        \
43     } while(0)
44 #else
45     #define IORLEGENDLOG(fmt, args...)
46 #endif
47 
48 
49 #define super OSObject
50 OSDefineMetaClassAndStructors(IOReportLegend, OSObject);
51 
52 OSSharedPtr<IOReportLegend>
with(OSArray * legend)53 IOReportLegend::with(OSArray *legend)
54 {
55 	OSSharedPtr<IOReportLegend> iorLegend = OSMakeShared<IOReportLegend>();
56 
57 	if (iorLegend) {
58 		if (legend != NULL) {
59 			if (iorLegend->initWith(legend) != kIOReturnSuccess) {
60 				return nullptr;
61 			}
62 		}
63 
64 		return iorLegend;
65 	} else {
66 		return nullptr;
67 	}
68 }
69 
70 /* must clean up everything if it fails */
71 IOReturn
initWith(OSArray * legend)72 IOReportLegend::initWith(OSArray *legend)
73 {
74 	if (legend) {
75 		_reportLegend = OSArray::withArray(legend);
76 	}
77 
78 	if (_reportLegend == NULL) {
79 		return kIOReturnError;
80 	} else {
81 		return kIOReturnSuccess;
82 	}
83 }
84 
85 
86 void
free(void)87 IOReportLegend::free(void)
88 {
89 	super::free();
90 }
91 
92 
93 OSArray*
getLegend(void)94 IOReportLegend::getLegend(void)
95 {
96 	return _reportLegend.get();
97 }
98 
99 IOReturn
addReporterLegend(IOService * reportingService,IOReporter * reporter,const char * groupName,const char * subGroupName)100 IOReportLegend::addReporterLegend(IOService *reportingService,
101     IOReporter *reporter,
102     const char *groupName,
103     const char *subGroupName)
104 {
105 	IOReturn res = kIOReturnError;
106 	OSSharedPtr<IOReportLegend> legend;
107 	OSSharedPtr<OSObject> curLegend;
108 
109 	// No need to check groupName and subGroupName because optional params
110 	if (!reportingService || !reporter) {
111 		goto finish;
112 	}
113 
114 	// It's fine if the legend doesn't exist (IOReportLegend::with(NULL)
115 	// is how you make an empty legend).  If it's not an array, then
116 	// we're just going to replace it.
117 	curLegend = reportingService->copyProperty(kIOReportLegendKey);
118 	legend = IOReportLegend::with(OSDynamicCast(OSArray, curLegend.get()));
119 	if (!legend) {
120 		goto finish;
121 	}
122 
123 	// Add the reporter's entries and update the service property.
124 	// The overwrite triggers a release of the old legend array.
125 	legend->addReporterLegend(reporter, groupName, subGroupName);
126 	reportingService->setProperty(kIOReportLegendKey, legend->getLegend());
127 	reportingService->setProperty(kIOReportLegendPublicKey, true);
128 
129 	res = kIOReturnSuccess;
130 
131 finish:
132 	return res;
133 }
134 
135 
136 IOReturn
addLegendEntry(IOReportLegendEntry * legendEntry,const char * groupName,const char * subGroupName)137 IOReportLegend::addLegendEntry(IOReportLegendEntry *legendEntry,
138     const char *groupName,
139     const char *subGroupName)
140 {
141 	kern_return_t res = kIOReturnError;
142 	OSSharedPtr<const OSSymbol> tmpGroupName;
143 	OSSharedPtr<const OSSymbol> tmpSubGroupName;
144 
145 	if (!legendEntry) {
146 		return res;
147 	}
148 
149 	if (groupName) {
150 		tmpGroupName = OSSymbol::withCString(groupName);
151 	}
152 
153 	if (subGroupName) {
154 		tmpSubGroupName = OSSymbol::withCString(subGroupName);
155 	}
156 
157 	// It is ok to call appendLegendWith() if tmpGroups are NULL
158 	res = organizeLegend(legendEntry, tmpGroupName.get(), tmpSubGroupName.get());
159 
160 	return res;
161 }
162 
163 
164 IOReturn
addReporterLegend(IOReporter * reporter,const char * groupName,const char * subGroupName)165 IOReportLegend::addReporterLegend(IOReporter *reporter,
166     const char *groupName,
167     const char *subGroupName)
168 {
169 	IOReturn res = kIOReturnError;
170 	OSSharedPtr<IOReportLegendEntry> legendEntry;
171 
172 	if (reporter) {
173 		legendEntry = reporter->createLegend();
174 
175 		if (legendEntry) {
176 			res = addLegendEntry(legendEntry.get(), groupName, subGroupName);
177 		}
178 	}
179 
180 	return res;
181 }
182 
183 
184 IOReturn
organizeLegend(IOReportLegendEntry * legendEntry,const OSSymbol * groupName,const OSSymbol * subGroupName)185 IOReportLegend::organizeLegend(IOReportLegendEntry *legendEntry,
186     const OSSymbol *groupName,
187     const OSSymbol *subGroupName)
188 {
189 	if (!legendEntry) {
190 		return kIOReturnBadArgument;
191 	}
192 
193 	if (!groupName && subGroupName) {
194 		return kIOReturnBadArgument;
195 	}
196 
197 	IORLEGENDLOG("IOReportLegend::organizeLegend");
198 	// Legend is empty, enter first node
199 	if (_reportLegend == NULL) {
200 		IORLEGENDLOG("IOReportLegend::new legend creation");
201 		_reportLegend = OSArray::withCapacity(1);
202 
203 		if (!_reportLegend) {
204 			return kIOReturnNoMemory;
205 		}
206 	}
207 
208 	if (groupName) {
209 		legendEntry->setObject(kIOReportLegendGroupNameKey, groupName);
210 	}
211 
212 	if (subGroupName) {
213 		legendEntry->setObject(kIOReportLegendSubGroupNameKey, subGroupName);
214 	}
215 
216 	_reportLegend->setObject(legendEntry);
217 
218 	// callers can now safely release legendEntry (it is part of _reportLegend)
219 
220 	return kIOReturnSuccess;
221 }
222