1/* 2 * Copyright (c) 2002-2006 Apple Computer, 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 * DINetBootHook.c 30 * DiskImages 31 * 32 * Created by Byron Han on Sat Apr 13 2002. 33 * 34 * Revision History 35 * 36 * $Log: DINetBootHook.cpp,v $ 37 * Revision 1.4 2005/07/29 21:49:57 lindak 38 * Merge of branch "chardonnay" to pick up all chardonnay changes in Leopard 39 * as of xnu-792.7.4 40 * 41 * Revision 1.3.1558.1 2005/06/24 01:47:25 lindak 42 * Bringing over all of the Karma changes into chardonnay. 43 * 44 * Revision 1.1.1.1 2005/02/24 21:48:06 akosut 45 * Import xnu-764 from Tiger8A395 46 * 47 * Revision 1.3 2002/06/16 20:36:02 lindak 48 * Merged PR-2957314 into Jaguar (siegmund: netboot kernel code needs to set 49 * com.apple.AppleDiskImageController.load to boolean Yes) 50 * 51 * Revision 1.2.40.2 2002/06/15 03:50:38 dieter 52 * - corrected com.apple.AppleDiskImageController.load string 53 * 54 * Revision 1.2.40.1 2002/06/15 03:01:08 dieter 55 * Bug #: 2957314 56 * - add call to force IOHDIXController to get loaded/matched 57 * 58 * Revision 1.2 2002/05/03 18:08:39 lindak 59 * Merged PR-2909558 into Jaguar (siegmund POST WWDC: add support for NetBoot 60 * over IOHDIXController) 61 * 62 * Revision 1.1.2.1 2002/04/24 22:29:12 dieter 63 * Bug #: 2909558 64 * - added IOHDIXController netboot stubs 65 * 66 * Revision 1.3 2002/04/16 00:41:37 han 67 * migrated code out of here to IOHDIXController's setProperty method 68 * 69 * Revision 1.2 2002/04/14 23:53:53 han 70 * eliminate qDEBUG=1, use emums instead of hard coded string constants 71 * 72 * Revision 1.1 2002/04/14 22:54:42 han 73 * Renamed from DINetBookHook.c. 74 * First stab at implementing this code. 75 * 76 * Revision 1.1 2002/04/13 19:22:28 han 77 * added stub file DINetBookHook.c 78 * 79 * 80 */ 81#ifndef qDEBUG 82#define qDEBUG 0 83#endif 84 85#if qDEBUG 86#warning qDEBUG is 1! 87#endif 88 89#include <sys/types.h> 90#include <IOKit/IOService.h> 91#include <IOKit/IOLib.h> 92 93#define kIOHDIXControllerClassName "IOHDIXController" 94#define kDIRootImageKey "di-root-image" 95#define kDIRootImageResultKey "di-root-image-result" 96#define kDIRootImageDevNameKey "di-root-image-devname" 97#define kDIRootImageDevTKey "di-root-image-devt" 98#define kDIRootRamFileKey "di-root-ram-file" 99 100static IOService * 101di_load_controller( void ) 102{ 103 OSIterator * controllerIterator = 0; 104 OSDictionary * matchDictionary = 0; 105 IOService * controller = 0; 106 107 do { 108 IOService::getResourceService()->publishResource("com.apple.AppleDiskImageController.load", kOSBooleanTrue); 109 IOService::getResourceService()->waitQuiet(); 110 111 // first find IOHDIXController 112 matchDictionary = IOService::serviceMatching(kIOHDIXControllerClassName); 113 if (!matchDictionary) 114 break; 115 116 controllerIterator = IOService::getMatchingServices(matchDictionary); 117 if (!controllerIterator) 118 break; 119 120 controller = OSDynamicCast(IOService, controllerIterator->getNextObject()); 121 if (!controller) 122 break; 123 124 controller->retain(); 125 } while (false); 126 127 if (matchDictionary) matchDictionary->release(); 128 if (controllerIterator) controllerIterator->release(); 129 130 return controller; 131} 132 133extern "C" { 134/* 135 Name: di_root_image 136 Function: mount the disk image returning the dev node 137 Parameters: path -> path/url to disk image 138 devname <- dev node used to set the rootdevice global variable 139 dev_p <- device number generated from major/minor numbers 140 Comments: 141*/ 142int di_root_image(const char *path, char devname[], dev_t *dev_p) 143{ 144 IOReturn res = 0; 145 IOService * controller = 0; 146 OSString * pathString = 0; 147 OSNumber * myResult = 0; 148 OSString * myDevName = 0; 149 OSNumber * myDevT = 0; 150 151 // sanity check arguments please 152 if (devname) *devname = 0; 153 if (dev_p) *dev_p = 0; 154 155 if (!path) return kIOReturnBadArgument; 156 if (!devname) return kIOReturnBadArgument; 157 if (!dev_p) return kIOReturnBadArgument; 158 159 controller = di_load_controller(); 160 if (!controller) { 161 res = kIOReturnNotFound; 162 goto NoIOHDIXController; 163 } 164 165 // okay create path object 166 pathString = OSString::withCString(path); 167 if (!pathString) { 168 res = kIOReturnNoMemory; 169 goto CannotCreatePathOSString; 170 } 171 172 // do it 173 if (!controller->setProperty(kDIRootImageKey, pathString)) 174 IOLog("IOHDIXController::setProperty(%s, %s) failed.\n", kDIRootImageKey, pathString->getCStringNoCopy()); 175 176 myResult = OSDynamicCast(OSNumber, controller->getProperty(kDIRootImageResultKey)); 177 res = kIOReturnError; 178 if (myResult) 179 res = myResult->unsigned32BitValue(); 180 181 if (res) { 182 IOLog("%s is 0x%08X/%d\n", kDIRootImageResultKey, res, res); 183 goto di_root_image_FAILED; 184 } 185 186 // success - grab 187 myDevT = OSDynamicCast(OSNumber, controller->getProperty(kDIRootImageDevTKey)); 188 if (myDevT) 189 *dev_p = myDevT->unsigned32BitValue(); 190 else { 191 IOLog("could not get %s\n", kDIRootImageDevTKey); 192 res = kIOReturnError; 193 goto di_root_image_FAILED; 194 } 195 196 myDevName = OSDynamicCast(OSString, controller->getProperty(kDIRootImageDevNameKey)); 197 if (myDevName) { 198 /* rootdevice is 16 chars in bsd_init.c */ 199 strlcpy(devname, myDevName->getCStringNoCopy(), 16); 200 } else { 201 IOLog("could not get %s\n", kDIRootImageDevNameKey); 202 res = kIOReturnError; 203 goto di_root_image_FAILED; 204 } 205 206 207di_root_image_FAILED: 208CannotCreatePathOSString: 209NoIOHDIXController: 210 211 // clean up memory allocations 212 if (pathString) pathString->release(); 213 if (controller) controller->release(); 214 215 return res; 216} 217 218void di_root_ramfile( IORegistryEntry * entry ) 219{ 220 OSData * data; 221 IOMemoryDescriptor * mem; 222 uint64_t dmgSize; 223 uint64_t remain, length; 224 OSData * extentData = 0; 225 IOAddressRange * extentList; 226 uint64_t extentSize; 227 uint32_t extentCount; 228 229 do { 230 data = OSDynamicCast(OSData, entry->getProperty("boot-ramdmg-size")); 231 if (!data || (data->getLength() != sizeof(uint64_t))) 232 break; // bad disk image size 233 234 dmgSize = *(uint64_t *) data->getBytesNoCopy(); 235 if (!dmgSize) 236 break; 237 238 data = OSDynamicCast(OSData, entry->getProperty("boot-ramdmg-extents")); 239 if (!data || (data->getLength() == 0) || 240 ((data->getLength() & (sizeof(IOAddressRange)-1)) != 0)) 241 break; // bad extents 242 243 // make modifications to local copy 244 extentData = OSData::withData(data); 245 assert(extentData); 246 247 extentList = (IOAddressRange *) extentData->getBytesNoCopy(); 248 extentCount = extentData->getLength() / sizeof(IOAddressRange); 249 extentSize = 0; 250 remain = dmgSize; 251 252 // truncate extent length to enclosing disk image 253 for (uint32_t i = 0; i < extentCount; i++) 254 { 255 length = extentList[i].length; 256 if (!length) break; 257 258 extentSize += length; 259 if (length >= remain) 260 { 261 extentList[i].length = remain; 262 extentCount = i + 1; 263 break; 264 } 265 remain -= length; 266 } 267 if (extentSize < dmgSize) 268 break; // not enough extent bytes for enclosing disk image 269 270 mem = IOMemoryDescriptor::withAddressRanges( 271 extentList, extentCount, 272 kIODirectionOut | kIOMemoryMapperNone, NULL); 273 274 if (mem) 275 { 276 IOService * controller = di_load_controller(); 277 if (controller) 278 { 279 controller->setProperty(kDIRootRamFileKey, mem); 280 controller->release(); 281 } 282 mem->release(); 283 } 284 } while (false); 285 286 if (extentData) 287 extentData->release(); 288} 289 290}; 291