コード例 #1
0
ファイル: Command.cs プロジェクト: colombod/DiscImageChef
        /// <summary>
        ///     Sends a MMC/SD command
        /// </summary>
        /// <returns>The result of the command.</returns>
        /// <param name="ptId">Platform ID for executing the command</param>
        /// <param name="fd">File handle</param>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendMmcCommand(PlatformID ptId, object fd, MmcCommands command,
                                           bool write,
                                           bool isApplication, MmcFlags flags, uint argument,
                                           uint blockSize,
                                           uint blocks, ref byte[] buffer, out uint[] response,
                                           out double duration,
                                           out bool sense, uint timeout = 0)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
            {
                return(Windows.Command.SendMmcCommand((SafeFileHandle)fd, command, write, isApplication, flags,
                                                      argument, blockSize, blocks, ref buffer, out response,
                                                      out duration, out sense, timeout));
            }

            case PlatformID.Linux:
            {
                return(Linux.Command.SendMmcCommand((int)fd, command, write, isApplication, flags, argument,
                                                    blockSize, blocks, ref buffer, out response, out duration,
                                                    out sense, timeout));
            }

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
コード例 #2
0
        /// <summary>
        ///     Sends a MMC/SD command
        /// </summary>
        /// <returns>The result of the command.</returns>
        /// <param name="fd">File handle</param>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        internal static int SendMmcCommand(int fd, MmcCommands command, bool write,
                                           bool isApplication, MmcFlags flags,
                                           uint argument, uint blockSize, uint blocks,
                                           ref byte[] buffer,
                                           out uint[] response, out double duration, out bool sense,
                                           uint timeout = 0)
        {
            response = null;
            duration = 0;
            sense    = false;

            if (buffer == null)
            {
                return(-1);
            }

            MmcIocCmd ioCmd = new MmcIocCmd();

            IntPtr bufPtr = Marshal.AllocHGlobal(buffer.Length);

            ioCmd.write_flag = write;
            ioCmd.is_ascmd   = isApplication;
            ioCmd.opcode     = (uint)command;
            ioCmd.arg        = argument;
            ioCmd.flags      = flags;
            ioCmd.blksz      = blockSize;
            ioCmd.blocks     = blocks;
            if (timeout > 0)
            {
                ioCmd.data_timeout_ns = timeout * 1000000000;
                ioCmd.cmd_timeout_ms  = timeout * 1000;
            }

            ioCmd.data_ptr = (ulong)bufPtr;

            Marshal.Copy(buffer, 0, bufPtr, buffer.Length);

            DateTime start = DateTime.UtcNow;
            int      error = Extern.ioctlMmc(fd, LinuxIoctl.MmcIocCmd, ref ioCmd);
            DateTime end   = DateTime.UtcNow;

            sense |= error < 0;

            if (error < 0)
            {
                error = Marshal.GetLastWin32Error();
            }

            Marshal.Copy(bufPtr, buffer, 0, buffer.Length);

            response = ioCmd.response;
            duration = (end - start).TotalMilliseconds;

            Marshal.FreeHGlobal(bufPtr);

            return(error);
        }
コード例 #3
0
ファイル: Command.cs プロジェクト: paulyc/Aaru
        /// <summary>Sends a MMC/SD command</summary>
        /// <returns>The result of the command.</returns>
        /// <param name="fd">File handle</param>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendMmcCommand(object fd, MmcCommands command, bool write, bool isApplication,
                                           MmcFlags flags, uint argument, uint blockSize, uint blocks,
                                           ref byte[] buffer, out uint[] response, out double duration, out bool sense,
                                           uint timeout = 0)
        {
            PlatformID ptId = DetectOS.GetRealPlatformID();

            return(SendMmcCommand(ptId, (int)fd, command, write, isApplication, flags, argument, blockSize, blocks,
                                  ref buffer, out response, out duration, out sense, timeout));
        }
