Esempio n. 1
0
        private static int Alloc(ServiceCtx Context)
        {
            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

            NvMapAlloc Args = MemoryHelper.Read <NvMapAlloc>(Context.Memory, InputPosition);

            NvMapHandle Map = GetNvMap(Context, Args.Handle);

            if (Map == null)
            {
                Logger.PrintWarning(LogClass.ServiceNv, $"Invalid handle 0x{Args.Handle:x8}!");

                return(NvResult.InvalidInput);
            }

            if ((Args.Align & (Args.Align - 1)) != 0)
            {
                Logger.PrintWarning(LogClass.ServiceNv, $"Invalid alignment 0x{Args.Align:x8}!");

                return(NvResult.InvalidInput);
            }

            if ((uint)Args.Align < NvGpuVmm.PageSize)
            {
                Args.Align = NvGpuVmm.PageSize;
            }

            int Result = NvResult.Success;

            if (!Map.Allocated)
            {
                Map.Allocated = true;

                Map.Align = Args.Align;
                Map.Kind  = (byte)Args.Kind;

                int Size = IntUtils.AlignUp(Map.Size, NvGpuVmm.PageSize);

                long Address = Args.Address;

                if (Address == 0)
                {
                    //When the address is zero, we need to allocate
                    //our own backing memory for the NvMap.
                    //TODO: Is this allocation inside the transfer memory?
                    Result = NvResult.OutOfMemory;
                }

                if (Result == NvResult.Success)
                {
                    Map.Size    = Size;
                    Map.Address = Address;
                }
            }

            MemoryHelper.Write(Context.Memory, OutputPosition, Args);

            return(Result);
        }
Esempio n. 2
0
        private static int Alloc(ServiceCtx context)
        {
            long inputPosition  = context.Request.GetBufferType0x21().Position;
            long outputPosition = context.Request.GetBufferType0x22().Position;

            NvMapAlloc args = MemoryHelper.Read <NvMapAlloc>(context.Memory, inputPosition);

            NvMapHandle map = GetNvMap(context, args.Handle);

            if (map == null)
            {
                Logger.PrintWarning(LogClass.ServiceNv, $"Invalid handle 0x{args.Handle:x8}!");

                return(NvResult.InvalidInput);
            }

            if ((args.Align & (args.Align - 1)) != 0)
            {
                Logger.PrintWarning(LogClass.ServiceNv, $"Invalid alignment 0x{args.Align:x8}!");

                return(NvResult.InvalidInput);
            }

            if ((uint)args.Align < NvGpuVmm.PageSize)
            {
                args.Align = NvGpuVmm.PageSize;
            }

            int result = NvResult.Success;

            if (!map.Allocated)
            {
                map.Allocated = true;

                map.Align = args.Align;
                map.Kind  = (byte)args.Kind;

                int size = IntUtils.AlignUp(map.Size, NvGpuVmm.PageSize);

                long address = args.Address;

                if (address == 0)
                {
                    //When the address is zero, we need to allocate
                    //our own backing memory for the NvMap.
                    //TODO: Is this allocation inside the transfer memory?
                    result = NvResult.OutOfMemory;
                }

                if (result == NvResult.Success)
                {
                    map.Size    = size;
                    map.Address = address;
                }
            }

            MemoryHelper.Write(context.Memory, outputPosition, args);

            return(result);
        }
Esempio n. 3
0
        public bool Run(bool NeedsHbAbi = false)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException(nameof(Process));
            }

            this.NeedsHbAbi = NeedsHbAbi;

            if (Executables.Count == 0)
            {
                return(false);
            }

            long MainStackTop = MemoryManager.CodeRegionEnd - KMemoryManager.PageSize;

            long MainStackSize = 1 * 1024 * 1024;

            long MainStackBottom = MainStackTop - MainStackSize;

            MemoryManager.HleMapCustom(
                MainStackBottom,
                MainStackSize,
                MemoryState.MappedMemory,
                MemoryPermission.ReadAndWrite);

            int Handle = MakeThread(Executables[0].ImageBase, MainStackTop, 0, 44, 0);

            if (Handle == -1)
            {
                return(false);
            }

            KThread MainThread = HandleTable.GetKThread(Handle);

            if (NeedsHbAbi)
            {
                HbAbiDataPosition = IntUtils.AlignUp(Executables[0].ImageEnd, KMemoryManager.PageSize);

                const long HbAbiDataSize = KMemoryManager.PageSize;

                MemoryManager.HleMapCustom(
                    HbAbiDataPosition,
                    HbAbiDataSize,
                    MemoryState.MappedMemory,
                    MemoryPermission.ReadAndWrite);

                string SwitchPath = Device.FileSystem.SystemPathToSwitchPath(Executables[0].FilePath);

                Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle, SwitchPath);

                MainThread.Context.ThreadState.X0 = (ulong)HbAbiDataPosition;
                MainThread.Context.ThreadState.X1 = ulong.MaxValue;
            }

            MainThread.TimeUp();

            return(true);
        }
