private ResultCode UnmapNroFromInfo(NroInfo info) { ulong textSize = (ulong)info.Executable.Text.Length; ulong roSize = (ulong)info.Executable.Ro.Length; ulong dataSize = (ulong)info.Executable.Data.Length; ulong bssSize = (ulong)info.Executable.BssSize; KernelResult result = KernelResult.Success; if (info.Executable.BssSize != 0) { result = _owner.MemoryManager.UnmapProcessCodeMemory( info.NroMappedAddress + textSize + roSize + dataSize, info.Executable.BssAddress, bssSize); } if (result == KernelResult.Success) { result = _owner.MemoryManager.UnmapProcessCodeMemory( info.NroMappedAddress + textSize + roSize, info.Executable.SourceAddress + textSize + roSize, dataSize); if (result == KernelResult.Success) { result = _owner.MemoryManager.UnmapProcessCodeMemory( info.NroMappedAddress, info.Executable.SourceAddress, textSize + roSize); } } return((ResultCode)result); }
private ResultCode MapNro(KProcess process, NroInfo info, out ulong nroMappedAddress) { KMemoryManager memMgr = process.MemoryManager; int retryCount = 0; nroMappedAddress = 0; while (retryCount++ < MaxMapRetries) { ResultCode result = MapCodeMemoryInProcess(process, info.NroAddress, info.NroSize, out nroMappedAddress); if (result != ResultCode.Success) { return(result); } if (info.BssSize > 0) { KernelResult bssMappingResult = memMgr.MapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize); if (bssMappingResult == KernelResult.InvalidMemState) { memMgr.UnmapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize); memMgr.UnmapProcessCodeMemory(nroMappedAddress, info.NroAddress, info.NroSize); continue; } else if (bssMappingResult != KernelResult.Success) { memMgr.UnmapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize); memMgr.UnmapProcessCodeMemory(nroMappedAddress, info.NroAddress, info.NroSize); return((ResultCode)bssMappingResult); } } if (CanAddGuardRegionsInProcess(process, nroMappedAddress, info.TotalSize)) { return(ResultCode.Success); } } return(ResultCode.InsufficientAddressSpace); }
public ResultCode ParseNro(out NroInfo res, ServiceCtx context, ulong nroAddress, ulong nroSize, ulong bssAddress, ulong bssSize) { res = null; if (_nroInfos.Count >= MaxNro) { return(ResultCode.TooManyNro); } else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0) { return(ResultCode.InvalidSize); } else if (bssSize != 0 && bssAddress + bssSize <= bssAddress) { return(ResultCode.InvalidSize); } else if ((nroAddress & 0xFFF) != 0) { return(ResultCode.InvalidAddress); } uint magic = context.Memory.ReadUInt32((long)nroAddress + 0x10); uint nroFileSize = context.Memory.ReadUInt32((long)nroAddress + 0x18); if (magic != NroMagic || nroSize != nroFileSize) { return(ResultCode.InvalidNro); } byte[] nroData = context.Memory.ReadBytes((long)nroAddress, (long)nroSize); byte[] nroHash = null; MemoryStream stream = new MemoryStream(nroData); using (SHA256 hasher = SHA256.Create()) { nroHash = hasher.ComputeHash(stream); } if (!IsNroHashPresent(nroHash)) { return(ResultCode.NotRegistered); } if (IsNroLoaded(nroHash)) { return(ResultCode.AlreadyLoaded); } stream.Position = 0; NxRelocatableObject executable = new NxRelocatableObject(stream, nroAddress, bssAddress); // check if everything is page align. if ((executable.Text.Length & 0xFFF) != 0 || (executable.Ro.Length & 0xFFF) != 0 || (executable.Data.Length & 0xFFF) != 0 || (executable.BssSize & 0xFFF) != 0) { return(ResultCode.InvalidNro); } // check if everything is contiguous. if (executable.RoOffset != executable.TextOffset + executable.Text.Length || executable.DataOffset != executable.RoOffset + executable.Ro.Length || nroFileSize != executable.DataOffset + executable.Data.Length) { return(ResultCode.InvalidNro); } // finally check the bss size match. if ((ulong)executable.BssSize != bssSize) { return(ResultCode.InvalidNro); } int totalSize = executable.Text.Length + executable.Ro.Length + executable.Data.Length + executable.BssSize; res = new NroInfo( executable, nroHash, nroAddress, nroSize, bssAddress, bssSize, (ulong)totalSize); return(ResultCode.Success); }
public ResultCode ParseNro(out NroInfo res, ServiceCtx context, ulong nroAddress, ulong nroSize, ulong bssAddress, ulong bssSize) { res = null; if (_nroInfos.Count >= MaxNro) { return(ResultCode.TooManyNro); } else if (nroSize == 0 || nroAddress + nroSize <= nroAddress || (nroSize & 0xFFF) != 0) { return(ResultCode.InvalidSize); } else if (bssSize != 0 && bssAddress + bssSize <= bssAddress) { return(ResultCode.InvalidSize); } else if ((nroAddress & 0xFFF) != 0) { return(ResultCode.InvalidAddress); } uint magic = _owner.CpuMemory.Read <uint>(nroAddress + 0x10); uint nroFileSize = _owner.CpuMemory.Read <uint>(nroAddress + 0x18); if (magic != NroMagic || nroSize != nroFileSize) { return(ResultCode.InvalidNro); } byte[] nroData = new byte[nroSize]; _owner.CpuMemory.Read(nroAddress, nroData); byte[] nroHash = null; MemoryStream stream = new MemoryStream(nroData); using (SHA256 hasher = SHA256.Create()) { nroHash = hasher.ComputeHash(stream); } if (!IsNroHashPresent(nroHash)) { return(ResultCode.NotRegistered); } if (IsNroLoaded(nroHash)) { return(ResultCode.AlreadyLoaded); } stream.Position = 0; NroExecutable nro = new NroExecutable(stream.AsStorage(), nroAddress, bssAddress); // Check if everything is page align. if ((nro.Text.Length & 0xFFF) != 0 || (nro.Ro.Length & 0xFFF) != 0 || (nro.Data.Length & 0xFFF) != 0 || (nro.BssSize & 0xFFF) != 0) { return(ResultCode.InvalidNro); } // Check if everything is contiguous. if (nro.RoOffset != nro.TextOffset + nro.Text.Length || nro.DataOffset != nro.RoOffset + nro.Ro.Length || nroFileSize != nro.DataOffset + nro.Data.Length) { return(ResultCode.InvalidNro); } // Check the bss size match. if ((ulong)nro.BssSize != bssSize) { return(ResultCode.InvalidNro); } uint totalSize = (uint)nro.Text.Length + (uint)nro.Ro.Length + (uint)nro.Data.Length + nro.BssSize; // Apply patches context.Device.FileSystem.ModLoader.ApplyNroPatches(nro); res = new NroInfo( nro, nroHash, nroAddress, nroSize, bssAddress, bssSize, (ulong)totalSize); return(ResultCode.Success); }