コード例 #4
0
        /// <summary>Sends a MMC/SD command to this device</summary>
        /// <returns>The result of the command.</returns>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        public int SendMmcCommand(MmcCommands command, bool write, bool isApplication, MmcFlags flags, uint argument,
                                  uint blockSize, uint blocks, ref byte[] buffer, out uint[] response,
                                  out double duration, out bool sense, uint timeout = 0)
        {
            switch (command)
            {
            case MmcCommands.SendCid when _cachedCid != null:
            {
                DateTime start = DateTime.Now;
                buffer = new byte[_cachedCid.Length];
                Array.Copy(_cachedCid, buffer, buffer.Length);
                response = new uint[4];
                sense    = false;
                DateTime end = DateTime.Now;
                duration = (end - start).TotalMilliseconds;

                return(0);
            }

            case MmcCommands.SendCsd when _cachedCid != null:
            {
                DateTime start = DateTime.Now;
                buffer = new byte[_cachedCsd.Length];
                Array.Copy(_cachedCsd, buffer, buffer.Length);
                response = new uint[4];
                sense    = false;
                DateTime end = DateTime.Now;
                duration = (end - start).TotalMilliseconds;

                return(0);
            }

            case (MmcCommands)SecureDigitalCommands.SendScr when _cachedScr != null:
            {
                DateTime start = DateTime.Now;
                buffer = new byte[_cachedScr.Length];
                Array.Copy(_cachedScr, buffer, buffer.Length);
                response = new uint[4];
                sense    = false;
                DateTime end = DateTime.Now;
                duration = (end - start).TotalMilliseconds;

                return(0);
            }

            case (MmcCommands)SecureDigitalCommands.SendOperatingCondition when _cachedOcr != null:
            case MmcCommands.SendOpCond when _cachedOcr != null:
            {
                DateTime start = DateTime.Now;
                buffer = new byte[_cachedOcr.Length];
                Array.Copy(_cachedOcr, buffer, buffer.Length);
                response = new uint[4];
                sense    = false;
                DateTime end = DateTime.Now;
                duration = (end - start).TotalMilliseconds;

                return(0);
            }
            }

            return(_remote is null
                       ? Command.SendMmcCommand(PlatformId, FileHandle, command, write, isApplication, flags, argument,
                                                blockSize, blocks, ref buffer, out response, out duration, out sense,
                                                timeout) : _remote.SendMmcCommand(command, write, isApplication, flags,
                                                                                  argument, blockSize, blocks, ref buffer, out response, out duration, out sense,
                                                                                  timeout));
        }
コード例 #5
0
        /// <summary>
        ///     Sends a MMC/SD command
        /// </summary>
        /// <returns>The result of the command.</returns>
        /// <param name="fd">File handle</param>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        internal static int SendMmcCommand(SafeFileHandle fd, MmcCommands command, bool write,
                                           bool isApplication,
                                           MmcFlags flags, uint argument, uint blockSize,
                                           uint blocks,
                                           ref byte[]     buffer, out uint[] response, out double duration,
                                           out bool sense,
                                           uint timeout = 0)
        {
            SffdiskDeviceCommandData commandData       = new SffdiskDeviceCommandData();
            SdCmdDescriptor          commandDescriptor = new SdCmdDescriptor();

            commandData.size    = (ushort)Marshal.SizeOf(commandData);
            commandData.command = SffdiskDcmd.DeviceCommand;
            commandData.protocolArgumentSize    = (ushort)Marshal.SizeOf(commandDescriptor);
            commandData.deviceDataBufferSize    = blockSize * blocks;
            commandDescriptor.commandCode       = (byte)command;
            commandDescriptor.cmdClass          = isApplication ? SdCommandClass.AppCmd : SdCommandClass.Standard;
            commandDescriptor.transferDirection = write ? SdTransferDirection.Write : SdTransferDirection.Read;
            commandDescriptor.transferType      = flags.HasFlag(MmcFlags.CommandAdtc)
                                                 ? SdTransferType.SingleBlock
                                                 : SdTransferType.CmdOnly;
            commandDescriptor.responseType = 0;

            if (flags.HasFlag(MmcFlags.ResponseR1) || flags.HasFlag(MmcFlags.ResponseSpiR1))
            {
                commandDescriptor.responseType = SdResponseType.R1;
            }
            if (flags.HasFlag(MmcFlags.ResponseR1B) || flags.HasFlag(MmcFlags.ResponseSpiR1B))
            {
                commandDescriptor.responseType = SdResponseType.R1b;
            }
            if (flags.HasFlag(MmcFlags.ResponseR2) || flags.HasFlag(MmcFlags.ResponseSpiR2))
            {
                commandDescriptor.responseType = SdResponseType.R2;
            }
            if (flags.HasFlag(MmcFlags.ResponseR3) || flags.HasFlag(MmcFlags.ResponseSpiR3))
            {
                commandDescriptor.responseType = SdResponseType.R3;
            }
            if (flags.HasFlag(MmcFlags.ResponseR4) || flags.HasFlag(MmcFlags.ResponseSpiR4))
            {
                commandDescriptor.responseType = SdResponseType.R4;
            }
            if (flags.HasFlag(MmcFlags.ResponseR5) || flags.HasFlag(MmcFlags.ResponseSpiR5))
            {
                commandDescriptor.responseType = SdResponseType.R5;
            }
            if (flags.HasFlag(MmcFlags.ResponseR6))
            {
                commandDescriptor.responseType = SdResponseType.R6;
            }

            byte[] commandB = new byte[commandData.size + commandData.protocolArgumentSize +
                                       commandData.deviceDataBufferSize];
            IntPtr hBuf = Marshal.AllocHGlobal(commandB.Length);

            Marshal.StructureToPtr(commandData, hBuf, true);
            IntPtr descriptorOffset = IntPtr.Add(hBuf, commandData.size);

            Marshal.StructureToPtr(commandDescriptor, descriptorOffset, true);
            Marshal.Copy(hBuf, commandB, 0, commandB.Length);
            Marshal.FreeHGlobal(hBuf);

            int      error = 0;
            DateTime start = DateTime.Now;

            sense = !Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB, (uint)commandB.Length,
                                            commandB, (uint)commandB.Length, out _, IntPtr.Zero);
            DateTime end = DateTime.Now;

            if (sense)
            {
                error = Marshal.GetLastWin32Error();
            }

            buffer = new byte[blockSize * blocks];
            Buffer.BlockCopy(commandB, commandB.Length - buffer.Length, buffer, 0, buffer.Length);

            response = new uint[4];
            duration = (end - start).TotalMilliseconds;

            return(error);
        }
