2 * Copyright (c) 2006-2009 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 #include <IOKit/IOLib.h>
33 #include <IOKit/IOBSD.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IOPolledInterface.h>
37 #include <IOKit/IOHibernatePrivate.h>
38 #include <IOKit/IOBufferMemoryDescriptor.h>
39 #include <IOKit/AppleKeyStoreInterface.h>
40 #include "IOKitKernelInternal.h"
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45 OSDefineMetaClassAndAbstractStructors(IOPolledInterface
, OSObject
);
47 OSMetaClassDefineReservedUnused(IOPolledInterface
, 0);
48 OSMetaClassDefineReservedUnused(IOPolledInterface
, 1);
49 OSMetaClassDefineReservedUnused(IOPolledInterface
, 2);
50 OSMetaClassDefineReservedUnused(IOPolledInterface
, 3);
51 OSMetaClassDefineReservedUnused(IOPolledInterface
, 4);
52 OSMetaClassDefineReservedUnused(IOPolledInterface
, 5);
53 OSMetaClassDefineReservedUnused(IOPolledInterface
, 6);
54 OSMetaClassDefineReservedUnused(IOPolledInterface
, 7);
55 OSMetaClassDefineReservedUnused(IOPolledInterface
, 8);
56 OSMetaClassDefineReservedUnused(IOPolledInterface
, 9);
57 OSMetaClassDefineReservedUnused(IOPolledInterface
, 10);
58 OSMetaClassDefineReservedUnused(IOPolledInterface
, 11);
59 OSMetaClassDefineReservedUnused(IOPolledInterface
, 12);
60 OSMetaClassDefineReservedUnused(IOPolledInterface
, 13);
61 OSMetaClassDefineReservedUnused(IOPolledInterface
, 14);
62 OSMetaClassDefineReservedUnused(IOPolledInterface
, 15);
64 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66 #ifndef kIOMediaPreferredBlockSizeKey
67 #define kIOMediaPreferredBlockSizeKey "Preferred Block Size"
70 enum { kDefaultIOSize
= 128*1024 };
72 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
74 class IOPolledFilePollers
: public OSObject
76 OSDeclareDefaultStructors(IOPolledFilePollers
)
81 IOBufferMemoryDescriptor
* ioBuffer
;
87 static IOPolledFilePollers
* copyPollers(IOService
* media
);
90 OSDefineMetaClassAndStructors(IOPolledFilePollers
, OSObject
)
92 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95 IOPolledFilePollers::copyPollers(IOService
* media
)
97 IOPolledFilePollers
* vars
;
101 IORegistryEntry
* next
;
102 IORegistryEntry
* child
;
104 if ((obj
= media
->copyProperty(kIOPolledInterfaceStackKey
)))
106 return (OSDynamicCast(IOPolledFilePollers
, obj
));
111 vars
= OSTypeAlloc(IOPolledFilePollers
);
114 vars
->pollers
= OSArray::withCapacity(4);
117 err
= kIOReturnNoMemory
;
121 next
= vars
->media
= media
;
124 IOPolledInterface
* poller
;
127 obj
= next
->getProperty(kIOPolledInterfaceSupportKey
);
128 if (kOSBooleanFalse
== obj
)
130 vars
->pollers
->flushCollection();
133 else if ((poller
= OSDynamicCast(IOPolledInterface
, obj
)))
134 vars
->pollers
->setObject(poller
);
136 if ((service
= OSDynamicCast(IOService
, next
))
137 && service
->getDeviceMemory()
138 && !vars
->pollers
->getCount()) break;
142 while ((next
= child
->getParentEntry(gIOServicePlane
))
143 && child
->isParent(next
, gIOServicePlane
, true));
145 if (!vars
->pollers
->getCount())
147 err
= kIOReturnUnsupported
;
153 media
->setProperty(kIOPolledInterfaceStackKey
, vars
);
158 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
161 IOPolledFilePollersIODone(IOPolledFilePollers
* vars
, bool abortable
);
163 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
166 IOPolledFilePollersProbe(IOPolledFilePollers
* vars
)
168 IOReturn err
= kIOReturnError
;
170 IOPolledInterface
* poller
;
172 for (idx
= vars
->pollers
->getCount() - 1; idx
>= 0; idx
--)
174 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
);
175 err
= poller
->probe(vars
->media
);
178 HIBLOG("IOPolledInterface::probe[%d] 0x%x\n", idx
, err
);
186 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
189 IOPolledFilePollersOpen(IOPolledFileIOVars
* filevars
, uint32_t state
, bool abortable
)
192 IOPolledFilePollers
* vars
= filevars
->pollers
;
193 IOBufferMemoryDescriptor
* ioBuffer
;
194 IOPolledInterface
* poller
;
196 IOReturn err
= kIOReturnError
;
199 vars
->abortable
= abortable
;
202 if (kIOPolledAfterSleepState
== state
)
207 (void) IOPolledFilePollersIODone(vars
, false);
209 if ((kIOPolledPreflightState
== state
) || (kIOPolledPreflightCoreDumpState
== state
))
211 ioBuffer
= vars
->ioBuffer
;
214 vars
->ioBuffer
= ioBuffer
= IOBufferMemoryDescriptor::withOptions(kIODirectionInOut
,
215 2 * kDefaultIOSize
, page_size
);
216 if (!ioBuffer
) return (kIOReturnNoMemory
);
220 for (idx
= vars
->pollers
->getCount() - 1; idx
>= 0; idx
--)
222 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
);
223 err
= poller
->open(state
, ioBuffer
);
224 if (kIOReturnSuccess
!= err
)
226 HIBLOG("IOPolledInterface::open[%d] 0x%x\n", idx
, err
);
230 if ((kIOReturnSuccess
== err
) && (kIOPolledPreflightState
== state
))
235 next
->setProperty(kIOPolledInterfaceActiveKey
, kOSBooleanTrue
);
236 next
= next
->getProvider();
243 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
246 IOPolledFilePollersClose(IOPolledFileIOVars
* filevars
, uint32_t state
)
248 IOPolledFilePollers
* vars
= filevars
->pollers
;
249 IOPolledInterface
* poller
;
250 IORegistryEntry
* next
;
254 (void) IOPolledFilePollersIODone(vars
, false);
256 if ((kIOPolledPostflightState
== state
) || (kIOPolledPostflightCoreDumpState
== state
))
261 for (idx
= 0, err
= kIOReturnSuccess
;
262 (poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
));
265 err
= poller
->close(state
);
266 if ((kIOReturnSuccess
!= err
) && (kIOPolledBeforeSleepStateAborted
== state
))
268 err
= poller
->close(kIOPolledBeforeSleepState
);
270 if (err
) HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx
, err
);
273 if (kIOPolledPostflightState
== state
)
278 next
->removeProperty(kIOPolledInterfaceActiveKey
);
279 next
= next
->getParentEntry(gIOServicePlane
);
283 if ((kIOPolledPostflightState
== state
) || (kIOPolledPostflightCoreDumpState
== state
)) do
285 if (vars
->openCount
) break;
288 vars
->ioBuffer
->release();
296 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
299 IOPolledFileGetIOBuffer(IOPolledFileIOVars
* vars
)
301 return (vars
->pollers
->ioBuffer
);
304 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
307 IOPolledIOComplete(void * target
,
310 UInt64 actualByteCount
)
312 IOPolledFilePollers
* vars
= (IOPolledFilePollers
*) parameter
;
314 vars
->ioStatus
= status
;
317 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
320 IOStartPolledIO(IOPolledFilePollers
* vars
,
321 uint32_t operation
, uint32_t bufferOffset
,
322 uint64_t deviceOffset
, uint64_t length
)
325 IOPolledInterface
* poller
;
326 IOPolledCompletion completion
;
328 err
= vars
->ioStatus
;
329 if (kIOReturnSuccess
!= err
) return (err
);
331 completion
.target
= 0;
332 completion
.action
= &IOPolledIOComplete
;
333 completion
.parameter
= vars
;
337 poller
= (IOPolledInterface
*) vars
->pollers
->getObject(0);
338 err
= poller
->startIO(operation
, bufferOffset
, deviceOffset
, length
, completion
);
340 HIBLOG("IOPolledInterface::startIO[%d] 0x%x\n", 0, err
);
345 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
348 IOPolledFilePollersIODone(IOPolledFilePollers
* vars
, bool abortable
)
350 IOReturn err
= kIOReturnSuccess
;
352 IOPolledInterface
* poller
;
353 AbsoluteTime deadline
;
355 if (!vars
->io
) return (kIOReturnSuccess
);
357 abortable
&= vars
->abortable
;
359 clock_interval_to_deadline(2000, kMillisecondScale
, &deadline
);
361 while (-1 == vars
->ioStatus
)
364 (poller
= (IOPolledInterface
*) vars
->pollers
->getObject(idx
));
368 newErr
= poller
->checkForWork();
369 if ((newErr
== kIOReturnAborted
) && !abortable
)
370 newErr
= kIOReturnSuccess
;
371 if (kIOReturnSuccess
== err
)
374 if ((false) && (kIOReturnSuccess
== err
) && (mach_absolute_time() > AbsoluteTime_to_scalar(&deadline
)))
376 HIBLOG("IOPolledInterface::forced timeout\n");
377 vars
->ioStatus
= kIOReturnTimeout
;
383 if ((kIOReturnSuccess
== err
) && abortable
&& hibernate_should_abort())
385 err
= kIOReturnAborted
;
386 HIBLOG("IOPolledInterface::checkForWork sw abort\n");
392 HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx
, err
);
396 err
= vars
->ioStatus
;
397 if (kIOReturnSuccess
!= err
) HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err
);
403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
404 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
406 struct _OpenFileContext
413 file_extent_callback(void * ref
, uint64_t start
, uint64_t length
)
415 _OpenFileContext
* ctx
= (_OpenFileContext
*) ref
;
416 IOPolledFileExtent extent
;
418 extent
.start
= start
;
419 extent
.length
= length
;
420 ctx
->extents
->appendBytes(&extent
, sizeof(extent
));
424 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
427 IOCopyMediaForDev(dev_t device
)
429 OSDictionary
* matching
;
432 IOService
* result
= 0;
434 matching
= IOService::serviceMatching("IOMedia");
439 num
= OSNumber::withNumber(major(device
), 32);
442 matching
->setObject(kIOBSDMajorKey
, num
);
444 num
= OSNumber::withNumber(minor(device
), 32);
447 matching
->setObject(kIOBSDMinorKey
, num
);
451 iter
= IOService::getMatchingServices(matching
);
454 result
= (IOService
*) iter
->getNextObject();
466 IOGetVolumeCryptKey(dev_t block_dev
, OSString
** pKeyUUID
,
467 uint8_t * volumeCryptKey
, size_t keySize
)
471 OSString
* keyUUID
= 0;
472 OSString
* keyStoreUUID
= 0;
473 uuid_t volumeKeyUUID
;
474 aks_volume_key_t vek
;
476 static IOService
* sKeyStore
;
478 part
= IOCopyMediaForDev(block_dev
);
479 if (!part
) return (kIOReturnNotFound
);
481 err
= part
->callPlatformFunction(PLATFORM_FUNCTION_GET_MEDIA_ENCRYPTION_KEY_UUID
, false,
482 (void *) &keyUUID
, (void *) &keyStoreUUID
, NULL
, NULL
);
483 if ((kIOReturnSuccess
== err
) && keyUUID
&& keyStoreUUID
)
485 // IOLog("got volume key %s\n", keyStoreUUID->getCStringNoCopy());
488 sKeyStore
= (IOService
*) IORegistryEntry::fromPath(AKS_SERVICE_PATH
, gIOServicePlane
);
490 err
= uuid_parse(keyStoreUUID
->getCStringNoCopy(), volumeKeyUUID
);
492 err
= kIOReturnNoResources
;
493 if (kIOReturnSuccess
== err
)
494 err
= sKeyStore
->callPlatformFunction(gAKSGetKey
, true, volumeKeyUUID
, &vek
, NULL
, NULL
);
495 if (kIOReturnSuccess
!= err
)
496 IOLog("volume key err 0x%x\n", err
);
499 if (vek
.key
.keybytecount
< keySize
) keySize
= vek
.key
.keybytecount
;
500 bcopy(&vek
.key
.keybytes
[0], volumeCryptKey
, keySize
);
502 bzero(&vek
, sizeof(vek
));
506 if (pKeyUUID
) *pKeyUUID
= keyUUID
;
511 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
514 IOPolledFileOpen(const char * filename
,
515 uint64_t setFileSize
, uint64_t fsFreeSize
,
516 void * write_file_addr
, size_t write_file_len
,
517 IOPolledFileIOVars
** fileVars
,
519 uint8_t * volumeCryptKey
, size_t keySize
)
521 IOReturn err
= kIOReturnSuccess
;
522 IOPolledFileIOVars
* vars
;
523 _OpenFileContext ctx
;
524 OSData
* extentsData
;
526 IOService
* part
= 0;
529 AbsoluteTime startTime
, endTime
;
532 vars
= IONew(IOPolledFileIOVars
, 1);
533 if (!vars
) return (kIOReturnNoMemory
);
534 bzero(vars
, sizeof(*vars
));
535 vars
->allocated
= true;
539 extentsData
= OSData::withCapacity(32);
540 ctx
.extents
= extentsData
;
542 clock_get_uptime(&startTime
);
544 vars
->fileRef
= kern_open_file_for_direct_io(filename
,
545 (write_file_addr
!= NULL
) || (0 != setFileSize
),
546 &file_extent_callback
, &ctx
,
550 0, write_file_addr
, write_file_len
,
558 uint32_t msDelay
= (131071 & random());
559 HIBLOG("sleep %d\n", msDelay
);
562 clock_get_uptime(&endTime
);
563 SUB_ABSOLUTETIME(&endTime
, &startTime
);
564 absolutetime_to_nanoseconds(endTime
, &nsec
);
566 if (!vars
->fileRef
) err
= kIOReturnNoSpace
;
568 HIBLOG("kern_open_file_for_direct_io took %qd ms\n", nsec
/ 1000000ULL);
569 if (kIOReturnSuccess
!= err
) break;
571 HIBLOG("Opened file %s, size %qd, extents %ld, maxio %qx ssd %d\n", filename
, ctx
.size
,
572 (extentsData
->getLength() / sizeof(IOPolledFileExtent
)) - 1,
573 vars
->maxiobytes
, kIOPolledFileSSD
& vars
->flags
);
574 assert(!vars
->block0
);
575 if (extentsData
->getLength() < sizeof(IOPolledFileExtent
))
577 err
= kIOReturnNoSpace
;
581 vars
->fileSize
= ctx
.size
;
582 vars
->extentMap
= (IOPolledFileExtent
*) extentsData
->getBytesNoCopy();
584 part
= IOCopyMediaForDev(image_dev
);
587 err
= kIOReturnNotFound
;
591 if (!(vars
->pollers
= IOPolledFilePollers::copyPollers(part
))) break;
593 if ((num
= OSDynamicCast(OSNumber
, part
->getProperty(kIOMediaPreferredBlockSizeKey
))))
594 vars
->blockSize
= num
->unsigned32BitValue();
595 if (vars
->blockSize
< 4096) vars
->blockSize
= 4096;
597 HIBLOG("polled file major %d, minor %d, blocksize %ld, pollers %d\n",
598 major(image_dev
), minor(image_dev
), (long)vars
->blockSize
,
599 vars
->pollers
->pollers
->getCount());
601 OSString
* keyUUID
= NULL
;
604 err
= IOGetVolumeCryptKey(block_dev
, &keyUUID
, volumeCryptKey
, keySize
);
608 vars
->fileExtents
= extentsData
;
614 #if defined(__i386__) || defined(__x86_64__)
615 char str2
[24 + sizeof(uuid_string_t
) + 2];
618 snprintf(str2
, sizeof(str2
), "%qx:%s",
619 vars
->extentMap
[0].start
, keyUUID
->getCStringNoCopy());
621 snprintf(str2
, sizeof(str2
), "%qx", vars
->extentMap
[0].start
);
623 err
= IOService::getPlatform()->callPlatformFunction(
624 gIOCreateEFIDevicePathSymbol
, false,
625 (void *) part
, (void *) str2
,
626 (void *) (uintptr_t) true, (void *) &data
);
629 err
= kIOReturnSuccess
;
631 if (kIOReturnSuccess
!= err
)
633 HIBLOG("error 0x%x getting path\n", err
);
641 if (kIOReturnSuccess
!= err
)
643 HIBLOG("error 0x%x opening polled file\n", err
);
644 IOPolledFileClose(&vars
, 0, 0, 0, 0, 0);
647 if (part
) part
->release();
652 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
655 IOPolledFileClose(IOPolledFileIOVars
** pVars
,
656 off_t write_offset
, void * addr
, size_t write_length
,
657 off_t discard_offset
, off_t discard_end
)
659 IOPolledFileIOVars
* vars
;
662 if (!vars
) return(kIOReturnSuccess
);
666 kern_close_file_for_direct_io(vars
->fileRef
, write_offset
, addr
, write_length
,
667 discard_offset
, discard_end
);
668 vars
->fileRef
= NULL
;
670 if (vars
->fileExtents
)
672 vars
->fileExtents
->release();
673 vars
->fileExtents
= 0;
677 vars
->pollers
->release();
681 if (vars
->allocated
) IODelete(vars
, IOPolledFileIOVars
, 1);
682 else bzero(vars
, sizeof(IOPolledFileIOVars
));
685 return (kIOReturnSuccess
);
688 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
691 IOPolledFilePollersSetup(IOPolledFileIOVars
* vars
,
696 err
= kIOReturnSuccess
;
699 if (!vars
->pollers
->openCount
)
701 err
= IOPolledFilePollersProbe(vars
->pollers
);
702 if (kIOReturnSuccess
!= err
) break;
704 err
= IOPolledFilePollersOpen(vars
, openState
, false);
705 if (kIOReturnSuccess
!= err
) break;
706 if ((kIOPolledPreflightState
== openState
) || (kIOPolledPreflightCoreDumpState
== openState
))
708 vars
->pollers
->openCount
++;
710 vars
->pollers
->io
= false;
711 vars
->buffer
= (uint8_t *) vars
->pollers
->ioBuffer
->getBytesNoCopy();
712 vars
->bufferHalf
= 0;
713 vars
->bufferOffset
= 0;
714 vars
->bufferSize
= (vars
->pollers
->ioBuffer
->getLength() >> 1);
716 if (vars
->maxiobytes
< vars
->bufferSize
) vars
->bufferSize
= vars
->maxiobytes
;
720 if (kIOReturnSuccess
!= err
) HIBLOG("IOPolledFilePollersSetup(%d) error 0x%x\n", openState
, err
);
726 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
729 IOPolledFileSeek(IOPolledFileIOVars
* vars
, uint64_t position
)
731 IOPolledFileExtent
* extentMap
;
733 extentMap
= vars
->extentMap
;
735 vars
->position
= position
;
737 while (position
>= extentMap
->length
)
739 position
-= extentMap
->length
;
743 vars
->currentExtent
= extentMap
;
744 vars
->extentRemaining
= extentMap
->length
- position
;
745 vars
->extentPosition
= vars
->position
- position
;
747 if (vars
->bufferSize
<= vars
->extentRemaining
)
748 vars
->bufferLimit
= vars
->bufferSize
;
750 vars
->bufferLimit
= vars
->extentRemaining
;
752 return (kIOReturnSuccess
);
755 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
758 IOPolledFileWrite(IOPolledFileIOVars
* vars
,
759 const uint8_t * bytes
, IOByteCount size
,
760 IOPolledFileCryptVars
* cryptvars
)
762 IOReturn err
= kIOReturnSuccess
;
770 // seek to end of block & flush
771 size
= vars
->position
& (vars
->blockSize
- 1);
773 size
= vars
->blockSize
- size
;
775 // use some garbage for the fill
776 bytes
= vars
->buffer
+ vars
->bufferOffset
;
779 copy
= vars
->bufferLimit
- vars
->bufferOffset
;
787 bcopy(bytes
, vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, copy
);
791 bzero(vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, copy
);
794 vars
->bufferOffset
+= copy
;
795 vars
->position
+= copy
;
797 if (flush
&& vars
->bufferOffset
)
799 uint64_t offset
= (vars
->position
- vars
->bufferOffset
800 - vars
->extentPosition
+ vars
->currentExtent
->start
);
801 uint32_t length
= (vars
->bufferOffset
);
804 if (cryptvars
&& vars
->encryptStart
805 && (vars
->position
> vars
->encryptStart
)
806 && ((vars
->position
- length
) < vars
->encryptEnd
))
808 AbsoluteTime startTime
, endTime
;
810 uint64_t encryptLen
, encryptStart
;
811 encryptLen
= vars
->position
- vars
->encryptStart
;
812 if (encryptLen
> length
)
814 encryptStart
= length
- encryptLen
;
815 if (vars
->position
> vars
->encryptEnd
)
816 encryptLen
-= (vars
->position
- vars
->encryptEnd
);
818 clock_get_uptime(&startTime
);
820 // encrypt the buffer
821 aes_encrypt_cbc(vars
->buffer
+ vars
->bufferHalf
+ encryptStart
,
822 &cryptvars
->aes_iv
[0],
823 encryptLen
/ AES_BLOCK_SIZE
,
824 vars
->buffer
+ vars
->bufferHalf
+ encryptStart
,
825 &cryptvars
->ctx
.encrypt
);
827 clock_get_uptime(&endTime
);
828 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
);
829 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
);
830 vars
->cryptBytes
+= encryptLen
;
832 // save initial vector for following encrypts
833 bcopy(vars
->buffer
+ vars
->bufferHalf
+ encryptStart
+ encryptLen
- AES_BLOCK_SIZE
,
834 &cryptvars
->aes_iv
[0],
839 err
= IOPolledFilePollersIODone(vars
->pollers
, true);
840 if (kIOReturnSuccess
!= err
)
843 if (vars
->position
& (vars
->blockSize
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
);
844 //if (length != vars->bufferSize) HIBLOG("short write of %qx ends@ %qx\n", length, offset + length);
846 err
= IOStartPolledIO(vars
->pollers
, kIOPolledWrite
, vars
->bufferHalf
, offset
, length
);
847 if (kIOReturnSuccess
!= err
)
849 vars
->pollers
->io
= true;
851 vars
->extentRemaining
-= vars
->bufferOffset
;
852 if (!vars
->extentRemaining
)
854 vars
->currentExtent
++;
855 vars
->extentRemaining
= vars
->currentExtent
->length
;
856 vars
->extentPosition
= vars
->position
;
859 vars
->bufferHalf
= vars
->bufferHalf
? 0 : vars
->bufferSize
;
860 vars
->bufferOffset
= 0;
861 if (vars
->bufferSize
<= vars
->extentRemaining
)
862 vars
->bufferLimit
= vars
->bufferSize
;
864 vars
->bufferLimit
= vars
->extentRemaining
;
866 if (!vars
->extentRemaining
)
868 err
= kIOReturnOverrun
;
880 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
883 IOPolledFileRead(IOPolledFileIOVars
* vars
,
884 uint8_t * bytes
, IOByteCount size
,
885 IOPolledFileCryptVars
* cryptvars
)
887 IOReturn err
= kIOReturnSuccess
;
890 // bytesWritten += size;
894 copy
= vars
->bufferLimit
- vars
->bufferOffset
;
900 bcopy(vars
->buffer
+ vars
->bufferHalf
+ vars
->bufferOffset
, bytes
, copy
);
904 vars
->bufferOffset
+= copy
;
905 // vars->position += copy;
907 if ((vars
->bufferOffset
== vars
->bufferLimit
) && (vars
->position
< vars
->readEnd
))
909 if (!vars
->pollers
->io
) cryptvars
= 0;
910 err
= IOPolledFilePollersIODone(vars
->pollers
, true);
911 if (kIOReturnSuccess
!= err
)
914 if (vars
->position
& (vars
->blockSize
- 1)) HIBLOG("misaligned file pos %qx\n", vars
->position
);
916 vars
->position
+= vars
->lastRead
;
917 vars
->extentRemaining
-= vars
->lastRead
;
918 vars
->bufferLimit
= vars
->lastRead
;
920 if (!vars
->extentRemaining
)
922 vars
->currentExtent
++;
923 vars
->extentRemaining
= vars
->currentExtent
->length
;
924 vars
->extentPosition
= vars
->position
;
925 if (!vars
->extentRemaining
)
927 err
= kIOReturnOverrun
;
933 uint64_t lastReadLength
= vars
->lastRead
;
934 uint64_t offset
= (vars
->position
935 - vars
->extentPosition
+ vars
->currentExtent
->start
);
936 if (vars
->extentRemaining
<= vars
->bufferSize
)
937 length
= vars
->extentRemaining
;
939 length
= vars
->bufferSize
;
940 if ((length
+ vars
->position
) > vars
->readEnd
)
941 length
= vars
->readEnd
- vars
->position
;
943 vars
->lastRead
= length
;
946 //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length);
947 err
= IOStartPolledIO(vars
->pollers
, kIOPolledRead
, vars
->bufferHalf
, offset
, length
);
948 if (kIOReturnSuccess
!= err
)
950 vars
->pollers
->io
= true;
953 vars
->bufferHalf
= vars
->bufferHalf
? 0 : vars
->bufferSize
;
954 vars
->bufferOffset
= 0;
959 uint8_t thisVector
[AES_BLOCK_SIZE
];
960 AbsoluteTime startTime
, endTime
;
962 // save initial vector for following decrypts
963 bcopy(&cryptvars
->aes_iv
[0], &thisVector
[0], AES_BLOCK_SIZE
);
964 bcopy(vars
->buffer
+ vars
->bufferHalf
+ lastReadLength
- AES_BLOCK_SIZE
,
965 &cryptvars
->aes_iv
[0], AES_BLOCK_SIZE
);
967 // decrypt the buffer
968 clock_get_uptime(&startTime
);
970 aes_decrypt_cbc(vars
->buffer
+ vars
->bufferHalf
,
972 lastReadLength
/ AES_BLOCK_SIZE
,
973 vars
->buffer
+ vars
->bufferHalf
,
974 &cryptvars
->ctx
.decrypt
);
976 clock_get_uptime(&endTime
);
977 ADD_ABSOLUTETIME(&vars
->cryptTime
, &endTime
);
978 SUB_ABSOLUTETIME(&vars
->cryptTime
, &startTime
);
979 vars
->cryptBytes
+= lastReadLength
;
989 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */