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