X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4452a7af2eac33dbad800bcc91f2399d62c18f53..935ed37a5c468c8a1c07408573c08b8b7ef80e8b:/iokit/Kernel/IOHibernateIO.cpp diff --git a/iokit/Kernel/IOHibernateIO.cpp b/iokit/Kernel/IOHibernateIO.cpp index d38300ad5..ae66cb9b8 100644 --- a/iokit/Kernel/IOHibernateIO.cpp +++ b/iokit/Kernel/IOHibernateIO.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -468,28 +468,39 @@ IOHibernatePollerIO(IOPolledFileIOVars * vars, } static IOReturn -IOHibernatePollerIODone(IOPolledFileIOVars * vars) +IOHibernatePollerIODone(IOPolledFileIOVars * vars, bool abortable) { - IOReturn err = kIOReturnError; - int32_t idx; + IOReturn err = kIOReturnSuccess; + int32_t idx = 0; IOPolledInterface * poller; while (-1 == vars->ioStatus) { - for (idx = 0; - (poller = (IOPolledInterface *) vars->pollers->getObject(idx)); + for (idx = 0; + (poller = (IOPolledInterface *) vars->pollers->getObject(idx)); idx++) { - err = poller->checkForWork(); - if (err) - HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx, err); + IOReturn newErr; + newErr = poller->checkForWork(); + if ((newErr == kIOReturnAborted) && !abortable) + newErr = kIOReturnSuccess; + if (kIOReturnSuccess == err) + err = newErr; } } - if (kIOReturnSuccess != vars->ioStatus) - HIBLOG("IOPolledInterface::ioStatus 0x%x\n", vars->ioStatus); + if (err) + { + HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx, err); + } + else + { + err = vars->ioStatus; + if (kIOReturnSuccess != err) + HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err); + } - return (vars->ioStatus); + return (err); } IOReturn @@ -608,7 +619,9 @@ IOPolledFileOpen( const char * filename, IOBufferMemoryDescriptor * ioBuffer, part->retain(); iter->release(); } - + if (!part) + break; + int minor, major; IORegistryEntry * next; IORegistryEntry * child; @@ -677,7 +690,7 @@ IOPolledFileOpen( const char * filename, IOBufferMemoryDescriptor * ioBuffer, if (!gIOCreateEFIDevicePathSymbol) gIOCreateEFIDevicePathSymbol = OSSymbol::withCString("CreateEFIDevicePath"); - sprintf(str2, "%qx", vars->extentMap[0]); + snprintf(str2, sizeof(str2), "%qx", vars->extentMap[0].start); err = IOService::getPlatform()->callPlatformFunction( gIOCreateEFIDevicePathSymbol, false, @@ -691,7 +704,7 @@ IOPolledFileOpen( const char * filename, IOBufferMemoryDescriptor * ioBuffer, err = kIOReturnNotFound; else { - sprintf(str2, ",%qx", vars->extentMap[0]); + snprintf(str2, sizeof(str2), ",%qx", vars->extentMap[0].start); // (strip the plane name) char * tail = strchr(str1, ':'); if (!tail) @@ -810,6 +823,7 @@ IOPolledFileWrite(IOPolledFileIOVars * vars, - vars->extentPosition + vars->currentExtent->start); uint32_t length = (vars->bufferOffset); +#if CRYPTO if (cryptvars && vars->encryptStart && (vars->position > vars->encryptStart)) { uint32_t encryptLen, encryptStart; @@ -829,10 +843,11 @@ IOPolledFileWrite(IOPolledFileIOVars * vars, &cryptvars->aes_iv[0], AES_BLOCK_SIZE); } +#endif /* CRYPTO */ if (vars->io) { - err = IOHibernatePollerIODone(vars); + err = IOHibernatePollerIODone(vars, true); if (kIOReturnSuccess != err) break; } @@ -902,7 +917,7 @@ IOPolledFileRead(IOPolledFileIOVars * vars, { if (vars->io) { - err = IOHibernatePollerIODone(vars); + err = IOHibernatePollerIODone(vars, false); if (kIOReturnSuccess != err) break; } @@ -927,14 +942,15 @@ if (vars->position & (vars->blockSize - 1)) HIBLOG("misaligned file pos %qx\n", } } - if (vars->extentRemaining <= vars->bufferSize) - vars->lastRead = vars->extentRemaining; - else - vars->lastRead = vars->bufferSize; - + uint64_t length; + uint64_t lastReadLength = vars->lastRead; uint64_t offset = (vars->position - vars->extentPosition + vars->currentExtent->start); - uint64_t length = (vars->lastRead); + if (vars->extentRemaining <= vars->bufferSize) + length = vars->extentRemaining; + else + length = vars->bufferSize; + vars->lastRead = length; //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length); @@ -946,20 +962,22 @@ if (vars->position & (vars->blockSize - 1)) HIBLOG("misaligned file pos %qx\n", vars->bufferHalf = vars->bufferHalf ? 0 : vars->bufferSize; vars->bufferOffset = 0; +#if CRYPTO if (cryptvars) { uint8_t thisVector[AES_BLOCK_SIZE]; // save initial vector for following decrypts bcopy(&cryptvars->aes_iv[0], &thisVector[0], AES_BLOCK_SIZE); - bcopy(vars->buffer + vars->bufferHalf + vars->lastRead - AES_BLOCK_SIZE, + bcopy(vars->buffer + vars->bufferHalf + lastReadLength - AES_BLOCK_SIZE, &cryptvars->aes_iv[0], AES_BLOCK_SIZE); // decrypt the buffer aes_decrypt_cbc(vars->buffer + vars->bufferHalf, &thisVector[0], - vars->lastRead / AES_BLOCK_SIZE, + lastReadLength / AES_BLOCK_SIZE, vars->buffer + vars->bufferHalf, &cryptvars->ctx.decrypt); } +#endif CRYPTO } } while (size); @@ -977,6 +995,7 @@ IOHibernateSystemSleep(void) OSObject * obj; OSString * str; OSNumber * num; + OSDictionary *sleepOverrideOptions; IOHibernateVars * vars = &gIOHibernateVars; @@ -986,23 +1005,53 @@ IOHibernateSystemSleep(void) gIOHibernateState = kIOHibernateStateInactive; - if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateModeKey))) + /* The invocation of IOPMSleepSystemWithOptions() may override + * existing hibernation settings. + */ + sleepOverrideOptions = (OSDictionary *)OSDynamicCast( OSDictionary, + IOService::getPMRootDomain()->copyProperty(kRootDomainSleepOptionsKey)); + + + /* Hibernate mode overriden by sleep otions ? */ + obj = NULL; + + if (sleepOverrideOptions) { + obj = sleepOverrideOptions->getObject(kIOHibernateModeKey); + if (obj) obj->retain(); + } + + if(!obj) { + obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateModeKey); + } + + if (obj && (num = OSDynamicCast(OSNumber, obj)) ) { - if ((num = OSDynamicCast(OSNumber, obj))) gIOHibernateMode = num->unsigned32BitValue(); if (kIOHibernateModeSleep & gIOHibernateMode) // default to discard clean for safe sleep gIOHibernateMode ^= (kIOHibernateModeDiscardCleanInactive | kIOHibernateModeDiscardCleanActive); + } - obj->release(); + if (obj) obj->release(); + + /* Hibernate free rotio overriden by sleep options ? */ + obj = NULL; + + if (sleepOverrideOptions) { + obj = sleepOverrideOptions->getObject(kIOHibernateFreeRatioKey); + if (obj) obj->retain(); + } + + if(!obj) { + obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFreeRatioKey); } - if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFreeRatioKey))) + if (obj && (num = OSDynamicCast(OSNumber, obj))) { - if ((num = OSDynamicCast(OSNumber, obj))) gIOHibernateFreeRatio = num->unsigned32BitValue(); - obj->release(); } + if (obj) obj->release(); + if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFreeTimeKey))) { if ((num = OSDynamicCast(OSNumber, obj))) @@ -1012,15 +1061,20 @@ IOHibernateSystemSleep(void) if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFileKey))) { if ((str = OSDynamicCast(OSString, obj))) - strcpy(gIOHibernateFilename, str->getCStringNoCopy()); + strlcpy(gIOHibernateFilename, str->getCStringNoCopy(), + sizeof(gIOHibernateFilename)); obj->release(); } + if (sleepOverrideOptions) + sleepOverrideOptions->release(); + if (!gIOHibernateMode || !gIOHibernateFilename[0]) return (kIOReturnUnsupported); HIBLOG("hibernate image path: %s\n", gIOHibernateFilename); + do { vars->srcBuffer = IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn, @@ -1179,9 +1233,24 @@ IOHibernateSystemSleep(void) } data = OSData::withBytes(&rtcVars, sizeof(rtcVars)); if (data) - { - IOService::getPMRootDomain()->setProperty(kIOHibernateRTCVariablesKey, data); - data->release(); + { + IOService::getPMRootDomain()->setProperty(kIOHibernateRTCVariablesKey, data); + + if( gIOOptionsEntry ) + { + if( gIOHibernateMode & kIOHibernateModeSwitch ) + { + const OSSymbol *sym; + sym = OSSymbol::withCStringNoCopy(kIOHibernateBootSwitchVarsKey); + if( sym ) + { + gIOOptionsEntry->setProperty(sym, data); /* intentional insecure backup of rtc boot vars */ + sym->release(); + } + } + } + + data->release(); } if (gIOChosenEntry) { @@ -1200,7 +1269,7 @@ IOHibernateSystemSleep(void) sym->release(); if (data) data->release(); - if (gIOHibernateBootSignature[0]) + if (false && gIOHibernateBootSignature[0]) { data = OSData::withCapacity(16); sym = OSSymbol::withCStringNoCopy(kIOHibernateBootSignatureKey); @@ -1257,27 +1326,173 @@ IOHibernateSystemSleep(void) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +DECLARE_IOHIBERNATEPROGRESSALPHA + +static void +ProgressInit(hibernate_graphics_t * display, uint8_t * screen, uint8_t * saveunder, uint32_t savelen) +{ + uint32_t rowBytes, pixelShift; + uint32_t x, y; + int32_t blob; + uint32_t alpha, in, color, result; + uint8_t * out; + uint32_t saveindex[kIOHibernateProgressCount] = { 0 }; + + rowBytes = display->rowBytes; + pixelShift = display->depth >> 4; + if (pixelShift < 1) return; + + screen += ((display->width + - kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1)) + + (display->height - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes; + + for (y = 0; y < kIOHibernateProgressHeight; y++) + { + out = screen + y * rowBytes; + for (blob = 0; blob < kIOHibernateProgressCount; blob++) + { + color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray; + for (x = 0; x < kIOHibernateProgressWidth; x++) + { + alpha = gIOHibernateProgressAlpha[y][x]; + result = color; + if (alpha) + { + if (0xff != alpha) + { + if (1 == pixelShift) + { + in = *((uint16_t *)out) & 0x1f; // 16 + in = (in << 3) | (in >> 2); + } + else + in = *((uint32_t *)out) & 0xff; // 32 + saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in; + result = ((255 - alpha) * in + alpha * result + 0xff) >> 8; + } + if (1 == pixelShift) + { + result >>= 3; + *((uint16_t *)out) = (result << 10) | (result << 5) | result; // 16 + } + else + *((uint32_t *)out) = (result << 16) | (result << 8) | result; // 32 + } + out += (1 << pixelShift); + } + out += (kIOHibernateProgressSpacing << pixelShift); + } + } +} + + +static void +ProgressUpdate(hibernate_graphics_t * display, uint8_t * screen, int32_t firstBlob, int32_t select) +{ + uint32_t rowBytes, pixelShift; + uint32_t x, y; + int32_t blob, lastBlob; + uint32_t alpha, in, color, result; + uint8_t * out; + uint32_t saveindex[kIOHibernateProgressCount] = { 0 }; + + pixelShift = display->depth >> 4; + if (pixelShift < 1) + return; + + rowBytes = display->rowBytes; + + screen += ((display->width + - kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1)) + + (display->height - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes; + + lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1); + + screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift; + + for (y = 0; y < kIOHibernateProgressHeight; y++) + { + out = screen + y * rowBytes; + for (blob = firstBlob; blob <= lastBlob; blob++) + { + color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray; + for (x = 0; x < kIOHibernateProgressWidth; x++) + { + alpha = gIOHibernateProgressAlpha[y][x]; + result = color; + if (alpha) + { + if (0xff != alpha) + { + in = display->progressSaveUnder[blob][saveindex[blob]++]; + result = ((255 - alpha) * in + alpha * result + 0xff) / 255; + } + if (1 == pixelShift) + { + result >>= 3; + *((uint16_t *)out) = (result << 10) | (result << 5) | result; // 16 + } + else + *((uint32_t *)out) = (result << 16) | (result << 8) | result; // 32 + } + out += (1 << pixelShift); + } + out += (kIOHibernateProgressSpacing << pixelShift); + } + } +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + IOReturn IOHibernateSystemHasSlept(void) { IOHibernateVars * vars = &gIOHibernateVars; + OSObject * obj; + OSData * data; - if ((vars->previewData = OSDynamicCast(OSData, - IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewBufferKey)))) + 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 = IOMemoryDescriptor::withAddress( - (void *) vars->previewData->getBytesNoCopy(), - vars->previewData->getLength(), - kIODirectionInOut); + vars->previewBuffer->release(); + vars->previewBuffer = 0; + } - if (vars->previewBuffer && (kIOReturnSuccess != vars->previewBuffer->prepare())) - { - vars->previewBuffer->release(); - vars->previewBuffer = 0; - } - if (!vars->previewBuffer) - vars->previewData = 0; + if (vars->previewBuffer && (data = OSDynamicCast(OSData, + IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewActiveKey)))) + { + UInt32 flags = *((UInt32 *)data->getBytesNoCopy()); + HIBPRINT("kIOHibernatePreviewActiveKey %08lx\n", 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, gIOHibernateGraphicsInfo->depth, + gIOHibernateGraphicsInfo->width, gIOHibernateGraphicsInfo->height); + if (vars->consoleMapping) + ProgressInit(graphicsInfo, vars->consoleMapping, + &graphicsInfo->progressSaveUnder[0][0], sizeof(graphicsInfo->progressSaveUnder)); + } } + if (gIOOptionsEntry) gIOOptionsEntry->sync(); @@ -1373,7 +1588,23 @@ IOHibernateSystemWake(void) #endif #ifdef __i386__ - IOService::getPMRootDomain()->removeProperty(kIOHibernateRTCVariablesKey); + IOService::getPMRootDomain()->removeProperty(kIOHibernateRTCVariablesKey); + + /* + * Hibernate variable is written to NVRAM on platforms in which RtcRam + * is not backed by coin cell. Remove Hibernate data from NVRAM. + */ + if (gIOOptionsEntry) { + const OSSymbol * sym = OSSymbol::withCStringNoCopy(kIOHibernateRTCVariablesKey); + + if (sym) { + if (gIOOptionsEntry->getProperty(sym)) { + gIOOptionsEntry->removeProperty(sym); + gIOOptionsEntry->sync(); + } + sym->release(); + } + } #endif if (vars->srcBuffer) @@ -1410,6 +1641,16 @@ IOHibernateSystemPostWake(void) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +SYSCTL_STRING(_kern, OID_AUTO, hibernatefile, + CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN, + gIOHibernateFilename, sizeof(gIOHibernateFilename), ""); +SYSCTL_STRING(_kern, OID_AUTO, bootsignature, + CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN, + gIOHibernateBootSignature, sizeof(gIOHibernateBootSignature), ""); +SYSCTL_UINT(_kern, OID_AUTO, hibernatemode, + CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN, + &gIOHibernateMode, 0, ""); + void IOHibernateSystemInit(IOPMrootDomain * rootDomain) { @@ -1420,27 +1661,17 @@ IOHibernateSystemInit(IOPMrootDomain * rootDomain) data->release(); } - if (PE_parse_boot_arg("hfile", gIOHibernateFilename)) + if (PE_parse_boot_argn("hfile", gIOHibernateFilename, sizeof(gIOHibernateFilename))) gIOHibernateMode = kIOHibernateModeOn; else gIOHibernateFilename[0] = 0; - static SYSCTL_STRING(_kern, OID_AUTO, hibernatefile, - CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN, - gIOHibernateFilename, sizeof(gIOHibernateFilename), ""); sysctl_register_oid(&sysctl__kern_hibernatefile); - - static SYSCTL_STRING(_kern, OID_AUTO, bootsignature, - CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN, - gIOHibernateBootSignature, sizeof(gIOHibernateBootSignature), ""); sysctl_register_oid(&sysctl__kern_bootsignature); - - static SYSCTL_UINT(_kern, OID_AUTO, hibernatemode, - CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN, - &gIOHibernateMode, 0, ""); sysctl_register_oid(&sysctl__kern_hibernatemode); } + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void @@ -1456,7 +1687,7 @@ hibernate_setup_for_wake(void) #define C_ASSERT(e) typedef char __C_ASSERT__[(e) ? 1 : -1] -extern "C" boolean_t +extern "C" uint32_t hibernate_write_image(void) { IOHibernateImageHeader * header = gIOHibernateCurrentHeader; @@ -1486,6 +1717,7 @@ hibernate_write_image(void) uint64_t nsec; uint32_t lastProgressStamp = 0; uint32_t progressStamp; + uint32_t blob, lastBlob = (uint32_t) -1L; hibernate_cryptvars_t _cryptvars; hibernate_cryptvars_t * cryptvars = 0; @@ -1495,6 +1727,7 @@ hibernate_write_image(void) restore1Sum = sum1 = sum2 = 0; +#if CRYPTO // encryption data. "iv" is the "initial vector". if (kIOHibernateModeEncrypt & gIOHibernateMode) { @@ -1522,6 +1755,7 @@ hibernate_write_image(void) bzero(&vars->cryptKey[0], sizeof(vars->cryptKey)); bzero(gIOHibernateCryptWakeVars, sizeof(hibernate_cryptwakevars_t)); } +#endif /* CRYPTO */ hibernate_setup_for_wake(); @@ -1630,7 +1864,7 @@ hibernate_write_image(void) addr64_t phys64; IOByteCount segLen; - if (vars->previewData) + if (vars->previewBuffer) { ppnum = 0; count = 0; @@ -1651,8 +1885,8 @@ hibernate_write_image(void) if (kIOReturnSuccess != err) break; - src = (uint8_t *) vars->previewData->getBytesNoCopy(); - count = vars->previewData->getLength(); + src = (uint8_t *) vars->previewBuffer->getSourceSegment(0, NULL); + count = vars->previewBuffer->getLength(); header->previewPageListSize = ppnum; header->previewSize = count + ppnum; @@ -1721,6 +1955,7 @@ hibernate_write_image(void) ppnum = 0; pagesDone = 0; + lastBlob = 0; HIBLOG("writing %d pages\n", pageCount); @@ -1801,7 +2036,16 @@ hibernate_write_image(void) uncompressedSize += page_size; ppnum++; pagesDone++; - + + if (vars->consoleMapping && (0 == (1023 & pagesDone))) + { + blob = ((pagesDone * kIOHibernateProgressCount) / pageCount); + if (blob != lastBlob) + { + ProgressUpdate(gIOHibernateGraphicsInfo, vars->consoleMapping, lastBlob, blob); + lastBlob = blob; + } + } if (0 == (8191 & pagesDone)) { clock_get_uptime(&endTime); @@ -1875,7 +2119,7 @@ hibernate_write_image(void) err = IOPolledFileWrite(vars->fileVars, 0, 0, cryptvars); if (kIOReturnSuccess != err) break; - err = IOHibernatePollerIODone(vars->fileVars); + err = IOHibernatePollerIODone(vars->fileVars, true); if (kIOReturnSuccess != err) break; } @@ -1904,74 +2148,39 @@ hibernate_write_image(void) if (pollerOpen) IOHibernatePollerClose(vars->fileVars, kIOPolledBeforeSleepState); + if (vars->consoleMapping) + ProgressUpdate(gIOHibernateGraphicsInfo, + vars->consoleMapping, 0, kIOHibernateProgressCount); + HIBLOG("hibernate_write_image done(%x)\n", err); // should we come back via regular wake, set the state in memory. gIOHibernateState = kIOHibernateStateInactive; - if ((kIOReturnSuccess == err) && !(kIOHibernateModeSleep & gIOHibernateMode)) - return (true /* power down */ ); + if (kIOReturnSuccess == err) + { + if (kIOHibernateModeSleep & gIOHibernateMode) + { + return (kIOHibernatePostWriteSleep); + } + else if(kIOHibernateModeRestart & gIOHibernateMode) + { + return (kIOHibernatePostWriteRestart); + } + else + { + /* by default, power down */ + return (kIOHibernatePostWriteHalt); + } + } + else if (kIOReturnAborted == err) + { + return (kIOHibernatePostWriteWake); + } else - return (false /* sleep */ ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -DECLARE_IOHIBERNATEPROGRESSALPHA - -static void -ProgressUpdate(hibernate_graphics_t * display, uint8_t * screen, int32_t firstBlob, int32_t select) -{ - uint32_t rowBytes, pixelShift; - uint32_t x, y; - int32_t blob, lastBlob; - uint32_t alpha, in, color, result; - uint8_t * out; - uint32_t saveindex[kIOHibernateProgressCount] = { 0 }; - - pixelShift = display->depth >> 4; - if (pixelShift < 1) - return; - - rowBytes = display->rowBytes; - - screen += ((display->width - - kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1)) - + (display->height - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes; - - lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1); - - screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift; - - for (y = 0; y < kIOHibernateProgressHeight; y++) { - out = screen + y * rowBytes; - for (blob = firstBlob; blob <= lastBlob; blob++) - { - color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray; - for (x = 0; x < kIOHibernateProgressWidth; x++) - { - alpha = gIOHibernateProgressAlpha[y][x]; - result = color; - if (alpha) - { - if (0xff != alpha) - { - in = display->progressSaveUnder[blob][saveindex[blob]++]; - result = ((255 - alpha) * in + alpha * result + 0xff) / 255; - } - if (1 == pixelShift) - { - result >>= 3; - *((uint16_t *)out) = (result << 10) | (result << 5) | result; // 16 - } - else - *((uint32_t *)out) = (result << 16) | (result << 8) | result; // 32 - } - out += (1 << pixelShift); - } - out += (kIOHibernateProgressSpacing << pixelShift); - } + /* on error, sleep */ + return (kIOHibernatePostWriteSleep); } } @@ -2062,7 +2271,7 @@ hibernate_machine_init(void) IOPolledFileSeek(vars->fileVars, gIOHibernateCurrentHeader->image1Size); - if (vars->videoMapping) + if (vars->videoMapSize) { lastBlob = ((vars->fileVars->position - progressZeroPosition) * kIOHibernateProgressCount) / (gIOHibernateCurrentHeader->imageSize - progressZeroPosition); @@ -2101,7 +2310,9 @@ hibernate_machine_init(void) uint32_t tag; vm_offset_t ppnum, compressedSize; - IOPolledFileRead(vars->fileVars, src, 8, cryptvars); + err = IOPolledFileRead(vars->fileVars, src, 8, cryptvars); + if (kIOReturnSuccess != err) + break; ppnum = header[0]; count = header[1]; @@ -2113,9 +2324,17 @@ hibernate_machine_init(void) for (page = 0; page < count; page++) { - IOPolledFileRead(vars->fileVars, (uint8_t *) &tag, 4, cryptvars); + err = IOPolledFileRead(vars->fileVars, (uint8_t *) &tag, 4, cryptvars); + if (kIOReturnSuccess != err) + break; compressedSize = kIOHibernateTagLength & tag; + if (kIOHibernateTagSignature != (tag & ~kIOHibernateTagLength)) + { + err = kIOReturnIPCError; + break; + } + if (!compressedSize) { ppnum++; @@ -2123,9 +2342,11 @@ hibernate_machine_init(void) continue; } - IOPolledFileRead(vars->fileVars, src, (compressedSize + 3) & ~3, cryptvars); - - if (compressedSize != page_size) + err = IOPolledFileRead(vars->fileVars, src, (compressedSize + 3) & ~3, cryptvars); + if (kIOReturnSuccess != err) + break; + + if (compressedSize < page_size) { decoOffset = page_size; WKdm_decompress((WK_word*) src, (WK_word*) (src + decoOffset), PAGE_SIZE_IN_WORDS); @@ -2137,12 +2358,15 @@ hibernate_machine_init(void) err = IOMemoryDescriptorReadToPhysical(vars->srcBuffer, decoOffset, ptoa_64(ppnum), page_size); if (err) + { HIBLOG("IOMemoryDescriptorReadToPhysical [%d] %x\n", ppnum, err); + break; + } ppnum++; pagesDone++; - if (vars->videoMapping && (0 == (255 & pagesDone))) + if (vars->videoMapSize && (0 == (1023 & pagesDone))) { blob = ((vars->fileVars->position - progressZeroPosition) * kIOHibernateProgressCount) / (gIOHibernateCurrentHeader->imageSize - progressZeroPosition); @@ -2170,14 +2394,17 @@ hibernate_machine_init(void) } while (true); + if (kIOReturnSuccess != err) + panic("Hibernate restore error %x", err); + gIOHibernateCurrentHeader->actualImage2Sum = sum; if (vars->fileVars->io) - (void) IOHibernatePollerIODone(vars->fileVars); + (void) IOHibernatePollerIODone(vars->fileVars, false); err = IOHibernatePollerClose(vars->fileVars, kIOPolledAfterSleepState); - if (vars->videoMapping) + if (vars->videoMapSize) ProgressUpdate(gIOHibernateGraphicsInfo, (uint8_t *) vars->videoMapping, 0, kIOHibernateProgressCount);