Esempio n. 4
0
        public void LoadProgram(IExecutable Program)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException(nameof(Process));
            }

            long ImageEnd = LoadProgram(Program, ImageBase);

            ImageBase = IntUtils.AlignUp(ImageEnd, KMemoryManager.PageSize);
        }
Esempio n. 5
0
        private static int EdgeMatrixGetWorkBufferSize(int Value)
        {
            int Result = IntUtils.AlignUp(Value * Value, 64);

            if (Result < 0)
            {
                Result |= 7;
            }

            return(Result / 8);
        }
Esempio n. 6
0
        private static int NodeStatesGetWorkBufferSize(int Value)
        {
            int Result = IntUtils.AlignUp(Value, 64);

            if (Result < 0)
            {
                Result |= 7;
            }

            return(4 * (Value * Value) + 0x12 * Value + 2 * (Result / 8));
        }
Esempio n. 7
0
        private static int EdgeMatrixGetWorkBufferSize(int value)
        {
            int result = IntUtils.AlignUp(value * value, 64);

            if (result < 0)
            {
                result |= 7;
            }

            return(result / 8);
        }
Esempio n. 8
0
        private static int NodeStatesGetWorkBufferSize(int value)
        {
            int result = IntUtils.AlignUp(value, 64);

            if (result < 0)
            {
                result |= 7;
            }

            return(4 * (value * value) + 0x12 * value + 2 * (result / 8));
        }
Esempio n. 9
0
        public void LoadProgram(IExecutable Program)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException(nameof(Process));
            }

            Device.Log.PrintInfo(LogClass.Loader, $"Image base at 0x{ImageBase:x16}.");

            Executable Executable = new Executable(Program, MemoryManager, Memory, ImageBase);

            Executables.Add(Executable);

            ImageBase = IntUtils.AlignUp(Executable.ImageEnd, KMemoryManager.PageSize);
        }
Esempio n. 10
0
        private static int Create(ServiceCtx Context)
        {
            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

            NvMapCreate Args = AMemoryHelper.Read <NvMapCreate>(Context.Memory, InputPosition);

            if (Args.Size == 0)
            {
                Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid size 0x{Args.Size:x8}!");

                return(NvResult.InvalidInput);
            }

            int Size = IntUtils.AlignUp(Args.Size, NvGpuVmm.PageSize);

            Args.Handle = AddNvMap(Context, new NvMapHandle(Size));

            Context.Ns.Log.PrintInfo(LogClass.ServiceNv, $"Created map {Args.Handle} with size 0x{Size:x8}!");

            AMemoryHelper.Write(Context.Memory, OutputPosition, Args);

            return(NvResult.Success);
        }
Esempio n. 11
0
        private static int Create(ServiceCtx context)
        {
            long inputPosition  = context.Request.GetBufferType0x21().Position;
            long outputPosition = context.Request.GetBufferType0x22().Position;

            NvMapCreate args = MemoryHelper.Read <NvMapCreate>(context.Memory, inputPosition);

            if (args.Size == 0)
            {
                Logger.PrintWarning(LogClass.ServiceNv, $"Invalid size 0x{args.Size:x8}!");

                return(NvResult.InvalidInput);
            }

            int size = IntUtils.AlignUp(args.Size, NvGpuVmm.PageSize);

            args.Handle = AddNvMap(context, new NvMapHandle(size));

            Logger.PrintInfo(LogClass.ServiceNv, $"Created map {args.Handle} with size 0x{size:x8}!");

            MemoryHelper.Write(context.Memory, outputPosition, args);

            return(NvResult.Success);
        }
