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); }
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); }
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); }
public void LoadProgram(IExecutable Program) { if (Disposed) { throw new ObjectDisposedException(nameof(Process)); } long ImageEnd = LoadProgram(Program, ImageBase); ImageBase = IntUtils.AlignUp(ImageEnd, KMemoryManager.PageSize); }
private static int EdgeMatrixGetWorkBufferSize(int Value) { int Result = IntUtils.AlignUp(Value * Value, 64); if (Result < 0) { Result |= 7; } return(Result / 8); }
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)); }
private static int EdgeMatrixGetWorkBufferSize(int value) { int result = IntUtils.AlignUp(value * value, 64); if (result < 0) { result |= 7; } return(result / 8); }
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)); }
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); }
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); }
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); }
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)); } }
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()); }
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)); } }