1/*
2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24// AppleCDDAFileSystemUtilities.cpp created by CJS on Fri 19-May-2000
25
26// Project Includes
27#ifndef __APPLE_CDDA_FS_UTILS_H__
28#include "AppleCDDAFileSystemUtils.h"
29#endif
30
31#ifndef __APPLE_CDDA_FS_DEBUG_H__
32#include "AppleCDDAFileSystemDebug.h"
33#endif
34
35// System Includes
36#include <libkern/c++/OSData.h>
37#include <libkern/c++/OSObject.h>
38#include <libkern/c++/OSIterator.h>
39#include <libkern/c++/OSDictionary.h>
40#include <IOKit/IOLib.h>
41#include <IOKit/IOService.h>
42#include <IOKit/storage/IOCDMedia.h>
43#include <IOKit/IORegistryEntry.h>
44
45
46//-----------------------------------------------------------------------------
47//	Static Function Prototypes
48//-----------------------------------------------------------------------------
49
50
51static QTOCDataFormat10Ptr	CreateBufferFromData 		( OSData * theData );
52static IOCDMedia *			GetCDMediaObjectFromName 	( const char * ioBSDNamePtr );
53
54
55//-----------------------------------------------------------------------------
56//	CreateBufferFromIORegistry - Allocates memory for a C-string and copies
57//								the contents of the IORegistryEntry to it.
58//
59//	NB:	The calling function should dispose of the memory by calling IOFree
60//-----------------------------------------------------------------------------
61
62QTOCDataFormat10Ptr
63CreateBufferFromIORegistry ( mount_t mountPtr )
64{
65
66	QTOCDataFormat10Ptr		TOCDataPtr			= NULL;
67	OSObject *				objectPtr			= NULL;
68	OSData *				dataPtr				= NULL;
69	IOCDMedia *				cdMediaPtr			= NULL;
70	char *					ioBSDNamePtr		= NULL;
71
72	DebugLog ( ( "CreateBufferFromIORegistry: Entering...\n" ) );
73
74	DebugAssert ( ( mountPtr != NULL ) );
75
76	ioBSDNamePtr = vfs_statfs ( mountPtr )->f_mntfromname;
77	DebugAssert ( ( ioBSDNamePtr != NULL ) );
78
79	cdMediaPtr = GetCDMediaObjectFromName ( ioBSDNamePtr );
80	DebugAssert ( ( cdMediaPtr != NULL ) );
81
82	if ( cdMediaPtr != NULL )
83	{
84
85		// Get the TOC property
86		objectPtr = cdMediaPtr->getProperty ( kIOCDMediaTOCKey );
87		if ( objectPtr == NULL )
88		{
89
90			DebugLog ( ( "CreateBufferFromIORegistry: objectPtr is NULL.\n" ) );
91			return NULL;
92
93		}
94
95		// Cast it to an OSData *
96		dataPtr = OSDynamicCast ( OSData, objectPtr );
97		if ( dataPtr == NULL )
98		{
99
100			DebugLog ( ( "CreateBufferFromIORegistry: dataPtr is NULL.\n" ) );
101			return NULL;
102
103		}
104
105		// Get the data from the registry entry
106		TOCDataPtr = CreateBufferFromData ( dataPtr );
107
108		DebugLog ( ( "Releasing refcsount on IOCDMedia.\n" ) );
109		cdMediaPtr->release ( );
110
111	}
112
113	DebugLog ( ( "CreateBufferFromIORegistry: exiting...\n" ) );
114
115	return TOCDataPtr;
116
117}
118
119
120//-----------------------------------------------------------------------------
121//	DisposeBufferFromIORegistry - Frees memory occupied by data structure
122//-----------------------------------------------------------------------------
123
124void
125DisposeBufferFromIORegistry ( QTOCDataFormat10Ptr TOCDataPtr )
126{
127
128	DebugLog ( ( "DisposeBufferFromIORegistry: Entering...\n" ) );
129
130	DebugAssert ( ( TOCDataPtr != NULL ) );
131
132	// Free the correct number of bytes. The TOCData has a length word
133	// for its first field, so we free the number of bytes specified by
134	// the length word, plus the length word itself.
135	IOFree ( TOCDataPtr,
136			( OSSwapBigToHostInt16 ( TOCDataPtr->TOCDataLength ) + sizeof ( TOCDataPtr->TOCDataLength ) ) );
137
138	DebugLog ( ( "DisposeBufferFromIORegistry: Exiting...\n" ) );
139
140}
141
142#if 0
143#pragma mark -
144#endif
145
146
147//-----------------------------------------------------------------------------
148//	CreateBufferFromData - 	Allocates memory for a C-string and copies
149//							the contents of the IORegistryEntry to it.
150//
151//	NB:	The calling function should dispose of the memory by calling IOFree
152//-----------------------------------------------------------------------------
153
154QTOCDataFormat10Ptr
155CreateBufferFromData ( OSData * theData )
156{
157
158	vm_size_t          		bufferLength	= 0;
159	QTOCDataFormat10Ptr		buffer			= NULL;
160
161	DebugLog ( ( "CreateBufferFromData: Entering...\n" ) );
162
163	DebugAssert ( ( theData != NULL ) );
164
165	if ( theData == NULL )
166	{
167
168		DebugLog ( ( "CreateBufferFromData: theData is NULL.\n" ) );
169		return NULL;
170
171	}
172
173	bufferLength = theData->getLength ( );
174	buffer		 = ( QTOCDataFormat10Ptr ) IOMalloc ( bufferLength );
175
176	if ( buffer != NULL )
177	{
178
179		// Copy the bytes into the buffer
180		bcopy ( theData->getBytesNoCopy ( ), buffer, bufferLength );
181
182	}
183
184	DebugLog ( ( "CreateBufferFromData: exiting.\n" ) );
185
186	return buffer;
187
188}
189
190
191//-----------------------------------------------------------------------------
192//	GetCDMediaObjectFromName - 	Uses the BSD name to get a reference to the
193//								corresponding IOCDMedia object
194//-----------------------------------------------------------------------------
195
196IOCDMedia *
197GetCDMediaObjectFromName ( const char * ioBSDNamePtr )
198{
199
200	OSIterator *		iteratorPtr			= NULL;
201	IORegistryEntry *	registryEntryPtr	= NULL;
202	IOCDMedia *			objectPtr			= NULL;
203	OSDictionary *		matchingDictPtr		= NULL;
204
205	DebugLog ( ( "GetCDMediaObjectFromName: Entering...\n" ) );
206
207	DebugAssert ( ( ioBSDNamePtr != NULL ) );
208
209	DebugLog ( ( "GetCDMediaObjectFromName: On enter ioBSDNamePtr = %s.\n", ioBSDNamePtr ) );
210
211	// Check to see if we need to strip off any leading stuff
212	if ( !strncmp ( ioBSDNamePtr, "/dev/r", 6 ) )
213	{
214
215		// Strip off the /dev/r from /dev/rdiskX
216		ioBSDNamePtr = &ioBSDNamePtr[6];
217
218	}
219
220	else if ( !strncmp ( ioBSDNamePtr, "/dev/", 5 ) )
221	{
222
223		// Strip off the /dev/ from /dev/diskX
224		ioBSDNamePtr = &ioBSDNamePtr[5];
225
226	}
227
228	if ( strncmp ( ioBSDNamePtr, "disk", 4 ) )
229	{
230
231		// Not in correct format, return NULL
232		DebugLog ( ( "GetCDMediaObjectFromName: not in correct format, ioBSDNamePtr = %s.\n", ioBSDNamePtr ) );
233
234		return NULL;
235
236	}
237
238	DebugLog ( ( "GetCDMediaObjectFromName: ioBSDNamePtr = %s.\n", ioBSDNamePtr ) );
239
240	// Get a dictionary which describes the bsd device
241	matchingDictPtr = IOBSDNameMatching ( ioBSDNamePtr );
242
243	// Get an iterator of registry entries
244	iteratorPtr = IOService::getMatchingServices ( matchingDictPtr );
245	if ( iteratorPtr == NULL )
246	{
247
248		DebugLog ( ( "GetCDMediaObjectFromName: iteratorPtr is NULL.\n" ) );
249		return NULL;
250
251	}
252
253	// Release the dictionary
254	matchingDictPtr->release ( );
255
256	DebugLog ( ( "Acquired refcount on iterator and media.\n" ) );
257
258	// Get the object out of the iterator (NB: we're guaranteed only one object in the iterator
259	// because there is a 1:1 correspondence between BSD Names for devices and IOKit objects
260	registryEntryPtr = ( IORegistryEntry * ) iteratorPtr->getNextObject ( );
261	if ( registryEntryPtr == NULL )
262	{
263
264		DebugLog ( ( "GetCDMediaObjectFromName: registryEntryPtr is NULL.\n" ) );
265		return NULL;
266
267	}
268
269	// Cast it to the correct type
270	objectPtr = OSDynamicCast ( IOCDMedia, registryEntryPtr );
271	if ( objectPtr == NULL )
272	{
273
274		// Cast failed...spew an error
275		DebugLog ( ( "GetCDMediaObjectFromName: objectPtr is NULL, Dynamic Cast failed.\n" ) );
276
277	}
278
279	DebugLog ( ( "GetCDMediaObjectFromName: exiting...\n" ) );
280
281	// Bump the refcount on the CDMedia so that when we release the iterator
282	// we still have a refcount on it.
283	if ( objectPtr != NULL )
284	{
285
286		objectPtr->retain ( );
287
288	}
289
290	// Release the iterator
291	iteratorPtr->release ( );
292
293	return ( objectPtr );
294
295}
296
297
298//-----------------------------------------------------------------------------
299//				End				Of			File
300//-----------------------------------------------------------------------------
301