1 //
2 // Copyright (c) 2010-2022 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 Antmicro.Renode.Utilities;
11 using Antmicro.Renode.Exceptions;
12 
13 namespace Antmicro.Renode.Utilities.GDB.Commands
14 {
15     internal class CalculateCRCCommand : Command
16     {
CalculateCRCCommand(CommandsManager manager)17         public CalculateCRCCommand(CommandsManager manager) : base(manager)
18         {
19             // CRC engine is initialized according to the gdb specification
20             // Source: https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files
21             crcEngine = new CRCEngine(CRCPolynomial.CRC32, false, false, 0xffffffff, 0);
22         }
23 
24         [Execute("qCRC:")]
Execute( [Argument(Separator = B, Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]ulong address, [Argument(Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]uint length)25         public PacketData Execute(
26             [Argument(Separator = ',', Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]ulong address,
27             [Argument(Encoding = ArgumentAttribute.ArgumentEncoding.HexNumber)]uint length)
28         {
29             var accesses = GetTranslatedAccesses(address, length, write: false);
30 
31             if(accesses == null)
32             {
33                 return PacketData.ErrorReply(Error.BadAddress);
34             }
35 
36             byte[] data = new byte[length];
37             int currentIndex = 0;
38 
39             foreach(var access in accesses)
40             {
41                 if(manager.Machine.SystemBus.WhatIsAt(access.Address, context: manager.Cpu) == null)
42                 {
43                     return PacketData.ErrorReply(Error.BadAddress);
44                 }
45 
46                 try
47                 {
48                     manager.Machine.SystemBus.ReadBytes(access.Address, (int)access.Length, data, currentIndex, onlyMemory: true, context: manager.Cpu);
49                     currentIndex += (int)access.Length;
50                 }
51                 catch(RecoverableException)
52                 {
53                     return PacketData.ErrorReply(Error.BadAddress);
54                 }
55             }
56 
57             return new PacketData($"C{crcEngine.Calculate(data):X8}");
58         }
59 
60         private readonly CRCEngine crcEngine;
61     }
62 }
63