2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/mach_types.h>
30 #include <sys/mount.h>
31 #include <libkern/libkern.h>
32 #include <IOKit/IOService.h>
33 #include <IOKit/IOBSD.h>
34 #include <IOKit/IOKitKeys.h>
35 #include <IOKit/IOPlatformExpert.h>
37 #include "hfs_iokit.h"
41 #ifndef panic_on_assert
46 bool hfs_corruption_panics
= true;
49 class com_apple_filesystems_hfs
: public IOService
{
50 OSDeclareDefaultStructors(com_apple_filesystems_hfs
)
54 bool start(IOService
*provider
) override
;
55 void stop(IOService
*provider
) override
;
58 vfstable_t vfs_handle
;
61 #define super IOService
62 OSDefineMetaClassAndStructors(com_apple_filesystems_hfs
, IOService
)
64 extern struct vnodeopv_desc hfs_vnodeop_opv_desc
;
66 extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc
;
68 extern struct vnodeopv_desc hfs_specop_opv_desc
;
69 extern struct vnodeopv_desc hfs_fifoop_opv_desc
;
70 extern struct vfsops hfs_vfsops
;
72 bool com_apple_filesystems_hfs::start(IOService
*provider
)
74 if (!super::start(provider
))
77 #ifndef panic_on_assert
78 panic_on_assert
= PE_i_can_has_kernel_configuration() & kPEICanHasAssertions
;
82 PE_parse_boot_argn("hfs_corruption_panics", &hfs_corruption_panics
, sizeof(hfs_corruption_panics
));
85 struct vnodeopv_desc
*op_descs
[] = {
86 &hfs_vnodeop_opv_desc
,
88 &hfs_std_vnodeop_opv_desc
,
96 #define lengthof(x) (sizeof(x)/sizeof(*x))
98 #ifndef VFS_TBLVNOP_SECLUDE_RENAME
99 #define VFS_TBLVNOP_SECLUDE_RENAME 0
102 struct vfs_fsentry vfe
= {
103 .vfe_vfsops
= &hfs_vfsops
,
104 .vfe_vopcnt
= lengthof(op_descs
),
105 .vfe_opvdescs
= op_descs
,
107 .vfe_flags
= (VFS_TBLNOTYPENUM
| VFS_TBLLOCALVOL
| VFS_TBLREADDIR_EXTENDED
108 | VFS_TBL64BITREADY
| VFS_TBLVNOP_PAGEOUTV2
| VFS_TBLVNOP_PAGEINV2
109 | VFS_TBLTHREADSAFE
| VFS_TBLCANMOUNTROOT
| VFS_TBLVNOP_SECLUDE_RENAME
110 | VFS_TBLNATIVEXATTR
)
113 int ret
= vfs_fsadd(&vfe
, &vfs_handle
);
116 printf("hfs: vfs_fsadd failed: %d!\n", ret
);
121 hfs_sysctl_register();
126 void com_apple_filesystems_hfs::stop(IOService
*provider
)
129 vfs_fsremove(vfs_handle
);
130 hfs_sysctl_unregister();
134 super::stop(provider
);
137 int hfs_is_ejectable(const char *cdev_name
)
140 OSDictionary
*dictionary
;
143 if (strncmp(cdev_name
, "/dev/", 5) == 0) {
147 dictionary
= IOService::serviceMatching("IOMedia");
149 dev_name
= OSString::withCString( cdev_name
);
152 mach_timespec_t tv
= { 5, 0 }; // wait up to "timeout" seconds for the device
154 dictionary
->setObject(kIOBSDNameKey
, dev_name
);
155 dictionary
->retain();
156 service
= IOService::waitForService(dictionary
, &tv
);
158 OSBoolean
*ejectable
= (OSBoolean
*)service
->getProperty("Ejectable");
161 ret
= (int)ejectable
->getValue();
167 dictionary
->release();
173 void hfs_iterate_media_with_content(const char *content_uuid_cstring
,
174 int (*func
)(const char *device
,
175 const char *uuid_str
,
179 OSDictionary
*dictionary
;
180 OSString
*content_uuid_string
;
182 dictionary
= IOService::serviceMatching("IOMedia");
184 content_uuid_string
= OSString::withCString(content_uuid_cstring
);
185 if (content_uuid_string
) {
189 dictionary
->setObject("Content", content_uuid_string
);
190 dictionary
->retain();
192 iter
= IOService::getMatchingServices(dictionary
);
193 while (iter
&& (service
= (IOService
*)iter
->getNextObject())) {
195 OSString
*iostr
= (OSString
*) service
->getProperty(kIOBSDNameKey
);
196 OSString
*uuidstr
= (OSString
*)service
->getProperty("UUID");
201 uuid
= uuidstr
->getCStringNoCopy();
203 uuid
= "00000000-0000-0000-0000-000000000000";
206 if (!func(iostr
->getCStringNoCopy(), uuid
, arg
))
214 content_uuid_string
->release();
216 dictionary
->release();
220 kern_return_t
hfs_get_platform_serial_number(char *serial_number_str
,
223 OSDictionary
* platform_dict
;
230 serial_number_str
[0] = '\0';
232 platform_dict
= IOService::serviceMatching( "IOPlatformExpertDevice" );
233 if (platform_dict
== NULL
) {
234 return KERN_NOT_SUPPORTED
;
237 platform
= IOService::waitForService( platform_dict
);
239 string
= (OSString
*)platform
->getProperty(kIOPlatformSerialNumberKey
);
241 return KERN_NOT_SUPPORTED
;
243 strlcpy( serial_number_str
, string
->getCStringNoCopy(), len
);
250 // Interface with AKS
252 static aks_file_system_key_services_t
*
255 static aks_file_system_key_services_t
*g_key_services
;
257 if (!g_key_services
) {
258 IOService
*platform
= IOService::getPlatform();
260 IOReturn ret
= platform
->callPlatformFunction
261 (kAKSFileSystemKeyServices
, true, &g_key_services
, NULL
, NULL
, NULL
);
263 printf("hfs: unable to get " kAKSFileSystemKeyServices
" (0x%x)\n", ret
);
267 return g_key_services
;
270 int hfs_unwrap_key(aks_cred_t access
, const aks_wrapped_key_t wrapped_key_in
,
271 aks_raw_key_t key_out
)
273 aks_file_system_key_services_t
*ks
= key_services();
274 if (!ks
|| !ks
->unwrap_key
)
276 return ks
->unwrap_key(access
, wrapped_key_in
, key_out
);
279 int hfs_rewrap_key(aks_cred_t access
, cp_key_class_t dp_class
,
280 const aks_wrapped_key_t wrapped_key_in
,
281 aks_wrapped_key_t wrapped_key_out
)
283 aks_file_system_key_services_t
*ks
= key_services();
284 if (!ks
|| !ks
->rewrap_key
)
286 return ks
->rewrap_key(access
, dp_class
, wrapped_key_in
, wrapped_key_out
);
289 int hfs_new_key(aks_cred_t access
, cp_key_class_t dp_class
,
290 aks_raw_key_t key_out
, aks_wrapped_key_t wrapped_key_out
)
292 aks_file_system_key_services_t
*ks
= key_services();
293 if (!ks
|| !ks
->new_key
)
295 return ks
->new_key(access
, dp_class
, key_out
, wrapped_key_out
);
298 int hfs_backup_key(aks_cred_t access
, const aks_wrapped_key_t wrapped_key_in
,
299 aks_wrapped_key_t wrapped_key_out
)
301 aks_file_system_key_services_t
*ks
= key_services();
302 if (!ks
|| !ks
->backup_key
)
304 return ks
->backup_key(access
, wrapped_key_in
, wrapped_key_out
);