]> git.saurik.com Git - apple/hfs.git/blob - core/hfs_iokit.cpp
ac9a43df100d0be08a1d14301dfe21c92b5c53b5
[apple/hfs.git] / core / hfs_iokit.cpp
1 /*
2 * Copyright (c) 2015 Apple 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 #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>
36
37 #include "hfs_iokit.h"
38 #include "hfs.h"
39 #include "hfs_dbg.h"
40
41 #ifndef panic_on_assert
42 bool panic_on_assert;
43 #endif
44
45 #if DEBUG
46 bool hfs_corruption_panics = true;
47 #endif
48
49 class com_apple_filesystems_hfs : public IOService {
50 OSDeclareDefaultStructors(com_apple_filesystems_hfs)
51
52 public:
53
54 bool start(IOService *provider) override;
55 void stop(IOService *provider) override;
56
57 protected:
58 vfstable_t vfs_handle;
59 };
60
61 #define super IOService
62 OSDefineMetaClassAndStructors(com_apple_filesystems_hfs, IOService)
63
64 extern struct vnodeopv_desc hfs_vnodeop_opv_desc;
65 #if CONFIG_HFS_STD
66 extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc;
67 #endif
68 extern struct vnodeopv_desc hfs_specop_opv_desc;
69 extern struct vnodeopv_desc hfs_fifoop_opv_desc;
70 extern struct vfsops hfs_vfsops;
71
72 bool com_apple_filesystems_hfs::start(IOService *provider)
73 {
74 if (!super::start(provider))
75 return false;
76
77 #ifndef panic_on_assert
78 panic_on_assert = PE_i_can_has_kernel_configuration() & kPEICanHasAssertions;
79 #endif
80
81 #if DEBUG
82 PE_parse_boot_argn("hfs_corruption_panics", &hfs_corruption_panics, sizeof(hfs_corruption_panics));
83 #endif
84
85 struct vnodeopv_desc *op_descs[] = {
86 &hfs_vnodeop_opv_desc,
87 #if CONFIG_HFS_STD
88 &hfs_std_vnodeop_opv_desc,
89 #endif
90 &hfs_specop_opv_desc,
91 #if FIFO
92 &hfs_fifoop_opv_desc,
93 #endif
94 };
95
96 #define lengthof(x) (sizeof(x)/sizeof(*x))
97
98 #ifndef VFS_TBLVNOP_SECLUDE_RENAME
99 #define VFS_TBLVNOP_SECLUDE_RENAME 0
100 #endif
101
102 struct vfs_fsentry vfe = {
103 .vfe_vfsops = &hfs_vfsops,
104 .vfe_vopcnt = lengthof(op_descs),
105 .vfe_opvdescs = op_descs,
106 .vfe_fsname = "hfs",
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)
111 };
112
113 int ret = vfs_fsadd(&vfe, &vfs_handle);
114
115 if (ret) {
116 printf("hfs: vfs_fsadd failed: %d!\n", ret);
117 vfs_handle = NULL;
118 return false;
119 }
120
121 hfs_sysctl_register();
122
123 return true;
124 }
125
126 void com_apple_filesystems_hfs::stop(IOService *provider)
127 {
128 if (vfs_handle) {
129 vfs_fsremove(vfs_handle);
130 hfs_sysctl_unregister();
131 vfs_handle = NULL;
132 }
133
134 super::stop(provider);
135 }
136
137 int hfs_is_ejectable(const char *cdev_name)
138 {
139 int ret = 0;
140 OSDictionary *dictionary;
141 OSString *dev_name;
142
143 if (strncmp(cdev_name, "/dev/", 5) == 0) {
144 cdev_name += 5;
145 }
146
147 dictionary = IOService::serviceMatching("IOMedia");
148 if( dictionary ) {
149 dev_name = OSString::withCString( cdev_name );
150 if( dev_name ) {
151 IOService *service;
152 mach_timespec_t tv = { 5, 0 }; // wait up to "timeout" seconds for the device
153
154 dictionary->setObject(kIOBSDNameKey, dev_name);
155 dictionary->retain();
156 service = IOService::waitForService(dictionary, &tv);
157 if( service ) {
158 OSBoolean *ejectable = (OSBoolean *)service->getProperty("Ejectable");
159
160 if( ejectable ) {
161 ret = (int)ejectable->getValue();
162 }
163
164 }
165 dev_name->release();
166 }
167 dictionary->release();
168 }
169
170 return ret;
171 }
172
173 void hfs_iterate_media_with_content(const char *content_uuid_cstring,
174 int (*func)(const char *device,
175 const char *uuid_str,
176 void *arg),
177 void *arg)
178 {
179 OSDictionary *dictionary;
180 OSString *content_uuid_string;
181
182 dictionary = IOService::serviceMatching("IOMedia");
183 if (dictionary) {
184 content_uuid_string = OSString::withCString(content_uuid_cstring);
185 if (content_uuid_string) {
186 IOService *service;
187 OSIterator *iter;
188
189 dictionary->setObject("Content", content_uuid_string);
190 dictionary->retain();
191
192 iter = IOService::getMatchingServices(dictionary);
193 while (iter && (service = (IOService *)iter->getNextObject())) {
194 if (service) {
195 OSString *iostr = (OSString *) service->getProperty(kIOBSDNameKey);
196 OSString *uuidstr = (OSString *)service->getProperty("UUID");
197 const char *uuid;
198
199 if (iostr) {
200 if (uuidstr) {
201 uuid = uuidstr->getCStringNoCopy();
202 } else {
203 uuid = "00000000-0000-0000-0000-000000000000";
204 }
205
206 if (!func(iostr->getCStringNoCopy(), uuid, arg))
207 break;
208 }
209 }
210 }
211 if (iter)
212 iter->release();
213
214 content_uuid_string->release();
215 }
216 dictionary->release();
217 }
218 }
219
220 kern_return_t hfs_get_platform_serial_number(char *serial_number_str,
221 uint32_t len)
222 {
223 OSDictionary * platform_dict;
224 IOService *platform;
225 OSString * string;
226
227 if (len < 1) {
228 return 0;
229 }
230 serial_number_str[0] = '\0';
231
232 platform_dict = IOService::serviceMatching( "IOPlatformExpertDevice" );
233 if (platform_dict == NULL) {
234 return KERN_NOT_SUPPORTED;
235 }
236
237 platform = IOService::waitForService( platform_dict );
238 if (platform) {
239 string = (OSString *)platform->getProperty(kIOPlatformSerialNumberKey);
240 if (string == 0) {
241 return KERN_NOT_SUPPORTED;
242 } else {
243 strlcpy( serial_number_str, string->getCStringNoCopy(), len);
244 }
245 }
246
247 return KERN_SUCCESS;
248 }
249
250 // Interface with AKS
251
252 static aks_file_system_key_services_t *
253 key_services(void)
254 {
255 static aks_file_system_key_services_t *g_key_services;
256
257 if (!g_key_services) {
258 IOService *platform = IOService::getPlatform();
259 if (platform) {
260 IOReturn ret = platform->callPlatformFunction
261 (kAKSFileSystemKeyServices, true, &g_key_services, NULL, NULL, NULL);
262 if (ret)
263 printf("hfs: unable to get " kAKSFileSystemKeyServices " (0x%x)\n", ret);
264 }
265 }
266
267 return g_key_services;
268 }
269
270 int hfs_unwrap_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
271 aks_raw_key_t key_out)
272 {
273 aks_file_system_key_services_t *ks = key_services();
274 if (!ks || !ks->unwrap_key)
275 return ENXIO;
276 return ks->unwrap_key(access, wrapped_key_in, key_out);
277 }
278
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)
282 {
283 aks_file_system_key_services_t *ks = key_services();
284 if (!ks || !ks->rewrap_key)
285 return ENXIO;
286 return ks->rewrap_key(access, dp_class, wrapped_key_in, wrapped_key_out);
287 }
288
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)
291 {
292 aks_file_system_key_services_t *ks = key_services();
293 if (!ks || !ks->new_key)
294 return ENXIO;
295 return ks->new_key(access, dp_class, key_out, wrapped_key_out);
296 }
297
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)
300 {
301 aks_file_system_key_services_t *ks = key_services();
302 if (!ks || !ks->backup_key)
303 return ENXIO;
304 return ks->backup_key(access, wrapped_key_in, wrapped_key_out);
305 }