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
);