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"
40 #include "hfs_cnode.h"
42 #ifndef panic_on_assert
47 bool hfs_corruption_panics
= true;
50 class com_apple_filesystems_hfs
: public IOService
{
51 OSDeclareDefaultStructors(com_apple_filesystems_hfs
)
55 bool start(IOService
*provider
) override
;
56 void stop(IOService
*provider
) override
;
59 vfstable_t vfs_handle
;
62 #define super IOService
63 OSDefineMetaClassAndStructors(com_apple_filesystems_hfs
, IOService
)
65 extern struct vnodeopv_desc hfs_vnodeop_opv_desc
;
67 extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc
;
69 extern struct vnodeopv_desc hfs_specop_opv_desc
;
70 extern struct vnodeopv_desc hfs_fifoop_opv_desc
;
71 extern struct vfsops hfs_vfsops
;
73 bool com_apple_filesystems_hfs::start(IOService
*provider
)
75 if (!super::start(provider
))
78 #ifndef panic_on_assert
79 panic_on_assert
= PE_i_can_has_kernel_configuration() & kPEICanHasAssertions
;
83 PE_parse_boot_argn("hfs_corruption_panics", &hfs_corruption_panics
, sizeof(hfs_corruption_panics
));
86 struct vnodeopv_desc
*op_descs
[] = {
87 &hfs_vnodeop_opv_desc
,
89 &hfs_std_vnodeop_opv_desc
,
97 #define lengthof(x) (sizeof(x)/sizeof(*x))
99 #ifndef VFS_TBLVNOP_SECLUDE_RENAME
100 #define VFS_TBLVNOP_SECLUDE_RENAME 0
103 struct vfs_fsentry vfe
= {
104 .vfe_vfsops
= &hfs_vfsops
,
105 .vfe_vopcnt
= lengthof(op_descs
),
106 .vfe_opvdescs
= op_descs
,
108 .vfe_flags
= (VFS_TBLNOTYPENUM
| VFS_TBLLOCALVOL
| VFS_TBLREADDIR_EXTENDED
109 | VFS_TBL64BITREADY
| VFS_TBLVNOP_PAGEOUTV2
| VFS_TBLVNOP_PAGEINV2
110 | VFS_TBLTHREADSAFE
| VFS_TBLCANMOUNTROOT
| VFS_TBLVNOP_SECLUDE_RENAME
111 | VFS_TBLNATIVEXATTR
)
114 int ret
= vfs_fsadd(&vfe
, &vfs_handle
);
117 printf("hfs: vfs_fsadd failed: %d!\n", ret
);
124 hfs_sysctl_register();
127 size_t sz
= sizeof(num_cpus
);
129 if (sysctlbyname("hw.physicalcpu", &num_cpus
, &sz
, NULL
, 0) == 0) {
130 if ((2 * num_cpus
) > MAX_CACHED_ORIGINS_DEFAULT
) {
131 _hfs_max_origins
= 2 * num_cpus
;
132 _hfs_max_file_origins
= 2 * num_cpus
;
133 } else if ((2 * num_cpus
) > MAX_CACHED_FILE_ORIGINS_DEFAULT
) {
134 _hfs_max_file_origins
= 2 * num_cpus
;
141 void com_apple_filesystems_hfs::stop(IOService
*provider
)
144 vfs_fsremove(vfs_handle
);
145 hfs_sysctl_unregister();
149 super::stop(provider
);
152 int hfs_is_ejectable(const char *cdev_name
)
155 OSDictionary
*dictionary
;
158 if (strncmp(cdev_name
, "/dev/", 5) == 0) {
162 dictionary
= IOService::serviceMatching("IOMedia");
164 dev_name
= OSString::withCString( cdev_name
);
167 mach_timespec_t tv
= { 5, 0 }; // wait up to "timeout" seconds for the device
169 dictionary
->setObject(kIOBSDNameKey
, dev_name
);
170 dictionary
->retain();
171 service
= IOService::waitForService(dictionary
, &tv
);
173 OSBoolean
*ejectable
= (OSBoolean
*)service
->getProperty("Ejectable");
176 ret
= (int)ejectable
->getValue();
182 dictionary
->release();
188 void hfs_iterate_media_with_content(const char *content_uuid_cstring
,
189 int (*func
)(const char *device
,
190 const char *uuid_str
,
194 OSDictionary
*dictionary
;
195 OSString
*content_uuid_string
;
197 dictionary
= IOService::serviceMatching("IOMedia");
199 content_uuid_string
= OSString::withCString(content_uuid_cstring
);
200 if (content_uuid_string
) {
204 dictionary
->setObject("Content", content_uuid_string
);
205 dictionary
->retain();
207 iter
= IOService::getMatchingServices(dictionary
);
208 while (iter
&& (service
= (IOService
*)iter
->getNextObject())) {
210 OSString
*iostr
= (OSString
*) service
->getProperty(kIOBSDNameKey
);
211 OSString
*uuidstr
= (OSString
*)service
->getProperty("UUID");
216 uuid
= uuidstr
->getCStringNoCopy();
218 uuid
= "00000000-0000-0000-0000-000000000000";
221 if (!func(iostr
->getCStringNoCopy(), uuid
, arg
))
229 content_uuid_string
->release();
231 dictionary
->release();
235 kern_return_t
hfs_get_platform_serial_number(char *serial_number_str
,
238 OSDictionary
* platform_dict
;
245 serial_number_str
[0] = '\0';
247 platform_dict
= IOService::serviceMatching( "IOPlatformExpertDevice" );
248 if (platform_dict
== NULL
) {
249 return KERN_NOT_SUPPORTED
;
252 platform
= IOService::waitForService( platform_dict
);
254 string
= (OSString
*)platform
->getProperty(kIOPlatformSerialNumberKey
);
256 return KERN_NOT_SUPPORTED
;
258 strlcpy( serial_number_str
, string
->getCStringNoCopy(), len
);
265 // Interface with AKS
267 static aks_file_system_key_services_t
*
270 static aks_file_system_key_services_t
*g_key_services
;
272 if (!g_key_services
) {
273 IOService
*platform
= IOService::getPlatform();
275 IOReturn ret
= platform
->callPlatformFunction
276 (kAKSFileSystemKeyServices
, true, &g_key_services
, NULL
, NULL
, NULL
);
278 printf("hfs: unable to get " kAKSFileSystemKeyServices
" (0x%x)\n", ret
);
282 return g_key_services
;
285 int hfs_unwrap_key(aks_cred_t access
, const aks_wrapped_key_t wrapped_key_in
,
286 aks_raw_key_t key_out
)
288 aks_file_system_key_services_t
*ks
= key_services();
289 if (!ks
|| !ks
->unwrap_key
)
291 return ks
->unwrap_key(access
, wrapped_key_in
, key_out
);
294 int hfs_rewrap_key(aks_cred_t access
, cp_key_class_t dp_class
,
295 const aks_wrapped_key_t wrapped_key_in
,
296 aks_wrapped_key_t wrapped_key_out
)
298 aks_file_system_key_services_t
*ks
= key_services();
299 if (!ks
|| !ks
->rewrap_key
)
301 return ks
->rewrap_key(access
, dp_class
, wrapped_key_in
, wrapped_key_out
);
304 int hfs_new_key(aks_cred_t access
, cp_key_class_t dp_class
,
305 aks_raw_key_t key_out
, aks_wrapped_key_t wrapped_key_out
)
307 aks_file_system_key_services_t
*ks
= key_services();
308 if (!ks
|| !ks
->new_key
)
310 return ks
->new_key(access
, dp_class
, key_out
, wrapped_key_out
);
313 int hfs_backup_key(aks_cred_t access
, const aks_wrapped_key_t wrapped_key_in
,
314 aks_wrapped_key_t wrapped_key_out
)
316 aks_file_system_key_services_t
*ks
= key_services();
317 if (!ks
|| !ks
->backup_key
)
319 return ks
->backup_key(access
, wrapped_key_in
, wrapped_key_out
);