+ OSObject * obj = 0;
+ OSData * data;
+
+ IOLockLock(gFSLock);
+ if ((kFSOpened != gFSState) && gIOHibernateMode)
+ {
+ ret = kIOReturnTimeout;
+ }
+ IOLockUnlock(gFSLock);
+ if (kIOReturnSuccess != ret) return (ret);
+
+ if (gIOHibernateMode) obj = IOService::getPMRootDomain()->copyProperty(kIOHibernatePreviewBufferKey);
+ vars->previewBuffer = OSDynamicCast(IOMemoryDescriptor, obj);
+ if (obj && !vars->previewBuffer)
+ obj->release();
+
+ vars->consoleMapping = NULL;
+ if (vars->previewBuffer && (kIOReturnSuccess != vars->previewBuffer->prepare()))
+ {
+ vars->previewBuffer->release();
+ vars->previewBuffer = 0;
+ }
+
+ if ((kIOHibernateOptionProgress & gIOHibernateCurrentHeader->options)
+ && vars->previewBuffer
+ && (data = OSDynamicCast(OSData,
+ IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewActiveKey))))
+ {
+ UInt32 flags = *((UInt32 *)data->getBytesNoCopy());
+ HIBPRINT("kIOHibernatePreviewActiveKey %08lx\n", (long)flags);
+
+ IOService::getPMRootDomain()->removeProperty(kIOHibernatePreviewActiveKey);
+
+ if (kIOHibernatePreviewUpdates & flags)
+ {
+ PE_Video consoleInfo;
+ hibernate_graphics_t * graphicsInfo = gIOHibernateGraphicsInfo;
+
+ IOService::getPlatform()->getConsoleInfo(&consoleInfo);
+
+ graphicsInfo->width = consoleInfo.v_width;
+ graphicsInfo->height = consoleInfo.v_height;
+ graphicsInfo->rowBytes = consoleInfo.v_rowBytes;
+ graphicsInfo->depth = consoleInfo.v_depth;
+ vars->consoleMapping = (uint8_t *) consoleInfo.v_baseAddr;
+
+ HIBPRINT("video %p %d %d %d\n",
+ vars->consoleMapping, graphicsInfo->depth,
+ graphicsInfo->width, graphicsInfo->height);
+ if (vars->consoleMapping)
+ ProgressInit(graphicsInfo, vars->consoleMapping,
+ &graphicsInfo->progressSaveUnder[0][0], sizeof(graphicsInfo->progressSaveUnder));
+ }
+ }
+
+ if (gIOOptionsEntry)
+ gIOOptionsEntry->sync();
+
+ return (ret);
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static DeviceTreeNode *
+MergeDeviceTree(DeviceTreeNode * entry, IORegistryEntry * regEntry)
+{
+ DeviceTreeNodeProperty * prop;
+ DeviceTreeNode * child;
+ IORegistryEntry * childRegEntry;
+ const char * nameProp;
+ unsigned int propLen, idx;
+
+ prop = (DeviceTreeNodeProperty *) (entry + 1);
+ for (idx = 0; idx < entry->nProperties; idx++)
+ {
+ if (regEntry && (0 != strcmp("name", prop->name)))
+ {
+ regEntry->setProperty((const char *) prop->name, (void *) (prop + 1), prop->length);
+// HIBPRINT("%s: %s, %d\n", regEntry->getName(), prop->name, prop->length);
+ }
+ prop = (DeviceTreeNodeProperty *) (((uintptr_t)(prop + 1)) + ((prop->length + 3) & ~3));
+ }
+
+ child = (DeviceTreeNode *) prop;
+ for (idx = 0; idx < entry->nChildren; idx++)
+ {
+ if (kSuccess != DTGetProperty(child, "name", (void **) &nameProp, &propLen))
+ panic("no name");
+ childRegEntry = regEntry ? regEntry->childFromPath(nameProp, gIODTPlane) : NULL;
+// HIBPRINT("%s == %p\n", nameProp, childRegEntry);
+ child = MergeDeviceTree(child, childRegEntry);
+ }
+ return (child);
+}
+
+IOReturn
+IOHibernateSystemWake(void)
+{
+ if (kFSOpened == gFSState)
+ {
+ IOHibernateDone(&gIOHibernateVars);
+ }
+ else
+ {
+ IOService::getPMRootDomain()->removeProperty(kIOHibernateOptionsKey);
+ IOService::getPMRootDomain()->removeProperty(kIOHibernateGfxStatusKey);
+ }
+ return (kIOReturnSuccess);
+}
+
+static IOReturn
+IOHibernateDone(IOHibernateVars * vars)
+{
+ IORegistryEntry * next;