+
+#if HIBERNATION
+IOReturn
+IOHibernateOpenForDebugData( )
+{
+ dev_t image_dev;
+ OSData *extentsData = NULL;
+ OSObject *obj;
+ OSString *str;
+ IOByteCount blockSize = 0;
+ IOByteCount size;
+ IOService * part = 0;
+ OSData * data = NULL;
+
+ IOPolledFileExtent * fileExtents;
+ IOReturn err = kIOReturnSuccess;
+ IORegistryEntry * regEntry;
+ OSArray * pollers = NULL;
+
+ _OpenFileContext ctx;
+
+ if (gDebugImageFileRef != NULL)
+ return kIOReturnError;
+
+ if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFileKey)))
+ {
+ if ((str = OSDynamicCast(OSString, obj)))
+ strlcpy(gIOHibernateFilename, str->getCStringNoCopy(),
+ sizeof(gIOHibernateFilename));
+ obj->release();
+ }
+
+ if (!gIOHibernateFilename[0]) {
+ HIBLOG("Failed to get hibernate image filename\n");
+ return (kIOReturnUnsupported);
+ }
+
+ extentsData = OSData::withCapacity(32);
+ ctx.extents = extentsData;
+ ctx.size = 0;
+
+ bzero(gIOHibernateCurrentHeader, sizeof(IOHibernateImageHeader));
+ gIOHibernateCurrentHeader->debugFlags = gIOHibernateDebugFlags;
+ gIOHibernateCurrentHeader->signature = kIOHibernateHeaderInvalidSignature;
+
+ gDebugImageFileRef = kern_open_file_for_direct_io(gIOHibernateFilename,
+ false,
+ &file_extent_callback, &ctx,
+ 0, 0,
+ (caddr_t)gIOHibernateCurrentHeader,
+ sizeof(IOHibernateImageHeader),
+ NULL, &image_dev, NULL, NULL, NULL);
+
+ if (gDebugImageFileRef == NULL)
+ {
+ HIBLOG("Failed to open the file \n");
+ err = kIOReturnError;
+ goto exit;
+ }
+ fileExtents = (IOPolledFileExtent *)extentsData->getBytesNoCopy();
+ size = extentsData->getLength();
+
+ part = IOCopyMediaForDev(image_dev);
+ if (!part)
+ {
+ HIBLOG("Failed to get the media device\n");
+ err = kIOReturnNotFound;
+ goto exit;
+ }
+
+
+ pollers = OSArray::withCapacity(4);
+ if (!pollers)
+ {
+ err = kIOReturnNoMemory;
+ goto exit;
+ }
+
+ err = GetImageBlockSize(part, pollers, &blockSize);
+ if (err != kIOReturnSuccess)
+ {
+ HIBLOG("Failed to get block size\n");
+ goto exit;
+ }
+ if (blockSize < sizeof(IOHibernateImageHeader))
+ {
+ HIBLOG("block size %llu is less than the size of the header\n", blockSize);
+ err = kIOReturnError;
+ goto exit;
+ }
+
+ WriteExtentsToFile(gDebugImageFileRef, kIOHibernateHeaderOpenSignature,
+ blockSize, fileExtents, size);
+
+ char str2[24 + sizeof(uuid_string_t) + 2];
+
+ if (!gIOCreateEFIDevicePathSymbol)
+ gIOCreateEFIDevicePathSymbol = OSSymbol::withCString("CreateEFIDevicePath");
+
+ snprintf(str2, sizeof(str2), "%qx", fileExtents[0].start);
+
+ err = IOService::getPlatform()->callPlatformFunction(
+ gIOCreateEFIDevicePathSymbol, false,
+ (void *) part, (void *) str2,
+ (void *) (uintptr_t) true, (void *) &data);
+
+ if (!gIOOptionsEntry)
+ {
+ regEntry = IORegistryEntry::fromPath("/options", gIODTPlane);
+ gIOOptionsEntry = OSDynamicCast(IODTNVRAM, regEntry);
+ if (regEntry && !gIOOptionsEntry)
+ regEntry->release();
+ }
+ if (gIOOptionsEntry)
+ {
+ const OSSymbol * sym;
+
+ sym = OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey);
+ if (sym)
+ {
+ gIOOptionsEntry->setProperty(sym, data);
+ sym->release();
+ }
+ }
+
+
+exit:
+
+ if ( (err != kIOReturnSuccess) && gDebugImageFileRef) {
+ kern_close_file_for_direct_io(gDebugImageFileRef, 0, 0, 0, 0, 0);
+ gDebugImageFileRef = NULL;
+ }
+ if (extentsData) extentsData->release();
+ if (part) part->release();
+ if (pollers) pollers->release();
+ if (data) data->release();
+
+ return err;
+}
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+