├── .gitignore ├── LICENSE ├── extract_data_dts.py └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Daniel Estévez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /extract_data_dts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import struct 5 | 6 | 7 | def parse_args(): 8 | parser = argparse.ArgumentParser( 9 | description='Extract data files from DTS FIT image') 10 | parser.add_argument('dts', type=str, 11 | help='DST input file') 12 | return parser.parse_args() 13 | 14 | 15 | def main(): 16 | args = parse_args() 17 | description = None 18 | with open(args.dts) as f: 19 | for line in f: 20 | if 'description' in line: 21 | description = line.split('=')[-1].strip() 22 | description = description.replace(';', '').replace('"', '') 23 | if 'data' in line: 24 | data = line.strip() 25 | data = data[len('data = '):] 26 | data_type = data[0] 27 | data = data[1:-2] 28 | if data_type == '[': 29 | data = bytes.fromhex(data.replace(' ', '')) 30 | elif data_type == '<': 31 | data = bytes().join( 32 | [struct.pack('>I', int(a, 16)) for a in data.split()]) 33 | else: 34 | raise ValueError(f'unknown data type {data_type}') 35 | print('Writing', description) 36 | with open(description, 'wb') as data_f: 37 | data_f.write(data) 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pluto firmware modifications 2 | 3 | This repository contains tools and documentation to aid in modifying the ADI 4 | ADALM Pluto firmware. 5 | 6 | ## Extraction of the Pluto firmware image 7 | 8 | This describes how to extract the individual components of the `pluto.frm` 9 | firmware image. It can be useful if only some of the components are going to be 10 | modified, since it saves us from having to build the rest from source. 11 | 12 | Assuming we have the file `pluto.frm` in the same directory as the 13 | `extract_data_dts.py` script included in this repository, we can create a 14 | directory `build` to extract the components of the FIT image. This needs `dtc`, 15 | which is often included in a package called `device-tree-compiler` in Linux 16 | distributions. 17 | 18 | ``` 19 | mkdir build 20 | cd build 21 | dtc -O dts ../pluto.frm | ../extract_data_dts.py /dev/stdin 22 | ``` 23 | 24 | This will extract the data files inside the FIT image. The filenames of the 25 | extracted files are chosen according to the `description` field in the 26 | corresponding node of the FDT tree. The files need to be renamed according to the 27 | filenames expected by the 28 | [`pluto.its`](https://github.com/analogdevicesinc/plutosdr-fw/blob/master/scripts/pluto.its) 29 | file. 30 | 31 | ``` 32 | for file in zynq-pluto*; do mv $file $file.dtb; done 33 | mv FPGA system_top.bit 34 | mv Linux zImage 35 | mv Ramdisk rootfs.cpio.gz 36 | ``` 37 | 38 | Now we can replace some of these files as required with our modifications. In 39 | order to modify the rootfs, it is necessary to extract it and re-pack it as 40 | indicated 41 | [`below`](#extraction-and-re-packing-of-the-rootfs) 42 | . Then we can build the FIT image and `.frm` file as described in the 43 | [ADI 44 | Wiki](https://wiki.analog.com/university/tools/pluto/building_the_image#build_multi_component_fit_image_flattened_image_tree). 45 | This requires `mkimage`, which is usually contained in the package `uboot-tools` 46 | in Linux distributions. 47 | 48 | ``` 49 | cd .. 50 | mkdir new_frm 51 | cd new_frm 52 | wget https://raw.githubusercontent.com/analogdevicesinc/plutosdr-fw/master/scripts/pluto.its 53 | mkimage -f pluto.its pluto.itb 54 | md5sum pluto.itb | cut -d ' ' -f 1 > pluto.frm.md5 55 | cat pluto.itb pluto.frm.md5 > pluto.frm 56 | mv pluto.itb pluto.dfu 57 | dfu-suffix -a pluto.dfu -v 0x0456 -p 0xb673 58 | ``` 59 | 60 | ## Extraction and re-packing of the rootfs 61 | 62 | Extraction 63 | 64 | ``` 65 | gzip -d rootfs.cpio.gz 66 | mkdir rootfs 67 | cd rootfs 68 | cpio -id < ../rootfs.cpio 69 | ``` 70 | 71 | Re-packing 72 | 73 | ``` 74 | rm ../rootfs.cpio 75 | find . | cpio --quiet -o -H newc > ../rootfs.cpio 76 | cd .. 77 | gzip rootfs.cpio 78 | ``` 79 | --------------------------------------------------------------------------------