+ struct AppleRTCHibernateVars
+ {
+ uint8_t signature[4];
+ uint32_t revision;
+ uint8_t booterSignature[20];
+ uint8_t wiredCryptKey[16];
+ };
+ AppleRTCHibernateVars rtcVars;
+ OSData * data;
+
+ rtcVars.signature[0] = 'A';
+ rtcVars.signature[1] = 'A';
+ rtcVars.signature[2] = 'P';
+ rtcVars.signature[3] = 'L';
+ rtcVars.revision = 1;
+ bcopy(&vars->wiredCryptKey[0], &rtcVars.wiredCryptKey[0], sizeof(rtcVars.wiredCryptKey));
+
+ if (gIOChosenEntry
+ && (data = OSDynamicCast(OSData, gIOChosenEntry->getProperty(gIOHibernateBootSignatureKey)))
+ && (sizeof(rtcVars.booterSignature) <= data->getLength()))
+ {
+ bcopy(data->getBytesNoCopy(), &rtcVars.booterSignature[0], sizeof(rtcVars.booterSignature));
+ }
+ else if (gIOHibernateBootSignature[0])
+ {
+ char c;
+ uint8_t value = 0;
+ uint32_t in, out, digits;
+ for (in = out = digits = 0;
+ (c = gIOHibernateBootSignature[in]) && (in < sizeof(gIOHibernateBootSignature));
+ in++)
+ {
+ if ((c >= 'a') && (c <= 'f')) c -= 'a' - 10;
+ else if ((c >= 'A') && (c <= 'F')) c -= 'A' - 10;
+ else if ((c >= '0') && (c <= '9')) c -= '0';
+ else
+ {
+ if (c == '=') out = digits = value = 0;
+ continue;
+ }
+ value = (value << 4) | c;
+ if (digits & 1)
+ {
+ rtcVars.booterSignature[out++] = value;
+ if (out >= sizeof(rtcVars.booterSignature)) break;
+ }
+ digits++;
+ }
+ }
+#if DEBUG || DEVELOPMENT
+ if (kIOLogHibernate & gIOKitDebug) IOKitKernelLogBuffer("H> rtc:",
+ &rtcVars, sizeof(rtcVars), &kprintf);
+#endif /* DEBUG || DEVELOPMENT */
+
+ data = OSData::withBytes(&rtcVars, sizeof(rtcVars));
+ if (data)
+ {
+ if (gIOHibernateRTCVariablesKey)
+ IOService::getPMRootDomain()->setProperty(gIOHibernateRTCVariablesKey, data);
+ data->release();
+ }
+ if (gIOChosenEntry && gIOOptionsEntry)
+ {
+ data = OSDynamicCast(OSData, gIOChosenEntry->getProperty(kIOHibernateMachineSignatureKey));
+ if (data) gIOHibernateCurrentHeader->machineSignature = *((UInt32 *)data->getBytesNoCopy());
+ // set BootNext
+ if (!gIOHibernateBoot0082Data)
+ {
+ OSData * fileData = 0;
+ data = OSDynamicCast(OSData, gIOChosenEntry->getProperty("boot-device-path"));
+ if (data && data->getLength() >= 4) fileData = OSDynamicCast(OSData, gIOChosenEntry->getProperty("boot-file-path"));
+ if (data)
+ {
+ // AppleNVRAM_EFI_LOAD_OPTION
+ struct {
+ uint32_t Attributes;
+ uint16_t FilePathLength;
+ uint16_t Desc;
+ } loadOptionHeader;
+ loadOptionHeader.Attributes = 1;
+ loadOptionHeader.FilePathLength = data->getLength();
+ loadOptionHeader.Desc = 0;
+ if (fileData)
+ {
+ loadOptionHeader.FilePathLength -= 4;
+ loadOptionHeader.FilePathLength += fileData->getLength();
+ }
+ gIOHibernateBoot0082Data = OSData::withCapacity(sizeof(loadOptionHeader) + loadOptionHeader.FilePathLength);
+ if (gIOHibernateBoot0082Data)
+ {
+ gIOHibernateBoot0082Data->appendBytes(&loadOptionHeader, sizeof(loadOptionHeader));
+ if (fileData)
+ {
+ gIOHibernateBoot0082Data->appendBytes(data->getBytesNoCopy(), data->getLength() - 4);
+ gIOHibernateBoot0082Data->appendBytes(fileData);
+ }
+ else gIOHibernateBoot0082Data->appendBytes(data);
+ }
+ }
+ }
+ if (!gIOHibernateBootNextData)
+ {
+ uint16_t bits = 0x0082;
+ gIOHibernateBootNextData = OSData::withBytes(&bits, sizeof(bits));
+ }
+
+#if DEBUG || DEVELOPMENT
+ if (kIOLogHibernate & gIOKitDebug) IOKitKernelLogBuffer("H> bootnext:",
+ gIOHibernateBoot0082Data->getBytesNoCopy(), gIOHibernateBoot0082Data->getLength(), &kprintf);
+#endif /* DEBUG || DEVELOPMENT */
+ if (gIOHibernateBoot0082Key && gIOHibernateBoot0082Data && gIOHibernateBootNextKey && gIOHibernateBootNextData)
+ {
+ gIOHibernateBootNextSave = gIOOptionsEntry->copyProperty(gIOHibernateBootNextKey);
+ gIOOptionsEntry->setProperty(gIOHibernateBoot0082Key, gIOHibernateBoot0082Data);
+ gIOOptionsEntry->setProperty(gIOHibernateBootNextKey, gIOHibernateBootNextData);
+ }
+ // BootNext
+ }