Esempio n. 12
0
        public long GetAudioRendererWorkBufferSize(ServiceCtx Context)
        {
            AudioRendererParameter Params = GetAudioRendererParameter(Context);

            int Revision = (Params.Revision - Rev0Magic) >> 24;

            if (Revision <= Rev)
            {
                bool IsSplitterSupported = Revision >= 3;

                long Size;

                Size  = IntUtils.AlignUp(Params.Unknown8 * 4, 64);
                Size += Params.MixCount * 0x400;
                Size += (Params.MixCount + 1) * 0x940;
                Size += Params.VoiceCount * 0x3F0;
                Size += IntUtils.AlignUp((Params.MixCount + 1) * 8, 16);
                Size += IntUtils.AlignUp(Params.VoiceCount * 8, 16);
                Size += IntUtils.AlignUp(
                    ((Params.SinkCount + Params.MixCount) * 0x3C0 + Params.SampleCount * 4) *
                    (Params.Unknown8 + 6), 64);
                Size += (Params.SinkCount + Params.MixCount) * 0x2C0;
                Size += (Params.EffectCount + Params.VoiceCount * 4) * 0x30 + 0x50;

                if (IsSplitterSupported)
                {
                    Size += IntUtils.AlignUp((
                                                 NodeStatesGetWorkBufferSize(Params.MixCount + 1) +
                                                 EdgeMatrixGetWorkBufferSize(Params.MixCount + 1)), 16);

                    Size += Params.SplitterDestinationDataCount * 0xE0;
                    Size += Params.SplitterCount * 0x20;
                    Size += IntUtils.AlignUp(Params.SplitterDestinationDataCount * 4, 16);
                }

                Size = Params.EffectCount * 0x4C0 +
                       Params.SinkCount * 0x170 +
                       Params.VoiceCount * 0x100 +
                       IntUtils.AlignUp(Size, 64) + 0x40;

                if (Params.PerformanceManagerCount >= 1)
                {
                    Size += (((Params.EffectCount +
                               Params.SinkCount +
                               Params.VoiceCount +
                               Params.MixCount + 1) * 16 + 0x658) *
                             (Params.PerformanceManagerCount + 1) + 0x13F) & ~0x3FL;
                }

                Size = (Size + 0x1907D) & ~0xFFFL;

                Context.ResponseData.Write(Size);

                Context.Device.Log.PrintDebug(LogClass.ServiceAudio, $"WorkBufferSize is 0x{Size:x16}.");

                return(0);
            }
            else
            {
                Context.ResponseData.Write(0L);

                Context.Device.Log.PrintWarning(LogClass.ServiceAudio, $"Library Revision 0x{Params.Revision:x8} is not supported!");

                return(MakeError(ErrorModule.Audio, AudErr.UnsupportedRevision));
            }
        }
Esempio n. 13
0
        public Executable(IExecutable Exe, KMemoryManager MemoryManager, AMemory Memory, long ImageBase)
        {
            Dynamic = new List <ElfDyn>();

            FilePath = Exe.FilePath;

            if (FilePath != null)
            {
                Name = Path.GetFileNameWithoutExtension(FilePath.Replace(Homebrew.TemporaryNroSuffix, ""));
            }

            this.Memory        = Memory;
            this.MemoryManager = MemoryManager;
            this.ImageBase     = ImageBase;
            this.ImageEnd      = ImageBase;

            long TextPosition = ImageBase + (uint)Exe.TextOffset;
            long ROPosition   = ImageBase + (uint)Exe.ROOffset;
            long DataPosition = ImageBase + (uint)Exe.DataOffset;

            long TextSize = (uint)IntUtils.AlignUp(Exe.Text.Length, KMemoryManager.PageSize);
            long ROSize   = (uint)IntUtils.AlignUp(Exe.RO.Length, KMemoryManager.PageSize);
            long DataSize = (uint)IntUtils.AlignUp(Exe.Data.Length, KMemoryManager.PageSize);

            long DataAndBssSize = (uint)IntUtils.AlignUp(Exe.BssSize, KMemoryManager.PageSize) + DataSize;

            ImageEnd = DataPosition + DataAndBssSize;

            MemoryManager.HleMapProcessCode(TextPosition, TextSize + ROSize + DataAndBssSize);

            MemoryManager.SetProcessMemoryPermission(ROPosition, ROSize, MemoryPermission.Read);
            MemoryManager.SetProcessMemoryPermission(DataPosition, DataAndBssSize, MemoryPermission.ReadAndWrite);

            Memory.WriteBytes(TextPosition, Exe.Text);
            Memory.WriteBytes(ROPosition, Exe.RO);
            Memory.WriteBytes(DataPosition, Exe.Data);

            if (Exe.Mod0Offset == 0)
            {
                return;
            }

            long Mod0Offset = ImageBase + Exe.Mod0Offset;

            int  Mod0Magic        = Memory.ReadInt32(Mod0Offset + 0x0);
            long DynamicOffset    = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset;
            long BssStartOffset   = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset;
            long BssEndOffset     = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset;
            long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset;
            long EhHdrEndOffset   = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset;
            long ModObjOffset     = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset;

            while (true)
            {
                long TagVal = Memory.ReadInt64(DynamicOffset + 0);
                long Value  = Memory.ReadInt64(DynamicOffset + 8);

                DynamicOffset += 0x10;

                ElfDynTag Tag = (ElfDynTag)TagVal;

                if (Tag == ElfDynTag.DT_NULL)
                {
                    break;
                }

                Dynamic.Add(new ElfDyn(Tag, Value));
            }

            long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB);
            long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB);

            long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);

            List <ElfSym> Symbols = new List <ElfSym>();

            while ((ulong)SymTblAddr < (ulong)StrTblAddr)
            {
                ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr);

                Symbols.Add(Sym);

                SymTblAddr += SymEntSize;
            }

            SymbolTable = Array.AsReadOnly(Symbols.OrderBy(x => x.Value).ToArray());
        }
