1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Linq;
9 using Antmicro.Renode.Logging;
10 using Endianess = ELFSharp.ELF.Endianess;
11 
12 namespace Antmicro.Renode.Utilities.GDB.Commands
13 {
14     internal class WriteDataToMemoryCommand : Command
15     {
WriteDataToMemoryCommand(CommandsManager manager)16         public WriteDataToMemoryCommand(CommandsManager manager) : base(manager)
17         {
18         }
19 
20         [Execute("M")]
WriteHexData( [Argument(Separator = B, Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]ulong address, [Argument(Separator = B, Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]uint length, [Argument(Encoding = ArgumentAttribute.ArgumentEncoding.HexBytesString)]byte[] data)21         public PacketData WriteHexData(
22            [Argument(Separator = ',', Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]ulong address,
23            [Argument(Separator = ':', Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]uint length,
24            [Argument(Encoding = ArgumentAttribute.ArgumentEncoding.HexBytesString)]byte[] data)
25         {
26             if(data.Length != length)
27             {
28                 Logger.LogAs(this, LogLevel.Warning, "length argument does not match the size of sent data.");
29                 return PacketData.ErrorReply(Error.InvalidArgument);
30             }
31             return WriteData(address, data);
32         }
33 
34         [Execute("X")]
WriteBinaryData( [Argument(Separator = B, Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]ulong address, [Argument(Separator = B, Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]uint length, [Argument(Encoding = ArgumentAttribute.ArgumentEncoding.BinaryBytes)]byte[] data)35         public PacketData WriteBinaryData(
36            [Argument(Separator = ',', Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]ulong address,
37            [Argument(Separator = ':', Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]uint length,
38            [Argument(Encoding = ArgumentAttribute.ArgumentEncoding.BinaryBytes)]byte[] data)
39         {
40             if(data.Length != length)
41             {
42                 Logger.LogAs(this, LogLevel.Warning, "length argument does not match the size of sent data.");
43                 return PacketData.ErrorReply(Error.InvalidArgument);
44             }
45             return WriteData(address, data);
46         }
47 
WriteData(ulong address, byte[] data)48         private PacketData WriteData(ulong address, byte[] data)
49         {
50             var accesses = GetTranslatedAccesses(address, (ulong)data.Length, write: true);
51 
52             if(accesses == null)
53             {
54                 return PacketData.ErrorReply(Error.BadAddress);
55             }
56 
57             int startingIndex = 0;
58             foreach(var access in accesses)
59             {
60                 var val = BitHelper.ToUInt64(data, startingIndex, (int)access.Length, reverse: manager.Cpu.Endianness == Endianess.LittleEndian);
61                 switch(access.Length)
62                 {
63                     case 1:
64                         manager.Machine.SystemBus.WriteByte(access.Address, (byte)val, context: manager.Cpu);
65                         break;
66                     case 2:
67                         manager.Machine.SystemBus.WriteWord(access.Address, (ushort)val, context: manager.Cpu);
68                         break;
69                     case 4:
70                         manager.Machine.SystemBus.WriteDoubleWord(access.Address, (uint)val, context: manager.Cpu);
71                         break;
72                     case 8:
73                         manager.Machine.SystemBus.WriteQuadWord(access.Address, (ulong)val, context: manager.Cpu);
74                         break;
75                     default:
76                         manager.Machine.SystemBus.WriteBytes(data, access.Address, startingIndex, (long)access.Length, context: manager.Cpu);
77                         break;
78                 }
79                 startingIndex += (int)access.Length;
80             }
81 
82             return PacketData.Success;
83         }
84     }
85 }
86 
87