コード例 #6
0
        public int SendMmcCommand(MmcCommands command, bool write, bool isApplication, MmcFlags flags, uint argument,
                                  uint blockSize, uint blocks, ref byte[] buffer, out uint[] response,
                                  out double duration, out bool sense, uint timeout = 0)
        {
            duration = 0;
            sense    = true;
            response = null;

            var cmdPkt = new AaruPacketCmdSdhci
            {
                hdr = new AaruPacketHeader
                {
                    remote_id  = Consts.RemoteId, packet_id = Consts.PacketId, version = Consts.PacketVersion,
                    packetType = AaruPacketType.CommandAtaLba48
                },
                command  = command, write = write, application = isApplication, flags = flags,
                argument = argument, block_size = blockSize, blocks = blocks, timeout = timeout * 1000
            };

            if (buffer != null)
            {
                cmdPkt.buf_len = (uint)buffer.Length;
            }

            cmdPkt.hdr.len = (uint)(Marshal.SizeOf <AaruPacketCmdSdhci>() + cmdPkt.buf_len);

            byte[] pktBuf = Marshal.StructureToByteArrayLittleEndian(cmdPkt);
            byte[] buf    = new byte[cmdPkt.hdr.len];

            Array.Copy(pktBuf, 0, buf, 0, Marshal.SizeOf <AaruPacketCmdSdhci>());

            if (buffer != null)
            {
                Array.Copy(buffer, 0, buf, Marshal.SizeOf <AaruPacketCmdSdhci>(), cmdPkt.buf_len);
            }

            int len = _socket.Send(buf, SocketFlags.None);

            if (len != buf.Length)
            {
                AaruConsole.ErrorWriteLine("Could not write to the network...");

                return(-1);
            }

            byte[] hdrBuf = new byte[Marshal.SizeOf <AaruPacketHeader>()];

            len = Receive(_socket, hdrBuf, hdrBuf.Length, SocketFlags.Peek);

            if (len < hdrBuf.Length)
            {
                AaruConsole.ErrorWriteLine("Could not read from the network...");

                return(-1);
            }

            AaruPacketHeader hdr = Marshal.ByteArrayToStructureLittleEndian <AaruPacketHeader>(hdrBuf);

            if (hdr.remote_id != Consts.RemoteId ||
                hdr.packet_id != Consts.PacketId)
            {
                AaruConsole.ErrorWriteLine("Received data is not an Aaru Remote Packet...");

                return(-1);
            }

            if (hdr.packetType != AaruPacketType.ResponseSdhci)
            {
                AaruConsole.ErrorWriteLine("Expected SDHCI Response Packet, got packet type {0}...", hdr.packetType);

                return(-1);
            }

            buf = new byte[hdr.len];
            len = Receive(_socket, buf, buf.Length, SocketFlags.None);

            if (len < buf.Length)
            {
                AaruConsole.ErrorWriteLine("Could not read from the network...");

                return(-1);
            }

            AaruPacketResSdhci res = Marshal.ByteArrayToStructureLittleEndian <AaruPacketResSdhci>(buf);

            buffer = new byte[res.buf_len];
            Array.Copy(buf, Marshal.SizeOf <AaruPacketResSdhci>(), buffer, 0, res.buf_len);
            duration    = res.duration;
            sense       = res.sense != 0;
            response    = new uint[4];
            response[0] = res.response[0];
            response[1] = res.response[1];
            response[2] = res.response[2];
            response[3] = res.response[3];

            return((int)res.error_no);
        }