summaryrefslogtreecommitdiff
path: root/src/sys/ioctl/etc/process_ioctls.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/ioctl/etc/process_ioctls.py')
-rw-r--r--src/sys/ioctl/etc/process_ioctls.py236
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)