1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Linq; 10 using Antmicro.Renode.Config.Devices; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.CPU; 14 using System.Collections.Generic; 15 using Machine = Antmicro.Renode.Core.Machine; 16 using Antmicro.Renode.Core.Structure; 17 using System.IO; 18 using FdtSharp; 19 using Antmicro.Renode.Logging; 20 using System.Text; 21 using Antmicro.Renode.Exceptions; 22 23 namespace Antmicro.Renode.Utilities 24 { 25 public static class MachineExtensions 26 { LoadPeripheralsFromJSONFile(this IMachine machine, String fileName)27 public static void LoadPeripheralsFromJSONFile(this IMachine machine, String fileName) 28 { 29 if(!File.Exists(fileName)) 30 { 31 throw new RecoverableException("Cannot load devices configuration from file {0} as it does not exist.".FormatWith(fileName)); 32 } 33 new DevicesConfig(File.ReadAllText(fileName), machine); 34 } 35 LoadPeripheralsFromJSONString(this IMachine machine, String text)36 public static void LoadPeripheralsFromJSONString(this IMachine machine, String text) 37 { 38 new DevicesConfig(text, machine); 39 } 40 LoadAtags(this IBusController bus, String bootargs, uint memorySize, uint beginAddress)41 public static void LoadAtags(this IBusController bus, String bootargs, uint memorySize, uint beginAddress) 42 { 43 var atags = Misc.CreateAtags(bootargs, memorySize); 44 //Fill ATAGs 45 var addr = beginAddress; 46 foreach(var elem in atags) 47 { 48 bus.WriteDoubleWord(addr, elem); 49 addr += 4; 50 } 51 } 52 LoadFdt(this IBusController sysbus, string file, ulong address, string bootargs = null, bool append = true, string disabledNodes = R, ICPU context = null)53 public static void LoadFdt(this IBusController sysbus, string file, ulong address, string bootargs = null, bool append = true, string disabledNodes = "", ICPU context = null) 54 { 55 if(!File.Exists(file)) 56 { 57 throw new RecoverableException("FDT file {0} not found".FormatWith(file)); 58 } 59 60 var fdtBlob = File.ReadAllBytes(file); 61 if(bootargs == null) 62 { 63 sysbus.WriteBytes(fdtBlob, address, true, context); 64 return; 65 } 66 var fdt = new FlattenedDeviceTree(fdtBlob); 67 var chosenNode = fdt.Root.Subnodes.FirstOrDefault(x => x.Name == "chosen"); 68 if(chosenNode == null) 69 { 70 chosenNode = new TreeNode { Name = "chosen" }; 71 fdt.Root.Subnodes.Add(chosenNode); 72 } 73 var bootargsProperty = chosenNode.Properties.FirstOrDefault(x => x.Name == "bootargs"); 74 if(bootargsProperty == null) 75 { 76 bootargsProperty = new Property("bootargs", new byte[] { 0 }); 77 chosenNode.Properties.Add(bootargsProperty); 78 } 79 var oldBootargs = bootargsProperty.GetDataAsString(); 80 if(append) 81 { 82 bootargs = oldBootargs + bootargs; 83 } 84 if(oldBootargs != bootargs) 85 { 86 sysbus.DebugLog("Bootargs altered from '{0}' to '{1}'.", oldBootargs, bootargs); 87 } 88 bootargsProperty.PutDataAsString(bootargs); 89 90 var disabledNodeNames = disabledNodes.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 91 byte[] disabledValue = Encoding.ASCII.GetBytes("disabled"); 92 foreach(var deviceName in disabledNodeNames) 93 { 94 TreeNode node = fdt.Root.Descendants.FirstOrDefault(x => x.Name == deviceName); 95 if(node == null) 96 { 97 throw new RecoverableException(String.Format("Device {0} not found.", deviceName)); 98 } 99 else 100 { 101 Property statusProperty = node.Properties.FirstOrDefault(x => x.Name == "status"); 102 if(statusProperty != null) 103 { 104 node.Properties.Remove(statusProperty); 105 } 106 statusProperty = new Property("status", disabledValue); 107 node.Properties.Add(statusProperty); 108 } 109 } 110 111 fdtBlob = fdt.GetBinaryBlob(); 112 sysbus.WriteBytes(fdtBlob, address, true, context); 113 } 114 WriteASCIIString(this IBusController sysbus, ulong address, string stringToLoad, ICPU context = null)115 public static void WriteASCIIString(this IBusController sysbus, ulong address, string stringToLoad, ICPU context = null) 116 { 117 sysbus.WriteBytes(Encoding.ASCII.GetBytes(stringToLoad), address, true, context); 118 } 119 GetPeripheralsWithAllRegistrationPoints(this IMachine machine)120 public static Dictionary<PeripheralTreeEntry, IEnumerable<IRegistrationPoint>> GetPeripheralsWithAllRegistrationPoints(this IMachine machine) 121 { 122 var result = new Dictionary<PeripheralTreeEntry, IEnumerable<IRegistrationPoint>>(); 123 124 var peripheralEntries = machine.GetRegisteredPeripherals().ToArray(); 125 var sysbusEntry = peripheralEntries.First(x => x.Name == Machine.SystemBusName).Peripheral; 126 foreach(var entryList in peripheralEntries.OrderBy(x => x.Name).GroupBy(x => x.Peripheral)) 127 { 128 var uniqueEntryList = entryList.DistinctBy(x => x.RegistrationPoint).ToArray(); 129 var entry = uniqueEntryList.FirstOrDefault(); 130 if(entry != null) 131 { 132 result.Add(entry, uniqueEntryList.Select(x => x.RegistrationPoint).ToList()); 133 } 134 // The peripherals command will not print the entry under sysbus if its first occurence in entryList is not directly a child of sysbus. 135 // This check prevents loosing sysbus registration info in peripherals command output. 136 if(entry.Parent != sysbusEntry) 137 { 138 entry = uniqueEntryList.FirstOrDefault(x => x.Parent == sysbusEntry); 139 if(entry != null) 140 { 141 result.Add(entry, uniqueEntryList.Where(x => x.Parent == sysbusEntry).Select(x => x.RegistrationPoint).ToList()); 142 } 143 } 144 } 145 146 return result; 147 } 148 } 149 } 150