In my account of how Tahoe updates macOS, I had reached the stage when Rosetta and the main update had started downloading from Pallas, Apple’s software update server (see the Appendix at the end for further explanation of terms used).
Download
Currently, the main update download (at least) is compressed using Zip, and is decompressed as a stream during download, so there’s no delay decompressing during the preparation phase later.
In this case, downloading the main update was completed within 8 minutes. The source of the Zip archive was originally given as a path on [https://]updates.cdn-apple.com/2026WinterFCS/patches, and that was written to a local path on /System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/ In my case, though, I have a local Content Caching Server running, and immediately before the download started com.apple.AssetCacheServices substituted a download URL on that server to ensure the update was obtained through the local caching server. At the same time, an Event Report was sent back to Apple, recording the start of download.
Progress was updated every second during the download, and brought the progress bar from 16% to 53.9% over the following 8 minutes, with little other activity taking place.
Preflight
Activity then changed to what is repeatedly referred to as Preflight FDR Recovery, and is the first entry point for the UpdateBrainService, downloaded for MobileSoftwareUpdate rather than softwareupdated.
This runs an Event Recorder and begins to perform preflight checks to “recover FDR SFR”, and to perform a “firmware-only update”. To prepare for that, it retrieves various nonces and their digests for LocalPolicy, RecoveryOS boot policy, and others. Following those is the first of many attempts to determine purgeable space, in preparation for installation of the update. Those are performed by com.apple.cache_delete.
Pallas was then checked to see if there was any more recent version of RecoveryOS UpdateBrain, but there wasn’t. A further check for any newer recoveryOS was also made, before the main macOS update was prepared, at a progress level of 60% as set previously.
Preparation
The first step of the main preparation phase is to purge staged assets with com.apple.cache_delete. With that complete, UpdateBrainService recalculates cryptex size requirement for the update, and the install target prepare size:
- cryptex size is 1.2 times the app cryptex size = 60 MB, plus 1.2 times the system cryptex size = 7749 MB, a total of 7809 MB, as previously calculated;
- prepare size is the sum of the snapshot installation size of 3785 MB, the cryptex size of 7809 MB, three ‘slack sizes’ for VW, Recovery and Preboot of 2048 + 1024 + 1024 = 4096 MB, the new template size of 991 MB, twice the update partition size totalling 600 MB, less the old template size of 363 MB. The grand total comes to 16,918 MB.
UpdateBrainService then checks volume free sizes, and confirms that they’re sufficient to complete the update. It next creates a ‘stash’, which is protected by keys in the stash keybag, handled by the Secure Enclave Processor. There is then another round of purging with com.apple.cache_delete.
Much of the preparation phase is spent verifying the protection of installation packages, cryptexes, then the contents of /System/Applications and /System/Library. As progress is about 64% complete, System volume preparations are started, and there’s another round of purging by com.apple.cache_delete. There’s surprisingly little log activity as progress passes 70% complete.
With progress reaching 84% complete, UpdateBrainService starts unarchiving files in parallel, taking just under 5 seconds to complete those. Following that, there’s another brief period unarchiving data files in parallel, then working with the contents of /System/Volumes/Update/mnt1/private/var/MobileAsset/PreinstalledAssetsV2 as progress reaches 87% complete.
When there’s 87.5% completed, UpdateBrainService reports it’s creating hard links in parallel, then is searching for new paths and verifying files, such as those in the Ruby framework. The Recovery volume is unmounted, and there’s yet another purge with com.apple.cache_delete. After those, key volume locations are checked.
The high water mark of disk usage during update is prepared. This reveals some of the steps to be undertaken during installation, including:
- prepare source package,
- patch cryptexes,
- patch system volume,
- extract to system volume,
- install personalised.
There’s a further round of purging with cache_delete before declaring PrepareUpdate as successful, then suspending the update briefly. When update resumes, the Update volume is mounted and prepared, and there’s another round of purging. The System volume is then mounted, checked, and prepared. Progress is now at 98.5% complete, and once 100% is reached, the countdown to restarting the Mac is begun.
Installation
During the download and preparation phases, apart from repeated purging, the log is generally quiet. This changes dramatically once the Mac starts preparing for shutdown and installation. WebKit is cleaned up and shut down, as are many other processes. The ‘stash’ of update components is then committed, and final scans and checks are completed.
The update is then applied, followed by Rosetta, RecoveryOS, UpdateBrain and finally minor documentation. After that period of nearly 20 seconds, this phase is declared complete, and a restart is notified before waiting for the essential reboot.
Reboot
Once rebooting by root has been initiated, the boot chime is muted to ensure the update continues in silence. The last log message is written a few seconds later, and UpdateBrain then runs the update.
Less than 3 minutes later, the system boot is recorded in the log, and kprintf is initialised 5 seconds later. About 3 minutes afterwards softwareupdated is started up, and runs various clean-up routines to complete the update sequence in conjunction with ControllerSetup and a Finite State Machine.
Key points
- The main update download is decompressed while streaming, to save preparation time later.
- If a local Content Caching Server is connected, AssetCacheServices will substitute its IP address for that of the Pallas server to ensure the download is obtained through the cache.
- Following download, extensive preflight checks are performed.
- During preparation components are verified, paths checked, and some unarchiving is performed.
- Prior to reboot and installation, processes including WebKit are shut down in readiness for reboot and install.
- The boot chime is muted.
- Once rebooted, clean-up is performed.
Previously
How macOS 26 Tahoe updates 1
How macOS 26 Tahoe updates: 2 Finite state machines
How macOS 26 Tahoe updates: 3 Catalogues and preparing to download
Appendix: Terms used
- FDR is unknown, but appears associated almost exclusively with a preflight phase.
- Pallas is the internal name for Apple’s software update server. This appears throughout log entries, where for example Pallas audience is jargon for the type of user, normally macOS Customer.
- RecoveryOS appears to refer to the version of Recovery in the hidden container of the internal SSD, more widely known as Fallback Recovery.
- SFR appears to refer to the version of Recovery in the Recovery volume of the active boot volume group, also known as Paired Recovery.
- Splat, semi-splat and rollback objects all refer to cryptexes. Splat is the general term, while semi-splat refers to a cryptex-based update that might include rapid security responses (RSR) and background security improvements (BSI) implemented by replacing one or both cryptexes. Rollback objects are older versions of a cryptex that have been saved to allow a newer cryptex to be reverted to that older one, in the event that the newer cryptex causes problems.
- UpdateBrain is the executable code supplied as part of an update that prepares and installs that specific update. There’s a separate UpdateBrainService for RecoveryOS.
