Example #1
0
        private static int MapBufferEx(ServiceCtx Context)
        {
            const string MapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16} and size 0x{1:x16}!";

            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

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

            NvGpuASCtx ASCtx = GetASCtx(Context);

            NvMapHandle Map = NvMapIoctl.GetNvMapWithFb(Context, Args.NvMapHandle);

            if (Map == null)
            {
                Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{Args.NvMapHandle:x8}!");

                return(NvResult.InvalidInput);
            }

            long PA;

            if ((Args.Flags & FlagRemapSubRange) != 0)
            {
                lock (ASCtx)
                {
                    if (ASCtx.TryGetMapPhysicalAddress(Args.Offset, out PA))
                    {
                        long VA = Args.Offset + Args.BufferOffset;

                        PA += Args.BufferOffset;

                        if (ASCtx.Vmm.Map(PA, VA, Args.MappingSize) < 0)
                        {
                            string Msg = string.Format(MapErrorMsg, VA, Args.MappingSize);

                            Context.Ns.Log.PrintWarning(LogClass.ServiceNv, Msg);

                            return(NvResult.InvalidInput);
                        }

                        return(NvResult.Success);
                    }
                    else
                    {
                        Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Address 0x{Args.Offset:x16} not mapped!");

                        return(NvResult.InvalidInput);
                    }
                }
            }

            PA = Map.Address + Args.BufferOffset;

            long Size = Args.MappingSize;

            if (Size == 0)
            {
                Size = (uint)Map.Size;
            }

            int Result = NvResult.Success;

            lock (ASCtx)
            {
                //Note: When the fixed offset flag is not set,
                //the Offset field holds the alignment size instead.
                bool VaAllocated = (Args.Flags & FlagFixedOffset) == 0;

                if (!VaAllocated)
                {
                    if (ASCtx.ValidateFixedBuffer(Args.Offset, Size))
                    {
                        Args.Offset = ASCtx.Vmm.Map(PA, Args.Offset, Size);
                    }
                    else
                    {
                        string Msg = string.Format(MapErrorMsg, Args.Offset, Size);

                        Context.Ns.Log.PrintWarning(LogClass.ServiceNv, Msg);

                        Result = NvResult.InvalidInput;
                    }
                }
                else
                {
                    Args.Offset = ASCtx.Vmm.Map(PA, Size);
                }

                if (Args.Offset < 0)
                {
                    Args.Offset = 0;

                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Failed to map size 0x{Size:x16}!");

                    Result = NvResult.InvalidInput;
                }
                else
                {
                    ASCtx.AddMap(Args.Offset, Size, PA, VaAllocated);
                }
            }

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

            return(Result);
        }
Example #2
0
        private static int MapBufferEx(ServiceCtx Context)
        {
            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

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

            NvGpuVmm Vmm = GetVmm(Context);

            NvMapHandle Map = NvMapIoctl.GetNvMapWithFb(Context, Args.NvMapHandle);

            if (Map == null)
            {
                Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{Args.NvMapHandle:x8}!");

                return(NvResult.InvalidInput);
            }

            long PA = Map.Address + Args.BufferOffset;

            long Size = Args.MappingSize;

            if (Size == 0)
            {
                Size = (uint)Map.Size;
            }

            int Result = NvResult.Success;

            //Note: When the fixed offset flag is not set,
            //the Offset field holds the alignment size instead.
            if ((Args.Flags & FlagFixedOffset) != 0)
            {
                long MapEnd = Args.Offset + Args.MappingSize;

                if ((ulong)MapEnd <= (ulong)Args.Offset)
                {
                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Offset 0x{Args.Offset:x16} and size 0x{Args.MappingSize:x16} results in a overflow!");

                    return(NvResult.InvalidInput);
                }

                if ((Args.Offset & NvGpuVmm.PageMask) != 0)
                {
                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Offset 0x{Args.Offset:x16} is not page aligned!");

                    return(NvResult.InvalidInput);
                }

                Args.Offset = Vmm.Map(PA, Args.Offset, Size);
            }
            else
            {
                Args.Offset = Vmm.Map(PA, Size);

                if (Args.Offset < 0)
                {
                    Args.Offset = 0;

                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"No memory to map size {Args.MappingSize:x16}!");

                    Result = NvResult.InvalidInput;
                }
            }

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

            return(Result);
        }