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
);
123 hfs_sysctl_register();
128 void com_apple_filesystems_hfs::stop(IOService
*provider
)
131 vfs_fsremove(vfs_handle
);
132 hfs_sysctl_unregister();
136 super::stop(provider
);
139 int hfs_is_ejectable(const char *cdev_name
)
142 OSDictionary
*dictionary
;
145 if (strncmp(cdev_name
, "/dev/", 5) == 0) {
149 dictionary
= IOService::serviceMatching("IOMedia");
151 dev_name
= OSString::withCString( cdev_name
);
154 mach_timespec_t tv
= { 5, 0 }; // wait up to "timeout" seconds for the device
156 dictionary
->setObject(kIOBSDNameKey
, dev_name
);
157 dictionary
->retain();
158 service
= IOService::waitForService(dictionary
, &tv
);
160 OSBoolean
*ejectable
= (OSBoolean
*)service
->getProperty("Ejectable");
163 ret
= (int)ejectable
->getValue();
169 dictionary
->release();
175 void hfs_iterate_media_with_content(const char *content_uuid_cstring
,
176 int (*func
)(const char *device
,
177 const char *uuid_str
,
181 OSDictionary
*dictionary
;
182 OSString
*content_uuid_string
;
184 dictionary
= IOService::serviceMatching("IOMedia");
186 content_uuid_string
= OSString::withCString(content_uuid_cstring
);
187 if (content_uuid_string
) {
191 dictionary
->setObject("Content", content_uuid_string
);
192 dictionary
->retain();
194 iter
= IOService::getMatchingServices(dictionary
);
195 while (iter
&& (service
= (IOService
*)iter
->getNextObject())) {
197 OSString
*iostr
= (OSString
*) service
->getProperty(kIOBSDNameKey
);
198 OSString
*uuidstr
= (OSString
*)service
->getProperty("UUID");
203 uuid
= uuidstr
->getCStringNoCopy();
205 uuid
= "00000000-0000-0000-0000-000000000000";
208 if (!func(iostr
->getCStringNoCopy(), uuid
, arg
))
216 content_uuid_string
->release();
218 dictionary
->release();
222 kern_return_t
hfs_get_platform_serial_number(char *serial_number_str
,
225 OSDictionary
* platform_dict
;
232 serial_number_str
[0] = '\0';
234 platform_dict
= IOService::serviceMatching( "IOPlatformExpertDevice" );
235 if (platform_dict
== NULL
) {
236 return KERN_NOT_SUPPORTED
;
239 platform
= IOService::waitForService( platform_dict
);
241 string
= (OSString
*)platform
->getProperty(kIOPlatformSerialNumberKey
);
243 return KERN_NOT_SUPPORTED
;
245 strlcpy( serial_number_str
, string
->getCStringNoCopy(), len
);
252 // Interface with AKS
254 static aks_file_system_key_services_t
*
257 static aks_file_system_key_services_t
*g_key_services
;
259 if (!g_key_services
) {
260 IOService
*platform
= IOService::getPlatform();
262 IOReturn ret
= platform
->callPlatformFunction
263 (kAKSFileSystemKeyServices
, true, &g_key_services
, NULL
, NULL
, NULL
);
265 printf("hfs: unable to get " kAKSFileSystemKeyServices
" (0x%x)\n", ret
);
269 return g_key_services
;
272 int hfs_unwrap_key(aks_cred_t access
, const aks_wrapped_key_t wrapped_key_in
,
273 aks_raw_key_t key_out
)
275 aks_file_system_key_services_t
*ks
= key_services();
276 if (!ks
|| !ks
->unwrap_key
)
278 return ks
->unwrap_key(access
, wrapped_key_in
, key_out
);
281 int hfs_rewrap_key(aks_cred_t access
, cp_key_class_t dp_class
,
282 const aks_wrapped_key_t wrapped_key_in
,
283 aks_wrapped_key_t wrapped_key_out
)
285 aks_file_system_key_services_t
*ks
= key_services();
286 if (!ks
|| !ks
->rewrap_key
)
288 return ks
->rewrap_key(access
, dp_class
, wrapped_key_in
, wrapped_key_out
);
291 int hfs_new_key(aks_cred_t access
, cp_key_class_t dp_class
,
292 aks_raw_key_t key_out
, aks_wrapped_key_t wrapped_key_out
)
294 aks_file_system_key_services_t
*ks
= key_services();
295 if (!ks
|| !ks
->new_key
)
297 return ks
->new_key(access
, dp_class
, key_out
, wrapped_key_out
);
300 int hfs_backup_key(aks_cred_t access
, const aks_wrapped_key_t wrapped_key_in
,
301 aks_wrapped_key_t wrapped_key_out
)
303 aks_file_system_key_services_t
*ks
= key_services();
304 if (!ks
|| !ks
->backup_key
)
306 return ks
->backup_key(access
, wrapped_key_in
, wrapped_key_out
);