Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }