Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: initial BPF implementation

Declare an entry point that can use fmod_ret BPF programs, and
also an API to access and change the incoming data.

A simpler implementation would consist in just calling
hid_bpf_device_event() for any incoming event and let users deal
with the fact that they will be called for any event of any device.

The goal of HID-BPF is to partially replace drivers, so this situation
can be problematic because we might have programs which will step on
each other toes.

For that, we add a new API hid_bpf_attach_prog() that can be called
from a syscall and we manually deal with a jump table in hid-bpf.

Whenever we add a program to the jump table (in other words, when we
attach a program to a HID device), we keep the number of time we added
this program in the jump table so we can release it whenever there are
no other users.

HID devices have an RCU protected list of available programs in the
jump table, and those programs are called one after the other thanks
to bpf_tail_call().

To achieve the detection of users losing their fds on the programs we
attached, we add 2 tracing facilities on bpf_prog_release() (for when
a fd is closed) and bpf_free_inode() (for when a pinned program gets
unpinned).

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Benjamin Tissoires and committed by
Jiri Kosina
f5c27da4 25621bcc

+1804
+2
drivers/hid/Kconfig
··· 1284 1284 1285 1285 endmenu 1286 1286 1287 + source "drivers/hid/bpf/Kconfig" 1288 + 1287 1289 endif # HID 1288 1290 1289 1291 source "drivers/hid/usbhid/Kconfig"
+2
drivers/hid/Makefile
··· 5 5 hid-y := hid-core.o hid-input.o hid-quirks.o 6 6 hid-$(CONFIG_DEBUG_FS) += hid-debug.o 7 7 8 + obj-$(CONFIG_HID_BPF) += bpf/ 9 + 8 10 obj-$(CONFIG_HID) += hid.o 9 11 obj-$(CONFIG_UHID) += uhid.o 10 12
+17
drivers/hid/bpf/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + menu "HID-BPF support" 3 + 4 + config HID_BPF 5 + bool "HID-BPF support" 6 + default HID_SUPPORT 7 + depends on BPF && BPF_SYSCALL 8 + help 9 + This option allows to support eBPF programs on the HID subsystem. 10 + eBPF programs can fix HID devices in a lighter way than a full 11 + kernel patch and allow a lot more flexibility. 12 + 13 + For documentation, see Documentation/hid/hid-bpf.rst 14 + 15 + If unsure, say Y. 16 + 17 + endmenu
+11
drivers/hid/bpf/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Makefile for HID-BPF 4 + # 5 + 6 + LIBBPF_INCLUDE = $(srctree)/tools/lib 7 + 8 + obj-$(CONFIG_HID_BPF) += hid_bpf.o 9 + CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE) 10 + CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE) 11 + hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o
+93
drivers/hid/bpf/entrypoints/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + OUTPUT := .output 3 + abs_out := $(abspath $(OUTPUT)) 4 + 5 + CLANG ?= clang 6 + LLC ?= llc 7 + LLVM_STRIP ?= llvm-strip 8 + 9 + TOOLS_PATH := $(abspath ../../../../tools) 10 + BPFTOOL_SRC := $(TOOLS_PATH)/bpf/bpftool 11 + BPFTOOL_OUTPUT := $(abs_out)/bpftool 12 + DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool 13 + BPFTOOL ?= $(DEFAULT_BPFTOOL) 14 + 15 + LIBBPF_SRC := $(TOOLS_PATH)/lib/bpf 16 + LIBBPF_OUTPUT := $(abs_out)/libbpf 17 + LIBBPF_DESTDIR := $(LIBBPF_OUTPUT) 18 + LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include 19 + BPFOBJ := $(LIBBPF_OUTPUT)/libbpf.a 20 + 21 + INCLUDES := -I$(OUTPUT) -I$(LIBBPF_INCLUDE) -I$(TOOLS_PATH)/include/uapi 22 + CFLAGS := -g -Wall 23 + 24 + VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \ 25 + $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ 26 + ../../../../vmlinux \ 27 + /sys/kernel/btf/vmlinux \ 28 + /boot/vmlinux-$(shell uname -r) 29 + VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) 30 + ifeq ($(VMLINUX_BTF),) 31 + $(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") 32 + endif 33 + 34 + ifeq ($(V),1) 35 + Q = 36 + msg = 37 + else 38 + Q = @ 39 + msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; 40 + MAKEFLAGS += --no-print-directory 41 + submake_extras := feature_display=0 42 + endif 43 + 44 + .DELETE_ON_ERROR: 45 + 46 + .PHONY: all clean 47 + 48 + all: entrypoints.lskel.h 49 + 50 + clean: 51 + $(call msg,CLEAN) 52 + $(Q)rm -rf $(OUTPUT) entrypoints 53 + 54 + entrypoints.lskel.h: $(OUTPUT)/entrypoints.bpf.o | $(BPFTOOL) 55 + $(call msg,GEN-SKEL,$@) 56 + $(Q)$(BPFTOOL) gen skeleton -L $< > $@ 57 + 58 + 59 + $(OUTPUT)/entrypoints.bpf.o: entrypoints.bpf.c $(OUTPUT)/vmlinux.h $(BPFOBJ) | $(OUTPUT) 60 + $(call msg,BPF,$@) 61 + $(Q)$(CLANG) -g -O2 -target bpf $(INCLUDES) \ 62 + -c $(filter %.c,$^) -o $@ && \ 63 + $(LLVM_STRIP) -g $@ 64 + 65 + $(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR) 66 + ifeq ($(VMLINUX_H),) 67 + $(call msg,GEN,,$@) 68 + $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ 69 + else 70 + $(call msg,CP,,$@) 71 + $(Q)cp "$(VMLINUX_H)" $@ 72 + endif 73 + 74 + $(OUTPUT) $(LIBBPF_OUTPUT) $(BPFTOOL_OUTPUT): 75 + $(call msg,MKDIR,$@) 76 + $(Q)mkdir -p $@ 77 + 78 + $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT) 79 + $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \ 80 + OUTPUT=$(abspath $(dir $@))/ prefix= \ 81 + DESTDIR=$(LIBBPF_DESTDIR) $(abspath $@) install_headers 82 + 83 + ifeq ($(CROSS_COMPILE),) 84 + $(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT) 85 + $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \ 86 + OUTPUT=$(BPFTOOL_OUTPUT)/ \ 87 + LIBBPF_BOOTSTRAP_OUTPUT=$(LIBBPF_OUTPUT)/ \ 88 + LIBBPF_BOOTSTRAP_DESTDIR=$(LIBBPF_DESTDIR)/ bootstrap 89 + else 90 + $(DEFAULT_BPFTOOL): | $(BPFTOOL_OUTPUT) 91 + $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \ 92 + OUTPUT=$(BPFTOOL_OUTPUT)/ bootstrap 93 + endif
+4
drivers/hid/bpf/entrypoints/README
··· 1 + WARNING: 2 + If you change "entrypoints.bpf.c" do "make -j" in this directory to rebuild "entrypoints.skel.h". 3 + Make sure to have clang 10 installed. 4 + See Documentation/bpf/bpf_devel_QA.rst
+66
drivers/hid/bpf/entrypoints/entrypoints.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2022 Benjamin Tissoires */ 3 + 4 + #include ".output/vmlinux.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + 8 + #define HID_BPF_MAX_PROGS 1024 9 + 10 + extern bool call_hid_bpf_prog_release(u64 prog, int table_cnt) __ksym; 11 + 12 + struct { 13 + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 14 + __uint(max_entries, HID_BPF_MAX_PROGS); 15 + __uint(key_size, sizeof(__u32)); 16 + __uint(value_size, sizeof(__u32)); 17 + } hid_jmp_table SEC(".maps"); 18 + 19 + struct { 20 + __uint(type, BPF_MAP_TYPE_HASH); 21 + __uint(max_entries, HID_BPF_MAX_PROGS * HID_BPF_PROG_TYPE_MAX); 22 + __type(key, void *); 23 + __type(value, __u8); 24 + } progs_map SEC(".maps"); 25 + 26 + SEC("fmod_ret/__hid_bpf_tail_call") 27 + int BPF_PROG(hid_tail_call, struct hid_bpf_ctx *hctx) 28 + { 29 + bpf_tail_call(ctx, &hid_jmp_table, hctx->index); 30 + 31 + return 0; 32 + } 33 + 34 + static void release_prog(u64 prog) 35 + { 36 + u8 *value; 37 + 38 + value = bpf_map_lookup_elem(&progs_map, &prog); 39 + if (!value) 40 + return; 41 + 42 + if (call_hid_bpf_prog_release(prog, *value)) 43 + bpf_map_delete_elem(&progs_map, &prog); 44 + } 45 + 46 + SEC("fexit/bpf_prog_release") 47 + int BPF_PROG(hid_prog_release, struct inode *inode, struct file *filp) 48 + { 49 + u64 prog = (u64)filp->private_data; 50 + 51 + release_prog(prog); 52 + 53 + return 0; 54 + } 55 + 56 + SEC("fexit/bpf_free_inode") 57 + int BPF_PROG(hid_free_inode, struct inode *inode) 58 + { 59 + u64 prog = (u64)inode->i_private; 60 + 61 + release_prog(prog); 62 + 63 + return 0; 64 + } 65 + 66 + char LICENSE[] SEC("license") = "GPL";
+648
drivers/hid/bpf/entrypoints/entrypoints.lskel.h
··· 1 + /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 + /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ 3 + #ifndef __ENTRYPOINTS_BPF_SKEL_H__ 4 + #define __ENTRYPOINTS_BPF_SKEL_H__ 5 + 6 + #include <bpf/skel_internal.h> 7 + 8 + struct entrypoints_bpf { 9 + struct bpf_loader_ctx ctx; 10 + struct { 11 + struct bpf_map_desc hid_jmp_table; 12 + struct bpf_map_desc progs_map; 13 + } maps; 14 + struct { 15 + struct bpf_prog_desc hid_tail_call; 16 + struct bpf_prog_desc hid_prog_release; 17 + struct bpf_prog_desc hid_free_inode; 18 + } progs; 19 + struct { 20 + int hid_tail_call_fd; 21 + int hid_prog_release_fd; 22 + int hid_free_inode_fd; 23 + } links; 24 + }; 25 + 26 + static inline int 27 + entrypoints_bpf__hid_tail_call__attach(struct entrypoints_bpf *skel) 28 + { 29 + int prog_fd = skel->progs.hid_tail_call.prog_fd; 30 + int fd = skel_raw_tracepoint_open(NULL, prog_fd); 31 + 32 + if (fd > 0) 33 + skel->links.hid_tail_call_fd = fd; 34 + return fd; 35 + } 36 + 37 + static inline int 38 + entrypoints_bpf__hid_prog_release__attach(struct entrypoints_bpf *skel) 39 + { 40 + int prog_fd = skel->progs.hid_prog_release.prog_fd; 41 + int fd = skel_raw_tracepoint_open(NULL, prog_fd); 42 + 43 + if (fd > 0) 44 + skel->links.hid_prog_release_fd = fd; 45 + return fd; 46 + } 47 + 48 + static inline int 49 + entrypoints_bpf__hid_free_inode__attach(struct entrypoints_bpf *skel) 50 + { 51 + int prog_fd = skel->progs.hid_free_inode.prog_fd; 52 + int fd = skel_raw_tracepoint_open(NULL, prog_fd); 53 + 54 + if (fd > 0) 55 + skel->links.hid_free_inode_fd = fd; 56 + return fd; 57 + } 58 + 59 + static inline int 60 + entrypoints_bpf__attach(struct entrypoints_bpf *skel) 61 + { 62 + int ret = 0; 63 + 64 + ret = ret < 0 ? ret : entrypoints_bpf__hid_tail_call__attach(skel); 65 + ret = ret < 0 ? ret : entrypoints_bpf__hid_prog_release__attach(skel); 66 + ret = ret < 0 ? ret : entrypoints_bpf__hid_free_inode__attach(skel); 67 + return ret < 0 ? ret : 0; 68 + } 69 + 70 + static inline void 71 + entrypoints_bpf__detach(struct entrypoints_bpf *skel) 72 + { 73 + skel_closenz(skel->links.hid_tail_call_fd); 74 + skel_closenz(skel->links.hid_prog_release_fd); 75 + skel_closenz(skel->links.hid_free_inode_fd); 76 + } 77 + static void 78 + entrypoints_bpf__destroy(struct entrypoints_bpf *skel) 79 + { 80 + if (!skel) 81 + return; 82 + entrypoints_bpf__detach(skel); 83 + skel_closenz(skel->progs.hid_tail_call.prog_fd); 84 + skel_closenz(skel->progs.hid_prog_release.prog_fd); 85 + skel_closenz(skel->progs.hid_free_inode.prog_fd); 86 + skel_closenz(skel->maps.hid_jmp_table.map_fd); 87 + skel_closenz(skel->maps.progs_map.map_fd); 88 + skel_free(skel); 89 + } 90 + static inline struct entrypoints_bpf * 91 + entrypoints_bpf__open(void) 92 + { 93 + struct entrypoints_bpf *skel; 94 + 95 + skel = skel_alloc(sizeof(*skel)); 96 + if (!skel) 97 + goto cleanup; 98 + skel->ctx.sz = (void *)&skel->links - (void *)skel; 99 + return skel; 100 + cleanup: 101 + entrypoints_bpf__destroy(skel); 102 + return NULL; 103 + } 104 + 105 + static inline int 106 + entrypoints_bpf__load(struct entrypoints_bpf *skel) 107 + { 108 + struct bpf_load_and_run_opts opts = {}; 109 + int err; 110 + 111 + opts.ctx = (struct bpf_loader_ctx *)skel; 112 + opts.data_sz = 10624; 113 + opts.data = (void *)"\ 114 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 115 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 116 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 117 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 118 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 119 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 120 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 121 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 122 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 123 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 124 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 125 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 126 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 127 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 128 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 129 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 130 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 131 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 132 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 133 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 134 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 135 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 136 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 137 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 138 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 139 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 140 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 141 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 142 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 143 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 144 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 145 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 146 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x01\0\ 147 + \x18\0\0\0\0\0\0\0\xf0\x11\0\0\xf0\x11\0\0\x0e\x0c\0\0\0\0\0\0\0\0\0\x02\x03\0\ 148 + \0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\ 149 + \0\0\x04\0\0\0\x03\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\ 150 + \x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\0\x04\0\0\0\0\0\0\ 151 + \0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\ 152 + \0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\ 153 + \x40\0\0\0\x2a\0\0\0\x07\0\0\0\x80\0\0\0\x33\0\0\0\x07\0\0\0\xc0\0\0\0\x3e\0\0\ 154 + \0\0\0\0\x0e\x09\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\0\0\0\0\0\0\0\x03\ 155 + \0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0e\0\0\0\0\0\0\0\0\0\ 156 + \0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\x02\x10\0\0\0\0\0\0\ 157 + \0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\x02\x12\0\0\0\x4c\0\0\0\0\0\0\x08\x13\0\0\0\ 158 + \x51\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\ 159 + \0\x0b\0\0\0\0\0\0\0\x1e\0\0\0\x0d\0\0\0\x40\0\0\0\x5f\0\0\0\x0f\0\0\0\x80\0\0\ 160 + \0\x63\0\0\0\x11\0\0\0\xc0\0\0\0\x69\0\0\0\0\0\0\x0e\x14\0\0\0\x01\0\0\0\0\0\0\ 161 + \0\0\0\0\x02\x17\0\0\0\x73\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\ 162 + \x0d\x02\0\0\0\x86\0\0\0\x16\0\0\0\x8a\0\0\0\x01\0\0\x0c\x18\0\0\0\x30\x01\0\0\ 163 + \x05\0\0\x04\x20\0\0\0\x3c\x01\0\0\x1b\0\0\0\0\0\0\0\x42\x01\0\0\x1d\0\0\0\x40\ 164 + \0\0\0\x46\x01\0\0\x1b\0\0\0\x80\0\0\0\x55\x01\0\0\x1f\0\0\0\xa0\0\0\0\0\0\0\0\ 165 + \x20\0\0\0\xc0\0\0\0\x61\x01\0\0\0\0\0\x08\x1c\0\0\0\x67\x01\0\0\0\0\0\x01\x04\ 166 + \0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x1e\0\0\0\0\0\0\0\0\0\0\x0a\xa9\0\0\0\x74\ 167 + \x01\0\0\x04\0\0\x06\x04\0\0\0\x84\x01\0\0\0\0\0\0\x95\x01\0\0\x01\0\0\0\xa7\ 168 + \x01\0\0\x02\0\0\0\xba\x01\0\0\x03\0\0\0\0\0\0\0\x02\0\0\x05\x04\0\0\0\xcb\x01\ 169 + \0\0\x21\0\0\0\0\0\0\0\xd2\x01\0\0\x21\0\0\0\0\0\0\0\xd7\x01\0\0\0\0\0\x08\x02\ 170 + \0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x86\0\0\0\x16\0\0\0\x13\x02\0\0\x01\0\0\ 171 + \x0c\x22\0\0\0\x82\x02\0\0\x14\0\0\x04\xe8\0\0\0\0\0\0\0\x25\0\0\0\0\0\0\0\x87\ 172 + \x02\0\0\x2c\0\0\0\x80\0\0\0\x8e\x02\0\0\x2f\0\0\0\0\x01\0\0\x96\x02\0\0\x30\0\ 173 + \0\0\x40\x01\0\0\x9b\x02\0\0\x32\0\0\0\x80\x01\0\0\xa2\x02\0\0\x41\0\0\0\xc0\ 174 + \x01\0\0\xaa\x02\0\0\x1c\0\0\0\0\x02\0\0\xb2\x02\0\0\x47\0\0\0\x20\x02\0\0\xb9\ 175 + \x02\0\0\x48\0\0\0\x40\x02\0\0\xc4\x02\0\0\x4d\0\0\0\x40\x03\0\0\xca\x02\0\0\ 176 + \x4f\0\0\0\x80\x03\0\0\xd2\x02\0\0\x5d\0\0\0\x80\x04\0\0\xd9\x02\0\0\x5f\0\0\0\ 177 + \xc0\x04\0\0\xde\x02\0\0\x61\0\0\0\xc0\x05\0\0\xe8\x02\0\0\x10\0\0\0\0\x06\0\0\ 178 + \xf3\x02\0\0\x10\0\0\0\x40\x06\0\0\0\x03\0\0\x63\0\0\0\x80\x06\0\0\x05\x03\0\0\ 179 + \x64\0\0\0\xc0\x06\0\0\x0f\x03\0\0\x65\0\0\0\0\x07\0\0\x18\x03\0\0\x65\0\0\0\ 180 + \x20\x07\0\0\0\0\0\0\x03\0\0\x05\x10\0\0\0\x21\x03\0\0\x26\0\0\0\0\0\0\0\x29\ 181 + \x03\0\0\x28\0\0\0\0\0\0\0\x33\x03\0\0\x1c\0\0\0\0\0\0\0\x40\x03\0\0\x01\0\0\ 182 + \x04\x08\0\0\0\x4b\x03\0\0\x27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x26\0\0\0\x50\ 183 + \x03\0\0\x02\0\0\x04\x10\0\0\0\x4b\x03\0\0\x29\0\0\0\0\0\0\0\x5e\x03\0\0\x2a\0\ 184 + \0\0\x40\0\0\0\0\0\0\0\0\0\0\x02\x28\0\0\0\0\0\0\0\0\0\0\x02\x2b\0\0\0\0\0\0\0\ 185 + \x01\0\0\x0d\0\0\0\0\0\0\0\0\x29\0\0\0\x63\x03\0\0\x02\0\0\x04\x10\0\0\0\x68\ 186 + \x03\0\0\x2d\0\0\0\0\0\0\0\x6c\x03\0\0\x2e\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\x02\ 187 + \xb0\0\0\0\0\0\0\0\0\0\0\x02\xa3\0\0\0\0\0\0\0\0\0\0\x02\x6d\0\0\0\0\0\0\0\0\0\ 188 + \0\x02\x31\0\0\0\0\0\0\0\0\0\0\x0a\xa5\0\0\0\x73\x03\0\0\0\0\0\x08\x33\0\0\0\ 189 + \x7e\x03\0\0\x01\0\0\x04\x04\0\0\0\0\0\0\0\x34\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\ 190 + \x05\x04\0\0\0\x87\x03\0\0\x35\0\0\0\0\0\0\0\x8d\x03\0\0\x01\0\0\x04\x04\0\0\0\ 191 + \x9a\x03\0\0\x36\0\0\0\0\0\0\0\xa3\x03\0\0\0\0\0\x08\x37\0\0\0\xb3\x03\0\0\x01\ 192 + \0\0\x04\x04\0\0\0\0\0\0\0\x38\0\0\0\0\0\0\0\0\0\0\0\x03\0\0\x05\x04\0\0\0\xbd\ 193 + \x03\0\0\x39\0\0\0\0\0\0\0\0\0\0\0\x3b\0\0\0\0\0\0\0\0\0\0\0\x3d\0\0\0\0\0\0\0\ 194 + \xc1\x03\0\0\0\0\0\x08\x3a\0\0\0\0\0\0\0\x01\0\0\x04\x04\0\0\0\xca\x03\0\0\x02\ 195 + \0\0\0\0\0\0\0\0\0\0\0\x02\0\0\x04\x02\0\0\0\xd2\x03\0\0\x3c\0\0\0\0\0\0\0\xd9\ 196 + \x03\0\0\x3c\0\0\0\x08\0\0\0\xe1\x03\0\0\0\0\0\x08\x12\0\0\0\0\0\0\0\x02\0\0\ 197 + \x04\x04\0\0\0\xe4\x03\0\0\x3e\0\0\0\0\0\0\0\xf3\x03\0\0\x3e\0\0\0\x10\0\0\0\ 198 + \xf8\x03\0\0\0\0\0\x08\x3f\0\0\0\xfc\x03\0\0\0\0\0\x08\x40\0\0\0\x02\x04\0\0\0\ 199 + \0\0\x01\x02\0\0\0\x10\0\0\0\x11\x04\0\0\0\0\0\x08\x42\0\0\0\x1f\x04\0\0\0\0\0\ 200 + \x08\x43\0\0\0\0\0\0\0\x01\0\0\x04\x08\0\0\0\xca\x03\0\0\x44\0\0\0\0\0\0\0\x2a\ 201 + \x04\0\0\0\0\0\x08\x45\0\0\0\x2e\x04\0\0\0\0\0\x08\x46\0\0\0\x34\x04\0\0\0\0\0\ 202 + \x01\x08\0\0\0\x40\0\0\x01\x3e\x04\0\0\0\0\0\x08\x1c\0\0\0\x46\x04\0\0\x04\0\0\ 203 + \x04\x20\0\0\0\x4c\x04\0\0\x41\0\0\0\0\0\0\0\x52\x04\0\0\x49\0\0\0\x40\0\0\0\ 204 + \x5c\x04\0\0\x4a\0\0\0\x60\0\0\0\x60\x04\0\0\x4b\0\0\0\x80\0\0\0\x6a\x04\0\0\0\ 205 + \0\0\x08\x35\0\0\0\x79\x04\0\0\x01\0\0\x04\x04\0\0\0\xf3\x03\0\0\x39\0\0\0\0\0\ 206 + \0\0\x8f\x04\0\0\x02\0\0\x04\x10\0\0\0\x4b\x03\0\0\x4c\0\0\0\0\0\0\0\x99\x04\0\ 207 + \0\x4c\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\x02\x4b\0\0\0\x9e\x04\0\0\0\0\0\x08\x4e\0\ 208 + \0\0\xa5\x04\0\0\0\0\0\x08\x46\0\0\0\xb5\x04\0\0\x06\0\0\x04\x20\0\0\0\xc1\x04\ 209 + \0\0\x50\0\0\0\0\0\0\0\xc6\x04\0\0\x57\0\0\0\x40\0\0\0\xca\x04\0\0\x58\0\0\0\ 210 + \x80\0\0\0\xd3\x04\0\0\x59\0\0\0\xa0\0\0\0\xd7\x04\0\0\x59\0\0\0\xc0\0\0\0\xdc\ 211 + \x04\0\0\x02\0\0\0\xe0\0\0\0\xe3\x04\0\0\0\0\0\x08\x51\0\0\0\0\0\0\0\x01\0\0\ 212 + \x04\x08\0\0\0\x9a\x03\0\0\x52\0\0\0\0\0\0\0\xec\x04\0\0\0\0\0\x08\x53\0\0\0\ 213 + \xfa\x04\0\0\x02\0\0\x04\x08\0\0\0\0\0\0\0\x54\0\0\0\0\0\0\0\x52\x04\0\0\x36\0\ 214 + \0\0\x20\0\0\0\0\0\0\0\x02\0\0\x05\x04\0\0\0\x02\x05\0\0\x39\0\0\0\0\0\0\0\0\0\ 215 + \0\0\x55\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\x04\x04\0\0\0\x07\x05\0\0\x3c\0\0\0\0\0\ 216 + \0\0\x0f\x05\0\0\x56\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x3c\0\0\0\x04\0\ 217 + \0\0\x03\0\0\0\0\0\0\0\0\0\0\x02\xab\0\0\0\xca\x04\0\0\x05\0\0\x06\x04\0\0\0\ 218 + \x18\x05\0\0\0\0\0\0\x24\x05\0\0\x01\0\0\0\x31\x05\0\0\x02\0\0\0\x3e\x05\0\0\ 219 + \x03\0\0\0\x4a\x05\0\0\x04\0\0\0\x56\x05\0\0\0\0\0\x08\x5a\0\0\0\0\0\0\0\x01\0\ 220 + \0\x04\x04\0\0\0\xbd\x03\0\0\x5b\0\0\0\0\0\0\0\x5d\x05\0\0\0\0\0\x08\x5c\0\0\0\ 221 + \x63\x05\0\0\0\0\0\x08\x1c\0\0\0\0\0\0\0\0\0\0\x02\x5e\0\0\0\0\0\0\0\0\0\0\x0a\ 222 + \xa2\0\0\0\x74\x05\0\0\x06\0\0\x04\x20\0\0\0\x82\x05\0\0\x60\0\0\0\0\0\0\0\xd2\ 223 + \x01\0\0\x1c\0\0\0\x40\0\0\0\x88\x05\0\0\x1c\0\0\0\x60\0\0\0\x93\x05\0\0\x1c\0\ 224 + \0\0\x80\0\0\0\x9c\x05\0\0\x1c\0\0\0\xa0\0\0\0\xa6\x05\0\0\x4d\0\0\0\xc0\0\0\0\ 225 + \xaf\x05\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\xbd\x05\0\0\0\0\0\x08\x62\0\0\0\xc1\ 226 + \x05\0\0\0\0\0\x08\x17\0\0\0\0\0\0\0\0\0\0\x02\x85\0\0\0\0\0\0\0\0\0\0\x02\x8a\ 227 + \0\0\0\xc7\x05\0\0\0\0\0\x08\x66\0\0\0\xd0\x05\0\0\0\0\0\x08\x1b\0\0\0\0\0\0\0\ 228 + \x02\0\0\x0d\x68\0\0\0\x03\x0c\0\0\x61\0\0\0\x03\x0c\0\0\x02\0\0\0\x94\x06\0\0\ 229 + \0\0\0\x08\x69\0\0\0\x99\x06\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x04\x9f\x06\0\0\ 230 + \x01\0\0\x0c\x67\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x86\0\0\0\x16\0\0\0\xb9\ 231 + \x06\0\0\x01\0\0\x0c\x6b\0\0\0\x0f\x07\0\0\x36\0\0\x04\x78\x02\0\0\x15\x07\0\0\ 232 + \x6e\0\0\0\0\0\0\0\x1c\x07\0\0\x40\0\0\0\x10\0\0\0\x26\x07\0\0\x59\0\0\0\x20\0\ 233 + \0\0\x2c\x07\0\0\x6f\0\0\0\x40\0\0\0\x32\x07\0\0\x1c\0\0\0\x60\0\0\0\x3a\x07\0\ 234 + \0\x73\0\0\0\x80\0\0\0\x40\x07\0\0\x73\0\0\0\xc0\0\0\0\x4e\x07\0\0\x74\0\0\0\0\ 235 + \x01\0\0\x53\x07\0\0\x76\0\0\0\x40\x01\0\0\x58\x07\0\0\x64\0\0\0\x80\x01\0\0\ 236 + \x62\x07\0\0\x10\0\0\0\xc0\x01\0\0\x6d\x07\0\0\x60\0\0\0\0\x02\0\0\0\0\0\0\x77\ 237 + \0\0\0\x40\x02\0\0\x73\x07\0\0\x79\0\0\0\x60\x02\0\0\x7a\x07\0\0\x4d\0\0\0\x80\ 238 + \x02\0\0\x81\x07\0\0\x7b\0\0\0\xc0\x02\0\0\x89\x07\0\0\x7b\0\0\0\x40\x03\0\0\ 239 + \x91\x07\0\0\x7b\0\0\0\xc0\x03\0\0\x99\x07\0\0\x32\0\0\0\x40\x04\0\0\xa0\x07\0\ 240 + \0\x40\0\0\0\x60\x04\0\0\xa8\x07\0\0\x3c\0\0\0\x70\x04\0\0\xb2\x07\0\0\x3c\0\0\ 241 + \0\x78\x04\0\0\xbf\x07\0\0\x7e\0\0\0\x80\x04\0\0\xc8\x07\0\0\x60\0\0\0\xc0\x04\ 242 + \0\0\xd0\x07\0\0\x7f\0\0\0\0\x05\0\0\xd8\x07\0\0\x60\0\0\0\x40\x06\0\0\xe5\x07\ 243 + \0\0\x60\0\0\0\x80\x06\0\0\xf7\x07\0\0\x80\0\0\0\xc0\x06\0\0\xfe\x07\0\0\x4b\0\ 244 + \0\0\x40\x07\0\0\x08\x08\0\0\x83\0\0\0\xc0\x07\0\0\x0d\x08\0\0\x02\0\0\0\0\x08\ 245 + \0\0\x1d\x08\0\0\x3e\0\0\0\x20\x08\0\0\x2f\x08\0\0\x3e\0\0\0\x30\x08\0\0\x40\ 246 + \x08\0\0\x4b\0\0\0\x40\x08\0\0\x46\x08\0\0\x4b\0\0\0\xc0\x08\0\0\x50\x08\0\0\ 247 + \x4b\0\0\0\x40\x09\0\0\0\0\0\0\x84\0\0\0\xc0\x09\0\0\x5a\x08\0\0\x42\0\0\0\x40\ 248 + \x0a\0\0\x64\x08\0\0\x42\0\0\0\x80\x0a\0\0\x6f\x08\0\0\x39\0\0\0\xc0\x0a\0\0\ 249 + \x77\x08\0\0\x39\0\0\0\xe0\x0a\0\0\x83\x08\0\0\x39\0\0\0\0\x0b\0\0\x90\x08\0\0\ 250 + \x39\0\0\0\x20\x0b\0\0\0\0\0\0\x86\0\0\0\x40\x0b\0\0\x9c\x08\0\0\x89\0\0\0\x80\ 251 + \x0b\0\0\xa4\x08\0\0\x8a\0\0\0\xc0\x0b\0\0\xab\x08\0\0\x4b\0\0\0\xc0\x11\0\0\0\ 252 + \0\0\0\x92\0\0\0\x40\x12\0\0\xb5\x08\0\0\x1b\0\0\0\x80\x12\0\0\xc2\x08\0\0\x1b\ 253 + \0\0\0\xa0\x12\0\0\xd2\x08\0\0\x97\0\0\0\xc0\x12\0\0\xe3\x08\0\0\x98\0\0\0\0\ 254 + \x13\0\0\xf0\x08\0\0\x99\0\0\0\x40\x13\0\0\xfe\x08\0\0\x10\0\0\0\x80\x13\0\0\ 255 + \x08\x09\0\0\0\0\0\x08\x40\0\0\0\x10\x09\0\0\0\0\0\x08\x70\0\0\0\0\0\0\0\x01\0\ 256 + \0\x04\x04\0\0\0\xbd\x03\0\0\x71\0\0\0\0\0\0\0\x17\x09\0\0\0\0\0\x08\x72\0\0\0\ 257 + \x1d\x09\0\0\0\0\0\x08\x1c\0\0\0\0\0\0\0\0\0\0\x02\xad\0\0\0\0\0\0\0\0\0\0\x02\ 258 + \x75\0\0\0\0\0\0\0\0\0\0\x0a\xaa\0\0\0\0\0\0\0\0\0\0\x02\xaf\0\0\0\0\0\0\0\x02\ 259 + \0\0\x05\x04\0\0\0\x2e\x09\0\0\x78\0\0\0\0\0\0\0\x36\x09\0\0\x1c\0\0\0\0\0\0\0\ 260 + \0\0\0\0\0\0\0\x0a\x1c\0\0\0\x40\x09\0\0\0\0\0\x08\x7a\0\0\0\x46\x09\0\0\0\0\0\ 261 + \x08\x66\0\0\0\x55\x09\0\0\x02\0\0\x04\x10\0\0\0\x60\x09\0\0\x7c\0\0\0\0\0\0\0\ 262 + \x67\x09\0\0\x7d\0\0\0\x40\0\0\0\x6f\x09\0\0\0\0\0\x08\x45\0\0\0\x78\x09\0\0\0\ 263 + \0\0\x01\x08\0\0\0\x40\0\0\x01\x7d\x09\0\0\0\0\0\x08\x61\0\0\0\x86\x09\0\0\x05\ 264 + \0\0\x04\x28\0\0\0\x93\x09\0\0\x41\0\0\0\0\0\0\0\x4c\x04\0\0\x41\0\0\0\x40\0\0\ 265 + \0\x5c\x04\0\0\x4a\0\0\0\x80\0\0\0\x52\x04\0\0\x49\0\0\0\xa0\0\0\0\x60\x04\0\0\ 266 + \x4b\0\0\0\xc0\0\0\0\x99\x09\0\0\x02\0\0\x04\x10\0\0\0\x4b\x03\0\0\x81\0\0\0\0\ 267 + \0\0\0\xa4\x09\0\0\x82\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\x02\x80\0\0\0\0\0\0\0\0\0\ 268 + \0\x02\x81\0\0\0\0\0\0\0\0\0\0\x02\xa0\0\0\0\0\0\0\0\x02\0\0\x05\x10\0\0\0\xaa\ 269 + \x09\0\0\x85\0\0\0\0\0\0\0\xb3\x09\0\0\x28\0\0\0\0\0\0\0\xb9\x09\0\0\x01\0\0\ 270 + \x04\x08\0\0\0\xc4\x09\0\0\x81\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\x05\x08\0\0\0\xca\ 271 + \x09\0\0\x30\0\0\0\0\0\0\0\xd0\x09\0\0\x87\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x88\ 272 + \0\0\0\0\0\0\0\x01\0\0\x0d\0\0\0\0\0\0\0\0\x2f\0\0\0\0\0\0\0\0\0\0\x02\xa4\0\0\ 273 + \0\xdb\x09\0\0\x0f\0\0\x04\xc0\0\0\0\xe9\x09\0\0\x2f\0\0\0\0\0\0\0\xee\x09\0\0\ 274 + \x8b\0\0\0\x40\0\0\0\xf6\x09\0\0\x7f\0\0\0\xc0\0\0\0\x06\x0a\0\0\x8c\0\0\0\0\ 275 + \x02\0\0\x0f\x0a\0\0\x39\0\0\0\x20\x02\0\0\x1f\x0a\0\0\x8d\0\0\0\x40\x02\0\0\ 276 + \x26\x0a\0\0\x7f\0\0\0\xc0\x02\0\0\x33\x0a\0\0\x60\0\0\0\0\x04\0\0\x3b\x0a\0\0\ 277 + \x60\0\0\0\x40\x04\0\0\x4b\x0a\0\0\x90\0\0\0\x80\x04\0\0\x51\x0a\0\0\x60\0\0\0\ 278 + \xc0\x04\0\0\x57\x0a\0\0\x65\0\0\0\0\x05\0\0\x5e\x0a\0\0\x32\0\0\0\x20\x05\0\0\ 279 + \x6b\x0a\0\0\x4b\0\0\0\x40\x05\0\0\xf3\x02\0\0\x10\0\0\0\xc0\x05\0\0\x78\x0a\0\ 280 + \0\x03\0\0\x04\x10\0\0\0\x7f\x0a\0\0\x32\0\0\0\0\0\0\0\x87\x0a\0\0\x8c\0\0\0\ 281 + \x20\0\0\0\x90\x0a\0\0\x10\0\0\0\x40\0\0\0\x98\x0a\0\0\0\0\0\x08\x1c\0\0\0\x9e\ 282 + \x0a\0\0\x02\0\0\x04\x10\0\0\0\xad\x0a\0\0\x8e\0\0\0\0\0\0\0\xb5\x0a\0\0\x8f\0\ 283 + \0\0\x40\0\0\0\xad\x0a\0\0\x01\0\0\x04\x08\0\0\0\xc1\x0a\0\0\x8f\0\0\0\0\0\0\0\ 284 + \0\0\0\0\0\0\0\x02\xae\0\0\0\0\0\0\0\0\0\0\x02\x91\0\0\0\0\0\0\0\0\0\0\x0a\x9f\ 285 + \0\0\0\0\0\0\0\x04\0\0\x05\x08\0\0\0\xc9\x0a\0\0\x93\0\0\0\0\0\0\0\xd0\x0a\0\0\ 286 + \x94\0\0\0\0\0\0\0\xd7\x0a\0\0\x95\0\0\0\0\0\0\0\xde\x0a\0\0\x1c\0\0\0\0\0\0\0\ 287 + \0\0\0\0\0\0\0\x02\xac\0\0\0\0\0\0\0\0\0\0\x02\xa1\0\0\0\0\0\0\0\0\0\0\x02\x96\ 288 + \0\0\0\xe8\x0a\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\0\x02\xa7\0\0\0\ 289 + \0\0\0\0\0\0\0\x02\xa6\0\0\0\0\0\0\0\0\0\0\x02\xa8\0\0\0\0\0\0\0\0\0\0\x03\0\0\ 290 + \0\0\x96\0\0\0\x04\0\0\0\x04\0\0\0\x15\x0b\0\0\0\0\0\x0e\x9a\0\0\0\x01\0\0\0\ 291 + \x1d\x0b\0\0\x01\0\0\x0f\x04\0\0\0\xb1\0\0\0\0\0\0\0\x04\0\0\0\x24\x0b\0\0\x02\ 292 + \0\0\x0f\x40\0\0\0\x0a\0\0\0\0\0\0\0\x20\0\0\0\x15\0\0\0\x20\0\0\0\x20\0\0\0\ 293 + \x2a\x0b\0\0\x01\0\0\x0f\x04\0\0\0\x9b\0\0\0\0\0\0\0\x04\0\0\0\x32\x0b\0\0\0\0\ 294 + \0\x07\0\0\0\0\x4b\x0b\0\0\0\0\0\x07\0\0\0\0\x59\x0b\0\0\0\0\0\x07\0\0\0\0\x5e\ 295 + \x0b\0\0\0\0\0\x07\0\0\0\0\x6c\x03\0\0\0\0\0\x07\0\0\0\0\x63\x0b\0\0\0\0\0\x07\ 296 + \0\0\0\0\x75\x0b\0\0\0\0\0\x07\0\0\0\0\x85\x0b\0\0\0\0\0\x07\0\0\0\0\x92\x0b\0\ 297 + \0\0\0\0\x07\0\0\0\0\xaa\x0b\0\0\0\0\0\x07\0\0\0\0\xb8\x0b\0\0\0\0\0\x07\0\0\0\ 298 + \0\xc3\x0b\0\0\0\0\0\x07\0\0\0\0\xc6\x04\0\0\0\0\0\x07\0\0\0\0\xd4\x0b\0\0\0\0\ 299 + \0\x07\0\0\0\0\xe4\x0b\0\0\0\0\0\x07\0\0\0\0\xc1\x0a\0\0\0\0\0\x07\0\0\0\0\xee\ 300 + \x0b\0\0\0\0\0\x07\0\0\0\0\xfa\x0b\0\0\0\0\0\x07\0\0\0\0\x03\x0c\0\0\0\0\0\x0e\ 301 + \x02\0\0\0\x01\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\ 302 + \x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\x6d\x61\x78\x5f\x65\ 303 + \x6e\x74\x72\x69\x65\x73\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\x75\ 304 + \x65\x5f\x73\x69\x7a\x65\0\x68\x69\x64\x5f\x6a\x6d\x70\x5f\x74\x61\x62\x6c\x65\ 305 + \0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x6b\ 306 + \x65\x79\0\x76\x61\x6c\x75\x65\0\x70\x72\x6f\x67\x73\x5f\x6d\x61\x70\0\x75\x6e\ 307 + \x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x63\x74\x78\ 308 + \0\x68\x69\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\x66\x6d\x6f\x64\x5f\ 309 + \x72\x65\x74\x2f\x5f\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\ 310 + \x63\x61\x6c\x6c\0\x2f\x68\x6f\x6d\x65\x2f\x62\x74\x69\x73\x73\x6f\x69\x72\x2f\ 311 + \x53\x72\x63\x2f\x68\x69\x64\x2f\x64\x72\x69\x76\x65\x72\x73\x2f\x68\x69\x64\ 312 + \x2f\x62\x70\x66\x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\x2f\x65\x6e\ 313 + \x74\x72\x79\x70\x6f\x69\x6e\x74\x73\x2e\x62\x70\x66\x2e\x63\0\x69\x6e\x74\x20\ 314 + \x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x74\x61\x69\x6c\x5f\x63\ 315 + \x61\x6c\x6c\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x68\x69\x64\x5f\x62\x70\x66\ 316 + \x5f\x63\x74\x78\x20\x2a\x68\x63\x74\x78\x29\0\x68\x69\x64\x5f\x62\x70\x66\x5f\ 317 + \x63\x74\x78\0\x69\x6e\x64\x65\x78\0\x68\x69\x64\0\x61\x6c\x6c\x6f\x63\x61\x74\ 318 + \x65\x64\x5f\x73\x69\x7a\x65\0\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\x70\x65\0\ 319 + \x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x68\ 320 + \x69\x64\x5f\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\x70\x65\0\x48\x49\x44\x5f\x49\ 321 + \x4e\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x4f\x55\x54\x50\ 322 + \x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x46\x45\x41\x54\x55\x52\ 323 + \x45\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x52\x45\x50\x4f\x52\x54\x5f\ 324 + \x54\x59\x50\x45\x53\0\x72\x65\x74\x76\x61\x6c\0\x73\x69\x7a\x65\0\x5f\x5f\x73\ 325 + \x33\x32\0\x30\x3a\x30\0\x09\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\ 326 + \x6c\x28\x63\x74\x78\x2c\x20\x26\x68\x69\x64\x5f\x6a\x6d\x70\x5f\x74\x61\x62\ 327 + \x6c\x65\x2c\x20\x68\x63\x74\x78\x2d\x3e\x69\x6e\x64\x65\x78\x29\x3b\0\x68\x69\ 328 + \x64\x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\x65\0\x66\x65\x78\x69\x74\ 329 + \x2f\x62\x70\x66\x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\x65\0\x69\x6e\ 330 + \x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x70\x72\x6f\x67\ 331 + \x5f\x72\x65\x6c\x65\x61\x73\x65\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x69\x6e\ 332 + \x6f\x64\x65\x20\x2a\x69\x6e\x6f\x64\x65\x2c\x20\x73\x74\x72\x75\x63\x74\x20\ 333 + \x66\x69\x6c\x65\x20\x2a\x66\x69\x6c\x70\x29\0\x66\x69\x6c\x65\0\x66\x5f\x70\ 334 + \x61\x74\x68\0\x66\x5f\x69\x6e\x6f\x64\x65\0\x66\x5f\x6f\x70\0\x66\x5f\x6c\x6f\ 335 + \x63\x6b\0\x66\x5f\x63\x6f\x75\x6e\x74\0\x66\x5f\x66\x6c\x61\x67\x73\0\x66\x5f\ 336 + \x6d\x6f\x64\x65\0\x66\x5f\x70\x6f\x73\x5f\x6c\x6f\x63\x6b\0\x66\x5f\x70\x6f\ 337 + \x73\0\x66\x5f\x6f\x77\x6e\x65\x72\0\x66\x5f\x63\x72\x65\x64\0\x66\x5f\x72\x61\ 338 + \0\x66\x5f\x76\x65\x72\x73\x69\x6f\x6e\0\x66\x5f\x73\x65\x63\x75\x72\x69\x74\ 339 + \x79\0\x70\x72\x69\x76\x61\x74\x65\x5f\x64\x61\x74\x61\0\x66\x5f\x65\x70\0\x66\ 340 + \x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x66\x5f\x77\x62\x5f\x65\x72\x72\0\x66\x5f\ 341 + \x73\x62\x5f\x65\x72\x72\0\x66\x5f\x6c\x6c\x69\x73\x74\0\x66\x5f\x72\x63\x75\ 342 + \x68\x65\x61\x64\0\x66\x5f\x69\x6f\x63\x62\x5f\x66\x6c\x61\x67\x73\0\x6c\x6c\ 343 + \x69\x73\x74\x5f\x6e\x6f\x64\x65\0\x6e\x65\x78\x74\0\x63\x61\x6c\x6c\x62\x61\ 344 + \x63\x6b\x5f\x68\x65\x61\x64\0\x66\x75\x6e\x63\0\x70\x61\x74\x68\0\x6d\x6e\x74\ 345 + \0\x64\x65\x6e\x74\x72\x79\0\x73\x70\x69\x6e\x6c\x6f\x63\x6b\x5f\x74\0\x73\x70\ 346 + \x69\x6e\x6c\x6f\x63\x6b\0\x72\x6c\x6f\x63\x6b\0\x72\x61\x77\x5f\x73\x70\x69\ 347 + \x6e\x6c\x6f\x63\x6b\0\x72\x61\x77\x5f\x6c\x6f\x63\x6b\0\x61\x72\x63\x68\x5f\ 348 + \x73\x70\x69\x6e\x6c\x6f\x63\x6b\x5f\x74\0\x71\x73\x70\x69\x6e\x6c\x6f\x63\x6b\ 349 + \0\x76\x61\x6c\0\x61\x74\x6f\x6d\x69\x63\x5f\x74\0\x63\x6f\x75\x6e\x74\x65\x72\ 350 + \0\x6c\x6f\x63\x6b\x65\x64\0\x70\x65\x6e\x64\x69\x6e\x67\0\x75\x38\0\x6c\x6f\ 351 + \x63\x6b\x65\x64\x5f\x70\x65\x6e\x64\x69\x6e\x67\0\x74\x61\x69\x6c\0\x75\x31\ 352 + \x36\0\x5f\x5f\x75\x31\x36\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x73\x68\x6f\ 353 + \x72\x74\0\x61\x74\x6f\x6d\x69\x63\x5f\x6c\x6f\x6e\x67\x5f\x74\0\x61\x74\x6f\ 354 + \x6d\x69\x63\x36\x34\x5f\x74\0\x73\x36\x34\0\x5f\x5f\x73\x36\x34\0\x6c\x6f\x6e\ 355 + \x67\x20\x6c\x6f\x6e\x67\0\x66\x6d\x6f\x64\x65\x5f\x74\0\x6d\x75\x74\x65\x78\0\ 356 + \x6f\x77\x6e\x65\x72\0\x77\x61\x69\x74\x5f\x6c\x6f\x63\x6b\0\x6f\x73\x71\0\x77\ 357 + \x61\x69\x74\x5f\x6c\x69\x73\x74\0\x72\x61\x77\x5f\x73\x70\x69\x6e\x6c\x6f\x63\ 358 + \x6b\x5f\x74\0\x6f\x70\x74\x69\x6d\x69\x73\x74\x69\x63\x5f\x73\x70\x69\x6e\x5f\ 359 + \x71\x75\x65\x75\x65\0\x6c\x69\x73\x74\x5f\x68\x65\x61\x64\0\x70\x72\x65\x76\0\ 360 + \x6c\x6f\x66\x66\x5f\x74\0\x5f\x5f\x6b\x65\x72\x6e\x65\x6c\x5f\x6c\x6f\x66\x66\ 361 + \x5f\x74\0\x66\x6f\x77\x6e\x5f\x73\x74\x72\x75\x63\x74\0\x6c\x6f\x63\x6b\0\x70\ 362 + \x69\x64\0\x70\x69\x64\x5f\x74\x79\x70\x65\0\x75\x69\x64\0\x65\x75\x69\x64\0\ 363 + \x73\x69\x67\x6e\x75\x6d\0\x72\x77\x6c\x6f\x63\x6b\x5f\x74\0\x61\x72\x63\x68\ 364 + \x5f\x72\x77\x6c\x6f\x63\x6b\x5f\x74\0\x71\x72\x77\x6c\x6f\x63\x6b\0\x63\x6e\ 365 + \x74\x73\0\x77\x6c\x6f\x63\x6b\x65\x64\0\x5f\x5f\x6c\x73\x74\x61\x74\x65\0\x50\ 366 + \x49\x44\x54\x59\x50\x45\x5f\x50\x49\x44\0\x50\x49\x44\x54\x59\x50\x45\x5f\x54\ 367 + \x47\x49\x44\0\x50\x49\x44\x54\x59\x50\x45\x5f\x50\x47\x49\x44\0\x50\x49\x44\ 368 + \x54\x59\x50\x45\x5f\x53\x49\x44\0\x50\x49\x44\x54\x59\x50\x45\x5f\x4d\x41\x58\ 369 + \0\x6b\x75\x69\x64\x5f\x74\0\x75\x69\x64\x5f\x74\0\x5f\x5f\x6b\x65\x72\x6e\x65\ 370 + \x6c\x5f\x75\x69\x64\x33\x32\x5f\x74\0\x66\x69\x6c\x65\x5f\x72\x61\x5f\x73\x74\ 371 + \x61\x74\x65\0\x73\x74\x61\x72\x74\0\x61\x73\x79\x6e\x63\x5f\x73\x69\x7a\x65\0\ 372 + \x72\x61\x5f\x70\x61\x67\x65\x73\0\x6d\x6d\x61\x70\x5f\x6d\x69\x73\x73\0\x70\ 373 + \x72\x65\x76\x5f\x70\x6f\x73\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\ 374 + \x67\0\x75\x36\x34\0\x5f\x5f\x75\x36\x34\0\x65\x72\x72\x73\x65\x71\x5f\x74\0\ 375 + \x75\x33\x32\0\x30\x3a\x31\x35\0\x09\x75\x36\x34\x20\x70\x72\x6f\x67\x20\x3d\ 376 + \x20\x28\x75\x36\x34\x29\x66\x69\x6c\x70\x2d\x3e\x70\x72\x69\x76\x61\x74\x65\ 377 + \x5f\x64\x61\x74\x61\x3b\0\x09\x76\x61\x6c\x75\x65\x20\x3d\x20\x62\x70\x66\x5f\ 378 + \x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x70\x72\ 379 + \x6f\x67\x73\x5f\x6d\x61\x70\x2c\x20\x26\x70\x72\x6f\x67\x29\x3b\0\x09\x69\x66\ 380 + \x20\x28\x21\x76\x61\x6c\x75\x65\x29\0\x09\x69\x66\x20\x28\x63\x61\x6c\x6c\x5f\ 381 + \x68\x69\x64\x5f\x62\x70\x66\x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\ 382 + \x65\x28\x70\x72\x6f\x67\x2c\x20\x2a\x76\x61\x6c\x75\x65\x29\x29\0\x09\x09\x62\ 383 + \x70\x66\x5f\x6d\x61\x70\x5f\x64\x65\x6c\x65\x74\x65\x5f\x65\x6c\x65\x6d\x28\ 384 + \x26\x70\x72\x6f\x67\x73\x5f\x6d\x61\x70\x2c\x20\x26\x70\x72\x6f\x67\x29\x3b\0\ 385 + \x62\x6f\x6f\x6c\0\x5f\x42\x6f\x6f\x6c\0\x63\x61\x6c\x6c\x5f\x68\x69\x64\x5f\ 386 + \x62\x70\x66\x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\x65\0\x68\x69\x64\ 387 + \x5f\x66\x72\x65\x65\x5f\x69\x6e\x6f\x64\x65\0\x66\x65\x78\x69\x74\x2f\x62\x70\ 388 + \x66\x5f\x66\x72\x65\x65\x5f\x69\x6e\x6f\x64\x65\0\x69\x6e\x74\x20\x42\x50\x46\ 389 + \x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x66\x72\x65\x65\x5f\x69\x6e\x6f\x64\ 390 + \x65\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x69\x6e\x6f\x64\x65\x20\x2a\x69\x6e\ 391 + \x6f\x64\x65\x29\0\x69\x6e\x6f\x64\x65\0\x69\x5f\x6d\x6f\x64\x65\0\x69\x5f\x6f\ 392 + \x70\x66\x6c\x61\x67\x73\0\x69\x5f\x75\x69\x64\0\x69\x5f\x67\x69\x64\0\x69\x5f\ 393 + \x66\x6c\x61\x67\x73\0\x69\x5f\x61\x63\x6c\0\x69\x5f\x64\x65\x66\x61\x75\x6c\ 394 + \x74\x5f\x61\x63\x6c\0\x69\x5f\x6f\x70\0\x69\x5f\x73\x62\0\x69\x5f\x6d\x61\x70\ 395 + \x70\x69\x6e\x67\0\x69\x5f\x73\x65\x63\x75\x72\x69\x74\x79\0\x69\x5f\x69\x6e\ 396 + \x6f\0\x69\x5f\x72\x64\x65\x76\0\x69\x5f\x73\x69\x7a\x65\0\x69\x5f\x61\x74\x69\ 397 + \x6d\x65\0\x69\x5f\x6d\x74\x69\x6d\x65\0\x69\x5f\x63\x74\x69\x6d\x65\0\x69\x5f\ 398 + \x6c\x6f\x63\x6b\0\x69\x5f\x62\x79\x74\x65\x73\0\x69\x5f\x62\x6c\x6b\x62\x69\ 399 + \x74\x73\0\x69\x5f\x77\x72\x69\x74\x65\x5f\x68\x69\x6e\x74\0\x69\x5f\x62\x6c\ 400 + \x6f\x63\x6b\x73\0\x69\x5f\x73\x74\x61\x74\x65\0\x69\x5f\x72\x77\x73\x65\x6d\0\ 401 + \x64\x69\x72\x74\x69\x65\x64\x5f\x77\x68\x65\x6e\0\x64\x69\x72\x74\x69\x65\x64\ 402 + \x5f\x74\x69\x6d\x65\x5f\x77\x68\x65\x6e\0\x69\x5f\x68\x61\x73\x68\0\x69\x5f\ 403 + \x69\x6f\x5f\x6c\x69\x73\x74\0\x69\x5f\x77\x62\0\x69\x5f\x77\x62\x5f\x66\x72\ 404 + \x6e\x5f\x77\x69\x6e\x6e\x65\x72\0\x69\x5f\x77\x62\x5f\x66\x72\x6e\x5f\x61\x76\ 405 + \x67\x5f\x74\x69\x6d\x65\0\x69\x5f\x77\x62\x5f\x66\x72\x6e\x5f\x68\x69\x73\x74\ 406 + \x6f\x72\x79\0\x69\x5f\x6c\x72\x75\0\x69\x5f\x73\x62\x5f\x6c\x69\x73\x74\0\x69\ 407 + \x5f\x77\x62\x5f\x6c\x69\x73\x74\0\x69\x5f\x76\x65\x72\x73\x69\x6f\x6e\0\x69\ 408 + \x5f\x73\x65\x71\x75\x65\x6e\x63\x65\0\x69\x5f\x63\x6f\x75\x6e\x74\0\x69\x5f\ 409 + \x64\x69\x6f\x5f\x63\x6f\x75\x6e\x74\0\x69\x5f\x77\x72\x69\x74\x65\x63\x6f\x75\ 410 + \x6e\x74\0\x69\x5f\x72\x65\x61\x64\x63\x6f\x75\x6e\x74\0\x69\x5f\x66\x6c\x63\ 411 + \x74\x78\0\x69\x5f\x64\x61\x74\x61\0\x69\x5f\x64\x65\x76\x69\x63\x65\x73\0\x69\ 412 + \x5f\x67\x65\x6e\x65\x72\x61\x74\x69\x6f\x6e\0\x69\x5f\x66\x73\x6e\x6f\x74\x69\ 413 + \x66\x79\x5f\x6d\x61\x73\x6b\0\x69\x5f\x66\x73\x6e\x6f\x74\x69\x66\x79\x5f\x6d\ 414 + \x61\x72\x6b\x73\0\x69\x5f\x63\x72\x79\x70\x74\x5f\x69\x6e\x66\x6f\0\x69\x5f\ 415 + \x76\x65\x72\x69\x74\x79\x5f\x69\x6e\x66\x6f\0\x69\x5f\x70\x72\x69\x76\x61\x74\ 416 + \x65\0\x75\x6d\x6f\x64\x65\x5f\x74\0\x6b\x67\x69\x64\x5f\x74\0\x67\x69\x64\x5f\ 417 + \x74\0\x5f\x5f\x6b\x65\x72\x6e\x65\x6c\x5f\x67\x69\x64\x33\x32\x5f\x74\0\x69\ 418 + \x5f\x6e\x6c\x69\x6e\x6b\0\x5f\x5f\x69\x5f\x6e\x6c\x69\x6e\x6b\0\x64\x65\x76\ 419 + \x5f\x74\0\x5f\x5f\x6b\x65\x72\x6e\x65\x6c\x5f\x64\x65\x76\x5f\x74\0\x74\x69\ 420 + \x6d\x65\x73\x70\x65\x63\x36\x34\0\x74\x76\x5f\x73\x65\x63\0\x74\x76\x5f\x6e\ 421 + \x73\x65\x63\0\x74\x69\x6d\x65\x36\x34\x5f\x74\0\x6c\x6f\x6e\x67\0\x62\x6c\x6b\ 422 + \x63\x6e\x74\x5f\x74\0\x72\x77\x5f\x73\x65\x6d\x61\x70\x68\x6f\x72\x65\0\x63\ 423 + \x6f\x75\x6e\x74\0\x68\x6c\x69\x73\x74\x5f\x6e\x6f\x64\x65\0\x70\x70\x72\x65\ 424 + \x76\0\x69\x5f\x64\x65\x6e\x74\x72\x79\0\x69\x5f\x72\x63\x75\0\x68\x6c\x69\x73\ 425 + \x74\x5f\x68\x65\x61\x64\0\x66\x69\x72\x73\x74\0\x69\x5f\x66\x6f\x70\0\x66\x72\ 426 + \x65\x65\x5f\x69\x6e\x6f\x64\x65\0\x61\x64\x64\x72\x65\x73\x73\x5f\x73\x70\x61\ 427 + \x63\x65\0\x68\x6f\x73\x74\0\x69\x5f\x70\x61\x67\x65\x73\0\x69\x6e\x76\x61\x6c\ 428 + \x69\x64\x61\x74\x65\x5f\x6c\x6f\x63\x6b\0\x67\x66\x70\x5f\x6d\x61\x73\x6b\0\ 429 + \x69\x5f\x6d\x6d\x61\x70\x5f\x77\x72\x69\x74\x61\x62\x6c\x65\0\x69\x5f\x6d\x6d\ 430 + \x61\x70\0\x69\x5f\x6d\x6d\x61\x70\x5f\x72\x77\x73\x65\x6d\0\x6e\x72\x70\x61\ 431 + \x67\x65\x73\0\x77\x72\x69\x74\x65\x62\x61\x63\x6b\x5f\x69\x6e\x64\x65\x78\0\ 432 + \x61\x5f\x6f\x70\x73\0\x66\x6c\x61\x67\x73\0\x77\x62\x5f\x65\x72\x72\0\x70\x72\ 433 + \x69\x76\x61\x74\x65\x5f\x6c\x6f\x63\x6b\0\x70\x72\x69\x76\x61\x74\x65\x5f\x6c\ 434 + \x69\x73\x74\0\x78\x61\x72\x72\x61\x79\0\x78\x61\x5f\x6c\x6f\x63\x6b\0\x78\x61\ 435 + \x5f\x66\x6c\x61\x67\x73\0\x78\x61\x5f\x68\x65\x61\x64\0\x67\x66\x70\x5f\x74\0\ 436 + \x72\x62\x5f\x72\x6f\x6f\x74\x5f\x63\x61\x63\x68\x65\x64\0\x72\x62\x5f\x72\x6f\ 437 + \x6f\x74\0\x72\x62\x5f\x6c\x65\x66\x74\x6d\x6f\x73\x74\0\x72\x62\x5f\x6e\x6f\ 438 + \x64\x65\0\x69\x5f\x70\x69\x70\x65\0\x69\x5f\x63\x64\x65\x76\0\x69\x5f\x6c\x69\ 439 + \x6e\x6b\0\x69\x5f\x64\x69\x72\x5f\x73\x65\x71\0\x63\x68\x61\x72\0\x30\x3a\x35\ 440 + \x33\0\x09\x75\x36\x34\x20\x70\x72\x6f\x67\x20\x3d\x20\x28\x75\x36\x34\x29\x69\ 441 + \x6e\x6f\x64\x65\x2d\x3e\x69\x5f\x70\x72\x69\x76\x61\x74\x65\x3b\0\x4c\x49\x43\ 442 + \x45\x4e\x53\x45\0\x2e\x6b\x73\x79\x6d\x73\0\x2e\x6d\x61\x70\x73\0\x6c\x69\x63\ 443 + \x65\x6e\x73\x65\0\x61\x64\x64\x72\x65\x73\x73\x5f\x73\x70\x61\x63\x65\x5f\x6f\ 444 + \x70\x65\x72\x61\x74\x69\x6f\x6e\x73\0\x62\x64\x69\x5f\x77\x72\x69\x74\x65\x62\ 445 + \x61\x63\x6b\0\x63\x64\x65\x76\0\x63\x72\x65\x64\0\x66\x69\x6c\x65\x5f\x6c\x6f\ 446 + \x63\x6b\x5f\x63\x6f\x6e\x74\x65\x78\x74\0\x66\x69\x6c\x65\x5f\x6f\x70\x65\x72\ 447 + \x61\x74\x69\x6f\x6e\x73\0\x66\x73\x63\x72\x79\x70\x74\x5f\x69\x6e\x66\x6f\0\ 448 + \x66\x73\x6e\x6f\x74\x69\x66\x79\x5f\x6d\x61\x72\x6b\x5f\x63\x6f\x6e\x6e\x65\ 449 + \x63\x74\x6f\x72\0\x66\x73\x76\x65\x72\x69\x74\x79\x5f\x69\x6e\x66\x6f\0\x68\ 450 + \x69\x64\x5f\x64\x65\x76\x69\x63\x65\0\x69\x6e\x6f\x64\x65\x5f\x6f\x70\x65\x72\ 451 + \x61\x74\x69\x6f\x6e\x73\0\x70\x69\x70\x65\x5f\x69\x6e\x6f\x64\x65\x5f\x69\x6e\ 452 + \x66\x6f\0\x70\x6f\x73\x69\x78\x5f\x61\x63\x6c\0\x73\x75\x70\x65\x72\x5f\x62\ 453 + \x6c\x6f\x63\x6b\0\x76\x66\x73\x6d\x6f\x75\x6e\x74\0\x64\x75\x6d\x6d\x79\x5f\ 454 + \x6b\x73\x79\x6d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x16\x1e\0\0\0\0\0\0\0\0\ 455 + \0\0\0\0\0\0\x03\0\0\0\x04\0\0\0\x04\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 456 + \x68\x69\x64\x5f\x6a\x6d\x70\x5f\x74\x61\x62\x6c\x65\0\0\0\0\0\0\0\0\0\0\0\0\0\ 457 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x08\0\0\0\x01\0\0\0\0\x08\0\0\0\ 458 + \0\0\0\0\0\0\0\0\0\0\0\x70\x72\x6f\x67\x73\x5f\x6d\x61\x70\0\0\0\0\0\0\0\0\0\0\ 459 + \0\0\0\0\0\x10\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\ 460 + \x79\x12\0\0\0\0\0\0\x61\x23\0\0\0\0\0\0\x18\x52\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 461 + \x85\0\0\0\x0c\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\0\0\0\x19\0\0\0\0\0\ 462 + \0\0\xb5\0\0\0\xfa\0\0\0\x05\x6c\0\0\x01\0\0\0\xb5\0\0\0\xe1\x01\0\0\x02\x74\0\ 463 + \0\x05\0\0\0\xb5\0\0\0\xfa\0\0\0\x05\x6c\0\0\x08\0\0\0\x1a\0\0\0\xdd\x01\0\0\0\ 464 + \0\0\0\x1a\0\0\0\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 465 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\ 466 + \x6c\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x10\0\ 467 + \0\0\0\0\0\0\0\0\0\0\x03\0\0\0\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\ 468 + \0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x5f\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\ 469 + \x69\x6c\x5f\x63\x61\x6c\x6c\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\x79\x11\x08\0\0\0\ 470 + \0\0\x79\x11\xc8\0\0\0\0\0\x7b\x1a\xf8\xff\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\ 471 + \0\0\xf8\xff\xff\xff\x18\x51\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\ 472 + \x15\0\x09\0\0\0\0\0\x71\x02\0\0\0\0\0\0\x79\xa1\xf8\xff\0\0\0\0\x85\x20\0\0\0\ 473 + \0\0\0\x15\0\x05\0\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xf8\xff\xff\xff\x18\ 474 + \x51\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x03\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\ 475 + \0\0\0\0\0\0\0\0\0\0\x23\0\0\0\0\0\0\0\xb5\0\0\0\x3b\x02\0\0\x05\xbc\0\0\x01\0\ 476 + \0\0\xb5\0\0\0\xd9\x05\0\0\x18\xc4\0\0\x04\0\0\0\xb5\0\0\0\0\0\0\0\0\0\0\0\x05\ 477 + \0\0\0\xb5\0\0\0\xfe\x05\0\0\x0a\x98\0\0\x08\0\0\0\xb5\0\0\0\x2f\x06\0\0\x06\ 478 + \x9c\0\0\x09\0\0\0\xb5\0\0\0\x3c\x06\0\0\x26\xa8\0\0\x0a\0\0\0\xb5\0\0\0\x3c\ 479 + \x06\0\0\x20\xa8\0\0\x0b\0\0\0\xb5\0\0\0\x3c\x06\0\0\x06\xa8\0\0\x0c\0\0\0\xb5\ 480 + \0\0\0\x3c\x06\0\0\x06\xa8\0\0\x0e\0\0\0\xb5\0\0\0\0\0\0\0\0\0\0\0\x0f\0\0\0\ 481 + \xb5\0\0\0\x6a\x06\0\0\x03\xac\0\0\x12\0\0\0\xb5\0\0\0\x3b\x02\0\0\x05\xbc\0\0\ 482 + \x08\0\0\0\x24\0\0\0\xd4\x05\0\0\0\0\0\0\x1a\0\0\0\x14\0\0\0\0\0\0\0\0\0\0\0\0\ 483 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\x64\x5f\ 484 + \x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\0\0\0\0\0\x19\0\0\0\0\0\0\0\x08\0\ 485 + \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x01\0\0\0\0\ 486 + \0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x62\x70\x66\ 487 + \x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\x65\0\0\0\0\0\0\0\0\x63\x61\ 488 + \x6c\x6c\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\ 489 + \x65\x61\x73\x65\0\0\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\x79\x11\0\0\0\0\0\0\x79\ 490 + \x11\x70\x02\0\0\0\0\x7b\x1a\xf8\xff\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\ 491 + \xf8\xff\xff\xff\x18\x51\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x15\ 492 + \0\x09\0\0\0\0\0\x71\x02\0\0\0\0\0\0\x79\xa1\xf8\xff\0\0\0\0\x85\x20\0\0\0\0\0\ 493 + \0\x15\0\x05\0\0\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xf8\xff\xff\xff\x18\x51\ 494 + \0\0\x01\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x03\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\ 495 + \0\0\0\0\0\0\0\0\x6c\0\0\0\0\0\0\0\xb5\0\0\0\xdd\x06\0\0\x05\xe4\0\0\x01\0\0\0\ 496 + \xb5\0\0\0\xf2\x0a\0\0\x19\xec\0\0\x04\0\0\0\xb5\0\0\0\0\0\0\0\0\0\0\0\x05\0\0\ 497 + \0\xb5\0\0\0\xfe\x05\0\0\x0a\x98\0\0\x08\0\0\0\xb5\0\0\0\x2f\x06\0\0\x06\x9c\0\ 498 + \0\x09\0\0\0\xb5\0\0\0\x3c\x06\0\0\x26\xa8\0\0\x0a\0\0\0\xb5\0\0\0\x3c\x06\0\0\ 499 + \x20\xa8\0\0\x0b\0\0\0\xb5\0\0\0\x3c\x06\0\0\x06\xa8\0\0\x0c\0\0\0\xb5\0\0\0\ 500 + \x3c\x06\0\0\x06\xa8\0\0\x0e\0\0\0\xb5\0\0\0\0\0\0\0\0\0\0\0\x0f\0\0\0\xb5\0\0\ 501 + \0\x6a\x06\0\0\x03\xac\0\0\x12\0\0\0\xb5\0\0\0\xdd\x06\0\0\x05\xe4\0\0\x08\0\0\ 502 + \0\x6d\0\0\0\xed\x0a\0\0\0\0\0\0\x1a\0\0\0\x14\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 503 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\x64\x5f\x66\x72\ 504 + \x65\x65\x5f\x69\x6e\x6f\x64\x65\0\0\0\0\0\0\x19\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\ 505 + \0\0\0\0\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x01\0\0\0\0\0\0\0\x01\ 506 + \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x62\x70\x66\x5f\x66\ 507 + \x72\x65\x65\x5f\x69\x6e\x6f\x64\x65\0\0\x63\x61\x6c\x6c\x5f\x68\x69\x64\x5f\ 508 + \x62\x70\x66\x5f\x70\x72\x6f\x67\x5f\x72\x65\x6c\x65\x61\x73\x65\0\0\0\0\0\0\0"; 509 + opts.insns_sz = 3152; 510 + opts.insns = (void *)"\ 511 + \xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x02\0\ 512 + \0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x1d\0\0\0\0\0\x61\ 513 + \xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c\xff\ 514 + \0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0\xd5\ 515 + \x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x84\xff\0\0\0\0\xd5\x01\x01\0\0\ 516 + \0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x88\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\ 517 + \0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\ 518 + \x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\ 519 + \0\0\x04\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\ 520 + \x85\0\0\0\xa8\0\0\0\xbf\x70\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\ 521 + \0\x18\x61\0\0\0\0\0\0\0\0\0\0\x30\x23\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\ 522 + \0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x2c\x23\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\ 523 + \0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20\x23\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\ 524 + \0\0\0\0\0\0\0\0\0\0\0\x05\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x18\x23\0\0\x7b\x01\ 525 + \0\0\0\0\0\0\xb7\x01\0\0\x12\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x18\x23\0\0\xb7\ 526 + \x03\0\0\x1c\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xcb\xff\0\0\ 527 + \0\0\x63\x7a\x78\xff\0\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\ 528 + \0\0\0\0\0\0\0\0\0\0\x44\x23\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\ 529 + \x62\0\0\0\0\0\0\0\0\0\0\x38\x23\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\ 530 + \xbf\x07\0\0\0\0\0\0\xc5\x07\xbe\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\ 531 + \0\x63\x71\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xb0\ 532 + \x23\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x2c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\ 533 + \0\0\0\0\0\0\0\0\0\0\x8c\x23\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\ 534 + \x62\0\0\0\0\0\0\0\0\0\0\x80\x23\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\ 535 + \xbf\x07\0\0\0\0\0\0\xc5\x07\xab\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x04\0\ 536 + \0\0\x63\x71\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xc8\x23\0\0\x18\x61\0\0\0\ 537 + \0\0\0\0\0\0\0\x60\x24\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xd0\ 538 + \x23\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x58\x24\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\ 539 + \0\0\0\0\0\0\0\0\0\x08\x24\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xa0\x24\0\0\x7b\x01\ 540 + \0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x10\x24\0\0\x18\x61\0\0\0\0\0\0\0\0\0\ 541 + \0\xb0\x24\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x40\x24\0\0\x18\ 542 + \x61\0\0\0\0\0\0\0\0\0\0\xd0\x24\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\ 543 + \0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc8\x24\0\0\x7b\x01\0\0\0\0\0\0\x61\ 544 + \x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x68\x24\0\0\x63\x01\0\0\0\0\0\0\ 545 + \x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x6c\x24\0\0\x63\x01\0\0\0\0\ 546 + \0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x70\x24\0\0\x7b\x01\0\0\ 547 + \0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\x24\0\0\x63\ 548 + \x01\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xe0\x24\0\0\xb7\x02\0\0\x14\0\0\0\ 549 + \xb7\x03\0\0\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\ 550 + \0\0\xc5\x07\x72\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x50\x24\0\0\x63\x70\ 551 + \x6c\0\0\0\0\0\x77\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0\xb7\x01\0\0\x05\0\0\ 552 + \0\x18\x62\0\0\0\0\0\0\0\0\0\0\x50\x24\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\xa6\ 553 + \0\0\0\xbf\x07\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xc0\x24\0\0\x61\x01\0\0\ 554 + \0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xc5\x07\ 555 + \x60\xff\0\0\0\0\x63\x7a\x80\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf8\x24\0\ 556 + \0\x18\x61\0\0\0\0\0\0\0\0\0\0\x88\x26\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\ 557 + \0\0\0\0\0\0\0\x25\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x80\x26\0\0\x7b\x01\0\0\0\0\ 558 + \0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xa0\x25\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc8\ 559 + \x26\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xa8\x25\0\0\x18\x61\0\ 560 + \0\0\0\0\0\0\0\0\0\xd8\x26\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ 561 + \x68\x26\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf8\x26\0\0\x7b\x01\0\0\0\0\0\0\x18\ 562 + \x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf0\x26\0\0\x7b\ 563 + \x01\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x26\0\0\ 564 + \x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x94\x26\ 565 + \0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\ 566 + \x26\0\0\x7b\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\ 567 + \0\xc0\x26\0\0\x63\x01\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x27\0\0\xb7\ 568 + \x02\0\0\x11\0\0\0\xb7\x03\0\0\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\0\0\ 569 + \0\xbf\x07\0\0\0\0\0\0\xc5\x07\x29\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x78\ 570 + \x26\0\0\x63\x70\x6c\0\0\0\0\0\x77\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0\x18\ 571 + \x68\0\0\0\0\0\0\0\0\0\0\x58\x25\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20\x27\0\0\ 572 + \xb7\x02\0\0\x1a\0\0\0\xb7\x03\0\0\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\ 573 + \0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x1a\xff\0\0\0\0\x75\x07\x03\0\0\0\0\0\x62\ 574 + \x08\x04\0\0\0\0\0\x6a\x08\x02\0\0\0\0\0\x05\0\x0a\0\0\0\0\0\x63\x78\x04\0\0\0\ 575 + \0\0\xbf\x79\0\0\0\0\0\0\x77\x09\0\0\x20\0\0\0\x55\x09\x02\0\0\0\0\0\x6a\x08\ 576 + \x02\0\0\0\0\0\x05\0\x04\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\x63\ 577 + \x90\0\0\0\0\0\0\x6a\x08\x02\0\x40\0\0\0\xb7\x01\0\0\x05\0\0\0\x18\x62\0\0\0\0\ 578 + \0\0\0\0\0\0\x78\x26\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\ 579 + \0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\ 580 + \0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ 581 + \xe8\x26\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\ 582 + \0\0\0\xa8\0\0\0\xc5\x07\xf9\xfe\0\0\0\0\x63\x7a\x84\xff\0\0\0\0\x18\x60\0\0\0\ 583 + \0\0\0\0\0\0\0\x40\x27\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd0\x28\0\0\x7b\x01\0\0\ 584 + \0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x48\x27\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\ 585 + \xc8\x28\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xe8\x27\0\0\x18\ 586 + \x61\0\0\0\0\0\0\0\0\0\0\x10\x29\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\ 587 + \0\0\0\xf0\x27\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20\x29\0\0\x7b\x01\0\0\0\0\0\0\ 588 + \x18\x60\0\0\0\0\0\0\0\0\0\0\xb0\x28\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x40\x29\0\ 589 + \0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\ 590 + \0\0\0\0\x38\x29\0\0\x7b\x01\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\ 591 + \0\0\0\0\0\0\xd8\x28\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\ 592 + \0\0\0\0\0\0\0\0\xdc\x28\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\ 593 + \0\0\0\0\0\0\0\0\0\0\xe0\x28\0\0\x7b\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\ 594 + \x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x29\0\0\x63\x01\0\0\0\0\0\0\x18\x61\0\0\0\0\0\ 595 + \0\0\0\0\0\x50\x29\0\0\xb7\x02\0\0\x0f\0\0\0\xb7\x03\0\0\x0c\0\0\0\xb7\x04\0\0\ 596 + \0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xc2\xfe\0\0\0\0\x18\ 597 + \x60\0\0\0\0\0\0\0\0\0\0\xc0\x28\0\0\x63\x70\x6c\0\0\0\0\0\x77\x07\0\0\x20\0\0\ 598 + \0\x63\x70\x70\0\0\0\0\0\x18\x68\0\0\0\0\0\0\0\0\0\0\xa0\x27\0\0\x18\x61\0\0\0\ 599 + \0\0\0\0\0\0\0\x60\x29\0\0\xb7\x02\0\0\x1a\0\0\0\xb7\x03\0\0\x0c\0\0\0\xb7\x04\ 600 + \0\0\0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xb3\xfe\0\0\0\0\ 601 + \x75\x07\x03\0\0\0\0\0\x62\x08\x04\0\0\0\0\0\x6a\x08\x02\0\0\0\0\0\x05\0\x0a\0\ 602 + \0\0\0\0\x63\x78\x04\0\0\0\0\0\xbf\x79\0\0\0\0\0\0\x77\x09\0\0\x20\0\0\0\x55\ 603 + \x09\x02\0\0\0\0\0\x6a\x08\x02\0\0\0\0\0\x05\0\x04\0\0\0\0\0\x18\x60\0\0\0\0\0\ 604 + \0\0\0\0\0\0\x01\0\0\x63\x90\0\0\0\0\0\0\x6a\x08\x02\0\x40\0\0\0\xb7\x01\0\0\ 605 + \x05\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc0\x28\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\ 606 + \0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\x61\ 607 + \x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\ 608 + \x18\x60\0\0\0\0\0\0\0\0\0\0\x30\x29\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\ 609 + \0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xc5\x07\x92\xfe\0\0\0\0\x63\x7a\ 610 + \x88\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\ 611 + \0\0\x85\0\0\0\xa8\0\0\0\x61\xa0\x80\xff\0\0\0\0\x63\x06\x38\0\0\0\0\0\x61\xa0\ 612 + \x84\xff\0\0\0\0\x63\x06\x3c\0\0\0\0\0\x61\xa0\x88\xff\0\0\0\0\x63\x06\x40\0\0\ 613 + \0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\ 614 + \0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x28\0\ 615 + \0\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0"; 616 + err = bpf_load_and_run(&opts); 617 + if (err < 0) 618 + return err; 619 + return 0; 620 + } 621 + 622 + static inline struct entrypoints_bpf * 623 + entrypoints_bpf__open_and_load(void) 624 + { 625 + struct entrypoints_bpf *skel; 626 + 627 + skel = entrypoints_bpf__open(); 628 + if (!skel) 629 + return NULL; 630 + if (entrypoints_bpf__load(skel)) { 631 + entrypoints_bpf__destroy(skel); 632 + return NULL; 633 + } 634 + return skel; 635 + } 636 + 637 + __attribute__((unused)) static void 638 + entrypoints_bpf__assert(struct entrypoints_bpf *s __attribute__((unused))) 639 + { 640 + #ifdef __cplusplus 641 + #define _Static_assert static_assert 642 + #endif 643 + #ifdef __cplusplus 644 + #undef _Static_assert 645 + #endif 646 + } 647 + 648 + #endif /* __ENTRYPOINTS_BPF_SKEL_H__ */
+223
drivers/hid/bpf/hid_bpf_dispatch.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * HID-BPF support for Linux 5 + * 6 + * Copyright (c) 2022 Benjamin Tissoires 7 + */ 8 + 9 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 + #include <linux/bitops.h> 11 + #include <linux/btf.h> 12 + #include <linux/btf_ids.h> 13 + #include <linux/filter.h> 14 + #include <linux/hid.h> 15 + #include <linux/hid_bpf.h> 16 + #include <linux/init.h> 17 + #include <linux/kfifo.h> 18 + #include <linux/module.h> 19 + #include <linux/workqueue.h> 20 + #include "hid_bpf_dispatch.h" 21 + #include "entrypoints/entrypoints.lskel.h" 22 + 23 + struct hid_bpf_ops *hid_bpf_ops; 24 + EXPORT_SYMBOL(hid_bpf_ops); 25 + 26 + /** 27 + * hid_bpf_device_event - Called whenever an event is coming in from the device 28 + * 29 + * @ctx: The HID-BPF context 30 + * 31 + * @return %0 on success and keep processing; a negative error code to interrupt 32 + * the processing of this event 33 + * 34 + * Declare an %fmod_ret tracing bpf program to this function and attach this 35 + * program through hid_bpf_attach_prog() to have this helper called for 36 + * any incoming event from the device itself. 37 + * 38 + * The function is called while on IRQ context, so we can not sleep. 39 + */ 40 + /* never used by the kernel but declared so we can load and attach a tracepoint */ 41 + __weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx) 42 + { 43 + return 0; 44 + } 45 + ALLOW_ERROR_INJECTION(hid_bpf_device_event, ERRNO); 46 + 47 + int 48 + dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data, 49 + u32 size, int interrupt) 50 + { 51 + struct hid_bpf_ctx_kern ctx_kern = { 52 + .ctx = { 53 + .hid = hdev, 54 + .report_type = type, 55 + .size = size, 56 + }, 57 + .data = data, 58 + }; 59 + 60 + if (type >= HID_REPORT_TYPES) 61 + return -EINVAL; 62 + 63 + return hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern); 64 + } 65 + EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event); 66 + 67 + /** 68 + * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx 69 + * 70 + * @ctx: The HID-BPF context 71 + * @offset: The offset within the memory 72 + * @rdwr_buf_size: the const size of the buffer 73 + * 74 + * @returns %NULL on error, an %__u8 memory pointer on success 75 + */ 76 + noinline __u8 * 77 + hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size) 78 + { 79 + struct hid_bpf_ctx_kern *ctx_kern; 80 + 81 + if (!ctx) 82 + return NULL; 83 + 84 + ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 85 + 86 + if (rdwr_buf_size + offset > ctx->size) 87 + return NULL; 88 + 89 + return ctx_kern->data + offset; 90 + } 91 + 92 + /* 93 + * The following set contains all functions we agree BPF programs 94 + * can use. 95 + */ 96 + BTF_SET8_START(hid_bpf_kfunc_ids) 97 + BTF_ID_FLAGS(func, call_hid_bpf_prog_release) 98 + BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL) 99 + BTF_SET8_END(hid_bpf_kfunc_ids) 100 + 101 + static const struct btf_kfunc_id_set hid_bpf_kfunc_set = { 102 + .owner = THIS_MODULE, 103 + .set = &hid_bpf_kfunc_ids, 104 + }; 105 + 106 + static int device_match_id(struct device *dev, const void *id) 107 + { 108 + struct hid_device *hdev = to_hid_device(dev); 109 + 110 + return hdev->id == *(int *)id; 111 + } 112 + 113 + /** 114 + * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device 115 + * 116 + * @hid_id: the system unique identifier of the HID device 117 + * @prog_fd: an fd in the user process representing the program to attach 118 + * @flags: any logical OR combination of &enum hid_bpf_attach_flags 119 + * 120 + * @returns %0 on success, an error code otherwise. 121 + */ 122 + /* called from syscall */ 123 + noinline int 124 + hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags) 125 + { 126 + struct hid_device *hdev; 127 + struct device *dev; 128 + int prog_type = hid_bpf_get_prog_attach_type(prog_fd); 129 + 130 + if (!hid_bpf_ops) 131 + return -EINVAL; 132 + 133 + if (prog_type < 0) 134 + return prog_type; 135 + 136 + if (prog_type >= HID_BPF_PROG_TYPE_MAX) 137 + return -EINVAL; 138 + 139 + if ((flags & ~HID_BPF_FLAG_MASK)) 140 + return -EINVAL; 141 + 142 + dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id); 143 + if (!dev) 144 + return -EINVAL; 145 + 146 + hdev = to_hid_device(dev); 147 + 148 + return __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags); 149 + } 150 + 151 + /* for syscall HID-BPF */ 152 + BTF_SET8_START(hid_bpf_syscall_kfunc_ids) 153 + BTF_ID_FLAGS(func, hid_bpf_attach_prog) 154 + BTF_SET8_END(hid_bpf_syscall_kfunc_ids) 155 + 156 + static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = { 157 + .owner = THIS_MODULE, 158 + .set = &hid_bpf_syscall_kfunc_ids, 159 + }; 160 + 161 + void hid_bpf_destroy_device(struct hid_device *hdev) 162 + { 163 + if (!hdev) 164 + return; 165 + 166 + /* mark the device as destroyed in bpf so we don't reattach it */ 167 + hdev->bpf.destroyed = true; 168 + 169 + __hid_bpf_destroy_device(hdev); 170 + } 171 + EXPORT_SYMBOL_GPL(hid_bpf_destroy_device); 172 + 173 + void hid_bpf_device_init(struct hid_device *hdev) 174 + { 175 + spin_lock_init(&hdev->bpf.progs_lock); 176 + } 177 + EXPORT_SYMBOL_GPL(hid_bpf_device_init); 178 + 179 + static int __init hid_bpf_init(void) 180 + { 181 + int err; 182 + 183 + /* Note: if we exit with an error any time here, we would entirely break HID, which 184 + * is probably not something we want. So we log an error and return success. 185 + * 186 + * This is not a big deal: the syscall allowing to attach a BPF program to a HID device 187 + * will not be available, so nobody will be able to use the functionality. 188 + */ 189 + 190 + err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set); 191 + if (err) { 192 + pr_warn("error while setting HID BPF tracing kfuncs: %d", err); 193 + return 0; 194 + } 195 + 196 + err = hid_bpf_preload_skel(); 197 + if (err) { 198 + pr_warn("error while preloading HID BPF dispatcher: %d", err); 199 + return 0; 200 + } 201 + 202 + /* register syscalls after we are sure we can load our preloaded bpf program */ 203 + err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set); 204 + if (err) { 205 + pr_warn("error while setting HID BPF syscall kfuncs: %d", err); 206 + return 0; 207 + } 208 + 209 + return 0; 210 + } 211 + 212 + static void __exit hid_bpf_exit(void) 213 + { 214 + /* HID depends on us, so if we hit that code, we are guaranteed that hid 215 + * has been removed and thus we do not need to clear the HID devices 216 + */ 217 + hid_bpf_free_links_and_skel(); 218 + } 219 + 220 + late_initcall(hid_bpf_init); 221 + module_exit(hid_bpf_exit); 222 + MODULE_AUTHOR("Benjamin Tissoires"); 223 + MODULE_LICENSE("GPL");
+27
drivers/hid/bpf/hid_bpf_dispatch.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _BPF_HID_BPF_DISPATCH_H 4 + #define _BPF_HID_BPF_DISPATCH_H 5 + 6 + #include <linux/hid.h> 7 + 8 + struct hid_bpf_ctx_kern { 9 + struct hid_bpf_ctx ctx; 10 + u8 *data; 11 + }; 12 + 13 + int hid_bpf_preload_skel(void); 14 + void hid_bpf_free_links_and_skel(void); 15 + int hid_bpf_get_prog_attach_type(int prog_fd); 16 + int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd, 17 + __u32 flags); 18 + void __hid_bpf_destroy_device(struct hid_device *hdev); 19 + int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type, 20 + struct hid_bpf_ctx_kern *ctx_kern); 21 + 22 + struct bpf_prog; 23 + 24 + /* HID-BPF internal kfuncs API */ 25 + bool call_hid_bpf_prog_release(u64 prog, int table_cnt); 26 + 27 + #endif
+568
drivers/hid/bpf/hid_bpf_jmp_table.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * HID-BPF support for Linux 5 + * 6 + * Copyright (c) 2022 Benjamin Tissoires 7 + */ 8 + 9 + #include <linux/bitops.h> 10 + #include <linux/btf.h> 11 + #include <linux/btf_ids.h> 12 + #include <linux/circ_buf.h> 13 + #include <linux/filter.h> 14 + #include <linux/hid.h> 15 + #include <linux/hid_bpf.h> 16 + #include <linux/init.h> 17 + #include <linux/module.h> 18 + #include <linux/workqueue.h> 19 + #include "hid_bpf_dispatch.h" 20 + #include "entrypoints/entrypoints.lskel.h" 21 + 22 + #define HID_BPF_MAX_PROGS 1024 /* keep this in sync with preloaded bpf, 23 + * needs to be a power of 2 as we use it as 24 + * a circular buffer 25 + */ 26 + 27 + #define NEXT(idx) (((idx) + 1) & (HID_BPF_MAX_PROGS - 1)) 28 + #define PREV(idx) (((idx) - 1) & (HID_BPF_MAX_PROGS - 1)) 29 + 30 + /* 31 + * represents one attached program stored in the hid jump table 32 + */ 33 + struct hid_bpf_prog_entry { 34 + struct bpf_prog *prog; 35 + struct hid_device *hdev; 36 + enum hid_bpf_prog_type type; 37 + u16 idx; 38 + }; 39 + 40 + struct hid_bpf_jmp_table { 41 + struct bpf_map *map; 42 + struct bpf_map *prog_keys; 43 + struct hid_bpf_prog_entry entries[HID_BPF_MAX_PROGS]; /* compacted list, circular buffer */ 44 + int tail, head; 45 + struct bpf_prog *progs[HID_BPF_MAX_PROGS]; /* idx -> progs mapping */ 46 + unsigned long enabled[BITS_TO_LONGS(HID_BPF_MAX_PROGS)]; 47 + }; 48 + 49 + #define FOR_ENTRIES(__i, __start, __end) \ 50 + for (__i = __start; CIRC_CNT(__end, __i, HID_BPF_MAX_PROGS); __i = NEXT(__i)) 51 + 52 + static struct hid_bpf_jmp_table jmp_table; 53 + 54 + static DEFINE_MUTEX(hid_bpf_attach_lock); /* held when attaching/detaching programs */ 55 + 56 + static void hid_bpf_release_progs(struct work_struct *work); 57 + 58 + static DECLARE_WORK(release_work, hid_bpf_release_progs); 59 + 60 + BTF_ID_LIST(hid_bpf_btf_ids) 61 + BTF_ID(func, hid_bpf_device_event) /* HID_BPF_PROG_TYPE_DEVICE_EVENT */ 62 + 63 + static int hid_bpf_max_programs(enum hid_bpf_prog_type type) 64 + { 65 + switch (type) { 66 + case HID_BPF_PROG_TYPE_DEVICE_EVENT: 67 + return HID_BPF_MAX_PROGS_PER_DEV; 68 + default: 69 + return -EINVAL; 70 + } 71 + } 72 + 73 + static int hid_bpf_program_count(struct hid_device *hdev, 74 + struct bpf_prog *prog, 75 + enum hid_bpf_prog_type type) 76 + { 77 + int i, n = 0; 78 + 79 + if (type >= HID_BPF_PROG_TYPE_MAX) 80 + return -EINVAL; 81 + 82 + FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 83 + struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 84 + 85 + if (type != HID_BPF_PROG_TYPE_UNDEF && entry->type != type) 86 + continue; 87 + 88 + if (hdev && entry->hdev != hdev) 89 + continue; 90 + 91 + if (prog && entry->prog != prog) 92 + continue; 93 + 94 + n++; 95 + } 96 + 97 + return n; 98 + } 99 + 100 + __weak noinline int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx) 101 + { 102 + return 0; 103 + } 104 + ALLOW_ERROR_INJECTION(__hid_bpf_tail_call, ERRNO); 105 + 106 + int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type, 107 + struct hid_bpf_ctx_kern *ctx_kern) 108 + { 109 + struct hid_bpf_prog_list *prog_list; 110 + int i, idx, err = 0; 111 + 112 + rcu_read_lock(); 113 + prog_list = rcu_dereference(hdev->bpf.progs[type]); 114 + 115 + if (!prog_list) 116 + goto out_unlock; 117 + 118 + for (i = 0; i < prog_list->prog_cnt; i++) { 119 + idx = prog_list->prog_idx[i]; 120 + 121 + if (!test_bit(idx, jmp_table.enabled)) 122 + continue; 123 + 124 + ctx_kern->ctx.index = idx; 125 + err = __hid_bpf_tail_call(&ctx_kern->ctx); 126 + if (err) 127 + break; 128 + } 129 + 130 + out_unlock: 131 + rcu_read_unlock(); 132 + 133 + return err; 134 + } 135 + 136 + /* 137 + * assign the list of programs attached to a given hid device. 138 + */ 139 + static void __hid_bpf_set_hdev_progs(struct hid_device *hdev, struct hid_bpf_prog_list *new_list, 140 + enum hid_bpf_prog_type type) 141 + { 142 + struct hid_bpf_prog_list *old_list; 143 + 144 + spin_lock(&hdev->bpf.progs_lock); 145 + old_list = rcu_dereference_protected(hdev->bpf.progs[type], 146 + lockdep_is_held(&hdev->bpf.progs_lock)); 147 + rcu_assign_pointer(hdev->bpf.progs[type], new_list); 148 + spin_unlock(&hdev->bpf.progs_lock); 149 + synchronize_rcu(); 150 + 151 + kfree(old_list); 152 + } 153 + 154 + /* 155 + * allocate and populate the list of programs attached to a given hid device. 156 + * 157 + * Must be called under lock. 158 + */ 159 + static int hid_bpf_populate_hdev(struct hid_device *hdev, enum hid_bpf_prog_type type) 160 + { 161 + struct hid_bpf_prog_list *new_list; 162 + int i; 163 + 164 + if (type >= HID_BPF_PROG_TYPE_MAX || !hdev) 165 + return -EINVAL; 166 + 167 + if (hdev->bpf.destroyed) 168 + return 0; 169 + 170 + new_list = kzalloc(sizeof(*new_list), GFP_KERNEL); 171 + if (!new_list) 172 + return -ENOMEM; 173 + 174 + FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 175 + struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 176 + 177 + if (entry->type == type && entry->hdev == hdev && 178 + test_bit(entry->idx, jmp_table.enabled)) 179 + new_list->prog_idx[new_list->prog_cnt++] = entry->idx; 180 + } 181 + 182 + __hid_bpf_set_hdev_progs(hdev, new_list, type); 183 + 184 + return 0; 185 + } 186 + 187 + static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx) 188 + { 189 + skel_map_delete_elem(map_fd, &idx); 190 + jmp_table.progs[idx] = NULL; 191 + } 192 + 193 + static void hid_bpf_release_progs(struct work_struct *work) 194 + { 195 + int i, j, n, map_fd = -1; 196 + 197 + if (!jmp_table.map) 198 + return; 199 + 200 + /* retrieve a fd of our prog_array map in BPF */ 201 + map_fd = skel_map_get_fd_by_id(jmp_table.map->id); 202 + if (map_fd < 0) 203 + return; 204 + 205 + mutex_lock(&hid_bpf_attach_lock); /* protects against attaching new programs */ 206 + 207 + /* detach unused progs from HID devices */ 208 + FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 209 + struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 210 + enum hid_bpf_prog_type type; 211 + struct hid_device *hdev; 212 + 213 + if (test_bit(entry->idx, jmp_table.enabled)) 214 + continue; 215 + 216 + /* we have an attached prog */ 217 + if (entry->hdev) { 218 + hdev = entry->hdev; 219 + type = entry->type; 220 + 221 + hid_bpf_populate_hdev(hdev, type); 222 + 223 + /* mark all other disabled progs from hdev of the given type as detached */ 224 + FOR_ENTRIES(j, i, jmp_table.head) { 225 + struct hid_bpf_prog_entry *next; 226 + 227 + next = &jmp_table.entries[j]; 228 + 229 + if (test_bit(next->idx, jmp_table.enabled)) 230 + continue; 231 + 232 + if (next->hdev == hdev && next->type == type) 233 + next->hdev = NULL; 234 + } 235 + } 236 + } 237 + 238 + /* remove all unused progs from the jump table */ 239 + FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 240 + struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 241 + 242 + if (test_bit(entry->idx, jmp_table.enabled)) 243 + continue; 244 + 245 + if (entry->prog) 246 + __hid_bpf_do_release_prog(map_fd, entry->idx); 247 + } 248 + 249 + /* compact the entry list */ 250 + n = jmp_table.tail; 251 + FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) { 252 + struct hid_bpf_prog_entry *entry = &jmp_table.entries[i]; 253 + 254 + if (!test_bit(entry->idx, jmp_table.enabled)) 255 + continue; 256 + 257 + jmp_table.entries[n] = jmp_table.entries[i]; 258 + n = NEXT(n); 259 + } 260 + 261 + jmp_table.head = n; 262 + 263 + mutex_unlock(&hid_bpf_attach_lock); 264 + 265 + if (map_fd >= 0) 266 + close_fd(map_fd); 267 + } 268 + 269 + static void hid_bpf_release_prog_at(int idx) 270 + { 271 + int map_fd = -1; 272 + 273 + /* retrieve a fd of our prog_array map in BPF */ 274 + map_fd = skel_map_get_fd_by_id(jmp_table.map->id); 275 + if (map_fd < 0) 276 + return; 277 + 278 + __hid_bpf_do_release_prog(map_fd, idx); 279 + 280 + close(map_fd); 281 + } 282 + 283 + /* 284 + * Insert the given BPF program represented by its fd in the jmp table. 285 + * Returns the index in the jump table or a negative error. 286 + */ 287 + static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog) 288 + { 289 + int i, cnt, index = -1, map_fd = -1, progs_map_fd = -1, err = -EINVAL; 290 + 291 + /* retrieve a fd of our prog_array map in BPF */ 292 + map_fd = skel_map_get_fd_by_id(jmp_table.map->id); 293 + /* take an fd for the table of progs we monitor with SEC("fexit/bpf_prog_release") */ 294 + progs_map_fd = skel_map_get_fd_by_id(jmp_table.prog_keys->id); 295 + 296 + if (map_fd < 0 || progs_map_fd < 0) { 297 + err = -EINVAL; 298 + goto out; 299 + } 300 + 301 + cnt = 0; 302 + /* find the first available index in the jmp_table 303 + * and count how many time this program has been inserted 304 + */ 305 + for (i = 0; i < HID_BPF_MAX_PROGS; i++) { 306 + if (!jmp_table.progs[i] && index < 0) { 307 + /* mark the index as used */ 308 + jmp_table.progs[i] = prog; 309 + index = i; 310 + __set_bit(i, jmp_table.enabled); 311 + cnt++; 312 + } else { 313 + if (jmp_table.progs[i] == prog) 314 + cnt++; 315 + } 316 + } 317 + if (index < 0) { 318 + err = -ENOMEM; 319 + goto out; 320 + } 321 + 322 + /* insert the program in the jump table */ 323 + err = skel_map_update_elem(map_fd, &index, &prog_fd, 0); 324 + if (err) 325 + goto out; 326 + 327 + /* insert the program in the prog list table */ 328 + err = skel_map_update_elem(progs_map_fd, &prog, &cnt, 0); 329 + if (err) 330 + goto out; 331 + 332 + /* return the index */ 333 + err = index; 334 + 335 + out: 336 + if (err < 0) 337 + __hid_bpf_do_release_prog(map_fd, index); 338 + if (map_fd >= 0) 339 + close_fd(map_fd); 340 + if (progs_map_fd >= 0) 341 + close_fd(progs_map_fd); 342 + return err; 343 + } 344 + 345 + int hid_bpf_get_prog_attach_type(int prog_fd) 346 + { 347 + struct bpf_prog *prog = NULL; 348 + int i; 349 + int prog_type = HID_BPF_PROG_TYPE_UNDEF; 350 + 351 + prog = bpf_prog_get(prog_fd); 352 + if (IS_ERR(prog)) 353 + return PTR_ERR(prog); 354 + 355 + for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) { 356 + if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) { 357 + prog_type = i; 358 + break; 359 + } 360 + } 361 + 362 + bpf_prog_put(prog); 363 + 364 + return prog_type; 365 + } 366 + 367 + /* called from syscall */ 368 + noinline int 369 + __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, 370 + int prog_fd, __u32 flags) 371 + { 372 + struct bpf_prog *prog = NULL; 373 + struct hid_bpf_prog_entry *prog_entry; 374 + int cnt, err = -EINVAL, prog_idx = -1; 375 + 376 + /* take a ref on the prog itself */ 377 + prog = bpf_prog_get(prog_fd); 378 + if (IS_ERR(prog)) 379 + return PTR_ERR(prog); 380 + 381 + mutex_lock(&hid_bpf_attach_lock); 382 + 383 + /* do not attach too many programs to a given HID device */ 384 + cnt = hid_bpf_program_count(hdev, NULL, prog_type); 385 + if (cnt < 0) { 386 + err = cnt; 387 + goto out_unlock; 388 + } 389 + 390 + if (cnt >= hid_bpf_max_programs(prog_type)) { 391 + err = -E2BIG; 392 + goto out_unlock; 393 + } 394 + 395 + prog_idx = hid_bpf_insert_prog(prog_fd, prog); 396 + /* if the jmp table is full, abort */ 397 + if (prog_idx < 0) { 398 + err = prog_idx; 399 + goto out_unlock; 400 + } 401 + 402 + if (flags & HID_BPF_FLAG_INSERT_HEAD) { 403 + /* take the previous prog_entry slot */ 404 + jmp_table.tail = PREV(jmp_table.tail); 405 + prog_entry = &jmp_table.entries[jmp_table.tail]; 406 + } else { 407 + /* take the next prog_entry slot */ 408 + prog_entry = &jmp_table.entries[jmp_table.head]; 409 + jmp_table.head = NEXT(jmp_table.head); 410 + } 411 + 412 + /* we steal the ref here */ 413 + prog_entry->prog = prog; 414 + prog_entry->idx = prog_idx; 415 + prog_entry->hdev = hdev; 416 + prog_entry->type = prog_type; 417 + 418 + /* finally store the index in the device list */ 419 + err = hid_bpf_populate_hdev(hdev, prog_type); 420 + if (err) 421 + hid_bpf_release_prog_at(prog_idx); 422 + 423 + out_unlock: 424 + mutex_unlock(&hid_bpf_attach_lock); 425 + 426 + /* we only use prog as a key in the various tables, so we don't need to actually 427 + * increment the ref count. 428 + */ 429 + bpf_prog_put(prog); 430 + 431 + return err; 432 + } 433 + 434 + void __hid_bpf_destroy_device(struct hid_device *hdev) 435 + { 436 + int type, i; 437 + struct hid_bpf_prog_list *prog_list; 438 + 439 + rcu_read_lock(); 440 + 441 + for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++) { 442 + prog_list = rcu_dereference(hdev->bpf.progs[type]); 443 + 444 + if (!prog_list) 445 + continue; 446 + 447 + for (i = 0; i < prog_list->prog_cnt; i++) 448 + __clear_bit(prog_list->prog_idx[i], jmp_table.enabled); 449 + } 450 + 451 + rcu_read_unlock(); 452 + 453 + for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++) 454 + __hid_bpf_set_hdev_progs(hdev, NULL, type); 455 + 456 + /* schedule release of all detached progs */ 457 + schedule_work(&release_work); 458 + } 459 + 460 + noinline bool 461 + call_hid_bpf_prog_release(u64 prog_key, int table_cnt) 462 + { 463 + /* compare with how many refs are left in the bpf program */ 464 + struct bpf_prog *prog = (struct bpf_prog *)prog_key; 465 + int idx; 466 + 467 + if (!prog) 468 + return false; 469 + 470 + if (atomic64_read(&prog->aux->refcnt) != table_cnt) 471 + return false; 472 + 473 + /* we don't need locking here because the entries in the progs table 474 + * are stable: 475 + * if there are other users (and the progs entries might change), we 476 + * would return in the statement above. 477 + */ 478 + for (idx = 0; idx < HID_BPF_MAX_PROGS; idx++) { 479 + if (jmp_table.progs[idx] == prog) { 480 + __clear_bit(idx, jmp_table.enabled); 481 + break; 482 + } 483 + } 484 + if (idx >= HID_BPF_MAX_PROGS) { 485 + /* should never happen if we get our refcount right */ 486 + idx = -1; 487 + } 488 + 489 + /* schedule release of all detached progs */ 490 + schedule_work(&release_work); 491 + return idx >= 0; 492 + } 493 + 494 + #define HID_BPF_PROGS_COUNT 3 495 + 496 + static struct bpf_link *links[HID_BPF_PROGS_COUNT]; 497 + static struct entrypoints_bpf *skel; 498 + 499 + void hid_bpf_free_links_and_skel(void) 500 + { 501 + int i; 502 + 503 + /* the following is enough to release all programs attached to hid */ 504 + if (jmp_table.prog_keys) 505 + bpf_map_put_with_uref(jmp_table.prog_keys); 506 + 507 + if (jmp_table.map) 508 + bpf_map_put_with_uref(jmp_table.map); 509 + 510 + for (i = 0; i < ARRAY_SIZE(links); i++) { 511 + if (!IS_ERR_OR_NULL(links[i])) 512 + bpf_link_put(links[i]); 513 + } 514 + entrypoints_bpf__destroy(skel); 515 + } 516 + 517 + #define ATTACH_AND_STORE_LINK(__name) do { \ 518 + err = entrypoints_bpf__##__name##__attach(skel); \ 519 + if (err) \ 520 + goto out; \ 521 + \ 522 + links[idx] = bpf_link_get_from_fd(skel->links.__name##_fd); \ 523 + if (IS_ERR(links[idx])) { \ 524 + err = PTR_ERR(links[idx]); \ 525 + goto out; \ 526 + } \ 527 + \ 528 + /* Avoid taking over stdin/stdout/stderr of init process. Zeroing out \ 529 + * makes skel_closenz() a no-op later in iterators_bpf__destroy(). \ 530 + */ \ 531 + close_fd(skel->links.__name##_fd); \ 532 + skel->links.__name##_fd = 0; \ 533 + idx++; \ 534 + } while (0) 535 + 536 + int hid_bpf_preload_skel(void) 537 + { 538 + int err, idx = 0; 539 + 540 + skel = entrypoints_bpf__open(); 541 + if (!skel) 542 + return -ENOMEM; 543 + 544 + err = entrypoints_bpf__load(skel); 545 + if (err) 546 + goto out; 547 + 548 + jmp_table.map = bpf_map_get_with_uref(skel->maps.hid_jmp_table.map_fd); 549 + if (IS_ERR(jmp_table.map)) { 550 + err = PTR_ERR(jmp_table.map); 551 + goto out; 552 + } 553 + 554 + jmp_table.prog_keys = bpf_map_get_with_uref(skel->maps.progs_map.map_fd); 555 + if (IS_ERR(jmp_table.prog_keys)) { 556 + err = PTR_ERR(jmp_table.prog_keys); 557 + goto out; 558 + } 559 + 560 + ATTACH_AND_STORE_LINK(hid_tail_call); 561 + ATTACH_AND_STORE_LINK(hid_prog_release); 562 + ATTACH_AND_STORE_LINK(hid_free_inode); 563 + 564 + return 0; 565 + out: 566 + hid_bpf_free_links_and_skel(); 567 + return err; 568 + }
+21
drivers/hid/hid-core.c
··· 2040 2040 report_enum = hid->report_enum + type; 2041 2041 hdrv = hid->driver; 2042 2042 2043 + ret = dispatch_hid_bpf_device_event(hid, type, data, size, interrupt); 2044 + if (ret) 2045 + goto unlock; 2046 + 2043 2047 if (!size) { 2044 2048 dbg_hid("empty report\n"); 2045 2049 ret = -1; ··· 2794 2790 sema_init(&hdev->driver_input_lock, 1); 2795 2791 mutex_init(&hdev->ll_open_lock); 2796 2792 2793 + hid_bpf_device_init(hdev); 2794 + 2797 2795 return hdev; 2798 2796 } 2799 2797 EXPORT_SYMBOL_GPL(hid_allocate_device); ··· 2822 2816 */ 2823 2817 void hid_destroy_device(struct hid_device *hdev) 2824 2818 { 2819 + hid_bpf_destroy_device(hdev); 2825 2820 hid_remove_device(hdev); 2826 2821 put_device(&hdev->dev); 2827 2822 } ··· 2909 2902 } 2910 2903 EXPORT_SYMBOL_GPL(hid_check_keys_pressed); 2911 2904 2905 + #ifdef CONFIG_HID_BPF 2906 + static struct hid_bpf_ops hid_ops = { 2907 + .owner = THIS_MODULE, 2908 + .bus_type = &hid_bus_type, 2909 + }; 2910 + #endif 2911 + 2912 2912 static int __init hid_init(void) 2913 2913 { 2914 2914 int ret; ··· 2929 2915 pr_err("can't register hid bus\n"); 2930 2916 goto err; 2931 2917 } 2918 + 2919 + #ifdef CONFIG_HID_BPF 2920 + hid_bpf_ops = &hid_ops; 2921 + #endif 2932 2922 2933 2923 ret = hidraw_init(); 2934 2924 if (ret) ··· 2949 2931 2950 2932 static void __exit hid_exit(void) 2951 2933 { 2934 + #ifdef CONFIG_HID_BPF 2935 + hid_bpf_ops = NULL; 2936 + #endif 2952 2937 hid_debug_exit(); 2953 2938 hidraw_exit(); 2954 2939 bus_unregister(&hid_bus_type);
+5
include/linux/hid.h
··· 26 26 #include <linux/mutex.h> 27 27 #include <linux/power_supply.h> 28 28 #include <uapi/linux/hid.h> 29 + #include <linux/hid_bpf.h> 29 30 30 31 /* 31 32 * We parse each description item into this structure. Short items data ··· 652 651 wait_queue_head_t debug_wait; 653 652 654 653 unsigned int id; /* system unique id */ 654 + 655 + #ifdef CONFIG_BPF 656 + struct hid_bpf bpf; /* hid-bpf data */ 657 + #endif /* CONFIG_BPF */ 655 658 }; 656 659 657 660 #define to_hid_device(pdev) \
+117
include/linux/hid_bpf.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + 3 + #ifndef __HID_BPF_H 4 + #define __HID_BPF_H 5 + 6 + #include <linux/spinlock.h> 7 + #include <uapi/linux/hid.h> 8 + 9 + struct hid_device; 10 + 11 + /* 12 + * The following is the user facing HID BPF API. 13 + * 14 + * Extra care should be taken when editing this part, as 15 + * it might break existing out of the tree bpf programs. 16 + */ 17 + 18 + /** 19 + * struct hid_bpf_ctx - User accessible data for all HID programs 20 + * 21 + * ``data`` is not directly accessible from the context. We need to issue 22 + * a call to ``hid_bpf_get_data()`` in order to get a pointer to that field. 23 + * 24 + * All of these fields are currently read-only. 25 + * 26 + * @index: program index in the jump table. No special meaning (a smaller index 27 + * doesn't mean the program will be executed before another program with 28 + * a bigger index). 29 + * @hid: the ``struct hid_device`` representing the device itself 30 + * @report_type: used for ``hid_bpf_device_event()`` 31 + * @size: Valid data in the data field. 32 + * 33 + * Programs can get the available valid size in data by fetching this field. 34 + */ 35 + struct hid_bpf_ctx { 36 + __u32 index; 37 + const struct hid_device *hid; 38 + enum hid_report_type report_type; 39 + __s32 size; 40 + }; 41 + 42 + /** 43 + * enum hid_bpf_attach_flags - flags used when attaching a HIF-BPF program 44 + * 45 + * @HID_BPF_FLAG_NONE: no specific flag is used, the kernel choses where to 46 + * insert the program 47 + * @HID_BPF_FLAG_INSERT_HEAD: insert the given program before any other program 48 + * currently attached to the device. This doesn't 49 + * guarantee that this program will always be first 50 + * @HID_BPF_FLAG_MAX: sentinel value, not to be used by the callers 51 + */ 52 + enum hid_bpf_attach_flags { 53 + HID_BPF_FLAG_NONE = 0, 54 + HID_BPF_FLAG_INSERT_HEAD = _BITUL(0), 55 + HID_BPF_FLAG_MAX, 56 + }; 57 + 58 + /* Following functions are tracepoints that BPF programs can attach to */ 59 + int hid_bpf_device_event(struct hid_bpf_ctx *ctx); 60 + 61 + /* Following functions are kfunc that we export to BPF programs */ 62 + /* only available in tracing */ 63 + __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t __sz); 64 + 65 + /* only available in syscall */ 66 + int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags); 67 + 68 + /* 69 + * Below is HID internal 70 + */ 71 + 72 + /* internal function to call eBPF programs, not to be used by anybody */ 73 + int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx); 74 + 75 + #define HID_BPF_MAX_PROGS_PER_DEV 64 76 + #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) 77 + 78 + /* types of HID programs to attach to */ 79 + enum hid_bpf_prog_type { 80 + HID_BPF_PROG_TYPE_UNDEF = -1, 81 + HID_BPF_PROG_TYPE_DEVICE_EVENT, /* an event is emitted from the device */ 82 + HID_BPF_PROG_TYPE_MAX, 83 + }; 84 + 85 + struct hid_bpf_ops { 86 + struct module *owner; 87 + struct bus_type *bus_type; 88 + }; 89 + 90 + extern struct hid_bpf_ops *hid_bpf_ops; 91 + 92 + struct hid_bpf_prog_list { 93 + u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV]; 94 + u8 prog_cnt; 95 + }; 96 + 97 + /* stored in each device */ 98 + struct hid_bpf { 99 + struct hid_bpf_prog_list __rcu *progs[HID_BPF_PROG_TYPE_MAX]; /* attached BPF progs */ 100 + bool destroyed; /* prevents the assignment of any progs */ 101 + 102 + spinlock_t progs_lock; /* protects RCU update of progs */ 103 + }; 104 + 105 + #ifdef CONFIG_HID_BPF 106 + int dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, 107 + u32 size, int interrupt); 108 + void hid_bpf_destroy_device(struct hid_device *hid); 109 + void hid_bpf_device_init(struct hid_device *hid); 110 + #else /* CONFIG_HID_BPF */ 111 + static inline int dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, 112 + u8 *data, u32 size, int interrupt) { return 0; } 113 + static inline void hid_bpf_destroy_device(struct hid_device *hid) {} 114 + static inline void hid_bpf_device_init(struct hid_device *hid) {} 115 + #endif /* CONFIG_HID_BPF */ 116 + 117 + #endif /* __HID_BPF_H */