Esempio n. 14
0
        public long GetAudioRendererWorkBufferSize(ServiceCtx context)
        {
            AudioRendererParameter Params = GetAudioRendererParameter(context);

            int revision = (Params.Revision - Rev0Magic) >> 24;

            if (revision <= Rev)
            {
                bool isSplitterSupported = revision >= 3;
                bool isVariadicCommandBufferSizeSupported = revision >= 5;

                long size;

                size  = IntUtils.AlignUp(Params.Unknown8 * 4, 64);
                size += Params.MixCount * 0x400;
                size += (Params.MixCount + 1) * 0x940;
                size += Params.VoiceCount * 0x3F0;
                size += IntUtils.AlignUp((Params.MixCount + 1) * 8, 16);
                size += IntUtils.AlignUp(Params.VoiceCount * 8, 16);
                size += IntUtils.AlignUp(
                    ((Params.SinkCount + Params.MixCount) * 0x3C0 + Params.SampleCount * 4) *
                    (Params.Unknown8 + 6), 64);
                size += (Params.SinkCount + Params.MixCount) * 0x2C0;
                size += (Params.EffectCount + Params.VoiceCount * 4) * 0x30 + 0x50;

                if (isSplitterSupported)
                {
                    size += IntUtils.AlignUp((
                                                 NodeStatesGetWorkBufferSize(Params.MixCount + 1) +
                                                 EdgeMatrixGetWorkBufferSize(Params.MixCount + 1)), 16);

                    size += Params.SplitterDestinationDataCount * 0xE0;
                    size += Params.SplitterCount * 0x20;
                    size += IntUtils.AlignUp(Params.SplitterDestinationDataCount * 4, 16);
                }

                size = Params.EffectCount * 0x4C0 +
                       Params.SinkCount * 0x170 +
                       Params.VoiceCount * 0x100 +
                       IntUtils.AlignUp(size, 64) + 0x40;

                if (Params.PerformanceManagerCount >= 1)
                {
                    size += (((Params.EffectCount +
                               Params.SinkCount +
                               Params.VoiceCount +
                               Params.MixCount + 1) * 16 + 0x658) *
                             (Params.PerformanceManagerCount + 1) + 0x13F) & ~0x3FL;
                }

                if (isVariadicCommandBufferSizeSupported)
                {
                    size += Params.EffectCount * 0x840 +
                            Params.MixCount * 0x5A38 +
                            Params.SinkCount * 0x148 +
                            Params.SplitterDestinationDataCount * 0x540 +
                            Params.VoiceCount * (Params.SplitterCount * 0x68 + 0x2E0) +
                            ((Params.VoiceCount + Params.MixCount + Params.EffectCount + Params.SinkCount + 0x65) << 6) + 0x3F8 + 0x7E;
                }
                else
                {
                    size += 0x1807E;
                }

                size = size & ~0xFFFL;

                context.ResponseData.Write(size);

                Logger.PrintDebug(LogClass.ServiceAudio, $"WorkBufferSize is 0x{size:x16}.");

                return(0);
            }
            else
            {
                context.ResponseData.Write(0L);

                Logger.PrintWarning(LogClass.ServiceAudio, $"Library Revision 0x{Params.Revision:x8} is not supported!");

                return(MakeError(ErrorModule.Audio, AudErr.UnsupportedRevision));
            }
        }