Table of Contents
System Titles
New sysmodule ngc was added (0100000000000050). All sysmodules were updated (excluding stubbed-lbl). Most SystemData were updated, except for: Chinese and Korean dictionaries, Dictionary, AvatarImage, UrlBlackList, ControllerIcon, ApplicationBlackList, FunctionBlackList. Most applets were updated, except for: cabinet, controller, netConnect, swkbd, miiEdit, starter, maintenance. NPDM changes (besides usual version-bump):
boot2.ProdBoot now has access to ncm. friends no longer has access to csrng. nifm now has htc:nd access. nifm, ldn, ns: pl:u access was replaced with pl:s. ns now has access to ns:am2 and ns:su (for GetService). nim no longer has access to spl: (on older versions this was unused besides service-init). vi now has pl:u access. glue now has hosted-service pl:u access (moved from sdb) and access to svcCreateSharedMemory. fatal had access for the following removed: nvdrv:s, pl:u, vi:s. sdb had access for pl:u (hosted-service) and svcCreateSharedMemory removed. qlaunch, playerSelect, photoViewer, myPage: access to ngc:u was added. The SafeMode bootpkgs KIP for PCV had "Default CPU Core" changed from 3 to 63.
RomFs changes:
CertStore: "/ssl_TrustedCerts.bdf" updated and "/ssl_TrustedCerts.Ounce.bdf" added. ErrorMessage: updated BrowserDll: "/browser/MediaControlsInline.css" updated "/browser/MediaControlsInline.js" updated "/browser/UserCssCore0.dat" added "/browser/UserCss.dat" updated "/buildinfo/buildinfo.dat" updated "/gfxShader/" added, which contains "BrowserOffscreenDrawer.bnsh". "/lyt/Browse/Page.arc" updated "/nro/" The various NROs located under here were updated. Help: "/legallines.htdocs/img/HDMI.png" and "/legallines.htdocs/index.html" were updated. NgWord: updated. LocalNews: "/image/LnSupIntro/main_Other.jpg", "/message/EUnl/localNews.msbt.szs", "/message/revision.txt" updated. Eula: "/KRko/Eula.msbt.szs" and "/revision.txt" updated. FirmwareDebugSettings: updated NgWord2: updated. Added "/ac_similar_form_nx" and "/table_similar_form_nx". NgWordT: "/mars_dirty_words_db" updated applets: various UI/message/gfx data updated. web-applets: "/buildinfo/buildinfo.dat" and "/.nrr/modules.nrr" updated.
IPC Interface Changes
The following interfaces were removed: nn::pl::detail::IPlatformServiceManager The following interfaces were added: nn::ngc::detail::IService nn::pl::sharedresource::detail::IPlatformSharedResourceManager The following interfaces were changed: nn::account::IAccountEntityServiceForAccountPolicy Changed command 152 - buffer_entry_sizes: [0x401] -> [0x801] (final state: buffer_entry_sizes: [0x801], buffers: [0x1A], inbytes: 0x0, outbytes: 0x0) Added command 910 - inbytes: 0x0, outbytes: 0x0 nn::account::IAccountServiceForAdministrator Changed command 152 - buffer_entry_sizes: [0x401] -> [0x801] (final state: buffer_entry_sizes: [0x801], buffers: [0x1A], inbytes: 0x0, outbytes: 0x0) Added command 910 - inbytes: 0x0, outbytes: 0x0 nn::account::IAccountServiceForSystemService Changed command 152 - buffer_entry_sizes: [0x401] -> [0x801] (final state: buffer_entry_sizes: [0x801], buffers: [0x1A], inbytes: 0x0, outbytes: 0x0) nn::account::IAccountServiceForSystemServiceWithProfileEditor Changed command 152 - buffer_entry_sizes: [0x401] -> [0x801] (final state: buffer_entry_sizes: [0x801], buffers: [0x1A], inbytes: 0x0, outbytes: 0x0) nn::account::baas::IAdministrator Added command 161 - inbytes: 0x0, outbytes: 0x0 nn::account::baas::IManagerForSystemService Added command 161 - inbytes: 0x0, outbytes: 0x0 nn::account::nas::IOAuthProcedureForNintendoAccountLinkage Added command 200 - buffers: [0x9, 0x9, 0x9], inbytes: 0x0, outbytes: 0x0, outinterfaces: ['nn::account::detail::IAsyncContext'] nn::am::service::IApplicationFunctions Removed command 34 - buffers: [0x5], inbytes: 0x0, outbytes: 0x1 nn::am::service::IDebugFunctions Added command 51 - inbytes: 0x4, outbytes: 0x0 Added command 300 - inbytes: 0x0, outbytes: 0x0 nn::am::service::IHomeMenuFunctions Added command 50 - inbytes: 0x0, outbytes: 0x0 Added command 51 - inbytes: 0x0, outbytes: 0x0 nn::aocsrv::detail::IAddOnContentManager Added command 300 - inbytes: 0x8, outbytes: 0x0, pid: True Added command 301 - buffers: [0x6], inbytes: 0x10, outbytes: 0x0, pid: True Added command 302 - inbytes: 0x0, outbytes: 0x0 nn::bsdsocket::cfg::ServerInterface Added command 13 - buffers: [0x5], inbytes: 0x0, outbytes: 0x0 Added command 14 - buffers: [0x5], inbytes: 0x0, outbytes: 0x0 Added command 15 - buffers: [0x5], inbytes: 0x0, outbytes: 0x0 nn::codec::detail::IHardwareOpusDecoderManager Added command 8 - inbytes: 0x10, outbytes: 0x4 Added command 9 - buffer_entry_sizes: [0x118], buffers: [0x19], inbytes: 0x0, outbytes: 0x4 nn::dauth::detail::IService Added command 3 - inbytes: 0x8, outbytes: 0x10 Added command 13 - inbytes: 0x10, outbytes: 0x10 nn::dp2hdmi::detail::IDp2hdmiController Added command 7 - inbytes: 0x0, outbytes: 0x0 Added command 8 - inbytes: 0x4, inhandles: [1], outbytes: 0x0 nn::ec::IContentsServiceManager Added command 1 - buffers: [0x5], inbytes: 0x60, outbytes: 0x0, outhandles: [1], outinterfaces: [None], pid: True nn:🇪🇸:IActiveRightsContext Changed command 11 - inbytes: 0x8 -> 0x10 (final state: buffer_entry_sizes: [0x10], buffers: [0x6], inbytes: 0x10, outbytes: 0x4) Changed command 16 - inbytes: 0x8 -> 0x10 (final state: buffer_entry_sizes: [0x10], buffers: [0x6], inbytes: 0x10, outbytes: 0x4) Added command 18 - buffer_entry_sizes: [0x10, 0x0, 0x8], buffers: [0x6, 0x6, 0x6], inbytes: 0x10, outbytes: 0x8 nn:🇪🇸:IETicketService Removed command 3001 - buffer_entry_sizes: [0x40, 0x248, 0x0], buffers: [0x16, 0x16, 0x5], inbytes: 0x0, outbytes: 0x0 Removed command 3002 - buffer_entry_sizes: [0x248], buffers: [0x16], inbytes: 0x0, outbytes: 0x0 nn::fan::detail::IManager Added command 1 - inbytes: 0x4, outbytes: 0x4 nn::friends::detail::ipc::IServiceCreator Changed command 2 - outinterfaces: ['0x7100078D58'] -> ['0x710007990C'] (final state: inbytes: 0x0, outbytes: 0x0, outinterfaces: ['0x710007990C']) nn::fssrv::sf::IFileSystemProxy Added command 10 - buffer_entry_sizes: [0x301], buffers: [0x19], inbytes: 0x10, outbytes: 0x0, outinterfaces: ['nn::fssrv::sf::IFileSystem'] Changed command 206 - inbytes: 0x4 -> 0x8 (final state: buffer_entry_sizes: [0x301], buffers: [0x19], inbytes: 0x8, outbytes: 0x0, outinterfaces: ['nn::fssrv::sf::IStorage']) Removed command 609 - buffer_entry_sizes: [0x301], buffers: [0x19], inbytes: 0x0, outbytes: 0x10 Changed command 610 - inbytes: 0x0 -> 0x1 (final state: buffer_entry_sizes: [0x301], buffers: [0x19], inbytes: 0x1, outbytes: 0x18) nn::fssrv::sf::IFileSystemProxyForLoader Changed command 0 - inbytes: 0x8 -> 0x10 (final state: buffer_entry_sizes: [0x124, 0x301], buffers: [0x1A, 0x19], inbytes: 0x10, outbytes: 0x0, outinterfaces: ['nn::fssrv::sf::IFileSystem']) nn::hid::IHidDebugServer Added command 25 - inbytes: 0x1C, outbytes: 0x0 Added command 26 - inbytes: 0x0, outbytes: 0x0 Added command 3000 - inbytes: 0x0, outbytes: 0x0 nn::hid::IHidServer Added command 26 - inbytes: 0x8, outbytes: 0x0, pid: True nn::hid::IHidSystemServer Removed command 1130 - inbytes: 0x10, inhandles: [1], outbytes: 0x0, pid: True nn::ncm::IContentManager Added command 15 - inbytes: 0x4, outbytes: 0x0 nn::ncm::IContentStorage Changed command 19 - inbytes: 0x10 -> 0x11 (final state: inbytes: 0x11, outbytes: 0x18) Changed command 20 - inbytes: 0x10 -> 0x11 (final state: inbytes: 0x11, outbytes: 0x18) Changed command 27 - inbytes: 0x20 -> 0x21 (final state: inbytes: 0x21, outbytes: 0x18) nn::nim::detail::INetworkInstallManager Changed command 10 - outbytes: 0x58 -> 0x60 (final state: inbytes: 0x10, outbytes: 0x60) nn::ns::detail::IApplicationManagerInterface Changed command 21 - outbytes: 0x0 -> 0x1 (final state: buffer_entry_sizes: [0x300], buffers: [0x16], inbytes: 0x10, outbytes: 0x1) Removed command 604 - inbytes: 0x10, outbytes: 0x0 Added command 611 - inbytes: 0x10, outbytes: 0x0 nn::ns::detail::IDocumentInterface Changed command 21 - outbytes: 0x0 -> 0x1 (final state: buffer_entry_sizes: [0x300], buffers: [0x16], inbytes: 0x10, outbytes: 0x1) nn::ns::detail::IDynamicRightsInterface Removed command 14 - buffers: [0x5], inbytes: 0x8, outbytes: 0x1 nn::pdm::detail::IQueryService Changed command 0 - buffer_entry_sizes: [0x18] -> [0x28] (final state: buffer_entry_sizes: [0x28], buffers: [0x6], inbytes: 0x8, outbytes: 0x4) Changed command 4 - outbytes: 0x28 -> 0x48 (final state: inbytes: 0x10, outbytes: 0x48) Changed command 5 - outbytes: 0x28 -> 0x48 (final state: inbytes: 0x20, outbytes: 0x48) Changed command 10 - buffer_entry_sizes: [0x40] -> [0x38] (final state: buffer_entry_sizes: [0x38], buffers: [0x6], inbytes: 0x4, outbytes: 0x4) nn::pl::detail::IPlatformServiceManagerForSystem Removed command 0 - inbytes: 0x4, outbytes: 0x0 Removed command 1 - inbytes: 0x4, outbytes: 0x4 Removed command 2 - inbytes: 0x4, outbytes: 0x4 Removed command 3 - inbytes: 0x4, outbytes: 0x4 Removed command 4 - inbytes: 0x0, outbytes: 0x0, outhandles: [1] Removed command 5 - buffer_entry_sizes: [0x4, 0x4, 0x4], buffers: [0x6, 0x6, 0x6], inbytes: 0x8, outbytes: 0x8 Removed command 6 - buffer_entry_sizes: [0x4, 0x4, 0x4], buffers: [0x6, 0x6, 0x6], inbytes: 0x8, outbytes: 0x8 nn::ssl::sf::ISslConnection Added command 28 - buffers: [0x5], inbytes: 0x4, outbytes: 0x4 Added command 29 - buffers: [0x6], inbytes: 0x0, outbytes: 0x0 Added command 30 - inbytes: 0x8, outbytes: 0x0 Added command 31 - buffers: [0x5], inbytes: 0x0, outbytes: 0x0 Added command 32 - inbytes: 0x0, outbytes: 0x2 Added command 33 - buffers: [0x6, 0x5, 0x5], inbytes: 0x0, outbytes: 0x0 Added command 34 - inbytes: 0x4, outbytes: 0x0 Added command 35 - inbytes: 0x0, outbytes: 0x4 nn::ssl::sf::ISslContext Added command 12 - buffers: [0x5, 0x5], inbytes: 0x4, outbytes: 0x8 Added command 13 - buffers: [0x6, 0x6, 0x5], inbytes: 0x4, outbytes: 0x8 nn::ssl::sf::ISslContextForSystem Added command 12 - buffers: [0x5, 0x5], inbytes: 0x4, outbytes: 0x8 Added command 13 - buffers: [0x6, 0x6, 0x5], inbytes: 0x4, outbytes: 0x8 nn::visrv::sf::IManagerDisplayService Added command 2060 - inbytes: 0x4, outbytes: 0x0 Added command 2062 - buffers: [0x5], inbytes: 0x4, outbytes: 0x0 Added command 2063 - inbytes: 0x8, outbytes: 0x0 Added command 6014 - inbytes: 0x10, outbytes: 0x0 Added command 6015 - inbytes: 0x8, outbytes: 0x0 nn::visrv::sf::IManagerRootService Added command 100 - inbytes: 0x0, outbytes: 0x0 Added command 101 - inbytes: 0x0, outbytes: 0x0 Added command 102 - inbytes: 0x14, outbytes: 0x0 Added command 103 - buffer_entry_sizes: [0x4], buffers: [0x5], inbytes: 0x20, outbytes: 0x4
BootImagePackages
All files in RomFs were updated.
Using updated master-key: master_key_0f (previously master_key_0e). See NCA for the KeyGeneration listing.
INI1 changes:
BootImagePackageSafe: 010000000000001A (PCV): MainThreadCoreNumber updated: 0x3 -> 0x3F. BootImagePackageExFatSafe: 010000000000001A (PCV): MainThreadCoreNumber updated: 0x3 -> 0x3F.
Kernel
Compiler upgrade
Version is currently unknown, probably ~LLVM 15?
Many NOPs inserted to align branch destinations to 16 bytes, many ADRP + ADD pairs replaced with NOP + ADR
This probably corresponds to this commit? 4450a2a23d
Alexander Shaposhnikov, why did you do this, it makes diffing harder :(
Compiler now more frequently detecting a reusable computed offset for load/store
KThreadStackParameters:
Stack parameters are now 0x10 larger.
The additional 0x10 bytes appear to be completely unused, at least on prod NX builds of the kernel.
KScheduler changes:
Idle count tracking has been changed to use two fields ("idle count", "switch count").
In UpdateHighestThreads(), switching to the idle thread does idle_count = ++switch_count, and switching to a non-kernel thread does ++switch_count.
KProcess now has an additional array of counts ("running_thread_switch_counts"), UpdateHighestThreads() also sets running_thread_switch_counts[core] = switch_count.
KDebug::GetRunningThreadInfo() now only succeeds if running_thread_switch_counts[core] == Scheduler->switch_count + 1.
Previously, this checked running_thread_idle_counts[core] == Scheduler->idle_count, which meant the thread had to have not switched to idle between its last execution and the GetRunningThreadInfo() wait finishing.
Now, this requires the core to have switched directly from the target thread to GetRunningThreadInfo(), which is to say the condition is "The thread is actually running at the target time".
In addition, now ResultNoThread is returned if switch_count == idle_count + 1, otherwise ResultUnknownThread is returned; previously only NoThread was returnable.
switch_count == idle_count + 1 implies that the switch to GetRunningThreadInfo() happened from idle thread, so ResultNoThread is returned exactly when the running thread was the idle thread.
Otherwise, if a thread other than the idle thread was the running thread, UnknownThread is returned.
KSchedulerLock::Lock() now always increments count, instead of setting count = 1 when the lock owner is not the current thread.
Note: Several KScheduler functions have big assembly changes, but this appears to be pure compiler optimization changes with no semantic differences.
KProcess had the creation time member deleted.
A new KPageTable::Operate operation was added ("ChangePermsAndRefreshWithFlushDataCache")
Previously, all calls to Operate with ChangePermsAndRefresh would flush data cache; now, calls to ChangePermsAndRefresh do not flush data cache and calls to ChangePermsAndRefreshWithFlushDataCache do.
ChangePermsAndRefreshWithFlushDataCache is otherwise identical to ChangePermsAndRefresh semantically.
QueryIoMapping now supports querying memory regions with KMemoryState_Static in addition to KMemoryState_Io.
Some changes surrounding KIoRegion:
KIoRegion now uses an intrusive red black tree member for the pool list, rather than an intrusive list node.
KIoPool::AddIoRegion() uses the intrusive tree to check fewer regions for Contains().
KPageTableBase::UnmapIoRegion now takes the MemoryMapping as argument (which was passed to CreateIoRegion).
When mapping is MemoryMapping_Memory, the mapping following is done before unmap:
The region is permission changed to be uncached, using ChangePermsAndRefresh (without FlushDataCache).
The table's lock is released.
cpu::FlushDataCache() is called to flush the mapping.
The table's lock is reacquired.
All fallible operations now call KernelPanic() on failure, rather than returning the result code
KAddressSpaceInfo::GetAddressSpaceStart()/GetAddressSpaceSize() no longer use complicated switch logic to only examine the indices with the right bit-width, and instead just iterate all indices with an if to check bit width.
Big changes to KThread waiting/priority inheritance:
m_waiter_list, m_lock_owner fields were deleted.
New fields m_held_lock_info_list, m_waiting_lock_info were added.
This is an intrusive list of new type KThreadLockInfo (storing info on all locks held), and a pointer to the lock this thread is waiting on, if any.
There is one lock info for each address key.
KThreadLockInfo is slab allocated, count = # of KThreads
KThreadLockInfo has the following fields:
LockWithPriorityInheritanceThreadTree m_cv_tree; // Tree of threads waiting on the lock, this re-uses the node for condvar/arbiter.
KProcessAddress m_address_key;
KThread *m_owner;
u32 m_waiter_count;
This greatly simplifies RemoveWaiterByKey (as there is a single KThreadLockInfo representing all threads waiting on the key).
RemoveWaiterByKey now also has an output bool pointer for whether the lock still has waiters, rather than an output s32 pointer for # of waiters.
RestorePriority has been shuffled to ensure the new CV tree inside lock info has its invariants maintained across the priority set.
Several calls to RestorePriority are now guarded by if statements, to only invoke RestorePriority if there is a possible change in inherited priority.
Big changes to crt0/Initialize0/KInitialPageTable/Sleep Manager:
KInitialPageTable::Map (and others) now take a new physical-to-virtual-offset argument, and add this to L1 table etc.
Changes to Initial Arguments:
Initial arguments are now size 0x80.
Initial argument pointers are no longer used; Init arguments array addresses are used directly, with presumption that no page boundary is crossed.
Initial arguments no longer use setup function/etc.
Instead of setting ep = HorizonKernelMain, Initial arguments now set ep = InvokeMain (this function was previously "InvokeEntryPoint")
idle stack is now retrieved from KMemoryLayout inside InvokeMain, instead of being a field inside Initial Arguments.
After setting up initial arguments, Initialize0 now returns to crt0, which sets sp = InitArguments[0]->sp and calls new function ("Initialize1").
All KInitialPageTable calls from here onward now pass g_LinearPhysToVirtDiff, and thus page table accesses are done using the Linear mapping set up by Initialize0.
Initialize1 does the following:
The initial identity mapping is unmapped in its entirety.
The single-page containing crt0 + interrupt vectors is re-identity-mapped as R-X.
PageAllocator for this is an extremely simplified new InitialPageAllocator type, which always has exactly two free pages to be allocated.
All remaining logic which used to be in Initialize0 happens here, with no changes.
TurnOnAllCores now calls a helper function ("TurnOnCore") to turn on the cores.
void TurnOnCore(__int64 core, InitArguments *argument);
TurnOnCore does virt->phys translation lookup (using at s1e1r) on StartOtherCore (from crt0 page) + argument, and calls smc::CpuOn directly.
TurnOnCore is "probably" a KSystemControl function.
Sleep handler thread function now sets resume entry addr = StartOtherCore, and sets up an InitArguments for each core.
ResumeEntry and ResumeEntryVirtual are now merged/simplified.
Changes to pool allocations:
Minimum non-secure system pool size is now ~2MB larger (0x2C04000 vs 0x2A0C000).
Slab heap gaps size is now 0x9000 smaller (0x1A7000 vs 0x1B0000).
KSystemControl::Initialize has been restructured (operations reordered), and now calls a helper which sets up the MT, creates system resource limit, etc.
This helper also modifies the KAddressSpaceInfo tables, when memory is large (these were previously read-only).
In particular, the following modifications are made to the 39-bit address space infos based on the total memory size:
size <= 8 GB: No changes (Heap Region = 8 GB, Alias region = 64 GB)
8 GB < size <= 16 GB: Heap Region = size, Alias Region = 8 * size
16 GB < size <= 32 GB: Heap region = size, Alias region = 128 GB
32 GB <= size: Heap region = 32 GB, Alias region = 128 GB
KSystemControl::Init::GenerateRandomRange now supports min=0, max=0xFFFFFFFFFFFFFFFF (previously it was incorrect for this case).
New InfoType (0x1B) ("IoRegionHint")
This takes a handle to a KIoRegion, and returns the low bits of the region's address.
If the region's size is < 0x10000, this is the low 12 bits, otherwise if size < 0x200000, this is the low 16 bits, otherwise it's the low 21 bits.
UserspaceAccess functions no longer do adr X30, fail in the loop, now do adr X#, fail before the loop and mov X30, X# in the loop.
All code which sets ThreadContext's pstate field now uses the mask 0xF0000000 for aarch64 threads and 0xFE0FFE20 for aarch32 threads.
Previously, this used the mask 0xFF0FFE20 for both.
This removes the ability to get/set the DIT bit for both aarch64 and aarch32, and removes many other bits for aarch64 only.
Interrupt disable logic was removed from a number of functions:
KAddressArbiter::SignalAndIncrementIfEqual, KAddressArbiter::SignalAndModifyBasedOnWaitingThreadCount, KAddressArbiter::WaitIfLessThan, KConditionVariable::SignalConditionVariableImpl
KConditionVariable::SignalToAddress now does dmb before copying updated value to userspace.
KDebugBase functions for DebugEvents were changed to take pointer to params + count, instead of 5 parameter arguments.
This propagates up to many/all caller functions.
The only variable length parameter counts are DebugEvent_Exception + DebugException_UserBreak/DebugException_DebuggerBreak
This copies the variable-count parameters directly to the result exception info without maximum size check.
This is not exploitable, because there is no way for userspace to control parameter count, and it will always remain in bounds.
Presumably exception info type is larger if compiling for a target with more than 4 CPUs, to prevent out-of-bounds copies.
usb
A vuln was fixed.
bluetooth
An IPC vuln due to a regression was fixed.
LibraryAppletError
As described here, nnSdk now supports two ErrorMessage SystemDataIds. NX LibraryAppletError is hard-coded for using the original ErrorMessage SystemDataId, the new ErrorMessage SystemData doesn't exist on NX retail.