OpenHisiIpCam / registers-description

HiSilicon ip camera SoCs SystemRDL registers description
https://www.openhisiipcam.org/hardware/registers-description/
MIT License
12 stars 3 forks source link

Question: RDL format as an output? #1

Open hanetzer opened 2 years ago

hanetzer commented 2 years ago

So. I'm also interested in hisi socs (not the camera ones, but the ones that go in the DVR/NVR the cameras plug into). To this end I've been writing some mainline drivers, dumping bootroms (its easy, can do it with tftp in u-boot) and popping them into ghidra, and modeling the SoCs in qemu (relatively easy once you get the hang of it).

Part of my ghidra workflow is writing up register descriptions in a yaml format support supported by svdtools, converting them to svd xml files, and loading them into ghidra with SVD-Loader-Ghidra to RE their bootflow for qemu. I was wondering, maybe we could combine efforts in this regard and have something like svdtools that will convert an input yaml into RDL?

hanetzer commented 2 years ago

Or, barring that, we could dispense with rdl entirely and just use svd's, shouldn't be too hard to make something to convert it to your web format. With the above tool we can even 'cheat' a bit and define common blocks (pl011 uart, pl061 gpio, sp804 timer, etc) in their own yaml and patch the primary yaml with those.

nikitos1550 commented 2 years ago

I didn't knew about SVD format before, LOL ) Will take a look. Am I right that your proposal it to make info first in SVD (yaml based) format and then make tool to transform it to RDL?

Actually RDL manual editing is a bit painful, maybe SVD is more suitable format for the task.

hanetzer commented 2 years ago

Well, svd's themselves are xml, and a pain to edit. but you can write them in yaml, and use the above svdtools program to convert it to xml.

hanetzer commented 2 years ago

Currently working on a python-based implementation of the intreg parser, using the svd file as the data input. I'm needing a detailed description of how the attr field in the reg.bin works, think you could help out with that?

hanetzer commented 2 years ago

Managed to throw together a python script that parses the reg.bin using svd files.

#!/usr/bin/env python3

import argparse
from colorama import Fore, Style
from cmsis_svd.parser import SVDParser
import struct
import sys

SPC = "                                                  "

def genmask(width, offset):
    # int(('1' * width) + ('0' * offset), 2)
    return ((2 ** width) - 1) << offset

def parse_reg_fields(register, value, bitstart, bitnum):
    periname = register[0]
    regname = register[1].name
    description = register[1].description
    print(f"{periname}:{regname}[{bitstart+bitnum}:{bitstart}] ({description})")
    for field in register[1].fields:
        mask = genmask(field.bit_width, field.bit_offset)
        bitend = field.bit_width + field.bit_offset - 1
        if bitend <= bitnum and field.bit_offset >= bitstart:
            fieldval = (value & mask) >> field.bit_offset
            print(SPC + Fore.CYAN + "field {}[{}:{}] ({})".format(field.name, bitend, field.bit_offset, field.description), end='')
            print(f" val = [{fieldval:0{field.bit_width}b}]", end='')
            if field.enumerated_values:
                for enumval in field.enumerated_values:
                    if enumval.value == fieldval:
                        print(f" ({enumval.name})")
            else:
                print("")

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
            '--file', type=str, required=True,
            help="file with reg data")
    parser.add_argument(
            '--svd', type=str, required=True,
            help="SVD file to use to parse reg data")
    parser.add_argument(
            '--offset', type=int, required=False, default=0,
            help="offset of reg data in file")
    parser.add_argument(
            '--size', type=int, required=True,
            help="size of reg data in file")
    args = parser.parse_args()
    # print(args)

    if args.size % 16 != 0:
        print("Size should be multiple of 16 bytes.")
        sys.exit(1)

    svd = SVDParser.for_xml_file(args.svd)

    reg_lookup = {}
    for peripheral in svd.get_device().peripherals:
        baseaddr = peripheral.base_address
        for register in peripheral.registers:
            reg_lookup[baseaddr + register.address_offset] = (peripheral.name, register)

    # print(reg_lookup)

    try:
        regfile = open(args.file, 'rb')
    except OSError as e:
        print("Error: {}".format(e.strerror))

    regfile.seek(args.offset)

    print("reg        value      delay      attrs")
    while True:
        reg = struct.unpack('<I', regfile.read(4))[0]
        value = struct.unpack('<I', regfile.read(4))[0]
        delay = struct.unpack('<I', regfile.read(4))[0]
        attr = struct.unpack('<I', regfile.read(4))[0]

        if not any((reg,value,delay,attr)):
            break
        else:
            if reg != 0:
                try:
                    regi = reg_lookup[reg]
                except KeyError as e:
                    raise KeyError(hex(e.args[0])) from e

            write = attr & 0x7
            read = (attr & 0x70000) >> 16
            print(Style.RESET_ALL, end='')
            print(f"{reg:#010x} {value:#010x} {delay:#010x} {attr:#010x}", end='')

            if write & 0x4 == 0x4:
                print(Fore.BLUE + " WRITE ", end='')
                start = (attr & 0xf800) >> 11
                num = (attr & 0xf8) >> 3
                # print(f":{value:#010x}:{start}:{num}")
                parse_reg_fields(regi, value, start, num)
            elif read & 0x4 == 0x4:
                print(Fore.GREEN + "  READ ", end='')
                start = (attr & 0xf8000000) >> 27
                num = (attr & 0xf80000) >> 19
                parse_reg_fields(regi, value, start, num)
            elif delay > 0:
                print(Fore.YELLOW + " DELAY {}".format(delay))
            else:
                print(Fore.RED + " UNKNOWN")
hanetzer commented 2 years ago

asciicast How it looks running.