diff options
Diffstat (limited to 'src/sys/ioctl/etc/process_ioctls.py')
-rw-r--r-- | src/sys/ioctl/etc/process_ioctls.py | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/src/sys/ioctl/etc/process_ioctls.py b/src/sys/ioctl/etc/process_ioctls.py new file mode 100644 index 00000000..815dae36 --- /dev/null +++ b/src/sys/ioctl/etc/process_ioctls.py @@ -0,0 +1,236 @@ +import sys +import os +import operator + +if len(sys.argv) != 2: + sys.stderr.write("Wrong number of argmuments. Wanted one, the name of the\ + arch to use, got %s" % sys.argv) + +arch = sys.argv[1] + +f = open(os.path.join(arch, 'ioctl_list')) # found by find_ioctls.py +m = open(os.path.join(arch, 'manually_found')) # found by the Mach V Eyeball +i = open(os.path.join(arch, 'ignore_list')) # removed from the output of find_ioctls.py + +print("// Initially generated by process_ioctls.py") + +consts = { + "mips": { "NONE": 1, "READ": 2, "WRITE": 4, "SIZEBITS": 13, "DIRBITS": 3}, + "powerpc": { "NONE": 1, "READ": 2, "WRITE": 4, "SIZEBITS": 13, "DIRBITS": 3}, + "x86": { "NONE": 0, "READ": 2, "WRITE": 1, "SIZEBITS": 14, "DIRBITS": 2}, + "x86_64": { "NONE": 0, "READ": 2, "WRITE": 1, "SIZEBITS": 14, "DIRBITS": 2}, + "arm": { "NONE": 0, "READ": 2, "WRITE": 1, "SIZEBITS": 14, "DIRBITS": 2}, + "aarch64": { "NONE": 0, "READ": 2, "WRITE": 1, "SIZEBITS": 14, "DIRBITS": 2}, +} + +ioc_consts = { + "SIOCPROTOPRIVATE": 0x89E0, + "SIOCDEVPRIVATE": 0x89F0, + "PCIIOC_BASE": (ord('P') << 24 | ord('C') << 16 | ord('I') << 8), + "FIONREAD": 0x541B, + "CZIOC": ord('M') << 8, + "TIOCOUTQ": 0x5411, + "TIOCM_CAR": 0x040, + "TIOCM_RNG": 0x080, +} + +NONE = consts[arch]["NONE"] +READ = consts[arch]["READ"] +WRITE = consts[arch]["WRITE"] +SIZEBITS = consts[arch]["SIZEBITS"] +DIRBITS = consts[arch]["DIRBITS"] +NRBITS = 8 +TYPEBITS = 8 +NRSHIFT = 0 +TYPESHIFT = NRSHIFT + NRBITS +SIZESHIFT = TYPESHIFT + SIZEBITS +DIRSHIFT = SIZESHIFT + DIRBITS +NRMASK = (1 << NRBITS) - 1 +TYPEMASK = (1 << TYPEBITS) - 1 +SIZEMASK = (1 << SIZEBITS) - 1 +DIRMASK = (1 << DIRBITS) - 1 + +def decode(val): + return (((val >> DIRSHIFT) & DIRMASK), ((val >> TYPESHIFT) & TYPEMASK), + ((val >> NRSHIFT) & NRMASK), ((val >> SIZESHIFT) & SIZEMASK)) + +ioctls = [] # ones we want to actually process + +for ioctl in f: + ioctls.append(eval(ioctl)) +for ioctl in m: + ioctls.append(eval(ioctl)) + +mp = { "_IO": "none", "_IOR": "read", "_IOW": "write", "_IOWR": "readwrite", + "DRM_IO": "none", "DRM_IOR": "read", "DRM_IOW": "write", "DRM_IOWR": "readwrite"} + +tys = { + "__uint8_t": "u8", + "__uint16": "u16", + "__uint32_t": "u32", + "__uint64_t": "u64", + "__int8_t": "i8", + "__int16": "i16", + "__int32_t": "i32", + "__int64_t": "i64", + "uint8_t": "u8", + "uint16": "u16", + "uint32_t": "u32", + "uint64_t": "u64", + "int8_t": "i8", + "int16": "i16", + "int32_t": "i32", + "int64_t": "i64", + "__u8": "u8", + "__u16": "u16", + "__u32": "u32", + "__u64": "u64", + "__s8": "i8", + "__s16": "i16", + "__s32": "i32", + "__s64": "i64", + "int": "::libc::c_int", + "long": "::libc::c_long", + "char": "::libc::c_char", + "size_t": "::libc::size_t", +} + +utys = { + "int": "::libc::c_uint", + "long": "::libc::c_ulong", + "char": "::libc::c_uchar", +} + +known_structs = ["input_id", "ff_effect", "ff_trigger", "ff_replay"] + +manually_bound = ["EVIOCGNAME", "EVIOCGPHYS", "EVIOCGUNIQ", "EVIOCGPROP", +"EVIOCGMTSLOTS", "EVIOCGKEY", "EVIOCGLED", "EVIOCGSND", "EVIOCGSW", +"EVIOCGBIT", "EVIOCGABS", "EVIOCSABS", "EVIOCGRAB", "EVIOCREVOKE", +"EVIOCSCLOCKID"] + +bad_recovery = {} + +def translate(ty): + if len(ty) == 1: + return tys.get(ty[0], "FIXME1<%s>" % ty) + elif ty[-1] == '*': + return "*mut " + translate(ty[:-1]) + elif len(ty) == 2: + if ty[0] == "struct": + return "/*struct*/ %s" % ty[1] + elif ty[0] == "unsigned": + return utys[ty[1]] + else: + return "FIXME2<%s>" % ty + elif ty[-1] == ']': + count = ty[-2] + return "[%s; %s]" % (translate(ty[:-3]), count) + else: + return "FIXME3<%s>" % ty + +def translate_type_code(ty): + if ty[0] == "'": + return "b" + ty + else: + return ty + +def bad(name, val): + if name in bad_recovery: + process(bad_recovery[name]) + else: + pval = None + try: + pval = int(val, 0) + except: + pass + if pval is None: + print("ioctl!(bad %s with %s);" % (name.lower(), val)) + else: + (dr, ty, nr, sz) = decode(pval) + if dr == NONE: + print("ioctl!(none %s with %s, %s);" % (name.lower(), ty, nr)) + elif dr == READ: + print("ioctl!(read %s with %s, %s; [u8; %s]);" % + (name.lower(), ty, nr, sz)); + elif dr == WRITE: + print("ioctl!(write %s with %s, %s; [u8; %s]);" % + (name.lower(), ty, nr, sz)); + elif dr == READ|WRITE: + print("ioctl!(readwrite %s with %s, %s; [u8; %s]);" % + (name.lower(), ty, nr, sz)); + else: + raise "This really shouldn't happen" + +def bad2(name, val1, val2, op): + if val1 in ioc_consts: + val1 = ioc_consts[val1] + else: + val1 = int(val1, 0) + + if val2 in ioc_consts: + val2 = ioc_consts[val2] + else: + val2 = int(val2, 0) + + bad(name, str(op(val1, val2))) + +def process(ioctl): + name = ioctl[0] + rhs = ioctl[1:-1] # remove '#' or trailing comment + cmd = rhs[0] + body = rhs[2:-1] + + if name in manually_bound: + return + elif cmd == "_IO": + print("ioctl!(none %s with %s, %s);" % (name.lower(), translate_type_code(body[0]), + body[2])) + elif cmd == '_IOR' or cmd == '_IOW' or cmd == '_IOWR': + if body[3] == ',': + # this looks like _IOR(X, B, type...) + first = body[0] + second = body[2] + ty = body[4:] + ty = translate(ty) + if "FIXME" in ty or "/*struct*/" in ty and not ty[11:] in known_structs: + print("// ioctl!(%s %s with %s, %s; %s);" % (mp[cmd], name.lower(), + translate_type_code(first), second, ty)) + else: + print("ioctl!(%s %s with %s, %s; %s);" % (mp[cmd], name.lower(), + translate_type_code(first), second, ty)) + elif body[3] == '+': + first = body[0] + second = " ".join(body[2:5]) + ty = body[6:] + ty = translate(ty) + if "FIXME" in ty or "/*struct*/" in ty and not ty[11:] in known_structs: + print("// ioctl!(%s %s with %s, %s; %s);" % (mp[cmd], name.lower(), + translate_type_code(first), second, ty)) + else: + print("ioctl!(%s %s with %s, %s; %s);" % (mp[cmd], name.lower(), + translate_type_code(first), second, ty)) + # We probably have _IOR(X, B + C, type...) + else: + raise "This really shouldn't happen" + elif cmd == "DRM_IO" or cmd == "DRM_IOR" or cmd == "DRM_IOW" or cmd == "DRM_IOWR": + # rewrite into "canonical" version. + process([name, cmd[3:], "(", "DRM_IOCTL_BASE", ","] + rhs[2:] + ["#"]) + elif len(rhs) == 1: # single constant :( + bad(name.lower(), ioc_consts.get(rhs[0], rhs[0])) + elif len(rhs) == 3 and rhs[0] == "(": # single constant in parens + bad(name.lower(), ioc_consts.get(rhs[1], rhs[1])) + elif rhs[2] == "+": # we have the sum of two constants + try: + bad2(name.lower(), rhs[1], rhs[3], operator.add) + except: + bad(name.lower(), " ".join(rhs[1:-1])) + elif rhs[2] == "|": # we have an or of two constants (eugh) + try: + bad2(name.lower(), rhs[1], rhs[3], operator.or_) + except: + bad(name.lower(), " ".join(rhs[1:-1])) + else: + print("// TODO #define %s %s" % (name, " ".join(rhs))) + +for ioctl in ioctls: + process(ioctl) |