From d97931a735ec9bc8c414a54db3951311eadd8514 Mon Sep 17 00:00:00 2001 From: pocopico Date: Fri, 16 Dec 2022 14:34:30 +0200 Subject: [PATCH] Initial commit --- CMakeLists.txt | 783 ++++++++++++++++ LICENSE | 674 ++++++++++++++ Makefile | 97 ++ PLATFORMS | 8 + common.h | 128 +++ compat/string_compat.c | 95 ++ compat/string_compat.h | 11 + compat/toolkit/drivers/usb/storage/usb.h | 135 +++ compat/toolkit/fs/proc/internal.h | 115 +++ compat/toolkit/include/.gitkeep | 0 compile-lkms.sh | 39 + config/.platforms.h.swp | Bin 0 -> 16384 bytes config/cmdline_delegate.c | 455 +++++++++ config/cmdline_delegate.h | 31 + config/cmdline_opts.h | 44 + config/platform_types.h | 126 +++ config/platforms.h | 462 +++++++++ config/platforms.h.bak | 156 ++++ config/runtime_config.c | 246 +++++ config/runtime_config.h | 71 ++ config/uart_defs.h | 50 + config/vpci_types.h | 18 + debug/debug_execve.c | 135 +++ debug/debug_execve.h | 6 + debug/debug_vuart.h | 77 ++ internal/call_protected.c | 113 +++ internal/call_protected.h | 77 ++ internal/helper/math_helper.c | 16 + internal/helper/math_helper.h | 29 + internal/helper/memory_helper.c | 44 + internal/helper/memory_helper.h | 37 + internal/helper/symbol_helper.c | 112 +++ internal/helper/symbol_helper.h | 22 + internal/intercept_driver_register.c | 269 ++++++ internal/intercept_driver_register.h | 59 ++ internal/intercept_execve.c | 145 +++ internal/intercept_execve.h | 9 + internal/ioscheduler_fixer.c | 26 + internal/ioscheduler_fixer.h | 6 + internal/notifier_base.h | 13 + internal/override/override_symbol.c | 307 ++++++ internal/override/override_symbol.h | 133 +++ internal/override/override_syscall.c | 168 ++++ internal/override/override_syscall.h | 59 ++ internal/scsi/hdparam.h | 350 +++++++ internal/scsi/scsi_notifier.c | 239 +++++ internal/scsi/scsi_notifier.h | 29 + internal/scsi/scsi_notifier_list.c | 4 + internal/scsi/scsi_notifier_list.h | 27 + internal/scsi/scsi_toolbox.c | 246 +++++ internal/scsi/scsi_toolbox.h | 100 ++ internal/scsi/scsiparam.h | 24 + internal/stealth.c | 60 ++ internal/stealth.h | 29 + internal/stealth/sanitize_cmdline.c | 162 ++++ internal/stealth/sanitize_cmdline.h | 23 + internal/uart/uart_swapper.c | 472 ++++++++++ internal/uart/uart_swapper.h | 18 + internal/uart/virtual_uart.c | 1032 +++++++++++++++++++++ internal/uart/virtual_uart.h | 126 +++ internal/uart/vuart_internal.h | 73 ++ internal/uart/vuart_virtual_irq.c | 152 +++ internal/uart/vuart_virtual_irq.h | 20 + internal/virtual_pci.c | 575 ++++++++++++ internal/virtual_pci.h | 202 ++++ lockfiles | 12 + output/rp-apollolake-4.4.180-dev.ko.gz | Bin 0 -> 67095 bytes output/rp-apollolake-4.4.180-prod.ko.gz | Bin 0 -> 32519 bytes output/rp-broadwell-4.4.180-dev.ko.gz | Bin 0 -> 67901 bytes output/rp-broadwell-4.4.180-prod.ko.gz | Bin 0 -> 32570 bytes output/rp-broadwellnk-4.4.180-dev.ko.gz | Bin 0 -> 67902 bytes output/rp-broadwellnk-4.4.180-prod.ko.gz | Bin 0 -> 32572 bytes output/rp-bromolow-3.10.108-dev.ko.gz | Bin 0 -> 68253 bytes output/rp-bromolow-3.10.108-prod.ko.gz | Bin 0 -> 32685 bytes output/rp-denverton-4.4.180-dev.ko.gz | Bin 0 -> 67086 bytes output/rp-denverton-4.4.180-prod.ko.gz | Bin 0 -> 32514 bytes output/rp-geminilake-4.4.180-dev.ko.gz | Bin 0 -> 66651 bytes output/rp-geminilake-4.4.180-prod.ko.gz | Bin 0 -> 32313 bytes output/rp-r1000-4.4.180-dev.ko.gz | Bin 0 -> 66649 bytes output/rp-r1000-4.4.180-prod.ko.gz | Bin 0 -> 32308 bytes output/rp-v1000-4.4.180-dev.ko.gz | Bin 0 -> 66647 bytes output/rp-v1000-4.4.180-prod.ko.gz | Bin 0 -> 32308 bytes redpill_main.c | 126 +++ redpill_main.h | 4 + shim/bios/bios_hwcap_shim.c | 117 +++ shim/bios/bios_hwcap_shim.h | 23 + shim/bios/bios_hwmon_shim.c | 374 ++++++++ shim/bios/bios_hwmon_shim.h | 12 + shim/bios/bios_shims_collection.c | 309 ++++++ shim/bios/bios_shims_collection.h | 56 ++ shim/bios/mfgbios_types.h | 273 ++++++ shim/bios/rtc_proxy.c | 270 ++++++ shim/bios/rtc_proxy.h | 42 + shim/bios_shim.c | 398 ++++++++ shim/bios_shim.h | 8 + shim/block_fw_update_shim.c | 88 ++ shim/block_fw_update_shim.h | 7 + shim/boot_dev/boot_shim_base.c | 70 ++ shim/boot_dev/boot_shim_base.h | 57 ++ shim/boot_dev/fake_sata_boot_shim.c | 317 +++++++ shim/boot_dev/fake_sata_boot_shim.h | 8 + shim/boot_dev/native_sata_boot_shim.c | 285 ++++++ shim/boot_dev/native_sata_boot_shim.h | 8 + shim/boot_dev/usb_boot_shim.c | 271 ++++++ shim/boot_dev/usb_boot_shim.h | 8 + shim/boot_device_shim.c | 109 +++ shim/boot_device_shim.h | 8 + shim/disable_exectutables.c | 37 + shim/disable_exectutables.h | 7 + shim/pci_shim.c | 243 +++++ shim/pci_shim.h | 24 + shim/pmu_shim.c | 387 ++++++++ shim/pmu_shim.h | 8 + shim/shim_base.h | 20 + shim/storage/sata_port_shim.c | 149 +++ shim/storage/sata_port_shim.h | 7 + shim/storage/smart_shim.c | 1082 ++++++++++++++++++++++ shim/storage/smart_shim.h | 7 + shim/uart_fixer.c | 105 +++ shim/uart_fixer.h | 8 + tools/README.md | 5 + tools/always_serial.sh | 24 + tools/always_telnet.sh | 25 + tools/inject_rp_ko.sh | 74 ++ tools/make_all.sh | 41 + 125 files changed, 15082 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 PLATFORMS create mode 100644 common.h create mode 100644 compat/string_compat.c create mode 100644 compat/string_compat.h create mode 100644 compat/toolkit/drivers/usb/storage/usb.h create mode 100644 compat/toolkit/fs/proc/internal.h create mode 100644 compat/toolkit/include/.gitkeep create mode 100644 compile-lkms.sh create mode 100644 config/.platforms.h.swp create mode 100644 config/cmdline_delegate.c create mode 100644 config/cmdline_delegate.h create mode 100644 config/cmdline_opts.h create mode 100644 config/platform_types.h create mode 100644 config/platforms.h create mode 100644 config/platforms.h.bak create mode 100644 config/runtime_config.c create mode 100644 config/runtime_config.h create mode 100644 config/uart_defs.h create mode 100644 config/vpci_types.h create mode 100644 debug/debug_execve.c create mode 100644 debug/debug_execve.h create mode 100644 debug/debug_vuart.h create mode 100644 internal/call_protected.c create mode 100644 internal/call_protected.h create mode 100644 internal/helper/math_helper.c create mode 100644 internal/helper/math_helper.h create mode 100644 internal/helper/memory_helper.c create mode 100644 internal/helper/memory_helper.h create mode 100644 internal/helper/symbol_helper.c create mode 100644 internal/helper/symbol_helper.h create mode 100644 internal/intercept_driver_register.c create mode 100644 internal/intercept_driver_register.h create mode 100644 internal/intercept_execve.c create mode 100644 internal/intercept_execve.h create mode 100644 internal/ioscheduler_fixer.c create mode 100644 internal/ioscheduler_fixer.h create mode 100644 internal/notifier_base.h create mode 100644 internal/override/override_symbol.c create mode 100644 internal/override/override_symbol.h create mode 100644 internal/override/override_syscall.c create mode 100644 internal/override/override_syscall.h create mode 100644 internal/scsi/hdparam.h create mode 100644 internal/scsi/scsi_notifier.c create mode 100644 internal/scsi/scsi_notifier.h create mode 100644 internal/scsi/scsi_notifier_list.c create mode 100644 internal/scsi/scsi_notifier_list.h create mode 100644 internal/scsi/scsi_toolbox.c create mode 100644 internal/scsi/scsi_toolbox.h create mode 100644 internal/scsi/scsiparam.h create mode 100644 internal/stealth.c create mode 100644 internal/stealth.h create mode 100644 internal/stealth/sanitize_cmdline.c create mode 100644 internal/stealth/sanitize_cmdline.h create mode 100644 internal/uart/uart_swapper.c create mode 100644 internal/uart/uart_swapper.h create mode 100644 internal/uart/virtual_uart.c create mode 100644 internal/uart/virtual_uart.h create mode 100644 internal/uart/vuart_internal.h create mode 100644 internal/uart/vuart_virtual_irq.c create mode 100644 internal/uart/vuart_virtual_irq.h create mode 100644 internal/virtual_pci.c create mode 100644 internal/virtual_pci.h create mode 100644 lockfiles create mode 100644 output/rp-apollolake-4.4.180-dev.ko.gz create mode 100644 output/rp-apollolake-4.4.180-prod.ko.gz create mode 100644 output/rp-broadwell-4.4.180-dev.ko.gz create mode 100644 output/rp-broadwell-4.4.180-prod.ko.gz create mode 100644 output/rp-broadwellnk-4.4.180-dev.ko.gz create mode 100644 output/rp-broadwellnk-4.4.180-prod.ko.gz create mode 100644 output/rp-bromolow-3.10.108-dev.ko.gz create mode 100644 output/rp-bromolow-3.10.108-prod.ko.gz create mode 100644 output/rp-denverton-4.4.180-dev.ko.gz create mode 100644 output/rp-denverton-4.4.180-prod.ko.gz create mode 100644 output/rp-geminilake-4.4.180-dev.ko.gz create mode 100644 output/rp-geminilake-4.4.180-prod.ko.gz create mode 100644 output/rp-r1000-4.4.180-dev.ko.gz create mode 100644 output/rp-r1000-4.4.180-prod.ko.gz create mode 100644 output/rp-v1000-4.4.180-dev.ko.gz create mode 100644 output/rp-v1000-4.4.180-prod.ko.gz create mode 100644 redpill_main.c create mode 100644 redpill_main.h create mode 100644 shim/bios/bios_hwcap_shim.c create mode 100644 shim/bios/bios_hwcap_shim.h create mode 100644 shim/bios/bios_hwmon_shim.c create mode 100644 shim/bios/bios_hwmon_shim.h create mode 100644 shim/bios/bios_shims_collection.c create mode 100644 shim/bios/bios_shims_collection.h create mode 100644 shim/bios/mfgbios_types.h create mode 100644 shim/bios/rtc_proxy.c create mode 100644 shim/bios/rtc_proxy.h create mode 100644 shim/bios_shim.c create mode 100644 shim/bios_shim.h create mode 100644 shim/block_fw_update_shim.c create mode 100644 shim/block_fw_update_shim.h create mode 100644 shim/boot_dev/boot_shim_base.c create mode 100644 shim/boot_dev/boot_shim_base.h create mode 100644 shim/boot_dev/fake_sata_boot_shim.c create mode 100644 shim/boot_dev/fake_sata_boot_shim.h create mode 100644 shim/boot_dev/native_sata_boot_shim.c create mode 100644 shim/boot_dev/native_sata_boot_shim.h create mode 100644 shim/boot_dev/usb_boot_shim.c create mode 100644 shim/boot_dev/usb_boot_shim.h create mode 100644 shim/boot_device_shim.c create mode 100644 shim/boot_device_shim.h create mode 100644 shim/disable_exectutables.c create mode 100644 shim/disable_exectutables.h create mode 100644 shim/pci_shim.c create mode 100644 shim/pci_shim.h create mode 100644 shim/pmu_shim.c create mode 100644 shim/pmu_shim.h create mode 100644 shim/shim_base.h create mode 100644 shim/storage/sata_port_shim.c create mode 100644 shim/storage/sata_port_shim.h create mode 100644 shim/storage/smart_shim.c create mode 100644 shim/storage/smart_shim.h create mode 100644 shim/uart_fixer.c create mode 100644 shim/uart_fixer.h create mode 100644 tools/README.md create mode 100644 tools/always_serial.sh create mode 100644 tools/always_telnet.sh create mode 100644 tools/inject_rp_ko.sh create mode 100644 tools/make_all.sh diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..53cf23a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,783 @@ +# This CMakeLists file is for usage with CLion (and maybe other) IDEs ONLY. Do NOT attempt to build the project with +# CMake as it will fail (kernel build process is tailored for Makefile while CLion's support for Makefile is... meh) + +cmake_minimum_required(VERSION 3.0) +project(redpill C) + +set(CMAKE_C_STANDARD 11) +include_directories(compat/toolkit/include) + +add_definitions(-DLINUX_VERSION_CODE=199273) +include_directories(../linux-3.10.x-bromolow-25426/include) +include_directories(../linux-3.10.x-bromolow-25426/arch/x86/include) +include_directories(../linux-3.10.x-bromolow-25426/arch/x86/include/uapi) +add_definitions(-DCONFIG_SYNO_X86_SERIAL_PORT_SWAP) + +#add_definitions(-DLINUX_VERSION_CODE=263227) +#include_directories(../linux-4.4.x-apollolake-25426/include) +#include_directories(../linux-4.4.x-apollolake-25426/arch/x86/include) +#include_directories(../linux-4.4.x-apollolake-25426/arch/x86/include/uapi) + +# Custom options in our makefile +add_definitions(-DDBG_EXECVE) + +# RP custom definitions +add_definitions(-DRP_MODULE_TARGET_VER=6) + +# Generic options +add_definitions(-D__KERNEL__) +add_definitions(-DMODULE) +add_definitions(-DKBUILD_MODNAME=\"dummy\") + +# bromolow + bromowell ones (minus CONFIG_SYNO_* which are replaced with "MY_ABC_HERE" in the kernel anyway) +add_definitions(-DCONFIG_64BIT) +add_definitions(-DCONFIG_X86_64) +add_definitions(-DCONFIG_X86) +add_definitions(-DCONFIG_INSTRUCTION_DECODER) +add_definitions(-DCONFIG_LOCKDEP_SUPPORT) +add_definitions(-DCONFIG_STACKTRACE_SUPPORT) +add_definitions(-DCONFIG_HAVE_LATENCYTOP_SUPPORT) +add_definitions(-DCONFIG_MMU) +add_definitions(-DCONFIG_NEED_DMA_MAP_STATE) +add_definitions(-DCONFIG_NEED_SG_DMA_LENGTH) +add_definitions(-DCONFIG_GENERIC_ISA_DMA) +add_definitions(-DCONFIG_GENERIC_BUG) +add_definitions(-DCONFIG_GENERIC_BUG_RELATIVE_POINTERS) +add_definitions(-DCONFIG_GENERIC_HWEIGHT) +add_definitions(-DCONFIG_ARCH_MAY_HAVE_PC_FDC) +add_definitions(-DCONFIG_RWSEM_XCHGADD_ALGORITHM) +add_definitions(-DCONFIG_GENERIC_CALIBRATE_DELAY) +add_definitions(-DCONFIG_ARCH_HAS_CPU_RELAX) +add_definitions(-DCONFIG_ARCH_HAS_CACHE_LINE_SIZE) +add_definitions(-DCONFIG_ARCH_HAS_CPU_AUTOPROBE) +add_definitions(-DCONFIG_HAVE_SETUP_PER_CPU_AREA) +add_definitions(-DCONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK) +add_definitions(-DCONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK) +add_definitions(-DCONFIG_ARCH_HIBERNATION_POSSIBLE) +add_definitions(-DCONFIG_ARCH_SUSPEND_POSSIBLE) +add_definitions(-DCONFIG_ZONE_DMA32) +add_definitions(-DCONFIG_AUDIT_ARCH) +add_definitions(-DCONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) +add_definitions(-DCONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) +add_definitions(-DCONFIG_HAVE_INTEL_TXT) +add_definitions(-DCONFIG_X86_64_SMP) +add_definitions(-DCONFIG_X86_HT) +add_definitions(-DCONFIG_ARCH_CPU_PROBE_RELEASE) +add_definitions(-DCONFIG_ARCH_SUPPORTS_UPROBES) +add_definitions(-DCONFIG_IRQ_WORK) +add_definitions(-DCONFIG_BUILDTIME_EXTABLE_SORT) +add_definitions(-DCONFIG_HAVE_KERNEL_GZIP) +add_definitions(-DCONFIG_HAVE_KERNEL_BZIP2) +add_definitions(-DCONFIG_HAVE_KERNEL_LZMA) +add_definitions(-DCONFIG_HAVE_KERNEL_XZ) +add_definitions(-DCONFIG_HAVE_KERNEL_LZO) +add_definitions(-DCONFIG_KERNEL_LZMA) +add_definitions(-DCONFIG_SWAP) +add_definitions(-DCONFIG_SYSVIPC) +add_definitions(-DCONFIG_SYSVIPC_SYSCTL) +add_definitions(-DCONFIG_POSIX_MQUEUE) +add_definitions(-DCONFIG_POSIX_MQUEUE_SYSCTL) +add_definitions(-DCONFIG_AUDIT) +add_definitions(-DCONFIG_HAVE_GENERIC_HARDIRQS) +add_definitions(-DCONFIG_GENERIC_HARDIRQS) +add_definitions(-DCONFIG_GENERIC_IRQ_PROBE) +add_definitions(-DCONFIG_GENERIC_IRQ_SHOW) +add_definitions(-DCONFIG_GENERIC_PENDING_IRQ) +add_definitions(-DCONFIG_IRQ_DOMAIN) +add_definitions(-DCONFIG_IRQ_FORCED_THREADING) +add_definitions(-DCONFIG_SPARSE_IRQ) +add_definitions(-DCONFIG_CLOCKSOURCE_WATCHDOG) +add_definitions(-DCONFIG_ARCH_CLOCKSOURCE_DATA) +add_definitions(-DCONFIG_GENERIC_TIME_VSYSCALL) +add_definitions(-DCONFIG_GENERIC_CLOCKEVENTS) +add_definitions(-DCONFIG_GENERIC_CLOCKEVENTS_BUILD) +add_definitions(-DCONFIG_GENERIC_CLOCKEVENTS_BROADCAST) +add_definitions(-DCONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST) +add_definitions(-DCONFIG_GENERIC_CMOS_UPDATE) +add_definitions(-DCONFIG_TICK_ONESHOT) +add_definitions(-DCONFIG_NO_HZ_COMMON) +add_definitions(-DCONFIG_NO_HZ_IDLE) +add_definitions(-DCONFIG_NO_HZ) +add_definitions(-DCONFIG_HIGH_RES_TIMERS) +add_definitions(-DCONFIG_TICK_CPU_ACCOUNTING) +add_definitions(-DCONFIG_TASKSTATS) +add_definitions(-DCONFIG_TASK_DELAY_ACCT) +add_definitions(-DCONFIG_TASK_XACCT) +add_definitions(-DCONFIG_TASK_IO_ACCOUNTING) +add_definitions(-DCONFIG_TREE_RCU) +add_definitions(-DCONFIG_RCU_STALL_COMMON) +add_definitions(-DCONFIG_RCU_FAST_NO_HZ) +add_definitions(-DCONFIG_HAVE_UNSTABLE_SCHED_CLOCK) +add_definitions(-DCONFIG_ARCH_SUPPORTS_NUMA_BALANCING) +add_definitions(-DCONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE) +add_definitions(-DCONFIG_CGROUPS) +add_definitions(-DCONFIG_CGROUP_FREEZER) +add_definitions(-DCONFIG_CGROUP_DEVICE) +add_definitions(-DCONFIG_CPUSETS) +add_definitions(-DCONFIG_CGROUP_CPUACCT) +add_definitions(-DCONFIG_RESOURCE_COUNTERS) +add_definitions(-DCONFIG_MEMCG) +add_definitions(-DCONFIG_MEMCG_SWAP) +add_definitions(-DCONFIG_MEMCG_SWAP_ENABLED) +add_definitions(-DCONFIG_CGROUP_SCHED) +add_definitions(-DCONFIG_FAIR_GROUP_SCHED) +add_definitions(-DCONFIG_BLK_CGROUP) +add_definitions(-DCONFIG_NAMESPACES) +add_definitions(-DCONFIG_UTS_NS) +add_definitions(-DCONFIG_IPC_NS) +add_definitions(-DCONFIG_PID_NS) +add_definitions(-DCONFIG_NET_NS) +add_definitions(-DCONFIG_UIDGID_CONVERTED) +add_definitions(-DCONFIG_MM_OWNER) +add_definitions(-DCONFIG_BLK_DEV_INITRD) +add_definitions(-DCONFIG_RD_GZIP) +add_definitions(-DCONFIG_RD_LZMA) +add_definitions(-DCONFIG_SYSCTL) +add_definitions(-DCONFIG_ANON_INODES) +add_definitions(-DCONFIG_HAVE_UID16) +add_definitions(-DCONFIG_SYSCTL_EXCEPTION_TRACE) +add_definitions(-DCONFIG_HOTPLUG) +add_definitions(-DCONFIG_HAVE_PCSPKR_PLATFORM) +add_definitions(-DCONFIG_EXPERT) +add_definitions(-DCONFIG_UID16) +add_definitions(-DCONFIG_SYSCTL_SYSCALL) +add_definitions(-DCONFIG_KALLSYMS) +add_definitions(-DCONFIG_PRINTK) +add_definitions(-DCONFIG_BUG) +add_definitions(-DCONFIG_ELF_CORE) +add_definitions(-DCONFIG_BASE_FULL) +add_definitions(-DCONFIG_FUTEX) +add_definitions(-DCONFIG_EPOLL) +add_definitions(-DCONFIG_SIGNALFD) +add_definitions(-DCONFIG_TIMERFD) +add_definitions(-DCONFIG_EVENTFD) +add_definitions(-DCONFIG_SHMEM) +add_definitions(-DCONFIG_AIO) +add_definitions(-DCONFIG_PCI_QUIRKS) +add_definitions(-DCONFIG_EMBEDDED) +add_definitions(-DCONFIG_HAVE_PERF_EVENTS) +add_definitions(-DCONFIG_PERF_EVENTS) +add_definitions(-DCONFIG_VM_EVENT_COUNTERS) +add_definitions(-DCONFIG_SLAB) +add_definitions(-DCONFIG_HAVE_OPROFILE) +add_definitions(-DCONFIG_OPROFILE_NMI_TIMER) +add_definitions(-DCONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +add_definitions(-DCONFIG_ARCH_USE_BUILTIN_BSWAP) +add_definitions(-DCONFIG_USER_RETURN_NOTIFIER) +add_definitions(-DCONFIG_HAVE_IOREMAP_PROT) +add_definitions(-DCONFIG_HAVE_KPROBES) +add_definitions(-DCONFIG_HAVE_KRETPROBES) +add_definitions(-DCONFIG_HAVE_OPTPROBES) +add_definitions(-DCONFIG_HAVE_KPROBES_ON_FTRACE) +add_definitions(-DCONFIG_HAVE_ARCH_TRACEHOOK) +add_definitions(-DCONFIG_HAVE_DMA_ATTRS) +add_definitions(-DCONFIG_USE_GENERIC_SMP_HELPERS) +add_definitions(-DCONFIG_GENERIC_SMP_IDLE_THREAD) +add_definitions(-DCONFIG_HAVE_REGS_AND_STACK_ACCESS_API) +add_definitions(-DCONFIG_HAVE_DMA_API_DEBUG) +add_definitions(-DCONFIG_HAVE_HW_BREAKPOINT) +add_definitions(-DCONFIG_HAVE_MIXED_BREAKPOINTS_REGS) +add_definitions(-DCONFIG_HAVE_USER_RETURN_NOTIFIER) +add_definitions(-DCONFIG_HAVE_PERF_EVENTS_NMI) +add_definitions(-DCONFIG_HAVE_PERF_REGS) +add_definitions(-DCONFIG_HAVE_PERF_USER_STACK_DUMP) +add_definitions(-DCONFIG_HAVE_ARCH_JUMP_LABEL) +add_definitions(-DCONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG) +add_definitions(-DCONFIG_HAVE_CMPXCHG_LOCAL) +add_definitions(-DCONFIG_HAVE_CMPXCHG_DOUBLE) +add_definitions(-DCONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION) +add_definitions(-DCONFIG_ARCH_WANT_OLD_COMPAT_IPC) +add_definitions(-DCONFIG_HAVE_ARCH_SECCOMP_FILTER) +add_definitions(-DCONFIG_HAVE_CONTEXT_TRACKING) +add_definitions(-DCONFIG_HAVE_IRQ_TIME_ACCOUNTING) +add_definitions(-DCONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE) +add_definitions(-DCONFIG_MODULES_USE_ELF_RELA) +add_definitions(-DCONFIG_OLD_SIGSUSPEND3) +add_definitions(-DCONFIG_COMPAT_OLD_SIGACTION) +add_definitions(-DCONFIG_SLABINFO) +add_definitions(-DCONFIG_RT_MUTEXES) +add_definitions(-DCONFIG_MODULES) +add_definitions(-DCONFIG_MODULE_UNLOAD) +add_definitions(-DCONFIG_X86_X2APIC) # broadwell only +add_definitions(-DCONFIG_MODULE_FORCE_UNLOAD) +add_definitions(-DCONFIG_MODULE_SIG) +add_definitions(-DCONFIG_MODULE_SIG_SHA384) +add_definitions(-DCONFIG_STOP_MACHINE) +add_definitions(-DCONFIG_BLOCK) +add_definitions(-DCONFIG_BLK_DEV_BSG) +add_definitions(-DCONFIG_BLK_DEV_BSGLIB) +add_definitions(-DCONFIG_BLK_DEV_INTEGRITY) +add_definitions(-DCONFIG_PARTITION_ADVANCED) +add_definitions(-DCONFIG_MAC_PARTITION) +add_definitions(-DCONFIG_MSDOS_PARTITION) +add_definitions(-DCONFIG_EFI_PARTITION) +add_definitions(-DCONFIG_BLOCK_COMPAT) +add_definitions(-DCONFIG_IOSCHED_NOOP) +add_definitions(-DCONFIG_IOSCHED_DEADLINE) +add_definitions(-DCONFIG_IOSCHED_CFQ) +add_definitions(-DCONFIG_DEFAULT_CFQ) +add_definitions(-DCONFIG_PREEMPT_NOTIFIERS) +add_definitions(-DCONFIG_ASN1) +add_definitions(-DCONFIG_INLINE_SPIN_UNLOCK_IRQ) +add_definitions(-DCONFIG_INLINE_READ_UNLOCK) +add_definitions(-DCONFIG_INLINE_READ_UNLOCK_IRQ) +add_definitions(-DCONFIG_INLINE_WRITE_UNLOCK) +add_definitions(-DCONFIG_INLINE_WRITE_UNLOCK_IRQ) +add_definitions(-DCONFIG_ARCH_SUPPORTS_ATOMIC_RMW) +add_definitions(-DCONFIG_MUTEX_SPIN_ON_OWNER) +add_definitions(-DCONFIG_FREEZER) +add_definitions(-DCONFIG_ZONE_DMA) +add_definitions(-DCONFIG_SMP) +add_definitions(-DCONFIG_X86_MPPARSE) +add_definitions(-DCONFIG_RETPOLINE) +add_definitions(-DCONFIG_X86_SUPPORTS_MEMORY_FAILURE) +add_definitions(-DCONFIG_NO_BOOTMEM) +add_definitions(-DCONFIG_GENERIC_CPU) +add_definitions(-DCONFIG_X86_TSC) +add_definitions(-DCONFIG_X86_CMPXCHG64) +add_definitions(-DCONFIG_X86_CMOV) +add_definitions(-DCONFIG_X86_DEBUGCTLMSR) +add_definitions(-DCONFIG_PROCESSOR_SELECT) +add_definitions(-DCONFIG_CPU_SUP_INTEL) +add_definitions(-DCONFIG_HPET_TIMER) +add_definitions(-DCONFIG_HPET_EMULATE_RTC) +add_definitions(-DCONFIG_DMI) +add_definitions(-DCONFIG_SWIOTLB) +add_definitions(-DCONFIG_IOMMU_HELPER) +add_definitions(-DCONFIG_SCHED_SMT) +add_definitions(-DCONFIG_SCHED_MC) +add_definitions(-DCONFIG_PREEMPT_NONE) +add_definitions(-DCONFIG_X86_LOCAL_APIC) +add_definitions(-DCONFIG_X86_IO_APIC) +add_definitions(-DCONFIG_X86_MCE) +add_definitions(-DCONFIG_X86_MCE_INTEL) +add_definitions(-DCONFIG_X86_MCE_THRESHOLD) +add_definitions(-DCONFIG_X86_THERMAL_VECTOR) +add_definitions(-DCONFIG_X86_MSR) +add_definitions(-DCONFIG_X86_CPUID) +add_definitions(-DCONFIG_ARCH_PHYS_ADDR_T_64BIT) +add_definitions(-DCONFIG_ARCH_DMA_ADDR_T_64BIT) +add_definitions(-DCONFIG_DIRECT_GBPAGES) +add_definitions(-DCONFIG_ARCH_SPARSEMEM_ENABLE) +add_definitions(-DCONFIG_ARCH_SPARSEMEM_DEFAULT) +add_definitions(-DCONFIG_ARCH_SELECT_MEMORY_MODEL) +add_definitions(-DCONFIG_ARCH_PROC_KCORE_TEXT) +add_definitions(-DCONFIG_SELECT_MEMORY_MODEL) +add_definitions(-DCONFIG_SPARSEMEM_MANUAL) +add_definitions(-DCONFIG_SPARSEMEM) +add_definitions(-DCONFIG_HAVE_MEMORY_PRESENT) +add_definitions(-DCONFIG_SPARSEMEM_EXTREME) +add_definitions(-DCONFIG_SPARSEMEM_VMEMMAP_ENABLE) +add_definitions(-DCONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER) +add_definitions(-DCONFIG_SPARSEMEM_VMEMMAP) +add_definitions(-DCONFIG_HAVE_MEMBLOCK) +add_definitions(-DCONFIG_HAVE_MEMBLOCK_NODE_MAP) +add_definitions(-DCONFIG_ARCH_DISCARD_MEMBLOCK) +add_definitions(-DCONFIG_PAGEFLAGS_EXTENDED) +add_definitions(-DCONFIG_COMPACTION) +add_definitions(-DCONFIG_MIGRATION) +add_definitions(-DCONFIG_PHYS_ADDR_T_64BIT) +add_definitions(-DCONFIG_BOUNCE) +add_definitions(-DCONFIG_NEED_BOUNCE_POOL) +add_definitions(-DCONFIG_VIRT_TO_BUS) +add_definitions(-DCONFIG_MMU_NOTIFIER) +add_definitions(-DCONFIG_KSM) +add_definitions(-DCONFIG_ARCH_SUPPORTS_MEMORY_FAILURE) +add_definitions(-DCONFIG_CROSS_MEMORY_ATTACH) +add_definitions(-DCONFIG_MTRR) +add_definitions(-DCONFIG_ARCH_RANDOM) +add_definitions(-DCONFIG_X86_SMAP) +add_definitions(-DCONFIG_EFI) +add_definitions(-DCONFIG_HZ_1000) +add_definitions(-DCONFIG_HZ=1000) +add_definitions(-DCONFIG_SCHED_HRTICK) +add_definitions(-DCONFIG_KEXEC) +add_definitions(-DCONFIG_CRASH_DUMP) +add_definitions(-DCONFIG_RELOCATABLE) +add_definitions(-DCONFIG_HOTPLUG_CPU) +add_definitions(-DCONFIG_ARCH_ENABLE_MEMORY_HOTPLUG) +add_definitions(-DCONFIG_ARCH_HIBERNATION_HEADER) +add_definitions(-DCONFIG_HIBERNATE_CALLBACKS) +add_definitions(-DCONFIG_HIBERNATION) +add_definitions(-DCONFIG_PM_SLEEP) +add_definitions(-DCONFIG_PM_SLEEP_SMP) +add_definitions(-DCONFIG_PM) +add_definitions(-DCONFIG_ACPI) +add_definitions(-DCONFIG_ACPI_SLEEP) +add_definitions(-DCONFIG_ACPI_DOCK) +add_definitions(-DCONFIG_ACPI_I2C) +add_definitions(-DCONFIG_ACPI_HOTPLUG_CPU) +add_definitions(-DCONFIG_X86_PM_TIMER) +add_definitions(-DCONFIG_ACPI_CONTAINER) +add_definitions(-DCONFIG_CPU_FREQ) +add_definitions(-DCONFIG_CPU_FREQ_GOV_COMMON) +add_definitions(-DCONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) +add_definitions(-DCONFIG_CPU_FREQ_GOV_USERSPACE) +add_definitions(-DCONFIG_CPU_IDLE) +add_definitions(-DCONFIG_CPU_IDLE_GOV_LADDER) +add_definitions(-DCONFIG_CPU_IDLE_GOV_MENU) +add_definitions(-DCONFIG_PCI) +add_definitions(-DCONFIG_PCI_DIRECT) +add_definitions(-DCONFIG_PCI_MMCONFIG) +add_definitions(-DCONFIG_PCI_DOMAINS) +add_definitions(-DCONFIG_PCIEPORTBUS) +add_definitions(-DCONFIG_PCIEAER) +add_definitions(-DCONFIG_PCIE_ECRC) +add_definitions(-DCONFIG_PCIEASPM) +add_definitions(-DCONFIG_PCIEASPM_PERFORMANCE) +add_definitions(-DCONFIG_ARCH_SUPPORTS_MSI) +add_definitions(-DCONFIG_PCI_MSI) +add_definitions(-DCONFIG_HT_IRQ) +add_definitions(-DCONFIG_PCI_ATS) +add_definitions(-DCONFIG_PCI_IOV) +add_definitions(-DCONFIG_PCI_IOAPIC) +add_definitions(-DCONFIG_PCI_LABEL) +add_definitions(-DCONFIG_ISA_DMA_API) +add_definitions(-DCONFIG_BINFMT_ELF) +add_definitions(-DCONFIG_COMPAT_BINFMT_ELF) +add_definitions(-DCONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE) +add_definitions(-DCONFIG_BINFMT_SCRIPT) +add_definitions(-DCONFIG_BINFMT_MISC) +add_definitions(-DCONFIG_COREDUMP) +add_definitions(-DCONFIG_IA32_EMULATION) +add_definitions(-DCONFIG_IA32_AOUT) +add_definitions(-DCONFIG_COMPAT) +add_definitions(-DCONFIG_COMPAT_FOR_U64_ALIGNMENT) +add_definitions(-DCONFIG_SYSVIPC_COMPAT) +add_definitions(-DCONFIG_KEYS_COMPAT) +add_definitions(-DCONFIG_HAVE_TEXT_POKE_SMP) +add_definitions(-DCONFIG_X86_DEV_DMA_OPS) +add_definitions(-DCONFIG_NET) +add_definitions(-DCONFIG_COMPAT_NETLINK_MESSAGES) +add_definitions(-DCONFIG_PACKET) +add_definitions(-DCONFIG_UNIX) +add_definitions(-DCONFIG_XFRM) +add_definitions(-DCONFIG_INET) +add_definitions(-DCONFIG_IP_MULTICAST) +add_definitions(-DCONFIG_IP_ADVANCED_ROUTER) +add_definitions(-DCONFIG_IP_MULTIPLE_TABLES) +add_definitions(-DCONFIG_IP_PNP) +add_definitions(-DCONFIG_IP_PNP_DHCP) +add_definitions(-DCONFIG_NET_IPGRE_BROADCAST) +add_definitions(-DCONFIG_SYN_COOKIES) +add_definitions(-DCONFIG_INET_LRO) +add_definitions(-DCONFIG_INET_DIAG) +add_definitions(-DCONFIG_INET_TCP_DIAG) +add_definitions(-DCONFIG_TCP_CONG_CUBIC) +add_definitions(-DCONFIG_IPV6_PRIVACY) +add_definitions(-DCONFIG_IPV6_ROUTER_PREF) +add_definitions(-DCONFIG_IPV6_OPTIMISTIC_DAD) +add_definitions(-DCONFIG_IPV6_SIT_6RD) +add_definitions(-DCONFIG_IPV6_NDISC_NODETYPE) +add_definitions(-DCONFIG_IPV6_MULTIPLE_TABLES) +add_definitions(-DCONFIG_IPV6_MROUTE) +add_definitions(-DCONFIG_IPV6_PIMSM_V2) +add_definitions(-DCONFIG_NETFILTER) +add_definitions(-DCONFIG_NETFILTER_ADVANCED) +add_definitions(-DCONFIG_BRIDGE_NETFILTER) +add_definitions(-DCONFIG_NF_CONNTRACK_MARK) +add_definitions(-DCONFIG_NF_CONNTRACK_PROCFS) +add_definitions(-DCONFIG_NF_NAT_NEEDED) +add_definitions(-DCONFIG_NF_CONNTRACK_PROC_COMPAT) +add_definitions(-DCONFIG_HAVE_NET_DSA) +add_definitions(-DCONFIG_NET_SCHED) +add_definitions(-DCONFIG_NET_CLS) +add_definitions(-DCONFIG_NET_SCH_FIFO) +add_definitions(-DCONFIG_DNS_RESOLVER) +add_definitions(-DCONFIG_RPS) +add_definitions(-DCONFIG_RFS_ACCEL) +add_definitions(-DCONFIG_XPS) +add_definitions(-DCONFIG_BQL) +add_definitions(-DCONFIG_FIB_RULES) +add_definitions(-DCONFIG_WIRELESS) +add_definitions(-DCONFIG_WIRELESS_EXT) +add_definitions(-DCONFIG_WEXT_CORE) +add_definitions(-DCONFIG_WEXT_PROC) +add_definitions(-DCONFIG_WEXT_PRIV) +add_definitions(-DCONFIG_HAVE_BPF_JIT) +add_definitions(-DCONFIG_DEVTMPFS) +add_definitions(-DCONFIG_STANDALONE) +add_definitions(-DCONFIG_PREVENT_FIRMWARE_BUILD) +add_definitions(-DCONFIG_FW_LOADER) +add_definitions(-DCONFIG_FW_LOADER_USER_HELPER) +add_definitions(-DCONFIG_GENERIC_CPU_VULNERABILITIES) +add_definitions(-DCONFIG_REGMAP) +add_definitions(-DCONFIG_REGMAP_I2C) +add_definitions(-DCONFIG_PNP) +add_definitions(-DCONFIG_PNPACPI) +add_definitions(-DCONFIG_BLK_DEV) +add_definitions(-DCONFIG_BLK_DEV_RAM) +add_definitions(-DCONFIG_ENCLOSURE_SERVICES) +add_definitions(-DCONFIG_HAVE_IDE) +add_definitions(-DCONFIG_SCSI_MOD) +add_definitions(-DCONFIG_RAID_ATTRS) +add_definitions(-DCONFIG_SCSI) +add_definitions(-DCONFIG_SCSI_DMA) +add_definitions(-DCONFIG_SCSI_PROC_FS) +add_definitions(-DCONFIG_BLK_DEV_SD) +add_definitions(-DCONFIG_SCSI_ENCLOSURE) +add_definitions(-DCONFIG_SCSI_MULTI_LUN) +add_definitions(-DCONFIG_SCSI_ISCSI_ATTRS) +add_definitions(-DCONFIG_SCSI_SAS_ATTRS) +add_definitions(-DCONFIG_SCSI_SAS_LIBSAS) +add_definitions(-DCONFIG_SCSI_SAS_ATA) +add_definitions(-DCONFIG_SCSI_SAS_HOST_SMP) +add_definitions(-DCONFIG_SCSI_LOWLEVEL) +add_definitions(-DCONFIG_SCSI_DH) +add_definitions(-DCONFIG_SCSI_DH_RDAC) +add_definitions(-DCONFIG_ATA) +add_definitions(-DCONFIG_ATA_VERBOSE_ERROR) +add_definitions(-DCONFIG_ATA_ACPI) +add_definitions(-DCONFIG_SATA_PMP) +add_definitions(-DCONFIG_SATA_AHCI) +add_definitions(-DCONFIG_SATA_SIL24) +add_definitions(-DCONFIG_ATA_SFF) +add_definitions(-DCONFIG_ATA_BMDMA) +add_definitions(-DCONFIG_SATA_MV) +add_definitions(-DCONFIG_MD) +add_definitions(-DCONFIG_BLK_DEV_MD) +add_definitions(-DCONFIG_MD_AUTODETECT) +add_definitions(-DCONFIG_MD_LINEAR) +add_definitions(-DCONFIG_MD_RAID0) +add_definitions(-DCONFIG_MD_RAID1) +add_definitions(-DCONFIG_MD_RAID10) +add_definitions(-DCONFIG_MD_RAID456) +add_definitions(-DCONFIG_BLK_DEV_DM_BUILTIN) +add_definitions(-DCONFIG_BLK_DEV_DM) +add_definitions(-DCONFIG_NETDEVICES) +add_definitions(-DCONFIG_NET_CORE) +add_definitions(-DCONFIG_ETHERNET) +add_definitions(-DCONFIG_NET_VENDOR_3COM) +add_definitions(-DCONFIG_NET_VENDOR_ADAPTEC) +add_definitions(-DCONFIG_NET_VENDOR_ALTEON) +add_definitions(-DCONFIG_NET_VENDOR_AMD) +add_definitions(-DCONFIG_NET_VENDOR_ATHEROS) +add_definitions(-DCONFIG_NET_CADENCE) +add_definitions(-DCONFIG_NET_VENDOR_BROADCOM) +add_definitions(-DCONFIG_BNX2X_SRIOV) +add_definitions(-DCONFIG_NET_VENDOR_BROCADE) +add_definitions(-DCONFIG_NET_VENDOR_CHELSIO) +add_definitions(-DCONFIG_NET_VENDOR_CISCO) +add_definitions(-DCONFIG_NET_VENDOR_DEC) +add_definitions(-DCONFIG_NET_VENDOR_DLINK) +add_definitions(-DCONFIG_NET_VENDOR_EMULEX) +add_definitions(-DCONFIG_NET_VENDOR_EXAR) +add_definitions(-DCONFIG_NET_VENDOR_HP) +add_definitions(-DCONFIG_NET_VENDOR_INTEL) +add_definitions(-DCONFIG_IGB_DCA) +add_definitions(-DCONFIG_NET_VENDOR_I825XX) +add_definitions(-DCONFIG_NET_VENDOR_MARVELL) +add_definitions(-DCONFIG_NET_VENDOR_MELLANOX) +add_definitions(-DCONFIG_NET_VENDOR_MICREL) +add_definitions(-DCONFIG_NET_VENDOR_MICROCHIP) +add_definitions(-DCONFIG_NET_VENDOR_MYRI) +add_definitions(-DCONFIG_NET_VENDOR_NATSEMI) +add_definitions(-DCONFIG_NET_VENDOR_8390) +add_definitions(-DCONFIG_NET_VENDOR_NVIDIA) +add_definitions(-DCONFIG_NET_VENDOR_OKI) +add_definitions(-DCONFIG_NET_VENDOR_QLOGIC) +add_definitions(-DCONFIG_NET_VENDOR_REALTEK) +add_definitions(-DCONFIG_NET_VENDOR_RDC) +add_definitions(-DCONFIG_NET_VENDOR_SEEQ) +add_definitions(-DCONFIG_NET_VENDOR_SILAN) +add_definitions(-DCONFIG_NET_VENDOR_SIS) +add_definitions(-DCONFIG_NET_VENDOR_SMSC) +add_definitions(-DCONFIG_NET_VENDOR_STMICRO) +add_definitions(-DCONFIG_NET_VENDOR_SUN) +add_definitions(-DCONFIG_NET_VENDOR_TEHUTI) +add_definitions(-DCONFIG_NET_VENDOR_TI) +add_definitions(-DCONFIG_NET_VENDOR_VIA) +add_definitions(-DCONFIG_NET_VENDOR_WIZNET) +add_definitions(-DCONFIG_WLAN) +add_definitions(-DCONFIG_INPUT) +add_definitions(-DCONFIG_SERIO) +add_definitions(-DCONFIG_SERIO_I8042) +add_definitions(-DCONFIG_SERIO_SERPORT) +add_definitions(-DCONFIG_SERIO_LIBPS2) +add_definitions(-DCONFIG_TTY) +add_definitions(-DCONFIG_VT) +add_definitions(-DCONFIG_CONSOLE_TRANSLATIONS) +add_definitions(-DCONFIG_VT_CONSOLE) +add_definitions(-DCONFIG_VT_CONSOLE_SLEEP) +add_definitions(-DCONFIG_HW_CONSOLE) +add_definitions(-DCONFIG_UNIX98_PTYS) +add_definitions(-DCONFIG_DEVPTS_MULTIPLE_INSTANCES) +add_definitions(-DCONFIG_LEGACY_PTYS) +add_definitions(-DCONFIG_SERIAL_NONSTANDARD) +add_definitions(-DCONFIG_DEVKMEM) +add_definitions(-DCONFIG_SERIAL_8250) +add_definitions(-DCONFIG_SERIAL_8250_DEPRECATED_OPTIONS) +add_definitions(-DCONFIG_SERIAL_8250_CONSOLE) +add_definitions(-DCONFIG_FIX_EARLYCON_MEM) +add_definitions(-DCONFIG_SERIAL_8250_DMA) +add_definitions(-DCONFIG_SERIAL_8250_PCI) +add_definitions(-DCONFIG_SERIAL_CORE) +add_definitions(-DCONFIG_SERIAL_CORE_CONSOLE) +add_definitions(-DCONFIG_DEVPORT) +add_definitions(-DCONFIG_I2C) +add_definitions(-DCONFIG_I2C_BOARDINFO) +add_definitions(-DCONFIG_I2C_COMPAT) +add_definitions(-DCONFIG_I2C_CHARDEV) +add_definitions(-DCONFIG_I2C_MUX) +add_definitions(-DCONFIG_I2C_HELPER_AUTO) +add_definitions(-DCONFIG_SPI) +add_definitions(-DCONFIG_SPI_MASTER) +add_definitions(-DCONFIG_SPI_BITBANG) +add_definitions(-DCONFIG_SPI_SPIDEV) +add_definitions(-DCONFIG_PPS) +add_definitions(-DCONFIG_PTP_1588_CLOCK) +add_definitions(-DCONFIG_ARCH_WANT_OPTIONAL_GPIOLIB) +add_definitions(-DCONFIG_GPIO_DEVRES) +add_definitions(-DCONFIG_HWMON) +add_definitions(-DCONFIG_HWMON_VID) +add_definitions(-DCONFIG_SENSORS_CORETEMP) +add_definitions(-DCONFIG_SENSORS_IT87) +add_definitions(-DCONFIG_THERMAL_HWMON) +add_definitions(-DCONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) +add_definitions(-DCONFIG_THERMAL_GOV_STEP_WISE) +add_definitions(-DCONFIG_SSB_POSSIBLE) +add_definitions(-DCONFIG_SSB_SPROM) +add_definitions(-DCONFIG_SSB_PCIHOST_POSSIBLE) +add_definitions(-DCONFIG_SSB_PCIHOST) +add_definitions(-DCONFIG_SSB_DRIVER_PCICORE_POSSIBLE) +add_definitions(-DCONFIG_BCMA_POSSIBLE) +add_definitions(-DCONFIG_MFD_CORE) +add_definitions(-DCONFIG_LPC_ICH) +add_definitions(-DCONFIG_VGA_ARB) +add_definitions(-DCONFIG_BACKLIGHT_LCD_SUPPORT) +add_definitions(-DCONFIG_DUMMY_CONSOLE) +add_definitions(-DCONFIG_SOUND_OSS_CORE) +add_definitions(-DCONFIG_SOUND_OSS_CORE_PRECLAIM) +add_definitions(-DCONFIG_SND_OSSEMUL) +add_definitions(-DCONFIG_SND_SUPPORT_OLD_API) +add_definitions(-DCONFIG_SND_DMA_SGBUF) +add_definitions(-DCONFIG_SND_USB) +add_definitions(-DCONFIG_USB_HIDDEV) +add_definitions(-DCONFIG_USB_ARCH_HAS_OHCI) +add_definitions(-DCONFIG_USB_ARCH_HAS_EHCI) +add_definitions(-DCONFIG_USB_ARCH_HAS_XHCI) +add_definitions(-DCONFIG_USB_SUPPORT) +add_definitions(-DCONFIG_USB_ARCH_HAS_HCD) +add_definitions(-DCONFIG_USB_DEFAULT_PERSIST) +add_definitions(-DCONFIG_USB_ETRON_HCD_DEBUGGING) +add_definitions(-DCONFIG_USB_ETRON_HUB) +add_definitions(-DCONFIG_USB_EHCI_ROOT_HUB_TT) +add_definitions(-DCONFIG_USB_EHCI_TT_NEWSCHED) +add_definitions(-DCONFIG_NEW_LEDS) +add_definitions(-DCONFIG_LEDS_CLASS) +add_definitions(-DCONFIG_LEDS_TRIGGERS) +add_definitions(-DCONFIG_LEDS_TRIGGER_TIMER) +add_definitions(-DCONFIG_LEDS_TRIGGER_HEARTBEAT) +add_definitions(-DCONFIG_RTC_LIB) +add_definitions(-DCONFIG_RTC_CLASS) +add_definitions(-DCONFIG_RTC_HCTOSYS) +add_definitions(-DCONFIG_RTC_SYSTOHC) +add_definitions(-DCONFIG_RTC_INTF_SYSFS) +add_definitions(-DCONFIG_RTC_INTF_PROC) +add_definitions(-DCONFIG_RTC_INTF_DEV) +add_definitions(-DCONFIG_RTC_DRV_CMOS) +add_definitions(-DCONFIG_DMADEVICES) +add_definitions(-DCONFIG_DMA_ENGINE) +add_definitions(-DCONFIG_DMA_ACPI) +add_definitions(-DCONFIG_ASYNC_TX_DMA) +add_definitions(-DCONFIG_STAGING) +add_definitions(-DCONFIG_USBIP_DEBUG) +add_definitions(-DCONFIG_ZSMALLOC) +add_definitions(-DCONFIG_NET_VENDOR_SILICOM) +add_definitions(-DCONFIG_X86_PLATFORM_DEVICES) +add_definitions(-DCONFIG_CLKEVT_I8253) +add_definitions(-DCONFIG_CLKBLD_I8253) +add_definitions(-DCONFIG_IOMMU_API) +add_definitions(-DCONFIG_IOMMU_SUPPORT) +add_definitions(-DCONFIG_DMAR_TABLE) +add_definitions(-DCONFIG_INTEL_IOMMU) +add_definitions(-DCONFIG_INTEL_IOMMU_DEFAULT_ON) +add_definitions(-DCONFIG_INTEL_IOMMU_FLOPPY_WA) +add_definitions(-DCONFIG_IRQ_REMAP) +add_definitions(-DCONFIG_FIRMWARE_MEMMAP) +add_definitions(-DCONFIG_DMIID) +add_definitions(-DCONFIG_EFI_VARS) +add_definitions(-DCONFIG_EFI_VARS_PSTORE) +add_definitions(-DCONFIG_DCACHE_WORD_ACCESS) +add_definitions(-DCONFIG_EXT2_FS) +add_definitions(-DCONFIG_EXT2_FS_XATTR) +add_definitions(-DCONFIG_EXT3_FS) +add_definitions(-DCONFIG_EXT3_DEFAULTS_TO_ORDERED) +add_definitions(-DCONFIG_EXT3_FS_XATTR) +add_definitions(-DCONFIG_EXT4_FS) +add_definitions(-DCONFIG_JBD) +add_definitions(-DCONFIG_JBD2) +add_definitions(-DCONFIG_FS_MBCACHE) +add_definitions(-DCONFIG_FS_POSIX_ACL) +add_definitions(-DCONFIG_FILE_LOCKING) +add_definitions(-DCONFIG_FSNOTIFY) +add_definitions(-DCONFIG_DNOTIFY) +add_definitions(-DCONFIG_INOTIFY_USER) +add_definitions(-DCONFIG_QUOTA) +add_definitions(-DCONFIG_QUOTACTL) +add_definitions(-DCONFIG_QUOTACTL_COMPAT) +add_definitions(-DCONFIG_JOLIET) +add_definitions(-DCONFIG_ZISOFS) +add_definitions(-DCONFIG_UDF_NLS) +add_definitions(-DCONFIG_PROC_FS) +add_definitions(-DCONFIG_PROC_KCORE) +add_definitions(-DCONFIG_PROC_VMCORE) +add_definitions(-DCONFIG_PROC_SYSCTL) +add_definitions(-DCONFIG_PROC_PAGE_MONITOR) +add_definitions(-DCONFIG_SYSFS) +add_definitions(-DCONFIG_TMPFS) +add_definitions(-DCONFIG_CONFIGFS_FS) +add_definitions(-DCONFIG_MISC_FILESYSTEMS) +add_definitions(-DCONFIG_PSTORE) +add_definitions(-DCONFIG_AUFS_BRANCH_MAX_1023) +add_definitions(-DCONFIG_AUFS_SBILIST) +add_definitions(-DCONFIG_AUFS_FHSM) +add_definitions(-DCONFIG_AUFS_BR_RAMFS) +add_definitions(-DCONFIG_AUFS_BR_HFSPLUS) +add_definitions(-DCONFIG_AUFS_BDEV_LOOP) +add_definitions(-DCONFIG_NETWORK_FILESYSTEMS) +add_definitions(-DCONFIG_NFS_FS) +add_definitions(-DCONFIG_NFS_V2) +add_definitions(-DCONFIG_NFS_V3) +add_definitions(-DCONFIG_NFS_V4) +add_definitions(-DCONFIG_NFS_USE_KERNEL_DNS) +add_definitions(-DCONFIG_NFS_DEBUG) +add_definitions(-DCONFIG_NFSD_V3) +add_definitions(-DCONFIG_NFSD_V4) +add_definitions(-DCONFIG_LOCKD) +add_definitions(-DCONFIG_LOCKD_V4) +add_definitions(-DCONFIG_NFS_COMMON) +add_definitions(-DCONFIG_SUNRPC) +add_definitions(-DCONFIG_SUNRPC_GSS) +add_definitions(-DCONFIG_SUNRPC_DEBUG) +add_definitions(-DCONFIG_CIFS_DEBUG) +add_definitions(-DCONFIG_CIFS_SMB2) +add_definitions(-DCONFIG_NLS) +add_definitions(-DCONFIG_NLS_UTF8) +add_definitions(-DCONFIG_TRACE_IRQFLAGS_SUPPORT) +add_definitions(-DCONFIG_PRINTK_TIME) +add_definitions(-DCONFIG_ENABLE_WARN_DEPRECATED) +add_definitions(-DCONFIG_ENABLE_MUST_CHECK) +add_definitions(-DCONFIG_MAGIC_SYSRQ) +add_definitions(-DCONFIG_DEBUG_FS) +add_definitions(-DCONFIG_DEBUG_KERNEL) +add_definitions(-DCONFIG_LOCKUP_DETECTOR) +add_definitions(-DCONFIG_HARDLOCKUP_DETECTOR) +add_definitions(-DCONFIG_BOOTPARAM_HARDLOCKUP_PANIC) +add_definitions(-DCONFIG_DETECT_HUNG_TASK) +add_definitions(-DCONFIG_SCHED_DEBUG) +add_definitions(-DCONFIG_SCHEDSTATS) +add_definitions(-DCONFIG_HAVE_DEBUG_KMEMLEAK) +add_definitions(-DCONFIG_STACKTRACE) +add_definitions(-DCONFIG_DEBUG_BUGVERBOSE) +add_definitions(-DCONFIG_ARCH_WANT_FRAME_POINTERS) +add_definitions(-DCONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS) +add_definitions(-DCONFIG_USER_STACKTRACE_SUPPORT) +add_definitions(-DCONFIG_HAVE_FUNCTION_TRACER) +add_definitions(-DCONFIG_HAVE_FUNCTION_GRAPH_TRACER) +add_definitions(-DCONFIG_HAVE_FUNCTION_GRAPH_FP_TEST) +add_definitions(-DCONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST) +add_definitions(-DCONFIG_HAVE_DYNAMIC_FTRACE) +add_definitions(-DCONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS) +add_definitions(-DCONFIG_HAVE_FTRACE_MCOUNT_RECORD) +add_definitions(-DCONFIG_HAVE_SYSCALL_TRACEPOINTS) +add_definitions(-DCONFIG_HAVE_FENTRY) +add_definitions(-DCONFIG_HAVE_C_RECORDMCOUNT) +add_definitions(-DCONFIG_TRACING_SUPPORT) +add_definitions(-DCONFIG_DYNAMIC_DEBUG) # bromolow only +add_definitions(-DCONFIG_HAVE_ARCH_KGDB) +add_definitions(-DCONFIG_HAVE_ARCH_KMEMCHECK) +add_definitions(-DCONFIG_X86_VERBOSE_BOOTUP) +add_definitions(-DCONFIG_EARLY_PRINTK) +add_definitions(-DCONFIG_DEBUG_RODATA) +add_definitions(-DCONFIG_DEBUG_RODATA_TEST) +add_definitions(-DCONFIG_HAVE_MMIOTRACE_SUPPORT) +add_definitions(-DCONFIG_IO_DELAY_0X80) +add_definitions(-DCONFIG_OPTIMIZE_INLINING) +add_definitions(-DCONFIG_KEYS) +add_definitions(-DCONFIG_KEYS_DEBUG_PROC_KEYS) +add_definitions(-DCONFIG_SECURITY) +add_definitions(-DCONFIG_SECURITYFS) +add_definitions(-DCONFIG_SECURITY_NETWORK) +add_definitions(-DCONFIG_KAISER) +add_definitions(-DCONFIG_SECURITY_PATH) +add_definitions(-DCONFIG_SECURITY_APPARMOR) +add_definitions(-DCONFIG_SECURITY_APPARMOR_COMPAT_24) +add_definitions(-DCONFIG_DEFAULT_SECURITY_APPARMOR) +add_definitions(-DCONFIG_XOR_BLOCKS) +add_definitions(-DCONFIG_ASYNC_CORE) +add_definitions(-DCONFIG_ASYNC_MEMCPY) +add_definitions(-DCONFIG_ASYNC_XOR) +add_definitions(-DCONFIG_ASYNC_PQ) +add_definitions(-DCONFIG_ASYNC_RAID6_RECOV) +add_definitions(-DCONFIG_CRYPTO) +add_definitions(-DCONFIG_CRYPTO_ALGAPI) +add_definitions(-DCONFIG_CRYPTO_ALGAPI2) +add_definitions(-DCONFIG_CRYPTO_AEAD2) +add_definitions(-DCONFIG_CRYPTO_BLKCIPHER2) +add_definitions(-DCONFIG_CRYPTO_HASH) +add_definitions(-DCONFIG_CRYPTO_HASH2) +add_definitions(-DCONFIG_CRYPTO_RNG2) +add_definitions(-DCONFIG_CRYPTO_PCOMP2) +add_definitions(-DCONFIG_CRYPTO_MANAGER2) +add_definitions(-DCONFIG_CRYPTO_MANAGER_DISABLE_TESTS) +add_definitions(-DCONFIG_CRYPTO_WORKQUEUE) +add_definitions(-DCONFIG_CRYPTO_CRC32C) +add_definitions(-DCONFIG_CRYPTO_CRCT10DIF) +add_definitions(-DCONFIG_CRYPTO_SHA512) +add_definitions(-DCONFIG_CRYPTO_AES) +add_definitions(-DCONFIG_ASYMMETRIC_KEY_TYPE) +add_definitions(-DCONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) +add_definitions(-DCONFIG_PUBLIC_KEY_ALGO_RSA) +add_definitions(-DCONFIG_X509_CERTIFICATE_PARSER) +add_definitions(-DCONFIG_HAVE_KVM) +add_definitions(-DCONFIG_HAVE_KVM_IRQCHIP) +add_definitions(-DCONFIG_HAVE_KVM_IRQ_ROUTING) +add_definitions(-DCONFIG_HAVE_KVM_EVENTFD) +add_definitions(-DCONFIG_KVM_APIC_ARCHITECTURE) +add_definitions(-DCONFIG_KVM_MMIO) +add_definitions(-DCONFIG_KVM_ASYNC_PF) +add_definitions(-DCONFIG_HAVE_KVM_MSI) +add_definitions(-DCONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT) +add_definitions(-DCONFIG_VIRTUALIZATION) +add_definitions(-DCONFIG_KVM_DEVICE_ASSIGNMENT) +add_definitions(-DCONFIG_RAID6_PQ) +add_definitions(-DCONFIG_BITREVERSE) +add_definitions(-DCONFIG_GENERIC_STRNCPY_FROM_USER) +add_definitions(-DCONFIG_GENERIC_STRNLEN_USER) +add_definitions(-DCONFIG_GENERIC_FIND_FIRST_BIT) +add_definitions(-DCONFIG_GENERIC_PCI_IOMAP) +add_definitions(-DCONFIG_GENERIC_IOMAP) +add_definitions(-DCONFIG_GENERIC_IO) +add_definitions(-DCONFIG_CRC16) +add_definitions(-DCONFIG_CRC_T10DIF) +add_definitions(-DCONFIG_CRC32) +add_definitions(-DCONFIG_CRC32_SLICEBY8) +add_definitions(-DCONFIG_ZLIB_INFLATE) +add_definitions(-DCONFIG_LZO_COMPRESS) +add_definitions(-DCONFIG_LZO_DECOMPRESS) +add_definitions(-DCONFIG_DECOMPRESS_GZIP) +add_definitions(-DCONFIG_DECOMPRESS_LZMA) +add_definitions(-DCONFIG_GENERIC_ALLOCATOR) +add_definitions(-DCONFIG_HAS_IOMEM) +add_definitions(-DCONFIG_HAS_IOPORT) +add_definitions(-DCONFIG_HAS_DMA) +add_definitions(-DCONFIG_CHECK_SIGNATURE) +add_definitions(-DCONFIG_CPU_RMAP) +add_definitions(-DCONFIG_DQL) +add_definitions(-DCONFIG_NLATTR) +add_definitions(-DCONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE) +add_definitions(-DCONFIG_AVERAGE) +add_definitions(-DCONFIG_CLZ_TAB) +add_definitions(-DCONFIG_MPILIB) +add_definitions(-DCONFIG_OID_REGISTRY) +add_definitions(-DCONFIG_UCS2_STRING) +add_definitions(-DCONFIG_SERIAL_8250_NR_UARTS=4) +add_definitions(-DCONFIG_SYNO_BOOT_SATA_DOM) # only some platforms support that, notably 3615xs while 918+ doesn't + +# SATA DOM-related configs (only models with it, e.g. 3615xs but not 918+) +add_definitions(-DCONFIG_SYNO_SATA_DOM_VENDOR=\"DUMMY_VENDOR\") +add_definitions(-DCONFIG_SYNO_SATA_DOM_MODEL=\"DUMMY_MODEL\") + +add_executable(redpill + redpill_main.c redpill_main.h internal/call_protected.c internal/call_protected.h common.h config/cmdline_delegate.c config/cmdline_delegate.h shim/boot_device_shim.c shim/boot_device_shim.h internal/stealth.c internal/stealth.h config/runtime_config.c config/runtime_config.h test.c shim/bios_shim.c shim/bios_shim.h internal/override/override_symbol.c internal/override/override_symbol.h shim/bios/bios_shims_collection.c shim/bios/bios_shims_collection.h shim/block_fw_update_shim.c shim/block_fw_update_shim.h internal/intercept_execve.c internal/intercept_execve.h shim/disable_exectutables.c shim/disable_exectutables.h debug/debug_execve.c debug/debug_execve.h compat/string_compat.c compat/string_compat.h internal/stealth/sanitize_cmdline.c internal/stealth/sanitize_cmdline.h internal/virtual_pci.c internal/virtual_pci.h shim/pci_shim.c shim/pci_shim.h shim/bios/rtc_proxy.c shim/bios/rtc_proxy.h shim/bios/rtc_proxy.c shim/bios/rtc_proxy.h internal/uart/virtual_uart.c internal/uart/virtual_uart.h shim/uart_fixer.c shim/uart_fixer.h config/uart_defs.h debug/debug_vuart.h internal/uart/vuart_virtual_irq.c internal/uart/vuart_virtual_irq.h internal/uart/vuart_internal.h shim/boot_dev/usb_boot_shim.c shim/boot_dev/usb_boot_shim.h shim/boot_dev/native_sata_boot_shim.c shim/boot_dev/native_sata_boot_shim.h internal/uart/uart_swapper.c internal/uart/uart_swapper.h shim/pmu_shim.c shim/pmu_shim.h internal/intercept_driver_register.c internal/intercept_driver_register.h shim/shim_base.h shim/storage/sata_port_shim.c shim/storage/sata_port_shim.h internal/scsi/scsi_notifier.c internal/scsi/scsi_notifier.h internal/scsi/scsi_notifier.c internal/scsi/scsi_notifier.h internal/notifier_base.h internal/scsi/scsi_toolbox.c internal/scsi/scsi_toolbox.h internal/scsi/scsi_notifier_list.c internal/scsi/scsi_notifier_list.h shim/storage/smart_shim.c shim/storage/smart_shim.h internal/helper/memory_helper.c internal/helper/memory_helper.h internal/scsi/hdparam.h internal/scsi/scsiparam.h internal/helper/symbol_helper.c internal/helper/symbol_helper.h compat/toolkit/drivers/usb/storage/usb.h shim/boot_dev/fake_sata_boot_shim.c shim/boot_dev/fake_sata_boot_shim.h shim/boot_dev/boot_shim_base.c shim/boot_dev/boot_shim_base.h config/cmdline_opts.h internal/ioscheduler_fixer.c internal/ioscheduler_fixer.h shim/bios/bios_hwcap_shim.c shim/bios/bios_hwcap_shim.h internal/helper/math_helper.c internal/helper/math_helper.h config/hwmon_defs.h config/platform_types.h shim/bios/bios_hwmon_shim.c shim/bios/bios_hwmon_shim.h config/vpci_types.h internal/override/override_syscall.c internal/override/override_syscall.h) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f86e9f8 --- /dev/null +++ b/Makefile @@ -0,0 +1,97 @@ +PWD := $(shell pwd) + +ifeq ($(LINUX_SRC),) +LINUX_SRC := "$(PWD)/../linux-3.10.x-bromolow-25426" +endif + +SRCS-$(DBG_EXECVE) += debug/debug_execve.c +ccflags-$(DBG_EXECVE) += -DRPDBG_EXECVE +SRCS-y += compat/string_compat.c \ + \ + internal/helper/math_helper.c internal/helper/memory_helper.c internal/helper/symbol_helper.c \ + internal/scsi/scsi_toolbox.c internal/scsi/scsi_notifier_list.c internal/scsi/scsi_notifier.c \ + internal/override/override_symbol.c internal/override/override_syscall.c internal/intercept_execve.c \ + internal/call_protected.c internal/intercept_driver_register.c internal/stealth/sanitize_cmdline.c \ + internal/stealth.c internal/virtual_pci.c internal/uart/uart_swapper.c internal/uart/vuart_virtual_irq.c \ + internal/uart/virtual_uart.c internal/ioscheduler_fixer.c \ + \ + config/cmdline_delegate.c config/runtime_config.c \ + \ + shim/boot_dev/boot_shim_base.c shim/boot_dev/usb_boot_shim.c shim/boot_dev/fake_sata_boot_shim.c \ + shim/boot_dev/native_sata_boot_shim.c shim/boot_device_shim.c \ + \ + shim/storage/smart_shim.c shim/storage/sata_port_shim.c \ + shim/bios/bios_hwcap_shim.c shim/bios/bios_hwmon_shim.c shim/bios/rtc_proxy.c \ + shim/bios/bios_shims_collection.c shim/bios_shim.c \ + shim/block_fw_update_shim.c shim/disable_exectutables.c shim/pci_shim.c shim/pmu_shim.c shim/uart_fixer.c \ + \ + redpill_main.c +OBJS = $(SRCS-y:.c=.o) +#this module name CAN NEVER be the same as the main file (or it will get weird ;)) and the main file has to be included +# in object file. So here we say the module file(s) which will create .ko(s) is "redpill.o" and that other objects which +# must be linked (redpill-objs variable) +obj-m += redpill.o +redpill-objs := $(OBJS) +ccflags-y += -std=gnu99 -fgnu89-inline -Wno-declaration-after-statement +ccflags-y += -I$(src)/compat/toolkit/include + +ifndef RP_VERSION_POSTFIX +RP_VERSION_POSTFIX := $(shell git rev-parse --is-inside-work-tree 1>/dev/null 2>/dev/null && echo -n "git-" && git log -1 --pretty='%h' 2>/dev/null || date '+at-%Y_%m_%d-%H_%M_%S') +endif +ccflags-y += -DRP_VERSION_POSTFIX="\"$(RP_VERSION_POSTFIX)\"" + +# Optimization settings per-target. Since LKM makefiles are evaluated twice (first with the specified target and second +# time with target "modules") we need to set the custom target variable during first parsing and based on that variable +# set additional CC-flags when the makefile is parsed for the second time +ifdef RP_MODULE_TARGET +ccflags-dev = -g -fno-inline -DDEBUG +ccflags-test = -O3 +ccflags-prod = -O3 +ccflags-y += -DRP_MODULE_TARGET_VER=${RP_MODULE_TARGET_VER} # this is assumed to be defined when target is specified + +$(info RP-TARGET SPECIFIED AS ${RP_MODULE_TARGET} v${RP_MODULE_TARGET_VER}) + +# stealth mode can always be overridden but there are sane per-target defaults (see above) +ifneq ($(STEALTH_MODE),) +$(info STEATLH MODE OVERRIDE: ${STEALTH_MODE}) +ccflags-y += -DSTEALTH_MODE=$(STEALTH_MODE) +else +ccflags-dev += -DSTEALTH_MODE=1 +ccflags-test += -DSTEALTH_MODE=2 +ccflags-prod += -DSTEALTH_MODE=3 +endif + +ccflags-y += ${ccflags-${RP_MODULE_TARGET}} +else +# during the first read of the makefile we don't get the RP_MODULE_TARGET - if for some reason we didn't get it during +# the actual build phase it should explode (and it will if an unknown GCC flag is specified). We cannot sue makefile +# error here as we don't know if the file is parsed for the first time or the second time. Just Kbuild peculiarities ;) +ccflags-y = --bogus-flag-which-should-not-be-called-NO_RP_MODULE_TARGER_SPECIFIED +endif + +# this MUST be last after all other options to force GNU89 for the file being a workaround for GCC bug #275674 +# see internal/scsi/scsi_notifier_list.h for detailed explanation +CFLAGS_scsi_notifier_list.o += -std=gnu89 + +# do NOT move this target - make <3.80 doesn't have a way to specify default target and takes the first one found +default_error: + $(error You need to specify one of the following targets: dev-v6, dev-v7, test-v6, test-v7, prod-v6, prod-v7, clean) + +# All v6 targets +dev-v6: # kernel running in v6.2+ OS, all symbols included, debug messages included + $(MAKE) -C $(LINUX_SRC) M=$(PWD) RP_MODULE_TARGET="dev" RP_MODULE_TARGET_VER="6" modules +test-v6: # kernel running in v6.2+ OS, fully stripped with only warning & above (no debugs or info) + $(MAKE) -C $(LINUX_SRC) M=$(PWD) RP_MODULE_TARGET="test" RP_MODULE_TARGET_VER="6" modules +prod-v6: # kernel running in v6.2+ OS, fully stripped with no debug messages + $(MAKE) -C $(LINUX_SRC) M=$(PWD) RP_MODULE_TARGET="prod" RP_MODULE_TARGET_VER="6" modules + +# All v7 targets +dev-v7: # kernel running in v6.2+ OS, all symbols included, debug messages included + $(MAKE) -C $(LINUX_SRC) M=$(PWD) RP_MODULE_TARGET="dev" RP_MODULE_TARGET_VER="7" modules +test-v7: # kernel running in v6.2+ OS, fully stripped with only warning & above (no debugs or info) + $(MAKE) -C $(LINUX_SRC) M=$(PWD) RP_MODULE_TARGET="test" RP_MODULE_TARGET_VER="7" modules +prod-v7: # kernel running in v6.2+ OS, fully stripped with no debug messages + $(MAKE) -C $(LINUX_SRC) M=$(PWD) RP_MODULE_TARGET="prod" RP_MODULE_TARGET_VER="7" modules + +clean: + $(MAKE) -C $(LINUX_SRC) M=$(PWD) clean diff --git a/PLATFORMS b/PLATFORMS new file mode 100644 index 0000000..5173e00 --- /dev/null +++ b/PLATFORMS @@ -0,0 +1,8 @@ +bromolow 3.10.108 +apollolake 4.4.180 +broadwell 4.4.180 +broadwellnk 4.4.180 +denverton 4.4.180 +geminilake 4.4.180 +v1000 4.4.180 +r1000 4.4.180 diff --git a/common.h b/common.h new file mode 100644 index 0000000..e1eb5e0 --- /dev/null +++ b/common.h @@ -0,0 +1,128 @@ +#ifndef REDPILLLKM_COMMON_H +#define REDPILLLKM_COMMON_H + +/******************************************** Available whole-module flags ********************************************/ +//This (shameful) flag disables shims which cannot be properly unloaded to make debugging of other things easier +//#define DBG_DISABLE_UNLOADABLE + +//disabled uart unswapping even if needed (useful for hand-loading while running) +//#define DBG_DISABLE_UART_SWAP_FIX + +//Whether to cause a kernel panic when module fails to load internally (which should be normally done on production) +#define KP_ON_LOAD_ERROR + +//Print A LOT of vUART debug messages +//#define VUART_DEBUG_LOG + +//Enabled printing of all ioctl() calls (hooked or not) +//#define DBG_SMART_PRINT_ALL_IOCTL + +//Normally GetHwCapability calls (checking what hardware supports) are responded internally. Setting this DBG adds log +// of all requests & responses for hardware capabilities (and there're frquent but not overwhelming). Additionally this +// option turns on additional calls to the original GetHwCapability and logs compared values. Some values are ALWAYS +// proxied to the original GetHwCapability +//#define DBG_HWCAP + +//Debug all hardware monitoring features (shim/bios/bios_hwmon_shim.c) +//#define DBG_HWMON +/**********************************************************************************************************************/ + +#include "internal/stealth.h" +#include +#include +#include +#include +#include //kmalloc +#include +#include "compat/string_compat.h" +#include //bool & others + +/************************************************** Strings handling **************************************************/ +#define get_static_name(variable) #variable +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#define strlen_static(param) (sizeof(param)-1) //gets the size of a string minus trailing nullbyte (useful for partial matches) +#define strlen_to_size(len) (sizeof(char) * ((len)+1)) //useful for static strings, use strsize() for dynamic ones +#define strsize(param) strlen_to_size(strlen(param)) //strlen including NULLbyte; useful for kmalloc-ing +/**********************************************************************************************************************/ + +/****************************************** Dynamic memory allocation helpers *****************************************/ +//[internal] Cleans up & provides standard reporting and return +#define __kalloc_err_report_clean(variable, size, exit) \ + (variable) = NULL; \ + pr_loc_crt("kernel memory alloc failure - tried to allocate %ld bytes for %s", \ + (long)(size), get_static_name(variable)); \ + return exit; + +//Use these if you need to do a manual malloc with some extra checks but want to return a consistant message +#define kalloc_error_int(variable, size) do { __kalloc_err_report_clean(variable, size, -ENOMEM); } while(0) +#define kalloc_error_ptr(variable, size) do { __kalloc_err_report_clean(variable, size, ERR_PTR(-ENOMEM)); } while(0) + +//[internal] Reserves memory & checks result +#define __kalloc_or_exit(type, variable, size, exit_type) \ + (variable) = (type)(size, GFP_KERNEL); \ + if (unlikely(!(variable))) { kalloc_error_ ## exit_type (variable, size); } + +//Use these to do a standard malloc with error reporting +#define kmalloc_or_exit_int(variable, size) do { __kalloc_or_exit(kmalloc, variable, size, int); } while(0) +#define kmalloc_or_exit_ptr(variable, size) do { __kalloc_or_exit(kmalloc, variable, size, ptr); } while(0) +#define kzalloc_or_exit_int(variable, size) do { __kalloc_or_exit(kzalloc, variable, size, int); } while(0) +#define kzalloc_or_exit_ptr(variable, size) do { __kalloc_or_exit(kzalloc, variable, size, ptr); } while(0) +#define try_kfree(variable) do { if(variable) { kfree(variable); } } while(0) +/**********************************************************************************************************************/ + +/****************************************************** Logging *******************************************************/ +#define _pr_loc_crt(fmt, ...) pr_crit( "<%s/%s:%d> " pr_fmt(fmt) "\n", KBUILD_MODNAME, __FILENAME__, __LINE__, ##__VA_ARGS__) +#define _pr_loc_err(fmt, ...) pr_err ( "<%s/%s:%d> " pr_fmt(fmt) "\n", KBUILD_MODNAME, __FILENAME__, __LINE__, ##__VA_ARGS__) +#define _pr_loc_wrn(fmt, ...) pr_warn( "<%s/%s:%d> " pr_fmt(fmt) "\n", KBUILD_MODNAME, __FILENAME__, __LINE__, ##__VA_ARGS__) +#define _pr_loc_inf(fmt, ...) pr_info( "<%s/%s:%d> " pr_fmt(fmt) "\n", KBUILD_MODNAME, __FILENAME__, __LINE__, ##__VA_ARGS__) +#define _pr_loc_dbg(fmt, ...) pr_info( "<%s/%s:%d> " pr_fmt(fmt) "\n", KBUILD_MODNAME, __FILENAME__, __LINE__, ##__VA_ARGS__) +#define _pr_loc_dbg_raw(fmt, ...) printk(fmt, ##__VA_ARGS__) +#define _pr_loc_bug(fmt, ...) \ + do { \ + pr_err("<%s/%s:%d> !!BUG!! " pr_fmt(fmt) "\n", KBUILD_MODNAME, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + WARN(1, "BUG log triggered"); \ + } while(0) + +#if STEALTH_MODE >= STEALTH_MODE_FULL //all logs will be disabled in full +#define pr_loc_crt(fmt, ...) +#define pr_loc_err(fmt, ...) +#define pr_loc_wrn(fmt, ...) +#define pr_loc_inf(fmt, ...) +#define pr_loc_dbg(fmt, ...) +#define pr_loc_dbg_raw(fmt, ...) +#define pr_loc_bug(fmt, ...) +#define DBG_ALLOW_UNUSED(var) ((void)var) //in debug modes some variables are seen as unused (as they're only for dbg) + +#elif STEALTH_MODE >= STEALTH_MODE_NORMAL //in normal mode we only warnings/errors/etc. +#define pr_loc_crt _pr_loc_crt +#define pr_loc_err _pr_loc_err +#define pr_loc_wrn _pr_loc_wrn +#define pr_loc_inf(fmt, ...) +#define pr_loc_dbg(fmt, ...) +#define pr_loc_dbg_raw(fmt, ...) +#define pr_loc_bug _pr_loc_bug +#define DBG_ALLOW_UNUSED(var) ((void)var) //in debug modes some variables are seen as unused (as they're only for dbg) + +#else +#define pr_loc_crt _pr_loc_crt +#define pr_loc_err _pr_loc_err +#define pr_loc_inf _pr_loc_inf +#define pr_loc_wrn _pr_loc_wrn +#define pr_loc_dbg _pr_loc_dbg +#define pr_loc_dbg_raw _pr_loc_dbg_raw +#define pr_loc_bug _pr_loc_bug +#define DBG_ALLOW_UNUSED(var) //when debug logs are enables we don't silence unused variables warnings + +#endif //STEALTH_MODE +/**********************************************************************************************************************/ + +#ifndef RP_MODULE_TARGET_VER +#error "The RP_MODULE_TARGET_VER is not defined - it is required to properly set VTKs" +#endif + +//Before you change that you need to go and check all usages of RP_MODULE_TARGET_VER +#if RP_MODULE_TARGET_VER != 6 && RP_MODULE_TARGET_VER != 7 +#error "The RP_MODULE_TARGET_VER value is invalid" +#endif + +#endif //REDPILLLKM_COMMON_H diff --git a/compat/string_compat.c b/compat/string_compat.c new file mode 100644 index 0000000..c3425e9 --- /dev/null +++ b/compat/string_compat.c @@ -0,0 +1,95 @@ +/* + * linux/lib/string.c + * Modified to take care of kernel versions + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ +#include "string_compat.h" +#include //E2BIG + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,3,0) +#include +#include +#include //PAGE_SIZE + +/** + * strscpy - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. + * The routine returns the number of characters copied (not including + * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. + * The behavior is undefined if the string buffers overlap. + * The destination buffer is always NUL terminated, unless it's zero-sized. + * + * Preferred to strlcpy() since the API doesn't require reading memory + * from the src string beyond the specified "count" bytes, and since + * the return value is easier to error-check than strlcpy()'s. + * In addition, the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation. + * + * Preferred to strncpy() since it always returns a valid string, and + * doesn't unnecessarily force the tail of the destination buffer to be + * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() + * with an overflow test, then just memset() the tail of the dest buffer. + */ +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; + size_t max = count; + long res = 0; + + if (count == 0) + return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* + * If src is unaligned, don't cross a page boundary, + * since we don't know if the next page is mapped. + */ + if ((long)src & (sizeof(long) - 1)) { + size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); + if (limit < max) + max = limit; + } +#else + /* If src or dest is unaligned, don't do word-at-a-time. */ + if (((long) dest | (long) src) & (sizeof(long) - 1)) + max = 0; +#endif + + while (max >= sizeof(unsigned long)) { + unsigned long c, data; + + c = *(unsigned long *)(src+res); + *(unsigned long *)(dest+res) = c; + if (has_zero(c, &data, &constants)) { + data = prep_zero_mask(c, data, &constants); + data = create_zero_mask(data); + return res + find_zero(data); + } + res += sizeof(unsigned long); + count -= sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +#endif //kernel 4.3.0 \ No newline at end of file diff --git a/compat/string_compat.h b/compat/string_compat.h new file mode 100644 index 0000000..ba85bae --- /dev/null +++ b/compat/string_compat.h @@ -0,0 +1,11 @@ +#ifndef REDPILL_STRING_COMPAT_H +#define REDPILL_STRING_COMPAT_H + +#include //KERNEL_VERSION() +#include //ssize_t + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,3,0) +ssize_t __must_check strscpy(char *, const char *, size_t); +#endif + +#endif //REDPILL_STRING_COMPAT_H diff --git a/compat/toolkit/drivers/usb/storage/usb.h b/compat/toolkit/drivers/usb/storage/usb.h new file mode 100644 index 0000000..a55108e --- /dev/null +++ b/compat/toolkit/drivers/usb/storage/usb.h @@ -0,0 +1,135 @@ +/** + * Cherry-picked USB.h internal structures from Linux v4.4.x. If possible avoid using anything from this file like fire. + * + * ORIGINAL FILE HEADER PRESERVED BELOW + * ------------------------------------ + * Driver for USB Mass Storage compliant devices + * Main Header File + * + * Current development and maintenance by: + * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI and ATAPI commands in + * mind when they created this document. The commands are all very + * similar to commands in the SCSI-II and ATAPI specifications. + * + * It is important to note that in a number of cases this class + * exhibits class-specific exemptions from the USB specification. + * Notably the usage of NAK, STALL and ACK differs from the norm, in + * that they are used to communicate wait, failed and OK on commands. + * + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef REDPILL_USB_H +#define REDPILL_USB_H + +#warning "Using compatibility file for drivers/usb/storage/usb.h - if possible do NOT compile using toolkit" + +//This structure didn't change substantially since v2.6 days; 5.14 is simply the newest one we checked - it will +// probably remain unchanged for years to come +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) && LINUX_VERSION_CODE < KERNEL_VERSION(5,14,0) //v3.3 - v5.14 +#include //struct usb_sg_request + +struct us_data; +typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); +typedef int (*trans_reset)(struct us_data*); +typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*); +typedef void (*extra_data_destructor)(void *); /* extra data destructor */ +typedef void (*pm_hook)(struct us_data *, int); /* power management hook */ + +struct us_data { + /* The device we're working with + * It's important to note: + * (o) you must hold dev_mutex to change pusb_dev + */ + struct mutex dev_mutex; /* protect pusb_dev */ + struct usb_device *pusb_dev; /* this usb_device */ + struct usb_interface *pusb_intf; /* this interface */ + struct us_unusual_dev *unusual_dev; /* device-filter entry */ + unsigned long fflags; /* fixed flags from filter */ + unsigned long dflags; /* dynamic atomic bitflags */ + unsigned int send_bulk_pipe; /* cached pipe values */ + unsigned int recv_bulk_pipe; + unsigned int send_ctrl_pipe; + unsigned int recv_ctrl_pipe; + unsigned int recv_intr_pipe; + + /* information about the device */ + char *transport_name; + char *protocol_name; + __le32 bcs_signature; + u8 subclass; + u8 protocol; + u8 max_lun; + + u8 ifnum; /* interface number */ + u8 ep_bInterval; /* interrupt interval */ + + /* function pointers for this device */ + trans_cmnd transport; /* transport function */ + trans_reset transport_reset; /* transport device reset */ + proto_cmnd proto_handler; /* protocol handler */ + + /* SCSI interfaces */ + struct scsi_cmnd *srb; /* current srb */ + unsigned int tag; /* current dCBWTag */ + char scsi_name[32]; /* scsi_host name */ + + /* control and bulk communications data */ + struct urb *current_urb; /* USB requests */ + struct usb_ctrlrequest *cr; /* control requests */ + struct usb_sg_request current_sg; /* scatter-gather req. */ + unsigned char *iobuf; /* I/O buffer */ + dma_addr_t iobuf_dma; /* buffer DMA addresses */ + struct task_struct *ctl_thread; /* the control thread */ + + /* mutual exclusion and synchronization structures */ + struct completion cmnd_ready; /* to sleep thread on */ + struct completion notify; /* thread begin/end */ + wait_queue_head_t delay_wait; /* wait during reset */ + struct delayed_work scan_dwork; /* for async scanning */ + + /* subdriver information */ + void *extra; /* Any extra data */ + extra_data_destructor extra_destructor;/* extra data destructor */ +#ifdef CONFIG_PM + pm_hook suspend_resume_hook; +#endif + + /* hacks for READ CAPACITY bug handling */ + int use_last_sector_hacks; + int last_sector_retries; +}; +#endif //LINUX_VERSION_CODE check + + +struct Scsi_Host; +static inline struct us_data *host_to_us(struct Scsi_Host *host) { + return (struct us_data *) host->hostdata; +} + +#endif //REDPILL_USB_H \ No newline at end of file diff --git a/compat/toolkit/fs/proc/internal.h b/compat/toolkit/fs/proc/internal.h new file mode 100644 index 0000000..2ed324f --- /dev/null +++ b/compat/toolkit/fs/proc/internal.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Internal procfs definitions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This file contains curated definitions from original fs/proc/internal.h file which we (unfortunately) need to access. + * As the internal.h, as the name implies, is meant for in-tree use only official toolkits lack it. + * Kernel version constrains here are taken from the real kernel source tree to prevent including wrong structs + * definitions. Please keep it neat as mismatch will cause very hard to debug problems. + */ + +#warning "Using compatibility file for fs/proc/internal.h - if possible do NOT compile using toolkit" + +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) && LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) //v3.10 - v3.18 +struct proc_dir_entry { + unsigned int low_ino; + umode_t mode; + nlink_t nlink; + kuid_t uid; + kgid_t gid; + loff_t size; + const struct inode_operations *proc_iops; + const struct file_operations *proc_fops; + struct proc_dir_entry *next, *parent, *subdir; + void *data; + atomic_t count; /* use count */ + atomic_t in_use; /* number of callers into module in progress; */ + /* negative -> it's going away RSN */ + struct completion *pde_unload_completion; + struct list_head pde_openers; /* who did ->open, but not ->release */ + spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ + u8 namelen; + char name[]; +}; + +union proc_op { + int (*proc_get_link)(struct dentry *, struct path *); + int (*proc_read)(struct task_struct *task, char *page); + int (*proc_show)(struct seq_file *m, + struct pid_namespace *ns, struct pid *pid, + struct task_struct *task); +}; + +struct proc_inode { + struct pid *pid; + int fd; + union proc_op op; + struct proc_dir_entry *pde; + struct ctl_table_header *sysctl; + struct ctl_table *sysctl_entry; + struct proc_ns ns; + struct inode vfs_inode; +}; + +//See https://github.com/torvalds/linux/commit/771187d61bb3cbaf62c492ec3b8b789933f7691e +//v3.19 - it's going away RSN */ + struct completion *pde_unload_completion; + struct list_head pde_openers; /* who did ->open, but not ->release */ + spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ + u8 namelen; + char name[]; +}; + +union proc_op { + int (*proc_get_link)(struct dentry *, struct path *); + int (*proc_show)(struct seq_file *m, + struct pid_namespace *ns, struct pid *pid, + struct task_struct *task); +}; + +struct proc_inode { + struct pid *pid; + int fd; + union proc_op op; + struct proc_dir_entry *pde; + struct ctl_table_header *sysctl; + struct ctl_table *sysctl_entry; + const struct proc_ns_operations *ns_ops; + struct inode vfs_inode; +}; +#endif + +//These methods are the same forever +static inline struct proc_inode *PROC_I(const struct inode *inode) +{ + return container_of(inode, struct proc_inode, vfs_inode); +} + +static inline struct proc_dir_entry *PDE(const struct inode *inode) +{ + return PROC_I(inode)->pde; +} \ No newline at end of file diff --git a/compat/toolkit/include/.gitkeep b/compat/toolkit/include/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/compile-lkms.sh b/compile-lkms.sh new file mode 100644 index 0000000..3675160 --- /dev/null +++ b/compile-lkms.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -e + +TMP_PATH="/tmp" +DEST_PATH="output" +TOOLKIT_VER="7.1" + +mkdir -p "${DEST_PATH}" + +if [ -f ../arpl/PLATFORMS ]; then + cp ../arpl/PLATFORMS PLATFORMS +else + curl -sLO "https://github.com/fbelavenuto/arpl/raw/main/PLATFORMS" +fi + +function compileLkm() { + PLATFORM=$1 + KVER=$2 + OUT_PATH="${TMP_PATH}/${PLATFORM}" + mkdir -p "${OUT_PATH}" + # Compile using docker + docker run --rm -t -v "${OUT_PATH}":/output -v "${PWD}":/input \ + fbelavenuto/syno-toolkit:${PLATFORM}-${TOOLKIT_VER} compile-lkm + mv "${OUT_PATH}/redpill-dev.ko" "${DEST_PATH}/rp-${PLATFORM}-${KVER}-dev.ko" + rm -f "${DEST_PATH}/rp-${PLATFORM}-${KVER}-dev.ko.gz" + gzip "${DEST_PATH}/rp-${PLATFORM}-${KVER}-dev.ko" + mv "${OUT_PATH}/redpill-prod.ko" "${DEST_PATH}/rp-${PLATFORM}-${KVER}-prod.ko" + rm -f "${DEST_PATH}/rp-${PLATFORM}-${KVER}-prod.ko.gz" + gzip "${DEST_PATH}/rp-${PLATFORM}-${KVER}-prod.ko" + rm -rf "${OUT_PATH}" +} + +# Main +while read PLATFORM KVER; do + docker pull fbelavenuto/syno-toolkit:${PLATFORM}-${TOOLKIT_VER} + compileLkm "${PLATFORM}" "${KVER}" & +done < PLATFORMS +wait \ No newline at end of file diff --git a/config/.platforms.h.swp b/config/.platforms.h.swp new file mode 100644 index 0000000000000000000000000000000000000000..e615aa235abbe1c74dd24cd5ee685c2ec5746b80 GIT binary patch literal 16384 zcmeI2UyKt)9LGmM#6O_H7=7?zyc7Sx(SHYcXcT(w!Zr4v-S$8QCVTDfb#v{u*`4J$ zk(h|QXiR({!9yv&rY$ zo8Qj-X1+VW>HOKT&}bq>hXNsj>mEWL`TXtTx>YO4M>`3rXk&KGbsS-u>vGC9Zd$yo zmo$4~jvIqjiwDc&h7*j}Cap?MD>*@1FV)RTWpibs8Z6ccQ3k%OL@01Ei1*8H}0jYpgKq?>=kP1izmc0VJ zzM8y(R;=(^lJ-7t@qPa7U3|5Y z-A%|bFa=yN3Z4MlzysjwIzqk!=fH>HIM@I_TT94p@bg`SnBdBtguDSB1Rvi)$PV!R z?SvG;ps6C4FEgM(lnP{5D3qCVgh zI0|&I8$1kFgWp#XasiwM6%YbHVRPXOr~w@u0DHkR;8AcDnzGtt+1Su%H)->ufV1)nTbV{T`kRA5!mRFw!=VqvRbo*o9Q|P zOox>?lDO^aop)*uE7o1c^=f^#)i4jSlIcvaie6$xZi}k>3b1w4GCAXXN)64nI+I$R zIl65&T5V_*r_;G!b@3{R&TL*pR-d(_JwnLCG{C3o;sG%>nvJu(l1nAh(R?Py7(LQ% zXT4}Lhr44A?(As3rBy}VzPP$QGPtR)sX)`-;iz4XaM^ffMc1}DSFJj3~a6CR0lUP-c8w!qZXa6xTE2MtVzhlq$) zc!Z64!b8-sGdgAm#SPkXwJsY=C@ecHTG+$gmZf(W zox|PWQo4&mNEXZIk|?x$7>Lfes9(TdVkRPC1nubUiK&E}Y(PQO_G;(jqvCH&mST-5W@59txO6r|w8*$Kg{aeHS5|-IfUryZ;ii8h2?F|SqMt7XkEQ?>Oe*k`QnyCN) literal 0 HcmV?d00001 diff --git a/config/cmdline_delegate.c b/config/cmdline_delegate.c new file mode 100644 index 0000000..755f771 --- /dev/null +++ b/config/cmdline_delegate.c @@ -0,0 +1,455 @@ +#include "cmdline_delegate.h" +#include "../common.h" //commonly used headers in this module +#include "../internal/call_protected.h" //used to call cmdline_proc_show() +#include //struct seq_file + +#define ensure_cmdline_param(cmdline_param) \ + if (strncmp(param_pointer, cmdline_param, strlen_static(cmdline_param)) != 0) { return false; } + +#define ensure_cmdline_token(cmdline_param) \ + if (strncmp(param_pointer, cmdline_param, sizeof(cmdline_param)) != 0) { return false; } + +/** + * Extracts device model (syno_hw_version=) from kernel cmd line + * + * @param model pointer to save model to + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_hw(syno_hw *model, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_KT_HW); + + if (strscpy((char *)model, param_pointer + strlen_static(CMDLINE_KT_HW), sizeof(syno_hw)) < 0) + pr_loc_wrn("HW version truncated to %zu", sizeof(syno_hw)-1); + + pr_loc_dbg("HW version set to: %s", (char *)model); + + return true; +} + +/** + * Extracts serial number (sn=) from kernel cmd line + * + * @param sn pointer to save s/n to + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_sn(serial_no *sn, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_KT_SN); + + if(strscpy((char *)sn, param_pointer + strlen_static(CMDLINE_KT_SN), sizeof(serial_no)) < 0) + pr_loc_wrn("S/N truncated to %zu", sizeof(serial_no)-1); + + pr_loc_dbg("S/N set to: %s", (char *)sn); + + return true; +} + +static bool extract_boot_media_type(struct boot_media *boot_media, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_KT_SATADOM); + + char value = param_pointer[strlen_static(CMDLINE_KT_SATADOM)]; + + switch (value) { + case CMDLINE_KT_SATADOM_NATIVE: + boot_media->type = BOOT_MEDIA_SATA_DOM; + pr_loc_dbg("Boot media SATADOM (native) requested"); + break; + + case CMDLINE_KT_SATADOM_FAKE: + boot_media->type = BOOT_MEDIA_SATA_DISK; + pr_loc_dbg("Boot media SATADISK (fake) requested"); + break; + + case CMDLINE_KT_SATADOM_DISABLED: + //There's no point to set that option but it's not an error + pr_loc_wrn("SATA-based boot media disabled (default will be used, %s0 is a noop)", CMDLINE_KT_SATADOM); + break; + + default: + pr_loc_err("Option \"%s%c\" is invalid (value should be 0/1/2)", CMDLINE_KT_SATADOM, value); + } + + return true; +} + +/** + * Extracts VID override (vid=) from kernel cmd line + * + * @param user_vid pointer to save VID + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_vid(device_id *user_vid, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_CT_VID); + + long long numeric_param; + int tmp_call_res = kstrtoll(param_pointer + strlen_static(CMDLINE_CT_VID), 0, &numeric_param); + if (unlikely(tmp_call_res != 0)) { + pr_loc_err("Call to %s() failed => %d", "kstrtoll", tmp_call_res); + return true; + } + + if (unlikely(numeric_param > VID_PID_MAX)) { + pr_loc_err("Cmdline %s is invalid (value larger than %d)", CMDLINE_CT_VID, VID_PID_MAX); + return true; + } + + if (unlikely(*user_vid) != 0) + pr_loc_wrn( + "VID was already set to 0x%04x by a previous instance of %s - it will be changed now to 0x%04x", + *user_vid, CMDLINE_CT_VID, (unsigned int)numeric_param); + + *user_vid = (unsigned int)numeric_param; + pr_loc_dbg("VID override: 0x%04x", *user_vid); + + return true; +} + +/** + * Extracts PID override (pid=) from kernel cmd line + * + * @param user_pid pointer to save PID + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_pid(device_id *user_pid, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_CT_PID); + + long long numeric_param; + int tmp_call_res = kstrtoll(param_pointer + strlen_static(CMDLINE_CT_PID), 0, &numeric_param); + if (unlikely(tmp_call_res != 0)) { + pr_loc_err("Call to %s() failed => %d", "kstrtoll", tmp_call_res); + return true; + } + + if (unlikely(numeric_param > VID_PID_MAX)) { + pr_loc_err("Cmdline %s is invalid (value larger than %d)", CMDLINE_CT_PID, VID_PID_MAX); + return true; + } + + if (unlikely(*user_pid) != 0) + pr_loc_wrn( + "PID was already set to 0x%04x by a previous instance of %s - it will be changed now to 0x%04x", + *user_pid, CMDLINE_CT_PID, (unsigned int)numeric_param); + + *user_pid = (unsigned int)numeric_param; + pr_loc_dbg("PID override: 0x%04x", *user_pid); + + return true; +} + +/** + * Extracts MFG mode enable switch (mfg) from kernel cmd line + * + * @param is_mfg_boot pointer to flag + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_mfg(bool *is_mfg_boot, const char *param_pointer) +{ + ensure_cmdline_token(CMDLINE_CT_MFG); + + *is_mfg_boot = true; + pr_loc_dbg("MFG boot requested"); + + return true; +} + +/** + * Extracts maximum size of SATA DOM (dom_szmax=) from kernel cmd line + */ +static bool extract_dom_max_size(struct boot_media *boot_media, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_CT_DOM_SZMAX); + + long size_mib = simple_strtol(param_pointer + strlen_static(CMDLINE_CT_DOM_SZMAX), NULL, 10); + if (size_mib <= 0) { + pr_loc_err("Invalid maximum size of SATA DoM (\"%s=%ld\")", CMDLINE_CT_DOM_SZMAX, size_mib); + return true; + } + + boot_media->dom_size_mib = size_mib; + pr_loc_dbg("Set maximum SATA DoM to %ld", size_mib); + + return true; +} + +/** + * Extracts MFG mode enable switch (syno_port_thaw=<1|0>) from kernel cmd line + * + * @param port_thaw pointer to flag + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_port_thaw(bool *port_thaw, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_KT_THAW); + + short value = param_pointer[strlen_static(CMDLINE_KT_THAW)]; + + if (value == '0') { + *port_thaw = false; + goto out_found; + } + if (value == '1') { + *port_thaw = true; + goto out_found; + } + + if (value == '\0') { + pr_loc_err("Option \"%s%d\" is invalid (value should be 0 or 1)", CMDLINE_KT_THAW, value); + return true; + } + + out_found: + pr_loc_dbg("Port thaw set to: %d", port_thaw?1:0); + return true; +} + +/** + * Extracts number of expected network interfaces (netif_num=) from kernel cmd line + * + * @param netif_num pointer to save number + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_netif_num(unsigned short *netif_num, const char *param_pointer) +{ + ensure_cmdline_param(CMDLINE_KT_NETIF_NUM); + + short value = *(param_pointer + strlen_static(CMDLINE_KT_NETIF_NUM)) - 48; //ASCII: 0=48 and 9=57 + + if (value == 0) { + pr_loc_wrn("You specified no network interfaces (\"%s=0\")", CMDLINE_KT_NETIF_NUM); + return true; + } + + if (value < 1 || value > 9) { + pr_loc_err("Invalid number of network interfaces set (\"%s%d\")", CMDLINE_KT_NETIF_NUM, value); + return true; + } + + *netif_num = value; + pr_loc_dbg("Declared network ifaces # as %d", value); + + return true; +} + +/** + * Extracts network interfaces MAC addresses (mac1...mac4= **OR** macs=) + * + * Note: mixing two notations may lead to undefined behaviors + * + * @param macs pointer to save macs + * @param param_pointer currently processed token + * @return true on match, false if param didn't match + */ +static bool extract_netif_macs(mac_address *macs[MAX_NET_IFACES], const char *param_pointer) +{ + if (strncmp(param_pointer, CMDLINE_KT_MACS, strlen_static(CMDLINE_KT_MACS)) == 0) { + unsigned short i = 0; + const char *pBegin = param_pointer + strlen_static(CMDLINE_KT_MACS); + char *pEnd = strchr(pBegin, ','); + + while (NULL != pEnd && MAX_NET_IFACES > i) { + *pEnd = '\0'; + macs[i] = kmalloc(sizeof(mac_address), GFP_KERNEL); + if (unlikely(!macs[i])) { + pr_loc_crt("kernel memory alloc failure - tried to allocate %lu bytes for macs[%d]", sizeof(mac_address), + i); + goto out_found; + } + if(strscpy((char *)macs[i], pBegin, sizeof(mac_address)) < 0) + pr_loc_wrn("MAC #%d truncated to %zu", i+1, sizeof(mac_address)-1); + pr_loc_dbg("Set MAC #%d: %s", i+1, (char *)macs[i]); + pBegin = pEnd + 1; + pEnd = strchr(pBegin, ','); + i++; + } + + if ('\0' != *pBegin && MAX_NET_IFACES > i) { + macs[i] = kmalloc(sizeof(mac_address), GFP_KERNEL); + if (unlikely(!macs[i])) { + pr_loc_crt("kernel memory alloc failure - tried to allocate %lu bytes for macs[%d]", sizeof(mac_address), + i); + goto out_found; + } + if(strscpy((char *)macs[i], pBegin, sizeof(mac_address)) < 0) + pr_loc_wrn("MAC #%d truncated to %zu", i+1, sizeof(mac_address)-1); + pr_loc_dbg("Set MAC #%d: %s", i+1, (char *)macs[i]); + } + + goto out_found; + } + + //mac1=...mac4= are valid options. ASCII for 1 is 49, ASCII for 4 is 52 + if (strncmp(param_pointer, "mac", 3) != 0 || *(param_pointer + 4) != '=' || *(param_pointer + 3) < 49 || + *(param_pointer + 3) > 52) + return false; + + //Find free spot + unsigned short i = 0; + for (; i < MAX_NET_IFACES; i++) { + if (macs[i]) + continue; + + macs[i] = kmalloc(sizeof(mac_address), GFP_KERNEL); + if (unlikely(!macs[i])) { + pr_loc_crt("kernel memory alloc failure - tried to allocate %lu bytes for macs[%d]", sizeof(mac_address), + i); + goto out_found; + } + + if(strscpy((char *)macs[i], param_pointer + strlen_static(CMDLINE_KT_MAC1), sizeof(mac_address)) < 0) + pr_loc_wrn("MAC #%d truncated to %zu", i+1, sizeof(mac_address)-1); + + pr_loc_dbg("Set MAC #%d: %s", i+1, (char *)macs[i]); + goto out_found; + } + + pr_loc_err("You set more than MAC addresses! Only first %d will be honored.", MAX_NET_IFACES); + + out_found: + return true; +} + +static bool report_unrecognized_option(const char *param_pointer) +{ + pr_loc_dbg("Option \"%s\" not recognized - ignoring", param_pointer); + + return true; +} + +/************************************************* End of extractors **************************************************/ + +static char cmdline_cache[CMDLINE_MAX] = { '\0' }; +/** + * Extracts the cmdline from kernel and caches it for later use + * + * The method we use here may seem weird but it is, believe or not, the most direct one available. Kernel cmdline + * internally is stored in a "saved_command_line" variable (and few derivatives) which isn't exported for modules in + * any way (at least on x86). The only semi-direct way to get it is to call the method responsible for /proc/cmdline) + */ +static int extract_kernel_cmdline(void) +{ + struct seq_file cmdline_itr = { + .buf = cmdline_cache, + .size = CMDLINE_MAX + }; + + int out = _cmdline_proc_show(&cmdline_itr, 0); + if (out != 0) + return out; + + pr_loc_dbg("Cmdline count: %d", (unsigned int)cmdline_itr.count); + if (unlikely(cmdline_itr.count == CMDLINE_MAX)) //if the kernel line is >1K + pr_loc_wrn("Cmdline may have been truncated to %d", CMDLINE_MAX); + + return 0; +} + +/** + * Returns kernel cmdline up to the length specified by maxlen + * + * @param cmdline_out + * @param maxlen + * @return 0 on success, -E2BIG if buffer was too small (but the operation succeeded up to maxlen), -E for error + */ +long get_kernel_cmdline(char *cmdline_out, size_t maxlen) +{ + if (unlikely(cmdline_cache[0] == '\0')) { + int out = extract_kernel_cmdline(); + if (out != 0) { + pr_loc_err("Failed to extract kernel cmdline"); + return out; + } + } + + if (unlikely(maxlen > CMDLINE_MAX)) + maxlen = CMDLINE_MAX; + + return strscpy(cmdline_out, cmdline_cache, maxlen); +} + +#define ADD_BLACKLIST_ENTRY(idx, token) kmalloc_or_exit_int(cmdline_blacklist[idx], sizeof(token)); \ + strcpy((char *)cmdline_blacklist[idx], token); \ + pr_loc_dbg("Add cmdline blacklist \"%s\" @ %d", \ + (char *)cmdline_blacklist[idx], idx); +int populate_cmdline_blacklist(cmdline_token *cmdline_blacklist[MAX_BLACKLISTED_CMDLINE_TOKENS], syno_hw *model) +{ + //Currently, this list is static. However, it's prepared to be dynamic based on the model + //Make sure you don't go over MAX_BLACKLISTED_CMDLINE_TOKENS (and if so adjust it) + ADD_BLACKLIST_ENTRY(0, CMDLINE_CT_VID); + ADD_BLACKLIST_ENTRY(1, CMDLINE_CT_PID); + ADD_BLACKLIST_ENTRY(2, CMDLINE_CT_MFG); + ADD_BLACKLIST_ENTRY(3, CMDLINE_CT_DOM_SZMAX); + ADD_BLACKLIST_ENTRY(4, CMDLINE_KT_ELEVATOR); + ADD_BLACKLIST_ENTRY(5, CMDLINE_KT_LOGLEVEL); + ADD_BLACKLIST_ENTRY(6, CMDLINE_KT_PK_BUFFER); + ADD_BLACKLIST_ENTRY(7, CMDLINE_KT_EARLY_PK); + ADD_BLACKLIST_ENTRY(8, CMDLINE_KT_THAW); + +#ifndef NATIVE_SATA_DOM_SUPPORTED //on kernels without SATA DOM support we shouldn't reveal that it's a SATA DOM-boot + ADD_BLACKLIST_ENTRY(9, CMDLINE_KT_SATADOM); +#endif + + return 0; +} + +int extract_config_from_cmdline(struct runtime_config *config) +{ + int out = 0; + char *cmdline_txt; + kzalloc_or_exit_int(cmdline_txt, strlen_to_size(CMDLINE_MAX)); + + if(get_kernel_cmdline(cmdline_txt, CMDLINE_MAX) <= 0) { + pr_loc_crt("Failed to extract cmdline"); + out = -EIO; + goto exit_free; + } + + pr_loc_dbg("Cmdline: %s", cmdline_txt); + + /** + * Temporary variables + */ + unsigned int param_counter = 0; + char *single_param_chunk; //Pointer to the beginning of the cmdline token + DBG_ALLOW_UNUSED(param_counter); + + while ((single_param_chunk = strsep(&cmdline_txt, CMDLINE_SEP)) != NULL ) { + if (unlikely(single_param_chunk[0] == '\0')) //Skip empty params (e.g. last one) + continue; + pr_loc_dbg("Param #%d: |%s|", param_counter++, single_param_chunk); + + //Stop after the first one matches + extract_hw(&config->hw, single_param_chunk) || + extract_sn(&config->sn, single_param_chunk) || + extract_boot_media_type(&config->boot_media, single_param_chunk) || + extract_vid(&config->boot_media.vid, single_param_chunk) || + extract_pid(&config->boot_media.pid, single_param_chunk) || + extract_dom_max_size(&config->boot_media, single_param_chunk) || + extract_mfg(&config->boot_media.mfg_mode, single_param_chunk) || + extract_port_thaw(&config->port_thaw, single_param_chunk) || + extract_netif_num(&config->netif_num, single_param_chunk) || + extract_netif_macs(config->macs, single_param_chunk) || + report_unrecognized_option(single_param_chunk) ; + } + + if (populate_cmdline_blacklist(config->cmdline_blacklist, &config->hw) != 0) { + out = -EIO; + goto exit_free; + } + + pr_loc_inf("CmdLine processed successfully, tokens=%d", param_counter); + + exit_free: + kfree(cmdline_txt); + return out; +} diff --git a/config/cmdline_delegate.h b/config/cmdline_delegate.h new file mode 100644 index 0000000..42d5510 --- /dev/null +++ b/config/cmdline_delegate.h @@ -0,0 +1,31 @@ +#ifndef REDPILLLKM_CMDLINE_DELEGATE_H +#define REDPILLLKM_CMDLINE_DELEGATE_H + +#include "runtime_config.h" +#include "cmdline_opts.h" + +/** + * Provides an easy access to kernel cmdline + * + * Internally in the kernel code it is available as "saved_command_line". However that variable is not accessible for + * modules. This function populates a char buffer with the cmdline extracted using other methods. + * + * WARNING: if something (e.g. sanitize cmdline) overrides the cmdline this method will return the overridden one! + * However, this method caches the cmdline, so if you call it once it will cache the original one internally. + * + * @param cmdline_out A pointer to your buffer to save the cmdline + * @param maxlen Your buffer space (in general you should use CMDLINE_MAX) + * @return cmdline length on success or -E on error + */ +long get_kernel_cmdline(char *cmdline_out, unsigned long maxlen); + +/** + * Extracts & processes parameters from kernel cmdline + * + * Note: it's not guaranteed that the config will be valid. Check runtime_config.h. + * + * @param config pointer to save configuration + */ +int extract_config_from_cmdline(struct runtime_config *config); + +#endif //REDPILLLKM_CMDLINE_DELEGATE_H diff --git a/config/cmdline_opts.h b/config/cmdline_opts.h new file mode 100644 index 0000000..77e5683 --- /dev/null +++ b/config/cmdline_opts.h @@ -0,0 +1,44 @@ +#ifndef REDPILL_CMDLINE_OPTS_H +#define REDPILL_CMDLINE_OPTS_H + +#define CMDLINE_MAX 1024 //Max length of cmdline expected/processed; if longer a warning will be emitted +#define CMDLINE_SEP "\t\n " + +/** + * Kernel command line tokens. For clarity keep them separated. + * CT = custom token + * KT = kernel token (default or syno) + * + * All should be defined in the .h to allow accessing outside for hints in errors. + */ +#define CMDLINE_CT_VID "vid=" //Boot media Vendor ID override +#define CMDLINE_CT_PID "pid=" //Boot media Product ID override +#define CMDLINE_CT_MFG "mfg" //VID & PID override will use force-reinstall VID/PID combo +#define CMDLINE_CT_DOM_SZMAX "dom_szmax=" //Max size of SATA device (MiB) to be considered a DOM (usually you should NOT use this) + +//Standard Linux cmdline tokens +#define CMDLINE_KT_ELEVATOR "elevator=" //Sets I/O scheduler (we use it to load RP LKM earlier than normally possible) +#define CMDLINE_KT_LOGLEVEL "loglevel=" +#define CMDLINE_KT_PK_BUFFER "log_buf_len=" //Length of the printk ring buffer (should usually be increased for debug) +#define CMDLINE_KT_EARLY_PK "earlyprintk" + +//Syno-specific cmdline tokens +#define CMDLINE_KT_HW "syno_hw_version=" +#define CMDLINE_KT_THAW "syno_port_thaw=" //?? + +//0|1 - whether to use native SATA Disk-on-Module for boot drive (syno); 2 - use fake/emulated SATA DOM (rp) +#define CMDLINE_KT_SATADOM "synoboot_satadom=" +# define CMDLINE_KT_SATADOM_DISABLED '0' +# define CMDLINE_KT_SATADOM_NATIVE '1' +# define CMDLINE_KT_SATADOM_FAKE '2' + +#define CMDLINE_KT_SN "sn=" +#define CMDLINE_KT_NETIF_NUM "netif_num=" +#define CMDLINE_KT_MACS "macs=" +//You CANNOT simply add more macN= - DSM kernel only uses 4. If they ever support >4 you need to modify cmdline handling +#define CMDLINE_KT_MAC1 "mac1=" +#define CMDLINE_KT_MAC2 "mac2=" +#define CMDLINE_KT_MAC3 "mac3=" +#define CMDLINE_KT_MAC4 "mac4=" + +#endif //REDPILL_CMDLINE_OPTS_H diff --git a/config/platform_types.h b/config/platform_types.h new file mode 100644 index 0000000..da15f6e --- /dev/null +++ b/config/platform_types.h @@ -0,0 +1,126 @@ +#ifndef REDPILL_PLATFORM_TYPES_H +#define REDPILL_PLATFORM_TYPES_H + +#include "vpci_types.h" //vpci_device_stub, MAX_VPCI_DEVS + +#ifndef RP_MODULE_TARGET_VER +#error "The RP_MODULE_TARGET_VER is not defined - it is required to properly set VTKs" +#endif + +//All HWMON_SYS enums defined here are for internal RP use only. Normally these have long names but duplicating names +// across multiple platforms is wasteful (and causes platforms.h compilation unit to grow) +//While adding new constants here MAKE SURE TO NOT CONFLICT with existing ones defining names in synobios.h (here we +// postfixed everything with _ID) +enum hwmon_sys_thermal_zone_id { + //i.e. "non-existent zone" so that we don't need another flag/number to indicated # of supported zones + HWMON_SYS_TZONE_NULL_ID = 0, + HWMON_SYS_TZONE_REMOTE1_ID, + HWMON_SYS_TZONE_REMOTE2_ID, + HWMON_SYS_TZONE_LOCAL_ID, + HWMON_SYS_TZONE_SYSTEM_ID, + HWMON_SYS_TZONE_ADT1_LOC_ID, + HWMON_SYS_TZONE_ADT2_LOC_ID, +}; +#define HWMON_SYS_THERMAL_ZONE_IDS 5 //number of thermal zones minus the fake NULL_ID + +enum hwmon_sys_voltage_sensor_id { + //i.e. "non-existent sensor type" so that we don't need another flag/number to indicated # of supported ones + HWMON_SYS_VSENS_NULL_ID = 0, + HWMON_SYS_VSENS_VCC_ID, + HWMON_SYS_VSENS_VPP_ID, + HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, + HWMON_SYS_VSENS_V12_ID, + HWMON_SYS_VSENS_ADT1_V33_ID, + HWMON_SYS_VSENS_ADT2_V33_ID, +}; +#define HWMON_SYS_VOLTAGE_SENSOR_IDS 7 //number of voltage sensors minus the fake NULL_ID + +enum hwmon_sys_fan_rpm_id { + //i.e. "non-existent fan" so that we don't need another flag/number to indicated # of supported fans + HWMON_SYS_FAN_NULL_ID = 0, + HWMON_SYS_FAN1_ID, + HWMON_SYS_FAN2_ID, + HWMON_SYS_FAN3_ID, + HWMON_SYS_FAN4_ID, +}; +#define HWMON_SYS_FAN_RPM_IDS 4 + +enum hwmon_sys_hdd_bp_id { + //i.e. "non-existent backplane sensor" so that we don't need another flag/number to indicated # of supported ones + HWMON_SYS_HDD_BP_NULL_ID = 0, + HWMON_SYS_HDD_BP_DETECT_ID, + HWMON_SYS_HDD_BP_ENABLE_ID, +}; +#define HWMON_SYS_HDD_BP_IDS 2 //number of HDD backplane sensors minus the fake NULL_ID + +enum hw_psu_sensor_id { + //i.e. "non-existent PSU sensor" so that we don't need another flag/number to indicated # of supported ones + HWMON_PSU_NULL_ID = 0, + HWMON_PSU_PWR_IN_ID, + HWMON_PSU_PWR_OUT_ID, +#if RP_MODULE_TARGET_VER == 6 + HWMON_PSU_TEMP_ID, +#elif RP_MODULE_TARGET_VER == 7 + HWMON_PSU_TEMP1_ID, + HWMON_PSU_TEMP2_ID, + HWMON_PSU_TEMP3_ID, + HWMON_PSU_FAN_VOLT, +#endif + HWMON_PSU_FAN_RPM_ID, + HWMON_PSU_STATUS_ID, +}; +#if RP_MODULE_TARGET_VER == 6 +#define HWMON_PSU_SENSOR_IDS 2 //number of power supply sensors minus the fake NULL_ID +#elif RP_MODULE_TARGET_VER == 7 +#define HWMON_PSU_SENSOR_IDS 8 //number of power supply sensors minus the fake NULL_ID +#else +#error "Unknown RP_MODULE_TARGET_VER version specified" +#endif + +enum hwmon_sys_current_id { + //i.e. "non-existent current sensor" so that we don't need another flag/number to indicated # of supported ones + HWMON_SYS_CURR_NULL_ID = 0, + HWMON_SYS_CURR_ADC_ID, +}; +#define HWMON_SYS_CURRENT_IDS 1 //number of current sensors minus the fake NULL_ID + +struct hw_config { + const char *name; //the longest so far is "RR36015xs+++" (12+1) + + const struct vpci_device_stub pci_stubs[MAX_VPCI_DEVS]; + + //All custom flags + const bool emulate_rtc:1; + const bool swap_serial:1; //Whether ttyS0 and ttyS1 are swapped (reverses CONFIG_SYNO_X86_SERIAL_PORT_SWAP) + const bool reinit_ttyS0:1; //Should the ttyS0 be forcefully re-initialized after module loads + const bool fix_disk_led_ctrl:1; //Disabled libata-scsi bespoke disk led control (which often crashes some v4 platforms) + + //See SYNO_HWMON_SUPPORT_ID in include/linux/synobios.h GPLed sources - it defines which ones are possible + //These define which parts of ACPI HWMON should be emulated + //For those with GetHwCapability() note enable DBG_HWCAP which will force bios_hwcap_shim to print original values. + // Unless there's a good reason to diverge from the platform-defined values you should not. + //Supported hwmon sensors; order of sensors within type IS IMPORTANT to be accurate with a real hardware. The number + // of sensors is derived from the enums defining their types. Internally the absolute maximum number is determined + // by MAX_SENSOR_NUM defined in include/linux/synobios.h + const bool has_cpu_temp:1; //GetHwCapability(id = CAPABILITY_CPU_TEMP) + // Device-tree models + const bool is_dt:1; + const struct hw_config_hwmon { + enum hwmon_sys_thermal_zone_id sys_thermal[HWMON_SYS_THERMAL_ZONE_IDS]; //GetHwCapability(id = CAPABILITY_THERMAL) + enum hwmon_sys_voltage_sensor_id sys_voltage[HWMON_SYS_VOLTAGE_SENSOR_IDS]; + enum hwmon_sys_fan_rpm_id sys_fan_speed_rpm[HWMON_SYS_FAN_RPM_IDS]; //GetHwCapability(id = CAPABILITY_FAN_RPM_RPT) + enum hwmon_sys_hdd_bp_id hdd_backplane[HWMON_SYS_HDD_BP_IDS]; + enum hw_psu_sensor_id psu_status[HWMON_PSU_SENSOR_IDS]; + enum hwmon_sys_current_id sys_current[HWMON_SYS_CURRENT_IDS]; + } hwmon; +}; + +#define platform_has_hwmon_thermal(hw_config_ptr) ((hw_config_ptr)->hwmon.sys_thermal[0] != HWMON_SYS_TZONE_NULL_ID) +#define platform_has_hwmon_voltage(hw_config_ptr) ((hw_config_ptr)->hwmon.sys_voltage[0] != HWMON_SYS_VSENS_NULL_ID) +#define platform_has_hwmon_fan_rpm(hw_config_ptr) ((hw_config_ptr)->hwmon.sys_fan_speed_rpm[0] != HWMON_SYS_FAN_NULL_ID) +#define platform_has_hwmon_hdd_bpl(hw_config_ptr) ((hw_config_ptr)->hwmon.hdd_backplane[0] != HWMON_SYS_HDD_BP_NULL_ID) +#define platform_has_hwmon_psu_status(hw_config_ptr) ((hw_config_ptr)->hwmon.psu_status[0] != HWMON_PSU_NULL_ID) +#define platform_has_hwmon_current_sens(hw_config_ptr) ((hw_config_ptr)->hwmon.sys_current[0] != HWMON_SYS_CURR_NULL_ID) + +#endif //REDPILL_PLATFORM_TYPES_H diff --git a/config/platforms.h b/config/platforms.h new file mode 100644 index 0000000..2eecfd2 --- /dev/null +++ b/config/platforms.h @@ -0,0 +1,462 @@ +/* + * DO NOT include this file anywhere besides runtime_config.c - its format is meant to be internal to the configuration + * parsing. + */ +#ifndef REDPILLLKM_PLATFORMS_H +#define REDPILLLKM_PLATFORMS_H + +#include "../shim/pci_shim.h" +#include "platform_types.h" +const struct hw_config supported_platforms[] = { + { + .name = "DS918+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9215, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_I211, .bus = 0x02, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_I211, .bus = 0x03, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_AHCI_CTRL, .bus = 0x00, .dev = 0x12, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_PCIE_PA, .bus = 0x00, .dev = 0x13, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_PCIE_PB, .bus = 0x00, .dev = 0x14, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_USB_XHCI, .bus = 0x00, .dev = 0x15, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_I2C, .bus = 0x00, .dev = 0x16, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_HSUART, .bus = 0x00, .dev = 0x18, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_SPI, .bus = 0x00, .dev = 0x19, .fn = 0x02, .multifunction = true }, + { .type = VPD_INTEL_CPU_SPI, .bus = 0x00, .dev = 0x19, .fn = 0x00, .multifunction = true }, + { .type = VPD_INTEL_CPU_SMBUS, .bus = 0x00, .dev = 0x1f, .fn = 0x01, .multifunction = true }, + { .type = VPD_INTEL_CPU_SMBUS, .bus = 0x00, .dev = 0x1f, .fn = 0x00, .multifunction = true }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = true, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_NULL_ID }, + .sys_voltage = { HWMON_SYS_VSENS_NULL_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN_NULL_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_DETECT_ID, HWMON_SYS_HDD_BP_ENABLE_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS920+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = true, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_NULL_ID }, + .sys_voltage = { HWMON_SYS_VSENS_NULL_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN_NULL_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_DETECT_ID, HWMON_SYS_HDD_BP_ENABLE_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS923+", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS1520+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = true, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_NULL_ID }, + .sys_voltage = { HWMON_SYS_VSENS_NULL_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN_NULL_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_DETECT_ID, HWMON_SYS_HDD_BP_ENABLE_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS1621+", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS923+", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS1621xs+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x09, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x0c, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS2422+", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS3615xs", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x07, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x08, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x09, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x0a, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = true, + .reinit_ttyS0 = false, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS3617xs", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9215, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9215, .bus = 0x02, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x08, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS3622xs+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x09, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x0c, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DVA1622", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = true, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_NULL_ID }, + .sys_voltage = { HWMON_SYS_VSENS_NULL_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN_NULL_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_DETECT_ID, HWMON_SYS_HDD_BP_ENABLE_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DVA3219", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DVA3221", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "FS2500", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "FS6400", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "RS3413xs+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x07, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x08, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x09, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x0a, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = true, + .reinit_ttyS0 = false, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "RS3618xs", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9215, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9215, .bus = 0x02, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x08, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "RS4021xs+", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .is_dt = false, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "SA6400", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .is_dt = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + } +}; + +#endif //REDPILLLKM_PLATFORMS_H diff --git a/config/platforms.h.bak b/config/platforms.h.bak new file mode 100644 index 0000000..c8e430d --- /dev/null +++ b/config/platforms.h.bak @@ -0,0 +1,156 @@ +/* + * DO NOT include this file anywhere besides runtime_config.c - its format is meant to be internal to the configuration + * parsing. + */ +#ifndef REDPILLLKM_PLATFORMS_H +#define REDPILLLKM_PLATFORMS_H + +#include "../shim/pci_shim.h" +#include "platform_types.h" +const struct hw_config supported_platforms[] = { + { + .name = "DS3615xs", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x07, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x08, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x09, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x0a, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = true, + .reinit_ttyS0 = false, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS3617xs", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9215, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9215, .bus = 0x02, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x08, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "FS6400", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + + { + .name = "DS3622xs+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9235, .bus = 0x09, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_MARVELL_88SE9235, .bus = 0x0c, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "RS4021xs+", + .pci_stubs = { + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = false, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = false, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_REMOTE1_ID, HWMON_SYS_TZONE_LOCAL_ID, HWMON_SYS_TZONE_REMOTE2_ID }, + .sys_voltage = { HWMON_SYS_VSENS_VCC_ID, HWMON_SYS_VSENS_VPP_ID, HWMON_SYS_VSENS_V33_ID, + HWMON_SYS_VSENS_V5_ID, HWMON_SYS_VSENS_V12_ID }, + .sys_fan_speed_rpm = {HWMON_SYS_FAN1_ID, HWMON_SYS_FAN2_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_NULL_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, + { + .name = "DS918+", + .pci_stubs = { + { .type = VPD_MARVELL_88SE9215, .bus = 0x01, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_I211, .bus = 0x02, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_I211, .bus = 0x03, .dev = 0x00, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_AHCI_CTRL, .bus = 0x00, .dev = 0x12, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_PCIE_PA, .bus = 0x00, .dev = 0x13, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_PCIE_PB, .bus = 0x00, .dev = 0x14, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_USB_XHCI, .bus = 0x00, .dev = 0x15, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_I2C, .bus = 0x00, .dev = 0x16, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_HSUART, .bus = 0x00, .dev = 0x18, .fn = 0x00, .multifunction = false }, + { .type = VPD_INTEL_CPU_SPI, .bus = 0x00, .dev = 0x19, .fn = 0x02, .multifunction = true }, + { .type = VPD_INTEL_CPU_SPI, .bus = 0x00, .dev = 0x19, .fn = 0x00, .multifunction = true }, + { .type = VPD_INTEL_CPU_SMBUS, .bus = 0x00, .dev = 0x1f, .fn = 0x01, .multifunction = true }, + { .type = VPD_INTEL_CPU_SMBUS, .bus = 0x00, .dev = 0x1f, .fn = 0x00, .multifunction = true }, + + { .type = __VPD_TERMINATOR__ } + }, + .emulate_rtc = true, + .swap_serial = false, + .reinit_ttyS0 = true, + .fix_disk_led_ctrl = true, + .has_cpu_temp = true, + .hwmon = { + .sys_thermal = { HWMON_SYS_TZONE_NULL_ID }, + .sys_voltage = { HWMON_SYS_VSENS_NULL_ID }, + .sys_fan_speed_rpm = { HWMON_SYS_FAN_NULL_ID }, + .hdd_backplane = { HWMON_SYS_HDD_BP_DETECT_ID, HWMON_SYS_HDD_BP_ENABLE_ID }, + .psu_status = { HWMON_PSU_NULL_ID }, + .sys_current = { HWMON_SYS_CURR_NULL_ID }, + } + }, +}; + +#endif //REDPILLLKM_PLATFORMS_H diff --git a/config/runtime_config.c b/config/runtime_config.c new file mode 100644 index 0000000..31400a6 --- /dev/null +++ b/config/runtime_config.c @@ -0,0 +1,246 @@ +#include "runtime_config.h" +#include "platforms.h" +#include "../common.h" +#include "cmdline_delegate.h" +#include "uart_defs.h" + +struct runtime_config current_config = { + .hw = { '\0' }, + .sn = { '\0' }, + .boot_media = { + .type = BOOT_MEDIA_USB, + .mfg_mode = false, + .vid = VID_PID_EMPTY, + .pid = VID_PID_EMPTY, + .dom_size_mib = 1024, //usually the image will be used with ESXi and thus it will be ~100MB anyway + }, + .port_thaw = true, + .netif_num = 0, + .macs = { '\0' }, + .cmdline_blacklist = { '\0' }, + .hw_config = NULL, +}; + +static inline bool validate_sn(const serial_no *sn) { + if (*sn[0] == '\0') { + pr_loc_err("Serial number is empty"); + return false; + } + + //TODO: add more validation here, probably w/model? + + return true; +} + +static __always_inline bool validate_boot_dev_usb(const struct boot_media *boot) +{ + if (boot->vid == VID_PID_EMPTY && boot->pid == VID_PID_EMPTY) { + pr_loc_wrn("Empty/no \"%s\" and \"%s\" specified - first USB storage device will be used", CMDLINE_CT_VID, + CMDLINE_CT_PID); + return true; //this isn't necessarily an error (e.g. running under a VM with only a single USB port) + } + + if (boot->vid == VID_PID_EMPTY) { //PID=0 is valid, but the VID is not + pr_loc_err("Empty/no \"%s\" specified", CMDLINE_CT_VID); + return false; + } + + pr_loc_dbg("Configured boot device type to USB"); + return true; + //not checking for >VID_PID_MAX as vid type is already ushort +} + +static __always_inline bool validate_boot_dev_sata_dom(const struct boot_media *boot) +{ +#ifndef NATIVE_SATA_DOM_SUPPORTED + pr_loc_err("Kernel you are running a kernel was built without SATA DoM support, you cannot use %s%c. " + "You can try booting with %s%c to enable experimental fake-SATA DoM.", + CMDLINE_KT_SATADOM, CMDLINE_KT_SATADOM_NATIVE, + CMDLINE_KT_SATADOM, CMDLINE_KT_SATADOM_FAKE); + return false; +#endif + + if (boot->vid != VID_PID_EMPTY || boot->pid != VID_PID_EMPTY) + pr_loc_wrn("Using native SATA-DoM boot - %s and %s parameter values will be ignored", + CMDLINE_CT_VID, CMDLINE_CT_PID); + + //this config is impossible as there's no equivalent for force-reinstall boot on SATA, so it's better to detect + //that rather than causing WTFs for someone who falsely assuming that it's possible + //However, it does work with fake-SATA boot (as it emulates USB disk anyway) + if (boot->mfg_mode) { + pr_loc_err("You cannot combine %s%c with %s - the OS supports force-reinstall on USB and fake SATA disk only", + CMDLINE_KT_SATADOM, CMDLINE_KT_SATADOM_NATIVE, CMDLINE_CT_MFG); + return false; + } + + pr_loc_dbg("Configured boot device type to fake-SATA DOM"); + return true; +} + +static __always_inline bool validate_boot_dev_sata_disk(const struct boot_media *boot) +{ +#ifdef NATIVE_SATA_DOM_SUPPORTED + pr_loc_wrn("The kernel you are running supports native SATA DoM (%s%c). You're currently using an experimental " + "fake-SATA DoM (%s%c) - consider switching to native SATA DoM (%s%c) for more stable operation.", + CMDLINE_KT_SATADOM, CMDLINE_KT_SATADOM_NATIVE, + CMDLINE_KT_SATADOM, CMDLINE_KT_SATADOM_FAKE, + CMDLINE_KT_SATADOM, CMDLINE_KT_SATADOM_NATIVE); +#endif + + if (boot->vid != VID_PID_EMPTY || boot->pid != VID_PID_EMPTY) + pr_loc_wrn("Using fake SATA disk boot - %s and %s parameter values will be ignored", + CMDLINE_CT_VID, CMDLINE_CT_PID); + + pr_loc_dbg("Configured boot device type to fake-SATA DOM"); + return true; +} + +static inline bool validate_boot_dev(const struct boot_media *boot) +{ + switch (boot->type) { + case BOOT_MEDIA_USB: + return validate_boot_dev_usb(boot); + case BOOT_MEDIA_SATA_DOM: + return validate_boot_dev_sata_dom(boot); + case BOOT_MEDIA_SATA_DISK: + return validate_boot_dev_sata_disk(boot); + default: + pr_loc_bug("Got unknown boot type - did you forget to update %s after changing cmdline parsing?", + __FUNCTION__); + return false; + + } +} + +static inline bool validate_nets(const unsigned short if_num, mac_address * const macs[MAX_NET_IFACES]) +{ + size_t mac_len; + unsigned short macs_num = 0; + bool valid = true; + for (; macs_num < MAX_NET_IFACES; macs_num++) { + if (!macs[macs_num]) + break; //You cannot have gaps in macs array + + mac_len = strlen(*macs[macs_num]); + if (mac_len != MAC_ADDR_LEN) { + pr_loc_err("MAC address \"%s\" is invalid (expected %d characters, found %zu)", *macs[macs_num], MAC_ADDR_LEN, + mac_len); + valid = false; + } //else if validate if the MAC is actually semi-valid + } + + if (if_num == 0) { + pr_loc_wrn("Number of defined interfaces (\"%s\") is not specified or empty", CMDLINE_KT_NETIF_NUM); + } + + if (macs_num == 0) { + pr_loc_wrn("No MAC addressed are specified - use \"%s\" or \"%s\"...\"%s\" to set them", CMDLINE_KT_MACS, + CMDLINE_KT_MAC1, CMDLINE_KT_MAC4); + } + + if (if_num != macs_num) { + pr_loc_err("Number of defined interfaces (\"%s%d\") is not equal to the number of MAC addresses found (%d)", + CMDLINE_KT_NETIF_NUM, if_num, macs_num); + valid = false; + } + + return valid; +} + +/** + * This function validates consistency of the currently loaded platform config with the current environment + * + * Some options don't make sense unless the kernel was built with some specific configuration. This function aims to + * detect common pitfalls in platforms configuration. This doesn't so much validate the platform definition per se + * (but partially too) but the match between platform config chosen vs. kernel currently attempting to run that + * platform. + */ +static inline bool validate_platform_config(const struct hw_config *hw) +{ +#ifdef UART_BUG_SWAPPED + const bool kernel_serial_swapped = true; +#else + const bool kernel_serial_swapped = false; +#endif + + //This will not prevent the code from working, so it's not an error state by itself + if (unlikely(hw->swap_serial && !kernel_serial_swapped)) + pr_loc_bug("Your kernel indicates COM1 & COM2 ARE NOT swapped but your platform specifies swapping"); + else if(unlikely(!hw->swap_serial && kernel_serial_swapped)) + pr_loc_bug("Your kernel indicates COM1 & COM2 ARE swapped but your platform specifies NO swapping"); + + return true; +} + +static int populate_hw_config(struct runtime_config *config) +{ + //We cannot run with empty model or model which didn't match + if (config->hw[0] == '\0') { + pr_loc_crt("Empty model, please set \"%s\" parameter", CMDLINE_KT_HW); + return -ENOENT; + } + + for (int i = 0; i < ARRAY_SIZE(supported_platforms); i++) { + if (strcmp(supported_platforms[i].name, (char *)config->hw) != 0) + continue; + + pr_loc_dbg("Found platform definition for \"%s\"", config->hw); + config->hw_config = &supported_platforms[i]; + return 0; + } + + pr_loc_crt("The model set using \"%s%s\" is not valid", CMDLINE_KT_HW, config->hw); + return -EINVAL; +} + +static bool validate_runtime_config(const struct runtime_config *config) +{ + pr_loc_dbg("Validating runtime config..."); + bool valid = true; + + valid &= validate_sn(&config->sn); + valid &= validate_boot_dev(&config->boot_media); + valid &= validate_nets(config->netif_num, config->macs); + valid &= validate_platform_config(config->hw_config); + + pr_loc_dbg("Config validation resulted in %s", valid ? "OK" : "ERR"); + if (valid) { + return 0; + } else { + pr_loc_err("Config validation FAILED"); + return -EINVAL; + } +} + +int populate_runtime_config(struct runtime_config *config) +{ + int out = 0; + + if ((out = populate_hw_config(config)) != 0 || (out = validate_runtime_config(config)) != 0) { + pr_loc_err("Failed to populate runtime config!"); + return out; + } + + pr_loc_inf("Runtime config populated"); + + return out; +} + +void free_runtime_config(struct runtime_config *config) +{ + for (int i = 0; i < MAX_NET_IFACES; i++) { + if (config->macs[i]) { + pr_loc_dbg("Free MAC%d @ %p", i, config->macs[i]); + kfree(config->macs[i]); + } + } + + for (int i = 0; i < MAX_BLACKLISTED_CMDLINE_TOKENS; i++) { + if (config->cmdline_blacklist[i]) { + pr_loc_dbg("Free cmdline blacklist entry %d @ %p", i, config->cmdline_blacklist[i]); + kfree(config->cmdline_blacklist[i]); + } + } + + pr_loc_inf("Runtime config freed"); +} diff --git a/config/runtime_config.h b/config/runtime_config.h new file mode 100644 index 0000000..04080e1 --- /dev/null +++ b/config/runtime_config.h @@ -0,0 +1,71 @@ +#ifndef REDPILLLKM_RUNTIME_CONFIG_H +#define REDPILLLKM_RUNTIME_CONFIG_H + +#include "uart_defs.h" //UART config values +#include //bool + +//These below are currently known runtime limitations +#define MAX_NET_IFACES 8 +#define MAC_ADDR_LEN 12 +#define MAX_BLACKLISTED_CMDLINE_TOKENS 10 + +#ifdef CONFIG_SYNO_BOOT_SATA_DOM +#define NATIVE_SATA_DOM_SUPPORTED //whether SCSI sd.c driver supports native SATA DOM +#endif + +//UART-related constants were moved to uart_defs.h, to allow subcomponents to importa a smaller subset than this header +#define MODEL_MAX_LENGTH 10 +#define SN_MAX_LENGTH 13 + +#define VID_PID_EMPTY 0x0000 +#define VID_PID_MAX 0xFFFF + +typedef unsigned short device_id; +typedef char syno_hw[MODEL_MAX_LENGTH + 1]; +typedef char mac_address[MAC_ADDR_LEN + 1]; +typedef char serial_no[SN_MAX_LENGTH + 1]; +typedef char cmdline_token[]; + +enum boot_media_type { + BOOT_MEDIA_USB, + BOOT_MEDIA_SATA_DOM, + BOOT_MEDIA_SATA_DISK, +}; + +struct boot_media { + enum boot_media_type type; // Default: BOOT_MEDIA_USB + + //USB only options + bool mfg_mode; //emulate mfg mode (valid for USB boot only). Default: false + device_id vid; //Vendor ID of device containing the loader. Default: empty + device_id pid; //Product ID of device containing the loader. Default: empty + + //SATA only options + unsigned long dom_size_mib; //Max size of SATA DOM Default: 1024 +}; + +struct hw_config; +struct runtime_config { + syno_hw hw; //used to determine quirks. Default: empty + serial_no sn; //Used to validate it and warn the user. Default: empty + struct boot_media boot_media; + bool port_thaw; //Currently unknown. Default: true + unsigned short netif_num; //Number of eth interfaces. Default: 0 + mac_address *macs[MAX_NET_IFACES]; //MAC addresses of eth interfaces. Default: [] + cmdline_token *cmdline_blacklist[MAX_BLACKLISTED_CMDLINE_TOKENS];// Default: [] + const struct hw_config *hw_config; +}; +extern struct runtime_config current_config; + +/** + * Takes a raw extracted config and "shakes it a little bit" by validating things & constructing dependent structures + * + * Warning: if this function returns false YOU MUST NOT trust the config structure. Other code WILL break as it assumes + * the config is valid (e.g. doesn't have null ptrs which this function generates). + * Also, after you call this function you should call free_runtime_config() to clear up memory reservations. + */ +int populate_runtime_config(struct runtime_config *config); + +void free_runtime_config(struct runtime_config *config); + +#endif //REDPILLLKM_RUNTIME_CONFIG_H diff --git a/config/uart_defs.h b/config/uart_defs.h new file mode 100644 index 0000000..fa8a444 --- /dev/null +++ b/config/uart_defs.h @@ -0,0 +1,50 @@ +/** + * This file is meant to be small and portable. It can be included by other parts of the module wishing to get some info + * about UARTs. It should not contain any extensive definitions or static structures reservation. It is mostly + * extracting information buried in the Linux serial subsystem into usable constants. + */ +#ifndef REDPILL_UART_DEFS_H +#define REDPILL_UART_DEFS_H + +#include //flags for pc_com* +#include //struct uart_port +#include //KERNEL_VERSION() + +//These definitions are taken from asm/serial.h for a normal (i.e. non-swapped) UART1/COM1 port on an x86 PC +#define STD_COM1_IOBASE 0x3f8 +#define STD_COM1_IRQ 4 +#define STD_COM2_IOBASE 0x2f8 +#define STD_COM2_IRQ 3 +#define STD_COM3_IOBASE 0x3e8 +#define STD_COM3_IRQ 4 +#define STD_COM4_IOBASE 0x2e8 +#define STD_COM4_IRQ 3 + +//They changed name of flags const: https://github.com/torvalds/linux/commit/196cf358422517b3ff3779c46a1f3e26fb084172 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) +#define STD_COMX_FLAGS STD_COM_FLAGS +#endif + +#define STD_COMX_BAUD BASE_BAUD + +#define STD_COMX_DEV_NAME "ttyS" +#define SRD_COMX_BAUD_OPTS "115200n8" + +#define UART_NR CONFIG_SERIAL_8250_NR_UARTS +#define SERIAL8250_LAST_ISA_LINE (UART_NR-1) //max valid index of ttyS +#define SERIAL8250_SOFT_IRQ 0 //a special IRQ value which, if set on a port, will force 8250 driver to use timers + + +#ifdef CONFIG_SYNO_X86_SERIAL_PORT_SWAP +#define UART_BUG_SWAPPED //indicates that first two UARTs are swapped (sic!). Yes, we do consider it a fucking bug. +#endif + +// CONFIG_SYNO_FIX_TTYS_FUNCTIONS=y +// CONFIG_SYNO_TTYS_FUN_NUM=2 +#ifdef CONFIG_SYNO_TTYS_FUN_NUM +#define UART_SYNO_TTYS_FUN_NUM CONFIG_SYNO_TTYS_FUN_NUM // 看着像群晖独占的口数 模拟时直接跳过 +#else +#define UART_SYNO_TTYS_FUN_NUM 0 +#endif + +#endif //REDPILL_UART_DEFS_H diff --git a/config/vpci_types.h b/config/vpci_types.h new file mode 100644 index 0000000..41bf24c --- /dev/null +++ b/config/vpci_types.h @@ -0,0 +1,18 @@ +#ifndef REDPILL_VPCI_LIMITS_H +#define REDPILL_VPCI_LIMITS_H + +#include "../shim/pci_shim.h" //pci_shim_device_type + +//Defines below are experimentally determined to be sufficient but can often be changed +#define MAX_VPCI_BUSES 8 //adjust if needed, max 256 +#define MAX_VPCI_DEVS 16 //adjust if needed, max 256*32=8192 + +struct vpci_device_stub { + enum pci_shim_device_type type; + u8 bus; + u8 dev; + u8 fn; + bool multifunction:1; +}; + +#endif //REDPILL_VPCI_LIMITS_H diff --git a/debug/debug_execve.c b/debug/debug_execve.c new file mode 100644 index 0000000..c7652a7 --- /dev/null +++ b/debug/debug_execve.c @@ -0,0 +1,135 @@ +#include "debug_execve.h" +#include "../common.h" +#include //task_struct +#include //get_user +#include //compat_uptr_t +#include //MAX_ARG_STRINGS + +/* + * Struct copied 1:1 from: + * + * linux/fs/exec.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ +struct user_arg_ptr { +#ifdef CONFIG_COMPAT + bool is_compat; +#endif + union { + const char __user *const __user *native; +#ifdef CONFIG_COMPAT + const compat_uptr_t __user *compat; +#endif + } ptr; +}; + +/* + * Function copied 1:1 from: + * + * linux/fs/exec.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ +static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) +{ + const char __user *native; + +#ifdef CONFIG_COMPAT + if (unlikely(argv.is_compat)) { + compat_uptr_t compat; + + if (get_user(compat, argv.ptr.compat + nr)) + return ERR_PTR(-EFAULT); + + return compat_ptr(compat); + } +#endif + + if (get_user(native, argv.ptr.native + nr)) + return ERR_PTR(-EFAULT); + + return native; +} + +/* + * Modified for simplicity from count() in: + * + * linux/fs/exec.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ +static int count_args(struct user_arg_ptr argv) +{ + if (argv.ptr.native == NULL) + return 0; + + int i = 0; + + for (;;) { + const char __user *p = get_user_arg_ptr(argv, i); + + if (!p) + break; + + if (IS_ERR(p) || i >= MAX_ARG_STRINGS) + return -EFAULT; + + ++i; + + if (fatal_signal_pending(current)) + return -ERESTARTNOHAND; + cond_resched(); + } + + return i; +} + +static void inline fixup_arg_str(char *arg_ptr, int cur_argc, const char *what) +{ + pr_loc_wrn("Failed to copy %d arg - %s failed", cur_argc, what); + memcpy(arg_ptr, "..?\0", 4); +} + +void RPDBG_print_execve_call(const char *filename, const char __user *const __user *argv) +{ + struct task_struct *caller = get_cpu_var(current_task); + + struct user_arg_ptr argv_up = { .ptr.native = argv }; + int argc = count_args(argv_up); + + char *arg_str = kzalloc(MAX_ARG_STRLEN, GFP_KERNEL); + if (unlikely(!arg_str)) { + pr_loc_crt("kzalloc failed"); + return; + } + + char *arg_ptr = &arg_str[0]; + for (int i = 0; i < argc; i++) { + const char __user *p = get_user_arg_ptr(argv_up, i); + if (IS_ERR(p)) { + fixup_arg_str(arg_ptr, i, "get_user_arg_ptr"); + goto out_free; + } + + int len = strnlen_user(p, MAX_ARG_STRLEN); //includes nullbyte + if (!len) { + fixup_arg_str(arg_ptr, i, "strnlen_user"); + goto out_free; + } + --len; //we want to copy without nullbyte as we handle it ourselves while attaching to arg_ptr + + if (copy_from_user(arg_ptr, p, len)) { + fixup_arg_str(arg_ptr, i, "copy_from_user"); + goto out_free; + } + + arg_ptr += len; + *arg_ptr = (i + 1 == argc) ? '\0' : ' '; //separate by spaces UNLESS it's the last argument + ++arg_ptr; + } + + out_free: + pr_loc_dbg("execve@cpu%d: %s[%d]=>%s[%d] {%s}", caller->on_cpu, caller->comm, caller->pid, filename, argc, arg_str); + kfree(arg_str); +} \ No newline at end of file diff --git a/debug/debug_execve.h b/debug/debug_execve.h new file mode 100644 index 0000000..09aea02 --- /dev/null +++ b/debug/debug_execve.h @@ -0,0 +1,6 @@ +#ifndef REDPILL_DEBUG_EXECVE_H +#define REDPILL_DEBUG_EXECVE_H + +void RPDBG_print_execve_call(const char *filename, const char *const *argv); + +#endif //REDPILL_DEBUG_EXECVE_H diff --git a/debug/debug_vuart.h b/debug/debug_vuart.h new file mode 100644 index 0000000..a0e66a7 --- /dev/null +++ b/debug/debug_vuart.h @@ -0,0 +1,77 @@ +#ifndef REDPILL_DEBUG_VUART_H +#define REDPILL_DEBUG_VUART_H + +//Whether the code will print all internal state changes +#ifdef VUART_DEBUG_LOG +//Main print macro used everywhere below +#define uart_prdbg(f, ...) pr_loc_dbg(f, ##__VA_ARGS__) + +#define reg_read(rN) uart_prdbg("Reading " rN " registry"); +#define reg_write(rN) uart_prdbg("Writing " rN " registry"); +#define reg_read_dump(d, rF, rN) reg_read(rN); dump_##rF(d); +#define reg_write_dump(d, rF, rN) reg_write(rN); dump_##rF(d); +#define dri(vdev, reg, flag) ((vdev)->reg&(flag)) ? 1:0 //Dump Register as 1-0 Integer +#define diiri(vdev, flag) (((vdev)->iir&UART_IIR_ID) == (flag)) ? 1:0 //Dump IIR Interrupt type as 1-0 integer +#define dump_ier(d) \ + uart_prdbg("IER[0x%02x]: DR_int=%d | THRe_int=%d | RLS_int=%d | " \ + "MS_int=%d", \ + (d)->ier, dri(d,ier,UART_IER_RDI), dri(d,ier,UART_IER_THRI), dri(d,ier,UART_IER_RLSI), \ + dri(d,ier,UART_IER_MSI)); +//Be careful interpreting the result of this macro - no_int_pend means "no interrupts pending" (so 0 if there are +// pending interrupts and 1 if there are no interrupts pending); see Table 3-5 in TI doc +//Also FIFO flags are slightly weird (it's 2 bit, see IIR table in https://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming) +// so fifoen=0_0 means "FIFO disabled", fifoen=1_1 means "FIFO enabled", and fifoen=0_1 means "FIFO enabled & broken" +//Also, since MSI is 0-0-0 it's a special-ish case: it's only considered enabled when int is pending and all bits are 0 +#define dump_iir(d) \ + uart_prdbg("IIR/ISR[0x%02x]: no_int_pend=%d | int_MS=%d | " \ + "int_THRe=%d | int_DR=%d | int_RLS=%d | " \ + "fifoen=%d_%d", \ + (d)->iir, dri(d,iir,UART_IIR_NO_INT), (!((d)->iir&UART_IIR_NO_INT)&&((d)->iir&UART_IIR_ID)==UART_IIR_MSI)?1:0, \ + diiri(d,UART_IIR_THRI), diiri(d,UART_IIR_RDI), diiri(d,UART_IIR_RLSI), \ + (((d)->iir & UART_IIR_FIFEN_B6)?1:0), (((d)->iir & UART_IIR_FIFEN_B7)?1:0)); +#define dump_fcr(d) \ + uart_prdbg("FCR[0x%02x]: FIFOon=%d | RxFIFOrst=%d | " \ + "TxFIFOrst=%d | EnDMAend=%d", \ + (d)->fcr, dri(d,fcr,UART_FCR_ENABLE_FIFO), dri(d,fcr,UART_FCR_CLEAR_RCVR), \ + dri(d,fcr,UART_FCR_CLEAR_XMIT), dri(d,fcr,UART_FCR_DMA_SELECT)); +#define dump_lcr(d) \ + uart_prdbg("LCR[0x%02x]: Stop=%d | PairEN=%d | EvenP=%d | " \ + "ForcPair=%d | SetBrk=%d | DLAB=%d", \ + (d)->lcr, dri(d,lcr,UART_LCR_STOP), dri(d,lcr,UART_LCR_PARITY), dri(d,lcr,UART_LCR_EPAR), \ + dri(d,lcr,UART_LCR_SPAR), dri(d,lcr,UART_LCR_SBC), dri(d,lcr,UART_LCR_DLAB)); +#define dump_mcr(d) \ + uart_prdbg("MCR[0x%02x]: DTR=%d | RTS=%d | Out1=%d | " \ + "Out2/IntE=%d | Loop=%d", \ + (d)->mcr, dri(d,mcr,UART_MCR_DTR), dri(d,mcr,UART_MCR_RTS), dri(d,mcr,UART_MCR_OUT1), \ + dri(d,mcr,UART_MCR_OUT2), dri(d,mcr,UART_MCR_LOOP)); +#define dump_lsr(d) \ + uart_prdbg("LSR[0x%02x]: data_ready=%d | ovrunE=%d | pairE=%d | " \ + "frE=%d | break_req=%d | THRemp=%d | TransEMP=%d | " \ + "FIFOdE=%d", \ + (d)->lsr, dri(d,lsr,UART_LSR_DR), dri(d,lsr,UART_LSR_OE), dri(d,lsr,UART_LSR_PE), \ + dri(d,lsr,UART_LSR_FE), dri(d,lsr,UART_LSR_BI), dri(d,lsr,UART_LSR_THRE), dri(d,lsr,UART_LSR_TEMT), \ + dri(d,lsr,UART_LSR_FIFOE)); +#define dump_msr(d) \ + uart_prdbg("MSR[0x%02x]: delCTS=%d | delDSR=%d | trEdgRI=%d | " \ + "delCD=%d | CTS=%d | DSR=%d | RI=%d | " \ + "DCD=%d", \ + (d)->msr, dri(d,msr,UART_MSR_DCTS), dri(d,msr,UART_MSR_DDSR), dri(d,msr,UART_MSR_TERI), \ + dri(d,msr,UART_MSR_DDCD), dri(d,msr,UART_MSR_CTS), dri(d,msr,UART_MSR_DSR), dri(d,msr,UART_MSR_RI), \ + dri(d,msr,UART_MSR_DCD)); + +#else //VUART_DEBUG_LOG disabled \/ +#define uart_prdbg(f, ...) { /* noop */ } +#define reg_read(rN) { /* noop */ } +#define reg_write(rN) { /* noop */ } +#define reg_read_dump(d, rF, rN) { /* noop */ } +#define reg_write_dump(d, rF, rN) { /* noop */ } +#define dump_ier(d) { /* noop */ } +#define dump_iir(d) { /* noop */ } +#define dump_fcr(d) { /* noop */ } +#define dump_lcr(d) { /* noop */ } +#define dump_mcr(d) { /* noop */ } +#define dump_lsr(d) { /* noop */ } +#define dump_msr(d) { /* noop */ } +#endif //VUART_DEBUG_LOG + +#endif //REDPILL_DEBUG_VUART_H diff --git a/internal/call_protected.c b/internal/call_protected.c new file mode 100644 index 0000000..3926692 --- /dev/null +++ b/internal/call_protected.c @@ -0,0 +1,113 @@ +#include "call_protected.h" +#include "../common.h" +#include //common exit codes +//#include //kallsyms_lookup_name() +#include "helper/symbol_helper.h" //kln_func +#include //symbol_get()/put + +//This will eventually stop working (since Linux >=5.7.0 has the kallsyms_lookup_name() removed) +//Workaround will be needed: https://github.com/xcellerator/linux_kernel_hacking/issues/3 + +#define __VOID_RETURN__ +//This macro should be used to export symbols which aren't normally EXPORT_SYMBOL/EXPORT_SYMBOL_GPL in the kernel but +// they exist within the kernel (and not a loadable module!). Keep in mind that most of the time "static" cannot be +// reexported using this trick. +//All re-exported function will have _ prefix (e.g. foo() becomes _foo()) +#define DEFINE_UNEXPORTED_SHIM(return_type, org_function_name, call_args, call_vars, fail_return) \ + extern asmlinkage return_type org_function_name(call_args); \ + typedef typeof(org_function_name) *org_function_name##__ret; \ + static unsigned long org_function_name##__addr = 0; \ + return_type _##org_function_name(call_args) \ + { \ + if (unlikely(org_function_name##__addr == 0)) { \ + org_function_name##__addr = kln_func(#org_function_name); \ + if (org_function_name##__addr == 0) { \ + pr_loc_bug("Failed to fetch %s() syscall address", #org_function_name); \ + return fail_return; \ + } \ + pr_loc_dbg("Got addr %lx for %s", org_function_name##__addr, #org_function_name); \ + } \ + \ + return ((org_function_name##__ret)org_function_name##__addr)(call_vars); \ + } + +//This macro should be used to export symbols which aren't normally EXPORT_SYMBOL/EXPORT_SYMBOL_GPL in the kernel but +// they exist within the kernel and are defined as __init. These symbol can only be called when the system is still +// booting (i.e. before init user-space binary was called). After that calling such functions is a lottery - the memory +// of them is freed by free_initmem() [called in main.c:kernel_init()]. That's why we skip any caching kere as these are +// called mostly as a one-off during boot process when this module was loaded as a I/O scheduler. +//All re-exported function will have _ prefix (e.g. foo() becomes _foo()) +#define DEFINE_UNEXPORTED_INIT_SHIM(return_type, org_function_name, call_args, call_vars, fail_return) \ + extern asmlinkage return_type org_function_name(call_args); \ + typedef typeof(org_function_name) *org_function_name##__ret; \ + return_type _##org_function_name(call_args) \ + { \ + unsigned long org_function_name##__addr = 0; \ + if (unlikely(!is_system_booting())) { \ + pr_loc_bug("Attempted to call %s() when the system is already booted (state=%d)", \ + #org_function_name, system_state); \ + return fail_return; \ + } \ + org_function_name##__addr = kln_func(#org_function_name); \ + if (org_function_name##__addr == 0) { \ + pr_loc_bug("Failed to fetch %s() syscall address", #org_function_name); \ + return fail_return; \ + } \ + pr_loc_dbg("Got addr %lx for %s", org_function_name##__addr, #org_function_name); \ + \ + return ((org_function_name##__ret)org_function_name##__addr)(call_vars); \ + } + +//This macro should be used to export symbols which are normally exported by modules in situations where this module +// must be loaded before such module exporting the symbol. +//Normally if symbol for module "X" is used in "Y" the kernel will complain that "X" muse be loaded before "Y". +//All re-exported function will have _ prefix (e.g. foo() becomes _foo()) +#define DEFINE_DYNAMIC_SHIM(return_type, org_function_name, call_args, call_vars, fail_return) \ + extern asmlinkage return_type org_function_name(call_args); \ + typedef typeof(org_function_name) *org_function_name##__ret; \ + return_type _##org_function_name(call_args) \ + { \ + org_function_name##__ret org_function_name##__ptr = (org_function_name##__ret)__symbol_get(#org_function_name); \ + if (!org_function_name##__ptr) { \ + pr_loc_bug("Failed to fetch %s() symbol (is that module loaded?)", #org_function_name); \ + return fail_return; \ + } \ + pr_loc_dbg("Got ptr %p for %s", org_function_name##__ptr, #org_function_name); \ + /*Doing this BEFORE the call makes a TINY window where the symbol can "escape" but it's protects from deadlock*/\ + __symbol_put(#org_function_name); \ + \ + return ((org_function_name##__ret)org_function_name##__ptr)(call_vars); \ + } +//********************************************************************************************************************// + +DEFINE_UNEXPORTED_SHIM(int, cmdline_proc_show, CP_LIST(struct seq_file *m, void *v), CP_LIST(m, v), -EFAULT); +DEFINE_UNEXPORTED_SHIM(void, flush_tlb_all, CP_LIST(void), CP_LIST(), __VOID_RETURN__); + +//See header file for detailed explanation what's going on here as it's more complex than a single commit +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) +DEFINE_UNEXPORTED_SHIM(int, do_execve, CP_LIST(const char *filename, + const char __user *const __user *__argv, + const char __user *const __user *__envp), CP_LIST(filename, __argv, __envp), -EINTR); + +#ifndef CONFIG_AUDITSYSCALL +DEFINE_UNEXPORTED_SHIM(void, final_putname, CP_LIST(struct filename *name), CP_LIST(name), __VOID_RETURN__); +#else +DEFINE_UNEXPORTED_SHIM(void, putname, CP_LIST(struct filename *name), CP_LIST(name), __VOID_RETURN__); +#endif +#else +DEFINE_UNEXPORTED_SHIM(int, do_execve, CP_LIST(struct filename *filename, + const char __user *const __user *__argv, + const char __user *const __user *__envp), CP_LIST(filename, __argv, __envp), -EINTR); +DEFINE_UNEXPORTED_SHIM(struct filename *, getname, CP_LIST(const char __user *name), CP_LIST(name), ERR_PTR(-EFAULT)); +#endif + +DEFINE_UNEXPORTED_SHIM(int, scsi_scan_host_selected, CP_LIST(struct Scsi_Host *shost, unsigned int channel, unsigned int id, u64 lun, int rescan), CP_LIST(shost, channel, id, lun, rescan), -EIO); +DEFINE_UNEXPORTED_SHIM(int, ida_pre_get, CP_LIST(struct ida *ida, gfp_t gfp_mask), CP_LIST(ida, gfp_mask), -EINVAL); + +DEFINE_UNEXPORTED_SHIM(int, early_serial_setup, CP_LIST(struct uart_port *port), port, -EIO); +DEFINE_UNEXPORTED_SHIM(int, serial8250_find_port, CP_LIST(struct uart_port *p), CP_LIST(p), -EIO); + +DEFINE_UNEXPORTED_INIT_SHIM(int, elevator_setup, CP_LIST(char *str), CP_LIST(str), -EINVAL); + +DEFINE_DYNAMIC_SHIM(void, usb_register_notify, CP_LIST(struct notifier_block *nb), CP_LIST(nb), __VOID_RETURN__); +DEFINE_DYNAMIC_SHIM(void, usb_unregister_notify, CP_LIST(struct notifier_block *nb), CP_LIST(nb), __VOID_RETURN__); diff --git a/internal/call_protected.h b/internal/call_protected.h new file mode 100644 index 0000000..88a4221 --- /dev/null +++ b/internal/call_protected.h @@ -0,0 +1,77 @@ +#ifndef REDPILLLKM_CALL_PROTECTED_H +#define REDPILLLKM_CALL_PROTECTED_H + +#include //LINUX_VERSION_CODE, KERNEL_VERSION +#include //bool +#include //system_states & system_state + +// *************************************** Useful macros *************************************** // +//Check if the system is still in booting stage (useful when you want to call __init functions as they're deleted) +#define is_system_booting() (system_state == SYSTEM_BOOTING) + +// ************************** Exports of normally protected functions ************************** // + +//A usual macros to make defining them easier & consistent with .c implementation +#define CP_LIST(...) __VA_ARGS__ //used to pass a list of arguments as a single argument +#define CP_DECLARE_SHIM(return_type, org_function_name, call_args) return_type _##org_function_name(call_args); + +struct seq_file; +CP_DECLARE_SHIM(int, cmdline_proc_show, CP_LIST(struct seq_file *m, void *v)); //extracts kernel cmdline +CP_DECLARE_SHIM(void, flush_tlb_all, CP_LIST(void)); //used to flush caches in memory.c operations + +/* Thanks Jeff... https://groups.google.com/g/kernel-meetup-bangalore/c/rvQccTl_3kc/m/BJCnnXGCAgAJ + * In case the link disappears: Jeff Layton from RedHat decided to just nuke the getname() API after 7 years of it being + * exposed in the kernel. So in practice we need to use kallsyms to get it on kernels >=3.14 (up to current 5.14) + * See https://github.com/torvalds/linux/commit/9115eac2c788c17b57c9256cb322fa7371972ddf + * Another unrelated change which happened in v3.14 was that when "struct filename*" is passed the callee is responsible + * for freeing it (using putname()). However, in older versions we (the caller) needs to free it + * See https://github.com/torvalds/linux/commit/c4ad8f98bef77c7356aa6a9ad9188a6acc6b849d + * + * This whole block deals with functions needed for execve() shimming + */ +struct filename; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) +CP_DECLARE_SHIM(int, do_execve, CP_LIST(const char *filename, + const char __user *const __user *__argv, + const char __user *const __user *__envp)); + +#include +#define _getname(...) getname(__VA_ARGS__) + +//If syscall audit is disabled putname is an alias to final_putname(), see include/linux/fs.h; later on this was changed +// but this branch needs to handle only <3.14 as we don't need (and shouldn't use!) putname() in >=3.14 +#ifndef CONFIG_AUDITSYSCALL //if CONFIG_AUDITSYSCALL disabled we unexport final_putname and add putname define line fs.h +#define _putname(name) _final_putname(name) +CP_DECLARE_SHIM(void, final_putname, CP_LIST(struct filename *name)); +#else //if the CONFIG_AUDITSYSCALL is enabled we need to proxy to traced putname to make sure references are counted +CP_DECLARE_SHIM(void, putname, CP_LIST(struct filename *name)); +#endif +#else +CP_DECLARE_SHIM(int, do_execve, CP_LIST(struct filename *filename, + const char __user *const __user *__argv, + const char __user *const __user *__envp)); +CP_DECLARE_SHIM(struct filename *, getname, CP_LIST(const char __user *name)); +#endif + +//The following functions are used by vUART and uart_fixer +typedef struct uart_port *uart_port_p; +CP_DECLARE_SHIM(int, early_serial_setup, CP_LIST(struct uart_port *port)); +CP_DECLARE_SHIM(int, serial8250_find_port, CP_LIST(struct uart_port *p)); + +//Exported so that we can forcefully rescan the SCSI host in scsi_toolbox. This operation is normally available in +// userland when you're a root, but somehow they missed an export for kernel code (which according to kernel rules is a +// bug, but probably nobody asked before) +struct Scsi_Host; +CP_DECLARE_SHIM(int, scsi_scan_host_selected, + CP_LIST(struct Scsi_Host *shost, unsigned int channel, unsigned int id, u64 lun, int rescan)); + +struct ida; +CP_DECLARE_SHIM(int, ida_pre_get, CP_LIST(struct ida *ida, gfp_t gfp_mask)); + +//Used for fixing I/O scheduler if module was loaded using elevator= and broke it +CP_DECLARE_SHIM(int, elevator_setup, CP_LIST(char *str)); + +struct notifier_block; +CP_DECLARE_SHIM(void, usb_register_notify, CP_LIST(struct notifier_block *nb)); +CP_DECLARE_SHIM(void, usb_unregister_notify, CP_LIST(struct notifier_block *nb)); +#endif //REDPILLLKM_CALL_PROTECTED_H diff --git a/internal/helper/math_helper.c b/internal/helper/math_helper.c new file mode 100644 index 0000000..19387e9 --- /dev/null +++ b/internal/helper/math_helper.c @@ -0,0 +1,16 @@ +#include "math_helper.h" +#include //prandom_u32() + +int prandom_int_range_stable(int *cur_val, int dev, int min, int max) +{ + if (likely(*cur_val != 0)) { + int new_min = (*cur_val) - dev; + int new_max = (*cur_val) + dev; + min = new_min < min ? min : new_min; + max = new_max > max ? max : new_max; + } + + *cur_val = prandom_int_range(min, max); + + return *cur_val; +} \ No newline at end of file diff --git a/internal/helper/math_helper.h b/internal/helper/math_helper.h new file mode 100644 index 0000000..4338a91 --- /dev/null +++ b/internal/helper/math_helper.h @@ -0,0 +1,29 @@ +#ifndef REDPILL_MATH_HELPER_H +#define REDPILL_MATH_HELPER_H + +/** + * Generates pseudo-random integer in a range specified + * + * @param min Lower boundary integer + * @param max Higher boundary integer + * + * @return pseudorandom integer up to 32 bits in length + */ +#define prandom_int_range(min, max) ({ \ + int _rand = (prandom_u32() % ((max) + 1 - (min)) + (min)); \ + _rand; \ +}) + +/** + * Generates temporally stable pseudo-random integer in a range specified + * + * @param cur_val Pointer to store/read current value; set its value to 0 initially to generate setpoint automatically + * @param dev Max deviation from the current value + * @param min Lower boundary integer + * @param max Higher boundary integer + * + * @return pseudorandom integer up to 32 bits in length + */ +int prandom_int_range_stable(int *cur_val, int dev, int min, int max); + +#endif //REDPILL_MATH_HELPER_H diff --git a/internal/helper/memory_helper.c b/internal/helper/memory_helper.c new file mode 100644 index 0000000..7f24dda --- /dev/null +++ b/internal/helper/memory_helper.c @@ -0,0 +1,44 @@ +/** + * TODO: look into override_symbol to check if there's any docs + */ +#include "memory_helper.h" +#include "../../common.h" +#include "../call_protected.h" //_flush_tlb_all() +#include //PAGE_ALIGN +#include //PAGE_SIZE +#include //_PAGE_RW + +#define PAGE_ALIGN_BOTTOM(addr) (PAGE_ALIGN(addr) - PAGE_SIZE) //aligns the memory address to bottom of the page boundary +#define NUM_PAGES_BETWEEN(low, high) (((PAGE_ALIGN_BOTTOM(high) - PAGE_ALIGN_BOTTOM(low)) / PAGE_SIZE) + 1) + +void set_mem_addr_rw(const unsigned long vaddr, unsigned long len) +{ + unsigned long addr = PAGE_ALIGN_BOTTOM(vaddr); + pr_loc_dbg("Disabling memory protection for page(s) at %p+%lu/%u (<<%p)", (void *) vaddr, len, + (unsigned int) NUM_PAGES_BETWEEN(vaddr, vaddr + len), (void *) addr); + + //theoretically this should use set_pte_atomic() but we're touching pages that will not be modified by anything else + unsigned int level; + for(; addr <= vaddr; addr += PAGE_SIZE) { + pte_t *pte = lookup_address(addr, &level); + pte->pte |= _PAGE_RW; + } + + _flush_tlb_all(); +} + +void set_mem_addr_ro(const unsigned long vaddr, unsigned long len) +{ + unsigned long addr = PAGE_ALIGN_BOTTOM(vaddr); + pr_loc_dbg("Enabling memory protection for page(s) at %p+%lu/%u (<<%p)", (void *) vaddr, len, + (unsigned int) NUM_PAGES_BETWEEN(vaddr, vaddr + len), (void *) addr); + + //theoretically this should use set_pte_atomic() but we're touching pages that will not be modified by anything else + unsigned int level; + for(; addr <= vaddr; addr += PAGE_SIZE) { + pte_t *pte = lookup_address(addr, &level); + pte->pte &= ~_PAGE_RW; + } + + _flush_tlb_all(); +} \ No newline at end of file diff --git a/internal/helper/memory_helper.h b/internal/helper/memory_helper.h new file mode 100644 index 0000000..e505305 --- /dev/null +++ b/internal/helper/memory_helper.h @@ -0,0 +1,37 @@ +#ifndef REDPILL_MEMORY_HELPER_H +#define REDPILL_MEMORY_HELPER_H + +#define WITH_MEM_UNLOCKED(vaddr, size, code) \ + do { \ + set_mem_addr_rw((unsigned long)(vaddr), size); \ + ({code}); \ + set_mem_addr_ro((unsigned long)(vaddr), size); \ + } while(0) + +/** + * Disables write-protection for the memory where symbol resides + * + * There are a million different methods of circumventing the memory protection in Linux. The reason being the kernel + * people make it harder and harder to modify syscall table (& others in the process), which in general is a great idea. + * There are two core methods people use: 1) disabling CR0 WP bit, and 2) setting memory page(s) as R/W. + * The 1) is a flag, present on x86 CPUs, which when cleared configures the MMU to *ignore* write protection set on + * memory regions. However, this flag is per-core (=synchronization problems) and it works as all-or-none. We don't + * want to leave such a big thing disabled (especially for long time). + * The second mechanism disabled memory protection on per-page basis. Normally the kernel contains set_memory_rw() which + * does what it says - sets the address (which should be lower-page aligned) to R/W. However, this function is evil for + * some time (~2.6?). In its course it calls static_protections() which REMOVES the R/W flag from the request + * (effectively making the call a noop) while still returning 0. Guess how long we debugged that... additionally, that + * function is removed in newer kernels. + * The easiest way is to just lookup the page table entry for a given address, modify the R/W attribute directly and + * dump CPU caches. This will work as there's no middle-man to mess with our request. + */ +void set_mem_addr_rw(const unsigned long vaddr, unsigned long len); + +/** + * Reverses set_mem_rw() + * + * See set_mem_rw() for details + */ +void set_mem_addr_ro(const unsigned long vaddr, unsigned long len); + +#endif //REDPILL_MEMORY_HELPER_H diff --git a/internal/helper/symbol_helper.c b/internal/helper/symbol_helper.c new file mode 100644 index 0000000..67dca75 --- /dev/null +++ b/internal/helper/symbol_helper.c @@ -0,0 +1,112 @@ +#include "symbol_helper.h" //kln_func +#include //__symbol_get(), __symbol_put() +#include //kallsyms_lookup_name +#include "../../common.h" //pr_loc_* + +unsigned long (*kln_func)(const char* name) = NULL; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0) +int get_kln_p(void) +{ + kln_func = kallsyms_lookup_name; + return 0; +} +#else +/* + * In kernel version 5.7, kallsyms_lookup_name() was unexported, so we can't use it anymore. + * The alternative method below is slower (but not really noticably), and works by brute-forcing + * possible addresses for the function name by starting at the kernel base address and using + * sprint_symbol() (which is still exported) to check if the symbol name at each address + * matches the one we want. + * + * https://github.com/xcellerator/linux_kernel_hacking/blob/446789fd152d2663cd2c7d7f8a5aaae873a92a30/3_RootkitTechniques/3.3_set_root/ftrace_helper.h + */ +static unsigned long kaddr_lookup_name(const char *fname_raw) +{ + int i; + unsigned long kaddr; + char *fname_lookup, *fname; + + fname_lookup = kzalloc(255, GFP_KERNEL); + if (!fname_lookup) + return 0; + + fname = kzalloc(strlen(fname_raw)+4, GFP_KERNEL); + if (!fname) + return 0; + + /* + * We have to add "+0x0" to the end of our function name + * because that's the format that sprint_symbol() returns + * to us. If we don't do this, then our search can stop + * prematurely and give us the wrong function address! + */ + strcpy(fname, fname_raw); + strcat(fname, "+0x0"); + + /* + * Get the kernel base address: + * sprint_symbol() is less than 0x100000 from the start of the kernel, so + * we can just AND-out the last 3 bytes from it's address to the the base + * address. + * There might be a better symbol-name to use? + */ + kaddr = (unsigned long) &sprint_symbol; + kaddr &= 0xffffffffff000000; + + /* + * All the syscalls (and all interesting kernel functions I've seen so far) + * are within the first 0x100000 bytes of the base address. However, the kernel + * functions are all aligned so that the final nibble is 0x0, so we only + * have to check every 16th address. + */ + for ( i = 0x0 ; i < 0x100000 ; i++ ) + { + /* + * Lookup the name ascribed to the current kernel address + */ + sprint_symbol(fname_lookup, kaddr); + + /* + * Compare the looked-up name to the one we want + */ + if ( strncmp(fname_lookup, fname, strlen(fname)) == 0 ) + { + /* + * Clean up and return the found address + */ + kfree(fname_lookup); + return kaddr; + } + /* + * Jump 16 addresses to next possible address + */ + kaddr += 0x10; + } + /* + * We didn't find the name, so clean up and return 0 + */ + kfree(fname_lookup); + return 0; +} + +int get_kln_p(void) +{ + kln_func = (long unsigned int (*)(const char *))kaddr_lookup_name("kallsyms_lookup_name"); + if (kln_func == 0) { + pr_loc_err("Error searching kallsyms_lookup_name address!"); + return -1; + } + pr_loc_dbg("kallsyms_lookup_name address = 0x%lx\n", (long unsigned int)kln_func); + return 0; +} +#endif + +bool kernel_has_symbol(const char *name) { + if (__symbol_get(name)) { //search for public symbols + __symbol_put(name); + + return true; + } + return kln_func(name) != 0; +} \ No newline at end of file diff --git a/internal/helper/symbol_helper.h b/internal/helper/symbol_helper.h new file mode 100644 index 0000000..d38c58e --- /dev/null +++ b/internal/helper/symbol_helper.h @@ -0,0 +1,22 @@ +#ifndef REDPILL_SYMBOL_HELPER_H +#define REDPILL_SYMBOL_HELPER_H + +#include //bool + +/** + * Workaround for kallsyms_lookup_name in kernels > 5.7 + * https://github.com/xcellerator/linux_kernel_hacking/issues/3 + */ +extern unsigned long (*kln_func)(const char*); +int get_kln_p(void); + +/** + * Check if a given symbol exists + * + * This function will return true for both public and private kernel symbols + * + * @param name name of the symbol + */ +bool kernel_has_symbol(const char *name); + +#endif //REDPILL_SYMBOL_HELPER_H diff --git a/internal/intercept_driver_register.c b/internal/intercept_driver_register.c new file mode 100644 index 0000000..64aa7bb --- /dev/null +++ b/internal/intercept_driver_register.c @@ -0,0 +1,269 @@ +#include "intercept_driver_register.h" +#include "../common.h" +#include "override/override_symbol.h" +#include //platform_bus_type + +#define MAX_WATCHERS 5 //can be increased as-needed +#define WATCH_FUNCTION "driver_register" + +struct driver_watcher_instance { + watch_dr_callback *cb; + bool notify_coming:1; + bool notify_live:1; + char name[]; +}; + +static override_symbol_inst *ov_driver_register = NULL; +static driver_watcher_instance *watchers[MAX_WATCHERS] = { NULL }; + +/** + * Finds a registered watcher based on the driver name + * + * @return pointer to the spot on the list containing driver_watcher_instance or NULL if not found + */ +static driver_watcher_instance **match_watcher(const char *name) +{ + for (int i=0; i < MAX_WATCHERS; ++i) { + if (!watchers[i]) + continue; //there could be "holes" due to unwatch calls + + if(strcmp(name, watchers[i]->name) == 0) + return &watchers[i]; + } + + return NULL; +} + +/** + * Finds an empty spot in the watchers list + * + * @return pointer to the spot on the list which is empty or NULL if not found + */ +static driver_watcher_instance **watcher_list_spot(void) +{ + for (int i=0; i < MAX_WATCHERS; ++i) { + if (!watchers[i]) + return &watchers[i]; + } + + return NULL; +} + +/** + * Checks if there any watchers registered (to determine if it makes sense to still shim the driver_register()) + */ +static bool has_any_watchers(void) +{ + for (int i=0; i < MAX_WATCHERS; ++i) { + if (watchers[i]) + return true; + } + + return false; +} + +/** + * Calls the original driver_register() with error handling + * + * @return 0 on success, -E on error + */ +static int call_original_driver_register(struct device_driver *drv) +{ + int driver_register_out, org_call_out; + org_call_out = call_overridden_symbol(driver_register_out, ov_driver_register, drv); + + if (unlikely(org_call_out != 0)) { + pr_loc_err("Failed to call original %s (error=%d)", WATCH_FUNCTION, org_call_out); + return org_call_out; + } + + return driver_register_out; +} + +/** + * Replacement for driver_register(), executing registered hooks + */ +static int driver_register_shim(struct device_driver *drv) +{ + driver_watcher_instance **watcher_lptr = match_watcher(drv->name); + int driver_load_result; + bool driver_register_fulfilled = false; + + if (unlikely(!watcher_lptr)) { + pr_loc_dbg("%s() interception active - no handler observing \"%s\" found, calling original %s()", + WATCH_FUNCTION, drv->name, WATCH_FUNCTION); + return call_original_driver_register(drv); + } + + pr_loc_dbg("%s() interception active - calling handler %pF<%p> for \"%s\"", WATCH_FUNCTION, (*watcher_lptr)->cb, + (*watcher_lptr)->cb, drv->name); + + if ((*watcher_lptr)->notify_coming) { + pr_loc_dbg("Calling for DWATCH_STATE_COMING"); + switch ((*watcher_lptr)->cb(drv, DWATCH_STATE_COMING)) { + //CONTINUE and DONE cannot use fall-through as we cannot unregister watcher before calling it (as if this is the + // last watcher the whole override will be stopped + case DWATCH_NOTIFY_CONTINUE: + pr_loc_dbg("Calling original %s() & leaving watcher active", WATCH_FUNCTION); + driver_load_result = call_original_driver_register(drv); + driver_register_fulfilled = true; + break; + case DWATCH_NOTIFY_DONE: + pr_loc_dbg("Calling original %s() & removing watcher", WATCH_FUNCTION); + driver_load_result = call_original_driver_register(drv); + unwatch_driver_register(*watcher_lptr); //regardless of the call result we unregister + return driver_load_result; //we return here as the watcher doesn't want to be bothered anymore + case DWATCH_NOTIFY_ABORT_OK: + pr_loc_dbg("Faking OK return of %s() per callback request", WATCH_FUNCTION); + driver_load_result = 0; + driver_register_fulfilled = true; + break; + case DWATCH_NOTIFY_ABORT_BUSY: + pr_loc_dbg("Faking BUSY return of %s() per callback request", WATCH_FUNCTION); + driver_load_result = -EBUSY; + driver_register_fulfilled = true; + break; + default: //This should never happen if the callback is correct + pr_loc_bug("%s callback %pF<%p> returned invalid status value during DWATCH_STATE_COMING", + WATCH_FUNCTION, (*watcher_lptr)->cb, (*watcher_lptr)->cb); + } + } + + if (!driver_register_fulfilled) + driver_load_result = call_original_driver_register(drv); + + if (driver_load_result != 0) { + pr_loc_err("%s driver failed to load - not triggering STATE_LIVE callbacks", drv->name); + return driver_load_result; + } + + if ((*watcher_lptr)->notify_live) { + pr_loc_dbg("Calling for DWATCH_STATE_LIVE"); + if ((*watcher_lptr)->cb(drv, DWATCH_STATE_LIVE) == DWATCH_NOTIFY_DONE) + unwatch_driver_register(*watcher_lptr); + } + + return driver_load_result; +} + +/** + * Enables override of driver_register() to watch for new drivers registration + * + * @return 0 on success, or -E on error + */ +static int start_watching(void) +{ + if (unlikely(ov_driver_register)) { + pr_loc_bug("Watching is already enabled!"); + return 0; + } + + pr_loc_dbg("Starting intercept of %s()", WATCH_FUNCTION); + ov_driver_register = override_symbol(WATCH_FUNCTION, driver_register_shim); + if (unlikely(IS_ERR(ov_driver_register))) { + pr_loc_err("Failed to intercept %s() - error=%ld", WATCH_FUNCTION, PTR_ERR(ov_driver_register)); + ov_driver_register = NULL; + return -EINVAL; + } + pr_loc_dbg("%s() is now intercepted", WATCH_FUNCTION); + + return 0; +} + +/** + * Disables override of driver_register(), started by start_watching() + * + * @return 0 on success, or -E on error + */ +static int stop_watching(void) +{ + if (unlikely(!ov_driver_register)) { + pr_loc_bug("Watching is NOT enabled"); + return 0; + } + + pr_loc_dbg("Stopping intercept of %s()", WATCH_FUNCTION); + int out = restore_symbol(ov_driver_register); + if (unlikely(out != 0)) { + pr_loc_err("Failed to restore %s() - error=%ld", WATCH_FUNCTION, PTR_ERR(ov_driver_register)); + return out; + } + pr_loc_dbg("Intercept of %s() stopped", WATCH_FUNCTION); + + return 0; +} + +driver_watcher_instance *watch_driver_register(const char *name, watch_dr_callback *cb, int event_mask) +{ + driver_watcher_instance **watcher_lptr = match_watcher(name); + if (unlikely(watcher_lptr)) { + pr_loc_err("Watcher for %s already exists (callback=%pF<%p>)", name, (*watcher_lptr)->cb, (*watcher_lptr)->cb); + return ERR_PTR(-EEXIST); + } + + watcher_lptr = watcher_list_spot(); + if (unlikely(!watcher_lptr)) { + pr_loc_bug("There are no free spots for a new watcher"); + return ERR_PTR(-ENOSPC); + } + + kmalloc_or_exit_ptr(*watcher_lptr, sizeof(driver_watcher_instance) + strsize(name)); + strcpy((*watcher_lptr)->name, name); + (*watcher_lptr)->cb = cb; + (*watcher_lptr)->notify_coming = ((event_mask & DWATCH_STATE_COMING) == DWATCH_STATE_COMING); + (*watcher_lptr)->notify_live = ((event_mask & DWATCH_STATE_LIVE) == DWATCH_STATE_LIVE); + pr_loc_dbg("Registered %s() watcher for \"%s\" driver (coming=%d, live=%d)", WATCH_FUNCTION, name, + (*watcher_lptr)->notify_coming ? 1 : 0, (*watcher_lptr)->notify_live ? 1 : 0); + + if (!ov_driver_register) { + pr_loc_dbg("Registered the first driver_register watcher - starting watching"); + int out = start_watching(); + if (unlikely(out != 0)) + return ERR_PTR(out); + } + + return *watcher_lptr; +} + +int unwatch_driver_register(driver_watcher_instance *instance) +{ + driver_watcher_instance **matched_lptr = match_watcher(instance->name); + if (unlikely(!matched_lptr)) { + //This means it could be a double-unwatch situation and this will prevent a double-kfree (but the lack of crash + // is not guaranteed as match_watcher() already touched the memory) + pr_loc_bug("Watcher %p for %s couldn't be found in the watchers list", instance, instance->name); + return -ENOENT; + } + + if (unlikely(*matched_lptr != instance)) { + pr_loc_bug("Watcher %p for %s was found but the instance on the list %p (@%p) isn't the same (?!)", instance, + instance->name, *matched_lptr, matched_lptr); + return -EINVAL; + } + + pr_loc_dbg("Removed %pF<%p> subscriber for \"%s\" driver", (*matched_lptr)->cb, (*matched_lptr)->cb, + (*matched_lptr)->name); + kfree(*matched_lptr); + *matched_lptr = NULL; + + if (!has_any_watchers()) { + pr_loc_dbg("Removed last %s() subscriber - unshimming %s()", WATCH_FUNCTION, WATCH_FUNCTION); + int out; + if ((out = stop_watching()) != 0) + return out; + } + + return 0; +} + +int is_driver_registered(const char *name, struct bus_type *bus) +{ + if (!bus) + bus = &platform_bus_type; + + struct device_driver *drv = driver_find(name, bus); + if (IS_ERR(drv)) + return PTR_ERR(drv); + + return drv ? 1:0; +} \ No newline at end of file diff --git a/internal/intercept_driver_register.h b/internal/intercept_driver_register.h new file mode 100644 index 0000000..fbd8c86 --- /dev/null +++ b/internal/intercept_driver_register.h @@ -0,0 +1,59 @@ +#ifndef REDPILL_DRIVER_WATCHER_H +#define REDPILL_DRIVER_WATCHER_H + +#include //struct device_driver, driver_find (in .c) + +/** + * Codes which the callback call on watch can return + */ +typedef enum { + DWATCH_NOTIFY_CONTINUE, //callback processed the data and allows for the chain to continue + DWATCH_NOTIFY_DONE, //callback processed the data, allows for the chain to continue but wants to unregister + DWATCH_NOTIFY_ABORT_OK, //callback processed the data and determined that fake-OK should be returned to the original caller (DWATCH_STATE_COMING only) + DWATCH_NOTIFY_ABORT_BUSY, //callback processed the data and determined that fake-EBUSY should be returned to the original caller (DWATCH_STATE_COMING only) +} driver_watch_notify_result; + +/** + * Controls when the callback for loaded driver is called + */ +typedef enum { + DWATCH_STATE_COMING = 0b100, //driver is loading, you can intercept the process using (DWATCH_NOTIFY_ABORT_*) and change data + DWATCH_STATE_LIVE = 0b010, //driver just loaded +} driver_watch_notify_state; + +typedef struct driver_watcher_instance driver_watcher_instance; +typedef driver_watch_notify_result (watch_dr_callback)(struct device_driver *drv, driver_watch_notify_state event); + +/** + * Start watching for a driver registration + * + * Note: if the driver is already loaded this will do nothing, unless the driver is removed and re-registers. You should + * probably call is_driver_registered() first. + * + * @param name Name of the driver you want to observe + * @param cb Callback called on an event + * @param event_mask ORed driver_watch_notify_state flags to when the callback is called + * + * @return 0 on success, -E on error + */ +driver_watcher_instance *watch_driver_register(const char *name, watch_dr_callback *cb, int event_mask); + +/** + * Undoes what watch_driver_register() did + * + * @return 0 on success, -E on error + */ +int unwatch_driver_register(driver_watcher_instance *instance); + +/** + * Checks if a given driver exists + * + * Usually if the driver exists already it doesn't make sense to watch for it as the event will never be triggered + * (unless the driver unregisters and registers again). If the bus is not specified here (NULL) a platform-driver will + * be looked up (aka legacy driver). + * + * @return 0 if the driver is not registered, 1 if the driver is registered, -E on lookup error + */ +int is_driver_registered(const char *name, struct bus_type *bus); + +#endif //REDPILL_DRIVER_WATCHER_H diff --git a/internal/intercept_execve.c b/internal/intercept_execve.c new file mode 100644 index 0000000..5df155e --- /dev/null +++ b/internal/intercept_execve.c @@ -0,0 +1,145 @@ +/* + * Submodule used to hook the execve() syscall, used by the userland to execute binaries. + * + * This submodule can currently block calls to specific binaries and fake a successful return of the execution. In the + * future, if needed, an option to fake certain response and/or execute a different binary instead can be easily added + * here. + * + * execve() is a rather special syscall. This submodule utilized override_symbool.c:override_syscall() to do the actual + * ground work of replacing the call. However some syscalls (execve, fork, etc.) use ASM stubs with a non-GCC call + * convention. Up until Linux v3.18 it wasn't a problem as long as the stub was called back. However, since v3.18 the + * stub was changed in such a way that calling it using a normal convention from (i.e. from the shim here) will cause + * IRET imbalance and a crash. This is worked around by skipping the whole stub and calling do_execve() with a filename + * struct directly. This requires re-exported versions of these functions, so it may be marginally slower. + * Because of that this trick is only utilized on Linux >v3.18 and older ones call the stub as normal. + * + * References: + * - https://github.com/torvalds/linux/commit/b645af2d5905c4e32399005b867987919cbfc3ae + * - https://my.oschina.net/macwe/blog/603583 + * - https://stackoverflow.com/questions/8372912/hooking-sys-execve-on-linux-3-x + */ +#include "intercept_execve.h" +#include "../common.h" +#include +#include //struct filename +#include "override/override_syscall.h" //SYSCALL_SHIM_DEFINE3, override_symbol +#include "call_protected.h" //do_execve(), getname(), putname() + +#ifdef RPDBG_EXECVE +#include "../debug/debug_execve.h" +#endif + +#define MAX_INTERCEPTED_FILES 10 + +static char * intercepted_filenames[MAX_INTERCEPTED_FILES] = { NULL }; + +int add_blocked_execve_filename(const char *filename) +{ + if (unlikely(strlen(filename) > PATH_MAX)) + return -ENAMETOOLONG; + + unsigned int idx = 0; + while (likely(intercepted_filenames[idx])) { //Find free spot + if (unlikely(strcmp(filename, intercepted_filenames[idx]) == 0)) { //Does it exist already? + pr_loc_bug("File %s was already added at %d", filename, idx); + return -EEXIST; + } + + if(unlikely(++idx >= MAX_INTERCEPTED_FILES)) { //Are we out of indexes? + pr_loc_bug("Tried to add %d intercepted filename (max=%d)", idx, MAX_INTERCEPTED_FILES); + return -ENOMEM; + } + } + + kmalloc_or_exit_int(intercepted_filenames[idx], strsize(filename)); + strcpy(intercepted_filenames[idx], filename); //Size checked above + + pr_loc_inf("Filename %s will be blocked from execution", filename); + return 0; +} + +SYSCALL_SHIM_DEFINE3(execve, + const char __user *, filename, + const char __user *const __user *, argv, + const char __user *const __user *, envp) +{ + struct filename *path = _getname(filename); + + //this is essentially what do_execve() (or SYSCALL_DEFINE3 on older kernels) will do if the getname ptr is invalid + if (IS_ERR(path)) + return PTR_ERR(path); + + const char *pathname = path->name; +#ifdef RPDBG_EXECVE + RPDBG_print_execve_call(pathname, argv); +#endif + + for (int i = 0; i < MAX_INTERCEPTED_FILES; i++) { + if (!intercepted_filenames[i]) + break; + + if (unlikely(strcmp(pathname, intercepted_filenames[i]) == 0)) { + pr_loc_inf("Blocked %s from running", pathname); + //We cannot just return 0 here - execve() *does NOT* return on success, but replaces the current process ctx + do_exit(0); + } + } + +//Depending on the version of the kernel do_execve() accepts bare filename (old) or the full struct filename (newer) +//Additionally in older kernels we need to take care of the path lifetime and put it back (it's automatic in newer) +//See: https://github.com/torvalds/linux/commit/c4ad8f98bef77c7356aa6a9ad9188a6acc6b849d +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) + int out = _do_execve(pathname, argv, envp); + _putname(path); + return out; +#else + return _do_execve(path, argv, envp); +#endif +} + +static override_symbol_inst *sys_execve_ovs = NULL; +int register_execve_interceptor() +{ + pr_loc_dbg("Registering execve() interceptor"); + + if (sys_execve_ovs) { + pr_loc_bug("Called %s() while execve() interceptor is already registered", __FUNCTION__); + return -EEXIST; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) + override_symbol_or_exit_int(sys_execve_ovs, "SyS_execve", SyS_execve_shim); +#else + // TODO there is another __ia32_sys_execve, maybe need to override. + override_symbol_or_exit_int(sys_execve_ovs, "__x64_sys_execve", SyS_execve_shim); +#endif + + pr_loc_inf("execve() interceptor registered"); + return 0; +} + +int unregister_execve_interceptor() +{ + pr_loc_dbg("Unregistering execve() interceptor"); + + if (!sys_execve_ovs) { + pr_loc_bug("Called %s() while execve() interceptor is not registered (yet?)", __FUNCTION__); + return -ENXIO; + } + + int out = restore_symbol(sys_execve_ovs); + if (out != 0) + return out; + sys_execve_ovs = NULL; + + //Free all strings duplicated in add_blocked_execve_filename() + unsigned int idx = 0; + while (idx < MAX_INTERCEPTED_FILES-1 && intercepted_filenames[idx]) { + kfree(intercepted_filenames[idx]); + intercepted_filenames[idx] = NULL; + idx++; + } + + pr_loc_inf("execve() interceptor unregistered"); + return 0; +} diff --git a/internal/intercept_execve.h b/internal/intercept_execve.h new file mode 100644 index 0000000..8e901f1 --- /dev/null +++ b/internal/intercept_execve.h @@ -0,0 +1,9 @@ +#ifndef REDPILL_INTERCEPT_EXECVE_H +#define REDPILL_INTERCEPT_EXECVE_H + +//There's no remove_ as this requires rearranging the list etc and is not needed for now +int add_blocked_execve_filename(const char * filename); +int register_execve_interceptor(void); +int unregister_execve_interceptor(void); + +#endif //REDPILL_INTERCEPT_EXECVE_H diff --git a/internal/ioscheduler_fixer.c b/internal/ioscheduler_fixer.c new file mode 100644 index 0000000..6c1405e --- /dev/null +++ b/internal/ioscheduler_fixer.c @@ -0,0 +1,26 @@ +/** + * This very simple submodule which prevents kernel log from being flooded with "I/O scheduler elevator not found" + * + * When this shim is loaded as a I/O scheduler (to load very early) it is being set as a I/O scheduler. As we later + * remove the module file the system will constantly try to load now non-existing module "elevator-iosched". By + * resetting the "chosen_elevator" using the same function called by "elevator=" handler we can pretend no custom + * I/O scheduler was ever set (so that the system uses default one and stops complaining) + */ +#include "ioscheduler_fixer.h" +#include "../common.h" +#include "call_protected.h" //is_system_booting(), elevator_setup() +#include //system_state + +#define SHIM_NAME "I/O scheduler fixer" + +int reset_elevator(void) +{ + if (!is_system_booting()) { + pr_loc_wrn("Cannot reset I/O scheduler / elevator= set - system is past booting stage (state=%d)", + system_state); + return 0; //This is not an error technically speaking + } + + pr_loc_dbg("Resetting I/O scheduler to default"); + return _elevator_setup("") == 1 ? 0 : -EINVAL; +} \ No newline at end of file diff --git a/internal/ioscheduler_fixer.h b/internal/ioscheduler_fixer.h new file mode 100644 index 0000000..728f789 --- /dev/null +++ b/internal/ioscheduler_fixer.h @@ -0,0 +1,6 @@ +#ifndef REDPILL_IOSCHEDULER_FIXER_H +#define REDPILL_IOSCHEDULER_FIXER_H + +int reset_elevator(void); + +#endif //REDPILL_IOSCHEDULER_FIXER_H diff --git a/internal/notifier_base.h b/internal/notifier_base.h new file mode 100644 index 0000000..57e2fab --- /dev/null +++ b/internal/notifier_base.h @@ -0,0 +1,13 @@ +#ifndef REDPILL_NOTIFIER_BASE_H +#define REDPILL_NOTIFIER_BASE_H + +#define notifier_reg_in() pr_loc_dbg("Registering %s notifier", NOTIFIER_NAME); +#define notifier_reg_ok() pr_loc_inf("Successfully registered %s notifier", NOTIFIER_NAME); +#define notifier_ureg_in() pr_loc_dbg("Unregistering %s notifier", NOTIFIER_NAME); +#define notifier_ureg_ok() pr_loc_inf("Successfully unregistered %s notifier", NOTIFIER_NAME); +#define notifier_sub(nb) \ + pr_loc_dbg("%pF (priority=%d) subscribed to %s events", (nb)->notifier_call, (nb)->priority, NOTIFIER_NAME); +#define notifier_unsub(nb) \ + pr_loc_dbg("%pF (priority=%d) unsubscribed from %s events", (nb)->notifier_call, (nb)->priority, NOTIFIER_NAME); + +#endif //REDPILL_NOTIFIER_BASE_H diff --git a/internal/override/override_symbol.c b/internal/override/override_symbol.c new file mode 100644 index 0000000..8a1bae5 --- /dev/null +++ b/internal/override/override_symbol.c @@ -0,0 +1,307 @@ +/** + * This little (and dangerous) utility allows for replacement of any arbitrary kernel symbols with your own + * + * Since we're in the kernel we can do anything we want. This also included manipulating the actual code of functions + * executed by the kernel. So, if someone calls printk() it normally goes to the correct place. However this place can + * be override with a snippet of ASM which jumps to another place - a place we specify. It doesn't require a genius to + * understand the power and implication of this ;) + * + * HOW IT WORKS? + * See header file for example of usage. In short this code does the following: + * 0. Kernel protects .text pages (r/o by default, so you don't override the code by accident): they need to be unlocked + * 1. Find where our symbol-to-be-replaced is located + * 2. Disable memory pages write protection (as symbols are in .text which is ) + * 4. Make memory page containing symbol-to-be-replaced r/w + * 5. Generate jump code ASM containing the address of new symbol specified by the caller + * 6. Mark the memory page from [4] r/o again + * 7. [optional] Process is fully reversible + * + * SYSCALL SPECIAL CASE + * There's also a variant made for syscalls specifically. It differs by the fact that override_symbol() makes + * the original code unusable (as the first bytes are replaced with a jump) yet allows you to replace ANY function. The + * overridden_syscall() in the other hand changes a pointer in the syscalls table. That way you CAN use the original + * pointer to call back the original Linux syscall code you replaced. It works roughly like so: + * 0. Kernel keeps syscalls table in .data section which is marked as r/o: it needs to be found & unlocked (#2-4 above) + * 1. replace pointer in the table with custom one + * 2. relock memory + * + * CALLING THE ORIGINAL CODE PROBLEM + * When we wrote this code intially it was meant to be a temporary stop-gap until we have time to write a proper + * rerouting using kernel's "insn" framework. However, this approach only looks simple on the surface. In theory we just + * need to override the function preamble with a simple trampoline consisting of MOV+JMP to our new code. This is rather + * simple and work well. However, attempting to call the original code without restoring the full function to its + * original shape opens a huge can of worms with many edge-cases. Again, in *theory* we can simply grab the original + * preamble, attach a JMP to the original function just after the preamble, and execute it.. it will work MOST of the + * time, but: + * - we must ensure we round copied preamble to full instruction + * - trampoline must be automatically padded with NOP-sled + * - if function has ANY arguments (and most do) we need to take care of fixing the stack or saving preamble with all + * pushes? + * - overriden function may be shorter than trampoline (ok, we don't handle this even now, but it's unlikely) + * - and the biggest one: RIP. Some instructions are execution-point addressed (e.g. jump -5 bytes from here). + * Detecting that for the preamble and blocking override of such function (or EVEN fixing that RIP/EIP addressing) is + * rather possible. However, what becomes a problem are backward jumps in the code following the preamble. If the + * code after the preamble jumps backwards and lands in our trampoline instead of the original preamble it will + * either jump into a "random" place or jump to the replacement function. This is not that unlikely if the function + * is a short loop and nothing else. Trying to find such bug would be nightmare and we don't see a sane way of + * scanning the whole function and determining if it has any negative RIPs/EIPs and if they happen to fall within + * preamble. It's a mess with maaaany traps. While kernel has kprobes and fprobes we cannot use them as they're not + * enabled in syno kernels. + * + * We decided to compromise. The code offers a special call_overridden_symbol(). It follows a very similar process to + * restore_symbol()+override_symbol(). Normally the restoration [R] + override [O] process chain will look like so: + * 1. [R] Disable CR0 + * 2. [R] Unlock memory page(s) where trampoline lies + * 3. [R] Copy original preamble over trampoline + * 4. [R] Lock memory page(s) with preamble + * 5. [R] Enable CR0 + * 6. Call original + * 7. [O] Disable CR0 + * 8. [R] Unlock memory page(s) where we want to copy the trampoline + * 9. [R] Copy original trampoline over original preamble + * 10. [R] Lock memory page(s) with trampoline + * 11. [R] Enable CR0 + * + * The call_overridden_symbol() obviously has to disable CR0 and unlock memory but it LEAVES the memory unlocked for any + * subsequent calls. While it's less safe (as something can accidentally override it will not be reported) it shortens + * the call path for 2nd and beyond calls to the original: + * 1. Check if memory needs to be unlocked + * 2. [O] Copy original preamble over trampoline + * 3. Call original + * 4. [R] Copy original trampoline over original preamble + * + * Using call_overridden_symbol() thus has huge advantages over override+restore if you plan to call the original + * function more than once. If you want to call it only once the call_overridden_symbol() is an equivalent of restore+ + * override. That's why, for readability reasons and DRY of checking code it's preferred to use call_overridden_symbol() + * even if you call the original method even once. + * There's a third method: utilizing forceful breakpoints like kprobe does. However, this is a rather complex system and + * also contains many traps. Additionally, its overhead is no smaller than the current call_overridden_symbol() + * implementation. The kernel uses breakpoints for more safety and to detect possible interactions between different + * subsystems utilizing breakpoints. This isn't our concern here. + * + * References: + * - https://www.cs.uaf.edu/2016/fall/cs301/lecture/09_28_machinecode.html + * - http://www.watson.org/%7Erobert/2007woot/2007usenixwoot-exploitingconcurrency.pdf + * - https://stackoverflow.com/a/5711253 + * - https://www.kernel.org/doc/Documentation/kprobes.txt + * - https://stackoverflow.com/a/6742086 + */ + +#include "override_symbol.h" +#include "../../common.h" +#include "../helper/memory_helper.h" //set_mem_addr_ro(), set_mem_addr_rw() +#include "../helper/symbol_helper.h" //kln_func +#include //memcpy() + +#define JUMP_ADDR_POS 2 //JUMP starts at [2] in the jump template below +#define OVERRIDE_JUMP_SIZE 1 + 1 + 8 + 1 + 1 //MOVQ + %rax + $vaddr + JMP + *%rax +static const unsigned char jump_tpl[OVERRIDE_JUMP_SIZE] = + "\x48\xb8" "\x00\x00\x00\x00\x00\x00\x00\x00" /* MOVQ 64-bit-vaddr, %rax */ + "\xff\xe0" /* JMP *%rax */ +; + +#define WITH_OVS_LOCK(__sym, code) \ + do { \ + pr_loc_dbg("Obtaining lock for <%pF/%p>", (__sym)->org_sym_ptr, (__sym)->org_sym_ptr); \ + spin_lock_irqsave(&(__sym)->lock, (__sym)->lock_irq); \ + ({code}); \ + spin_unlock_irqrestore(&(__sym)->lock, (__sym)->lock_irq); \ + pr_loc_dbg("Released lock for <%p>", (__sym)->org_sym_ptr); \ + } while(0) + +struct override_symbol_inst { + void *org_sym_ptr; + const void *new_sym_ptr; + char org_sym_code[OVERRIDE_JUMP_SIZE]; + char trampoline[OVERRIDE_JUMP_SIZE]; + spinlock_t lock; + unsigned long lock_irq; + bool installed:1; //whether the symbol is currently overrode (=has trampoline installed) + bool has_trampoline:1; //does this structure contain a valid trampoline code already? + bool mem_protected:1; //is the trampoline installation site memory-protected? + char name[]; +}; + +/** + * Wrapper for set_mem_addr_rw() which works with symbols + */ +static void __always_inline set_symbol_rw(struct override_symbol_inst *sym) +{ + set_mem_addr_rw((unsigned long)sym->org_sym_ptr, OVERRIDE_JUMP_SIZE); + sym->mem_protected = false; +} + +/** + * Wrapper for set_mem_addr_ro() which works with symbols + */ +static void __always_inline set_symbol_ro(struct override_symbol_inst *sym) +{ + set_mem_addr_ro((unsigned long)sym->org_sym_ptr, OVERRIDE_JUMP_SIZE); + sym->mem_protected = true; +} + +void put_overridden_symbol(struct override_symbol_inst *sym) +{ + pr_loc_dbg("Freeing OVS for %s", sym->name); + kfree(sym); +} + +/** + * Initializes new "override symbol instance" structure + * + * @return ptr to struct override_symbol_inst or ERR_PTR(-E) on error + */ +static struct override_symbol_inst* get_ov_symbol_instance(const char *symbol_name, const void *new_sym_ptr) +{ + struct override_symbol_inst *sym; + kmalloc_or_exit_ptr(sym, sizeof(struct override_symbol_inst) + strsize(symbol_name)); + + sym->new_sym_ptr = new_sym_ptr; + spin_lock_init(&sym->lock); + sym->installed = false; + sym->has_trampoline = false; + sym->mem_protected = true; + strcpy(sym->name, symbol_name); + sym->org_sym_ptr = (void *)kln_func(sym->name); + if (unlikely(sym->org_sym_ptr == 0)) { //header file: "Lookup the address for a symbol. Returns 0 if not found." + pr_loc_err("Failed to locate vaddr for %s()", sym->name); + put_overridden_symbol(sym); + return ERR_PTR(-EFAULT); + } + pr_loc_dbg("Saved %s() ptr <%p>", sym->name, sym->org_sym_ptr); + + return sym; +} + +/** + * Generates trampoline code to jump from old symbol to the new symbol location and saves the original code + */ +static inline void prepare_trampoline(struct override_symbol_inst *sym) +{ + pr_loc_dbg("Generating trampoline"); + + //First generate jump/trampoline to new_sym_ptr + memcpy(sym->trampoline, jump_tpl, OVERRIDE_JUMP_SIZE); //copy "empty" trampoline + *(long *)&sym->trampoline[JUMP_ADDR_POS] = (long)sym->new_sym_ptr; //paste new addr into trampoline + pr_loc_dbg("Generated trampoline to %pF<%p> for %s<%p>: ", sym->new_sym_ptr, sym->new_sym_ptr, sym->name, + sym->org_sym_ptr); + + memcpy(sym->org_sym_code, sym->org_sym_ptr, OVERRIDE_JUMP_SIZE); //Backup old code + sym->has_trampoline = true; +} + +/** + * Enables (previously disabled) symbol override, disabling memory barriers if needed & leaving them disabled upon exit + * + * Warning: this function is exported only to make universal call original macros working. You should NOT use it outside + * of this submodule + * + * @return 0 on success, -E on error + */ +int __enable_symbol_override(struct override_symbol_inst *sym) +{ + if (sym->mem_protected) + set_symbol_rw(sym); + + WITH_OVS_LOCK(sym, + if (likely(!sym->installed)) { + if (!sym->has_trampoline) + prepare_trampoline(sym); + + //after we got the lock need to re-check the memory protection - this shouldn't be changed within spinlock + //since it generates a warning... but sometimes we have no choice + if (sym->mem_protected) + set_symbol_rw(sym); + + pr_loc_dbg("Writing trampoline code to <%p>", sym->org_sym_ptr); + memcpy(sym->org_sym_ptr, sym->trampoline, OVERRIDE_JUMP_SIZE); + sym->installed = true; + } + ); + + return 0; +} + +/** + * Disables (previously enables) symbol override, disabling memory barriers if needed & leaving them disabled upon exit + * + * Warning: this function is exported only to make universal call original macros working. You should NOT use it outside + * of this submodule + * + * @return 0 on success, -E on error + */ +int __disable_symbol_override(struct override_symbol_inst *sym) +{ + if (sym->mem_protected) + set_symbol_rw(sym); + + WITH_OVS_LOCK(sym, + if (likely(sym->installed)) { + //after we got the lock need to re-check the memory protection - this shouldn't be changed within spinlock + //since it generates a warning... but sometimes we have no choice + if (sym->mem_protected) + set_symbol_rw(sym); + + pr_loc_dbg("Writing original code to <%p>", sym->org_sym_ptr); + memcpy(sym->org_sym_ptr, sym->org_sym_code, OVERRIDE_JUMP_SIZE); + sym->installed = false; + } + ); + + return 0; +} + +struct override_symbol_inst* __must_check override_symbol(const char *name, const void *new_sym_ptr) +{ + pr_loc_dbg("Overriding %s() with %pf()<%p>", name, new_sym_ptr, new_sym_ptr); + + int out; + struct override_symbol_inst *sym = get_ov_symbol_instance(name, new_sym_ptr); + if (unlikely(IS_ERR(sym))) + return sym; + + if ((out = __enable_symbol_override(sym)) != 0) + goto error_out; + + set_symbol_ro(sym); //by design standard override leaves the memory protected + + pr_loc_dbg("Successfully overrode %s() with trampoline to %pF<%p>", sym->name, sym->new_sym_ptr, sym->new_sym_ptr); + return sym; + + error_out: + put_overridden_symbol(sym); + return ERR_PTR(out); +} + +int restore_symbol(struct override_symbol_inst *sym) +{ + pr_loc_dbg("Restoring %s<%p> to original code", sym->name, sym->org_sym_ptr); + + int out; + if ((out = __disable_symbol_override(sym)) != 0) + goto out_free; + + set_symbol_ro(sym); //by design restore leaves the memory protected + + pr_loc_dbg("Successfully restored original code of %s", sym->name); + + out_free: + put_overridden_symbol(sym); + return out; +} + +/** + * Returns pointer to original symbol. This is a function made to avoid exposing internals of the struct to header. + */ +__always_inline void * __get_org_ptr(struct override_symbol_inst *sym) +{ + return sym->org_sym_ptr; +} + +/** + * Checks if override is enabled. This is a function made to avoid exposing internals of the struct to header. + */ +__always_inline bool symbol_is_overridden(struct override_symbol_inst *sym) +{ + return likely(sym) && sym->installed; +} diff --git a/internal/override/override_symbol.h b/internal/override/override_symbol.h new file mode 100644 index 0000000..b370ae8 --- /dev/null +++ b/internal/override/override_symbol.h @@ -0,0 +1,133 @@ +#ifndef REDPILLLKM_OVERRIDE_KFUNC_H +#define REDPILLLKM_OVERRIDE_KFUNC_H + +#include +#include //PTR_ERR, IS_ERR + +typedef struct override_symbol_inst override_symbol_inst; + +/************************************************* Current interface **************************************************/ +/** + * Calls the original symbol, returning nothing, that was previously overridden + * + * @param sym pointer to a override_symbol_inst + * @param ... any arguments to the original function + * + * @return 0 if the execution succeeded, -E if it didn't + */ +#define call_overridden_symbol_void(sym, ...) ({ \ + int __ret; \ + bool __was_installed = symbol_is_overridden(sym); \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wstrict-prototypes\"") \ + void (*__ptr)() = __get_org_ptr(sym); \ + _Pragma("GCC diagnostic pop") \ + __ret = __disable_symbol_override(sym); \ + if (likely(__ret == 0)) { \ + __ptr(__VA_ARGS__); \ + if (likely(__was_installed)) { \ + __ret = __enable_symbol_override(sym); \ + } \ + } \ + __ret; \ +}); + +/** + * Calls the original symbol, returning a value, that was previously overridden + * + * @param out_var name of the variable where original function return value should be placed + * @param sym pointer to a override_symbol_inst + * @param ... any arguments to the original function + * + * @return 0 if the execution succeeded, -E if it didn't + */ +#define call_overridden_symbol(out_var, sym, ...) ({ \ + int __ret; \ + bool __was_installed = symbol_is_overridden(sym); \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wstrict-prototypes\"") \ + typeof (out_var) (*__ptr)() = __get_org_ptr(sym); \ + _Pragma("GCC diagnostic pop") \ + __ret = __disable_symbol_override(sym); \ + if (likely(__ret == 0)) { \ + out_var = __ptr(__VA_ARGS__); \ + if (likely(__was_installed)) { \ + __ret = __enable_symbol_override(sym); \ + } \ + } \ + __ret; \ +}); + +/** + * override_symbol() with automatic error handling. See the original function for details. + * + * @param ptr_var Variable to store ovs pointer + */ +#define override_symbol_or_exit_int(ptr_var, name, new_sym_ptr) \ + (ptr_var) = override_symbol(name, new_sym_ptr); \ + if (unlikely(IS_ERR((ptr_var)))) { \ + int _err = PTR_ERR((ptr_var)); \ + pr_loc_err("Failed to override %s - error=%d", name, _err); \ + (ptr_var) = NULL; \ + return _err; \ + } \ + +/** + * Overrides a kernel symbol with something else of your choice + * + * @param name Name of the kernel symbol (function) to override + * @param new_sym_ptr An address/pointer to a new function + * + * @return Instance of override_symbol_inst struct pointer on success, ERR_PTR(-E) on error + * + * @example + * struct override_symbol_inst *ovi; + * int null_printk() { + * int print_res; + * call_overridden_symbol(print_res, ovi, "No print for you!"); + * return print_res; + * } + * ovi = override_symbol("printk", null_printk); + * if (IS_ERR(ovi)) { ... handle error ... } + * ... + * restore_symbol(backup_addr, backup_code); //restore backed-up copy of printk() + * + * @todo: This should be rewritten using INSN without inline ASM wizardy, but this is much more complex + */ +struct override_symbol_inst* __must_check override_symbol(const char *name, const void *new_sym_ptr); + +/** + * Restores symbol overridden by override_symbol() + * + * For details see override_symbol() docblock + * + * @return 0 on success, -E on error + */ +int restore_symbol(struct override_symbol_inst *sym); + +/** + * Frees the symbol previously reserved by get_ov_symbol_instance() (e.g. via override_symbol) + * + * !! READ THIS SERIOUS WARNING BELOW CAREFULLY !! + * STOP! DO NOT USE THIS if you don't understand what it does and why it exists. This function should be called from + * outside of this submodule ONLY if the overridden code disappeared from memory. This practically can happen only when + * you override a symbol inside of a loadable module and the module is unloaded. In ANY other case you must call + * restore_symbol() to actually restore the original code. This function simply "forgets" about the override and frees + * memory (as if external module has been unloaded we are NOT allowed to touch that memory anymore as it may be freed). + * It is explicitly NOT necessary to call this function after restore_symbol() as it does so internally. + */ +void put_overridden_symbol(struct override_symbol_inst *sym); + +/** + * Check if the given symbol override is currently active + */ +bool symbol_is_overridden(struct override_symbol_inst *sym); + + +/****************** Private helpers (should not be used directly by any code outside of this unit!) *******************/ +#include +int __enable_symbol_override(override_symbol_inst *sym); +int __disable_symbol_override(override_symbol_inst *sym); +void * __get_org_ptr(struct override_symbol_inst *sym); + +#endif //REDPILLLKM_OVERRIDE_KFUNC_H diff --git a/internal/override/override_syscall.c b/internal/override/override_syscall.c new file mode 100644 index 0000000..3c1f3b8 --- /dev/null +++ b/internal/override/override_syscall.c @@ -0,0 +1,168 @@ +#include "override_syscall.h" +#include "../../common.h" +#include "../helper/memory_helper.h" //set_mem_addr_ro(), set_mem_addr_rw() +#include //__NR_syscall_max & NR_syscalls +#include //syscalls numbers (e.g. __NR_read) +#include "../helper/symbol_helper.h" //kln_func + +static unsigned long *syscall_table_ptr = NULL; +static void print_syscall_table(unsigned int from, unsigned to) +{ + if (unlikely(!syscall_table_ptr)) { + pr_loc_dbg("Cannot print - no syscall_table_ptr address"); + return; + } + + if (unlikely(from < 0 || to > __NR_syscall_max || from > to)) { + pr_loc_bug("%s called with from=%d to=%d which are invalid", __FUNCTION__, from, to); + return; + } + + pr_loc_dbg("Printing syscall table %d-%d @ %p containing %d elements", from, to, (void *)syscall_table_ptr, NR_syscalls); + for (unsigned int i = from; i < to; i++) { + pr_loc_dbg("#%03d\t%pS", i, (void *)syscall_table_ptr[i]); + } +} + +static int find_sys_call_table(void) +{ + syscall_table_ptr = (unsigned long *)kln_func("sys_call_table"); + if (syscall_table_ptr != 0) { + pr_loc_dbg("Found sys_call_table @ <%p> using kallsyms", syscall_table_ptr); + return 0; + } + + //See https://kernelnewbies.kernelnewbies.narkive.com/L1uH0n8P/ + //In essence some systems will have it and some will not - finding it using kallsyms is the easiest and fastest + pr_loc_dbg("Failed to locate vaddr for sys_call_table using kallsyms - falling back to memory search"); + + /* + There's also the bruteforce way - scan through the memory until you find it :D + We know numbers for syscalls (e.g. __NR_close, __NR_write, __NR_read, etc.) which are essentially fixed positions + in the sys_call_table. We also know addresses of functions handling these calls (sys_close/sys_write/sys_read + etc.). This lets us scan the memory for one syscall address reference and when found confirm if this is really + a place of sys_call_table by verifying other 2-3 places to make sure other syscalls are where they should be + The huge downside of this method is it is slow as potentially the amount of memory to search may be large. + */ + unsigned long sys_close_ptr = kln_func("sys_close"); + unsigned long sys_open_ptr = kln_func("sys_open"); + unsigned long sys_read_ptr = kln_func("sys_read"); + unsigned long sys_write_ptr = kln_func("sys_write"); + if (sys_close_ptr == 0 || sys_open_ptr == 0 || sys_read_ptr == 0 || sys_write_ptr == 0) { + pr_loc_bug( + "One or more syscall handler addresses cannot be located: " + "sys_close<%p>, sys_open<%p>, sys_read<%p>, sys_write<%p>", + (void *)sys_close_ptr, (void *)sys_open_ptr, (void *)sys_read_ptr, (void *)sys_write_ptr); + return -EFAULT; + } + + /* + To speed up things a bit we search from a known syscall which was loaded early into the memory. To be safe we pick + the earliest address and go from there. It can be nicely visualized on a system which DO export sys_call_table + by running grep -E ' (__x64_)?sys_(close|open|read|write|call_table)$' /proc/kallsyms | sort + You will get something like that: + ffffffff860c18b0 T __x64_sys_close + ffffffff860c37a0 T __x64_sys_open + ffffffff860c7a80 T __x64_sys_read + ffffffff860c7ba0 T __x64_sys_write + ffffffff86e013a0 R sys_call_table <= it's way below any of the syscalls but not too far (~13,892,336 bytes) + */ + unsigned long i = sys_close_ptr; + if (sys_open_ptr < i) i = sys_open_ptr; + if (sys_read_ptr < i) i = sys_read_ptr; + if (sys_write_ptr < i) i = sys_write_ptr; + + //If everything goes well it should take ~1-2ms tops (which is slow in the kernel sense but it's not bad) + pr_loc_dbg("Scanning memory for sys_call_table starting at %p", (void *)i); + for (; i < ULONG_MAX; i += sizeof(void *)) { + syscall_table_ptr = (unsigned long *)i; + + if (unlikely( + syscall_table_ptr[__NR_close] == sys_close_ptr && + syscall_table_ptr[__NR_open] == sys_open_ptr && + syscall_table_ptr[__NR_read] == sys_read_ptr && + syscall_table_ptr[__NR_write] == sys_write_ptr + )) { + pr_loc_dbg("Found sys_call_table @ %p", (void *)syscall_table_ptr); + return 0; + } + } + + pr_loc_bug("Failed to find sys call table"); + syscall_table_ptr = NULL; + return -EFAULT; +} + +static unsigned long *overridden_syscall[NR_syscalls] = { NULL }; //@todo this should be alloced dynamically +int override_syscall(unsigned int syscall_num, const void *new_sysc_ptr, void * *org_sysc_ptr) +{ + pr_loc_dbg("Overriding syscall #%d with %pf()<%p>", syscall_num, new_sysc_ptr, new_sysc_ptr); + + int out = 0; + if (unlikely(!syscall_table_ptr)) { + out = find_sys_call_table(); + if (unlikely(out != 0)) + return out; + } + + if (unlikely(syscall_num > __NR_syscall_max)) { + pr_loc_bug("Invalid syscall number: %d > %d", syscall_num, __NR_syscall_max); + return -EINVAL; + } + + print_syscall_table(syscall_num-5, syscall_num+5); + + if (unlikely(overridden_syscall[syscall_num])) { + pr_loc_bug("Syscall %d is already overridden - will be replaced (bug?)", syscall_num); + } else { + //Only save original-original entry (not the override one) + overridden_syscall[syscall_num] = (unsigned long *)syscall_table_ptr[syscall_num]; + } + + if (org_sysc_ptr != 0) + *org_sysc_ptr = overridden_syscall[syscall_num]; + + set_mem_addr_rw((long)&syscall_table_ptr[syscall_num], sizeof(unsigned long)); + pr_loc_dbg("syscall #%d originally %ps<%p> will now be %ps<%p> @ %d", syscall_num, + (void *) overridden_syscall[syscall_num], (void *) overridden_syscall[syscall_num], new_sysc_ptr, + new_sysc_ptr, smp_processor_id()); + syscall_table_ptr[syscall_num] = (unsigned long) new_sysc_ptr; + set_mem_addr_ro((long)&syscall_table_ptr[syscall_num], sizeof(unsigned long)); + + print_syscall_table(syscall_num-5, syscall_num+5); + + return out; +} + +int restore_syscall(unsigned int syscall_num) +{ + pr_loc_dbg("Restoring syscall #%d", syscall_num); + + if (unlikely(!syscall_table_ptr)) { + pr_loc_bug("Syscall table not found in %s ?!", __FUNCTION__); + return -EFAULT; + } + + if (unlikely(syscall_num > __NR_syscall_max)) { + pr_loc_bug("Invalid syscall number: %d > %d", syscall_num, __NR_syscall_max); + return -EINVAL; + } + + if (unlikely(overridden_syscall[syscall_num] == 0)) { + pr_loc_bug("Syscall #%d cannot be restored - it was never overridden", syscall_num); + return -EINVAL; + } + + print_syscall_table(syscall_num-5, syscall_num+5); + + set_mem_addr_rw((long)&syscall_table_ptr[syscall_num], sizeof(unsigned long)); + pr_loc_dbg("Restoring syscall #%d from %ps<%p> to original %ps<%p>", syscall_num, + (void *) syscall_table_ptr[syscall_num], (void *) syscall_table_ptr[syscall_num], + (void *) overridden_syscall[syscall_num], (void *) overridden_syscall[syscall_num]); + syscall_table_ptr[syscall_num] = (unsigned long)overridden_syscall[syscall_num]; + set_mem_addr_rw((long)&syscall_table_ptr[syscall_num], sizeof(unsigned long)); + + print_syscall_table(syscall_num-5, syscall_num+5); + + return 0; +} \ No newline at end of file diff --git a/internal/override/override_syscall.h b/internal/override/override_syscall.h new file mode 100644 index 0000000..4d5c06c --- /dev/null +++ b/internal/override/override_syscall.h @@ -0,0 +1,59 @@ +#ifndef REDPILL_OVERRIDE_SYSCALL_H +#define REDPILL_OVERRIDE_SYSCALL_H + +#include "override_symbol.h" +#include + +//Modified syscall defines for shims based on native Linux syscalls (defined in linux/syscalls.h) +#define SYSCALL_SHIM_DEFINE1(name, ...) SYSCALL_SHIM_DEFINEx(1, _##name##_shim, __VA_ARGS__) +#define SYSCALL_SHIM_DEFINE2(name, ...) SYSCALL_SHIM_DEFINEx(2, _##name##_shim, __VA_ARGS__) +#define SYSCALL_SHIM_DEFINE3(name, ...) SYSCALL_SHIM_DEFINEx(3, _##name##_shim, __VA_ARGS__) +#define SYSCALL_SHIM_DEFINE4(name, ...) SYSCALL_SHIM_DEFINEx(4, _##name##_shim, __VA_ARGS__) +#define SYSCALL_SHIM_DEFINE5(name, ...) SYSCALL_SHIM_DEFINEx(5, _##name##_shim, __VA_ARGS__) +#define SYSCALL_SHIM_DEFINE6(name, ...) SYSCALL_SHIM_DEFINEx(6, _##name##_shim, __VA_ARGS__) +#define SYSCALL_SHIM_DEFINEx(x, name, ...) \ + static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + static asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ + long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ + __MAP(x,__SC_TEST,__VA_ARGS__); \ + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ + return ret; \ + } \ + static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + +/** + * Non-destructively overrides a syscall + * + * This produces an effect similar to override_symbol(). However, it should be faster, safer, and most importantly + * allows calling the original syscall in the override. + * + * Warning: DO NOT use this method to override stubbed syscalls. These are syscall which aren't named "sys_foo" (e.g. + * sys_execve or SyS_execve [alias]) but are handled by ASM stubs in arch/x86/kernel/entry_64.S (and visible as e.g. + * stub_execve). If you do override such call with a normal function in the syscall table things will start breaking + * unexpectedly as the registries will be modified in an unexpected way (stubs don't use cdecl)! + * In such cases you need to override the actual sys_* (or even better: SyS_*) function with a jump using + * override_symbol(). Either way you should use SYSCALL_SHIM_DEFINE#() to define the new target/shim. + * Make sure to read https://lwn.net/Articles/604287/ and https://lwn.net/Articles/604406/ + * + * @param syscall_num Number of the syscall to override (e.g. open) + * You can find them as __NR_* defines in arch/x86/include/generated/uapi/asm/unistd_64.h + * @param new_sysc_ptr An address/pointer to a new function + * @param org_sysc_ptr Pointer to some space to save address of the original syscall (warning: it's a pointer-pointer); + * You can pass a null-ptr if you don't care about the original syscall and the function will not + * touch it + * + * @return 0 on success, -E on error + */ +int override_syscall(unsigned int syscall_num, const void *new_sysc_ptr, void * *org_sysc_ptr); + +/** + * Restores the syscall previously replaced by override_syscall() + * + * For details see override_syscall() docblock. + * + * @return 0 on success, -E on error + */ +int restore_syscall(unsigned int syscall_num); + +#endif //REDPILL_OVERRIDE_SYSCALL_H diff --git a/internal/scsi/hdparam.h b/internal/scsi/hdparam.h new file mode 100644 index 0000000..c93e681 --- /dev/null +++ b/internal/scsi/hdparam.h @@ -0,0 +1,350 @@ +/** + * This file serves a similar role to include/uapi/linux/hdreg.h, combining constants & macros for dealing with ATA + */ +#include //HDIO_* +#include //ATA_ID_*, ATA_CMD_*, ATA_SECT_SIZE + +#ifndef REDPILL_HDPARAM_H +#define REDPILL_HDPARAM_H + +/********************************** Parameters related to HDIO_DRIVE_CMD ioctl call ***********************************/ +//the following constants contain size/offsets/indexes of "struct hd_drive_cmd_hdr" fields from user API +// also see HDIO_DRIVE_CMD in https://www.kernel.org/doc/Documentation/ioctl/hdio.txt +#define HDIO_DRIVE_CMD_HDR_OFFSET 4 //same as HDIO_DRIVE_CMD_HDR_SIZE but in sectors +#define HDIO_DRIVE_CMD_HDR_CMD 0 //command +#define HDIO_DRIVE_CMD_HDR_SEC_NUM 1 //sector number +#define HDIO_DRIVE_CMD_HDR_FEATURE 2 //feature +#define HDIO_DRIVE_CMD_HDR_SEC_CNT 3 //sector count + +#define HDIO_DRIVE_CMD_RET_STATUS 0 +#define HDIO_DRIVE_CMD_RET_ERROR 1 +#define HDIO_DRIVE_CMD_RET_SEC_CNT 2 //sector count + +//convert sector size of data section of an ATA (sub)command to the full buffer size with header +#define ata_ioctl_buf_size(data_sectors) (u16)(HDIO_DRIVE_CMD_HDR_SIZE+((data_sectors)*(ATA_SECT_SIZE*sizeof(u8)))) + +//Expected sizes of various commands/subcommands data sections +#define ATA_CMD_ID_ATA_SECTORS 1 +#define ATA_SMART_READ_VALUES_SECTORS 1 //subcommand of ATA_CMD_SMART +#define ATA_SMART_READ_THRESHOLDS_SECTORS 1 //subcommand of ATA_CMD_SMART +#define ATA_WIN_SMART_READ_LOG_SECTORS 1 //subcommand of ATA_CMD_SMART +#define ATA_WIN_SMART_EXEC_TEST 1 //subcommand of ATA_CMD_SMART + +/********************************** Parameters related to HDIO_DRIVE_TASK ioctl call **********************************/ +//another method of calling some ioctls +// see https://github.com/mirror/smartmontools/blob/b63206bc12efb2ae543040b9008f42c037eb1f04/os_linux.cpp#L379 +// also see HDIO_DRIVE_TASK in https://www.kernel.org/doc/Documentation/ioctl/hdio.txt +#define HDIO_DRIVE_TASK_HDR_OFFSET 7 +#define HDIO_DRIVE_TASK_HDR_CMD 0 //command code +#define HDIO_DRIVE_TASK_HDR_FEATURE 1 //feature +#define HDIO_DRIVE_TASK_HDR_SEC_CNT 2 //sector count +#define HDIO_DRIVE_TASK_HDR_SEC_NUM 3 //sector number +#define HDIO_DRIVE_TASK_HDR_LCYL 4 //CYL LO +#define HDIO_DRIVE_TASK_HDR_HCYL 5 //CYL HI +#define HDIO_DRIVE_TASK_HDR_SEL 6 //device head + +#define HDIO_DRIVE_TASK_RET_STATUS 0 +#define HDIO_DRIVE_TASK_RET_ERROR 1 +#define HDIO_DRIVE_TASK_RET_SEC_CNT 2 //sector count +#define HDIO_DRIVE_TASK_RET_SEC_NUM 3 //sector number +#define HDIO_DRIVE_TASK_RET_LCYL 4 //CYL LO +#define HDIO_DRIVE_TASK_RET_HCYL 5 //CYL HI +#define HDIO_DRIVE_TASK_RET_SEL 6 //device head + +//all WIN_FT_* entries are defined under "WIN_SMART sub-commands" in hdreg.h +#define WIN_CMD_SMART 0xb0 //defined in full linux headers as WIN_SMART in hdreg.h +#define WIN_FT_SMART_IMMEDIATE_OFFLINE 0xd4 +#define WIN_FT_SMART_READ_LOG_SECTOR 0xd5 +#define WIN_FT_SMART_STATUS 0xda +#define WIN_FT_SMART_AUTOSAVE 0xd2 //this is not a typo (AUTOSAVE and AUTO_OFFLINE are spelled differently in ATA spec) +#define WIN_FT_SMART_AUTO_OFFLINE 0xdb + +/*************************************** Params related to ATA IDENTIFY command ***************************************/ +//Word numbers for the ATA IDENTIFY command response fields & bits in them (described in "struct hd_driveid") +#define ATA_ID_COMMAND_SET_1_SMART 0x01 //first bit of command set #1 contains SMART supported flag +#define ATA_ID_COMMAND_SET_2_VALID 0x4000 //14th bit with should always be 1 when disk supports cmd set 2 +#define ATA_ID_CFS_ENABLE_1_SMART 0x01 //first bit of command set #1 contains SMART enable flag +#define ATA_ID_CSF_DEFAULT_VALID 0x4000 //14th bit with should always be 1 when disk supports that + +/************************************************* ATA IDENTIFY macros ************************************************/ +//These can be used with ATA IDENTIFY data returned by HDIO_GET_IDENTITY or HDIO_DRIVE_CMD=>ATA_CMD_IDENTIFY_DEV with +// when buffer is corrected by HDIO_DRIVE_CMD_HDR_OFFSET (to move over the header data) +#define ata_is_smart_supported(id_data) (((id_data)[ATA_ID_COMMAND_SET_2] & ATA_ID_COMMAND_SET_2_VALID) && \ + ((id_data)[ATA_ID_COMMAND_SET_1] & ATA_ID_COMMAND_SET_1_SMART)) + +#define ata_is_smart_enabled(id_data) (((id_data)[ATA_ID_CSF_DEFAULT] & ATA_ID_CSF_DEFAULT_VALID) && \ + ((id_data)[ATA_ID_CFS_ENABLE_1] & ATA_ID_CFS_ENABLE_1_SMART)) + +//set_/unset_ are deliberately asymmetrical here - we don't want to invalidate whole word when disabling SMART +#define ata_set_smart_supported(id_data) \ + do { \ + (id_data)[ATA_ID_COMMAND_SET_2] |= ATA_ID_COMMAND_SET_2_VALID; \ + (id_data)[ATA_ID_COMMAND_SET_1] |= ATA_ID_COMMAND_SET_1_SMART; \ + } while(0) +#define ata_reset_smart_supported(id_data) \ + do { \ + (id_data)[ATA_ID_COMMAND_SET_1] &= ~ATA_ID_COMMAND_SET_1_SMART; \ + } while(0) + +#define ata_set_smart_enabled(id_data) \ + do { \ + (id_data)[ATA_ID_CSF_DEFAULT] |= ATA_ID_CSF_DEFAULT_VALID; \ + (id_data)[ATA_ID_CFS_ENABLE_1] |= ATA_ID_CFS_ENABLE_1_SMART; \ + } while(0) +#define ata_reset_smart_enabled(id_data) \ + do { \ + (id_data)[ATA_ID_CFS_ENABLE_1] &= ~ATA_ID_CFS_ENABLE_1_SMART; \ + } while(0) + +/*********************************************** Miscellaneous constants **********************************************/ +#define ATA_SMART_RECORD_LEN 12 //length of the SMART snapshot data row in bytes, defined + +//Modified for kernel use - it's the "hd_driveid" struct from Linux include/uapi/linux/hdreg.h which represents a +// response to HDIO_GET_IDENTITY. See "Table 26 − IDENTIFY DEVICE information" in ATA/ATAPI-6 spec for details. +struct rp_hd_driveid { + u16 config; /* lots of obsolete bit flags */ + u16 cyls; /* Obsolete, "physical" cyls */ + u16 reserved2; /* reserved (word 2) */ + u16 heads; /* Obsolete, "physical" heads */ + u16 track_bytes; /* unformatted bytes per track */ + u16 sector_bytes; /* unformatted bytes per sector */ + u16 sectors; /* Obsolete, "physical" sectors per track */ + u16 vendor0; /* vendor unique */ + u16 vendor1; /* vendor unique */ + u16 vendor2; /* Retired vendor unique */ + u8 serial_no[20]; /* 0 = not_specified */ + u16 buf_type; /* Retired */ + u16 buf_size; /* Retired, 512 byte increments + * 0 = not_specified + */ + u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */ + u8 fw_rev[8]; /* 0 = not_specified */ + u8 model[40]; /* 0 = not_specified */ + u8 max_multsect; /* 0=not_implemented */ + u8 vendor3; /* vendor unique */ + u16 dword_io; /* 0=not_implemented; 1=implemented */ + u8 vendor4; /* vendor unique */ + u8 capability; /* (upper byte of word 49) + * 3: IORDYsup + * 2: IORDYsw + * 1: LBA + * 0: DMA + */ + u16 reserved50; /* reserved (word 50) */ + u8 vendor5; /* Obsolete, vendor unique */ + u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */ + u8 vendor6; /* Obsolete, vendor unique */ + u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */ + u16 field_valid; /* (word 53) + * 2: ultra_ok word 88 + * 1: eide_ok words 64-70 + * 0: cur_ok words 54-58 + */ + u16 cur_cyls; /* Obsolete, logical cylinders */ + u16 cur_heads; /* Obsolete, l heads */ + u16 cur_sectors; /* Obsolete, l sectors per track */ + u16 cur_capacity0; /* Obsolete, l total sectors on drive */ + u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */ + u8 multsect; /* current multiple sector count */ + u8 multsect_valid; /* when (bit0==1) multsect is ok */ + unsigned int lba_capacity; /* Obsolete, total number of sectors */ + u16 dma_1word; /* Obsolete, single-word dma info */ + u16 dma_mword; /* multiple-word dma info */ + u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */ + u16 eide_dma_min; /* min mword dma cycle time (ns) */ + u16 eide_dma_time; /* recommended mword dma cycle time (ns) */ + u16 eide_pio; /* min cycle time (ns), no IORDY */ + u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */ + u16 words69_70[2]; /* reserved words 69-70 + * future command overlap and queuing + */ + u16 words71_74[4]; /* reserved words 71-74 + * for IDENTIFY PACKET DEVICE command + */ + u16 queue_depth; /* (word 75) + * 15:5 reserved + * 4:0 Maximum queue depth -1 + */ + u16 words76_79[4]; /* reserved words 76-79 */ + u16 major_rev_num; /* (word 80) */ + u16 minor_rev_num; /* (word 81) */ + u16 command_set_1; /* (word 82) supported + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + u16 command_set_2; /* (word 83) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + u16 cfsse; /* (word 84) + * cmd set-feature supported extensions + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:6 reserved + * 5: General Purpose Logging + * 4: Streaming Feature Set + * 3: Media Card Pass Through + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + u16 cfs_enable_1; /* (word 85) + * command set-feature enabled + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + u16 cfs_enable_2; /* (word 86) + * command set-feature enabled + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + u16 csf_default; /* (word 87) + * command set-feature default + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:6 reserved + * 5: General Purpose Logging enabled + * 4: Valid CONFIGURE STREAM executed + * 3: Media Card Pass Through enabled + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + u16 dma_ultra; /* (word 88) */ + u16 trseuc; /* time required for security erase */ + u16 trsEuc; /* time required for enhanced erase */ + u16 CurAPMvalues; /* current APM values */ + u16 mprc; /* master password revision code */ + u16 hw_config; /* hardware config (word 93) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: + * 12: + * 11: + * 10: + * 9: + * 8: + * 7: + * 6: + * 5: + * 4: + * 3: + * 2: + * 1: + * 0: Shall be ONE + */ + u16 acoustic; /* (word 94) + * 15:8 Vendor's recommended value + * 7:0 current value + */ + u16 msrqs; /* min stream request size */ + u16 sxfert; /* stream transfer time */ + u16 sal; /* stream access latency */ + unsigned int spg; /* stream performance granularity */ + unsigned long long lba_capacity_2;/* 48-bit total number of sectors */ + u16 words104_125[22];/* reserved words 104-125 */ + u16 last_lun; /* (word 126) */ + u16 word127; /* (word 127) Feature Set + * Removable Media Notification + * 15:2 reserved + * 1:0 00 = not supported + * 01 = supported + * 10 = reserved + * 11 = reserved + */ + u16 dlf; /* (word 128) + * device lock function + * 15:9 reserved + * 8 security level 1:max 0:high + * 7:6 reserved + * 5 enhanced erase + * 4 expire + * 3 frozen + * 2 locked + * 1 en/disabled + * 0 capability + */ + u16 csfo; /* (word 129) + * current set features options + * 15:4 reserved + * 3: auto reassign + * 2: reverting + * 1: read-look-ahead + * 0: write cache + */ + u16 words130_155[26];/* reserved vendor words 130-155 */ + u16 word156; /* reserved vendor word 156 */ + u16 words157_159[3];/* reserved vendor words 157-159 */ + u16 cfa_power; /* (word 160) CFA Power Mode + * 15 word 160 supported + * 14 reserved + * 13 + * 12 + * 11:0 + */ + u16 words161_175[15];/* Reserved for CFA */ + u16 words176_205[30];/* Current Media Serial Number */ + u16 words206_254[49];/* reserved words 206-254 */ + u16 integrity_word; /* (word 255) + * 15:8 Checksum + * 7:0 Signature + */ +} __packed; + +#endif //REDPILL_HDPARAM_H diff --git a/internal/scsi/scsi_notifier.c b/internal/scsi/scsi_notifier.c new file mode 100644 index 0000000..933277a --- /dev/null +++ b/internal/scsi/scsi_notifier.c @@ -0,0 +1,239 @@ +/** + * Notification chain implementation for SCSI devices + * + * Linux kernel contains a subsystem responsible for delivering notifications about asynchronous events. It implements a + * pub/sub model. As many subsystems predate existence of the so-called Notification Chains these subsystems usually + * lack any pub/sub functionality. SCSI is no exception. SCSI layer/driver is ancient and huge. It does not have any way + * of delivering events to other parts of the system. This submodule retrofits notification chains to the SCSI layer to + * notify about new devices being added to the system. It can be easily extended to notify about removed devices as + * well. + * + * Before using this submodule you should read the notice below + the gitbooks article if you have never worked with + * Linux notification chains. + * + * !! READ ME - THIS IS IMPORTANT !! + * The core notifier.h contains the following return constants: + * - NOTIFY_DONE: "don't care about that event really" + * - NOTIFY_OK: "good, processed" (really the same as DONE; semantic is defined by a particular publisher[!]) + * - NOTIFY_BAD: "stop the notification chain! I veto that action!" + * - NOTIFY_STOP: "stop the notification chain. It's all good." + * This SCSI notifier defines them as such: + * - NOTIFY_DONE, NOTIFY_OK: processed, continue calling other + * - NOTIFY_BAD: + * scsi_event=SCSI_EVT_DEV_PROBING: stop sd_probe() with EBUSY error; subscribers with lower priority will not exec + * scsi_event=SCSI_EVT_DEV_PROBED_OK: subscribers with lower priority will not exec + * scsi_event=SCSI_EVT_DEV_PROBED_ERR: subscribers with lower priority will not exec + * - NOTIFY_STOP: + * scsi_event=SCSI_EVT_DEV_PROBING: stop sd_probe() with 0 err-code; subscribers with lower priority will not exec + * scsi_event=SCSI_EVT_DEV_PROBED_OK: subscribers with lower priority will not exec + * scsi_event=SCSI_EVT_DEV_PROBED_ERR: subscribers with lower priority will not exec + * + * SUPPORTED DEVICES + * Currently only SCSI disks are supported. This isn't a technical limitation but rather a practical one - we don't want + * to trigger notifications for all-all SCSI devices (which include hosts, buses, etc). If needed a new set of functions + * subscribe_.../ubsubscribe_... can easily be added which don't filter by type. + * + * TODO + * This notifier does not support notifying about disconnection of the device. It should as we need to know if device + * disappeared (e.g. while processing shimming of boot devices). + * + * ADDITIONAL TOOLS + * It is highly recommended to use scsi_toolbox when subscribing to notifications from the SCSI subsystem. + * + * References: + * - https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-4.html (about notification chains subsystem) + */ +#include "scsi_notifier.h" +#include "../../common.h" +#include "../notifier_base.h" //notifier_*() +#include "scsi_notifier_list.h" +#include "scsi_toolbox.h" +#include "../intercept_driver_register.h" //watching for sd driver loading +#include //to_scsi_device() + +#define NOTIFIER_NAME "SCSI device" + +/*********************************** Interacting with an active/loaded SCSI driver ************************************/ +static driver_watcher_instance *driver_watcher = NULL; +static int (*org_sd_probe) (struct device *dev) = NULL; //set during register + +/** + * Main notification routine hooking sd_probe() + */ +static int sd_probe_shim(struct device *dev) +{ + pr_loc_dbg("Probing SCSI device using %s", __FUNCTION__); + if (!is_scsi_leaf(dev)) { + pr_loc_dbg("%s: new SCSI device connected - not a leaf, ignoring", __FUNCTION__); + return org_sd_probe(dev); + } + + struct scsi_device *sdp = to_scsi_device(dev); + if (!is_scsi_disk(sdp)) { + pr_loc_dbg("%s: new SCSI device connected - not a disk, ignoring", __FUNCTION__); + return org_sd_probe(dev); + } + + pr_loc_dbg("Triggering SCSI_EVT_DEV_PROBING notifications"); + int out = notifier_to_errno(blocking_notifier_call_chain(&rp_scsi_notify_list, SCSI_EVT_DEV_PROBING, sdp)); + if (unlikely(out == NOTIFY_STOP)) { + pr_loc_dbg("After SCSI_EVT_DEV_PROBING a callee stopped chain with non-error condition. Faking probe-ok."); + return 0; + } else if (unlikely(out == NOTIFY_BAD)) { + pr_loc_dbg("After SCSI_EVT_DEV_PROBING a callee stopped chain with non-error condition. Faking probe-ok."); + return -EIO; //some generic error + } + + pr_loc_dbg("Calling original sd_probe()"); + out = org_sd_probe(dev); + scsi_event evt = (out == 0) ? SCSI_EVT_DEV_PROBED_OK : SCSI_EVT_DEV_PROBED_ERR; + + pr_loc_dbg("Triggering SCSI_EVT_DEV_PROBED notifications - sd_probe() exit=%d", out); + blocking_notifier_call_chain(&rp_scsi_notify_list, evt, sdp); + + return out; +} + +/** + * Overrides sd_probe() to provide notifications via sd_probe_shim() + * + * @param drv "sd" driver instance + */ +static inline void install_sd_probe_shim(struct device_driver *drv) +{ + pr_loc_dbg("Overriding %pf()<%p> with %pf()<%p>", drv->probe, drv->probe, sd_probe_shim, sd_probe_shim); + org_sd_probe = drv->probe; + drv->probe = sd_probe_shim; +} + +/** + * Removes override of sd_probe(), installed by install_sd_probe_shim() + * + * @param drv "sd" driver instance + */ +static inline void uninstall_sd_probe_shim(struct device_driver *drv) +{ + if (unlikely(!org_sd_probe)) { + pr_loc_wrn( + "Cannot %s - original drv->probe is not saved. It was either never installed or it's a bug. " + "The current drv->probe is %pf()<%p>", + __FUNCTION__, drv->probe, drv->probe); + return; + } + + pr_loc_dbg("Restoring %pf()<%p> to %pf()<%p>", drv->probe, drv->probe, org_sd_probe, org_sd_probe); + drv->probe = org_sd_probe; + org_sd_probe = NULL; +} + +/** + * Watches for the sd driver to load in order to shim it. The driver registration is modified before the driver loads. + */ +static driver_watch_notify_result sd_load_watcher(struct device_driver *drv, driver_watch_notify_state event) +{ + if (unlikely(event != DWATCH_STATE_COMING)) + return DWATCH_NOTIFY_CONTINUE; + + pr_loc_dbg("%s driver loaded - triggering sd_probe shim installation", SCSI_DRV_NAME); + install_sd_probe_shim(drv); + + driver_watcher = NULL; //returning DWATCH_NOTIFY_DONE causes automatic unwatching + return DWATCH_NOTIFY_DONE; +} + +/******************************************** Public API of the notifier **********************************************/ +extern struct bus_type scsi_bus_type; + +int subscribe_scsi_disk_events(struct notifier_block *nb) +{ + notifier_sub(nb); + return blocking_notifier_chain_register(&rp_scsi_notify_list, nb); +} + +int unsubscribe_scsi_disk_events(struct notifier_block *nb) +{ + notifier_unsub(nb); + return blocking_notifier_chain_unregister(&rp_scsi_notify_list, nb); +} + +// We need an additional flag as depending on which method of sd_probe override (watcher vs. existing driver find & +// switch) +static bool notifier_registered = false; +int register_scsi_notifier(void) +{ + notifier_reg_in(); + + if (unlikely(notifier_registered)) { + pr_loc_bug("%s notifier is already registered", NOTIFIER_NAME); + return -EEXIST; + } + + struct device_driver *drv = find_scsi_driver(); + + if(unlikely(drv < 0)) { //some error occurred while looking for the driver + return PTR_ERR(drv); //find_scsi_driver() should already log what went wrong + } else if(drv) { //the driver is already loaded - driver watcher cannot help us + pr_loc_wrn( + "The %s driver was already loaded when %s notifier registered - some devices may already be registered", + SCSI_DRV_NAME, NOTIFIER_NAME); + install_sd_probe_shim(drv); + } else { //driver not yet loaded - driver watcher will trigger sd_probe_shim installation when driver loads + pr_loc_dbg("The %s driver is not ready to dispatch %s notifier events - awaiting driver", SCSI_DRV_NAME, + NOTIFIER_NAME); + driver_watcher = watch_scsi_driver_register(sd_load_watcher, DWATCH_STATE_COMING); + if (unlikely(IS_ERR(driver_watcher))) { + pr_loc_err("Failed to register driver watcher for driver %s", SCSI_DRV_NAME); + return PTR_ERR(driver_watcher); + } + } + + notifier_registered = true; + + notifier_reg_ok(); + return 0; +} + +int unregister_scsi_notifier(void) +{ + notifier_ureg_in(); + + if (unlikely(!notifier_registered)) { + pr_loc_bug("%s notifier is not registered", NOTIFIER_NAME); + return -ENOENT; + } + + bool is_error = false; + int out = -EINVAL; + + //Check if we're watching sd driver (i.e. SCSI notifier was registered and is now being unregistered before the + // driver had a chance to load) + if (unlikely(driver_watcher)) { + pr_loc_dbg("%s notifier is still observing %s driver - stopping observer", NOTIFIER_NAME, SCSI_DRV_NAME); + out = unwatch_driver_register(driver_watcher); + if (unlikely(out != 0)) { + pr_loc_err("Failed to unregister driver watcher - error=%d", out); + is_error = true; + } + } + + //sd_probe() was replaced either after watching for the driver or on-the-spot after the driver was already loaded + if (likely(org_sd_probe)) { + struct device_driver *drv = find_scsi_driver(); + if (unlikely(IS_ERR(drv))) { + return PTR_ERR(drv); //find_scsi_driver() should already log what went wrong + } else if(likely(drv)) { + uninstall_sd_probe_shim(drv); + } else { //that is almost impossible as sd is built-in, but we if it happens there's nothing to recover + pr_loc_wrn("%s driver went away (?!)", SCSI_DRV_NAME); + is_error = true; + } + } + + notifier_registered = false; + if (unlikely(is_error)) { + return out; + } else { + notifier_ureg_ok(); + return 0; + } +} diff --git a/internal/scsi/scsi_notifier.h b/internal/scsi/scsi_notifier.h new file mode 100644 index 0000000..66b1142 --- /dev/null +++ b/internal/scsi/scsi_notifier.h @@ -0,0 +1,29 @@ +#ifndef REDPILL_SCSI_NOTIFIER_H +#define REDPILL_SCSI_NOTIFIER_H + +#include //All other parts including scsi_notifier.h cannot really not use linux/notifier.h + +typedef enum { + SCSI_EVT_DEV_PROBING, //device is being probed; it can be modified or outright ignored + SCSI_EVT_DEV_PROBED_OK, //device is probed and ready + SCSI_EVT_DEV_PROBED_ERR, //device was probed but it failed +} scsi_event; + +/** + * Callback signature: void (*f)(struct notifier_block *self, unsigned long state, void *data), where: + * unsigned long state => scsi_event event + * void *data => struct scsi_device *sdp + * + * Currently these methods are DELIBERATELY limited to SCSI TYPE_DISK scope. If you need other SCSI devices watching + * add another set of methods (subscribe scsi_device_events() and such, do NOT extend the scope of these methods as + * other parts of the code rely on pre-filtered events as in most cases listening for ALL devices is a lot of noise). + * + * @return + */ +int subscribe_scsi_disk_events(struct notifier_block *nb); +int unsubscribe_scsi_disk_events(struct notifier_block *nb); + +int register_scsi_notifier(void); +int unregister_scsi_notifier(void); + +#endif //REDPILL_SCSI_NOTIFIER_H diff --git a/internal/scsi/scsi_notifier_list.c b/internal/scsi/scsi_notifier_list.c new file mode 100644 index 0000000..dd4cd62 --- /dev/null +++ b/internal/scsi/scsi_notifier_list.c @@ -0,0 +1,4 @@ +#include "scsi_notifier_list.h" +#include + +BLOCKING_NOTIFIER_HEAD(rp_scsi_notify_list); diff --git a/internal/scsi/scsi_notifier_list.h b/internal/scsi/scsi_notifier_list.h new file mode 100644 index 0000000..32de773 --- /dev/null +++ b/internal/scsi/scsi_notifier_list.h @@ -0,0 +1,27 @@ +/** + * This file exists solely as a workaround for GCC bug #275674 - static structures are misdirected as dynamic + * + * Linux contains many clever idioms. One of them is a complex initialization of heads for notifier chains + * (include/linux/notifier.h). They do contain an embedded cast to a struct. GCC <5 detects that as a dynamic allocation + * and refuses to initialize it statically. This breaks all the macros for notifier (e.g. BLOCKING_NOTIFIER_INIT). Old + * kernels (i.e. <3.18) cannot be compiled with GCC >4.9 so... we cannot use a newer GCC but we cannot use older due to + * a bug. One of the solutions would be to convert the whole code of this module to GNU89 but this is painful to use. + * + * Such structures are working in GNU89 mode as well as when defined as a heap variable in a function. However, GCC is + * smart enough to release the memory from within a function (so we cannot just wrap it in a function and return a ptr). + * Due to the complex nature of the struct we didn't want to hardcode it here as they change between kernel version. + * As a workaround we created a separate compilation unit containing just the struct and compile it in GNU89 mode, while + * rest of the project stays at GNU99. + * + * Resources + * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63567 (bug report) + * - https://unix.stackexchange.com/a/275674 (kernel v3.18 restriction) + * - https://stackoverflow.com/a/49119902 (linking files compiled with different language standard in GCC) + * - https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt (compilation option per file in Kbuild; sect. 3.7) + */ +#ifndef REDPILL_SCSI_NOTIFIER_LIST_H +#define REDPILL_SCSI_NOTIFIER_LIST_H + +extern struct blocking_notifier_head rp_scsi_notify_list; + +#endif //REDPILL_SCSI_NOTIFIER_LIST_H diff --git a/internal/scsi/scsi_toolbox.c b/internal/scsi/scsi_toolbox.c new file mode 100644 index 0000000..4f22d87 --- /dev/null +++ b/internal/scsi/scsi_toolbox.c @@ -0,0 +1,246 @@ +#include "scsi_toolbox.h" +#include "scsiparam.h" //SCSI_* +#include "../../common.h" +#include "../../internal/call_protected.h" //scsi_scan_host_selected() +#include //DMA_FROM_DEVICE +#include //get_unaligned_be32() +#include //msleep +#include //cmd consts (e.g. SERVICE_ACTION_IN), SCAN_WILD_CARD, and TYPE_DISK +#include //struct scsi_sense_hdr, scsi_sense_valid() +#include //struct Scsi_Host, SYNO_PORT_TYPE_SATA +#include //struct scsi_transport_template +#include //struct scsi_device, scsi_execute_req(), scsi_is_sdev_device() + +extern struct bus_type scsi_bus_type; //SCSI bus type for driver scanning + +/** + * Issues SCSI "READ CAPACITY (16)" command + * Make sure you read what this function returns! + * + * @param sdp + * @param buffer Pointer to a buffer of size SCSI_BUF_SIZE + * @param sshdr Sense header + * @return 0 on command success, >0 if command failed; if the command failed it MAY be repeated + */ +static int scsi_read_cap16(struct scsi_device *sdp, unsigned char *buffer, struct scsi_sense_hdr *sshdr) +{ + unsigned char cmd[16]; + memset(cmd, 0, 16); + cmd[0] = SCSI_SERVICE_ACTION_IN_16; + cmd[1] = SAI_READ_CAPACITY_16; + cmd[13] = SCSI_RC16_LEN; + memset(buffer, 0, SCSI_RC16_LEN); + + return scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, buffer, SCSI_RC16_LEN, sshdr, SCSI_CMD_TIMEOUT, + SCSI_CMD_MAX_RETRIES, NULL); +} + +/** + * Issues SCSI "READ CAPACITY (10)" command + * Make sure you read what this function returns! + * + * @param sdp + * @param buffer Pointer to a buffer of size SCSI_BUF_SIZE + * @param sshdr Sense header + * @return 0 on command success, >0 if command failed; if the command failed it MAY be repeated + */ +static int scsi_read_cap10(struct scsi_device *sdp, unsigned char *buffer, struct scsi_sense_hdr *sshdr) +{ + unsigned char cmd[16]; + cmd[0] = READ_CAPACITY; + memset(&cmd[1], 0, 9); + memset(buffer, 0, 8); + + return scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, buffer, 8, sshdr, SCSI_CMD_TIMEOUT, SCSI_CMD_MAX_RETRIES, NULL); +} + +long long opportunistic_read_capacity(struct scsi_device *sdp) +{ + //some drives work only with the 16 version but older ones can only accept the older variant + //to prevent false-positive "command failed" we need to try both + bool use_cap16 = true; + + unsigned char *buffer = NULL; + kmalloc_or_exit_int(buffer, SCSI_BUF_SIZE); + + int out; + int sense_valid = 0; + struct scsi_sense_hdr sshdr; + int read_retry = SCSI_CAP_MAX_RETRIES; + do { + //It can return 0 or a positive integer; 0 means immediate success where 1 means an error. Depending on the error + //the command may be repeated. + out = (use_cap16) ? scsi_read_cap16(sdp, buffer, &sshdr) : scsi_read_cap10(sdp, buffer, &sshdr); + if (out == 0) + break; //command just succeeded + + if (unlikely(out > 0)) { //it's technically an error but we may be able to recover + if (use_cap16) { //if we previously used CAP(16) and it failed we can try older CAP(10) [even on hard-fail] + use_cap16 = false; + continue; + } + + //Some failures are hard-failure (e.g. drive doesn't support the cmd), some are soft-failures + //In soft failures some are known to take more time (e.g. spinning rust is spinning up) and some should be + //fast-repeat. We really only distinguish hard from soft and just wait some time for others + //In a normal scenario this path will be cold as the drive will respond to CAP(16) or CAP(10) right away. + + sense_valid = scsi_sense_valid(&sshdr); + if (!sense_valid) { + pr_loc_dbg("Invalid sense - trying again"); + continue; //Sense invalid, this can be repeated right away + } + + //Drive deliberately rejected the request and indicated that this situtation will not change + if (sshdr.sense_key == ILLEGAL_REQUEST && (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00) { + pr_loc_err("Drive refused to provide capacity"); + kfree(buffer); + return -EINVAL; + } + + //Drive is busy - wait for some time + if (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29 && sshdr.ascq == 0x00) { + pr_loc_dbg("Drive busy during capacity pre-read (%d attempts left), trying again", read_retry-1); + msleep(500); //if it's a spinning rust over USB we may need to wait + continue; + } + } + } while (--read_retry); + + if (out != 0) { + pr_loc_err("Failed to pre-read capacity of the drive after %d attempts due to SCSI errors", + (SCSI_CAP_MAX_RETRIES - read_retry)); + kfree(buffer); + return -EIO; + } + + unsigned sector_size = get_unaligned_be32(&buffer[8]); + unsigned long long lba = get_unaligned_be64(&buffer[0]); + + //Good up to 8192000000 pebibytes - good luck overflowing that :D + long long size_mb = ((lba+1) * sector_size) / 1024 / 1024; //sectors * sector size = size in bytes + + kfree(buffer); + return size_mb; +} + +bool is_scsi_disk(struct scsi_device *sdp) +{ + return (likely(sdp) && (sdp)->type == TYPE_DISK); +} + +bool is_sata_disk(struct device *dev) +{ + //from the kernel's pov SCSI devices include SCSI hosts, "leaf" devices, and others - this filters real SCSI devices + if (!is_scsi_leaf(dev)) + return false; + + struct scsi_device *sdp = to_scsi_device(dev); + + //end/leaf devices can be disks or other things - filter only real disks + //more than that use syno's private property (hey! not all of their kernel mods are bad ;)) to determine port which + //a given device uses (vanilla kernel doesn't care about silly ports - SCSI is SCSI) + if (!is_scsi_disk(sdp) || sdp->host->hostt->syno_port_type != SYNO_PORT_TYPE_SATA) + return false; + + return true; +} + +int scsi_force_replug(scsi_device *sdp) +{ + if (unlikely(!is_scsi_leaf(&sdp->sdev_gendev))) { + pr_loc_bug("%s expected SCSI leaf - got something else", __FUNCTION__); + return -EINVAL; + } + + struct Scsi_Host *host = sdp->host; + pr_loc_dbg("Removing device from host%d", host->host_no); + scsi_remove_device(sdp); //this will do locking for remove + + //See drivers/scsi/scsi_sysfs.c:scsi_scan() for details + if (unlikely(host->transportt->user_scan)) { + pr_loc_dbg("Triggering template-based rescan of host%d", host->host_no); + return host->transportt->user_scan(host, SCAN_WILD_CARD, SCAN_WILD_CARD, SCAN_WILD_CARD); + } else { + pr_loc_dbg("Triggering generic rescan of host%d", host->host_no); + //this is unfortunately defined in scsi_scan.c, it can be emulated because it's just bunch of loops, but why? + //This will also most likely never be used anyway + return _scsi_scan_host_selected(host, SCAN_WILD_CARD, SCAN_WILD_CARD, SCAN_WILD_CARD, 1); + } +} + +//We assume that if the sd was loaded once it will never unload (as on most kernels it's built in). +//If this assumption changes the cache can simply be removed +bool sd_driver_loaded = false; +struct device_driver *find_scsi_driver(void) +{ + struct device_driver *drv = driver_find("sd", &scsi_bus_type); + if (IS_ERR(drv)) { + pr_loc_err("Failed to query sd driver status - error=%ld", PTR_ERR(drv)); + return drv; + } + + if (drv) { + sd_driver_loaded = true; + return drv; + } + + return NULL; +} + +int is_scsi_driver_loaded(void) +{ + if (likely(sd_driver_loaded)) + return true; + + struct device_driver *drv = find_scsi_driver(); + if (IS_ERR(drv)) //get_scsi_driver() will already print an error message + return PTR_ERR(drv); + + return drv ? SCSI_DRV_LOADED : SCSI_DRV_NOT_LOADED; +} + +/** + * Filters out all SCSI leafs and calls the callback prescribed + */ +static int for_each_scsi_leaf_filter(struct device *dev, on_scsi_device_cb cb) +{ + if (!is_scsi_leaf(dev)) + return 0; + + return (cb)(to_scsi_device(dev)); +} + +/** + * Filters out all SCSI disks and calls the callback prescribed + */ +static int for_each_scsi_disk_filter(struct device *dev, on_scsi_device_cb cb) +{ + if (!is_scsi_leaf(dev)) + return 0; + + struct scsi_device *sdp = to_scsi_device(dev); + if (!is_scsi_disk(sdp)) + return 0; + + return (cb)(to_scsi_device(dev)); +} + +static int inline for_each_scsi_x(on_scsi_device_cb *cb, int (*filter)(struct device *dev, on_scsi_device_cb cb)) +{ + if (!is_scsi_driver_loaded()) + return -ENXIO; + + int code = bus_for_each_dev(&scsi_bus_type, NULL, cb, (int (*)(struct device *, void *))filter); + return unlikely(code == -ENXIO) ? -EIO : code; +} + +int for_each_scsi_leaf(on_scsi_device_cb *cb) +{ + return for_each_scsi_x(cb, for_each_scsi_leaf_filter); +} + +int for_each_scsi_disk(on_scsi_device_cb *cb) +{ + return for_each_scsi_x(cb, for_each_scsi_disk_filter); +} \ No newline at end of file diff --git a/internal/scsi/scsi_toolbox.h b/internal/scsi/scsi_toolbox.h new file mode 100644 index 0000000..f43687e --- /dev/null +++ b/internal/scsi/scsi_toolbox.h @@ -0,0 +1,100 @@ +#ifndef REDPILL_SCSI_TOOLBOX_H +#define REDPILL_SCSI_TOOLBOX_H + +#include //bool + +typedef struct device device; +typedef struct scsi_device scsi_device; +typedef int (on_scsi_device_cb)(struct scsi_device *sdp); + +#define SCSI_DRV_NAME "sd" //useful for triggering watchers +//To use this one import intercept_driver_register.h header (it's not imported here to avoid pollution) +#define watch_scsi_driver_register(callback, event_mask) \ + watch_driver_register(SCSI_DRV_NAME, (callback), (event_mask)) + +#define IS_SCSI_DRIVER_ERROR(state) (unlikely((state) < 0)) +typedef enum { + SCSI_DRV_NOT_LOADED = 0, + SCSI_DRV_LOADED = 1, +} scsi_driver_state; + +/** + * From the kernel's pov SCSI devices include SCSI hosts, "leaf" devices, and others - this filters real SCSI devices + * + * This is simply an alias for scsi_is_sdev_device() which is more descriptive for people who aren't SCSI wizards. + * + * @param dev struct device* + */ +#define is_scsi_leaf(dev) scsi_is_sdev_device(dev) + +/** + * Attempts to read capacity of a device assuming reasonably modern pathway + * + * This function (along with scsi_read_cap{10|16}) is loosely based on drivers/scsi/sd.c:sd_read_capacity(). However, + * this method cuts some corners to be faster as we're expecting rather modern hardware. Additionally, functions from + * sd.c cannot be used as they're static. Even that some of them can be called using kallsyms they aren't stateless and + * will cause a KP later on (as they modify the device passed to them). + * Thus this function should be seen as a way to quickly estimate (as it reports full mebibytes rounded down) the + * capacity without causing side effects. + * + * @param sdp + * @return capacity in full mebibytes, or -E on error + */ +long long opportunistic_read_capacity(struct scsi_device *sdp); + +/** + * Checks if a SCSI device is a SCSI-complain disk (e.g. SATA, SAS, iSCSI etc) + * + * To be 101% sure and proper you should probably call is_scsi_leaf() first + */ +bool is_scsi_disk(struct scsi_device *sdp); + +/** + * Checks if a given generic device is an SCSI disk connected to a SATA port/host controller + * + * Every SATA disk, by definition, will also be an SCSI disk (as SATA is a connector carrying SCSI commands) + */ +bool is_sata_disk(struct device *dev); + +/** + * Triggers a re-probe of SCSI leaf device by forcefully "unplugging" and "replugging" the device + * + * WARNING: be careful what are you doing - this method is no different than yanking a power cable from a device, so if + * you do that with a disk which is used data loss may occur! + * + * @return 0 on success, -E on error + */ +int scsi_force_replug(scsi_device *sdp); + +/** + * Locates & returns SCSI driver structure if loaded + * + * @return driver struct on success, NULL if driver is not loaded, ERR_PTR(-E) on error + */ +struct device_driver *find_scsi_driver(void); + +/** + * Checks if SCSI driver is loaded or not + * + * This function is useful to make a decision whether to just watch for new devices or watch for new ones + scan + * existing ones. You cannot just scan blindly as this will cause an error. + * + * @return 0 if not loaded, 1 if loaded, -E on error; see scsi_driver_state enum for constants + */ +int is_scsi_driver_loaded(void); + +/** + * Traverses list of all SCSI devices and calls the callback with every leaf/terminal device found + * + * @return 0 on success, -E on failure. -ENXIO is reserved to always mean that the driver is not loaded + */ +int for_each_scsi_leaf(on_scsi_device_cb *cb); + +/** + * Traverses list of all SCSI devices and calls the callback with every SCSCI-complaint disk found + * + * @return 0 on success, -E on failure. -ENXIO is reserved to always mean that the driver is not loaded + */ +int for_each_scsi_disk(on_scsi_device_cb *cb); + +#endif //REDPILL_SCSI_TOOLBOX_H diff --git a/internal/scsi/scsiparam.h b/internal/scsi/scsiparam.h new file mode 100644 index 0000000..153b2a4 --- /dev/null +++ b/internal/scsi/scsiparam.h @@ -0,0 +1,24 @@ +/** + * This file contains a list of cherry-picked constants useful while dealing with SCSI subsystem + */ +#ifndef REDPILL_SCSIPARAM_H +#define REDPILL_SCSIPARAM_H + +#include //KERNEL_VERSION_CODE, KERNEL_VERSION() +#include //SERVICE_ACTION_IN or SERVICE_ACTION_IN_16 + +#define SCSI_RC16_LEN 32 //originally defined in drivers/scsi/sd.c as RC16_LEN +#define SCSI_CMD_TIMEOUT (30 * HZ) //originally defined in drivers/scsi/sd.h as SD_TIMEOUT +#define SCSI_CMD_MAX_RETRIES 5 //normal drives shouldn't fail the command even once +#define SCSI_CAP_MAX_RETRIES 3 +#define SCSI_BUF_SIZE 512 //originally defined in drivers/scsi/sd.h as SD_BUF_SIZE + +//Old kernels used ambiguous constant: https://github.com/torvalds/linux/commit/eb846d9f147455e4e5e1863bfb5e31974bb69b7c +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +#define SCSI_SERVICE_ACTION_IN_16 SERVICE_ACTION_IN +#else +#define SCSI_SERVICE_ACTION_IN_16 SERVICE_ACTION_IN_16 +#endif + + +#endif //REDPILL_SCSIPARAM_H diff --git a/internal/stealth.c b/internal/stealth.c new file mode 100644 index 0000000..7ca8684 --- /dev/null +++ b/internal/stealth.c @@ -0,0 +1,60 @@ +#include "stealth.h" +#include "stealth/sanitize_cmdline.h" +#include //struct module (for list_del) + +//TODO: +//https://github.com/xcellerator/linux_kernel_hacking/blob/master/3_RootkitTechniques/3.0_hiding_lkm/rootkit.c +//remove file which was used for insmod +//remove kernel taint +//remove module loading from klog +//delete module file from ramdisk + +int initialize_stealth(void *config2) +{ + struct runtime_config *config = config2; + + int error = 0; +#if STEALTH_MODE <= STEALTH_MODE_OFF + //STEALTH_MODE_OFF shortcut + return error; +#endif + +#if STEALTH_MODE > STEALTH_MODE_OFF + //These are STEALTH_MODE_BASIC ones + if ((error = register_stealth_sanitize_cmdline(config->cmdline_blacklist)) != 0) + return error; +#endif + +#if STEALTH_MODE > STEALTH_MODE_BASIC + //These will be STEALTH_MODE_NORMAL ones +#endif + +#if STEALTH_MODE > STEALTH_MODE_NORMAL + //These will be STEALTH_MODE_FULL ones + list_del(&THIS_MODULE->list); +#endif + + return error; +} + +int uninitialize_stealth(void) +{ + int error; + +#if STEALTH_MODE > STEALTH_MODE_NORMAL + //These will be STEALTH_MODE_FULL ones +#endif + +#if STEALTH_MODE > STEALTH_MODE_BASIC + //These will be STEALTH_MODE_NORMAL ones +#endif + +#if STEALTH_MODE > STEALTH_MODE_OFF + //These are STEALTH_MODE_BASIC ones + if ((error = unregister_stealth_sanitize_cmdline()) != 0) + return error; +#endif + + //Mode set to STEALTH_MODE_OFF or nothing failed before + return error; +} \ No newline at end of file diff --git a/internal/stealth.h b/internal/stealth.h new file mode 100644 index 0000000..fa58282 --- /dev/null +++ b/internal/stealth.h @@ -0,0 +1,29 @@ +/* + * This header file should be included as the first one before anything else so other header files can use STEALTH_MODE + */ + +#ifndef REDPILLLKM_STEALTH_H +#define REDPILLLKM_STEALTH_H + +#define STEALTH_MODE_OFF 0 //Nothing is hidden, useful for full-on debugging +#define STEALTH_MODE_BASIC 1 //Hides basic things like cmdline (which is more to prevent DSM code from complaining about unknown options etc.) +#define STEALTH_MODE_NORMAL 2 //Hides everything except making the module not unloadable +#define STEALTH_MODE_FULL 3 //Same as STEALTH_MODE_NORMAL + removes the module from list of loaded modules & all logs + +//Define just after levels so other headers can use it if needed to e.g. replace some macros +#ifndef STEALTH_MODE +//#warning "Stealth mode not specified - using default" +#define STEALTH_MODE STEALTH_MODE_BASIC +#endif + +//Some compile-time stealthiness +#if STEALTH_MODE > STEALTH_MODE_OFF //STEALTH_MODE_BASIC or above +#define VIRTUAL_UART_THREAD_FMT "irq/%d-serial" //pattern format for vUART kernel thread which spoofs IRQ one +#endif + +struct runtime_config; + +int initialize_stealth(void *config); +int uninitialize_stealth(void); + +#endif //REDPILLLKM_STEALTH_H \ No newline at end of file diff --git a/internal/stealth/sanitize_cmdline.c b/internal/stealth/sanitize_cmdline.c new file mode 100644 index 0000000..ccb96d0 --- /dev/null +++ b/internal/stealth/sanitize_cmdline.c @@ -0,0 +1,162 @@ +/* + * This submodule removes blacklisted entries from /proc/cmdline to hide some options after the LKM is loaded + * + * OVERVIEW + * The main reason to sanitize cmdline is to avoid leaking information like "vid=..." or "pid=..." to userspace. Doing + * this may cause some other external modules parsing kernel cmdline to be confused why such options are present in the + * boot params. + * + * HOW IT WORKS? + * The module overrides cmdline_proc_show() from fs/proc/cmdline.c with a jump to our implementation. The implementation + * here serves a filtrated version of the cmdline. + * + * WHY OVERRIDE A STATIC METHOD? + * This module has actually been rewritten to hard-override cmdline_proc_show() instead of "gently" finding the dentry + * for /proc/cmdline, and then without modifying the dentry replacing the read operation in file_operations struct. + * While this method is much cleaner and less invasive it has two problems: + * - Requires "struct proc_dir_entry" (which is internal and thus not available in toolkit builds) + * - Doesn't work if the module is loaded as ioscheduler (as funny enough this code will execute BEFORE /proc/cmdline + * is created) + * This change has been made in commit "Rewrite cmdline sanitize to replace cmdline_proc_show". + * + * FILTRATION + * The second part of the code deals with the actual filtration. List of blacklisted entries is passed during + * registration (to allow flexibility). Usually it will be gathered form pre-generated config. Then a filtrated copy of + * cmdline is created once (as this is a quite expensive string-ridden operation). + * The only sort-of way to find the original implementation is to access the kmesg buffer where the original cmdline is + * baked into early on boot. Technically we can replace that too but this will get veeery messy and I doubt anyone will + * try dig through kmesg messages with a regex for cmdline (especially that with a small dmesg buffer it will roll over) + */ + +#include "sanitize_cmdline.h" +#include "../../common.h" +#include "../../config/cmdline_delegate.h" //get_kernel_cmdline() & CMDLINE_MAX +#include "../override/override_symbol.h" //override_symbol() & restore_symbol() +#include //seq_file, seq_printf() + +/** + * Pre-generated filtered cmdline (by default it's an empty string in case it's somehow printed before filtration) + * See filtrate_cmdline() for details + */ +static char *filtrated_cmdline = NULL; + +/** + * Check if a given cmdline token is on the blacklist + */ +static bool +is_token_blacklisted(const char *param_pointer, cmdline_token *cmdline_blacklist[MAX_BLACKLISTED_CMDLINE_TOKENS]) { + for (int i = 0; i < MAX_BLACKLISTED_CMDLINE_TOKENS; i++) { + if (!cmdline_blacklist[i]) + return false; + + if (strncmp(param_pointer, (char *)cmdline_blacklist[i], strlen((char *)cmdline_blacklist[i])) == 0) + return true; + } + + return false; +} + +/** + * Filters-out all blacklisted entries from the cmdline string (fetched from /proc/cmdline) + */ +static int filtrate_cmdline(cmdline_token *cmdline_blacklist[MAX_BLACKLISTED_CMDLINE_TOKENS]) +{ + char *raw_cmdline; + kmalloc_or_exit_int(raw_cmdline, strlen_to_size(CMDLINE_MAX)); + + long cmdline_len = get_kernel_cmdline(raw_cmdline, CMDLINE_MAX); + if(unlikely(cmdline_len < 0)) { //if <0 it's an error code + pr_loc_dbg("get_kernel_cmdline failed with %ld", cmdline_len); + kfree(raw_cmdline); + return (int) cmdline_len; + } + + filtrated_cmdline = kmalloc(strlen_to_size(cmdline_len), GFP_KERNEL); + if (unlikely(!filtrated_cmdline)) { + kfree(raw_cmdline); + kalloc_error_int(filtrated_cmdline, strlen_to_size(cmdline_len)); + } + + char *single_param_chunk; //Pointer to the beginning of the cmdline token + char *filtrated_ptr = &filtrated_cmdline[0]; //Pointer to the current position in filtered + + size_t curr_param_len; + while ((single_param_chunk = strsep(&raw_cmdline, CMDLINE_SEP)) != NULL) { + if (single_param_chunk[0] == '\0') //Skip empty + continue; + + if (is_token_blacklisted(single_param_chunk, cmdline_blacklist)) { + pr_loc_dbg("Cmdline param \"%s\" blacklisted - skipping", single_param_chunk); + continue; + } + + curr_param_len = strlen(single_param_chunk); + memcpy(filtrated_ptr, single_param_chunk, curr_param_len); + filtrated_ptr += curr_param_len; + *(filtrated_ptr++) = ' '; + } + + *(filtrated_ptr-1) = '\0'; //Terminate whole param string (removing the trailing space) + kfree(raw_cmdline); + + pr_loc_dbg("Sanitized cmdline to: %s", filtrated_cmdline); + + return 0; +} + +/** + * Handles fs/proc/ semantics for reading. See include/linux/fs.h:file_operations.read for details. + */ +static int cmdline_proc_show_filtered(struct seq_file *m, void *v) +{ + seq_printf(m, "%s\n", filtrated_cmdline); + return 0; +} + +static override_symbol_inst *ov_cmdline_proc_show = NULL; +int register_stealth_sanitize_cmdline(cmdline_token *cmdline_blacklist[MAX_BLACKLISTED_CMDLINE_TOKENS]) +{ + if (unlikely(ov_cmdline_proc_show)) { + pr_loc_bug("Attempted to %s while already registered", __FUNCTION__); + return 0; //Technically it succeeded + } + + int out; + //This has to be done once (we're assuming cmdline doesn't change without reboot). In case this submodule is + // re-registered the filtrated_cmdline is left as-is and reused + if (!filtrated_cmdline && (out = filtrate_cmdline(cmdline_blacklist)) != 0) + return out; + + ov_cmdline_proc_show = override_symbol("cmdline_proc_show", cmdline_proc_show_filtered); + if (unlikely(IS_ERR(ov_cmdline_proc_show))) { + out = PTR_ERR(ov_cmdline_proc_show); + pr_loc_err("Failed to override cmdline_proc_show - error %d", out); + ov_cmdline_proc_show = NULL; + return out; + } + + pr_loc_inf("/proc/cmdline sanitized"); + + return 0; +} + +int unregister_stealth_sanitize_cmdline(void) +{ + if (unlikely(!ov_cmdline_proc_show)) { + pr_loc_bug("Attempted to %s while it's not registered", __FUNCTION__); + return 0; //Technically it succeeded + } + + int out = restore_symbol(ov_cmdline_proc_show); + //We deliberately fall through here without checking as we have to free stuff at this point no matter what + + kfree(filtrated_cmdline); + filtrated_cmdline = NULL; + + if (likely(out == 0)) + pr_loc_inf("Original /proc/cmdline restored"); + else + pr_loc_err("Failed to restore original /proc/cmdline: org_cmdline_proc_show failed - error %d", out); + + return out; +} \ No newline at end of file diff --git a/internal/stealth/sanitize_cmdline.h b/internal/stealth/sanitize_cmdline.h new file mode 100644 index 0000000..00bfbf0 --- /dev/null +++ b/internal/stealth/sanitize_cmdline.h @@ -0,0 +1,23 @@ +#ifndef REDPILL_SANITIZE_CMDLINE_H +#define REDPILL_SANITIZE_CMDLINE_H + +#include "../../config/cmdline_delegate.h" //MAX_BLACKLISTED_CMDLINE_TOKENS + +/** + * Register submodule sanitizing /proc/cmdline + * + * After registration /proc/cmdline will be non-destructively cleared from entries listed in cmdline_blacklist param. + * It can be reversed using unregister_stealth_sanitize_cmdline() + * + * @return 0 on success, -E on error + */ +int register_stealth_sanitize_cmdline(cmdline_token *cmdline_blacklist[MAX_BLACKLISTED_CMDLINE_TOKENS]); + +/** + * Reverses what register_stealth_sanitize_cmdline() did + * + * @return 0 on success, -E on error + */ +int unregister_stealth_sanitize_cmdline(void); + +#endif //REDPILL_SANITIZE_CMDLINE_H diff --git a/internal/uart/uart_swapper.c b/internal/uart/uart_swapper.c new file mode 100644 index 0000000..28e4991 --- /dev/null +++ b/internal/uart/uart_swapper.c @@ -0,0 +1,472 @@ +/** + * This tool is an isolated UART port-swapping utility allowing you to swap any two ports on runtime + * + * REASONING + * Some kernels are compiled with CONFIG_SYNO_X86_SERIAL_PORT_SWAP set which effectively swaps first two serial ports. + * This function reverses that. It also makes sure to move kernel console output between them (if configured). + * + * + * OVERVIEW + * Swapping the serials involves two things: swapping console drivers and swapping kernel console printk itself. + * The first one can be done on any kernel by modifying exported "console_drivers". The second one requires an access + * to either struct serial8250_ports (drivers/tty/serial/8250/8250_core.c) or to struct console_cmdline + * (kernel/printk/printk.c). Both of them are static so they're no-go directly. + * Kernels before v4.1 had a convenient method update_console_cmdline(). Unfortunately this method was removed: + * https://github.com/torvalds/linux/commit/c7cef0a84912cab3c9df8949b034e4aa62982ec9 so there's currently no method + * of un-swapping on v4. Even worse calling this method on lower kernels is a combination of luck and timing (as this is + * a init-only method). + * + * + * IMPLEMENTATION + * Things we've tried and failed: + * - Set the new console as preferred (making it default for /dev/console) -> /dev/ttyS0 and 1 are still wrong + * - Unregistering both ports and re-registering them -> we tried a bit and it's a nightmare to re-do and crashes the + * kernel + * - Unregistering and re-registering consoles -> will fail with KP or do nothing (and even if it worked if a + * non-console port is involved it will be broken) + * - Recreating the flow for serial8250_isa_init_ports() -> it appears to work (i.e. doesn't crash) but the serial port + * is dead afterwards and doesn't pass any traffic (we've never discovered why) + * => Hours wasted trying to reverse stupid ports: 37 + * + * What actually did work was carefully split-stopping the port (stopping the driver/hardware end of but not the higher + * level ttyS# side), exchanging the iobase & IRQ (+ some other internal things generated during init), restarting the + * port and hoping for the best. It does work BUT it's ridden with edge cases. Properly implementing and testing this + * took ~3 full days and two people... so if you're not sure what you're doing here you can easily break it. + * + * + * INTERNAL DETAILS + * What we are doing here may not be intuitive if you don't exactly know how the 8250 driver works internally. Let's go + * over this first. Each port is composed of outer uart_8250_port which contains various driver-specific information. + * Inside it there's an uart_port struct which contains the information about the actual physical UART channel. + * + * When the ports were flipped their position in the internal 8250 list, their line# in uart_8250_port and other + * internal properties were kept intact. The only two things which were changed are ->port.iobase and ->port.irq + * Flipping these is enough to make port sort-of-working. The port will pass data BUT only if the other port triggers + * interrupts (e.g. you type something on ttyS0 and nothing happens, you hold a space bar on ttyS1 afterwards and + * stuff you've typed on ttyS0 starts appearing). This strange effect is caused by how 8250 driver implements IRQ + * handling (serial8250_interrupt in 8250_core.c). It does not iterate over ALL ports looking for ports which match + * the IRQ triggering the function. [FROM NOW ON READ CAREFULLY!] Instead, it uses and struct irq_info passed as + * "user data" to the IRQ handler function. That struct contains a POINTER to a list_head of the first port, making + * the irq_struct the list owner. That doubly-linked list ties together multiple uart_8250_port structures (->list) + * which share the same IRQ. Here's the major problem: changing the NUMERIC IRQ value in uart_8250_port->port.irq + * does nothing to the actual IRQ handling for that port. + * + * When an IRQ happens and serial8250_interrupt() fires, it looks at the irq_struct, gets the pointer to list_head + * containing all active ports sharing a given IRQ and then just iterates over them triggering their internal + * handling of stuff. The irq_struct list_head pointer is just a memory address and our swaps of anything will never + * change it. This means two things: we need to fix the shared IRQ lists in uart_8250_port for ttyS0 and ttyS1 AND + * fix the mapping of IRQ => uart_8250_port element. Keep in mind that uart_8250_port->list contains only the ports + * which are currently active (i.e. enabled AND open). Kernel registers for IRQs only if something actually opens + * the port (as there's no point to receive data where you don't place to deliver them). + * + * Unfortunately, fixing these lists isn't really possible. The irq_struct contains a pointer to list_head which can + * be in any of the uart_8250_port. If it points to ttyS0 and/or ttyS1 (spoiler: most likely yes, as they're open) + * deleting an element from that list will break it completely (as irq_struct only knows the address of that one + * uart_8250_port in practice). If we replace prev/next to point to a different port it will still break because + * the interrupt handler calls container_of() which make prev/next irrelevant for the first fetch. + * struct_irq is contained in two places: internally cached in the 8250_core.c and as a pointer in the kernel IRQ + * handling. It will be unwise to try to modify it (ok, we're saying this only because we found a better way :D). + * + * Normally the IRQ manipulation is enabled/disabled by serial_link_irq_chain/serial_unlink_irq_chain in 8250_core.c + * but they're static. However, we an exploit the fact that 8250 driver is modular and operations on the Linux port + * are separated from operations on the hardware (which makes sense). We can command the UART chip to shutdown + * before we touch iobase or irq (which naturally has to remove IRQ if present) and then command the chip to startup + * which will register IRQ if needed (for the new irq value of course ;)) + * + * References: + * - Linux kernel sources (mainly drivers/tty/serial/8250/8250_core.c and drivers/tty/serial/serial_core.c) + * - https://linux-kernel-labs.github.io/refs/heads/master/labs/interrupts.html + * - https://www.ti.com/lit/ug/sprugp1/sprugp1.pdf + */ + +#include "../../common.h" +#include "../call_protected.h" //early_serial_setup() +#include "../override/override_symbol.h" //overriding uart_match_port() +#include "../../config/uart_defs.h" //struct uart_port, COM ports definition, UART_NR +#include //struct uart_8250_port +#include //console_lock(), console_unlock() +#include //synchronize_irq() +#include //LIST_POISON1, LIST_POISON2 +#include //timer_pending() +#include //disable_irq()/enable_irq() +#include // irq_common_data +#include //irq_has_action + +#define pause_irq_save(irq) ({bool __state = irq_has_action(irq); if (__state) { disable_irq(irq); } __state; }) +#define resume_irq_saved(irq, saved) if (saved) { enable_irq(irq); } + +/*********************************************** Extracting 8250 ports ************************************************/ +static struct uart_8250_port *serial8250_ports[UART_NR] = { NULL }; //recovered ptrs to serial8250_ports structure +static override_symbol_inst *ov_uart_match_port = NULL; + +/** + * Fake uart_match_port() which always returns "no match" but collects all passing ports to serial8250_ports + * + * See recover_serial8250_ports() for usage. This is a very specific thing and shouldn't be used standalone. + * + * @return 0 + */ +static int uart_match_port_collector(struct uart_port *port1, struct uart_port *port2) +{ + //our fake trigger calls with one port being NULL, that's how we can easily detect which one is the one provided by + //the driver ;] + struct uart_port *port = port1 ? port1:port2; + pr_loc_dbg("Found ptr to line=%d iobase=0x%03lx irq=%d", port->line, port->iobase, port->irq); + + serial8250_ports[port->line] = container_of(port, struct uart_8250_port, port); + + return 0; +} + +/** + * Enables collecting of 8250 serial port structures + * + * Warning: before you do that you MUST disable IRQs or you're risking a serious crash or a silent corruption of the + * kernel! + * + * @return 0 on success, -E on failure + */ +static int __must_check enable_collector_matcher(void) +{ + if (unlikely(ov_uart_match_port)) + return 0; //it's not a problem is we already enabled it as it's enabled all the time + + ov_uart_match_port = override_symbol("uart_match_port", uart_match_port_collector); + if (unlikely(IS_ERR(ov_uart_match_port))) { + int out = PTR_ERR(ov_uart_match_port); + ov_uart_match_port = NULL; + return out; + } + + return 0; +} + +/** + * Disabled collecting of 8250 serial port structures (reverses enable_collector_matcher()) + * + * @return 0 on success or noop, -E on failure + */ +static int disable_collector_matcher(void) +{ + if (unlikely(!ov_uart_match_port)) + return 0; //it's not a problem is we already disabled it + + int out = restore_symbol(ov_uart_match_port); + ov_uart_match_port = NULL; + + if (unlikely(out != 0)) + pr_loc_err("Failed to disable collector matcher, error=%d", out); + + return out; +} + +/** + * Fish-out 8250 serial driver ports from its internal structures + * + * The 8250 serial driver is very secretive of its ports and doesn't allow anyone to access them. This is for a good + * reason - it's very easy to cause a deadlock, KP, or a runaway CPU-hogging process. However, we must access them as + * we're intentionally messing up with the structures of them (as SOMEONE had a BRILLIANT idea to break them by swapping + * iobases and IRQs defined since the 1970s). + * + * Ports will be populated in a serial8250_ports. + */ +static int recover_serial8250_ports(void) +{ + int out = 0; + //Stops and buffers printks while pulling console semaphore down (in case console is active on any of the ports) + console_lock(); + preempt_disable(); + + //We cannot acquire any locks as we don't have ports information. The most we can do is ensure nothing tirggers + // while we collect them. It's imperfect as some ports are timer based etc. However, the chance is abysmal that + // with preempt disabled and IRQs disabled something magically triggers ports lookup (which is rare by itself). + //While there may be more than 4 ports their IRQs aren't well defined by the platform nor kernel. + //Some of these may be shared but we don't make assumptions here (as it will be a noop if we call it twice) + bool com1_irq_state = pause_irq_save(STD_COM1_IRQ); + bool com2_irq_state = pause_irq_save(STD_COM2_IRQ); + bool com3_irq_state = pause_irq_save(STD_COM3_IRQ); + bool com4_irq_state = pause_irq_save(STD_COM4_IRQ); + + if (unlikely((out = enable_collector_matcher()) != 0)) { //Install a fake matching function + pr_loc_err("Failed to enable collector!"); + goto out; + } + + _serial8250_find_port(NULL); //Force the driver to iterate over all its ports... using our fake matching function + + if (unlikely((out = disable_collector_matcher()) != 0)) //Restore normal matcher + pr_loc_err("Failed to enable collector!"); + + //Other processes will use spinlocks with IRQ-save as we now know the ports + out: + resume_irq_saved(STD_COM1_IRQ, com1_irq_state); + resume_irq_saved(STD_COM2_IRQ, com2_irq_state); + resume_irq_saved(STD_COM3_IRQ, com3_irq_state); + resume_irq_saved(STD_COM4_IRQ, com4_irq_state); + preempt_enable(); + console_unlock(); + + return out; +} + +/** + * Gets an internal 8250 driver port structure for the line/ttyS specified + * + * Things to know: + * - line = ttyS#, so line=0 = ttyS0 (this is universal across Linux UART subsystem) + * - this function returns things as-is in the 8250 driver, so if ports are already reversed you will get them reversed + * - this function only runs scanning once but only ptrs are stored, so if you flip ports the re-scan is not needed as + * 8250 builds its internal array (to which elements we get ptrs) only once during boot + * + * @return ptr to a port OR error ptr with -E + */ +static __must_check struct uart_8250_port *get_8250_port(unsigned int line) +{ + if (unlikely(line >= UART_NR)) { + pr_loc_bug("Requested UART line %u but kernel supports up to %u", line, UART_NR); + return ERR_PTR(-EINVAL); + } + + if (!serial8250_ports[0]) //Port not recovered or port 0 doesn't exist (HIGHLY unlikely) + recover_serial8250_ports(); //there's no point in checking the return code here - it will fail below + + return (likely(serial8250_ports[line])) ? serial8250_ports[line] : ERR_PTR(-ENODEV); +} + + +/****************************************** Shutting down & restarting ports ******************************************/ +#define is_irq_port(uart_port_ptr) ((uart_port_ptr)->irq != 0) + +/** + * Check if IRQ-based port is active (i.e. open and running) + * + * To use this function the caller is responsible for obtaining a port spinlock. + * + * Warning: it's up to the CALLER to check type of the port (is_irq_port()). Passing a timer-based port here will + * always return false, as timer ports don't register for IRQs and are not listed in IRQ-sharing list. + */ +static bool __always_inline is_irq_port_active(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + + //if the kernel doesn't have an action for the IRQ there's no way 8250 has the port active in interrupt mode + if (!irq_has_action(port->irq)) { + pr_loc_dbg("IRQ=%d not active => port not active", port->irq); + return false; + } + + //IRQ port list was never initialized, or it was deleted (which poisons it) => list element is invalid + // We don't care where prev/next point - they can point both at us (=we're the only ones active on that IRQ), + // can both point at a single other element (=two element list with us included), or can point to two different + // elements (=list with >2 elements). Either way WE are active. + if (!up->list.prev || !up->list.next) { + pr_loc_dbg("IRQ sharing list not initialized => port not active"); + return false; + } + + if (up->list.next == LIST_POISON1 && up->list.prev == LIST_POISON2) { + pr_loc_dbg("IRQ sharing list poisoned/deleted => port not active"); + return false; + } + + pr_loc_dbg("Port is active (IRQ=%d active, list valid p=%p/n=%p)", port->irq, up->list.prev, up->list.next); + return true; +} + +/** + * Checks if a timer-based port is active (i.e. open and running) + * + * To use this function the caller is responsible for obtaining a port spinlock. + * + * For the timer-based port to be active it must: have a function set (=it was configured at least once), and be + * in active or pending state. We only care about the pending one as time timer cannot be active (=currently + * executing handler function) when we have a lock on the port. + * + * Warning: it's up to the CALLER to check type of the port (is_irq_port()). Passing IRQ port here will always return + * false, as IRQ ports don't use timers. + */ +static bool __always_inline is_timer_port_active(struct uart_8250_port *up) +{ + return (likely(up->timer.function) && timer_pending(&up->timer)); +} + +/** + * Checks if a given port is active (i.e. open and running) + * + * The startup & shutdown of the port is needed any time the port is active/open. The port is formally shut down if + * there's nooone using it. The 8250 driver doesn't really know that (ok, it does if you try to probe the chip etc) + * directly, as only the TTY serial layer tracks that (drivers/tty/serial/serial_core.c). + * + * The trick here is that We cannot check if the driver has the + * interrupt for a given port directly (as the irq_lists is static). However, we can derive this by checking if the + * kernel has the IRQ handler registered for the given IRQ# *AND* if the port in question is part of the list for + * the IRQ. We can cheat here as we only need to know our own state. So in practice we need to just check if our + * list element (embedded list_head) is valid. See code for details. + * While technically we CAN re-shutdown a port as many times as we want AS LONG AS it's not using the IRQ subsystem we + * shouldn't re-start a port which wasn't started before we tinkered with it! This is why we take care of IRQ and non- + * IRQ ports in the same. If you attempt to shutdown already shutdown port which is an IRQ one it will result in a + * kernel BUG() as the driver detects that something went wrong as it expects the IRQ to be running. If you do the + * same with timer-based port it will simply re-clear registries on the UART chip which will be a noop hardware-wise. + * This is because the 8250 and derivates cannot be really turned off once they start/reset. They can only be set in a + * way that they don't deliver interrupts for new data (and any new data will just override existing one). With timer- + * based port the kernel simply don't ask the chip if there's any data but the chip is still running. This is exactly + * why the 8250 driver will always attempt a read before "starting" the port and clear FIFOs on it. + */ +static bool is_port_active(struct uart_8250_port *up) +{ + bool out; + struct uart_port *port = &up->port; + pr_loc_dbg("Checking if port iobase=0x%03lx irq=%d (mapped to ttyS%d) active", port->iobase, port->irq, port->line); + + //Most of the ports will be IRQs unless something's broken/special about the platform + if (likely(is_irq_port(port))) + out = is_irq_port_active(up); + else + out = is_timer_port_active(up); + + return out; +} + +/** + * Shuts down the port if it's active + * + * You should NOT call this function with a lock active! + * + * @return 0 if the operation resulted in noop, 1 if the port was actually shut down; currently there are no error + * conditions + */ +static inline int try_shutdown_port(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + pr_loc_dbg("Shutting down physical port iobase=0x%03lx (mapped to ttyS%d)", port->iobase, port->line); + + if (!is_port_active(up)) { + pr_loc_dbg("Port not active - noop"); + return 0; + } + + port->ops->shutdown(port); //this must be called with the lock released or otherwise a deadlock may occur + if (is_irq_port(port)) + synchronize_irq(port->irq); //Make sure interrupt handler is not running on another CPU/core + + pr_loc_dbg("Port iobase=0x%03lx ttyS%d is now DOWN", port->iobase, port->line); + + return 1; +} + +/** + * Restart previously stopped port + * + * Warnings: + * - you shouldn't attempt to restart ports which weren't configured; this can lead to a KP + * - you should NOT call this function when holding a lock + * + */ +static inline void restart_port(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + pr_loc_dbg("Restarting physical port iobase=0x%03lx (mapped to ttyS%d)", port->iobase, port->line); + + //We are not checking if the port is active here due to an edge case of swap between one port which is active where + // another one isn't. In such case when we shut down that active port and try to activate the other (to keep the + // userland state happy) the check will lead to a false-negative state saying the port is already active. This is + // because we did swap IRQ values. However, we MUST restart such port not to reinit the hardware (which doesn't + // care) but to fix the interrupt mapping in the kernel! + //skip extensive tests - it was working before +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5,0,0) + port->flags |= UPF_NO_TXEN_TEST; +#else + port->quirks |= UPQ_NO_TXEN_TEST; +#endif + port->flags |= UPF_SKIP_TEST; + port->ops->startup(port); //this must be called with the lock released or otherwise a deadlock may occur + + pr_loc_dbg("Port iobase=0x%03lx ttyS%d is now UP", port->iobase, port->line); +} + + +/*************************************************** Swapping logic ***************************************************/ +/** + * Swaps two UART data lines with proper locking + * + * This function assumes ports are already stopped. + */ +static inline void swap_uart_lanes(struct uart_8250_port *a, struct uart_8250_port *b) +{ + unsigned long flags_a, flags_b; + spin_lock_irqsave(&a->port.lock, flags_a); + spin_lock_irqsave(&b->port.lock, flags_b); + + swap(a->port.iobase, b->port.iobase); + swap(a->port.irq, b->port.irq); + swap(a->port.uartclk, b->port.uartclk); //Just to be complete we should move flags & clock + swap(a->port.flags, b->port.flags); // (they're probably the same anyway) + swap(a->timer, b->timer); //if one port was timer based and another wasn't this ensures they aren't broken + + spin_unlock_irqrestore(&a->port.lock, flags_b); //flags_a were a property of B + spin_unlock_irqrestore(&b->port.lock, flags_a); +} + +int uart_swap_hw_output(unsigned int from, unsigned int to) +{ + if (unlikely(from == to)) + return -EINVAL; + + pr_loc_dbg("Swapping ttyS%d<=>ttyS%d started", from, to); + + struct uart_8250_port *port_a = get_8250_port(from); + struct uart_8250_port *port_b = get_8250_port(to); + + if (unlikely(!port_a)) { + pr_loc_err("Failed to locate ttyS%d port", from); + return PTR_ERR(port_a); + } + if (unlikely(!port_b)) { + pr_loc_err("Failed to locate ttyS%d port", to); + return PTR_ERR(port_b); + } + + + pr_loc_dbg("Disabling preempt & locking console"); + pr_loc_inf("======= OUTPUT ON THIS PORT WILL STOP AND CONTINUE ON ANOTHER ONE (swapping ttyS%d & ttyS%d) =======", + from, to); //That will be the last message user sees before swap on the "old" port + + pr_loc_dbg("### LAST MESSAGE BEFORE SWAP ON \"OLD\" PORT ttyS%d<=>ttyS%d", from, to); + preempt_disable(); //we cannot be rescheduled here due to timing constraint and possibly IRQ interactions + console_lock(); //We don't want stray messages landing somewhere randomly when we swap, + the ports will be down + //this will be the first message after port unlocks after swapping + pr_loc_dbg("### FIRST MESSAGE AFTER SWAP ON \"NEW\" PORT ttyS%d<=>ttyS%d", from, to); + + //This is an edge case when swapping two ports where one is active and another one is not. Since the active status + // is a property of the software (i.e. port opened/used by something) and shutting down/starting alters the state + // of the hardware we may have a problem with restarting the previously inactive port. If WE did shut it down there + // is no issue as we know the hardware is initialized. But if it wasn't and we try to just start it up without + // reinit we can either crash the driver or leave the port in inactive state. + pr_loc_dbg("Disabling ports"); + int port_a_was_running = try_shutdown_port(port_a); + int port_b_was_running = try_shutdown_port(port_b); + if (unlikely(port_a_was_running != port_b_was_running)) + pr_loc_wrn("Swapping hw data paths of ttyS%d (was %sactive) and ttyS%d (was %sactive). We will attempt to " + "reactivate inactive one but this may fail.", port_a->port.line, port_a_was_running ? "" : "in", + port_b->port.line, port_b_was_running ? "" : "in"); + + swap_uart_lanes(port_a, port_b); + //This code IS CORRECT - make sure to read comment next to port_a_was_running/port_b_was_running vars initialization + //We swapped the data paths but we need to restore the state as the userland expects it. + pr_loc_dbg("Restarting ports"); + if (port_a_was_running) + restart_port(port_a); + if (port_b_was_running) + restart_port(port_b); + + console_unlock(); + preempt_enable(); + + pr_loc_inf("======= OUTPUT ON THIS PORT CONTINUES FROM A DIFFERENT ONE (swapped ttyS%d & ttyS%d) =======", from, + to); + + pr_loc_dbg("Swapping ttyS%d (curr_iob=0x%03lx) <=> ttyS%d (curr_iob=0x%03lx) finished successfully", from, + port_a->port.iobase, to, port_b->port.iobase); + + return 0; +} diff --git a/internal/uart/uart_swapper.h b/internal/uart/uart_swapper.h new file mode 100644 index 0000000..e04bff8 --- /dev/null +++ b/internal/uart/uart_swapper.h @@ -0,0 +1,18 @@ +#ifndef REDPILL_UART_SWAPPER_H +#define REDPILL_UART_SWAPPER_H + +/** + * Swaps two given UARTs/serial prots so that their data paths are exchanged without the change of /dev/tty# + * + * This method is blind to whether UARTs were swapped during kernel build. However, it's the reason it exists to un-swap + * these stupid ports. You can swap any ports you want. It's not recommended to swap ports which are in different run + * state (i.e. one is active/open/running and the other one is not). In such cases the swap will be attempted BUT the + * port which was active may not be usable until re-opened (usually it will be, but there's a chance). + * + * @param from Line number (line = ttyS#, so line=0 = ttyS0; this is universal across Linux UART subsystem)) + * @param to Line number + * @return 0 on success or -E on error + */ +int uart_swap_hw_output(unsigned int from, unsigned char to); + +#endif //REDPILL_UART_SWAPPER_H diff --git a/internal/uart/virtual_uart.c b/internal/uart/virtual_uart.c new file mode 100644 index 0000000..1e957f3 --- /dev/null +++ b/internal/uart/virtual_uart.c @@ -0,0 +1,1032 @@ +/** + * A true National Semiconductors 16550A software emulator + * + * WHAT IS THIS? + * ------------- + * In short this provides a feature-complete emulation of the now-famous 16550A chip present in IBM/PC compatibles + * since ~1987. This emulator was prepared to work with the Linux 8250 driver and fool it into believing it talks with a + * real chip. Moreover, the code isn't hacking around any private parts of the kernel but rather fully emulates + * registries and their behaviors according to the chip's data sheet. + * The emulation layer supports standard 8250-compliant feature (in essence UART) set with addition of two 16 bytes + * TX/RX FIFOs with configurable threshold as well as timer or virtual IRQ model. The code should be pretty + * straight-forward to read but it contains MANY quirks. All of them however are heavily documented throughout the file. + * + * DEALING WITH OPEN PORTS + * ----------------------- + * While using this module you should know that there's a one important quirk: since we're in the Linux kernel we can + * do anything with the port even if it's open. It's a blessing and a curse. Even if the physical ttyS1 port is open and + * you add a virtual ttyS1 all of the sudden all applications will talk to your virtual port. This is great as you don't + * have to restart them but it's also bad while debugging as you may get input you don't expect. To see what's using the + * port execute "ls -l /proc/[0-9]/fd/ 2>&1 |grep /dev/ttyS1 2>&1 | grep ttyS" (replace ) + * as lsof is not available in pre-boot. + * A note however: the /dev/ttyS node WILL be recreated, so if you do replce a port which was opened you can expect to + * see "/dev/ttyS1 (deleted)" in the ls output from above. It is not an issue as we're "taking over" the port anyway so + * both the /dev/ttyS1 as well as the old fd are pointing to the same place kernel-wise. + * + * LIMITATIONS + * ----------- + * - For obvious reasons (as we are not working with a real hw) the DMA portion of the chip is not emulated + * - On most system the maximum number of UARTs emulated is 4 (driver's limitation, see CONFIG_SERIAL_8250_NR_UARTS) + * - FIFOs, true to the original 16550A, are limited to 16 bytes each. In theory, if needed, they can be enlarge up to + * even 256 bytes each with chip model change (as 8250 driver actually tests how big a FIFO is on setup) + * - FIFO mode is always enabled. There are some not-fully-accurate pieces which don't handle non-FIFO operation. There + * is (at least to our knowledge) no reason to use it adn kernel always asks for FIFO to save CPU anyway. + * + * USAGE + * ----- + * See header file docs. + * + * INTERNALS + * --------- + * - To DISABLE vIRQ and fall back to a timer (offered by 8250) define VUART_USE_TIMER_FALLBACK - this will cause the + * Linux driver to poll every so often for new data. This is fine if the port is opened-written to-closed but not + * when apps keep it long open (as the APIC timer will constantly fire for nothing) + * - To see detailed logs of registries being accessed and modified and what not define VUART_DEBUG_LOG - you will get + * all the info you need for debugging. However keep in mind setting this along with VUART_USE_TIMER_FALLBACK will be + * pretty catastrophic as you will be flooded with messages about IIR being read as long as the port stays open in + * the userland. This consciously does not use kernel's dynamic debug facilities are some (e.g. 918+) kernels are + * compiled without it. + * - To change name of the vIRQ thread define VUART_THREAD_FMT which gets a real port IRQ # and ttyS# as its params. + * - UART_BUG_SWAPPED (defined in uart_defs.h) is used to detect swapped ports and make sure numbers used here are real + * ttyS* values and not swapped bs (as 8250 matches ports by iobase and not line#) + * + * References: + * - https://github.com/clearlinux/kvmtool/blob/b5891a4337eb6744c8ac22cc02df3257961ae23e/hw/serial.c (inspiration) + * - https://www.ti.com/lit/ug/sprugp1/sprugp1.pdf (everything you need to know abt UART, referred in code as "Ti doc") + * - http://caro.su/msx/ocm_de1/16550.pdf (useful and short UART know-how with a good registry table in Table 2, p. 9) + * - https://www.linuxjournal.com/article/8144 (handling threading in kernel) + */ + +//Here are some flags which can be used to modify the behavior of VirtualUART. They're checked by other header files. +//Keep in mind you may need to set the debug in vuart_virtual_irq separatedly (or in common.h) +//#define VUART_DEBUG_LOG +//#define VUART_USE_TIMER_FALLBACK + +#include "virtual_uart.h" +#include "vuart_internal.h" +#include "../../common.h" //can set VUART_DEBUG_LOG and others +#include "../../debug/debug_vuart.h" //it will provide normal or nooped versions of macros; CHECKS VUART_DEBUG_LOG +#include "../../config/uart_defs.h" //COM defs & struct uart_port +#include "../../internal/intercept_driver_register.h" //is_driver_registered, watch_driver_register, unwatch_driver_register +#include "vuart_virtual_irq.h" //vIRQ handling & shimming; CHECKS VUART_USE_TIMER_FALLBACK +#include //serial8250_unregister_port, uart_8250_port +#include //UART_* consts +#include //locking devices (vdev->lock) +#include //kfifo_* + +/************************************************* Static definitions *************************************************/ +/* + * According to https://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming bits 6 and 7 must be set to + * consider FIFO as enabled-and-working (bit 7 only designates "FIFO enabled, but not functioning" (?) + */ +#define UART_IIR_FIFOEN 0xc0 +#define UART_IIR_FIFEN_B6 0x40 +#define UART_IIR_FIFEN_B7 0x80 +#define UART_DRIVER_NAME "serial8250" //see drivers/tty/serial/8250/8250_core.c in "serial8250_isa_driver" + +/** + * Static definition of all possible UARTs in the system supported by 8250 driver + * These definitions are exactly the same as in arch/x86/include/asm/serial.h + */ +static struct serial8250_16550A_vdev ttySs[] = { +//we're crying too... the issue is normally operate on port lines (=ttyS#) but during port registration ports the driver +// performs matching based on its internal iobase mapping, so we can ask for the port to be line=0 but if the driver +// finds a port with iobase specified under line=1 it will just register is as line=1 instead of line=0. This causes all +// sorts of problems as during reads we expect the vdev line to match what we actually registered. To fix it and make it +// independent of all fucking swapping and reswapping we will have to emit events from uart_swapper and other nonsense +// ...this is ridiculous. So we take a sane assumptions: +// - if the kernel is broken we accommodate for that assuming no un-swapping will be done afterwards +// - if the kernel is broken and swap fix is disabled by debug flag we handle the swapping +// - if something is borked we don't offer a detection comparing lines because before we get a response from the driver +// registering the port it will call our read function and break everything +// TODO: this whole code should switch to relying on iobases instead o lines. This way when we do reads or writes we +// don't care if something is swapped - we call for registration on line 0, we lookup what's the expected iobase +// for that ttyS and we register for it. If the driver decides to use a different line# we shouldn't care. +#if defined(UART_BUG_SWAPPED) && defined(DBG_DISABLE_UART_SWAP_FIX) + [0] = { .line = 0, .iobase = STD_COM2_IOBASE, .irq = STD_COM2_IRQ, .baud = STD_COMX_BAUD }, //COM1 aka ttyS1 + [1] = { .line = 1, .iobase = STD_COM1_IOBASE, .irq = STD_COM1_IRQ, .baud = STD_COMX_BAUD }, //COM2 aka ttyS0 +#else + [0] = { .line = 0, .iobase = STD_COM1_IOBASE, .irq = STD_COM1_IRQ, .baud = STD_COMX_BAUD }, //COM1 aka ttyS0 + [1] = { .line = 1, .iobase = STD_COM2_IOBASE, .irq = STD_COM2_IRQ, .baud = STD_COMX_BAUD }, //COM2 aka ttyS1 +#endif + [2] = { .line = 2, .iobase = STD_COM3_IOBASE, .irq = STD_COM3_IRQ, .baud = STD_COMX_BAUD }, //COM3 aka ttyS2 + [3] = { .line = 3, .iobase = STD_COM4_IOBASE, .irq = STD_COM4_IRQ, .baud = STD_COMX_BAUD }, //COM4 aka ttyS3 +}; + +//Internal type for callbacks; see vuart_set_tx_callback() for details +struct flush_callback { + vuart_callback_t *fn; + void *buffer; + int threshold; +}; +//Storage for all TX callbacks, see vuart_set_tx_callback() +static struct flush_callback *flush_cbs[SERIAL8250_LAST_ISA_LINE] = { NULL }; +static volatile bool kernel_driver_ready = false; //Whether the 8250 UART driver is ready + +/**************************************** Internal helper function-like macros ****************************************/ +//Get vDEV from line/ttyS number (created for consistency) +#define get_line_vdev(line) (&ttySs[(line)]) + +//8250 driver doesn't give access to the real uart_port upon adding but does it on first read/write +#define capture_uart_port(vdev, port) if (unlikely(!(vdev)->up)) (vdev)->up = port; + +//Some functions should warn use out of courtesy that we're running in a stupid environment +#if defined(UART_BUG_SWAPPED) && defined(DBG_DISABLE_UART_SWAP_FIX) +#define warn_bug_swapped(line) \ + if ((line) < 2) { \ + pr_loc_inf( \ + "Requested ttyS%d vUART - this kernel has UART SWAP => modifying what physically is ttyS%d (io=0x%x)", \ + line, !line, get_line_vdev(line)->iobase); \ + } +#else +#define warn_bug_swapped(line) //noop +#endif + +#define for_each_vdev() for (int line=0; line < ARRAY_SIZE(ttySs); ++line) + +//Before v3.13 the kfifo_put() accepted a pointer, since then it accepts a value +//ffs... https://github.com/torvalds/linux/commit/498d319bb512992ef0784c278fa03679f2f5649d +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) +#define kfifo_put_val(fifo, val) kfifo_put(fifo, &val) +#else +#define kfifo_put_val(fifo, val) kfifo_put(fifo, val) +#endif + +/****************************************** Internal chip emulation functions ******************************************/ +/** + * Updates state of the IIR register + * + * In the physical world when the UART chip is connected to the CPU there's an interrupt line which goes high when + * the chip detects any of the conditions which are interrupt-worthy. Whether something is interrupt-worthy is + * determined by the driver (i.e. Linux kernel) and set in the IER. When an interrupt is generated the kernel gets only + * the information "something happened on IRQ 4" (which means SOMETHING happened on COM1 *or* COM 3). To determine + * what it is (or maybe there multiple things even!) the kernel reads IIR which gives the REASON why a given interrupt + * happened (and thus also indirectly specifies which channel/chip generated the interrupt). + * + * This code below is written based on the Table 3-6 in Ti doc - it summarizes IIR state and how it should change. It + * should be called AFTER everything else modified registers. In general if you changed some other registries you should + * call this function. You usually want to do it once upon returning control to an outside caller (after making all + * all changes). + * + * Regardless of whether vIRQ is enabled or not this register MUST be updated. + */ +static void update_interrupts_state(struct serial8250_16550A_vdev *vdev) +{ + uart_prdbg("Recomputing IIR state"); + //Order of these if/elseifs is CRUCIAL - interrupts have priorities and they're masked + u8 new_iir_int_state = 0; + if ((vdev->ier & UART_IER_RLSI) && + unlikely((vdev->lsr & UART_LSR_OE) || (vdev->lsr & UART_LSR_PE) || (vdev->lsr & UART_LSR_FE) || + (vdev->lsr & UART_LSR_BI))) { + //Kernel enabled OE/PE/FE/BI interrupts and there's one of them + uart_prdbg("IIR: setting RLS (errors) interrupt"); + new_iir_int_state |= UART_IIR_RLSI; + } else if ((vdev->ier & UART_IER_RDI) && (vdev->lsr & UART_LSR_DR)) { + //We don't distinguish between FIFO and non-FIFO mode and just set interrupt if there's some data to be read + //We also don't support the receiver time-out (kernel should pick up the data in time as it's a virtual port) + uart_prdbg("IIR: setting RD (data-ready) interrupt"); + new_iir_int_state |= UART_IIR_RDI; + } else if ((vdev->ier & UART_IER_THRI) && ((vdev->lsr & UART_LSR_TEMT) || kfifo_is_empty(vdev->tx_fifo))) { + //When THR is empty or FIFO is empty (for us it's the same thing) kernel wants to know about that + uart_prdbg("IIR: setting THR (transmitter empty) interrupt"); + new_iir_int_state |= UART_IIR_THRI; + } + + //If any interrupts are triggered (or not) we need to set IPEND accordingly + if (new_iir_int_state) { + new_iir_int_state &= ~UART_IIR_NO_INT; //since there were some interrupts we clear IPEND (=interrupts pending) + vuart_virq_wake_up(vdev); + } else { + new_iir_int_state |= UART_IIR_NO_INT; //since there were no interrupts we set IPEND (=no interrupts pending) + } + + //IIR (despite its name) also contains FIFO status along interrupts + vdev->iir = new_iir_int_state; + if (likely(vdev->fcr & UART_FCR_ENABLE_FIFO)) + vdev->iir |= UART_IIR_FIFOEN; + + dump_iir(vdev); + uart_prdbg("Finished IIR state"); +} + +/** + * Put registries into the "chip reset" state as described by the datasheet (see Tables 3-* in Ti doc) + * You should NOT modify these values under any circumstances as they're meant to represent the real chip RESET state + */ +static void reset_device(struct serial8250_16550A_vdev *vdev) +{ + uart_prdbg("Resetting virtual chip @ ttyS%d", vdev->line); + lock_vuart_oppr(vdev); + + //Upon reset both FIFOs must be erased + if (vdev->tx_fifo) + kfifo_reset(vdev->tx_fifo); + if (vdev->rx_fifo) + kfifo_reset(vdev->rx_fifo); + + //Registries for when DLAB=0 + vdev->rhr = 0x00; //no data in receiving channel + vdev->thr = 0x00; //no data in transmission channel + vdev->ier = 0x00; //no interrupts enabled + vdev->iir = UART_IIR_NO_INT; //no pending interrupts, FIFO not active + vdev->fcr = 0x00; //FIFO disabled (which invalidates other FIFO properties in FCR), DMA disabled + vdev->lcr = 0x00; //non-DLAB mode, errors cleared, 1 STOP bit, 5 bit words (not that it matters for virtual port) + vdev->mcr = UART_MCR_OUT2; //autoflow disabled, loop mode disabled, OUT2 enabled as global interrupt + vdev->lsr = UART_LSR_TEMT | UART_LSR_THRE; //transmitter empty & idle, all errors cleared, break not requested + vdev->msr = 0x00; //all flow control flags not triggered + vdev->scr = 0x00; //empty scratchpad + + //Additional registries when DLAB=1 + vdev->dll = 0x00; //undefined divisor LSB latch + vdev->dlm = 0x00; //undefined divisor MSB latch + + unlock_vuart_oppr(vdev); + uart_prdbg("Virtual chip @ ttyS%d reset done", vdev->line); +} + +/** + * Allocate/create FIFOs on the device if they don't exist (and if they do you shouldn't call this function) + * + * @todo it should free on errors + */ +static int alloc_fifos(struct serial8250_16550A_vdev *vdev) +{ + if (unlikely(vdev->rx_fifo)) { //this shouldn't happen on non-initialized port + pr_loc_bug("RX FIFO @ %d already alloc'd", vdev->line); + return -EINVAL; + } + + if (unlikely(vdev->tx_fifo)) { //this shouldn't happen on non-initialized port + pr_loc_bug("TX FIFO @ %d already alloc'd", vdev->line); + return -EINVAL; + } + + kzalloc_or_exit_int(vdev->rx_fifo, sizeof(struct kfifo)); + kzalloc_or_exit_int(vdev->tx_fifo, sizeof(struct kfifo)); + + if (unlikely(kfifo_alloc(vdev->rx_fifo, VUART_FIFO_LEN, GFP_KERNEL) != 0)) { + pr_loc_crt("kfifo_alloc for RX FIFO elements @ %d failed", vdev->line); + return -EFAULT; + } + + if (unlikely(kfifo_alloc(vdev->tx_fifo, VUART_FIFO_LEN, GFP_KERNEL) != 0)) { + pr_loc_crt("kfifo_alloc for TX FIFO elements @ %d failed", vdev->line); + return -EFAULT; + } + + return 0; +} + +/** + * Reverses what alloc_fifos() did + */ +static int free_fifos(struct serial8250_16550A_vdev *vdev) +{ + //This should be called when the vIRQ thread is killed so nothing call the IRQ handler without FIFOs + if (unlikely(!vdev->rx_fifo || !vdev->tx_fifo)) { //this shouldn't happen on initialized port + pr_loc_bug("RX and/or TX FIFO @ %d are not alloc'd (nothing to free)", vdev->line); + return -EINVAL; + } + + kfifo_free(vdev->rx_fifo); + kfifo_free(vdev->tx_fifo); + + return 0; +} + +/** + * Deposits the TX queue contents into callbacks set using vuart_set_tx_callback() and clears the FIFO itself + * If no callbacks were defined it will simply clear. + * + * This function does NOT recalculate IIRs (see update_interrupts_state()) and assumes you have vdev lock. + */ +static void flush_tx_fifo(struct serial8250_16550A_vdev *vdev, vuart_flush_reason reason) +{ + uart_prdbg("Flushing TX FIFO now! reason=%d", reason); + + if (likely(flush_cbs[vdev->line])) { + unsigned int flushed_bytes = 0; + flushed_bytes = kfifo_out(vdev->tx_fifo, flush_cbs[vdev->line]->buffer, VUART_FIFO_LEN); + flush_cbs[vdev->line]->fn(vdev->line, flush_cbs[vdev->line]->buffer, flushed_bytes, reason); + } else { + uart_prdbg("No callback for TX FIFO @ %d - discarding", vdev->line); + kfifo_reset(vdev->tx_fifo); + } + + vdev->lsr |= UART_LSR_TEMT | UART_LSR_THRE; //nothing should be in the buffer +} + +/** + * Pulls a character/byte from RX FIFO and places it into RHR for the driver to read it + * - It updates all registers according to the specs + * - It assumes you have vdev lock + * - It does NOT recalculate IIRs (see update_interrupts_state()) + * - It will produce an error if you try to do the transfer while FIFO is empty but it will not crash. You should check + * UART_LSR_DR before calling this function. + * + * @return character which was read + */ +static unsigned char transfer_char_fifo_rhr(struct serial8250_16550A_vdev *vdev) +{ + //Before this function is called UART_LSR_DR should be verified - it wasn't or it was wrong if this exploded + if(unlikely(kfifo_get(vdev->rx_fifo, &vdev->rhr) == 0)) + pr_loc_bug("Attempted to %s with empty FIFO - that shouldn't happen if the DR flag was checked", __FUNCTION__); + + if (kfifo_is_empty(vdev->rx_fifo)) + vdev->lsr &= ~UART_LSR_DR; + + //See descriptions of these fields in Table 3-12 from TI doc - these flags are cleared on character read + vdev->lsr &= ~UART_LSR_BI; + vdev->lsr &= ~UART_LSR_FE; + vdev->lsr &= ~UART_LSR_PE; + vdev->lsr &= ~UART_LSR_OE; //by definition, we cannot have overrun if a character was just read + + return vdev->rhr; +} + +/** + * An alternative to transfer_char_fifo_rhr() when FIFOs aren't used for transfers (e.g. in MSR TEST/LOOP mode) + * + * This function does NOT recalculate IIRs (see update_interrupts_state()) and assumes you have vdev lock. + */ +static void handle_receive_char(struct serial8250_16550A_vdev *vdev, unsigned char value) +{ + //@todo this only handles overruns in FIFO mode and does not do that in non-FIFO; it behaves correctly but it + // doesn't report OEs in non-FIFO + vdev->rhr = value; //RHR is always populated with the value no matter the FIFO or non-FIFO mode + + //Put value in FIFO, it will indicate with return of 0 if it was full before attempted put (overrun/overflow) + if (kfifo_put_val(vdev->rx_fifo, value) == 0) { + vdev->lsr |= UART_LSR_OE; //set overrun flag as FIFO detected that + + //During TEST/LOOP mode many overflows are caused on purpose - we don't want to hear about them really + if (unlikely(!(vdev->mcr & UART_MCR_LOOP))) + pr_loc_wrn("RX FIFO overflow detected @ ttyS%d", vdev->line); + } else { + vdev->lsr &= ~UART_LSR_OE; //no overrun condition - clear OE flag just in case + } + + vdev->lsr |= UART_LSR_DR; //receiver has something for the kernel to pickup +} + +/** + * Called when kernel sent something to the device and it has to be put into TX FIFO & THR + * + * This function does NOT recalculate IIRs (see update_interrupts_state()) and assumes you have vdev lock. + * + * CAUTION: order of these "ifs" for flushes here is crucial: we make a guarantee to the reason parameter that if both + * VUART_FLUSH_THRESHOLD and VUART_FLUSH_FULL are true (i.e. callback was set with threshold == VUART_FIFO_LEN) we + * will prioritize threshold trigger (as a user-specified event takes precedence over internal event of FIFO full) + * If the threshold specified by the callback setter was met flush the FIFO + */ +static void handle_transmit_char(struct serial8250_16550A_vdev *vdev, unsigned char value) +{ + //@todo this only handle non-FIFO properly: doesn't detect OE, and doesn't reset THRE + vdev->thr = value; //THR is always populated with the value no matter the FIFO or non-FIFO mode + vdev->lsr &= ~UART_LSR_THRE; + + int fifo_len = kfifo_len(vdev->tx_fifo); + uart_prdbg("%s got new char ascii=%c hex=%02x on ttyS%d (FIFO#=%d)", __FUNCTION__, value, value, vdev->line, + fifo_len); + + //FIFO is full - try to flush it; if we got here it means the threshold is for sure >VUART_FIFO_LEN as this is + // checked after we put data into the FIFO (to make sure we trigger THRESHOLD event and not FULL) + //The reason why we check this at the beginning of new char and not after adding to FIFO is that if the transmitting + // party sends exactly VUART_FIFO_LEN bytes and then ends the transmission we don't want to flush with FULL but with + // IDLE to give a better sense of what's going on to the caller. FULL implies "we got too much data, there may be + // more coming" while IDLE implies that the unit of transmission ended. + if (unlikely(fifo_len == VUART_FIFO_LEN)) + flush_tx_fifo(vdev, VUART_FLUSH_FULL); + + //Put value in FIFO, it will indicate with return of 0 if it was full before attempted put (overrun/overflow) + //This, if we are correct, cannot happen if the flush_tx_fifo() is functioning correctly as we try to flush above + int fifo_add = kfifo_put_val(vdev->tx_fifo, value); + fifo_len += fifo_add; //we can call kfifo_ API for this but why if we have both pieces of info anyway? ;) + if (unlikely(fifo_add == 0)) { + vdev->lsr |= UART_LSR_OE; //set overrun flag as FIFO detected that + pr_loc_wrn("TX FIFO overflow detected"); + } else { + vdev->lsr &= ~UART_LSR_OE; //no overrun condition - clear OE flag just in case + } + + vdev->lsr &= ~UART_LSR_TEMT; //transmitter buffers are no longer empty + + //@todo THRE should be reset immediately in non-FIFO mode (i.e. at the same time as TEMT) + //This is to prevent kernel from freaking out about "blackhole" UART (see https://unix.stackexchange.com/a/387650) + if (fifo_len >= VUART_FIFO_LEN / 2) + vdev->lsr &= ~UART_LSR_THRE; + + if (likely(flush_cbs[vdev->line]) && fifo_len >= flush_cbs[vdev->line]->threshold) + flush_tx_fifo(vdev, VUART_FLUSH_THRESHOLD); +} + +/** + * The main READ routing passed to the 8250 driver. It should be as fast as possible and MUST be multithread-safe + * + * Device ==responding-to==> kernel; aka "do you have something for me?" + * This function is used to read data and registers. + * + * @param offset This is really the register value. It's named "offset" in accordance with Linux nomenclature which + * makes sense for physical chips (as this is a memory offset from chip's memory base) + */ +static unsigned int serial_remote_read(struct uart_port *port, int offset) +{ + uart_prdbg("Serial READ for line=%d/%d", port->line, ttySs[port->line].line); + + struct serial8250_16550A_vdev *vdev = get_line_vdev(port->line); + lock_vuart(vdev); + capture_uart_port(vdev, port); + unsigned int out; + switch (offset) { + case UART_RX: + //if DLAB is enabled DLL registry is desired; otherwise we should send THR + //See Table 2 in the chip manual. DLAB controls access to address 000, 001, and 101. When DLAB=1 these + //addrs respond with DLL, DLM, and PSD respectively, when DLAB=0 they respond with RHR/THR, IER/DLM, and LSR + if (vdev->lcr & UART_LCR_DLAB) { + out = vdev->dll; + reg_read("DLL"); + } else if (vdev->lsr & UART_LSR_BI) { //chip wants a break? + out = 0; + vdev->lsr &= ~UART_LSR_BI; //clear the break for the next cycle; see BI in Table 3-12 from TI doc + uart_prdbg("LSR indicated break request, cleared"); + dump_lsr(vdev); + } else if(vdev->lsr & UART_LSR_DR) { //Did we receive anything? + out = transfer_char_fifo_rhr(vdev); + dump_lsr(vdev); + uart_prdbg("Providing RHR registry (val=%x DLAB=0 LSR_DR=1)", out); + } else { + out = 0; + //Such read isn't invalid. However, it is done e.g. in the init sequence as a workaround for some + // physical chips bugs in the past or to clear the RHR before other operations (even if LSR DR=0) + uart_prdbg("Nothing in RHR (DLAB=0; LSR_DR=0) - noop"); + dump_lsr(vdev); + } + break; + case UART_IER: + if (vdev->lcr & UART_LCR_DLAB) { + out = vdev->dlm; + reg_read("DLM"); + } else { + out = vdev->ier; + reg_read_dump(vdev, ier, "IER"); + } + break; + case UART_IIR: + out = vdev->iir; + reg_read_dump(vdev, iir, "IIR/ISR"); + break; + //case UART_FCR not present - write only register + case UART_LCR: + out = vdev->lcr; + reg_read_dump(vdev, lcr, "LCR"); + break; + case UART_MCR: + out = vdev->mcr; + reg_read_dump(vdev, mcr, "MCR"); + break; + case UART_LSR: + out = vdev->lsr; + reg_read_dump(vdev, lsr, "LSR"); + vdev->lsr &= ~UART_LSR_OE; //See "OE" Table 3-12 or Table 3-6 - it needs to be cleared on LSR read + break; + case UART_MSR: + out = vdev->msr; + reg_read_dump(vdev, msr, "MSR"); + + //See table 3-13 in Ti doc; MSR is masked with values from MCR when MCR indicates test/loop mode + if (unlikely(vdev->mcr & UART_MCR_LOOP)) { + if (vdev->mcr & UART_MCR_RTS) out |= UART_MSR_CTS; else out &= ~UART_MSR_CTS; + if (vdev->mcr & UART_MCR_DTR) out |= UART_MSR_DSR; else out &= ~UART_MSR_DSR; + if (vdev->mcr & UART_MCR_OUT1) out |= UART_MSR_RI; else out &= ~UART_MSR_RI; + if (vdev->mcr & UART_MCR_OUT2) out |= UART_MSR_DCD; else out &= ~UART_MSR_DCD; + uart_prdbg("[!] Masked real MSR values to: CTS=%d | DSR=%d | RI=%d | DCD=%d", + out&UART_MSR_CTS?1:0, out&UART_MSR_DSR?1:0, out&UART_MSR_RI?1:0, out&UART_MSR_DCD?1:0); + } + break; + case UART_SCR: + out = vdev->scr; + reg_read("SCR/SPR"); + break; + default: + pr_loc_bug("Unknown registry %x read attempt on ttyS%d", offset, vdev->line); + out = 0; + break; + } + + update_interrupts_state(vdev); + unlock_vuart(vdev); + + return out; +} + +/** + * The main WRITE routing passed to the 8250 driver. It should be as fast as possible and MUST be multithread-safe + * + * Kernel => device, aka "I have something FOR YOU, send it along" + * This function is also used to write registers. + * + * @param offset This is really the register value. It's named "offset" in accordance with Linux nomenclature which + * makes sense for physical chips (as this is a memory offset from chip's memory base) + */ +static void serial_remote_write(struct uart_port *port, int offset, int value) +{ + //uart_prdbg("Serial WRITE for line=%d/%d", port->line, ttySs[port->line].line); + + struct serial8250_16550A_vdev *vdev = get_line_vdev(port->line); + lock_vuart(vdev); + capture_uart_port(vdev, port); + + switch (offset) { + case UART_TX: + //See "case UART_RX" for explanation + if (vdev->lcr & UART_LCR_DLAB) { //DLAB overrides everything + vdev->dll = value; + reg_write("DLL"); + } else if (vdev->mcr & UART_MCR_LOOP) { //are we in the reflection/loop mode? (=> fake TX->RX connection) + uart_prdbg("Loopback enabled, writing %x meant for THR to RHR directly", value); + handle_receive_char(vdev, (unsigned char)value); //loopback emulates receiving char on RX + dump_mcr(vdev); + dump_lsr(vdev); + } else { //just pickup the data from kernel + handle_transmit_char(vdev, (unsigned char)value); + reg_write("THR"); + dump_lsr(vdev); + } + break; + case UART_IER: + if (vdev->lcr & UART_LCR_DLAB) { + vdev->dlm = value; + reg_write("DLM"); + break; + } + + /* + * This is a little shortcut to deliver data to the callback even if the threshold wasn't met. This is + * done since kernel DISABLES THR empty interrupts when it finishes writing (which makes sense - otherwise + * it will be flooded with interrupts all the time as nothing gets written to THR). This means that + * kernel wrote everything what was there to write and [presumably] nothing else is coming anytime soon + * So in short: if THReINT was enabled and it JUST got disabled flush the FIFO if it isn't empty + */ + if ((vdev->ier & UART_IER_THRI) && !(value & UART_IER_THRI) && !kfifo_is_empty(vdev->tx_fifo)) { + uart_prdbg("Kernel driver disabled THRe interrupt and fifo isn't empty - triggering IDLE flush"); + flush_tx_fifo(vdev, VUART_FLUSH_IDLE); + } + vdev->ier = value & 0x0f; //we're not letting kernel set DMA registers since we don't support DMA + reg_write_dump(vdev, ier, "IER"); + break; + //case UART_IIR not present - read only register + case UART_FCR: + //FIFO registers are guarded by the FIFOEN - if it's not set only FIFOEN can be modified, see p27 of Ti doc + if (!(vdev->fcr & UART_FCR_ENABLE_FIFO) && !(value & UART_FCR_ENABLE_FIFO)) + value &= UART_FCR_ENABLE_FIFO; + + vdev->fcr = value; + reg_write_dump(vdev, fcr, "FCR"); + + //If the new FCR value called for flush of TX and/or RX do that right away + if (vdev->fcr & UART_FCR_CLEAR_XMIT) { + kfifo_reset(vdev->tx_fifo); + vdev->lsr |= UART_LSR_TEMT | UART_LSR_THRE; + uart_prdbg("TX FIFO flushed on FCR request"); + dump_lsr(vdev); + } + + if (vdev->fcr & UART_FCR_CLEAR_RCVR) { + kfifo_reset(vdev->rx_fifo); + vdev->lsr &= ~UART_LSR_DR; + uart_prdbg("RX FIFO flushed on FCR request"); + dump_lsr(vdev); + } + break; + case UART_LCR: + vdev->lcr = value; + reg_write_dump(vdev, lcr, "LCR"); + break; + case UART_MCR: + vdev->mcr = value; + reg_write_dump(vdev, mcr, "MCR"); + break; + case UART_LSR: + vdev->lsr = value; + pr_loc_bug("Bogus LSR write attempt on ttyS%d - why?", vdev->line); + dump_lsr(vdev); + break; + case UART_MSR: + vdev->msr = value; + pr_loc_bug("Bogus MSR write attempt on ttyS%d - why?", vdev->line); + dump_msr(vdev); + break; + case UART_SCR: + vdev->scr = value; + reg_write("SCR"); + break; + default: + pr_loc_bug("Unknown registry %x write attempt on ttyS%d with %x", offset, vdev->line, value); + break; + } + + update_interrupts_state(vdev); + unlock_vuart(vdev); +} + + +/************************************************** vUART Glue Layer **************************************************/ +static driver_watcher_instance *driver_watcher = NULL; +static int update_serial8250_isa_port(struct serial8250_16550A_vdev *vdev); +static int restore_serial8250_isa_port(struct serial8250_16550A_vdev *vdev); + +/** + * Initializes/allocates what's needed in a fresh vdev structure (or one which was previously freed) + */ +static int initialize_ttyS(struct serial8250_16550A_vdev *vdev) +{ + int out; + + pr_loc_dbg("Initializing ttyS%d vUART", vdev->line); + if (unlikely(vdev->initialized)) { + pr_loc_bug("ttyS%d is already initialized", vdev->line); + return -EBUSY; + } + + reset_device(vdev); //Puts device in a known RESET state as defined by the real chip docs + if ((out = alloc_fifos(vdev) != 0)) + return out; + + kmalloc_or_exit_int(vdev->lock, sizeof(spinlock_t)); + spin_lock_init(vdev->lock); + + //virq_* stuff is allocated/freed by enable_/disable_interrupts() + + vdev->initialized = true; + pr_loc_dbg("Initialized ttyS%d vUART", vdev->line); + + return 0; +} + +/** + * Deinitializes/frees what was previously built by initialize_ttyS() + */ +static int deinitialize_ttyS(struct serial8250_16550A_vdev *vdev) +{ + int out; + + pr_loc_dbg("Deinitializing ttyS%d vUART", vdev->line); + if (unlikely(!vdev->initialized)) { + pr_loc_bug("ttyS%d is not initialized", vdev->line); + return -ENODEV; + } + + if ((out = free_fifos(vdev) != 0)) + return out; + + kfree(vdev->lock); + vdev->initialized = false; + pr_loc_dbg("Deinitialized ttyS%d vUART", vdev->line); + + return 0; +} + +/** + * Watches for the serial8250 driver to load in order to register ports which were added before the driver loaded + */ +static driver_watch_notify_result serial8250_ready_watcher(struct device_driver *drv, driver_watch_notify_state event) +{ + if (unlikely(event != DWATCH_STATE_LIVE)) + return DWATCH_NOTIFY_CONTINUE; + + pr_loc_dbg("%s driver loaded - adding queued ports", UART_DRIVER_NAME); + kernel_driver_ready = true; + + int out; + for_each_vdev() { + //non-initialized ports are these which were never added as vUARTs + if (!ttySs[line].initialized || ttySs[line].registered) + continue; + + pr_loc_dbg("Processing enqueued port %d", line); + if ((out = update_serial8250_isa_port(&ttySs[line])) != 0) { + //This is critical as ports were promised to be registered to other parts of the application but we cannot + // fulfill that promise now + pr_loc_crt("Failed to process port %d - error=%d", line, out); + } + } + + pr_loc_dbg("Finished processing enqueued ports"); + return DWATCH_NOTIFY_DONE; +} + +/** + * Checks the current serial8250 status + * + * @return 0 if not loaded, 1 if loaded, -E on error + */ +static int probe_driver(void) +{ + if (kernel_driver_ready) + return 1; //we've already checked the state and confirmed as ready before + + int driver_ready_tristate = is_driver_registered(UART_DRIVER_NAME, NULL); + if (driver_ready_tristate < 0) { + pr_loc_err("Failed to check %s driver state - error=%d", UART_DRIVER_NAME, driver_ready_tristate); + return -EIO; + } + + if (driver_ready_tristate == 1) + kernel_driver_ready = true; + + return driver_ready_tristate; +} + +/** + * Attempt to watch for the serial8250 driver readiness (if needed) + * + * @return 0 if driver is not loaded and a watcher has been set up, + * 1 if driver is already loaded (and nothing needs to be done), + * -E on error + */ +static int try_wait_for_serial8250_driver(void) +{ + int driver_ready_tristate = probe_driver(); + if (driver_ready_tristate != 0) + return driver_ready_tristate; //if the driver is ready (=1) or an error occurred (-E) we don't do anything here + + pr_loc_inf("%s driver is not ready - the port addition will be delayed until the driver loads", UART_DRIVER_NAME); + driver_watcher = watch_driver_register(UART_DRIVER_NAME, serial8250_ready_watcher, DWATCH_STATE_LIVE); + + if (IS_ERR(driver_watcher)) { + pr_loc_err("Failed to register driver watcher - no ports can be registered till the driver loads"); + return PTR_ERR(driver_watcher); + } + + return 0; +} + +/** + * Disable the driver watcher if it was set up + * + * @return 0 on success, -E on error + */ +static int try_leave_serial8250_driver(void) +{ + if (!driver_watcher) //we're only concerned about watching the driver + return 0; + + for_each_vdev() { + if (ttySs[line].initialized && !ttySs[line].registered) { + pr_loc_dbg("Cannot leave %s driver yet - port %d is still awaiting registration", UART_DRIVER_NAME, line); + return 0; + } + } + + int out = unwatch_driver_register(driver_watcher); + driver_watcher = NULL; + if (out != 0) + pr_loc_err("Failed to unwatch driver (error=%d)", out); + + return out; +} + +/** + * Asks the Linux 8250 driver to UPDATE properties of a given serial device which matches line & iobase + * + * The reason why this function is called update_ rather than add_ is that we're NOT adding anything new to the driver. + * Rather we're registering a port which is already there (as vUART only deals with COM1-4, i.e. legacy IBM/PC ports) + * and matches our spec. + */ +static int update_serial8250_isa_port(struct serial8250_16550A_vdev *vdev) +{ + int out; + pr_loc_dbg("Registering ttyS%d (io=0x%x) in the driver", vdev->line, vdev->iobase); + + if (unlikely(vdev->registered)) { + pr_loc_bug("Port ttyS%d (io=0x%x) is already registered in the driver", vdev->line, vdev->iobase); + return -EEXIST; + } + + int driver_ready_tristate = try_wait_for_serial8250_driver(); + if (driver_ready_tristate == 0) { + pr_loc_wrn("The %s driver is not ready - vUART port ttyS%d (io=0x%x) will be activated later", UART_DRIVER_NAME, + vdev->line, vdev->iobase); + return 0; + } + + if (driver_ready_tristate < 0) { + pr_loc_err("%s failed due to underlining driver error", __FUNCTION__); + return driver_ready_tristate; + } + + + struct uart_8250_port *up; + kzalloc_or_exit_int(up, sizeof(struct uart_8250_port)); + struct uart_port *port = &up->port; + + port->line = vdev->line; + port->iobase = vdev->iobase; + port->uartclk = vdev->baud * 16; + port->flags = STD_COMX_FLAGS; + + //This is a silly workaround to let the kernel know "we don't REALLY support IRQ" + //While the code do support IRQs handling we weren't able to find a smart way to "simulate" IRQ 3-4 (which are + // normally HW interrupts). However, the 8250 driver will emulate them for us using APIC + port->irq = (vuart_virq_supported()) ? vdev->irq : SERIAL8250_SOFT_IRQ; + port->irqflags = 0; + port->hub6 = 0; + port->membase = 0; + port->iotype = 0; + port->regshift = 0; + port->serial_in = serial_remote_read; + port->serial_out = serial_remote_write; + port->type = PORT_16550A; + up->cur_iotype = 0xFF; + + //DO NOT EVEN THINK about assigning "port" top vdev->port!!! serial8250_register_8250_port() uses our passed port to + // match internally reserved (during boot) port structure. Our structure misses a lot of stuff like handlers and so + //YOU CANNOT ASSIGN IT HERE! + + //This is the most explosion-prone section so logs are useful + uart_prdbg("Calling serial8250_register_8250_port to register port"); + if ((out = serial8250_register_8250_port(up)) < 0) { //it returns port # on success or -E on error + pr_loc_err("Failed to register ttyS%d - driver failure (error=%d)", vdev->line, out); + goto out_free; + } + pr_loc_dbg("ttyS%d registered with driver (line=%d)", vdev->line, out); + out = 0; //serial8250_register_8250_port return serial port line # or -E code + vdev->registered = true; + + out_free: + kfree(up); + return out; +} + +/** + * Restores original UART in 8250 driver + */ +static int restore_serial8250_isa_port(struct serial8250_16550A_vdev *vdev) +{ + int out; + pr_loc_dbg("Unregistering ttyS%d (io=0x%x) from the driver", vdev->line, vdev->iobase); + + if (unlikely(!vdev->registered)) { + pr_loc_dbg("Port ttyS%d (io=0x%x) is not registered in the driver - nothing to restore", vdev->line, + vdev->iobase); + return 0; + } + + if (unlikely(!kernel_driver_ready)) { + pr_loc_wrn("Port ttyS%d (io=0x%x) cannot be restored - kernel driver not ready", vdev->line, vdev->iobase); + return 0; //not an error as technically the port is NOT in the driver + } + + struct uart_8250_port *up; + kzalloc_or_exit_int(up, sizeof(struct uart_8250_port)); + struct uart_port *port = &up->port; + + port->line = vdev->line; + up->cur_iotype = 0xFF; + port->iobase = vdev->iobase; + port->uartclk = vdev->baud * 16; + port->irq = vdev->irq; //set a REAL IRQ + port->flags = STD_COMX_FLAGS; + up->port = *port; + + //This is the most explosion-prone section so logs are useful + //This may sound counter-intuitive but we don't want to REMOVE the port, we want to just re-register it with + //all default callbacks. + pr_loc_dbg("Calling serial8250_register_8250_port to restore port"); + if ((out = serial8250_register_8250_port(up)) < 0) { //it returns port # on success or -E on error + pr_loc_err("Failed to restore ttyS%d - driver failure (error=%d)", vdev->line, out); + goto out_free; + } + pr_loc_dbg("ttyS%d finished unregistraton from driver (line=%d)", vdev->line, out); + out = 0; //serial8250_register_8250_port return serial port line # or -E code + + vdev->registered = false; + out = try_leave_serial8250_driver(); + + out_free: + kfree(up); + return out; +} + +int vuart_set_tx_callback(int line, vuart_callback_t *cb, char *buffer, int threshold) +{ + validate_isa_line(line); + + struct serial8250_16550A_vdev *vdev = get_line_vdev(line); + if (!cb) { + pr_loc_dbg("Removing TX callback for ttyS%d (line=%d)", line, vdev->line); + if (unlikely(!flush_cbs[line])) { + pr_loc_dbg("Nothing to do - no TX callback set"); + return 0; + } + + //We don't really need to lock for that + kfree(flush_cbs[line]); + flush_cbs[line] = NULL; + + pr_loc_dbg("Removed TX callback for ttyS%d (line=%d)", line, vdev->line); + return 0; + } + + pr_loc_dbg("Setting TX callback for for ttyS%d (line=%d)", line, vdev->line); + line = vdev->line; //this looks to make no sense BUT it does when serials are swapped + if (likely(!flush_cbs[line])) { //if there was already a cb there we don't need to reserve memory + kmalloc_or_exit_int(flush_cbs[line], sizeof(struct flush_callback)); + } + + //This can technically be called during serial port operation so we need to get a lock before we change these or + // we risk sending a buffer to a wrong function. That lock may not exist when device is not added yet. + lock_vuart_oppr(vdev); + flush_cbs[line]->fn = cb; + flush_cbs[line]->buffer = buffer; + flush_cbs[line]->threshold = threshold; + unlock_vuart_oppr(vdev); + + pr_loc_dbg("Added TX callback for ttyS%d (line=%d)", line, vdev->line); + + return 0; +} + +int vuart_inject_rx(int line, const char *buffer, int length) +{ + validate_isa_line(line); + + if (unlikely(length > VUART_FIFO_LEN)) { + pr_loc_bug("Attempted to inject buffer of %d bytes - it's larger than FIFO size (%d bytes)", length, VUART_FIFO_LEN); + return -E2BIG; + } + + struct serial8250_16550A_vdev *vdev = get_line_vdev(line); + if (unlikely(!vdev->initialized)) { + pr_loc_bug("Cannot inject data into non-initialized or non-registered device"); + return -ENXIO; + } + + if (unlikely(!vdev->registered)) { + pr_loc_wrn("Cannot inject data into unregistered device"); //...as it will be removed by the driver on reg + return 0; + } + + //No space to put data - not an error per-sen as this can be re-run again + if ((vdev->lsr & UART_LSR_DR) && unlikely(kfifo_is_full(vdev->rx_fifo) || unlikely(vdev->mcr & UART_MCR_LOOP))) + return 0; + + + int put_bytes = kfifo_in(vdev->rx_fifo, buffer, VUART_FIFO_LEN); + if (likely(put_bytes > 0)) + vdev->lsr |= UART_LSR_DR; + + uart_prdbg("Injected %d bytes into ttyS%d RX", put_bytes, line); + update_interrupts_state(vdev); + + return put_bytes; +} + +int vuart_add_device(int line) +{ + pr_loc_dbg("Adding vUART ttyS%d", line); + + validate_isa_line(line); + warn_bug_swapped(line); + + int out; + struct serial8250_16550A_vdev *vdev = get_line_vdev(line); + + if ((out = initialize_ttyS(vdev)) != 0) + return out; + + if ((out = update_serial8250_isa_port(vdev)) != 0) + goto error_deinit; + + if ((out = vuart_enable_interrupts(vdev)) != 0) + goto error_restore; + + pr_loc_inf("Added vUART at ttyS%d", line); + return 0; + + error_restore: + restore_serial8250_isa_port(vdev); + + error_deinit: + deinitialize_ttyS(vdev); + + return out; +} + +int vuart_remove_device(int line) +{ + pr_loc_dbg("Removing vUART ttyS%d", line); + + validate_isa_line(line); + warn_bug_swapped(line); + + int out; + struct serial8250_16550A_vdev *vdev = get_line_vdev(line); + if ((out = vuart_disable_interrupts(vdev)) != 0 || (out = deinitialize_ttyS(vdev)) != 0 || + (out = restore_serial8250_isa_port(vdev)) != 0 || (out = vuart_set_tx_callback(line, NULL, NULL, 0)) != 0) + return out; + + pr_loc_inf("Removed vUART & restored original UART at ttyS%d", line); + + return 0; +} \ No newline at end of file diff --git a/internal/uart/virtual_uart.h b/internal/uart/virtual_uart.h new file mode 100644 index 0000000..b6c2226 --- /dev/null +++ b/internal/uart/virtual_uart.h @@ -0,0 +1,126 @@ +#ifndef REDPILL_VIRTUAL_UART_H +#define REDPILL_VIRTUAL_UART_H + +#include //bool + +/** + * Length of the RX/TX FIFO in bytes + * Do NOT change this value just because you want to inject more data at once - it's a hardware-defined property + */ +#define VUART_FIFO_LEN 16 + +/** + * Defines maximum threshold possible; in practice this means you will never get any THRESHOLD events but only ID:E and + * FULL ones. + */ +#define VUART_THRESHOLD_MAX INT_MAX + +/** + * Specified the reason why the vUART flushed the buffer + * + * This value carries one guarantee: they will be evaluated in that order of priority. If you set a threshold to exactly + * VUART_FIFO_LEN and the application sends exactly VUART_FIFO_LEN bytes you will get a reason of VUART_FLUSH_THRESHOLD + * even thou all three conditions are met. If you set the threshold to 10 and the app sends 12 bytes you will get a call + * with VUART_FLUSH_THRESHOLD after 10 bytes, then another one with two bytes and VUART_FLUSH_IDLE. + */ +typedef enum { + //Threshold specified while setting the callback has been reached + VUART_FLUSH_THRESHOLD, + + //Kernel put the transmitter in an idle mode, which most of the time indicated end of transmission/packet + VUART_FLUSH_IDLE, + + //FIFO was full before threshold has been reached and the transmission isn't finished yet + VUART_FLUSH_FULL, +} vuart_flush_reason ; + +/** + * Represents a callback signature + * + * @param line UART# where the data arrived; you can ignore it if you registered only one UART + * @param buffer Place where you can read the data from; as of now this is the same buffer but don't rely on this! + * @param len Number of bytes you're allowed to read from beginning of the buffer + * @param reason Denotes why the vUART decided to flush the buffer to the callback + */ +typedef void (vuart_callback_t)(int line, const char *buffer, unsigned int len, vuart_flush_reason reason); + +/** + * Adds a virtual UART device + * + * Calling this function will immediately yank the port from the real one and began capturing its output, so that no + * data will leave through the real one. However, by itself the data will not be delivered anywhere until you call + * vuart_set_tx_callback(), which you can do before or after calling vuart_add_device(). + * + * @param line UART number to replace, e.g. 0 for ttyS0. On systems with inverted UARTs you should use the real one, so + * even if ttyS0 points to 2nd physical port this method will ALWAYS use the one corresponding to ttyS* + * + * @return 0 on success or -E on error + */ +int vuart_add_device(int line); + +/** + * Removes a virtual UART device + * + * Calling this function restores previously replaced port. Unlike vuart_add_device() this function WILL alter TX + * callbacks by removing all of them. The reasoning behind this is that adding a device and later on adding/changing + * callbacks makes sense while removing the device and potentially leaving broken pointers can lead to nasty and hard to + * trace bugs. + * + * @param line UART number to replace, e.g. 0 for ttyS0. On systems with inverted UARTs you should use the real one, so + * even if ttyS0 points to 2nd physical port this method will ALWAYS use the one corresponding to ttyS* + * + * @return 0 on success or -E on error + */ +int vuart_remove_device(int line); + +/** + * Injects data into RX stream of the port + * + * It may be confusing at first what's TX and RX in the context here. Imagine a physical chip connected to a computer + * with some bus (not UART). The chip's RX is what the chip would get from *something*. So injecting data into RX of the + * chip causes the data to be processed by the chip and arrive in the kernel and then in the application which opened + * the port. So while TX implies "transmission" from the perspective of the chip and the app opening the port it's an + * RX side. This naming is consistent with what the whole 8250 subsystem uses. + * + * @param line UART number to replace, e.g. 0 for ttyS0. On systems with inverted UARTs you should use the real one, so + * even if ttyS0 points to 2nd physical port this method will ALWAYS use the one corresponding to ttyS* + * @param buffer Pointer to a buffer where we will read from. There's no assumption as to what the buffer contains. + * @param length Length to read from the buffer up to VUART_FIFO_LEN + * + * @return 0 on success or -E on error + */ +int vuart_inject_rx(int line, const char *buffer, int length); + +/** + * Set a function which will be called upon data transmission by the port opener + * + * In short you will get data which some app (e.g. cat file > /dev/ttyS0) sent. If you're confused by the RX/TX read the + * comment for inject_rx(). + * + * Example of the callback usage: + * //The len is the real number of bytes available to read. The buffer ptrs is the same as you gave to set_tx_ + * void dummy_tx_callback(int line, const char *buffer, int len, vuart_flush_Reason reason) { + * pr_loc_inf("TX @ ttyS%d: |%.*s|", line, len, buffer); + * } + * //.... + * char buf[VUART_FIFO_LEN]; //Your buffer should be able to accommodate at least VUART_FIFO_LEN + * vuart_set_tx_callback(TRY_PORT, dummy_tx_callback, buf, VUART_FIFO_LEN); + * + * WARNING: + * You callback should be multithreading-aware. It may be called from different contexts. You shouldn't do a lot of work + * on the thread where your callback has been called. If you need something more copy the buffer and process it on a + * separate thread. + * + * @param line UART number to replace, e.g. 0 for ttyS0. On systems with inverted UARTs you should use the real one, so + * even if ttyS0 points to 2nd physical port this method will ALWAYS use the one corresponding to ttyS* + * @param cb Function to be called; call it with a NULL ptr to remove callback, see docblock for vuart_callback_t + * @param buffer A pointer to a buffer where data will be placed. The buffer should be able to accommodate + * VUART_FIFO_LEN number of bytes. The buffer you pass will be the same one as passed back during a call + * @param threshold a *HINT* how many bytes at minimum should be deposited in the FIFO before callback is called. Keep + * in mind that this is just a hint and you callback may be called sooner (e.g. when a client program + * wrote only a single byte using e.g. echo -n X > /dev/ttyS0). + * @return 0 on success or -E on error + */ +int vuart_set_tx_callback(int line, vuart_callback_t *cb, char *buffer, int threshold); + +#endif //REDPILL_VIRTUAL_UART_H diff --git a/internal/uart/vuart_internal.h b/internal/uart/vuart_internal.h new file mode 100644 index 0000000..0377ed6 --- /dev/null +++ b/internal/uart/vuart_internal.h @@ -0,0 +1,73 @@ +#ifndef REDPILL_VUART_INTERNAL_H +#define REDPILL_VUART_INTERNAL_H + +#include +#ifndef VUART_USE_TIMER_FALLBACK +#include +#endif + + +//Lock/unlock vdev for registries operations +#define lock_vuart(vdev) spin_lock_irqsave((vdev)->lock, (vdev)->lock_flags); +#define unlock_vuart(vdev) spin_unlock_irqrestore((vdev)->lock, (vdev)->lock_flags); + +//In some circumstances operations may be performed on the chip before or after the chip is initialized. If it is +// initialized we need a lock first; otherwise we do not. This is a shortcut for this opportunistic/conditional locking. +#define lock_vuart_oppr(vdev) if ((vdev)->initialized) { lock_vuart(vdev); } +#define unlock_vuart_oppr(vdev) if ((vdev)->initialized) { unlock_vuart(vdev); } + +#define validate_isa_line(line) \ + if (unlikely((line) > SERIAL8250_LAST_ISA_LINE)) { \ + pr_loc_bug("%s failed - requested line %d but kernel supports only %d", __FUNCTION__, line, \ + SERIAL8250_LAST_ISA_LINE); \ + return -EINVAL; \ + } + +/** + * An emulated 16550A chips internal state + * + * See http://caro.su/msx/ocm_de1/16550.pdf for details; registers are on page 9 (Table 2) + */ +struct serial8250_16550A_vdev { + //Port properties + u8 line; + u16 iobase; + u8 irq; + unsigned int baud; + + //The 8250 driver port structure - it will be populated as soon as 8250 gives us the real pointer + struct uart_port *up; + + //Chip emulated FIFOs + struct kfifo *tx_fifo; //character to be sent (aka what we've got from the OS) + struct kfifo *rx_fifo; //characters received (aka what we want the OS to get from us) + + //Chip registries (they're considered volatile but there's a spinlock protecting them) + u8 rhr; //Receiver Holding Register (characters received) + u8 thr; //Transmitter Holding Register (characters REQUESTED to be sent, TSR will contain these to be TRANSMITTED) + u8 ier; //Interrupt Enable Register + u8 iir; //Interrupt ID Register (same as ISR/Interrupt Status Register) + u8 fcr; //FIFO Control Register (not really used but holds values written to it) + u8 lcr; //Line Control Register (not really used but holds values written to it) + u8 mcr; //Modem Control Register (used to control autoflow) + u8 lsr; //Line Status Register + u8 msr; //Modem Status Register + u8 scr; //SCratch pad Register (in the original docs refered to as SPR, but linux uses SCR name) + u8 dll; //Divisor Lat Least significant byte (not really used but holds values written to it) + u8 dlm; //Divisor Lat Most significant byte (not really used but holds values written to it; also called DLH) + u8 psd; //Prescaler Division (not really used but holds values written to it) + + //Some operations (e.g. FIFO access) must be locked + bool initialized:1; + bool registered:1; //whether the vdev is actually registered with 8250 subsystem + spinlock_t *lock; + unsigned long lock_flags; + +#ifndef VUART_USE_TIMER_FALLBACK + //We emulate (i.e. self-trigger) interrupts on threads + struct task_struct *virq_thread; //where fake interrupt code is executed + wait_queue_head_t *virq_queue; //wait queue used to put thread to sleep +#endif +}; + +#endif //REDPILL_VUART_INTERNAL_H diff --git a/internal/uart/vuart_virtual_irq.c b/internal/uart/vuart_virtual_irq.c new file mode 100644 index 0000000..5e5924d --- /dev/null +++ b/internal/uart/vuart_virtual_irq.c @@ -0,0 +1,152 @@ +#ifndef VUART_USE_TIMER_FALLBACK + +#include "vuart_virtual_irq.h" +#include "vuart_internal.h" +#include "../../common.h" +#include "../../debug/debug_vuart.h" +#include //UART_* consts +#include //running vIRQ thread +#include //wait queue handling (init_waitqueue_head etc.) +#include //serial8250_handle_irq + +//Default name of the thread for vIRQ +#ifndef VUART_THREAD_FMT +#define VUART_THREAD_FMT "vuart/%d-ttyS%d" +#endif + +/** + * Function running on a separate kernel thread responsible for simulating the IRQ call (normally done via hardware + * interrupt triggering CPU to invoke Linux IRQ subsystem) + * + * There's no sane way to trigger IRQs in the low range used by 8250 UARTs. A pure asm call of "int $4" will result in a + * crash (yes, we did try first ;)). So instead of hacking around the kernel we simply used the 8250 public interface to + * trigger interrupt routines and implemented a small IRQ handling subsystem on our own. + * @param data + * @return + */ +static int virq_thread(void *data) +{ + allow_signal(SIGKILL); + + int out = 0; + struct serial8250_16550A_vdev *vdev = data; + + uart_prdbg("%s started for ttyS%d pid=%d", __FUNCTION__, vdev->line, current->pid); + while(likely(!kthread_should_stop())) { + wait_event_interruptible(*vdev->virq_queue, !(vdev->iir & UART_IIR_NO_INT) || unlikely(kthread_should_stop())); + if (unlikely(signal_pending(current))) { + uart_prdbg("%s started for ttyS%d pid=%d received signal", __FUNCTION__, vdev->line, current->pid); + out = -EPIPE; + break; + } + + if (unlikely(kthread_should_stop())) + break; + + if (unlikely(!vdev->up)) { + pr_loc_bug("Cannot call serial8250 interrupt handler - port not captured (yet?)"); + continue; + } + + uart_prdbg("Calling serial8250 interrupt handler"); + serial8250_handle_irq(vdev->up, vdev->iir); + } + uart_prdbg("%s stopped for ttyS%d pid=%d exit=%d", __FUNCTION__, vdev->line, current->pid, out); + + //that can lead to a small memory leak for virq_queue if thread is killed outisde disable_interrupts() but this + // shouldn't normally happen unless something goes horribly wrong + vdev->virq_thread = NULL; + + return out; +} + +int vuart_enable_interrupts(struct serial8250_16550A_vdev *vdev) +{ + int out; + pr_loc_dbg("Enabling vIRQ for ttyS%d", vdev->line); + lock_vuart(vdev); + + if (unlikely(!vdev->initialized)) { + pr_loc_bug("ttyS%d is not initialized as vUART", vdev->line); + out = -ENODEV; + goto error_unlock_free; + } + + if (unlikely(vuart_virq_active(vdev))) { + pr_loc_bug("Interrupts are already enabled & scheduled for ttyS%d", vdev->line); + out = -EBUSY; + goto error_unlock_free; + } + + if (!(vdev->virq_queue = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL)) || + !(vdev->virq_thread = kmalloc(sizeof(struct task_struct), GFP_KERNEL))) { + out = -ENOMEM; + pr_loc_crt("kernel memory alloc failure - tried to reserve memory for vIRQ structures"); + goto error_unlock_free; + } + + init_waitqueue_head(vdev->virq_queue); + unlock_vuart(vdev); //we can safely unlock after reserving memory but before starting thread (so we're not atomic) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-extra-args" + //VUART_THREAD_FMT can resolve to anonymized version without line or even IRQ# + vdev->virq_thread = kthread_run(virq_thread, vdev, VUART_THREAD_FMT, vdev->irq, vdev->line); +#pragma GCC diagnostic pop + if (IS_ERR(vdev->virq_thread)) { + out = PTR_ERR(vdev->virq_thread); + pr_loc_bug("Failed to start vIRQ thread"); + goto error_free; + } + pr_loc_dbg("vIRQ fully enabled for for ttyS%d", vdev->line); + + return 0; + + error_unlock_free: + unlock_vuart(vdev); + error_free: + if (vdev->virq_queue) { + kfree(vdev->virq_queue); + vdev->virq_queue = NULL; + } + if (vdev->virq_thread) { + kfree(vdev->virq_thread); + vdev->virq_thread = NULL; + } + return out; +} + +int vuart_disable_interrupts(struct serial8250_16550A_vdev *vdev) +{ + int out; + pr_loc_dbg("Disabling vIRQ for ttyS%d", vdev->line); + lock_vuart(vdev); + + if (unlikely(!vdev->initialized)) { + pr_loc_bug("ttyS%d is not initialized as vUART", vdev->line); + out = -ENODEV; + goto out_unlock; + } + + if (unlikely(!vuart_virq_active(vdev))) { + pr_loc_bug("Interrupts are not enabled/scheduled for ttyS%d", vdev->line); + out = -EBUSY; + goto out_unlock; + } + + out = kthread_stop(vdev->virq_thread); + if (out < 0) { + pr_loc_bug("Failed to stop vIRQ thread"); + goto out_unlock; + } + + kfree(vdev->virq_thread); + vdev->virq_thread = NULL; + pr_loc_dbg("vIRQ disabled for ttyS%d", vdev->line); + + out_unlock: + unlock_vuart(vdev); + + return 0; +} +#endif \ No newline at end of file diff --git a/internal/uart/vuart_virtual_irq.h b/internal/uart/vuart_virtual_irq.h new file mode 100644 index 0000000..963a8ad --- /dev/null +++ b/internal/uart/vuart_virtual_irq.h @@ -0,0 +1,20 @@ +#ifndef REDPILL_VUART_VIRTUAL_IRQ_H +#define REDPILL_VUART_VIRTUAL_IRQ_H + +#ifdef VUART_USE_TIMER_FALLBACK +#define vuart_virq_supported() 0 +#define vuart_virq_wake_up(dummy) //noop +#define vuart_enable_interrupts(dummy) (0) +#define vuart_disable_interrupts(dummy) (0) + +#else //VUART_USE_TIMER_FALLBACK +#include "vuart_internal.h" + +#define vuart_virq_supported() 1 +#define vuart_virq_active(vdev) (!!(vdev)->virq_thread) +#define vuart_virq_wake_up(vdev) if (vuart_virq_active(vdev)) { wake_up_interruptible(vdev->virq_queue); } +int vuart_enable_interrupts(struct serial8250_16550A_vdev *vdev); +int vuart_disable_interrupts(struct serial8250_16550A_vdev *vdev); +#endif //VUART_USE_TIMER_FALLBACK + +#endif //REDPILL_VUART_VIRTUAL_IRQ_H \ No newline at end of file diff --git a/internal/virtual_pci.c b/internal/virtual_pci.c new file mode 100644 index 0000000..6b7905c --- /dev/null +++ b/internal/virtual_pci.c @@ -0,0 +1,575 @@ +/* + * This file is a SIMPLE (yes, this IS simple) software emulation layer for PCI devices. + * + * Before you even start reading it you need to get familiar with references listed below. As the kernel people put it + * mildly "The world of PCI is vast and full of (mostly unpleasant) surprises.". This module tries to abstract hardware + * space emulation into highest level API possible. + * + * + * QUICK INTRODUCTION + * ------------------ + * To use it you need to supply a descriptor (e.g. struct pci_dev_descriptor) and give it domain-unique combination of + * {bus#, device#, function#}. The domain for most (all?) physical devices is usually 0x0000. This module uses 0x0001 to + * avoid conflicts. + * Fast PCI facts (read this to add devices): + * - every device is in the system has a location of BDF (256 buses max, 32 devices/bus, 8 functions/device = 65536) + * - every device MUST contain a function 0 (and may contain 1-7) + * - function is kind-of a subdevice (e.g. a quad-port network card will usually have functions 0-3) + * - you should (but you don't HAVE to) set "master bus" (.command |= PCI_COMMAND_MASTER) for every function 0 device + * instance + * - every device MUST have a valid VID/DEV. None of the fields can be 0x0000 or 0xFFFF (they have special meanings) + * - this module does NOT have any support for capabilities (CAPs) as they're variable length and we don't want to + * force every device struct to take 256K of memory (todo if needed?) + * - there are three types of headers: PCI device, PCI-PCI bridge, PCI-CardBus bridge. Only the first one was tested. + * The second one allows for more levels of the tree and should work if configured properly (see struct + * pci_pci_bridge_descriptor) but it wasn't needed yet. The third one is practically a bitrot now. + * - EVERYTHING IN PCI IS LITTLE ENDIAN no matter what your CPU says. Triple check if you're setting values correctly. + * Then you realize you set them incorrectly. + * - "devfn" in Linux terminology does NOT mean "device function" but rather "device# and function#". It is described + * in drivers/pci/search.c as "encodes number of PCI slot in which the desired PCI device resides and the logical + * device number within that slot in case of multi-function devices". + * You can use macros PCI_SLOT() and PCI_FUNC() to get dev# and fn# from that field. + * - Linux provides class & subclass constants (PCI_CLASS_* in include/linux/pci_ids.h). However they're defined as + * either: + * - 8 bit class + * - e.g. PCI_BASE_CLASS_SERIAL [0x0c] + * - can be put into pci_dev_descriptor.class directly + * - 16 bit class+subclass + * - e.g. PCI_CLASS_SERIAL_USB [0x0c03] + * - use U16_CLASS_TO_U8_CLASS(PCI_CLASS_SERIAL_USB) for pci_dev_descriptor.class [0x0c] + * - use U16_CLASS_TO_U8_SUBCLASS(PCI_CLASS_SERIAL_USB) for pci_dev_descriptor.subclass [0x03] + * - 24 bit (sic!) class+subclass+prog_if + * - e.g. PCI_CLASS_SERIAL_USB_EHCI (0x0c0320) + * - use U24_CLASS_TO_U8_CLASS(PCI_CLASS_SERIAL_USB) for pci_dev_descriptor.class [0x0c] + * - use U24_CLASS_TO_U8_SUBCLASS(PCI_CLASS_SERIAL_USB) for pci_dev_descriptor.subclass [0x03] + * - use U24_CLASS_TO_U8_PROGIF(PCI_CLASS_SERIAL_USB) for pci_dev_descriptor.prog_if [0x03] + * - "pci_dev_conf_default_normal_dev" provides a sane-default device where you need to only set: vid, dev, class, + * and subclass. + * + * + * DEBUGGING DEVICES + * ----------------- + * To see the tree you can use "lspci -tvnn". Here's a quick cheat-sheet from the output format: + * 0001:0a:00.0 Class 0000: Device 1b4b:9235 (rev ff) + * ^ ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | |_______ pci_dev_descriptor.class_revision (lower 24 bits) + * | | | | | | |_________________ pci_dev_descriptor.dev (device ID) + * | | | | | |______________________ pci_dev_descriptor.vid (vendor ID) + * | | | | |___________________________________ pci_dev_descriptor.class_revision (higher 24 bits) + * | | | |___________________________________________ PCI device function + * | | |______________________________________________ device num on the bus + * | |_________________________________________________ PCI bus no + * |_____________________________________________________ PCIBUS_VIRTUAL_DOMAIN + * + * + * To debug the Linux PCI subsytem side of things these will be useful: + * echo 'file probe.c +p' > /sys/kernel/debug/dynamic_debug/control + * echo 'file search.c +p' > /sys/kernel/debug/dynamic_debug/control + * echo 'file delete.c +p' > /sys/kernel/debug/dynamic_debug/control + * + * + * INTERNAL STRUCTURE + * ------------------ + * The module emulates PCI on the lowest possible level - it literally fakes the otherwise-physical memory of + * configuration registries. + * + * The two header types are memory-mapped as follows: (PCI-CardBus isn't shown as nobody uses that) + * HEADER TYPE 0x00 (Normal Device) HEADER TYPE 0x01 (PCI-PCI Bridge) + * 31 16 15 0 hh 31 16 15 0 hh + * ╠══════════╩══════════╬══════════╩═══════════╬════ ╠═════════╩══════════╬═══════════╩═══════════╬════ + * ║ Device ID ║ Vendor ID ║ 00 ║ Device ID ║ Vendor ID ║ 00 + * ╠═════════════════════╬══════════════════════╬════ ╠════════════════════╬═══════════════════════╬════ + * ║ Status ║ Command ║ 04 ║ Status ║ Command ║ 04 + * ╠══════════╦══════════╬══════════╦═══════════╬════ ╠═════════╦══════════╬═══════════╦═══════════╬════ + * ║ Class ║ Subclass ║ ProgIF ║ Rev. ID ║ 08 ║ Class ║ Subclass ║ ProgIF ║ Rev. ID ║ 08 + * ╠══════════╬══════════╬══════════╬═══════════╬════ ╠═════════╬══════════╬═══════════╬═══════════╬════ + * ║ BIST ║ HeaderT ║ Lat.Tmr. ║ Cache LS ║ 0c ║ BIST ║ HeaderT ║ Lat.Tmr. ║ Cache LS ║ 0c + * ╠══════════╩══════════╩══════════╩═══════════╬════ ╠═════════╩══════════╩═══════════╩═══════════╬════ + * ║ BAR0 ║ 10 ║ BAR0 ║ 10 + * ╠════════════════════════════════════════════╬════ ╠════════════════════════════════════════════╬════ + * ║ BAR1 ║ 14 ║ BAR1 ║ 14 + * ╠════════════════════════════════════════════╬════ ╠═════════╦══════════╦═══════════╦═══════════╬════ + * ║ BAR2 ║ 18 ║ SecLatT ║ SubordB# ║ SecBus# ║ PriBus# ║ 18 + * ╠════════════════════════════════════════════╬════ ╠═════════╩══════════╬═══════════╬═══════════╬════ + * ║ BAR3 ║ 1c ║ Secondary Status ║ I/O Limit ║ I/O Base ║ 1c + * ╠════════════════════════════════════════════╬════ ╠════════════════════╬═══════════╩═══════════╬════ + * ║ BAR4 ║ 20 ║ Memory limit ║ Memory base ║ 20 + * ╠════════════════════════════════════════════╬════ ╠════════════════════╬═══════════════════════╬════ + * ║ BAR5 ║ 24 ║ Prefetch. Mem. L. ║ Prefetch. Mem. B. ║ 24 + * ╠════════════════════════════════════════════╬════ ╠════════════════════╩═══════════════════════╬════ + * ║ Cardbus CIS ptr ║ 28 ║ Prefetchable Base Upper 32 bit ║ 28 + * ╠═════════════════════╦══════════════════════╬════ ╠════════════════════════════════════════════╬════ + * ║ Subsys ID ║ Subsys VID ║ 2c ║ Prefetchable Limit Upper 32 bit ║ 2c + * ╠═════════════════════╩══════════════════════╬════ ╠════════════════════╦═══════════════════════╬════ + * ║ Exp. ROM Base Addr. ║ 30 ║ I/O Lim. Up. 16b ║ I/O Base Up. 16b ║ 30 + * ╠════════════════════════════════╦═══════════╬════ ╠════════════════════╩═══════════╦═══════════╬════ + * ║ *RSV* ║ Cap. ptr ║ 34 ║ *RSV* ║ Cap. ptr ║ 34 + * ╠════════════════════════════════╩═══════════╬════ ╠════════════════════════════════╩═══════════╬════ + * ║ *RSV* ║ 38 ║ Exp. ROM Base Addr. ║ 38 + * ╠══════════╦══════════╦══════════╦═══════════╬════ ╠════════════════════╦═══════════╦═══════════╬════ + * ║ Max Lat. ║ Min Gnt. ║ Int. pin ║ Int. lin. ║ 3c ║ Bridge Control ║ Int. pin ║ Int. lin. ║ 3c + * ╠══════════╩══════════╩══════════╩═══════════╬═══════ ╠════════════════════╩═══════════╩═══════════╬═══════ + * ║ Optional Dev.-Dep. Config (192 bytes) ║ 40-100 ║ Optional Dev.-Dep. Config (192 bytes) ║ 40-100 + * ╚════════════════════════════════════════════╩═══════ ╚════════════════════════════════════════════╩═══════ + * + * + * LINUX PCI SUBSYSTEM SCANNING ROUTINE + * ------------------------------------ + * The kernel has a surprisingly readable code for the PCI scanning. We recommend starting from drivers/pci/probe.c and + * "struct pci_bus *pci_scan_bus()" function. + * In a big simplification it goes something like this: + * probe.c + * pci_scan_bus() + * => pci_scan_child_bus + * => loop pci_scan_slot(bus, devfn) with devfn=<0,0x100> every 8 bytes + * => pci_scan_single_device + * => pci_get_slot to check if device already exists + * => pci_scan_device to probe the device + * => pci_bus_read_dev_vendor_id + * => .... [and others] + * => pci_device_add if device probe succeeded + * + * THE ACPI SAGA + * ------------- + * If you were thinking PCI is hard you haven't heard about ACPI. Kernels starting from v3.13 require ACPI companion + * for PCI devices when the system was configured to run on an ACPI-complain x86 platform. This isn't an unusual + * assumption. Before v3.13 the struct x86_sysdata contained a simple ACPI handle, which could be NULL. Now it should + * contain a structure. However it still PROBABLY can be NULL. + * See https://github.com/torvalds/linux/commit/7b1998116bbb2f3e5dd6cb9a8ee6db479b0b50a9 for details of that change. + * + * When the structure (=ACPI data) is NULL the error "ACPI: \: failed to evaluate _DSM (0x1001)" will be logged upon + * scanning. However it seems to be harmless. There are two ways to get rid of this error: 1) Implement a proper ACPI + * _DSM [no, just NO], or 2) user override_symbol() for acpi_evaluate_dsm() with a function doing the following (for the + * time of scanning ONLY): + * union acpi_object *obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + * obj->type = ACPI_TYPE_INTEGER; + * obj->integer.value = 1; + * return obj; + * + * x86 BUS SCANNING BUG (>=v4.1) + * ----------------------------- + * Since v4.1 adding a new bus under a different domain will cause devices on the bus to not be fully populated. See the + * comment in "vpci_add_single_device()" here for details & a simple fix. + * + * KNOWN BUGS + * ---------- + * Under Linux v3.10 once bus is added it cannot be fully removed (or we didn't find the correct way). When you do the + * initial add and scan everything works correctly. You can later even remove that bus BUT the kernel leaves some sysfs + * stuff behind in /sys/devices (while /sys/bus/pci/devices are cleaned up). This means that if you try to re-register + * the same bus it explode with sysfs duplication errors. + * As of now we have no idea how to go around that. + * + * + * References: + * - https://stackoverflow.com/a/31465293 (how PCI subsystem works) + * - https://docs.oracle.com/cd/E19120-01/open.solaris/819-3196/hwovr-25/index.html (PCI working theory) + * - https://elixir.bootlin.com/linux/v3.10.108/source/include/uapi/linux/pci_regs.h (Linux PCI registers) + * - https://elixir.bootlin.com/linux/v3.10.108/source/drivers/pci/probe.c (PCI scanning code; very readable) + * - https://blog.csdn.net/moon146/article/details/18988849 (scanning process) + * - https://wiki.osdev.org/PCI (details regarding flags & commands) + */ +#include "virtual_pci.h" +#include "../common.h" +#include "../config/vpci_types.h" //MAX_VPCI_BUSES +#include +#include //PCI device header constants +#include //Constants for vendors, classes, and other +#include //list_for_each +#include //device_del + +#define PCIBUS_VIRTUAL_DOMAIN 0x0001 //normal PC buses are (always?) on domain 0, this is just a next one +#define PCI_DEVICE_NOT_FOUND_VID_DID 0xFFFFFFFF //A special case to detect non-existing devices (per PCI spec) + +/* As per PCI spec + * If a single function device is detected (i.e., bit 7 in the Header + * Type register of function 0 is 0), no more functions for that + * Device Number will be checked. If a multi-function device is + * detected (i.e., bit 7 in the Header Type register of function 0 + * is 1), then all remaining Function Numbers will be checked. + * This helper converts single-function header type to multifunction header type + */ +#define PCI_HEADER_TO_MULTI(x) ((1 << 7) | (x)) +#define IS_PCI_HEADER_MULTI(x) (!!((x) & 0x80)) + +//Model of a default config for a device +const struct pci_dev_descriptor pci_dev_conf_default_normal_dev = { + .vid = 0xDEAD, //set me! + .dev = 0xBEEF, //set me! + + .command = 0x0000, + .status = 0x0000, + + .rev_id = PCI_DSC_REV_NONE, + .prog_if = PCI_DSC_PROGIF_NONE, + .subclass = U16_CLASS_TO_U8_CLASS(PCI_CLASS_NOT_DEFINED), //set me! + .class = U16_CLASS_TO_U8_CLASS(PCI_CLASS_NOT_DEFINED), //set me! + + .cache_line_size = 0x00, + .latency_timer = 0x00, + .header_type = PCI_HEADER_TYPE_NORMAL, + .bist = PCI_DSC_BIST_NONE, //Built-In Self Test + + .bar0 = PCI_DSC_NULL_BAR, + .bar1 = PCI_DSC_NULL_BAR, + .bar2 = PCI_DSC_NULL_BAR, + .bar3 = PCI_DSC_NULL_BAR, + .bar4 = PCI_DSC_NULL_BAR, + .bar5 = PCI_DSC_NULL_BAR, + + .cardbus_cis = 0x00000000, + + .subsys_vid = 0x0000, //you probably want to set this + .subsys_id = 0x0000, //you probably want to set this + + .exp_rom_base_addr = 0x00000000, + + .cap_ptr = PCI_DSC_NULL_CAP, + .reserved_34_8_15 = PCI_DSC_RSV8, + .reserved_34_16_31 = PCI_DSC_RSV16, + + .reserved_38h = 0x00000000, + + .interrupt_line = PCI_DSC_NO_INT_LINE, + .interrupt_pin = PCI_DSC_NO_INT_PIN, + .min_gnt = PCI_DSC_ZERO_BURST, + .max_lat = PCI_DSC_INF_LATENCY, +}; + +struct virtual_device { + unsigned char *bus_no; //same as bus->number, used when bus is not initialized yet (e.g. during scanning) + unsigned char dev_no; + unsigned char fn_no; + struct pci_bus* bus; + void *descriptor; +}; +static unsigned int free_bus_idx = 0; //Used to find next free bus and for indexing other arrays +static struct pci_bus *buses[MAX_VPCI_BUSES] = { NULL }; //All virtual buses + +static unsigned int free_dev_idx = 0; //Used to find next free bus and for indexing other arrays +static struct virtual_device *devices[MAX_VPCI_DEVS] = { NULL }; //All virtual devices + +//Macros to easily iterate over lists above +#define for_each_bus_idx() for (int i = 0, last_bus_idx = free_bus_idx-1; i <= last_bus_idx; i++) +#define for_each_dev_idx() for (int i = 0, last_dev_idx = free_dev_idx-1; i <= last_dev_idx; i++) + +/** + * Prints pci_dev_descriptor or pci_pci_bridge_descriptor + */ +void print_pci_descriptor(void *test_dev) +{ + pr_loc_dbg("Printing PCI descriptor @ %p", test_dev); + pr_loc_dbg_raw("\n31***********0***ADDR*******************\n"); + u8 *ptr = (u8 *)test_dev; + DBG_ALLOW_UNUSED(*ptr); + + for (int row = 3; row < 64; row += 4) { + for (int byte = 0; byte > -4; byte--) { + pr_loc_dbg_raw("%02x ", *(ptr + row + byte)); + if (byte == -1) pr_loc_dbg_raw(" "); + } + + pr_loc_dbg_raw(" | 0x%02X\n", row - 3); + } + //The following format will be useful when/if CAPs are implemented +// printk("\n--------------Device Private--------------\n"); +// printk("00000000 00000000 00000000 00000000 | xxx\n"); +// printk("******************************************\n"); +} + +/** + * @param bus The bus (may be under first scan so only its number may be present in virtual_device) + * @param devfn Device AND its function; it's a 0-256 number allowing for 32 devices with 8 functions each + * @param where Offset in the device structure to read + * @param size How many BYTES (not bits) to read + * @param val Pointer to save read bytes + * @return PCIBIOS_* + */ +static int pci_read_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) +{ + //devfn is a combination of device number on bus and function number (Bus/Device/Function addressing) + //Each device which exists MUST implement function 0. So every 8th value of devfn we have a new device. + unsigned char vdev_no = PCI_SLOT(devfn); + unsigned char vdev_fn = PCI_FUNC(devfn); + + void *pci_descriptor = NULL; + + //Very noisy! + //pr_loc_dbg("Read SYN wh=0x%d sz=%d B / %d for vDEV @ bus=%02x dev=%02x fn=%02x", where, size, size * 8, + // bus->number, vdev_no, vdev_fn); + for_each_dev_idx() { + //Very noisy! + //pr_loc_dbg("Checking vDEV @ bus=%02x dev=%02x fn=%02x", *devices[i]->bus_no, devices[i]->dev_no, + // devices[i]->fn_no); + + //We cannot use devices[i]->bus->number during scan as the bus may just being created and no ->bus is available + if(*devices[i]->bus_no == bus->number && devices[i]->dev_no == vdev_no && devices[i]->fn_no == vdev_fn) { + //Very noisy! + //pr_loc_dbg("Found matching vDEV @ bus=%02x dev=%02x fn=%02x => vidx=%d mf=%d", bus->number, vdev_no, + // vdev_fn, i, + // IS_PCI_HEADER_MULTI(((struct pci_dev_descriptor *) devices[i]->descriptor)->header_type) ? 1:0); + pci_descriptor = devices[i]->descriptor; + break; + } + }; + + if (!pci_descriptor) { //This is not a hack - this is per PCI spec to return special "not found pid/vid" + if (where == PCI_VENDOR_ID || where == PCI_DEVICE_ID) + *val = PCI_DEVICE_NOT_FOUND_VID_DID; + + //Very noisy! + //pr_loc_dbg("Read NAK wh=0x%d sz=%d B / %d for vDEV @ bus=%02x dev=%02x fn=%02x", where, size, size * 8, bus->number, + // vdev_no, vdev_fn); + return PCIBIOS_DEVICE_NOT_FOUND; + } + + //Very noisy! + //pr_loc_dbg("Read ACK wh=0x%d sz=%d B / %d for vDEV @ bus=%02x dev=%02x fn=%02x", where, size, size * 8, bus->number, + // vdev_no, vdev_fn); + memcpy(val, (u8 *)pci_descriptor + where, size); + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_write_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) +{ + return PCIBIOS_SET_FAILED; +} + +//Definition of callbacks the PCI subsystem uses to query the root bus +static struct pci_ops pci_shim_ops = { + .read = pci_read_cfg, + .write = pci_write_cfg +}; + +//x86-specific sysdata which is expected to be present while running on x86 (if it's not you will get a KP) +static struct pci_sysdata x86_sysdata = { + .domain = PCIBUS_VIRTUAL_DOMAIN, +#ifdef CONFIG_ACPI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) + .companion = NULL, //See https://github.com/torvalds/linux/commit/7b1998116bbb2f3e5dd6cb9a8ee6db479b0b50a9 +#else + .acpi = NULL, +#endif //LINUX_VERSION_CODE +#endif //CONFIG_ACPI + .iommu = NULL +}; + +//_NO => number according to the PCI spec +//_IDX => index in arrays (internal to this emulation layer only) +#define BUS_NO_VALID(x) ((x) >= 0 && (x) <= 0xFF) //Check if a given bus# is valid according to the PCI spec +#define DEV_NO_VALID(x) ((x) >= 0 && (x) <= 32) //Check if a given dev# is valid according to the PCI spec +#define FN_NO_VALID(x) ((x) >= 0 && (x) <= 7) //Check if a given function# is valid according to the PCI spec +#define VBUS_IDX_VALID(x) ((x) >= 0 && (x) < MAX_VPCI_BUSES-1) //Check if virtual bus INDEX is valid for this emulator +#define VBUS_IDX_USED(x) ((x) >= 0 && (x) < free_bus_idx) //Check if a given bus index is used now in the emulator +#define VDEV_IDX_VALID(x) ((x) >= 0 && (x) < MAX_VPCI_DEVS-1) //Check if virtual device INDEX is valid for this emulator +#define VDEV_IDX_USED(x) ((x) >= 0 && (x) < free_dev_idx) //Check if a given bus index is used now in the emulator + +static inline int validate_bdf(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no) +{ + if (unlikely(!BUS_NO_VALID(bus_no))) { + pr_loc_err("%02x is not a valid PCI bus number", bus_no); + return -EINVAL; + } + + if (unlikely(!DEV_NO_VALID(dev_no))) { + pr_loc_err("%02x is not a valid PCI device number", dev_no); + return -EINVAL; + } + + if (unlikely(!FN_NO_VALID(fn_no))) { + pr_loc_err("%02x is not a valid PCI device function number", fn_no); + return -EINVAL; + } + + //if the free device index is not valid it means we're out of free IDs for devices + if (unlikely(!VDEV_IDX_VALID(free_dev_idx))) { + pr_loc_bug("No more device indexes are available (max devs: %d)", MAX_VPCI_DEVS); + return -ENOMEM; + } + + //If the device has the same B/D/F address it is a duplicate + for_each_dev_idx() { + if ( + likely(*devices[i]->bus_no == bus_no) && + unlikely(devices[i]->dev_no == dev_no && devices[i]->fn_no == fn_no) + ) { + pr_loc_err("Device bus=%02x dev=%02x fn=%02x already exists in vidx=%d", bus_no, dev_no, fn_no, i); + return -EEXIST; + } + }; + + return 0; +} + +static inline struct pci_bus *get_vbus_by_number(unsigned char bus_no) +{ + for_each_bus_idx() { //Determine whether we need to rescan existing bus after adding a device OR scan a new root bus + if (buses[i]->number == bus_no) { + pr_loc_dbg("Found existing bus_no=%d @ bidx=%d", bus_no, i); + return buses[i]; + break; + } + }; + + return NULL; +} + +const __must_check struct virtual_device * +vpci_add_device(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, void *descriptor) +{ + pr_loc_dbg("Attempting to add vPCI device [printed below] @ bus=%02x dev=%02x fn=%02x", bus_no, dev_no, fn_no); + print_pci_descriptor(descriptor); + + int error = validate_bdf(bus_no, dev_no, fn_no); + if (error != 0) + return ERR_PTR(error); + + struct pci_bus *bus = get_vbus_by_number(bus_no); + + //At this point we know the device can be added either to a new or existing bus so we have to populate their struct + struct virtual_device *device; + kmalloc_or_exit_ptr(device, sizeof(struct virtual_device)); + + device->dev_no = dev_no; + device->fn_no = fn_no; + device->descriptor = descriptor; + + if (bus) { //We have an existing bus to use + device->bus_no = &bus->number; + devices[free_dev_idx++] = device; + + //We cannot use "pci_scan_single_device" here in case there are mf devices + pci_rescan_bus(bus); //this cannot fail - it simply return max device num + + pr_loc_err("Added device with existing bus @ bus=%02x dev=%02x fn=%02x", *device->bus_no, device->dev_no, + device->fn_no); + return device; + } + + //No existing bus - check if we can add a new one + //if the free bus index is not valid it means we're out of free IDs for buses + if (unlikely(!VBUS_IDX_VALID(free_bus_idx))) { + pr_loc_bug("No more bus indexes are available (max buses: %d)", MAX_VPCI_BUSES); + return ERR_PTR(-ENOMEM); + } + + //Since we don't have a bus so we need to add the device with a mock dev_no and trigger scanning (which actually + // creates the bus). While it sounds counter-intuitive it is how the PCI subsystem works. + unsigned char tmp_bus_no = bus_no; //It will be valid for the time of initial scan + device->bus_no = &tmp_bus_no; + devices[free_dev_idx++] = device; + + bus = pci_scan_bus(*device->bus_no, &pci_shim_ops, &x86_sysdata); + if (!bus) { + pr_loc_err("pci_scan_bus failed - cannot add new bus"); + devices[free_dev_idx--] = NULL; //Reverse adding & ensure idx is still free + kfree(device); //Free memory for the device itself + return ERR_PTR(-EIO); + } + + device->bus_no = &bus->number; //Replace temp bus number pointer with the actual bus struct pointer + device->bus = bus; + buses[free_bus_idx++] = bus; + + /* + * There was a commit in v4.1 which made "subtle" change aimed to "cleanup control flow" by moving + * pci_bus_add_devices(bus) from drivers/pci/probe.c:pci_scan_bus() to a higher order + * arch/x86/pci/common.c:pcibios_scan_root(). + * However this means that adding a bus with a domain different than 0 as used on x86 with BIOS/ACPI causes some + * resources to not be created (e.g. /sys/bus/pci/devices/..../config) which in turn breaks a ton of tools (lspci + * included). This is because pci_bus_add_devices() calls pci_create_sysfs_dev_files(). + * It's important to mention that this is broken only for new buses - pci_rescan_bus() calls pci_bus_add_devices(). + * + * Don't even fucking ask how long we looked for that... + * + * See https://github.com/torvalds/linux/commit/8e795840e4d89df3d594e736989212ee8a4a1fca# + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) + pr_loc_dbg("Linux >=v4.1 quirk: calling pci_bus_add_devices(bus) manually"); + pci_bus_add_devices(bus); +#endif + + pr_loc_inf("Added device with new bus @ bus=%02x dev=%02x fn=%02x", *device->bus_no, device->dev_no, device->fn_no); + return device; +} + +const struct virtual_device * +vpci_add_single_device(unsigned char bus_no, unsigned char dev_no, struct pci_dev_descriptor *descriptor) +{ + if (unlikely(IS_PCI_HEADER_MULTI(descriptor->header_type))) { + pr_loc_bug("Attempted to use %s() to add multifunction device." + "Did you mean to use vpci_add_multifunction_device()?", __FUNCTION__); + return ERR_PTR(-EINVAL); + } + + return vpci_add_device(bus_no, dev_no, 0x00, descriptor); +} + +const struct virtual_device * +vpci_add_multifunction_device(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, + struct pci_dev_descriptor *descriptor) +{ + descriptor->header_type = PCI_HEADER_TO_MULTI(descriptor->header_type); + + return vpci_add_device(bus_no, dev_no, fn_no, descriptor); +} + +const struct virtual_device * +vpci_add_single_bridge(unsigned char bus_no, unsigned char dev_no, struct pci_pci_bridge_descriptor *descriptor) +{ + if (unlikely(IS_PCI_HEADER_MULTI(descriptor->header_type))) { + pr_loc_bug("Attempted to use %s() to add multifunction device." + "Did you mean to use vpci_add_multifunction_device()?", __FUNCTION__); + return ERR_PTR(-EINVAL); + } + + return vpci_add_device(bus_no, dev_no, 0x00, descriptor); +} + +const struct virtual_device * +vpci_add_multifunction_bridge(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, + struct pci_pci_bridge_descriptor *descriptor) +{ + descriptor->header_type = PCI_HEADER_TO_MULTI(descriptor->header_type); + + return vpci_add_device(bus_no, dev_no, fn_no, descriptor); +} + +int vpci_remove_all_devices_and_buses(void) +{ + //The order here is crucial - kernel WILL NOT remove references to devices on bus removal (and cause a KP) + //Doing this in any other order will cause an instant KP when PCI subsys tries to access its structures (e.g. lspci) + //However, this is still leaving dangling things in /sys/devices which cannot be removed (kernel bug?) + + struct pci_dev *pci_dev, *pci_dev_n; + for_each_bus_idx() { + list_for_each_entry_safe(pci_dev, pci_dev_n, &buses[i]->devices, bus_list) { + pr_loc_dbg("Detaching vDEV dev=%02x fn=%02x from bus=%02x [add=%d]", PCI_SLOT(pci_dev->devfn), +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5,0,0) + PCI_FUNC(pci_dev->devfn), buses[i]->number, pci_dev->is_added); +#else + PCI_FUNC(pci_dev->devfn), buses[i]->number, 0); // Not found a replacement for pci_dev->is_added +#endif + pci_stop_and_remove_bus_device(pci_dev); + } + } + + for_each_dev_idx() { + pr_loc_dbg("Removing PCI vDEV @ didx %d", i); + kfree(devices[i]); + devices[i] = NULL; + }; + free_dev_idx = 0; + + for_each_bus_idx() { + pr_loc_dbg("Removing child PCI vBUS @ bidx %d", i); + pci_rescan_bus(buses[i]); + pci_remove_bus(buses[i]); + buses[i] = NULL; + } + free_bus_idx = 0; + + pr_loc_inf("All vPCI devices and buses removed"); + + return -EIO; //This is hardcoded to return an error as there's a known bug (see "KNOWN BUGS" in the file header) +} diff --git a/internal/virtual_pci.h b/internal/virtual_pci.h new file mode 100644 index 0000000..137c6a3 --- /dev/null +++ b/internal/virtual_pci.h @@ -0,0 +1,202 @@ +#ifndef REDPILL_VIRTUAL_PCI_H +#define REDPILL_VIRTUAL_PCI_H + +#include + +/* + * The following macros are useful for converting PCI_CLASS_* constants to individual values in structs + * 31 .................. 0 + * [class][sub][prog][rev] (each is 8 bit number, often times class-sub-prog is represented as on 24-bit int) + * + * For more information see header comment in the corresponding .c file. + */ +#define U24_CLASS_TO_U8_CLASS(x) (((x) >> 16) & 0xFF) +#define U24_CLASS_TO_U8_SUBCLASS(x) (((x) >> 8) & 0xFF) +#define U24_CLASS_TO_U8_PROGIF(x) ((x) & 0xFF) +#define U16_CLASS_TO_U8_CLASS(x) (((x) >> 8) & 0xFF) +#define U16_CLASS_TO_U8_SUBCLASS(x) ((x) & 0xFF) + +//Some helpful constants on top of what's in linux/pci_ids.h & linux/pci_regs.h +#define PCI_DSC_NO_INT_LINE 0xFF +#define PCI_DSC_NO_INT_PIN 0x00 +#define PCI_DSC_PROGIF_NONE 0x00 +#define PCI_DSC_REV_NONE 0x00 +#define PCI_DSC_NULL_BAR 0x00000000 +#define PCI_DSC_NULL_CAP 0x00 +#define PCI_DSC_RSV8 0x00 +#define PCI_DSC_RSV16 0x0000 +#define PCI_DSC_INF_LATENCY 0xFF //i.e. accepts any latency in access +#define PCI_DSC_ZERO_BURST 0xFF //i.e. doesn't need any length of burst +#define PCI_DSC_BIST_NONE 0x00 + +//See https://en.wikipedia.org/wiki/PCI_configuration_space#/media/File:Pci-config-space.svg +//This struct MUST be packed to allow for easy reading, see https://kernelnewbies.org/DataAlignment +struct pci_dev_descriptor { + u16 vid; //Vendor ID + u16 dev; //Device ID + + u16 command; //see PCI_COMMAND_*. Simply do "dev.command |= PCI_COMMAND_xxx" to set a flag. + u16 status; //see PCI_STATUS_*. Simply do "dev.status |= PCI_STATUS_xxx" to set a flag. + + u8 rev_id; + u8 prog_if; // ] + u8 subclass; // ]-> prof_if, subclass, and class are normally represented as 24-bit class code + u8 class; // ] + + u8 cache_line_size; + u8 latency_timer; + u8 header_type; //see PCI_HEADER_TYPE_* + u8 bist; //see PCI_BIST_* + + u32 bar0; + u32 bar1; + u32 bar2; + u32 bar3; + u32 bar4; + u32 bar5; + + u32 cardbus_cis; + + u16 subsys_vid; + u16 subsys_id; + + u32 exp_rom_base_addr; //see PCI_ROM_* (esp PCI_ROM_ADDRESS_MASK) + + u8 cap_ptr; + u8 reserved_34_8_15; //should be 0x00 + u16 reserved_34_16_31; //should be 0x00 + + u32 reserved_38h; + + u8 interrupt_line; + u8 interrupt_pin; + u8 min_gnt; + u8 max_lat; +} __packed; +extern const struct pci_dev_descriptor pci_dev_conf_default_normal_dev; //See details in the .c file + +//Support for bridges wasn't tested +struct pci_pci_bridge_descriptor { + u16 vid; //Vendor ID + u16 dev; //Device ID + + u16 command; //see PCI_COMMAND_*. Simply do "dev.command |= PCI_COMMAND_xxx" to set a flag. + u16 status; //see PCI_STATUS_*. Simply do "dev.status |= PCI_STATUS_xxx" to set a flag. + + u8 rev_id; + u8 prog_if; // ] + u8 subclass; // ]-> prof_if, subclass, and class are normally represented as 24-bit class code + u8 class; // ] + + u8 cache_line_size; + u8 latency_timer; + u8 header_type; //see PCI_HEADER_TYPE_* + u8 bist; //see PCI_BIST_* + + u32 bar0; + u32 bar1; + + u8 pri_bus_no; + u8 sec_bus_no; + u8 subord_bus_no; + u8 sec_lat_timer; + + u8 io_base; + u8 io_limit; + u16 sec_status; + + u16 mem_base; + u16 mem_limit; + + u16 prefetch_mem_base; + u16 prefetch_mem_limit; + + u32 prefetch_base_up32b; + u32 prefetch_limit_up32b; + + u16 io_base_up16b; + u16 io_limit_up16b; + + u8 cap_ptr; + u8 reserved_34_8_15; //should be 0x00 + u16 reserved_34_16_31; //should be 0x00 + + u32 exp_rom_base_addr; //see PCI_ROM_* (esp PCI_ROM_ADDRESS_MASK) + + u8 interrupt_line; + u8 interrupt_pin; + u16 bridge_ctrl; +} __packed; + +//This is currently not implemented +struct pci_dev_capability { + u8 cap_id; //see PCI_CAP_ID_*, set to 0x00 to denote null-capability + u8 cap_next; //offset where next capability exists, set to 0x00 to denote null-capability + u8 cap_data[]; +} __packed; + +/** + * Adds a single new device (along with the bus if needed) + * + * If you don't want to create the descriptor from scratch you can use "const struct pci_dev_conf_default_normal_dev" + * while setting some missing params (see .c file header for details). + * Note: you CAN reuse the same descriptor under multiple BDFs (bus_no/dev_no/fn_no) + * + * @param bus_no (0x00 - 0xFF) + * @param dev_no (0x00 - 0x20) + * @param descriptor Pointer to pci_dev_descriptor or pci_pci_bridge_descriptor + * @return virtual_device ptr or error pointer (ERR_PTR(-E)) + */ +const struct virtual_device * +vpci_add_single_device(unsigned char bus_no, unsigned char dev_no, struct pci_dev_descriptor *descriptor); + +/** + * See vpci_add_single_device() for details + */ +const struct virtual_device * +vpci_add_single_bridge(unsigned char bus_no, unsigned char dev_no, struct pci_pci_bridge_descriptor *descriptor); + + +/* + * Adds a new multifunction device (along with the bus if needed) + * + * Warning about multifunctional devices + * - this function has a slight limitation due to how Linux scans devices. You HAVE TO add fn_no=0 entry as the LAST + * one when calling it multiple times. Kernel scans devices only once for changes and if it finds fn=0 and it's the + * only one (i.e. you added fn=0 first) adding more functions will not populate them (as kernel will never re-scan + * the device). + * - As per PCI spec Linux doesn't allow devices to have fn>0 if they don't have corresponding fn=0 entry + * + * @param bus_no (0x00 - 0xFF) + * @param dev_no (0x00 - 0x20) + * @param fn_no (0x00 - 0x07) + * @param descriptor Pointer to pci_dev_descriptor or pci_pci_bridge_descriptor + * @return virtual_device ptr or error pointer (ERR_PTR(-E)) + */ +const struct virtual_device * +vpci_add_multifunction_device(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, + struct pci_dev_descriptor *descriptor); + +/** + * See vpci_add_multifunction_device() for details + */ +const struct virtual_device * +vpci_add_multifunction_bridge(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, + struct pci_pci_bridge_descriptor *descriptor); + +/** + * Removes all previously added devices and buses + * + * Known bug: while you can remove things and they will be gone from the system you CANNOT re-add the same under the + * same BFD coordinates. This will cause the kernel to complain about duplicated internal sysfs entries. It's most + * likely an old kernel bug (we tried everything... it doesn't work). + * + * @param bus_no + * @param dev_no + * @param fn_no + * @param descriptor + * @return + */ +int vpci_remove_all_devices_and_buses(void); + +#endif //REDPILL_VIRTUAL_PCI_H diff --git a/lockfiles b/lockfiles new file mode 100644 index 0000000..6695d9d --- /dev/null +++ b/lockfiles @@ -0,0 +1,12 @@ +# no need change, this file hash will check by actions/cache +https://sourceforge.net/projects/dsgpl/files/toolkit/DSM7.0/ds.apollolake-7.0.dev.txz/download +https://sourceforge.net/projects/dsgpl/files/Tool%20Chain/DSM%207.0.0%20Tool%20Chains/Intel%20x86%20Linux%204.4.180%20%28Apollolake%29/apollolake-gcc750_glibc226_x86_64-GPL.txz/download + +https://sourceforge.net/projects/dsgpl/files/toolkit/DSM7.0/ds.bromolow-7.0.dev.txz/download +https://sourceforge.net/projects/dsgpl/files/Tool%20Chain/DSM%207.0.0%20Tool%20Chains/Intel%20x86%20linux%203.10.108%20%28Bromolow%29/bromolow-gcc750_glibc226_x86_64-GPL.txz/download + +https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.2/ds.apollolake-6.2.dev.txz/download +https://sourceforge.net/projects/dsgpl/files/Tool%20Chain/DSM%206.2.4%20Tool%20Chains/Intel%20x86%20Linux%204.4.59%20%28Apollolake%29/apollolake-gcc493_glibc220_linaro_x86_64-GPL.txz/download + +https://sourceforge.net/projects/dsgpl/files/toolkit/DSM6.2/ds.bromolow-6.2.dev.txz/download +https://sourceforge.net/projects/dsgpl/files/Tool%20Chain/DSM%206.2.4%20Tool%20Chains/Intel%20x86%20linux%203.10.105%20%28Bromolow%29/bromolow-gcc493_glibc220_linaro_x86_64-GPL.txz/download diff --git a/output/rp-apollolake-4.4.180-dev.ko.gz b/output/rp-apollolake-4.4.180-dev.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..944b86d85b0d55695dbf4e7d7802d5f69ee17387 GIT binary patch literal 67095 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

x>Q{jw01Q0Nu>;xv8Z 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 literal 0 HcmV?d00001 diff --git a/output/rp-apollolake-4.4.180-prod.ko.gz b/output/rp-apollolake-4.4.180-prod.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..d22bd52cfb25e02cc0a2f4ac86dd905db369a311 GIT binary patch literal 32519 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 literal 0 HcmV?d00001 diff --git a/output/rp-broadwell-4.4.180-dev.ko.gz b/output/rp-broadwell-4.4.180-dev.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..e74b8e10ab11204bd3162a16adcbbab178d84ee7 GIT binary patch literal 67901 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 literal 0 HcmV?d00001 diff --git a/output/rp-broadwell-4.4.180-prod.ko.gz b/output/rp-broadwell-4.4.180-prod.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..e8ce57f5b04a56b8911f11dd36fcf465ef7a4c9c GIT binary patch literal 32570 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 R?v6lbYe-IW%W>u`(J~BtX$t1_vS@=@1OuR zgXeZ16hFJXadT9;X=k|!SV4Lv4Bxgp5SLhw3Y_UU*KjlZRfCR_y~oVpxADVYqU+mJ zRM1O5Y?jbhmF_v-+GC-{VRgU1X6mi~fqxQ#_pf10=(HKoLw7%RcRkhre7r{Yc$&<3qSmn$NDgTtmAa6nCr8%c~@bSQ3z6Xc+%AHEE|l_vo`NxeEhc z+XF^6ou}VXE2_P_Irig+;8w%?ele2?OXEY2uGvA(mAwT|^h9dGM8#^7$8FweS*`~U z0~xad@poe*u3LfpdoSQY)Z9Z{*q`?(W$tD2PVEP{YtL3{D^|)n3m)-^ebLHtT8=k9 zp}&k{|Gcis%!8Z49Yl8Rd%yF}H_RxWK(jSRYtrT`hiJt?fxgQz9=IRi4wUM5w8^9| z;02C>mRH`xjW5McC86(DZti$nw|m)Za`vqE{b6|TM#7CeulY`L*n=yl}qA`xV2vhi0zGAcKr}lJ#Lfw_4L{#? zSJJuFm(?j*)4xIvyE^V!wWgfgRdv!KW=^oh-*n?ePX{CTLAvi}gSZ7#QTnj*p_k+< zRcri3P1ODoPnW3w?r<)R3*isn-iyKcul&^SjB2R+@Vl%^98)s3b;f<}Exzn{Qmqd; zuI1f@(Cp>`?)JQz`CC!0G2afLMWxo=*Ij35(vgS9{eBu#7?%ts63ZajM+(jO1q9sj{~i1w+txMyOp2{q0QNsaM&b^CdP>B(;=?pU_H%e(vdPWk;; z7msHs5AAfrZFpk4rG56%SJWB72lL`%zZ;;}`z9DcSHAc;PMCiVJUY6)&HEgD7=G4e z;AWI!z@yewE-iRjF=^EDHI}!_>)VNwFJ3hA25w4ye(#Gjmn>FZ{&x5Hu4|t1=GWSD zzaJ&m^ilVHds$r+S&+r?&7Jq%{(_XMoN;U@FgEeq=dv!+ka_!{+L!-Oa-lkE9JzoK z%Zkf&CWVbFZM@=#xeGYSx||(cE6p%>%k&bL9~$mN`J|aQ)(nEfwQKd}<1&NAE2hik zs_uT(zGrF`fOCz{8tdMZ-keUn8!#Nj`Vi`RAt5|IdG}K7&z2ZJ#^lu~;-;DZ7*DH5 zVoHkJdbz1yu8lLn8tnbrtp}nbKh(S9IFCsoaTg!;XVkxun_cg{|$0a6km!X9It;5!_)*2@G1UU~z)~Y_U^dl%&et#nbT)%!Tr~jILvS0c;#?%zZmTBSYUo{Rew{Zy)OmG**|3 zGoA9y|_ouS?AOF4qoO#??PJ65WtwV5}RfKw`*A(qU?n%3dbb5n^ zy!rU8l+`M7>c0<#_{=)#e+hduVq0jG_8gCKr!{11m@;zx&;k6Isp0jxj%_UQK$vM2~n z=#KB5%sCj;M&&gg9-hqE|EKjCmd3kc0;sEo;4U}Tz3i!xt?7GnFzA_3G_~?Ou-$*e zYn9d0b_hS2IQi(}nz3~C-PtP}3hN&|-Ab&$w$uG@4SKD`FHfG3 zwMo8tK)Cvnh0fRH?h(K&)Us(*Ra^sWs~QpXtx$` zUi0{hU~V-*On0NX-}~wMcG;ooZTwC2wC%dQk1c=n)RSOah#bKUO`9M7&&)mAxAf%J zSoi8+d+cx(5lI~a!ItMu?}!f}jY_gNQlD4nTB zzKw~n;ras$=D5N@5nhT}+Y5mg6OI$5ZSr%@5?<9)&hqKyX zC4kcL_kgW*rV1|2zIpV@%~8nv-Jb~5Y_9L^j-3QsbwvO6opHETsT+GjVY0~u(<-OJ zj9M#F#vkfqgZRRUmAGK%3iF}!lxQpAtxD3w#W|KWolMQby;EUo$^s$XmQ<(v4eE{+ z+xN}PurACcsW1h~yCM02JzWo_9m)4||5Xr#kYdI59f#*bA#_#xIKZ;uDXTKE(p{Y4 zEZ{NyMXm7W#(7XEh2G03*H)UgwBcO$8b3mV2ruS&x#LKc@NAw;wdJl!GZiet-iu^6 z&%6(B9^Jq&OlbMcCOZpzqg$5^mqog8^byR-r}5HiF{9OlWnys%-K-;mXy926%@O*9 z%;kov#208}H>2%ZkBLQsmK#QSh47N6ifEm-86HGlp3_ugatF53;cCDmL8LmWKlrG0 z>--^I@jCjqEag){e;y^$^{5*u4i%`pD5Q-5o^83Cus!@}#~s08di@us7M*0F<66#4 zvB@^hs?9=rh^^`4A#qw5#mIp%D#ZaE9-C*`%x&aIK_O!d!r1*;YcopJq&8hl02}&t z%`A-^As~kfaMwoaUB(7!tM9&Y$A4!eM)c%UTJ`yc0}O*YaVYZRbOx}k3$SMx(rWcD z3CeE>${R7Wtxhf()YDzH9ztFkqJ7$Cj2(7h<-H%rVydk1bPyABE*7MSTKH>9sxvAwDA2IXfK@wWMQ%h@c>8T&fbCn`>(>7=^s#H9dj% z4HBO7qATGOgPP`&qjSC)QfLi%yC@+;s#8PO7S&`(u{C6Qkw%8pk}^T-RqH4ebW{Tw z;6D6wu~`qyC6`%B9EQPD-Vh?+ig&3bMD*osMu*RQ4WS%8XBm(QQ(!}y{Jdh+kT+wuBZ~($b0+*_j8b3$(yL8U7T}^RdOKe z8gFC9xI{AdQ>6`i1*7*XMm3rgBpR|nRVTp^*OQb=zA{HMTK>6jh4k+mB^WMrus?zE zkdh*PJ?mSN0gxJa$z1J{He(3am*v)Y2<&6(QD^e8`5Iua4G&?~&LiLzC4nB65>#6y zt=6+QLH|da=R;HkUK;#V3h#>{(7!!_ybv@_33FIV*bMr_M^ANp?8{vPi(i<&=3*m^;z?#UcO2`Y|P(Im)7wTate6bsr%6pfA-OdqK6E4kZ zZnHF&}b+|6ftL^h>9KMkw0taSCutM^|$VRkMB!92nw3{}} zIXgPpIAt+1z$Sblh1s7&EpUWsH@#j?%zNDfGYP6+k(GJU&^@{ML$FBz<& z@yfo5jf_cW7{&l|O33f#WKt&hklEJ5fmvKW1iN!GU(BB~hzddfbuQ<|9^+pX>#N`l z=5u>%@7WWh>#`vy#UNs*&#`-0mHow6 z*qj`i49trYIu)&fQ^z<(8d&0&b$@s!Ic=&CVm65bYgqZ5!APT`sh;P05t*Rr*{-W6@} zuZBD;3U)g&9jJp4qL|@u`qFXSZW=QH27*a-LBb?ormo0=vUVRR0q5^#RVJzZ!pNeN zp>mm`q?ST_694;O&M0fbd=fbCOz&Qs19aApV6&D zEQ|-1ur`qqd{jxnU3|0XPQnc5jr+V2HPD@!ARQP4UW!9WZ|(PwaO3Bb&yTqMt_M=S zM}?9Uta)x~Ae)cunM=1o&RqJC3-7=gFrj5)5U2pz1xHreG`V{accdKrBDwBGHv@GR z`P94-Ar9mz^d0za9SuBZB@N6t>gzGAL!#929BWW{EL}j!l^!V{lYj=qa-1nd+Y*Sm z`Owb5l4{yME7TZ@uAo`-Sf)5_O9&_~&;AZ?!dFo%`fZT5Ws;6)nUX-_?Hourlxojx zI3e_GA2Kue(sjZa2Ln|rS5e}W0aRs3w}7(4?&tl=q^u#FcEbqK;LE`anXN-A{?}zR zu(VPGmd-Jb{oj46;1AZH0U1K6GGoc7guU^tFypVf1^BU&kQLHhUOBTzK{DKj{M;`O zcHc_&O5s1zxf1i4(9BAp6qHA>QXVx>6O@$Lxk~Co{F3>ZSvfd}*f}u6uy!U>*yPbc z_+d~~NRS-2Vg-+p7V(%Xe4nV9ey0O=uz^d*shsljbJSB(Ra6Sy{Bnm6OcmG*%EEGw zbbEJn>vYrUk}(+$=^1Y&u7tc>a^du{5@<`(-XVL@(`&CK^wngAWSlen(;(sUT&_a0 zLu3GL=X3N2vC|dN)R=3H$|jN> ztsOh0wnB0Q+e?;qg^kW;`a<qHrw@sU_Oub|)cL0_Vm}Ww#~FZ+?5E&G0B8a-0ZqcIcS!ZYuRWUCIv` zZ0xy5-MwOJD;}l@NeQK$XyeHo%%stP5O^T?UX6A%nIxM><~L;sl!l1<>VG;L_&S3j zV~SE6;mz_NX*2zj^EXGBA%YXyM-$l6vfNmLS2;f$c@jEA%R&wie9eKgY#_ZQmw7?Z ze8{XX?g)IoF@C3@GY7sNmSvAq!tRaKL^#p4-O9%z->=~9nI;4W_SuUR;E4**;BJakB*wBTa*}pDOhA&;kK-)7uuj$zzfK>#6rh9xB^T1Fvbk!BAsRfJ9i{Gxr zfj(&|hY}_eYIyi%Ooh4Y=e3ang=B$<;X{WK zL&61^Yix9HCi68xF}YyI*{L}RNgqeZ>O)x3Mv?eTcx6blnT1ejBP6>?0~M2L-W<%` zPE8XFt~fZSUxa%{_v}Raie=e+w{%YQA*_4(80SzInK2hnaB}Tg<7w$bsNZvPfymjW z+rOI!*`*if7QuBLTGZ-VPE}#XbT9U~{nRK^AiPogWG^HUe1ZnnG|RV%*a^UPI@Dr$ z4=k65RxJpE`?O+01b28CY*_Ne11BBGx9qJZYlpKdl?liX|1*?Nbu&mem4wl_mgA9O z{Q6#|TOTzqL+bAgm_!b6Wz(4X*&@4-xWR{~Xm?g_z8UIofq6!j;`%i3&=Ubc3o)>g z{?!kZLCgKTQ4`75IrI)E=JbUjF6qP2AQ6mi6-m{G?6h?kf^p`qxUtY1&(WO;2D+i8a&ftz!zgBV0~c*o5kf#0|-WwI&8xDm@s%s4K#+t7TtvPxcH-IELcRL zJjaCs94Y7iqK^nL%ZT!|>B8F2;M!$7iF-edtC|KfeXCZJ*RLku;RVqMc~N60?^^N? z(}R}pWM62-SDxVex+PA6LFGy$B5{(&d)IlWd^=V7fM9l`)hP!a3X#mSXk9%KVigR2;+!c0JC4xv*zew6M68H$73)Zy*h zwlVFKbYNA*1+(OlshAwkHtL>%B^Y9!oFWCs5pB|~oM`F4jmc%%^dVQo_f?p>l!QsF zT+s5E`V*&vDsfz@k(L{zNEruTlCKJWB(dnLA%~h;Bn2 z@~g7cf)G{WG7D{Ql%j=#6 z9!_&}=;3_Dd>W|4U3=)5kgG*^`STCJ7mtVq*hd%^wZL>V<>PT zcYL$|Yg2#V!Ijv(^SGUodC@$j-T^+#5?#Q0-^4Vn%*zwTvbo$mmaQ1LEFkW7 zf}_@C45b0t+=OZU8oc<1KS@{MZ#b~WWhaxxzoOB-rguu6W%F@R+3J5jU_!`IF|n8l z!WdzOQlvr$GLi&%cXPlS4`-4acflSIiJif1Z9BhbF)uy9Qx>U4pvSb9#f?Af0*wL) z_B8ab>mFJKZMPl-nozy63z%Nuy3+$fM(FHlsDABdrqBo+f3EbPh_yEYOh?G}Jh$bI z=v@OG=qUphxpNAl4NZ>iZG|HfW3`M6_+`hbk_9C?lrWAGz^@44&WRO>$^Dqg0FK_> z_zpX|`-xnB*r9z3hO57G?R$oO=hqGss>BRdxT3G9Vz8iW`#0xrh1Y`cL67YD3h9;pXs}05P(9_#v)>%WI zNR!5rD{+&9=v_`oNVsu(ApXyVV3EzdFtOUp?|IzJMU`9nbw{0$1qv^7`0yMaNlLD0 z>1TTPGMjRgH_;B46PyJpmB3wlcqZH28E}fkDqYB3xCc2w@{A!Nl<8uzL1u>3oDM}wE(>mXbg$hq zmPYR4IqcA2MaP=GB+kf8{ir6F&|6)F>dxf5n4n4NT~fmiC!+DF89`NWV>iTZ_XE1{ z6G0ocZy@_Yn+oH-gYgKl7J6&<0OQ{-h($AezIFVyYwJv26!UqM5qi`dyH#+F0l>tg zI*g8s6k&%qjd(g)mmM^7%!`EJKYC8xBmg}b$?R2U_yc<;>R_aF^3PE^Nr^nb2CC@y znQ(KMf_U-KRT$X?Mh*yC5$6^Xl;#Cc7C!$^f`-VCe2YXq!?4kV6=g+N)GJ7Y6bEX- zHYSxuFd9g}eqjTrBEN9q8gTEGQ@Y zq{nKgY0}fqxc5V~r)cM#;dp!MC3$r`cjaO?LJsWY4l4WhkS8vFe2{oLQJZyLLE>LW z6o+5ub2a7@$X%9{%)$6DC&LPq3dP zGFOl&+R(=s2Zy+Pw(&@2q8+*6qd3+jnM7S(%BF-W_G3=9CZe(i9}8oZ$n5ge!BN3duEsIc(z=sWb#M~_OejdUcunV0$*cXg|NfWdq$wb~e6aJ+xz`VOTwfUj`|E#9>O;w_F zHZ3`pM4ik*%dv>!(N5f}A*4J2?P4D5ZewZcX_^8U0p48V%SLF!nC6pP#McHi7NC4)Wynv zq9rznvT8R9N~elS$lxu(J|e;tGD7h66vjfJ(Fd28=9YA5Zs*zQ!f^j{S(^Iby3*^# z9hPFGEoRbBe2%@;2iKIs%_N5t^8d+jU}r&0Xp)=y9A_X__7P39Stx;Cy}+8y>4QV0 zMa5VJvAhDIl!7~chbw-qxRY>{*;c6N4Jk!aPl-+0bs75yn&vU*YI&%qkO6Cqg`YTq zZ8QrM48kHahwvW(SQpc~yWl7`WEUV+2NpfZDpIsAj9>!WCe~aboRsbZcgWK2-~zk5 zYwPLBoyx8Id4T6tg4T1MWfv}M+U6W*da7m?>A?vwX@{cV;ew#UpgmRwf|g6cX86%9 zWg7UHZkT2|ENp?=o&`CE`RKxd8LH!>jCG|l8NdyCUiM8$CuW6Dq(z3bkv1$ZRHa5rZwlX*=z*9gE)A|>i@T_IFVSrrZSe%6KgxHD+J778D0CR~fcsY}lXxbrzsRE5OcnwB0 zsyWv)cDjOkxPoj1sX)cHA6T%InB@vCcEFuUhX}QxJyvVU;Z%e1iu;5M_|Kz@o9IEr zqTb9!+wacD+7g_Rc+s886=R0lSjsQEn5F^uEBFZ$SBsNs>DJ2?zR+QWIzIAs zNTjwVOBHgGgSklIKK3R;+^K8t&rx$l$1BFnEu>(SOK2Q8Z={^LjaI;uWV8At9>N12 zZB+S1#-rHnzndTNGVfDmC808$Yk7h-Ma?dlW1 zxwXFs;k%G|bgER-ncN>*Ir$A(887&U?_T8lh+OCR2YEdz55!1Ap1Kox-%aegq>uq${$bH~<=8(lmv90Sv)R0qC!jJ<7Sjd-{Fg8`u=6 zY?%e*x^1Y=XS4{w-fkml1X#;AHkhZ%&v0=qmGClqCJ4d}0Q!AyD}W=I2?Xf?r&jyE zHiJ)=Aq@zC5}0WN-C`Ot@(T_;8wYFy`7q3ihH)(msK7C2@;#7-HrVtU!%zr-;3Ghw z7*d@(cENxoQwt%h2IS!s*u)K_0Rb6;BO|kMZ$J)x=;hQA4UUiy@xSnon0x}{JY}U& z%!&=gNckW<0xt$BzXG3}23bIWV!&nmuNg?o6#NvfI$n$f+qBO03B*X$9CFWqkOqD| z?Upx2x(12@0=i~6RgkgWU<)IVM7;)HOsEIhxd>L|s^bNC6AK|Zka2{L>@a}=1==EN zR8XKGi)Cyh#*=|399Mu1RGE**H1%7}e1_t@}ov1IE-9KCQA&gm5q;x9{x@mKzT6D}MBYii7+;!w^6L^+qR3w*OVh{XP{9Rm91 z|K!BH0<8OgCChv&?g71Yl?;db_y1H2P?>QKp!D&xESCIdz5#BR6KixiI=Odk8+GRZN1+u4lX_P(Sp|7E zm_{RrCh7=&s-=)8Wsb0cV;p8Dg1oaMQP zg$q8%gVrm~J@VuMOoTO$uO+fm$89D3@ajajQd<=^TCP1ih1oGL)nhsB<|# z5?mOVnIM*07NvhdFdi=0>kGTj1ShY%e7pi-G*5&*4@Q6~z&^$=^Mi%y|E|8-U5Ed7 z%^f4lh(^?C0?FB2`=u(LDhdQ{&&=0!bSX%-c#xGuHtNWYA$0;Xb}`-jBT5yh=nK9& zJMG;~TZijpC;VccMUU{44G9DtQMfA%x1Z+~kxxa*bsG^T)bSXDCoQwwD7wuHWH6DZ zTM3L$1*5Z96sH`TDT@Vrq>4Y9{chV3(t2qs10Hu0rQ@WsA-ky-d?j_~^5=<6fwXga zcIFug{#GHsV5j8#O4t!nMtl;T;M@Lh2f$RDMg$Bs?<7bRB}b~^g*?!^mCU%Q5}ZXB zD1<8eo^7Zz3^!=81;Mrkv<_sU7{LA$IdT)p#;ZP(xW$0nJ zi3!CxS=e)zVw_^dm~|g+18dlX)ggkjjJd+1o}Y+SN`F=7L9)T%GHGZYg0EaYlIk_LGlcus}e8K4cj zt`545Cpm$gpfRr;Uq$cl48_%1#1+#Kx0&YB1A_S+xO~VHf&5fx4skugRB9dHPRDIT z@23-L1xZu6>VTG5wwt^OStp1MLw4he|M`)OK2L9_O9wwC{}-NPHx*6Me>5XK`qZ;n za|-Kqy&F&e;OH5Rnf&RpHWf{~(amK$Btp6arlX$)b?b5xzU=63ii96Ptj)kC92^aT zAQhhDH7hE!++EJ(!yxh^1wFu~A+oF_I77O=2B$27Yl})e02!X8jwql+8ZZY&R`NV( z>$z*&odNLFnVf{5(J>$5Eh!vq{$(CQZW|(OO}2BUdCu2Af&U&XI4u$m)+$I&)Q}ZL z@`@5n4Q`vLUQwc2gOrgx&cK!q5z{)ZkH#lc8@(lMgOD3@a%K|$xgH%+wg;fb`;pNR zGJoje#Nhck%m4YXG%$7$AX-0&yD#hYJ{G)WxzpJ!fU%k6YjXe{;UPI#Q{lF07c? zMYFkj8mbKazPB$rva_&3a1iQdhgjr5>o>eJc)-V-b`W1e6eQ4YK7KWg?(hbC3Uluz zL>*$fDA#S=D>}m2rAItP^7xsTGukgY#W2>Tq5mxAJ`nJ6Jq5b{%RZGa=m~-ePtKo( z_}i4~mLRu$l2Kn%v4vbkLJmG=t6A%%vo}d{7mKlZ!xcCQBtUw}gm2#+vmmR>(1hxm zFhtSHbGL*uc`I>G#8kjVcqwlskf>B#Yp2+c*7n7!Kx5X7BIL2}{;G8U^7wbCN}S3} zThaY}htZsG3fw5BA=}AD78JnK=vlVNX*eFJ`_akzV|D=wv=S1s1tMaCg&>(kZ}`E9 ziO1Q1YEpDQH*sg+{P>E!1ul>H1lV;7Pmaxg%#CaF#!l*po!g)ExBfE0Nj~f;j0zI! zU+lxF-l$!P?3zuR^sZ>Q1p;^A?v|Lk3%AyYUVou`#t}cwt@gVvTCigNilxm!_u8eN se14N6ixzd5JrAsI0EhJqR`l~Ce2{EnlXZL+31kIcv&ow3n~STQRr+w`>dbP;C?TMP`o4Cd~0 zD)wl#$DV4}UAxKUS#tLJwhV!&^1J3Kx}MfGYrWu#FOl)Lt;b8784&m4_GYtH|K1payj|Mcv7C_ zvDxHUxjM9_evSM*4!CVvx!j+$z~lP*N4Z>%L^s)KLO%qz&7^0zipI(0!6c(kPvIcP zH{P>yzmJ|ZHxY>kD@gQDt44DL*ns<*BaZ?D14P z@dmCAWJ1bbeRD{#VgUK&ql29eHuE%}>?El&HZ>YL)#p8R6G?eL!{}S$~(eAyr=m}m#g$Se5K`GHrQ8p z+~zJp&O9J=rwLYa5bfKhSW&2qA|LJjQz;{V`F=k=?x!d92LTmu(Wz#nNPJU6n8>8g7@`hp|Wu6fqB6dKu?#_ zfi!piJ>x=xGoz1RQv8yioF9YZ^|AvpD*V6cG z)#peqcvX1EAfpC!*oA6rE7adH`Ztqo&b%rydtyU0;flBI2~HYMAFcN1+5?m4Ta}k4 z+Ty`VqNzASv~V1$?RXGyOY-vxI=Hf#SyeGTh>>hgAq|2iIl@@LwoypG!7$D~phmcY z6ro9d(IqB~2xrB?V0j<&3=#?#m$rqON^!psl#x2s~%bGAsrAF*c&VD%^y7g7;ze zKK~9OnLN}{J68->d}Sekg}>QlwE~K0cXU@6WQJGQUSw>x?(d7k6Ro_^pMw55FI#_wkM2WPVE6$V8Z?9i=CAkXP{^T1VWmE8W_2L? z<3^wMS0s`RUTOYP*e1wXJU7^bqp1;)Y#VFcnIQ7=vrWadFb z@A{$}CFT^_guAKdGV_3Wqp*-zByS!It!hfpIf4%}7{k=jup>+8B$Q7rvc4jHHSr_b zayIdcW7}$_4_y7b1w>xsrym#6iOIlUM5zV8f%PgA-xtT#GR}UL6<(TB9`Mn(LHJ0y zlBax@m!9|2&ph;FPZ9lGMqi3Q)&-oNuUvj#HGjSud>(D8x&J0_WPk&KsTm7dTr7C} zA~ahK|9nZnHRK(abdI8NW6s5IGv0V>oD@?;$~g$1{M(4u9R5(7RR^vm~OJ zzg?2ulFvdU%UL6tHKV28L6f`PSZDzgtZLoP*`DNqz-MgehzL15Er!(gOGb4T64F5n zil94un=SZ}pN`@*DQC%z1RA!@!zgF5*?{y(Ao`) zZGtpb@VY35n)7|B9!~rI&cH+{ECnC0;Lc*&^zV87QF#W34oB=oj09^6bHlu1ap$x9 za(@3zE%oo9awUOJeIh-?e2R;R`LjrlONV3PFKALPA~SN(f)nUF88)=8S=594p6Oo) zO4Smw!QXvDtcUjaf9mma@cZ!-rA-QC`RiABqCl-kE9hmQC(r4pro16h6A5Bp!en@D{^G$N*|!un${Mzl;#|`<2`rEMQZY+y;Ot$51y}7VnkFIm< z5T&!;%`@nN_u3{0zIunf+M37Dx(IS?-1d7`NkV5x*i`sjX3DO z1?%l~7uJ4b_Aa6kr@MX0G!+WESVN6EbXo0}+8b)neDJxy1Rk;ti=Cm5(#7~(InALp z+Us_^LX_HCd)+OeQgvul9r_TE!`R%F zh4JkECONiZKGrM=d$26Ktmekh53&g?Mhey{+wF{>8;A{}C2+zu!1&cI8Jzdf zA+jI$WY`XNBSsK;#ZOlG)Zooh0o9IjgD`dpc9@J0#-H#!T(7i3=XMvlr6r)2_?5?;T^wtl`G zYpls8fRLAA9k1)CIxNX;kL9ojb5cJF&KM{jN++*H|FwmGW3hn-_BV{7l^$G zK0iIX7<^Is>RjPY0r1fplhMXRuD!7){Wd=B zaw_W4li8jUIkv|mdxv2@3>;DWtFk>33=Hvs9csTj+haEd!bdk%gw+on_?+H?9DgkN zpqCDH=A;P%9jpmtSCkp46JEMGbUv1*Zv#|g^HtFIa&$r3rb?pOnIf@p4|+zlHI6Q) zF&{FD8!llNX}X7g=-2G;@>sKvCVT)F&_qptcg-qMRFpIC@@YZ8hXp2ddfKu|?iS{S zzh84iyP1BrfY=rK-|7XY+=d-Dtxp@QucY(Ei8iit&(~0s`8v9Q*{4123k`pw zsJ#+OtD%M_)S(^f@GGEr4mpruhF@ykY?-HSm2+dcQ6$nMuB?6-xFrTyT+rWQZ78r- zPHTE4w$#S>^A!sA8;a}|gP*Wj+B$e;yCqs+klXI7rtQ|Etv>rt+*U#J|C-tIpsmnU zvhIcO?vxny&=J#|+t)8t)Q{}J=|pR+B&ib4wZ?^EQnLy?Q}F9nGyqd2V8W|vM$y8C zM+$8R6a&nDeXY^^a2DGAB<^)vWz(kGpX^(l`6D_S{)#(?gO&{-h%57R<^z(paeTmH zMUI^VVzTbVpdr6NiM)IvmrFkkVopGD+fj@fQKe*zZGVUqM0)4bK zOg4Yg&NvfU19C%{GvxOq`e%HC!Sy(3H{4UwjP{#*aTd$N3;dm^r@~NAnVGqnP>cR2 znyP5*2Ir8?qlmwYRaEkw?-f)7sP^bALOK}rDgE{wF91X#p|zeOT1d}qx2}(QzERJy zysw~!D;?9nvF5idOLXYp!mUqS?!oA@CI)La&#YG&w(uP`;|S!EXfL`B3Z=_j2RXQU zak|k;Y_<6|?>x^e;kXcaUnCwnFmeB*Nq??@8Pf=%z@%38_KFGYysoeht?O~oz2Ra**IdE3&m7K2)O+kK9f$R7UC;;9q7fxBJ& zE`Yw8Gg?^FVdE%OxA4F7p^3Hz%M!?PwzBN( zOQ`f!%+EjlYI%V^@ODn!2=Irsh7z*}lLh)aI*wr)O2H3A3iN$!{{W}np+Cjy&-HU{ zq5;NU8GIEwYxo-wWF#A!XW%O0=zC_dXBx-j!&nI55U^Nwh=bq{RyO=fJp*5)7{qSE(0^t6Y5YHjU8 zPVLudHe3NThD*lx}1+qg%V(J>~Me`^ewT{!;fyweu414 zXlxFsv>8ZvW2x|-D1|M|A+y7zgQNN5Ti$;(npb&zj6e2q_;X0`$D#l8sD&O6p0xvi zK1D`Z_#?-b9}17W5v&W3e1d&ovrE>T^l8sjzr?6J0CoBy*reK1p)W2xkZR6{D(hfT zKf`i9!?(40Sr(W&d73p%3o=qiI|2oAmVM_egr86 zO}C=%ou&P@*3y2%cC1k^7xdeLv+{X?z-}UBxq<5-PZ0{@!#HO$7Wd-g?dHzcORwaF z3T@f6ccMLuvzdiz&tYY*j+6#x3--vdFlH@reUdsPsi!1$L;?p@H5ih>TR-j)_&YK2 zGNTNh$`|)rcn99EmHQzlpw>Pum<==fao{Tj{C5lCD+}Q9#Gn+YLRd$Ebb1W53a1IDDS z&oJ4uvvrs@&YUNwz^uvgvjeugKOL_N3+asY5e=CS?~D|6xWOHH+pZ9;rgwb{r--g>vAw1m(AC>$gM&6yFcen* z#!CS+h*|k%=H14L6@LTCqudrZ7zw3eAo{(fm^q6swzWLSbCstZtCO1jDPY7pgAw>m z(eQYj=$wNqTyO4+v(g`}f5}hH?|S_7G-H%P%LRZ>?XA};Ucz*ltETF$VyAgBtCY-A z5v%ka_#vJ?f|15@^uyG1HtTD63iano{Ma`UKZ>^HUwzS}G-Y3^c{=R4sAkc#30Wd0 zc28oASn`s=6MBx}(JI(U0{(_krZ0?IczGIBM*&X(@aG7&gF5~G$qHY^6~S* zEAgx6OY4v4shhu;0_hN+y7t0P_bp$60@>xrx-pz#9e~bD<8Y=*a3-}3^BnfACDW(A za(2JCs2|ABZY)UxZ%5>Am7m5NdeMiS$Qd8-EiB|$tzthhY7<}G?tH{D(=E3lc~`u1 z314lW7{Mk2-N#1R?Xmp1NpmrM{QNv$w3^50NVHF_KV)R=yhvRV%8XOC@XU(E+w9Zm z-yI@%IVcVb!)(3oM{N0?1fhNS?N~Ng**V2#<`>q`KgJ)@0n+nfnW263J>$b75}hft zBV(b3e(f=*-1ZKma6{E~@|JDL#h&A3uB>ao*ZKS3@xQyH^-D5yu|Ep=CC1+b)8OfT z+E31{u8Q6xLHbI1KDLv(-A}9|QM)e?y?>`oYgic2ZXi8FWr5O%?M|Pz)In&1#sRX5 zL@Vwi+6pIJclosYoTT(#pbCoQML&5Fu2VuX9aQLaQa2d2ljdSyotvnXGY|ca4tx zt!1<_e_NHmotwYCIe%Nr@1l2scJea{I+a_tS$|=E{}#{hAqVmr1zeB5i;MPZ{lARn zKU!|bqzYiY9D5u7_sX#|N=n)i-usYOj_qtws4_)=%?e$79>6~IQrJg0e9^s4^o%|@ zYA!1D$*I@p(V!xCYzgObu;g2?B&?O{3Qq&=^wP&mVAXr4ATe+w={FTlv#c-25-2pc z9D9%A@3|d)4{-u!D$IkZ2*F8OF3)i-;J19+?dRvVY}wj&?bb$~ zP)ST6p{@$Z(iDLpvO2>9LBWt;WcHr>?1IPE2 z2_J;zTk-ws8o-B9c|CLzeWy@-FAwPWuIKpNdGQ6T_&)C+j=YS|Al=%}QYa+^rM4>9`Sqe$eS%a=mtOc1C1pX!ovq?x9_{D#yH7x9LsxnH#1O*F|s_sTL~vuDN~@(FkvdpuIt zE~0LT+=a)b9pSQ*$#25W#Vi|v?o}T!T$sa=(qkcXjs@UbC`&cG)k3<>i9L2y>GLTu<4j4;2$bA(Co^l%lEbY>M6G2C`R!cl6n>kot zLWip0x(rxP$0v{CB{z&xz}&msl&dAW#l&d$Ll670#>njdk}{3z3N&KwFzyyU$6Q<5 z8*eE=;e(OHtddBegX$aHK_yW~kN{4R>jR4puDlz6EsB-lp&DEyTUrPX5MpVB_y^A{1+E3P{MT9$gH%jMF=O-%eV6jq9f#=D`aB`)z+ zcvvNt?&JM$O^!*oR1)HA7fOLoR>92!F(IE8*R{bl048bPBJBkInpkp<2wiqsZvKCu zW&9;8E$ZUToXKJp1p{_R+bJI9mNGmCnfM;5@}<#qu|wtobczQ|6=Sx|bYlUK zZ&NF6t#y|>ibj!4Ad&*%06VL=qDO{A9MkKtV7`y)Dj5qWTb zltsOJ+p5)b=NsK5|2b$eaA!c{JFX z^K(o2_OoDX`I7(Sq56#f^g6-q>g)MOdLvdDv^DDQ@=!s(6Q^p9aQ)@1h{TPjfY9ZhgzXR2}ckIMAxI z37XxfBq>2}`cCyNmth^qf;9@JwBQZ21`7JcL@*$s;7yf$B@~qs5ml8a72bxqFEuOGaVs=3NQ6aP#uE+6c@r%UL#_iVe_tL@wJTMYURfW)Te#xqWTjFF%LKpD^ z{G7=Ou98(`FYcETLIqKZ__QM`(=Ui6t1U&eCDbONdas0fIw~eYr41G3QeqkI_u2UI z-gsy6`d~TJ1sT09UflP(eWh^P)Z5V#;LF6Y1d^?;w8nS9?4Z- zO4Lo{dzOC17X_#InuF!r+_JE(D7IWwrf(~jpT=sACWek0JH_d3}n_r2ScD=ucnH{*>_kjD`Nx zl@D3_lamT#f6P75nyT3$hM{-4UHT!0->4MP`3KEwJUO(xs5K9QdB))dr50;?bO91j zJGs`#b@aMHViN;#nT|W0p+HjR!oUF3%vP4q^(_ zTODgH7Qx#dn`faR={%4jRf-OL@(9SUPHnjuH)gAfb0v38VmFq`q0**(Xroe8e~Vm=w_P$I%Gt zGOB_=t{5Lk$FK(3B?X=xE8imp=9b9iQs7ScPARa=E8hWk6(7vSO%dH_V7>M*+!7Vu zaBIK7yIgD(8#&{ts9!| zak*9%2ZmP65~_(IL_mMat8Q~@ue6je)Sg;811$dN3jq%?cylUsC;kyLph)XUkI`#h zQyU6sE6P}hz^rhsD~qil-8N4dGd>b;_fjS1511pF7#moJ0COGV38awFg^UN_>hrnM zydW_Js5bV%x&dIz${InP?xD0iUJySXw~ihtSg9-ED1O}_$r`hj97hwu5du1vSTO>H z4<>>G^Ai5ApgQWnQ!F_VZ;Er`Gf0UmHUqH73c?<FWtiZSESCRNo}Y^d>o zp5imKGRr9PrWmM*MzLKB&?lcCU=IATmeJI=g)a30TaW1)NzXw7362o9!+*7`Am)@= znR9_h2H;gIijJ$_E(pxGtzgb_Ff_85DYnPefFn4(&C(ArkH+_=^J?J{)T!QOr@fjO zP@RwW`sqv;`A2iL*>To-(tOlHc&gEWA^Wi#{^4`qOlAe3D4)o{6l^{f+l6@TX7x!M zjb^(U38CT2kGj&{qs(DD69y{J;`BV7iv_~Yek%{2w(vmvu0e~dGUk{2NK|GVWw>J3 zGa$uB`ExPdhP8#!@}JZVxzHQ5JD3kGu*|gSSr1zBSP0pooicJhPYc$^DoZ(C-zXd% z`GR31&(ne-UtlS>;(cV;c=NPicptHLdN50;mkb+uo)!%G5?eVv*p3>q)39{dG~{W) zXjp1xz(5uTe1F);^R!^dzi&l;Dhu*u!$zK`1w+29ke)v_Y~*=bFyxOpAg6GiCVuyi z@sy1SuquKcLvOpfCzf)oDZJsz2*#^_WsJ86M0@`i-$!}r6L6j$`BG)g@#O|}%si$Z~ zs0}M`INU4-&uN@dfC9s!W;~G2kthOa2PxD zjfZv{ue!?-9Z`@(g_nU+-DzteDP9SU@pIuJ>ff#SpjErjsFo+{NAp{r5vAB4F&y(v zrV=zIgpv_ujK4Kmgx>Kr3*Pt%cl`L!=zZ%2FO=iQ`;)%r`QG?(x4R{N;u3pO>{sDB zfv>s33t1c7`%a-^KW>W__`Qr^lPc?Lg6pm7M~)0gt{$YhV8|ugy56LOf2VH2T~yz9 z9w;`}@7u~dP6C690nTA!f9?*UUJ>mt#E4#^9xwnRMs#rKrhWwZ1TY6u>+u&u@?$CS zz0p;=$rjIu*-`W{SO`xQMEogB`F3z3rC_B3SDfOK0?C+IrJi-caRuO3=7)LK3KN!w z+J)M3NpT4axCQru4M@fjJe|Sw5E#4qAt)OI`1bdk)5pho}he$O*@qFg!)(;YoMOUM|Go_ryY& zvBZNq0ITdmN2pZI!+J|N4|10A4t1F$njo1)w$PcZrj6uMSnZl@wFNzP$A0!U>7n&5 zXa6c6nfh$K%yP=L#J(6&Z7dMgM(cpy0v57Y963Vv!aNF?b{Gb*nt5*f5|v=10^e(0 zSKyu1LH!5qjp><4 z!`~YEN0AoqsH+QT0h$QAirM?Ml_6m}g!Zb>I}^$n{JbTD6wRObXhOu(tXDu^3h2YK zmO$(32PJm@E}~o)D)-1jxO~1>o*ph=I9i_OYd%nkseK=K^nm(;BjOrjM61Sz~)BZttUcA+YSsyp=+6+T1CqV|wd-3hA2;Sf5Md>5-@3n70ms4xpJQMdaX zyfC5eP*F=%xf zPg9S>9eL7~kt^p5+r7}Ly&%zTcW3X(EvzS3!Sh7;kD>KT{;127oq9|%y2b$4*UU0? zk!-edmAcQ^2b(6r{c3o?X|gd2K5b-5M+eE)kC#S015ql73&Jx*RiII z=RpttOP3uW&oL&vQt-lt$kz;+Pwg~}E-HiuTFXwujeiCWl==G2g-~K~S_mBRCA#!s z)}Li|P`wuTnbjG&h_%Eu)QO&?c|8nYm45}J=P@79i3-(j_wFc=@3!i*r?3)MiM*y zPm(GBTlk0|$?sL>){CghE8sfy0xqam6i^sZRlT5W_QO{Jy+A${1)!l#qzpexvS;u~ zyyR$8k}&X>1W8o+7k@qZ-0W{4pBN1JZ1leb*l{^%3g@><=ruwW+C%PR|G1vqi`dja zK9u$3BmNSpv1yB2pWHo`tni>qG^N$$8PPX~iiy6^F*X27upUBPLP{KhTJYPGfeu*Aa$QG(cHJ4cpBWXa>P^YJ=knLUJ52-)x2b z9UWF%)@gEQP%bWO(MpmZT{2my7LnIR7}COEwX!K4E4OO8#0YZ>L_0dC;i73{S|E+c z%PpBNnKyqZ^-GigL+)PbLDKiSP3%*C$hcP-Qtq#}vQT-pz7}$nz`RXvB^hkx+e3KJ z)FDU0%34S`hNLLl+%z@X7(5!}JuDc)ZR#jTj^oxuK_~Ceak+kVEE3o+PZrmmBEuQj zCr`*762$;$QY9g?#96<4-K|XkL+K8XZCC7SQP}}9pWH@XheMMj$B(k@2IvMWcd49kM`7T7&{o1ij7<~+Yot1M|=|3GS8EZB>)>MD*_!x}v%Ld71 z8Z61l#UMA~gF>JqR?XhQzz!Di=MLgc@?|c8icfZ#uc(cSZ>%qFnH1wX?)7-Hu zL}hJ;n~-Ciybntx@G7=Ja!85oxY7T zyQh8+&4_Y``js;z=0Dza2`FF@ah79`uMy6#;j+ElhgH`qE^DdT5Goq6%^jPxtw_F| zlkN35Ti`W8NVf{{zGC^U+()Sr#~hiAMxJhW?RZ$2M&Z3=tV_O+$nCg-1aX|zMol7L zO86o*)-WU0SM59`v4L6EH?pJ!2^~Mp#rZ57I{&(4OrX+s43 zFC7O~8%bXq!UF+qISbV~JDYVS;LZDS)dA8ybKi<&JbB)nTSO@M`&gPzXVLaTem^O6ZNTFP=w!SF6F~TM?kq2LaX;Q`rB~J zboN%L(GNQ3|I+sS;ZYUW?k1ZM0o`cvGxcX|7feNb34#WJcCXoe?#iZs5DW4FMe2$` zMR6CzfGplba#^=(zh_(f`B~qmuMexfXRQ@(f?*+;6-7l9g`$A(VcD?$215vjeRJl= zy>oxfF8V$GSZ-#{oH=u5=FH5QIp=scG?av4(}vD(TMl|4xeX&}@JN{!ti18NT$K_6 zxrZ*>hc&t1nnnvc5(+CWRo4i|ac-pAA_PDkJ&;}UE#4t$kB$OLmMyuLIQ1Xsv~U-i z`%mf(_{NsR8iU>q5g&M%@%YpqIrGr+l9#}8Qu1-=pK&MYX)|6gc{ccOYYdxFF{YSN0cSx87=Wgkg4I}rcC;i`NJ-T98JYDn z8Ul*kM&JWJw40L?F7i)lxTjmLb>kWuu;-g-Mt;Oas%)UKksGSv|BU=C`i1jqw~R+1 zIe`EL+=!Vf9x*lQbR7WA6uXUVB7(YDvvkC_%j}hd_Qt5hQAkrme5#MeIOtl{n2Pyo zL-V^p@&hBvLH2vrm&C@R_JrkaGvt$=_yP5G@frxcqA%w6s9PO1yfEA^z?zCJXi<0q zfV&-mdz$m))yuSyyt*2+J28mPGf2(5M6|F$oj22nZ$GEw^U3Ne7sX|Bi)e$(W4EUC zRKTEx(SUt8p%DhVviLA<)IydDK)K-rYzhH`&0PFyBiI>Yb<#0ru7Q?|Y86f|B*+vW zi)X_(*cRw=EQrPGIsAk>Hwl(Q2V@HgvKox+?83jTJFA95x{6EL~4WY3K$e^f7!m^9X1 z%xX>Vg}JzmRUxHmr_#7X&X?Zz^M$1nT)(8Dton%9r#NNFBPQWJgA7g(Mxpr!*u+M_RORMo`JB ze|6j|p>_5`$`O+pl-gZrp}juDad;ea(W?egsS?^9Tt+P3Jrf!HpRBB^X(yCbk9O_7nZN~ z(jti|Z9mIO47lA@M;1%WsDi|Jbz+WDNKhWIS}`&AMkQ}&z~_z1eYNp2BtCN!(Ptfe zx^ttW2x62bPq#B^`Ib}FxsgG*_12HKAINOIk+&>ysf`?L8S7|hQZ3#sC=Y0 zemT?1P?|n*r0JJ(wl3h^jEePDEE^RB(*Q%sBaS6UL?vaIPyIsJC3-__+HfOkM7ws) zM_O_a5Tu$tp;S}0u9pfw*zk`s5jNYYLgG6n8O(+zLX@}rYH2}9g+E#GTO8Xp51oWP zzGx73uv6IU@!N#0oDqTQXtyr5z(j+J$A_?{X%*n`L)kg&|Aj59zaLv#PLC~O|7r%d z{N{Aof>n9iBS?Kx`q1QKNUi4M6c@q+lLwBe+AX>kRh^cYsyhJmw(iGgyRI^9iA}=E z=IiTO8p}zV+Z{+0E;@vK);@S{@Kdb~LPJfk(c?z*7!p^ikeXQHq#SN|8{UQ0iR^M|T7lmRGr4 zvGG!VTUdUzA_{?D<2m|(bb?dG(o4jNTMvFbVICofm4_(HHMV_B*;ZQ!Wo`*tB+Dr4 z5Z|_0`F0R{#Vy3QgKB-jx=PX4&BkENP3@d}TBpU++qwx4na+ssY$XQpx+U&##DFM3G#H7;P^r$od;t`DxSfQ zX={45CZF{yq30b*8y-dyk+tB(0(7Z&iT8~2NqDD>YuW9;nuzu%YKsov?f1B_Z!SwQ zE~=;@oM=M@jM9*H6b3N0wXou8*6c208K5HfIuIb?_)I*KjO$KBD?E|1qs-$#StU?* zo>3k107BXWe$F$lUq^3)S67u1s5nWEGtGD#Y*$H@u@V4N;k`o7whZ<{*HDckn4r*LKVBjfU z4%Ko4PuJP;w3gI2)STFmQQqnmI%?|$2geY z>oK?v!UkMyTlSdK81K+@kvE(C7Y28#|L#;OSoaz477LyXr>Gejxr2)>lM)kruGlBW za*fKza72Gz#~Vzoa#I}t1o1iRD|{inJg5xh)~k;TrzUn&tl6*ijEBEc9SO{-{hC%F zHi)=0ejjSyDnyuj5y|W!;O2eaS0qqj9OG=RhP3lekhFOuZ3LuUbCjetlC&B~yY?7K z8%NS=A#FP?JDjBXAnhmLkhHT&T0NvKqxBA)!fDq++TgEAS`SI{L)ule>~8FT`f&D7 zU*z*Wubt8~F*a_r*)ra#IeDE0KK$tmZ`3mdJ<&>?nsP7K1!w9GCrGy5glgf+k5 z?)i&b2NpYALi1%6=!t6!q5OqL)F4b$Y?O&8zYqi3PP$^_7GOqVS5mCl^}=E^5PhK7 z#&6$p_s~KM>j)0)bVstcs9rc)qRwFDZPih^nGoJ=L%7)OpE{=iXLA1U=aqz+1d!Ne zC9$71IeUE2p2AaH>n+sGCLS^H8E=CdoI>3J8g2(^H0gU;loBW;3mUUaqvo? zA%1J~+e7k+p|Q)Sl0CEYW3wQA-aIo52LQD9f2Ie#TcD%xXYo;t7gl3fp3Z3NzW8;y zGWc)o06;D9y*H4il(p=OUy8jTh=wiJD}e9>L5v)o+gXoKW* zbUDB~bq51P-9=0+$S8oQiN)BdZ!othWlEqn8?T5tdNaGa-D-j3spZQ+m_Zv~FFZ*0 zPiRULtN1^Q0hcj%WHv4tE%z98>BiPWYCs3HXwBIOCg9rQvOfVS+l1{I9A!4Mqn$ocwm)sb` zaDK2DLa;j~<28e6Z7_S84eK5q-W7y>uA=tsW9`iY+hti?1g2ueL)bl6(mF zH5lcsJ!nS5-2Kp)sN+I4F-d(%-1m^(am1dNJ#dv8N%?C?7=~iF#%Kr-8jRAGL@NlH z^=qMIB8`hAX1FyprNk$$y2Vl@=V6-^R37Gx5NUCuY?y-v3B(Yl6JbsP>pP3bF#N(= zEZI2*s5^?r&OhZQPqew9);I(s>f-p6LIITM^bZSa3J`??eCC?epBF{peb~O2&sL|p zj2!0Bl8dSKsxr{@BsjMiY+|TOgtcOCB(p%*g6)|jWbdUuAS_hihAq1|&xg$BpDLBv zI?A!=XL}ZMVgIP1dm#r#Y)a@VA)FL>@ z*jtB?^n8v6AdL#;*h%<79z?ZO*N6eJ$LPla@K}NFBeUt4Ih|6rpq~cBBHJ^!_?Cep zBTz<5AQ^vLfCajb zD~L&|))WBOzsa+%YvjIuQqf4Kk^$v^&2{M~FUR{r{s^ma)$v|X*R@!AJHFW61l|tX z4e3IQIy(!-MmQg%^l_g1l}T?>z`&2nTDY7EwNFDUPhfK6D2=qrZhr-W=>XWHPixnD zX)LVQ5t`qPB=0|H!LB~0*K3&dR3qJzjt|zS0AMDbOwy>Kht(&=4J}D%k?829$4jTd zP!lB(fZf{yiw#|P=rUB`oTxuQL?o{m!3f!E4~?IK=d>HlZ2~CrK!bJPn^q$1raC%0 z(Ag@lUN+U8uuZ{_c` z$b=R3AQP^FvW{mOT_$j-wBTo7I~C(k_qid)4VpnvIQj@-f+C@vW4_xOLC&0W_$2H) zLhN3Ik>~ij#qo4%qw=@YTn1>k7r8Hw2EA*YHq4lk4JTZTI3in$EgjtAit#wUG6aq1RZP8IZQN+wI5 zVbhMzb-UJi&I{$YmaNUAQQ3xnLu>lszxXG|_mBh*>J)}LMW9YmsBR4PA0)l&g=+81 zuZNYsqkpMOuNzw4vORXL)E05M*G0z0$@((1J4^AIWbz zshPXsuJgVed{^CDB4R&=2`F3SEmtN^oUzx_>}d-g$PR{q0DCh`7;3cog%btRrmqdng;3=1 zzy4UHM5MD}@)h5j|A2-j#N|nBmjcFQrqF`B26O~g%iC#O8#Kqm-192b*z4Uqdg37G zZ-g1#$q&DOxk=b3(;ZOKQlf8l>}Sg>(ElaNuE`CO)2k=A zmtE;>KyOs;;OqA(B!DUjsE55vq7JJAo-HX33pO$v%YUAkf7QyQ68mm+Hcqp#}J~wbU zcHz?V(f{S~%cGeFkK5HPxEapb?SxPLPVq&*3k~Y zJpsMY?f1Cr(#c`itfFmtX}SJ62npDsp^0z<7vG<~03Bs@HXhEd?dL{xPQ3dOu<=V8 z^YMZ2$HaBTFtJP<%88RsO#E#TOnilBV%>I~jf>tH8kwI?#VSie^WVv*LyL9|4bAV3 zxVI*UJ&Kt+?3&b6x7;@*zFY1e7AsfYsY~Zx&&YS6O7C|CT^adq^i@^rcBA1Ae%#6? zWuNLZ^4)uam) zfy*D-2s@QCTxkJQ`ZgLuCF*l_q<4=s+J z51)U-sb2U5xA<;v>ys`sdi8d7c3nTxq!hcehGHInjIsk3z~(~M}Q*#*~3USAcGGgW+0AVa<~7w78| zp^7{MWBT^iUEY?pv?(EFx~~!w(F{azSNX;RpdMp}FqG7kx~IyT$h7)XsE&nYWvIrU79}^GSSBX@Ec}7x2_ISB2+B;rSBW=T4LnZ%7P>gp z+GQ)bX4PMD6nsU;MNL(koq)3DZ_If-ZpDruaqw96{-W`cYqu*v#g4H%KAB=FcKxnR zd>wCAojxSshlMIuNF3%FG}@-uI+DD@xSOeV!a$r?aN~nr?>QGZX`Y7T&CJIbLPDZR zy~eRJ*;>N-R!n=+GTC(B=cttK_>Gz18_fiBk$$wAxhr7(DZ?MI^Y7TiY?3pzXwp#^ z6LDA*1;22K-**}U4;zi#%}io3X|(vmv0v)*1z$LcQROB+Lf7xbioS4nHRF-4YR@WYC_$r@(9$@enBspq_B%(+6(IcChM zb(thww7~Nw8v$?QPT43zIpN41R<)=S+#2AJz-o#WAP$Esy1rb!%w(pQ zQXAb7v!qb6sWOy|@1#_=5eFcKpi7$bKDM*ENg|eNyQwF?WUw-zG;Rwh!L-u2gT-1i zGG;RvWiu!50p)NflVF}Th%xF(_0QzW&*m^wgG z2XU$1msjl|spVX1AQ?<=7}^#9m<+8`^c?B2kDIO0B3qF5`?5Jm@OU$HlD6OLelsoay?*w`46_?In2`;Ssj;?F`y;8%kIj!w%qE-NR8q4{s-lAs zz-(gIckM9XIPoA|T4-ocqz=-S3U4Q(M{;)BSGWbM86ko_p@O_nv#(dDD3m z-dvz>W_U4CzFXdR75O3IlV!L__+w(XMb33^f#;YC?ES-Ib;+L8`|(`DmArvG7AvK} z6O$xt0qoiM3*KA0OzNl^i*Be{y7NUHkCw@Z)Xp_YC|~e?K`f zo)7SFI(__JAj1B-5~4!$;b@NoUP3;R!5n>rvlHF$nu@<|L5=_N({ zje|Qy_MAOZXP4+J>cQV5>n+d@j-@Nl9^6M@)*kJnyK;fc6IcM*fv`PvdXb=_M`Av7 z_9;Yl@SC$+_f7s)pS|rfa>IZ_#>ArlBKOT4{I#6gK6wnv#4oV@9R9!9ntYmk9B%wo z=&V6WKq9jkn&e2^Y=+9O7EFoU+Ho{t+i^6&?iE^2X=Kp8dxxk0^W~9&bspElA5%x! zz5_IC^rc{N6o^`;PO8wT$9G`Ddq1$xamVkl3~ogA9I&PRS`E@(9dg)NNSUuW=>T z;Rl}G2DjUOEgIUX^=p8yN)Ns2!F&r>zg`~SV!nrq7z`AHpbw#efIyxCf6 z%eK0}~v-fUm3E!!QnWm{8Qwvg?>x3e9RY_-`q?}sr*mpaQi~=EKg^^@m#n2#c$mS-IKX6 zk*QGEaJa4RsVl4{TZX>WUU@S$+`a6=mce6l4quwd4Pk|S8hG-^#6P%+%M5j#7%j!p z|G+~opN)%cLo5jIcsBS&L5i%%%jRL6fNO>k(|l)2*=vWHnM4R%hB_c^89lGMLQj|O ztSJ0s`t#9&xE_-HF}U{fF!9b#nRC*WpQWKz?fBkm)8Q2DH+|_XV`rbQL%DxQzLZRN zI*mB{*~q|W+=cX+27kg;{)Bn{grq;=8h^s|{)8L+2@CuQ3;hX;{0WQw2}}G5OL+o@ zZ5&8o*v1n$Jy2!t+=HXupD@dxFyEhWoj>7Pf5LC^go&jcEn}m97E6wOz-{Hf#xH^c z$j+$f9Gd%Trt(WX{{aI@>~9VRv=@(Xm`BcWV6Mh|nvpM$&VPx{&ByOPuswlWy>sG> zGK7KY8Ug#{!0LRdGr5VZHygE$+6j{-TGyX91S<-PQ|chc*QBnNSr zoZj>Dg7nPYC&^rPXXQfs(3d9-zLwijdD|=3&bo68SK8$I0>Cc#zsq$4RzI zuFtW}Dw}D;m)y4*F4G{BL+9-|Z}$l<_Aa#VM)4Y4ll-nv5OiwEYa4H7ryEB$qgSvQ zg&i>xKMgZ+^XLzwGPpN~5oO0P@xfShG{_RN#jiQC=(zBRtMN4-G68u}MlSoi>5MtM z<)@J~vfp1L{$q7Q1zY7zotr}r)A11OvLg0S{XG{*WrG_sWc7qKN_Of;;vzrwWBiei z{D+prZ))+H|j9olf2I zA{Rs!8M^ZP3_r=cn;)X`9De_;Wei&MyMK#5^|=?)lRry8ei3(1^ex30+oo6vkk6B2 zXs#>G?uKF^(}Ndh_kYd%o{j8-j(Z^eP}e|7la*2e&-$g|BCcb6?D>&(u_R2a4Y;fP ztnkshVP?oh@hwI-;?PT5(o6*1TORTW%?a7h!)qFZX zInp|p&4f&J zJ2Ai3wEd9H>(%s>XmwVJQ`meFXvB31>^~+jFt-n2bC^kPgDu?{(l)Gd0 zv6UU;(ch5C49&?5wO+{p9~)1OyntQy&=rp7S9Qt5$=aTLdW?^@F@!5qdAGw3;d6_S z<{q+MMCD!|g}9^gPDh2cFgjhE!9m8G>B{p=4Gw4O-boGqs*Vj*=;xc#w~-%%7wVFK zWEbXNQFhy! z)mhC^)Mb*B7Zb@vw`EBP0-<3h=S`<*#pi z=-AuGt4~twXc?ok_UOY8|I+~+mOlPg835n=YySKA{_nu;{7h(5`|(TxoRB=ee;zy~ zgqz^03{S0z#5^`0CAs&HRgOTlM6M6#HZ;9RC&{qAUrEGImSq z&eTDQh0)RSaS@>P@CPJ8#XrCl*KlG?$( zz6|4EJm~SQhgs|DIKb}TVfQ~__wTd&Q|$f|c0a`KW9)u{-A}UnOYD9I@0lU_l>_9M z_rNLCot4)*D`#A6ldq92A}2hA<)`#c9s&1tuJxB;gKjfcRHIhxYjC?CW)Uw5dKo!G z74w>&Q$$@U7p$Iy_p(ZA$uOltK{RBstZP|CGL}`^}$%N`tbX6*>U46$_MAeY+ zTP!A{pWsIZLXg|<)zTwM4#?QcejAD@ntMgmfvl9<6T?HFR8R>8SxqysjEHsbhwtgWF!tK5Z~WrCU^=?0vqIio&h`1J;U`p=Q43l z<(i-PqJ4kSk4^3RO|)~LS9|_><$JpNvFX01)1H6Pe}8`Z@9DliuY6CJT_f|Qs$ow@ ziKe9YD5m}1HQz`l#Ke+js(Dq>1Me*(o5QJ5PlkAC*ZWXt?|VulnV?Ms;7gLJ_9>zv znUXu7i@p$O7kud35P8X>s^!drn3GD9KH&T|iew_N8Un1dX7+r7{g1kEjt}d%p8ej3 z@@Dt2t2IIO&_&^r8I zFq#{|Fkm>%lVHgHaK7`Nr}O)CU%HvYg~YuBqNSEpQo|6BL_ zP;ei-sTP%}@_Rh*7vHpa5&R>6;^?X_;F>iFM8Q;+AkOX<)RhzXF#`dieZTTn!ZQO zTKT*ZzD^yu0+VCEISGO5V@&jYDs+4**QX+n&qm0fM6q97mwkOULjGi06b;|#2QRI+ zU(_tKY*A-tm02vWQcLi26$!~HNrhFtN};UitBOid(+5QQYh{k1UUOHYv8vHn-zeWL zK*tDOlv?T$XkG!Vrm5siRVxX3O&7}G(lr^&1<4c|%eOTatW}Mc&~(>bjpgNhPR)a_ zqjb6GLixe5Klvk?npVhadx4p{)vj{)Kt83wOO*-*Ehpq9wP5Lr&@7m`s>p(=(HD}b z2#p0<$PSo_LC9(}8hm_gDUt9O!B9#D#V~+eNj;KUVwBe1?v|qtLwZ41@|HnM0>=AP zSrNdimU7^JH~8dE@@Fk$K#(mRQS*!dsWj_~BnwTAG6>34ie=Lf3QFEwzM?7}n}BCd z07GLV*75>4@q$c>mhvE4!CiuEDG1lq*0n`YbY0Vph9LeWOYYgRdC3xxn4s(}L(M{A z1frlwd5}|&W(tN@RLou^Qz;mVU9TSgw_{ioW}%ZULSEO3La%0+jdG}7b?a(Rk3s~6 zN(mlvk$@5MeAH4vvkaNaPZ#J|1Xw1r+5igGP>cR@ z2aLByAD#Erc~njlyNu3v8W6j94iP)Wd`HAMl*YvnRf zmFtB@AoQzdFQ6?olX^g+Wfifngu2^PFnZenC1wJKdQ_+>fk#(1h1<6{ z{yN&d?19)EY|va(a|3Fb2j4bOC0&(C1()+p%fS-fO5sAUMXxbg?dt6AD=(N6UN1x7UL~V(cZ)gA$MmXqpEEK7vtD zFWmKl!gJ~vh0Z}(efRe&B@b2y73v+BVAhNcp(qX5&{@S(W>CL9<+9qRpdd|X|76VQ zDVWL#3YGdLXnAPU33L^E%E@qe1jKO1{+K0EljotY%gW)PE^ieIZt3~!Ai&oSd$1U& zv0CbjN+CvWzWj!%77BuvH59#%707sMrsj*-9P-*GI6_X&FxM|ByX&C@dGyDnJJ|l9 zY6gU+jZ2pM+mA<{PElbJ4eQr5YQ7ZvK{N)6S*?J*o2Q)3*y&0{J4{_FmNg9E4v{0v zhpgM#r~%kSYytJw@NvBmX3sb2ih_k~+u7xKb}Zi~?JtJc7X#>%WLamKX$7}Zy zeyo1FUHuv|8PcUi>mgAl#P5KHYD1`9w)+o*cOD*^8)EGV*)bvexC9RoE4)_yC;KaK zeB#kd%__lYV!#lc-4{YDkskB!_CPu`9+$qZsZGCpNWIuVne)uW!O3+*z;xbFBt6&b z*JEz~wt=7lH{?_V#*)x0mE;0g6f7BJ25liny$9%2C{^-$N=-pC6l84$`KgtalJg5Y z6X#by=#@h2(pxWx+BJ?0VHDgBo#-SPOg7XcZ;~&JUq`-ql>!oPQy_pLddB=FvZsc) z$AV{Ljfjn!$tkoSboDbi>OB!PN52E?InaTB`+HUBYbB@xl@3RP?dCotfVh0Dk|?K* zax=gqzvvKi69P%l+>6YmiE6JL({DG*p`K_cANF{e0hg>|R?*jEkmV=g%r8PwL z>-OF*w%IGtpWlQ11@#h0A-YAHYh*odQVYbfbbGSUJ`|a>-e~>kwtHe(CQ8ByLnj?@ zmLza=n~Kt2^x+#moqpb9S9qDo3scN2lLZk3%FALStq}cmj~l3Hp@(zrq>Iv%Hfkhj zhuDk441*_xgIzWQ5cvJLt1YUm^=T)#LZ!GNfIjo`Or08rNEs9!BDk3nI zIJpN!LI$@UV6+g*1?Q_2r+{RbaZhi!7hoqb4|;`_0Qqo0U$C6&hz=kf2dmq>04Yj zDqz1W*h-@C1w^Bx>u@ImI3`DT4j6xV@yavyp=JLmJWcDY9P zjjpQO3$+cb^X;e`m}kE{$_{n|5{0-#;Bw`4oDD2%CbiZQnZabE?k1L!o&+VNqJPVr`0LhPlJ9nZO>e}arsKhVbmt|_4!E1 zncyJ=5izVFE!#6zrbX0>pM+*2P|Oz60u&tqez_Fbv&wzSyQo$Bro+qQLXxp#BG zJ_P2y2|+jGNCcwNV#1^R+qoPs%W-;_J`iq5skJ8sFs>`DFRgZW)%0N0 zH_Ox^Zf1K{rES>cd;t;|jH1BMP&+VUo-VQZl4ho+lYmPl0u9RReN zQRB*9#;TXs=(9y1|3vGwk6GlLba*`P@5``5Kd@|}U*g;U+DL|h0X{R)JjuvhPI**$ zoKsof&{!IDsmm(U4?rX4ZEUx|&RI345;b-%BtJgAvb<>!Ki>`AZ`rv`el$=TceihG zLHbdqn~sR+S8d>XW(}dOorxeapT^X>xiWmOvZg#3ainZVrF2dZ8#^sv#;L|4W#&bq z`{9M|`$4(~S!sc_`(s9p`z?A-LEAk?#wBuo$R*0OfOhEPro!w`+q|4^nV;<7-{8W+ zaow8#MD<%xKJApV8>G*n@Eu|2$AWS(Jy}&dcdE%mEn$B`e~sfh*v>UTmaT%gjI}H* zDxYM&8J@`23b3Mdk_MkD#5E6zUeG_3O$b{2$X@k#X{W_|$rm-o0(4aZJd*;Mv zH&)iq8kp`l7*2EJWVVJ$Wd+w=bZNf_`vaoL$l#}D@eR+qESSu8><>B z)3=s$+OsgY^XAny23cNO#1S za0j=})Trms=*O7SY^n0&<-v^>SJtPb?E~jkt_qnGbW%`l#hX3%9~=z+=uQa=jqO02 zNp-hlQ09J)sz=RQuwLl}VQz6(L_KOo;HKjd)YYaAt*kXmW(H+9bQlstn3j+^l()96{-}YcT>Z4Gr^3s9F>CP{eoL7yPJsLUGIURONQ1nt7a6 zRh29=by&6QVs;Nd1{M8@ie#DXF;>oq)bC;tk&H~wH$2`Qcc`(qcc<&H4?4&ZXP~Hh zGWcFRRZ(hte0Dr!%+0#_%AmN*13Y!Lm8sgG)7q;%S(R*Pi6|mJQa%w`NSC|p z?xS$m0_wP z@S370^6K*`+y1!??fj4;sL5NHpU3lBJL#I)QP0i5)HepX;b&WVWNOc{(z=Gm@H2&G z=}xbAo?~ie)Avl5rbr!JM}-@Jps>s_bxX_r%@JNOx|!iA@F1^JL6c}^=gY%lV*lBA zKNt*}B})7h-X=8FP~TW)f|J_d^K@HI-M1PljM~UJy71Xm7(Ok=8K*(1=b8n6W8!9l z4?n%Mh;1-kwRKU+ibxl_F2aFcu2G`Rh3VIEeKc-zP`wQuYiA#31Y@e8|LC4g1wBn! zk8RX^f*lG4$UMi}!#&{%#`Ksat}t~$jp;s_Dcizv@flU6Gwq~rndw?3H{fqV&8!;J zGjJ0XK@sZQWS0}BYe6$d+(P|3UQ4f%&qHcw24j{{CFA0DWl3{4Wk*k{_MwHRal1USxr^rMK)r3IrFmg$P$B!8+SR6R z!DV^{D#BmN58~DJl~!^3fsJ?yr}YOXo2I^3a6kJJnr~mGK;2?1)Gk5G5nNPYa>P8X zYPSBeFqv)xsPzmr1pi(;BJ0T{w=q%lEj_pQ&2?q1X{b#rZHCX8d{g@6&A!(BF+H9+ zr5D9goG<|yT^~gAN3NVf69*URdmzL6XU>27`Fh&DH~qG%y|QJOrdu-|`VGv>rmG=( zzF<@~E4U#&_*S}?<(EDLw}^Q)%Vev+0Wez--QOA4Qt1d~YRm0{T27iz!Asf}*2#;y z&X#jmOEh!kYdzlqH;)P%lFioNbWYF8;q|D-n(}0Qm0M2-uQu=-t{*oxYi_vJ=?5ZvkBuU|*$h+GlbnD39@i0_BjSE#MS z2HFLmxKP`m^EYoDwCASjS?c=qoQRtaDUX~EsjV^VFJ-%wo-Yjol70}I=^k^*4t;M- zrkyCSb$twGNF^Jh+cm!)V8iajxHjpgx8(Pf?>6)6=G8aC>&Eog-Cpi-x0iu^?(G|) z9`2D~mDv%i-gMz>Tro=p8EfAowPr2&K|c!~>`X^6D5=6@9jEVfNc;zOYZu z6QKl$otXP4Iis|(Ds#V3I?8HmW>n7f&wLYRYI$bh1oJDQ=ge;LihWS;5>!?@v&I&c z9^ysO$mjfJwZU*>psOExM|^H3z$#4Ne|plaaI9~vDJ%7(SD%0Uz2TGML8F&4n!?6M zN6*KSy@_>t(SYPF=`}_p4BbzecyuoBXmZT2CCPHDNZi2MbUd=ny_6&CH`gz!D4m;; zlWrGS&tbKV@l;*1%)Fmv9!JD$k_~2~6E~wZqtrZ7$_i8r%I?@TN~d41@1AR$x+H?Y zNXT+Ykva>LWkF?QT>G!Nuk35)u_ESA3hd(eTK5>b=Vth_zt$kkW*Qw2Li=WL}dvpuS0v|JNWannSA5o5t zKfe-WV8~32TmF}I6}O;^?M4qBX6utoWBxxiK5C@#QFUoq>WK7nR*uW)!3FkBg@}7A zR4#0JPd2!R?Y01zZ>HZwGA}Fz-3+&E(oU_oa8=aSnA*E%v;OfAljiDVd1Yzb?hiF~ zbTC#gb#wS46fJ&lM9Ii_){N3w&A%qYH9Uy>gqatM&Cjb!k&&bz`;bFa+h!=#3ZFj&_wuFxu@HJsvDEd4lhz zzhkm6v%pJx{?-%>KFiYmMYJ_-|KxFb&|gTe5KAvCbIn)!J)r3Ejn|tND%-PBcHNpA z&WPt2-2;MI$(qz4u`UYjY`vLst4=1|WqO|$)=^}qXsc_3rnq~&&c3s0?+2^gE|yC+ zM9s%w9Y8R)4dPL4+I-ua!*(pZoHXpujH|6T>&3lOXbM@XqaS3aUq}m;bE~sg&>mS~ z=4qJyBhys%z)d=#WQdtUuQy$o^sdJnut z&nr!^DReb}yID;^wiG?=g7q5vu2VYFZc%9F9U$A)iC9->>MhJpmDN^HcTHR8GR*y^ zFd;j(Br{&JCxQhXZ0xIG=8H|Ni~v*5xVy}3#9>EP&E}n2PQPL3;qKG1qoe96lkd3a z%wilfpNUtyG72e5u8J@z>e|z!wM%_^&j<59xeaPiSDUS3>MPBFH|RiD zRM1$}$5TOU%KRWN+Lvoo?7OM%g}d6iq?_#R*)}R)Md1FUY>gf_nfF{8G3Re-ZKQjc zwL&(4fzX+*sdvYDS*Lc76Wfy8$MTsauSV>_EzbJ}F|PL+R9RDQwi*fK7K|O86AV^@ zU%BzY7&-w-E!Qtq<8-5Y&T&s)nd?x?vB?0 zg4VlhvwC4nx}RyQpk%r1sCG=x5@+g)Ad~H*sfhmgnA%VWz|FjKEn}9CS>dSWdiLyT zFU^y?q<#OOI;uV0pia{l_DX{Wztr|>%{`pyNr!qS2uc?9SMx&cr}?B5X4K---#O>v`jt1a=HXDt!?F`1V>dinjsd!_f$PMD5a z^m^prS7x&`M2kL}CZJ$c;T<)&|6KB#k}tqg)&+Wa{uSyLVi{cT~j zE$|?;(#n1SL6@_#+T?@V*DJl-m!DRysw(g5#t?QLkEt54F;I0x`-%0(73TRa?HhJ{ zK+_l>T{%Q$if0`Z^!dBWd7vTG2!+N!_?D@i+?U6XJvdIILM4Ay2ed~W(S>i z`!m~iVvS7D?J93HTV>S*qo|-(M61x)5Hz}GbT9&$W!f40Jk{2SLDf}0x3oU${r-)M zLpndJtv_UH)`5c%ik8b?XrFl64=k$QhaS5li+MQGgP(B5=LBO3^Dw_xt$#POvBth_ zl6kvId5#kV)ATONiN3O>b?&rZfqfGpz3Gkm+VKXTi$Jm5zDL!I?f3QXarqO*mCg21 z%JMC>jh8D>&bFbp);<$DIJkWdit}Sp5v_QA<;)7V$4;|$PxyD)VjC#y3d1u~xnQA1 zP)@7e8tqW}Jx?aQ-Tecd^xfs(dld6T^`V}inXtfYa=C!u4J|mQ(jnfs8 zpQ;|YADHu{wr6IPB~CSIwr_~57r4>n9VdI(=LdGzNsRySqGa5^t}F9*LQPp|b#0?r zlxAP1On0@^Zj`pJFBlXya2qOR< zGd%#X+YN&nGQHd8&vCH7i(Ag%3ZtJwkFxKP^h;Cm)F(a8i_{Zz`x8O+X7=JYFY45n z)@`u;7Vim$8JaIp3-^z!lBG52IJm(3m(yB$em~swx~wBoYG+e|`Z%5{uX9^f+LDBn zSqn4Jm+xgq#Vy0nq1cDs@A1Vg=|^5IzZV@MbM`#X7Jh#&L+*C;C^gHX%+k7a3AD>k zX4Zz4;Qr4I>A-sDG+|IYgMO@iDZj4P4r<*PHZ$G~tur+{88=ha^Z%Ikwcy{W72N9; zwX@Yclx_m=5<8{X$5v)>>%%!n&7HZEILG zalCzi7Jh=h(ft~>8*gqh_b|28ZpL1V3ChYDcJ9<34P-tI3U8(BizPGV-#w)=Gtt_* zeb!-0YNp5Uw+~J4^}L~Rp!vG%3!$2Xhoi=)xHNN$fxN$o!ZW*}NK(F{_W#Owa|}Hf+t_jEpIQI9FQ!*vi%B+D4)BOB zx`q}zh-l-6KYP5a#`WKr2TAWVFdcg!3@sw)n5}1FIN%WsX&icn`J6Pi>mh#rj@s^L0^7Qv;CO; zdvPIc_C>(Cy~5Pd>GFryW{J4P4=_&)@zt(wppibVq#{Up(ysUEp4mp=e`_Cj8$VNx z*q~s|w#`QuAY(Jj4#@|(fliC#%S=Yp&Y0o$w+coK;rl8t6z}w8y7}tR@$TD+aYcg* z6QjlsOOzB9j2}DB-PcvMGtDk5e&5%PDi7m}O421&=6qDSRMQhUH(ew1gts!;ES^QQ z)WF5vtY%Ny9UD?z7#-z)Um^XrhZgExl zf0Z6e%lP5rib{r$9aUJ8Nm5JcK^~>Q)l!l+B0X+ZOjN!9AEsyG;87EbND@FU?a2!Yhv~cVOmq6YDP=yYzP8c59aEl| z5xDDdkmWNQeEQ9W#R(#s4*GWJ7_7|xY~eSRmFG48osNRin$r4tk%?FLt#<21DUxND zWCQn6W6cJ>Dc>*6jE8NpwyS#aJ$*hE>7hYJX2rBy7g-xV@n*<`pzmplO=*47?njYy zJu`E-Sek2ky;)uzxeo5%^=B%f+NSj6ShyIJSJnr$2KJ?i9zRYPHOd_bkbbaNno9W* zk^a5VSIjz|nYeN6GK`k`FFw}-*=7ga%v}@x+|9)!J)PYn?(di8sU6hfIXfFSzNG!z z%=+4D({tsy0(pvJ^gImSvvylv_V7t|55dv}w59hN(~}%jsq~<^BIlqZEpNxng?Vlm zRQG<4#!84PXMff>*58W>m(WD!F4gBtBEO#*ooG%p?x`X$rD8;yEs@ zU-}=_W8Z&h!u=NU`MPDZdqwvX8jAN*Ypof8_@$#JUee- zp935&5I!Z!wopM9Cvgm9(6KV--PvA}-*;BTDcz_IOEwIjTTohuss5}=yOgfSLB10{ z$Sid%tujOMBg|IMLHpBSMxI5+y?f~*og8e>N9%M;$I052fC$noAsf-sJ2w@t7~gA z<(|hi)iY)e88NnGV7yzm31dc#E*@1hIvA}L6?W@pvd-0hE$>f|&Tp*san8zS*nKS< zl1-+DcMA_PuNJfvcRT9Kyr!CJNIz%)-#9m9L-qN;Tkihs{H<>&OV~O@X~##;m|0L; zU02#L-n@lTU+Q+t9B5`B%u5YHzt8-ts5k$gJIlWFP+mIEe$-H5e$6ux2S(hYtpYWm8D-x7x#-zhM5axXH6Ji(6#w^ewba~;hgz{#|;~H#0b^@{5}6(uCc93me$4RB}?l~$l_T+ zu!8YdV^=dd5!?diJ;Fw&Qh9=66xUU1)tkTv^$ zUG3ateGl_iGqz~#h!-4Mm}eN=XkSUf7pu)kE@F?(sQ2=05%71|!Sa3`jlFYi*U|FF zhZT)Ci|C@uVT652OZMUP`uD*@3I31zFW46=`srnOVbOopuC!F2MeNhn!V|_Gk^)f9g8A4cD`JduJ|F3G5(kUOsKUKT5jYs|h@qS9gw1*4OqhhlUzG6UUEC1jQpU zbnqB=oJ+HMedE4wwjoHkxAp#`?-x%Rm;U;H^8I1OBgQ6*M~q1f88u?e$f)*a<9G&- z`tNiMnQ(ZbVAQz(`1=LL6ViDxq2xbLNAd8({;PBhFDy(9E*S4P{>|?P)l*{hh=Orr zixVRX|HJa6e?O?!6Eo{7gSxiTw4yU=McR!^mL)6aWO|D6 zirSPJvY1C$QS%$k?9CwP-?8`nRrZ~vX7#-m+Z}MFqJ_LyB6LK*n7nND;dq}X{ z3l9SmL6>}xdfrCn`2$Bvo(CKXjk3PdOn;fUm{C@JZB=}5@rV}3vo=4?Q7t8hjTvkA z$O#xmCCdvM>Z?LWb+q*T)V!M7L}^7?Wy1JR1Ro__Ur-+Q5&WpOiRts~{9{zUZ>&Gh z5#d+#%TgPPn7&?YV58>k^2vM)QCjaNA_UTrpgB8T+@j8n9{nss(Fd}r0c<% zg(=-zn4fk>)23VpERF-c=a|~{K=ZElL3T%@Bg~&uBget+`(_KOpkeW~i=E0nrgQ2z zt~es*hjDN9aN8ysCvx0W=-zL&hswLh3)n2rzWriHN^Z;bE!N1WgdrAv!l^1-6HX^SojU$*rga&$*#*W8x8I$x|8*|LDj-zOu*tE{6F7_Rn zDz}E#tgOf^Ug%L>=BCD7AAO_i+yCf2a+^*6PvE; zVVflT%7}SUH;`vf!wUW~1JzPL@~JDWsVp;ZZyYvuLgsbyX73q#zHWA8(@ov)A#E3o z@1@o7u;7>R#)P2l|AR7Dp@nLp(0AZUFl#ptZl3_PBYtLMwg2c zyv~u)mv%`yeNSzl=Jhy^^>nlGhQ)T9?VbkF`?UTam%o_YNtmPP8yaoPk!tpSbPMU~ z)tIX9Wt!z)(<^K2ABj5q=)liFc)P%FVQE8Yub>>|H<;(JDOajy)(3S(BB%kY^n7f7 z-kMo+7B`w9Il8{vm^g2^-)*0ojvne?fpANZYI>M4YJ5gbqNY~m`ESnO{Qtsye?icG z*n8V1BcpE4F{(G7xZVebpiAo#CT4Ij_r)(YWaB-e?90r zIMRs2oc_1&PrHv4G_|yE)W195Ij4B^1k+(iPXf5Nq|;;d9`P|_$GVdY|I~8j=k@LM zjjP4uSoCLhgswN+CflWd7|r_6Qk64n>{7t4b}~FwR$5;kwVpKd{wt;v(kU!W1=k*%Px zou0`TIz8RzJNwVnJ3(9N&OdUR56+we$o8)PJ+riay4|o6Pj8HBBz1anhN*vycN_Su zj%GvFUUC0sg4_*T=pRSB$ zUd@``P`I|vls)Sb<+}dgY;U!7Y5utjHd8kR*#t~%)4sv}_PEUE`OW7|{_OXM{+;u; zwRD&rmA}oO$J>%) zPvWy1-KU?%+m$IM(TU(233L8paS`t~)$+J$30ZcF$PT?NyGB}=Q!$^bNd zdpOho`+v@7bIh3{Bq1bci;_x_gb)j5m2)Gf9h`+qz;I&0>gbLa974$r;P{Q0LVbMS8IbxZQMqWZUC_4y@{H(+aXg8a`{#GJqn z?n|bv0;fMj*rl-vVlOvZuuFXiY^TGQ->s$!$GE!wcV{D#ZrGI;2&$+XE5>#=+16fA zI-yVfwOnOgxZ5I6yIxmp-}uRg^iQ*KH);)jp5%S}i;~MV!ha`R3>M!Wj=intcIE!J z*L6=$n3k5luA9|XHuV{~Ozh5gY`#V{xnWILmA4TZeB3-L9tzRMR$aer_Jwoya>#B~ z@pO^NDZ|w}mVzOa;^{IIZ~KtY5%t(Z7X+Nj?-Q>Js11`_S4ESa|M|ohL`9$dyLvOl z=4i#}+C~&_4ZSMg%GuNokDGxCQ?}w{c_CVbs(I8y;h)#F+dtRt?B?zJaV4k5e;j&y zo8E_6kwE2+de0eO$3Ae=nEkaNo~bKvf1g6I6M_AjVay)Ct9iY^Xf#jx_U)%y*6B|n zecWU~?qdxVLsd)T;L|Fjeq$BR+FIgSW9wy; zbq0SptJ%Q&koTj5eW{6!dlf}x<{0+aXpWST*k&r3=tEfOL&fMO_CWqUVq2Y=09Gmc ze7BwLFi;7PfS%ncbA7WiBK*j-dCSXn_v7@s3B#{_Wt7~a`Pq!qv{aK2WQTfrG|SvF zY0!z;m9L?(9|%Epzj~Dz_3E?tPlTD_(e~!@O6x>>NQgXd_t(~9X6Cbvret63l?AyN zfM3}9<=XJx>%QwRUIMhttS(pj_9I(=Dehri2lPLiOTa>c7o*1Smrhp72}LSGYmWF9 zX#ZMzE|xR)Cr6ICa47@O5_{`>w8Ss3LSakIk+hj#Mnx7T*Sw3oUv(F3ZO+)noP*qZ zH}duB-P)W@oA8shAN5wR{_sk!t#&N9akWTtrYYugt@W$gu=ItS)K62y{BXL(FxW(76$dp~bp`h@cxEYC>Nb|OBzlZI`>mp z166EWJX~Ts2=8ORDN5gYo>J_qSA6>TJ-N{7;Qg>WnEVs2x^**pb|?eQ*e^Gb4G}-= zRoJ4wh|`S@A0pJkI5Ma1Ym_6-FFNaov(=z7+Xz86u0FVwGc_N5)Wm4;_?(oAeLwl& zDpI=Gho@;NoJT^;Bf9l!Ni@|;+Xt)TTlVKHb~iN4CtX87=$jXAklM}TeQIZKy!vIA zzE<*9RQbsF8zqli17z;VzIgZ~_`X|>o!7zI>4lZEKOaB;@?iQz?X+%J+e~Z zQ?EE`)o}Bg$NoLWA`N#T#3d1}D>RUf5_z=t^fe#&ruPYH6IHu=Eb2$GGa;plA4kYi ziWa8b8y=7GXGd>&T-zup*?A~sWI^gaQa1AC#A;nLut{X#$v4&er}VqP1kG1c_V-&L z5P56soNltFwSXM#zI>0!;M=saTD?N`lMM;iM(8ZR4}iZva%c7(m$3lIw(y&MGw!FF z?wUTf1XJqkTG6b@s+E-Hb5E;}xD;)$Po?C!Z+{FX--Xw|`_vMft&;uomAT=t@b2bx z7ubzUW-sg3=8X>g6s&9*;$Y!^Y@Ej;n5|b<3d-l;%-V9_NA-L~VrFexY3>tU7s5A? zHFN@J`UiU-;rki6XU;|MvGRc&D?T)r0odc_GcLGaViAyB<~Emv3=$F&SoR$ly0ofF zA+)&T$lN>@=r{M)OYptGxD(NmaLXTE1Vs+2bSCQ-uEgT8eVwJZcOkw0c>eB5iKygK z{puYsu4?j55su#+@NH`7_MF=Mls*aAp z2i_4pD0rQ(P+q)wuzg+K)#l33)8!3!Q}z$NvcD?z>UPVim0t@-R^K}>mmN#+7b5ue zwRuoC6rkA9;&reEiC`DHU-~{IFJ?nAN&;%o*w#;}NJU{jf#(2>V>hC*2qFhS>FYgP zUCQm014$e+;)bAuNP>ET5>X;mNdPFy*uW_9Qv_I1f%;TID#@t#Zi79Ql!DscnjQ?G z3oNu2ws2)=wu|)M_m`fV?R5#j>6z>#g~Ck?_M;P2hS7(~{|NQ3TV6w)${uqYmmfo2 z4)MiIZeF-cZlvO46iAWG|O!6dcG)IvF2}rD6L4lR=5h< z^U!KA9)fqMz-bJOl^nT5h4MtGC0Q}~bRn21e=26p=u96)yj#`oogg=+38+T% z*LKK*sh_o@oK=U~cZk4&;&bb>5@?vi3Nx1vi0X@a3oGV&G6D=)tusHSwFH>UDU{wf zEg&6oav$8DT$ZBL2mjQBJizRf4&szFfpp1gL0nz3J0JWQ87W7@55Q@WK^*K&w9^z? zn2E|@*ENCk$o^3)WblS&D*<8-MqitvXS4l+fP4vZD#`ZLW5fvBS({WOA4@%z$qa5s zrED!z@+{g>Y}n%ZD~&7BEZ8EYC@x~49Swpy(*7iV4drPK;~)3XlFXT;mK2~cy9iv75+tNm~XrNb%s+5A@?-pgi zV&Z!g;B5A%TSeDbvDie_zdxhdEqB9_>?%NeK3Ibcv#X2Rr0!v!bx*~Vb?wlU*6aba zyf$gpi$JBm zmjPJ8RLL``8@W3HB22}u?8HsMN&wV>DpF;h+!d{^*+!dvH47l162uZ(F$Cwil{45z z44x0EN4-2_#Rl#~FT3?uXW zbuqGjt7CF5bn8QCKPO~LOQM^Pv7;Vuugb6{eig|#Y0C>j=#ydHT7n#r=-9eo6aJ_I zwIQHDuYEKjYELBrOcXjFRc53S_>9y@$zn%h;@3ACVIAKD0#o=hP&g3*gm{9$UsGg$ zm<`qm=-E1GC8VJXjQqEkaL8uPOlv!p32orReS8oEHKy7SdrN#pp+Q~I&=>q5@i~09 z2_J}Wjy{V&01}wXckMl`e$I)Mis4Ru|HFh5QU=dLJF{a5s7*Sek^qL$#&e_mz&ZOX1NjnV89p(KVx_KLv0XRM|e|-A1w)= ztp=`* z$Kd@j9JeX=Fby|+EoM8lwjCQN&^v^SIzXpW%s%RvrsA{|hVV`}wL3DMe1uzSJ0Z`| z%c+!BshJp16fp}oGqm+lb-6L0w+%FvXYA6{GpUGUR09m@Q5@bi1%H4bVYxqvAqj8= z8I2FI(-;Ksk0z`4~jTQF|bryLB_bj=Dz*}KxI?^JGEf$Al&0A3~rGM9)GsEe~zeh0HMWb zJPNW5U;p+q_y#kGD$vADEbY=1gDO&;VwC|YWAqf{iTMEL5<`k=o5I{HFlvJ&SUdk?-X(zrTAWGYv;4}HOQBqT-avtg^NEf(!WrQgYp zkrJ;$`DC{au%Bf8$hQRZ)NJVUbTkxdI|4YJkHX;&N4E2Dl8)*EcR5Vbefsfp!Y=BVl1tiI2d~ z;9yWPwDeTM5$abAMJ~aJ`UeBENBpBHqeIk5%RHkBCiZG{+)FMpSziuf&IW-*l7Vhe zVOle+pBCkagN&y~!pQMNG#@DYU(sQ4EpBoqOHe8|*u*24d$yw?cl3|Q4=$1E%VP^U0%NjsjtDedVeH$1j zV@#U%9+6<~ZijEvrI+D>cMeA*2wvpX1WggZ>yTi5ey*fd7Q1=)!PyQuJJ*}&^@+_H zJQ8pK2eb+2S|z+l!{XLC@_WyX{?QGoj|AN<5rmD5y{GM6v{5f)MLBHQ^gMtXH38g{ zZAXFSnh5Ih0=`7x!36h94V5A+CnCajAwY=_9j3n{{}gR_#rVZQ?=JME5)CB)ROMGo zMdZYeDy_|ggTdV03!9yMw2B8qR-!bx`ZEC2>{2*In0bE+=TZ)9dm~1}E@r7ovuY|P z+ztoyf?(!kWJ-?~*8y$5g2hmV7nw~66pdo~q`OPQ)L! z<3mpl!r0a;_OJUE2uddDb}P^9alWKU?3 zf;6t6gHBIRpvqQ>tb-D03*weWJ(O6-4?4WEjY_RNrIfX6N8YH`w+8_1U1QQCH`N+7X?TLny@9Kfq>=V z?XIp4D}0U>D!oSwkYry*e!>uVitEeE2Vk-IY>mbk{0E0Q`F0c_etNzzTXFU1E4qk4 z@7u5}JnJ`QGvNbfnRMYf1}n~zBtit?YSedv92+WDh+|I03H4$%r3pbX%39*k6pUf2 zyF9~*SSP`9AjXTbjEE>c`nD@!BX!HfY>vKdNs!;`0vFc}R6ZdUhRs`Owhiw0!&S+! zJrzFYXd?sX^(s zrO5XFe02VYs2Kb|hrd#D1Q!YVeO@hK+Wlx=vLehTGmaBs@^P8jwcht|z!ifJs=*g! zTM*F_EY8+c5|L+}KL2I!_ESzJhrmx0H|P)S{5-#3kIm1FfHTfJA&(l)5x(Ew)Rntm$4S!5I!50k8b zJLpT#eX^Y$3{+SjgbTZqZ0C2oFqSzX&_(k>AnIXAd1mJ2PmFd~^*{1(Sn@NtaWs4i z6(yn+pghE8*r*8vTlbFf5;qdYYQ>Tl(zyJqa|Z$UVN8F19^r3@ZqBxOm(xVwLh^B5 z5kZo6J@5mH3s54@BAyYgB^b8@!R}Okv>HR42v?@6Q=yk`*4jLT9q4xZpVvQ5t)Mw3 zi_Dqa7!$5UYS3)O8M)*WxJ$%!LAV?>!L699N|X?S1EN8E2`ma`J%tIg0sezS2H;#O ze7ip(`^hTu5W=)4?|%DbvOFl7I@wY?jAFoek!(O+6nc_snWFVwc02b=JjhLtAEZlN z!}y5W39$@Pk^Jb2&3HV#^DpbkQQ&#XHDa4~58UCe-rR}dK8SDvt9!DG=qs)%2?{|D z@NyVtl3A&V)Q7oa zL_J5nA*{)TE{0QoOK2h~)4@4R3u591>VJMeeslfbA7lW7**q1}1l(|pe>`hJ3u3zavb3)lk_)%()5h80)zsoWju|e`b zcYwZL#M)S#%`^J^PS7)mm+!`w1wY2H*(>WmCsS|-lN$Lq@t*r}cUHg!vDbK$8m_4K zC#VS#y!+aGs1*uOQs|U@#fbU0%ONcuLBtqma*11s=^<`6cq5&2;N@$4TRKV6?qQ|y z+zy~7VJ7wgEnZup1=bsX3ie~;JMIq~8h{%ci&BTfm{teuM5|9(mI2K`an^eD83q)IMoyxI_6M|T5udIscAV=gN&%`-92uk) zKq|s?2volrLSb4F`E*_w48pH4{NrDZTA3n;dhLyT$YF}C zvqI>reNkT2LUE4jk~}uM7fE{)%+>hrW%(_DE5SGzpwYXe9X~I>ML>m}bgyhfd7pVK_m3wb8|qWR^*~OjXEBBIY%|?wv8+hKs_v!c6FY z2rl$qS)_2(0%3LBXeJ6D*-kmJl^^LFe%i8*>-i{sOc-~5in+%tqsqmY5!B$3pBVS6 ztiYGVwsf@g_D4e}-F-d256BV&;4>%<3~6 z*vlK8F582O-Pvh?tJIp!Rlv=(L6nXSKO_87J@c~p+Y~KGb{9v2DzC_Ky$QVVo6-?#GNT=Z?iIvUG&F-hJFxM1R_&p*Byd zy+XIY`{3mr0RT@|3=%H5&ry^`BhuP6g;@53llcgDkAyKF>TF+&sDus6CfB7J;h-vW zJnC_e@SM+D<+eE$O2R9qfVTss3F>SvK8Gtg9W*?zxKti@ z+hMnbg9*~~E-e>IfyRcVYaax&j8xkv#faRtML(u@hF$W<4jI@LHgOdNP|poJQiE2Q+ecXP6i#7z z+`;-`T>>XTl-GYN_{Ai5x#MBF1wV0;W& zS}FQk%Pzn`e-XPUVu}cK_>1-ZFCcHC z#hqBt&@MX?J@)uRWf8P*;vJtA zjg2v^-nJaEbP$HVS)%(+fig1HxCb~qTQnrIp}E|iILaMnMRFHsKz#5Wzd(Ltk13_u z*D8RmP^m4X^@`|Xz_1fSpYAhR-}ufvT&YAqZNuSb$L!Eq$w4LD~#X7!5+!5%=HrHJ3$J{=>6GZ<^{UvbhYw??E}5&BkA3=yBJyNg=3=6+)5`e zc_8O5X`5wt6>t2Ocl;_gV)*VJctuY&z5KmIu#X>-caI|PF7~+y4u0&yOLFx`vGw-X z$5o&bE|et!#I?qPat-Jv?%<=7UmW!^+$F?}&3(imcA2xMtupdUGE_sSo<9Jmlw1g-c}Ucdu`C= z4k@vA2yvpjwS=6K3+1lwU$2=KS!4Wrqq|@u_}aAyI5Ft|iVqP&d@0YhHlDBR`Lylc z{pnvb^MTgFI|3s85csF%5=$X!jwMg8fIkyycR=1+P_$}UclKsGMtkk6^53u_A)(8$$)`MO!iO&T zD~**b6q}JA<4=0K1DvdD9ZD`K*MI0XILMOz3z%Ik-MMUnTy(IseOHEKH~!7~`6-I; z4WVp)^CIB~8ug}+oRt`Kxr3cdj}qP;eLNa-Yvr_Ma@~N-mDk_oz4HN4_ag5G^hdsn zcoKB}YwZJ8&ij?{oRQI>{2w_bp3ujiY-_&!WZs2fWizzD02874Q39oEWg$cB@}coz zkc$UP&p=MNCz^S^XtK<-cbK=lw^A#4?_#N9gfZzzh}5p5;+2W1D}lCcLy1FtGdZDm zO%scIV;!5Gy(tcR0wb?q|ACNJyT z*)y4=3;*Mku5H^vHFx}Kq|$^3c4v{PTypz~*2R;h z!Y!SqRQbVS%f(N6ww&3Hb1xf+~-}jG>5EA-&ZWNTtX3V6} zL|>kTIrs3p(7)Yhl2$%P4}Od&SXWzDy($KIbWZNo#KD-^H1+(-L|7C#K5>%y|@)6}GO)$|{@K#!yWt0)J& zP$qYOS$@25`*|Y*6yNCmw9rM!5?0guwQcwN{gnENfB!x}TFM*~^{Q!+mWoNf8zZHd zxWp>~Go^>76>h~6g-U*_sSuw3C&b=+8T?zG1bkmy#xXBE?55RPc<#H1#j9u5eMb!= z+!1BzmHh-Wu+6K($xmG3K6HOLIdKAIy!OtK+iZ<^*ZI+){>~G({iLQu)95oF>;K!$ z`T6r#3B=<2Xu#_rxA+F4A+gNE+C0c@OtN5S_^F`ROY^)GXvEXIEV7F3SL+XVHwek6 zhw6t?C+$8 zyRS0y4{ftz?RopY*`kP#X>TR=%=;4;9=M^qiy4h-=Wo@=?0aR+ZanXjofG&M{BQVB zRC%TNfYp_&Yz+4FydNPCU;&dTMX4-(N*sYx;Y@%2^mWbR4z48t3 z7;r@?%xy+eY~IehBlNzw!wL8ebNf(cZ?wY8PCaYO0%GXtqy`y9P3vM!nMWui z+j-*>V8D&D8$VDe@-6y09%ynf7CUO^d_pg#=lX2oMIouv`vQ{@B`Q0I(q6Q*I(%Wy zbS5^MNp%um+sedx2~1u~x9-Bj?hRiuoB#CoD5@b&BehCcTzgr%`X3f86w*;*(o0t>8=Ccnj~61`mh+W*s?S3P$A@2 zs}bmObFI0z7{0D?jaL7JTvGc#nFx-k|MWbSm$qPe#?RZ&^Im7p>+g|Uwy=@8$JRX- z`yuA1$AP1H7oD~3+aB)xK2>o0uVku4ix}j$1@lJI+Whf*j`%B3vDdIm7Phq?zFzy% zdn>&C!^mClf;(PM>O($XcxcQt*Eqb_EavvZM;mN#e}89Vwoc^-8Z=Vr1djAfep#i# zn{B26x#MsYqHp@mq|BN>$hYX;C8Aw_=uqPKDRob)dE}3Wo{FRDnap9hpVHh-N7Tp0 z&!}TxH;_dI7yNw#Li*KTD@%NT-XYUqrG8aYam{#?e5`74;*%rgl%L8a?d(cx*uD^3 zYAbUms9=fw^%35BWh*ycKWMU1u=>2k@JaXI{_ZLjRUc#t=aF{|q}xZ@PwF1AnO?9m z_m!c&C|fpHu1m^#9+E4S^6&S~P>Izy6Xo$Em-KBy>rDQteIuXvGWvAyT{LqV*w$7a zC{e|6%x-;M-9MtF_sx~`s?>L9O(Ra`)yKbOc=f-e8K`_(Nt|O(q#+QGa4q67(_Hkw zz5T0kB8K(l?1g8xPsh}s`zXAuId;_JYm#k%+^J*g9%kPw3-M`>f%lt)3jROHHbz9T z^_F$Q583)JfU3_ zdTaZH;)Sb`xo3$O$JndZ&J@ydcc(tonj#W=U#--b6Fid{DAF z(c$T(KJVW?AM~EjfG;N9`Z|5kzI$YC5^H%q_^8J2{7BQ3mXm+PlkCVov*6h7n3}Z8 zj^t3!02K*NiKBO7ZAq{hVC|C5+;yb^-;cju`#O?Cv;s>D{!Sw9*#GA+9r+KJG2swK z#SWgUS^ElsMAW-HQURU(<_*-X&AxQ>EA)i9Z$SepR-o>tRe;)F;gYNel`02m0{_t0 zxi3+36O!@w_o9%_Ns1%?a}R={v9ia1M>T5@C$0Y0_NCUH?PJ8${?0C7?%X|CBHQ5@ z@$-`RxE8WN^6eRjYp8>UeZt&ejYq8)3gj6Q8!~7~iv7Nkn9dwJM#AEniY#NTE2QHl$XEn3iWo#rx0iBo{8g7~ho4 zlZl-qQP9Mt-uK6>JY=uOn%q78;AzOp$nw5kms{VQ|391i_iY)WXn6C@;^*~|C*99) z$bO=AIG^%KQqt|K8io-#jU68g)%0W8k>o`5(CXV*QzC>k8!gWv0ejNn+A!dd|~t`_qoCTg~CA z@!NN-lRlr-Gp|NgI=cge%ipLbw~al#Zu%N|fYPPD`pyC*_mt|Io5s|s_kOz`uK&Kb zx;3}*ewLHsF$F&@gC&(z-c7d&RvM=>ZMNa357zN?JM>&Wuiu&W)~h- zw=Z9)o4ET+ZmQ(MZ8u$SP|?wMCYQZlMnQi6_g!Vz-Ndude2Z-N-+X}TFT2`;Et4oa}q>s{i#9E$5dw<^0<# zUoUaTj{I`l%wC*24l$Y0&lSTbm4ds8((QZ`GQVZ}2$mRLy$ zpw#)eqoRjzRJp~qlfOp9m!=f9ia%st#QfZJd>L_Hd+GMC&Z(+B{z&g^V&g?0*PoBQ zQen{pWoeW$)%Qk@SE;e*lTRoM>fG=9uLn6tJk*{(xd&dK&f4GqkeehOGUHQ)v5796 z-}&%wZq4!eoYB#c(aSH?{!SIPuHY2-PoeapuZ3wotu=OecCtTWFPdKYUO7DM`ZQ6b zY|&BoqU6tw4>H%YThhWsZ@iRipN)XL&maJ+<=#bEcBdKC+oqu}^MGx`)nfBx?GHGOY?g)O6~6ozV@x>z>{LV1wbe>4F`vj>kEgRE-$vnj0EjUM_2Gat*!e zp^*~15%xA<_FkrzqvyoSIi;NKisReIkLe*Ti?6O~y}i$;9q5~gWnEoX_*C=^ckH`S za0{o@FQA0;qJtFvxb*Hs#QW-o!%c**3i#L!wWNnd=U-BcnS*-DZv`Fm8;?TaouUS= zF130|_0VbToyBhhJHYP}ka63O?B%MDf-&`9rH&O{^1HO(@tHQ7Vj_3DkDGp_xK8KO zpKIWAJ~!@xZ8D{AR_WXxz8_EvvQ`Ovq@E{(`t)37e(v1^_8W}*_e=1PpUEA@f`})fg&c4`*KNz@%iR)@TRCxopqtSfr{saDJ%Rk5Um}l>bUkr{8 z8#xi?@@H5nVFCFoedc)2s{QKhv|h(sJr8WBv+5}6wKPDO9QtU@39M9~m6@%xQVN)D zd07n^j~|U4B2E7p_b_Y^a1K3aP; z(QcbrN?L7Am}3Wjj=nrPe8FM=sCF&2@lySynyT8bq0kP~E75?HGb=`4j)Ckv6K1i- zVt2nB7yeXneRix^^+nMErwgIg4PmwBkMmwgdM*kERD>2LC15n>lb?ACIJ8xtQWlS1 zkLvAzZ##e2gEy<>4|cv<*tq7wdp9rL^jzKXs~a_0gh;EW7jf6h0*fe(#U3}Qq)SZ6 zzLAf0IN1|X_bU`w6g+UwU2G92%=HJTW2L9*W%+f>qlRC5a}r7g^Rf9lb{81F86??F z`dw2-Z-&-c#(IXyAr>VgKcb=!Ey2lNZv9SrT>>ij0zbC6LXe{_TxOj3far|Vb6EL# znY+M13*wrIYuy(R{A={&7w3e^EmeXb9gR;miemV)Sb=hu( zpnSvRAmd_qc(mp6Lgv4n`W zQH6_bmu3FFYD-fxWHh`tW6dF~T$&N(M1XywY<%}PMK zo@{mw|5CBf|M=t;;@_7_Caz8y%?*iM$ta2@%+Z_Jg0Yj|KtNX`ZcOb?XOSzAGnNb1X6-P&Yl6;|FvgV_pOv zrCYw-Qcl(GCmboq=7cHOgRXRrXokUorIfQtbjKvFbGyn?19m71Ap^|!w+&Z&uiqO{ zj5cH>%Z?@S#&@H@GK=Tj5vvAA(0V=7=P7skeZd_~1TESp-cum8K`Ww6yD6NK4Ip!D zQq0opC-gr`OAZP3k|fth&|u*u>|LwDIhf>Nt+!ak%AyQ*!W7z#!RxpM^eqqLvM+Mr zje}hMMY)n3uV!>xKzTMk4R)6I}uV;U{7#CiC5ZRks;{J zv6#Zli!f~lK80)8Ke|u}2k#RUDg$OSw^YOL;9ZFM%XXRaq9#Y!1bK%ns!=O$)%WZ! zG<&0Vqf0h&TbcRxkL*GrnQ3UZtl0gCnwWu?3v^`UWaR6y>@pFiivsPixx?j+Wzkg1 zl~lAOE3!W?2Ry4`zID=5Vp|rsDZT*4O5y~UIv!JpMWfJ=EG&70LQ4&i`- z{g+|w2h_-aHp&-CNl{hAHU7%#G_cC4Mzsre*)r}r(`EnAGW22JTU={WUNAyw8sSWv zrO0Vy(=s6HG`+c1P^MMvjINFJ#!M_u9-)X~NGC zCsWYh9c-kdWXEC{`ipwfm#wg*ZQ4W(!<)+ZN9`hR{Rt|NR?##D#PpA%LrypXd1$4Z zwd`m7l!vfNSKC{xQmbWU{+Q6RWcFGc*Zqu-B`5 z9@I;GI1_#ZAOSl+z>o@ZP%wjB20Zjcx*`*{2Z|mLpWl;B5BJT8H(?R>yrH`vJvP3 z%^)V~CgB3nwymJ^MjU9OYj;09}l#0BRAhlKQ+`dOwI91x? zNQH`2+Ger~rkc27soY$teB|Ns;YGuKjw`j{U;@b|zQ=81yP$~&!X*@1h4;qCs&{T` ztaR|(iHNbz5VIv%|NiUheMWT~$}_KOc#d5JAZF;e2#`=y{tcT7tGCSTa$ zzv#)xrQ*`5qx~K8<%beNwU!&f5-ek)l32IISZa?S5sCcW$mPNLnxa0rD1qW~j;y9-uAV4jHP)`NAG72)##}eT7qXCGctj)Z29?17yUDvu+3NvZh z*bc-hj5Y^);$;bx;ziTfa3JlyC@Hb5A`_-R6@O%oH5-)LwfTMuaJZZlbWW^tf@mOX z7eg(dHZ3q7!s#$`1`%S@WsTgEkHC#O-R->53UmIVmRojwTQ@GYzsWXiLhZtS7p*V; zaYEy;*t1DsogQ~FmM;-0%Ogr9N!!eBsQubgk9{&{InttX>LTzQu^<&_ObxPfSr+J* z+D#oN^m?9jI7jSBb=RI_h4FJ0`cc1`9*ZT;4B*$^z-C}6weS|=?Knhcr~Hf+N}}`X zBKigOD^LHU3rt=)cKp*n>2S9FD+>7(gp-T>=9Tx}AvswVC+>_h%&kNmOLFkpVF*ONsvM=|{W5<_-ssd=wJs(j4l!#*NhAxY3<#%^ z=Pu%Z3vKS-2mW`K*bKlZUc=v^n|D z?Xe{5K7+V#m2X&l{1v z|J*KU3__DIQU3kboa6_i)G{j`D6Xr(ew(hya!Et{M>G-S-r_y@TSexwC<(g9^R@Zo zEy8;r+@?Ukv6uUMjmG@%&Ko@f@q%(>2}8N^GjZ(**@X%5SLi-X{auT;a9l(>+u^RL z{}lz6P$4-aCX)bT)Q2FFeDRnk|7{u-U0S`+Jkxi9hM`*{v|kjVS>gqVr|zL1Dn z=b2=-^_9gfQdMFFhnK(T1#rsIrWs|8%AKyw10fS@_YOf77WHM|z{UJyNtFkaR+jgT zoN?G(O$4>|M~mWO0~U=6VeIuZ8E0%K2ic3Y;nrg+Tv!cY(Zz1gJ>|s}cW&jZavz0| zUiNzR!ZA2c{#n$He#$mAxd9VD*qPR%fL0Q%7>I$rsR1|lqt8x2>Zt3umK$$=<2`f7 zlrr78(7gy}lBzDK*PF$uXRt4?=p@XvKB099EK>f#=51!8_!h}@nf?uy+LE33mTfw< zNDQT~iO{RvvkshqysaUHSA$g>aXvf8<1PTfB1yWy_w5tcDMIz5DMNwh=Bpw>}${ST-k%yb2N z=iExu|J|kNXi}&FYge3Wm&r}Y7_hvuTCT&y?Gwa0u?z{A$q!M}V@TVW$UP}i|J zJgNBRjwMxtjT%YElEw}uv9>4k#4LCJHn;a)oZueXv#8Dy0KHj7@V?ZHBOmXYqmJzp zd>Cji2I3&g5X0^2N2~M{jjql65#e+HIa6|4Dg!fGDg^`=01VOo2>bkX)89pLZhFba zT+gqZ=np8**fFoz%7#@t(CQ8a394DW(XiV6j9m1LZO^M<6xi;^_K`|9hE>~f&LmrH zL>oU(0V|^v?SY0#!TuS$#|L*q{m-sXC*_@R=eslGs`BEem%}8L;$^vg*V*P|5PKs|=GX-{UM6AM{B5&0NnR=`D3s zL~qw2^;u>8+>g&2y)Jex$gKH2itVX=xh~+0v%JXRyk4EY)(xWUhC8=UvX;=cjTZ^B7w|p48w^w5;h&IWl8>|Jqc}X|W?J*Ir;MjA03U_*qV)y@bWKsP- za2+SM-_?NSlTd_T=ItvmrJm&OO@(Fl!S>4XLo_Ms)^XkPIB(HpREsxHvU`?C zZSoJ=u-S1R(o7WKFizn6)ozc8#Io@csfu_58}0>KXr$us+mJ9Jt{@R8&T%GkofipN z3wf4pgECa|S;~A1Vg56du@L3b9|4rX_Xq+5Cv*PDk0rfTL`&ro3Nk>*pgKbqNp@_z z-d$#FJ##@0zNLDREZ|H6=Z-~Xj2&MM-#|!Ih{!LbQe`u?9RMMsq?q8(-V-)qV&Dph zXxlEJG2bJ$@)G0FX3;Ttls9YPFw3}am!}6_;#@UxZgLs{!8On1`uFd#do}J71ZZ7t zQ-D6^e15dQLrf2FBN+qdW!w~iW+TJMi{&kfo^EgSW>sFcqO8ZIFVVd}Q|9|o`P&1z z1btq@iKt?*{kE93R9h81`Y1fU4kl?eHh+hA*)kp41uC4G2a|)Aix@DEJUU#yY!|R) z>q0d-z`c-LIjM-YlpkBaPth-@5WF(bE(||s5XoVc8hvkQ|B=OX&5h%ve)NX*`e}fL?+RMS4;DbA-Fvm5H|Pe z6fy|V-L|K_MX!zRF=j1UR7`bg2jo3%q!-4rtEk+!)F>yW{uD`%7N}yJr*3_Z|$HVgu6goYoz`@YR4AB`4SDTBxD)dg$My&NDWDQCOo;8V0=jP30EWE( zLpjVlDmWw7wk)w)+(6~cBOLJ{yI%x^wFc?sG1|P$(aV(oMsX@Ed~zd%Hf> z=pF*f{Q@3;u@ipn`)=8fw9;x@a5Qondr^rKz0&wbK{Z z)WYdJ%wD#3nXm>;Bz6)(A{9zU?TU`=M;$5OUgzT-q3~!;ti(*NzO(zRM*luj2OWQ; zoZVW-zFv%o;zb6@9g;kNsqvbcFPrqYs_yJoayxNr&*2P}hq!dME2p$Q>j@|lt;|+r zyC2<0%JV2}tmid|Pc_^#&fL0OPLwkXwzn5>0q<>lZrOGcZZ$IbEP7KvUYF(2FCqiP zzCXQ{EV@|ze^k8*R8wacHd;p}WlW@2Bnl#viqa6pK*j zRLFFZvfnOz4rUgPw2`et?thJS#|{;LO^h2k{U;|~<64yNxDGMo#_vK)PSuSn{aoGs z%G~@CZ;=Y?Zs84y9^PFavlFikFmVcq zH}fXGZ@=ZKAf2^}P~&WRln$PtJ<$~uOeaPyqFyB*$D&JMvRbegbu2?jVMy^+ucAjt z{F+JoHsj(>c_mw<#~WdH-KTGqcTYE2gD!T4XfMiGrLJzXZ;e!=t1@#MPP%Bcst;#U z|8~9JJ++moGOlT|>(LF|L6%Mn`u}v!W=x+sdzj2g$rsoh76lTx<4*CdqK#35m?E=% zOwjF`*69$uVzSzrQOK7c?v%fFN;2kL8#49&uYGB2OR!LPiKp64k*Wd{SEjXA z$a10-X$u9x=M#N01ET&T(1LJrql&f=Cd*6LPj&q{{&#E8z(`p+N$h};et^4r{g(5u z;h=zBF#yZi_ugBN(u++z{48+Ad8Wky#v}M*yF~>BSX%qo7&&T?TO0DQyE-<+jDazP zyF(g#BHlcYxQum%G*;o1TIu~b&os-I^xH1%o@{)vmAfAyT7qRzq!uBlC{lu1xfr?Z zG@a^5pBV!h`41taajR(kPx80Vmx7a7c^vBL4VXF%?S%rm6PPRhW%UjoKxX_>O%sa^ z_+k?aa5gM<&yDk4UC_-@rIH&+bijTDWaLQsc7>@8N`p4Ft9R zl^!V7_GVq-sRAg{(-i5E5R@C4*81y9?4*nF#BBsx`{qOcwOnV!kmbGUZ^E6o&shUq z@5)Zh;UoVyjNgl@-kXZfOP+g+FaBK}Iz*j28+`EsT(K^&tN^;fOT9gJ9_uo5&@x-A zF6i;DLNfI0PK91eEr@!P&c0bydmHiE_a^xZ~D>xZf8>=pOA9zj{mDZ@SMY7l>zRPXgZ@28g zQc{`cxL?ff{tw`R?R}HpbW^VN7^m;q-M=}cF=3w?-VU^d|1Tj*wBC=3klg!^IF&Dr z9mZVwdq8;WO|#|Rp_4JqU#R>C*&+s8wBQv-(6N3^(b)b9#h$(DLigDM+gW`ORLO(# z0iUK=1Gr1^_{)wDDJ7#yX=;3_4Bjn-nrtyW&d`mAJ?|joxqHBpa@oe`Y-9Bu1ge%{ zl*`z%!?Y6wtnvrK$6n&r!J(3se;2eK7JbY;XXUEDce|?QFn7wkB$3x!`_;H#;9z2Q za;Z$)rtz!9i%6FW~A| zy?I9%_oM9Y_hkbw7JLO%Di(0MBKy8XyZR7psu8#`Xpv}ZxuR~w^@2(@d`7>cETcb{ zr_(wOSDCaC-)~~p_UQicRx_N$IU>-^5LYfc;G|x6fir}MtKHCKcND{+WX2w%!8ifT-5#UYcPxp z6p!p4@6S0npC`3qC91-O^cObu{k3-Dts=4ai2L8kG*;sE(F5|KDEf{u{`yzXkt9fXTo>eKsG6e$?5Ffyhj+tL&Dq`iEfN?mdNLisZ>1N1u{RC zcm~vZp_x#(wy1me*5VUw z((PJ1sXL;2U9V1zf6tLh9qIEluwCW-VK+m0pzxA?`JMT8dqIV7ChZS`N`|>GZb^Usg!B z{qKq;bseos_;NwovbQvPoPR4rpnjB4XM<$325mu2>u zaVVDrRv=X6*!w{*Tj4JZi@>f6GEFq(*(P-_P*WeO0=~s+%&}MI809>?@{eo%?r5E< zK4(BwGC=k~9Zg^;W|D^2xON!BI*qA^psyz3m`Uxw%U)K)gHF(}}91LLW=!I;xpfH!1MaocsR6OGWtyzW%5 z&Q@Ww8Pzt#){**X z1wudKu1slBnh)N8gmw1n@@=Km+c^iy2Cy}V!H7ZEfm1ax*e~PaSnUcx$mhQF-4be3 zXSkjEW8;<7gytT`%Z_o6eUl){7&L=yp!yXgcTsV({ejqEU_o-CS48H9C`syb+r0ax zWR}7N&$$!Q$N_1fl$RB+)O$UxlRkU^wPqC@hli|t7#U8(NU;^XQZ~F?v%;QeWQ=df zL=88Ch&ixBNTwA((H&8~Ocs^TjODttNIl2nA3g+cqHOVY8;}3}p*Fy!rP_Ub_Fy|? zD<$akE<2@@DfEoV* zq^tN-s$7|Sg!(EDZ4FqrHakh{>Zyr()#^Ivir0Jo$KScL9{9nW5q9Pe z`Jcdf4Pj@CGnM5y&k*Kk_(xC(4FX%7noybd=HTrtv{6&9fy6H zDs&`8atJ~U(y#rp!hGqZpAIGhU-_?T(knEzk2Jx<16 zWUrWfKunHOP#0iX=GX;uEQE!*x5K8Wz!Qbt(8^9-5(f(9Po+93l0&6Uo3PfS0`xu3 z=+G{g=FWPcwRq!NKtO?^2*yyH(I02j1l|yAPsp)hmYAXEX9kM5EZ#$9zbpPid4kzb}gGo0wgiLT{dfA{9=JO%pqud#>4|GiGl?&Rfu*=r`(?{vSQN6f|)xK zt%*xg<>DP(Csp%=rzUo3Dr!B&6`Nxf)famfT;ir%+7J_@Us4h;^EPkyA$R?@x`;bg zRPk_P56GGpqyu+d8+YvPw=F4iK&{;992dr0t9u2EKf413@?OF0jzZC0SI3zQwb-?vZAI=3cX{M#?aL-#OPUlO3vS>|aj<35N zv9)NQwN>G*Qhc$iho8ME;9MFagjsV?V#rLYYwNwpIE2?R8NLlCjV@GY*`ogx*2%0j?-AR~qev(E8Ukre4W zCT$0@k_}e4p_@e`CpSe3vD-W>nu6VD8?DTwpLFFs=+=VLnL3wYfPM`_E5EFStoXWs zUv~Hu4o%?o`d9MWhpOa2>Bz5E1be^!ZPK^woN@E6+Rbi6Bmn#;M3GVb(Knb`4 zy0CeIP7x5!mt7$fG9vCKE`RebDdJ+DDi@H`jTa9?wLLF8W&xC(RWU^~y|is;1!mno zHbdQ~CX~pyYt>w)cKlzQAr)`vvVaYnymG2|*kK9=3hethL!HO0+-X>C7rvb=J|)ih z0u2b(P_408wxKH|r*)r1)dHaZC4nF$=Y^kJ1$I;>l0P_3Y5=wGJpRbUE7#%t{*Cgu z9gHA-ha1BcU~7?OK0rX+I-jVA6W@aWDA+5uaWl(kE+bQg&}E6%%iQ>-@_zbS1}4b3 z7~c>L+fcJqn@|Z41k{*3KT>>JaO%26#;A&oH0z* zfu3lC;~C#z8+3<29i0#GW2J>MWq7e&kKvvfxQk_`Z~}BsF=VOwgl8Myno3iZ8}_3K zpb*-Iyv`GSV2iwQMlH@*un@~pK))%fU5kcFr%ZzNC#gRA_xDp`9Y^cBM~}ml^JUh= zTR1q_gK>+W4E@#L@6HhHMZ6-BYHQS@4f~ysS&9jt43B_-p==tz{zMe5X!>ydINWrT z^uG|a44v8}9}W|fFDZI+%aCFoQtXL_Ul1L^!!d5?=UT(qISR*!p< ztolP~7LFpLkta)zx2^;M`LP-n%r1@rI4*7fh&WTBi&%|VCeWi&tcW%q) zM<5{9cPxUTfEy7Ai1K>nnszWZBak9^#O9QiB4(LXBRL;Q=pPrQ76=D%&5!^QW4G!A)V zIAhd8>?;MgMB#-4g-lZzJ@FHV1;^i%B}eF zK*Ufe$!IzxM4PO8(D#6hUX5fgz48$}#9(*SKu0a=)*i1HMRDsZsOx+J$sZ)SDSVD7<4Ew;WCW z`!(yhH@p`C%Bm2OcQ6LG|M%0Tw1Pb_KZw zW;1VSI8uf?{bw^$YXW_bP<3@wIrC;>Zp9|sffak=c3N(U3=0=xUSjVRN;F6azx(sJ z!T;(KRi>dS|7xG;MoOQk0APsi{OW$%8gy3rTjxu{LGA;YSCl%&ZMGalHuqWTUNy~a z#@Pt|q3}ja$)CXuxjU5lhZ1d;xW8~{PHyu!rQdaVC^2N1u{t}6s$G7k24YQ`6tKhl zQ~18|N6hL}9+#w<604T#5(T$HL0g3kjp+tIm}7>c$=Vg|`kVhJ3(x4D17vg&q>Gtz z;N$tvnLaRMZFW!f{?g5wyc@ZeVlPEzR$3Z8*sf=MCAEHKfpbru4J2!^0`@r+C&}9I z^LQTD1$C6GVvzXx@Mm!Ykw+kMJ9J9XJhhz#fwJYb)&w{=2cc~m%+z?uciZIV_Ef*j z);ZEznn)3BJ;KvvI2GwKT!;U#LzSC^D9OybE+iT1c`nJgE6KR3(BsgbK~(l+Bw83% zZRCPU!3W(kzWl@K&%7|i?Im=m8cgs8PrPwXPdQIsfy&)b*aC?8gE>E?IcNZt)0_R% zvz`TiT-3GntOnT1$}i7`JmF9Z7=EOC5o3V@)QM?_;5T(+Ar6kwYGRq9Vt<-3=;fgR ziK2w3GU=3m-zh|6?UE2fs%+{?sZO;}5IX96cGA}}?*?h&-ebi+cR%2;JSh7qGA-d( zqy_BATN3RVvA3rvUQ~$~nk3pqENn}=oJ)ltDX=w}Bl85`=Y0!;No*dSjVGlp6l9G0o||mQ0ggIXCV6-Ly+W1Vu63sm zm{wK&aKhdtzOpOt?Uv=^e;>|CYm@*FS>h_?6Hz;mNW^@3B(ky+Xk3UV&Uo+~Hp%Vw zL@j_{SG32c3$p>tq1@At9GzAbCBZK6Qtz8BFB%ga3w#F5owcF>W-4l8OV+QfR20M@ z1=jTi*f%Wb#S>9_R7UQ)L6zatL!LB?A}DuiDZeq2fg_zTljdNolpd|6UFpnAvqVxn zu!zXFY&uA_5f{nLI^|0`lbQ5P;r=kx6ltHK>bvyg5ZYKwvoRT6Ur2X-xRKkux}KEM+$Ebw9DgE z>;r^EMdD3h0BYs-L{b~JaWK``8j_hjO?I1w_aV@J^-#yiE@*4t+n=`j9>l_r5*n+` ztlsyZhb__fcw@UcmcoK6z!Vpw(i~WnUK0f$7@S~b_UEd*znb6|s?2r~H#?3V~_4P+ZAfEU;lyki2Wue04|iH4S&B;bH$h*IvlCW&TP6T$IJ9DdB&Q8;Sg^ zmH*uc9JS4RgsHcAi7$HJE+nPmNV?#QS(cRHoi@hhy7e}iw}&7f@tI*0_?2_1!Lbw} z#VfO`B-+E`44=LNP>+o~Qg}rn1RHd!4Xfv49)ncNg@J$u=rS8Nfukc*0@uNaB$46xKe3==FvH&u9&Xks}2vZ^J79^*y_ zBxBZg*|-&{+KoP9M=U!hO+DugR9>N~iI-UW!y%GIN!ir1<0Rz|haBa=hdr5b{fU-g z!4lVn!$%|jTWqKsq;X!w_1Mt#lCby z=02tVnIz+mBKBNb%VQ)rSW#rgd44|8{a>lq<-C6BPtjjhrkVhH-voFiz9`n;-Z}A? zEioZ6xqU3%a+PD>9MJiVr~0v->@Z=I9GMp2ky)jlIV<^$-uQAS#84*D#-zq;_fzz7RufZ;?@%U|mm|f$DyVpX zlF9L6GAL$)#qh4V%Kex*cG4Up0ixkNWP=d)BDB4kBeuZKhDBrsxD@Fznhl^-UbfC+ zk#FApPCQ6m0iaHwbNtZl;E6%1cziV&G3gp3_Pq;gn$^IjbpP<#+%-yQd3VK7g)RN7 ztr`99C5iL;Y&Jxw*R4Un;U`C+BPB=+h#D5Kl?Q|1oc(q>Q9fBk+lRJ-vM*+?8q(rn z*p@>LEPW{wx3T+HxwG3q#j+OAq;bJZi*oqi%($he3@~YwH zx=%k1$8&cP*AncV2!hqaIGNgL6)33bO=b1gnk#{SrQv|0Xg()(v+Bp+OvZnYd6Rzi32mwV zEgqJ7Fua@?J=H*H={M(uwx!w)5<17$0y!E-D!7vNyuhiAmsfBeEZY_tj-*( zX5QCKXFba}`Tb7)`}`D5lZE(9^W}6(li(_#8itXT7gHal;$RauMjjAWo&-!OPe7_@UN;KbP3h#{s_u<({tPNi8W@ZeZfpJ}VMWmII3U*?*1! zEO*QMlB+twaWFOalg%I;rXd4%4b`NxWcR+FDjP7Y=r(e-B1d!ChwH!xiWWj=($E(t3BYFs0@9 zhbJ!Itnz1Zw(RQ94IvUD-{>>iA#bo0)ygLxm73kBt)%hxOF&QbRw-8e(AnPIS(1`h9xwl09Xtb3$^ z8}_MzG|_NSc5gAM-;-{1QdeB$m;mh%4^z$H&{1txr@WkB4U0hAhBUt4RR8=5wsTZ8 zPt@pl5X%SY5CFLk4zt>-{63fqaLCT8xeqeHkz=d)4Md!E&xb=x#07Q%l-y%jXvES35kC z-CM6-cYaQ_dduR_z~p0o;VlCmcn5K$I#be#60m6mx#y)v6zg1vbEKjF4fed8C$M4c zf7mUO6Fg?gF>1(DP5omQ=Hd)PeLGc?aVz@9hPqlnE5u}QeM>dqca+Q#XKS>T91-H9 zjs5J?GTJdYk9t$tz!}*oX9bpdVKHXI{n_3&jMYkVg$xRu^Yw`wXKB%DxKfrw1Cvg% zqLd^mjMua}y!h=(AG}gr0ojA>ba7_5sh=_dhz`9cYGPp&k9zGxtYQ$LxtO=Zi1x${Oterw^t8y}wAp+{|PvR=5@Watxnnu>(UyClLBqYCGjh_O=rhY20 ze!Z1q2w2b}6wek2zB?zk%z4I3Z01Q#fmKtz2RIGOWDR#G8{mvOiME=b>@X3>jZl+I zWm%U~f?8$*rf0+WC;l|r@xu(87fpRPaq&1DYuhtBWHZOSVLeNQb48%x%wF`PJEO}S zo)Bj=OSGoIM|NzkPbx-TR4!}yR(6m0KAu)3YsgRGB-4IJ;z2UqGgq2Z-5InP1lT~y zc(kKtgUXXd?)&oN_(D!45HtMEv*j5y(8giIsQs$c@X@wM2dKTfzvryvaP#-6uYz-5 zt6q1G1H{_Bb7RK=GV=Scs>|9+dy8r}{`bQ1Mxft6;$d`g#!|J{UNsgiguyCh@-UaD z-eK_$Q{xjy1%?&@5Om5PP9&DNT1;$*V%|LOEV|mF`-ygYtWtV(vO)BYHF>iJj)TL>Cw`d!Z!`MbUR_=-c8qi09 zC-s0ZE3bFZa$>ChzQ2mb;6a6!-WrzU~b6`$-`Zh`L(2g|jvLtY7BMGqB? zDo@?rL3GG72bK-$1s?V#1=|hIN=DlT3@AlFH35cVU}Y<2bM(g?9?Z2#f;&}UMhn)^ zY+KJOxMozF)|qC&;(#@k;XFK2@NIR27JQ$h%JLXt=nB~nYZ#jBZ^YlnHAI2R>=DueJbCvND>`Po0oD2cs>w$i z+pv5-28sXz$nx$CZ_?Vyj4fzV)}CjglVF)TU(Pe+I~N%o*PsoHE2)X=Y($KNDnWQU0!*=U59>{%D>jv z;018W{ghIbyKFKDtw;r?Io;RM%GfHT*ae-<`7P@ILYtFMMwF*mm@h!?WOoJ>gC?Dc z8%W-Sz90dsC9s}|a&gTBK!=wACjM2Rz)5!RcbV_@{}tJa>iO6rz*>R3%q_#gULFjZ zJtJ3_6|2l1RSMBX%+1(pW~y#^cFs508h(&e0P1`Y4sndy?;9qr0D{?_ksPIP#gnSt z>3yc8^j_5s0DSCtI$$)=Wvm&ly08e+gRfSAh()jNMZ+V|a2s#{_h^(8qB(=vsa@^O zQQuLjCw;#=eZ-pH=WHo=qXz(crq+Lv=tssg4)70=ip}b#{QI_~-zQW`tyx$E3wjF1 z#A5qc*bY$U7y>)xfNwv+qH*QkK>M5H4BB0H>Q{o`w-Pwx6K{+t!PnwI(Bijl5m-H` z=XlZ|OUjn^ZP~C_O`LOLf$I=OpslXxECP&7Co>`!OAY0E4(=o1xjGgyO1PjSEInY& zWJ^!5S=|SMQs+N@sMrfcqfeakbtK<|0u8vi8s^aKJi3PHdys0+4}+EB`X1v4yHPx^E;LWo2Ncyyv2%V1$H zH>x(=g^b@S^^YXlY_Ycm1KN)!o&NEes2JC*|4m5$1n%hqv$~1h52W7#VY%9a;p(2r zIxmP)=pJ^p=H+XYKe@!)dyF^60Y8{Y%g){XVdte^DTV>fz7bY~%0Pp+8E*t7tJ83V z+!A%=bJuVxsaL|~`OH*0*u#D0yW}Hfl(GzfI^N#*%*>(dZLG>NaD(^NJ;9BZpy>6O z^<;{U_0lS3$q{PMV!{1gM*CGptB?T`KOBWzJCr-JfNjhJw*tDC67+s0ePmVhW~~X1 zlg@;@W?qd8(f8p6;W3tChdd()j2G3GYZ>A46aaj70D?9OuMeSM4xsDL)l|Q3fa{L* zcNhctVOg0gHT`a<>UUornsN%zT@t(x$uW9l=43H|l=lf;qD;wRfD8fh>SZ40Db~9G zk87r2A1!z@$l_sAY+EE1E8)v=&r3p&lSe0s=iPz$vY&liuEiFZQw^ z!CzpzlzNs#>ko!8qg64evE=2U^38ys-v%=Iw)*(I%jw&T1(!5Kc_|wIyNWg9JX?4i z+Y^K({?4n76Z(eAehSR_7gwCR2#7V*WkjPfej70dODOqF=3E)2F;6q{K3f|@C{hrJ zGjPQOH$So+8fqh`#ut-4{9?JwD^ss*E=`{fMCLKI{+s{8Rv~~OOk3#$R1r%&u={eX zT;Zash2s8HXpb`cszkd+oUt0^Q~`=p3@3;&aF|6#f4niSsHrv#L*u(roZ&fBWk|m%(Jtwf2a3VS(hXo_)I)3WR-9-1yi`D`6)K`iAzrf6t1XnTu zJYHWlR5yjY)0df&I%*uJJt%@OHYb=VIs%NAe0iQi&*o!4^HkhGsfP>=6xM=^4ibyd zqKz=kzW$xB5cR*_asazkFhg#-nOigo+T|u*ITy_=!O@@Aa3;T_P;2<)-C}a2LSO>j z<3nI)ps#lt`)-n|t;kWr)KE|3zU=>3Fo9Ub01XIxl=^Fm6*x9veh5d3=`bCwb^}xoRq$Xx+j341N+gcw}GrXR@?#Fe*d``K22Yu9AE_W z1QClAZ$>RLm%8ltP^14yU(Y$sZbhoUF(Z*nhJljp8~Qm`eqADUmo;n`rk0QD77(pW zIcou|;Pf_^->j124RcLAKQn5=ldkbFaECL_L;9`LvsM(rM=7wxTu$-#GAFIc?!>;}u zP`0e2v=(iUq^^>rZWTAf|8e2BdQT=tqX7?Io_u6mSGI#b_AOV-v#slAaek8Nw!IQ1 z<46;D5@bs1?5!Q=1JLTVWJr*g3wRN#EB}DN2=wUja%ANWA8GeSeipafoh|yhQ@+88-TfeYzq}yn_tN05ld=2*SduhPr{69JVBV*HO^_C-SD|a(48|(1E*8vV z4(T??)&Xab9nr2W^=_|S9_JyiEJO$%fJ3RwHwd}bF7E`b5P*cSfXhcSfZQ0~9`&)i zc2qf$8)I!%XD_f$`kPg$N$r=r&5|S3&|375ns7CkAR%CjDmPr3>vWr}13wwn7CgiE zfT+qgGo}KrT(~(-xOuh1 zS4^R~Bdw}xjpK$GZ};(ok7dvfA@=YlEby46MWGBHVgULUXpo@+Bcs<?*D(y9GS2pbw!tdaG{flzz4Po1+aA?Jtk~=bicOav}Tk!I|K1KL*sx+%Y1-elK4O zwtD)_n^kiTT+o>S2Cy4PDr9h|Qh!&XUEV1V{mg)zz`HhI zdsrU+KjsB!5L&>!0Ou?C+n|b=E0QZeZ@M@!w0{)-0s`Cw*ppw<1ESREPR$wPliH>c zwd88cc=gYvaHETO(aX1D$wsQfl)jan%Xw0L!LX{6@$3n=fX=vim>f0W)oJjLts(Cn zkUCo?x@%&t1B9_;Hrm@mqczjVe}`QKK!Z1xaNYio3?eKuZ(dL_@Dx-dDO&+RCu4m4zRG8 zr`0FsIP%7Cj*!ny);Xi|dqkn7>1TkpaK>f$MR4!nEhK2-F%H%-y{#F)9)|87=I)y; z$LmY+`dc`?3a1an>sR3QLwGPo#9-cOq_D|S{lrmd`5;s_Ab;ToK+T#fDSdB)+kf^{gtwu6gTp{UC)Qg%PFz)lIE4cXxvD+GkS*a1xTFV21L98QRM)cH$Z+g06!jp zs|TRU0qpmIqIA$iF_MwEhK9`Mi8J&aRXD|Tw)0z6H<_5a%QTk}&!VlbSf zP8I4?m$X_OSGB@l6r#ustGDR9U z@=`WuGmd0|Cl#8Lram@Jc!H1wq88A$%4As-WJcZu8qB6Mk9{LZh`E^c@j@BcGt%px zrMm7vM|#Rv#XmO}I8X$qK=-E17Z@}H#E&5#3q!{W99-wYkS}BOx62o>MR|(^%TB(Z z*?hk2%c=e=FFVGj3%~@DT^#U&pNx>kK2N{8W)BCh$IG(r=;e<7fTH}5bCC|L5Ex?oPN^(mdwM%Rj0>XYC^KnRwamY5GJt;5>Hu6!f35LlXp`GmGQM=8ObV z1Jn-N7-0?`)_H-H#2Q{An^!g`@AO8QkY?DTtiZDBuJHZpB0xugcHTR^wWjnc5O((< zo0%f#wAs@$mlRE2X{`WKSIW@5-iF0~Q5LyG0a&^6Hd?8I3(N0&OxQm5dxNgv`Zp;md3b+U*z6 z)+ll+sIB{j@IE1SmWLfGfi|hhAQkPrj7@+pq5YD%n*EAf%tQq34v>+ji{l!x=5#*1%vY`XW+>yQZ6I7<&TktAP&6z!;@!H%+pc zQP7T+9LB)do_XVj?KN2RfYn*UNAI0O$*D&M!24G+q9?VsnzD|7&>FeRr2MSmi%td+ z=;i4P#U*EMff^}Ke`2jtWr(IA9n7*zQej_>T5yWp6ZI#a)0`e8%-p4ZQ-w$$A zH1|X6i?touA1U6H&+@%%b``nIHfdTL+ncb@mU_JTH(3$r!^-Oc&0DT^Bh~5O6KX^!oiEp) z`MJrsSNQhdkH_^}nbPZ=lS%n~zy!Jz2wk;g=p+HNu6&sTF(Hdq0Cy;8CFAMbBk zR}J6p*y5H46sS9F(M}ugTAC$=ZojGpv}E*vJWwKQ2p6X2_0}$-PutPa)du@_Om?R;qSZe&uK5ehnmPk|QsP06u+jxMIDvO5oxs<%)GlDP z2(*Be607og6~p4y?nh>{dLl)da|l>C9z8NijrRXODh5n5@K-YYZIh%QfWdFQkYQo!J)YZi ztBJD;Db!2%Gwb+2wyVY)rI(xq98E8&!{X^=~;3Z9xjb zW&=I=ZsIsc&RzuCoAyE%3YNC>@XxWpTj?eA^Tcy-V1&W(cJ8&@rOVtZm-VfA>Vb3wW4Ywsai%Plwjc zD)$v99q425Spxvl0wp+A&vW{TB_*}w5f!{m+z>LL&vi(OoCK1U{!B){m8k*VhS|ML zmga3L(B8Dodly2)R;O*a*h2-?@IvZPi^OzKuBa=N$Hv8J?N2rL2P`X>LV zVEkWzyc?gId5<5wk~Xv27(v>j`5wLzJ&=6VXAs(>$@8R#;7RyE>ZXy7YM^<5ko{1> zU5(hE#fTE=r_>sWc3G!9vQxf*pS*SCZ31|A%9`QZD*uR{|HI~N2%?h#RPvB0JSB>2 zZT<7H=+TL@buFX|&~|jlW@Hx<4hRcv3(2qLy{T0F(K@MX{8B1eB28QBL{vK*5N-y% z!0E3qqkl7O{=N4#1>4Iu0(I`FjJ#8r1=xA5QFciLdrRlRZ(n1p~(T2VLOSNYv*OLmJal1InH!#x1>| ztJZ-V$In>Zd>i39&)sK7b-y|3#Dg+$h_44%6f1kC>GKA;VHznYRzWLMRN4p_fRMX< zIwCCqq_N)>@G4}Y4VwePqrP7d2^O4Vm!wi~D-_>{Zmz#9n7$;i4BbpT6JR|BIx|xn z{eZ#k-|+f(7t%gl7xfwgnW+sPYaDyJ_8t|Tn{@T`vt#!xpHEnt^E0n@??4RSxT8}J zE;Gw1;DimA0?P7*g3F@~=O(GHdOg0lz{8KbKds8vZ%Ayw`fy?Z%ve*OZ-wSxFy=eH|`&xS~FtWKKDC~Hkc5D zZ;%S}8u-Rd1BCJc?rL=fi<1iaG?=;m&B-uG0kM|_v^z+JH83h*Ok1vWq2R>mf%Tco zR>#Y2t@>{fJazg?9+pUfCa0f>*2+Ya)5i@%w_4(*ANv>C7|nE3JL;7~^b;8^u%c-p zqZSVv7E)tDGDPhjp6~(w;y-MX{@7BcP3ezj8-Y{&cnP#p4cv=>M1s!out-2|mtfa9 z)3f32wI-lpVw@hbyZ?$)ylx<4G#aR1zzL2+i~k3UsLwc+^2;wo7r-zW)8hE)%YDEP z;k!#2y9Oydhgq|rWrIW7(G;3Pxq`b6=|7Kou&_;_mE);Ydi8)Kc9n;*^2Z|FPtY#ojy_e8lja%DN+x^N)3Qv+!0@!}z{2giCF zI&y`6sec+{Byuk#_&oOATzS-iGdi1k%PYrb+P_^cMn`7%GVj;7u+k z^F6H2ku8a#qX9->i>%BytV@VSTi0jiFA})U7c4d|Ql>!T z{w^@XX8iBx-kF3;;r*6#8w0e3zH^Q*2H#`I{Dzi*>nWvDKbiX~h90$)=3k3W3*VO( zj`yp5BIrz`NcWVKH5N2g*%NQIr?LU}#e!Cg0l~KpW#sv++xsRPn0Oc^n=cyN_k+PZ zk?Q8~Oq)T7HvqY-38MaZ$ZIl}q`Lov%5R-{dYtp3n?L@`)wGk;`pX@ZOC20$>ad?# zHlfb(AMbrhX5^nIf>=;9A7b{B3A4A@q9bO~S=2$YNqK<%DQn&!yp8DX=9e6uHnKjg z>THh*uGsT7LM}scDN6m%iY7}2R)WL_BPC1>Og#BiEu{Z#*z%KnW-_E+XxA0stb}(? zj0b`tUNP5czAuk(t$2?9fSlMT+$hgBjuSnit^VinjX4QdMR({hA%UaoQ)T%ozSx;n~C?I^&l$)>y_Eqi)s2o z@e5*y{7Xq99ECFi6Q)}`mt~0f5pUcHF!9&71u7g|=*FnFMLOD&_n{*@kzM@48qp|i zD<_o%oL>8ds;8GazIiDIgN(?F0DGv594(xO{hW!k9-oOAFnSIo2l-5hb^|vZ=w9u1 zRcGY79fTsq)saZld1yUyA7`91g8q)Q98_kPDux{OmFryKI7@kynph<}@JN;wBvf&F zH#^V+_M!~;wAQ77j-AyeI97sThX<%uprvZ3>{YyDrSuD6=GhpijIBV5*UVM=fWHD3 zip`nd-!cR~?b0~)F}nMv>vTWZTc{?Rikn96q?9J&)er9d^f-~+UQ5nAjfWQi0MAbj z&`{kYQO7{!?QoB+V7l_iIM?|V!*4LgQ!{fES~xx#Ums1W=TnA=2z(AbOSuS5m zUK00*ZWEv8imqf~3);C>#^>f3{i#&1_I@fCe28$zrfz?N%Oj0i+YhjrpEmkGkQWQC z=97V#uQ_#z56}N0c@ZaQYifV@Rr2cL;jQN*VAjJ6 zv$6YQdW#oJ#)jr|MO&|ew}byszR}Snp)UPP`Qqlo_cwAZa{hjCC})-86_~lXy6p=1 zv}wyrCj4>boK$Z8hn2|))U`2TF)_PrW5QJW^aja=%xKf*uQH3&C%>p>eQX~*RT&Ks=^lWOS>LpF`QA<4_*|V z-<05~J6C-R9h|1Ow8ea(T}dyf{`W)GkZH~)aK!2bBMGCrwz2tMf6%Y0z$nur4g%>0 z*Ws6{ga38zch}UJ>zfWi1&86df$Fn{F}6X)H)dhz!5WA<058xN;PurkL(CIwca3(z zykyLOa_D90RGqzMsMI+1U?2mhi9aL?s}anRUgT{xUN}wEA#!vLclD&Sol$Zay7z=^ zuj%*DKsK6~c4JbfarNA*vlpL&rszHHACr3hQJKoDt2z%fYo_Jjeh44w=sEu z;WH_UnFNP)d4h${A;Q8A#@lf4zo(fGdABhVI~iVwAiqiB`m<>vk=T+Y{EQ18~+ zLvI&4n)DcAhY}vd$2lv`WRgiQc7Lgzii;cV{M7`cAL~;^Yi9-H#=C8GD#M0OFd;KT zZP;*5F4o7-7YVdY3rAKUw&$$oweB13Z2M6Eow))JhK}akxg^M0S8;FH;{sv#SoOQx zUO}cYVi z#2`FGlHUppNpX&U#F{nDV`D~(A`G8c7orz^!^eC&u~VW3QKDJi8|-)|Hd`F`aLg2` zQmi&mW6(NXyCEQLfw9cPIFyl+Z!k1^=7eH1HG7KxAirg#!4{NxY>TEJJE6CZJuso` zE9|5*N?3|D)F=cu-^Yb`HLbmx+VUf#C!&>%Y){QKhXJ?>CE^BW9>{|_R zR8^Mlmo(4`$ip>g{3T+m_&3tyI@=wh_A}jb8@e@ah@wm!W?31WopEt^&tzp%Hr3rj zZauq-@n=S@8JF29XPn)2w`NAO5dt)6NQWOaMwBRs5dx%b5LApvNP5q?_rBM!I~{Oq zr)q1fq$<4o?stFAJLkLSp8L~}`-69sNRrL?C)sYb<=%4tj`!qpz2g51Y!x;;q$=RA z6#nMk*`Ym}zG}qpO zdJ_NVtZcK9RR?Uxvstn#W19wVks}V``S2$*0`xSYACkCsgse&;!dfR0M@hi5cg28s z+u~THe77+v&+yv*LhVJ$=Rzj!p8cNY&L7t z%5$|Bxe|t^8rIoLY_^RFo3|uq*+6Q`38+&K3UU+u7E^YVJo+;Gu%yya%D#Es3!txH zJk&$zdnx~ZET*(qVVStr7o^9Q(uTfuCHS85zmMor>Oa)wKUhUlrL4_VtwTJgiDxB$ z`kZEhA@Fpd9#eMbY)wc6ANwsOazu(H9)H*$8<1oF0CL0E!xs!^g~Gsc?jY@lFGuR> zwT_^E1r(9H1M*Iq2t>9>LHR%X&7y(LM=BOUd0t#@^Y=#jhij^|@^H)BHaYq(ejxM+ zy{W(G^7maSzTNo7_qYZeISq9AKeCx0`}ICbjy8bwk59&qwCB^;!3zk|6X{=Gvt08* z@~xT)a&$3dV~LuHa_q;D4!87PBgdAo6o?wT4^o>>NTOAyp81fK-aCr*PD^sMca*n~ zzR6VE$A;R{TL4@`Vp(-^cvBDK`_qXekX)WoFuqLcxq87K*OFDkjCq$E%&R1N1nEok za00zT`$B*v`RPvDvuM2WN{7j+)LKJ!+S!hB#d_5_+;}WEphunEs7yWVmKZy=%hzR5 zDQsAg)Mk7M(!=!K9QRp)F;M1!JR{8ePjztvrT7Rw$cb?a`i-V3(1$vyi;ZRpMYo07 z=-}g6m6GFCr=6mO3Tq3l1c~*6FUTLyr=S+PCegGy(=`P0T3TgIu0wuri<~?q`#O_^ zww%oGnRlx_MgV_s-;Y@7C*ZSAL^DHOr?f8T#()UG)#PL=3$-6S>F&9yke z)HNrf*TNSubbxK({45TaCTSnDd@%l7WFZ)x?#pj#R0^>I(*L;24;L|ZsiPq3y5(sp68PV%N7ha)@=}f?cNyc?{rv0%- z;9BE$c=V0NB+OEU;|*NOmH1Y_9u$=IM+ekK;rC(uYYY9Z0TSVYt;cbwF18Me2T-^l z5Pdo?->b@mqM)V?p}lr|a#3xvuTQ8>*awVunbE#F0Xoa96-8ZpGP`Ip(_^68Y5`<6 znB&#dqQPImhoQM{yA}$@m&`IOF1OXY39X$y)G28*i9Tnjvqb&d$bP$4P4wDJ2%V(Y zI_X>oyvz>IcT0qJ88uxACNI%%+c?G0Yj}x!II}kY9U9I2Sr90)9cI+pOZW?|bwaZa z$N(!&g2yy{uA{ZyO=~ODkAX&)j`e>`elm{y>ZKqz^u|P=#ze0)L|@__{W_w*SVVLl zzhD&b1qKzT>q#nk!k7?vkPvTHOh*0?;(#Ds<_OY5Deo*UqSsC0^&UcZNBU1jy6vsC zZo$Hobzl)%iVYB$D;S5W44>9hW9`Ya;Zhi6vw6Jr(qylHP>L*97A`PLz~&2>lmCG>Gj{(F^slm;HJ1c)UqGn~6NPn?%0KYEv?^No2DF)9O`( zz8ReJP^ES>IOmaR+Tq|FkG7x8Q5@P{LeIf2(tp5UCFj4|kyq(YA(N*LLn>##>1Gks zYa=&DmYYMc4~%~Awa%U{Bz78WH{bp8QuOhJ_IqHzms)x&s{#$*&dZqiX9XI%wgB%f zz%MGm|5SjN6yQ%5;2+zpxcaCSdp94u---@V-uAQoJAJ-j8zrP z@qu`Y#AXy$Xdbm65-b!fKNBskZ@`eU!!*QyeVC8h}gx+A$Ezv`RKHWc{ zwYB5IDf3^J`1Nbp51K9VDbR^UD?8cLlX<;heQw&1>nCw`{TNbc?{Zmp7w5xYq&;2` zux}T(Y+b?>^uj-Mh&_t#AK-=_uU~IAaDh3d`MSfH6^iet{jchq@!DzJLaPkwHwZ@e z(1x8Dz*Gj}TA2uPI??l>(|!XRm14Rj@*G+wG1>|43QV@b|6vJJfRw zG+oc4)w3*}-^z2{ok+g)MeKudT1q=v5@)9Lg)E7aQhF*b?h4o2_XcQ|QzRJwL0P@U zOqEtM1(yu^V@Kuav-zg1u$DnnpFRtII3J&ukE`Din6hz{dBZ*G`Jx0jrBSW|rlI3G zQ}Pc~HliMao?-1HV}Q;}aZ|DWjD`C=Gvzf?-!W6yo2i+WrOo-q_)=(>(ukc44h=yb zzM7IS13Z#5z*4@X_T|Q7fR6I{n15?fzj|DCe{>dgelDFE-zS|>-H%(a;)-69x985& zur9W~LhzZ}JgExOFU1>f-JEN!4g&f6#4_1xx1m~xq+U<-(v8@&(Lm&+#KU)-f+8nN z)CboC^RtnYrRw^xBUCCUl%6kCMS)N;41K_J#BdYa7~Df%M+tZh-L|nLUno^}?aBLy zd3p`2;o8GPjs5>a>CUP$qXU+c#%(ddvgD}AvUW()Wcr2Cy#1Tl5X2R%U)guu+?|4` z!`SU5t4>L{RIBY|=S3oZ5#GlLI1|?WEHR(dvmnYCDK{CZ03A_1XY*e2>I_pC##?!s zTqoIuFJ6xhI8Tq%kIQ;>$3{FRG~#jGxNY5wiFmUmg2%->?=TSe*Fn|pkhy{ovc+3^ z%+)G1`;Xx{HuXS=9tr6+PMpeM0hbk1>nLvM&`x7SYzROY6!bjUt-Wn{889HM69ROL zQ7j~#2*p*Wq;%PxRT1&^L75kp(gcA=2B~iG(3iu5|i60pK?X0{OdDTz#}5=l#P>uZu3wE5(=U-mHx z+`j4y;>u^TB`NV3{0UGZuV-gXL;dabU9g zKyhG->MstQgPyqtAJojJC+_jkdE1tW3 z1ajS&n}Ag2XFRuO#3*Wx zCa};1?nL1D=s3Xc@qmrv0WXdRJb{4Q1l%UDVpObL_$V!m4=w&ad}@-sx*0}`H#}M; zuYR}$$1w8^fz;L$>;(AK)TV$E`B;KfR=r!H!}N27?s6rd0G7*43C6urz|*PT9Hfbm z?%Qe$=?;JOh1y{Sgw{UtS1&Hp_CRTj_Hlv;(m~4%VXkkxp;d(r(c#D-xC|UaVjZHm zH=)Onqd$~*2=pHotXg1qN+Q1ad69}P29~JJg|#XfP^x~f5XjmPu&Z|z0*4qdLA{|6 zc%1)fHv5;mE-dyLhbLc+UJfTxji z>D`d#6@&B`WDc|SlbzM)&1J34yflIv=HapYP9;BPlsn=GKQ`6Yd_Qu$X@MYIBv~Fg zIkm|TY>S-Cs&^^$D}{dM+9tNmkk*PsJl#m^%|YG1BcxaQt0!xN{^~l1wqFT1m)W#E zP+HL1LGl70-b;Y)21+Y*gmJo;QS(a9jt(cM$HRiuuNDLEHdy`3V(3kR)-7X@3k9#2 zj6n=y2gV==1+#A)gX|F0o<0WoTXovJ;~7&PeR~afvO$MjsNp%ZtJ`1E~k(=sZU1sFSn$ za4{jRZ2WWt$;!?((+5o=^Ap6g5V?&JdCY!Op1%%E4Rco=23O6zcTaS#Nx3HtXg3ASUq-OMUUaJ3u{#w9=i~jBngjQ2z(-V zeM2Gej-Yi#Arb6!A*wnnl~$kAVUqjUSaJub-D&ZLPG*aM zZg-AP?^kUW$L(`+&t2g>Bf&#w@Z2c7dT$ZA*(Tdixjih+?w!D|C zzla?*8kalr?pG1nH>$5@M_06lNyzS!7V!tHqfO@4d{AG$3{U3Db6J~8bKtUNctTd5 z%d*y74B$ZVnnYi?3=ab=H7&;>XW7?ndQ4ngv7DRyUE!9dLQ@5D7f4zlTY)s}KOa4r zcaE3M{Cj>6IG&c{x$M){^DfVqa`chXJiW4OOP0_fk}Ykz%J^bAdJUAOK!@()+dI85*aCNx;j^7Vkye^iKr9QonMHL3d%lyv0q==42oGMl-s<_rYX2ZKed*nd)0;HHT*>c+j8}EYcgp!cVIo8YBkj28?P`3yo+;f%dtk>(cH*xs9ZoI z>s#54@N!7u)~HSE^1Fr<{ijYW8_Q+p>R=g9JB3to^h->QHb7P<#Yv2X7GF?kl`H?F!K+ zn1mr3WwHd|eGPl^%EnoQad_v4F?4B;0IS$%dc!D+ccCb8RIRcYL0QH1lUGO>ev5-$ z>N7@EAkyLFoRKlfNF&FtgUJS5b9$cf>!0*Q>Ou`8OE(m zNb$=NYZ};5nt2I!QyJ^~$gG?s(S%kzRC}GI)jddb`<2|6cpdonl3k9)E#)pI`pRkO zVY=kD71vptP&c>|Bvnhqr_IV;?}lo>cMXwv3qMQAl*6#po)IoA=I>%yWhJ5sGS0z1ryOGI2K5d@knXb&R50g$73F|3J>LkKA_ewRi`+)2>b&ntS7A z+CzBh`qrV^8zt4v@9i-|;py+nI@dNv3+7D!o3y6^kE*(I{z66s-dNE_S25U8QIHV8 zEwQ1_kQsR6CYlx_R@VZGBd(|zXCR8fiEl>pe2!q%t*z~+-+o=StDm~A1~O8d1e{5< ztCS+xtt%11&2v=fiXjA&>^bM&`+g?jr(M1e-n{#J&UxqDd+xdC9QfwbqjY8aYNk1Z zQfO;y%~V2H+2dj^fwA2%P$1^zj)89iSY?{*sq)5ig#z~ie9r0*5MkegZSz44o`Zcz zdzR@0&D-R(=b75{?3zf&=kB`nD{OsiX7q_D%|3E?j;P^)lpLUonWJtg`4aqEdkg$7 zk&>^Y_WJ01tZoc*n1NrVQfeQuyXP7BTN9SrmgOsJ)&0FYQK#gkk@Up8tTh5%@0%l# zFLJ|X!CRAXl6Ajw@X#*JGIAvC$tRjFbx5r@lOA1P(bwsVM}a4lJq~uJlT6<0b@KAHyk?c^)S$0OdqPDLK<=4jq)*Liq|gJ@FZ(=Tmqr1bBC~ z&Z_{nziEnIfv2NA`&;WPU@m>~u!$BSJC*!ltWZL?B{QTpd3s3Q)7RmXl3xKSly`kW zW$*sJ4wuxnJtT$qAR{Y#cPm}xeH~6H=wStKD_w!U4v#2E?0sNdLiyB-?{p_qOpd0T zaJox$b*KogOZ8PnUjWgmK(^}{1myHZ#XY9$At;Kd4L*GkR%9G^rd~P3e$CP^vb1Lu zQ+kH<9664UyzfC>vv0v=E-5*LQqxw#RzE4ZpVo_`nSOKi+MG=UT*2QNQ5nJvfJYga z$>Yy~GVE|*G@q&}y@?XNZV*V*>h3r1?B?->4khI1=ybOjy$A@81EiW6S1 z47sFK1@vp+Bl37BT()3v?~6dRPM1M6QS>M0h@t}yOA)ldCyb5G>{9AIJKg8I&D{cN zPeiwo`J1GT+Mpfl;w%YQb z(VB8L5PE!BJcgP|6Ldgz37U$qVktG2LPrh6rk)Tn^nTzS(Cc}(2{p&lhMftDi6^JR z@sTu9d}1^dkA;|iIf9p(JY>VF&v_!O4h))Db=$DAf@Q_b_^JY}sH!2PfR^!@E!dfa zupoERSp5jWOU)UyVfD!gu`0D-)%UkyB|rtVqUwJT=$~=Le)L~lLO*(k>qqhN#wOc(e~wh6x4yOQ<2hMd393=k9OD!_)R)MMx_R zO6yJ#)~+qn#%lL@gKBqZ>Xn{g)nVzO2sBc-?l42xxTGPY z&XZ{YG{eCd5 zlW`enl%zd(If*-vA@tKxECbUV`dB{dEZu=qYx8`Q4?}OS;&MuD^DBZ%)`=SF{0cJb zDm~A#{{IFqeDp3?;kjZ8#+De=3#s94$EDyY?JhyVkQUx%e(;HK=${AUFF}3y;88r( zmeMl+#E|j3u#La)hU z-n?7ZShOapy+$Og&E9P9VO^36ugKb3I1tB$?`XWsz(t)OAfLD5{5KSDh=f~6ltYtC zP}wRe1F#4r7>(fFDS!vQd51~ogZKai_otv^FXQI+NIG-|Oxsl67l6aHPy6oFMV_if z-o{X0V7f2yL9)5TR-amR5^a8Lna*Qpe%f8eEzA(-cYNvwhMxcoHizav1^O{s!B-t$;si-> zF$!4p%L&KPFFR2c29CQ%Cbbei&$Bhk+nhn}g-}%(vLiJE&Zst`v4M z@dB^_%gah!-1fy3QneEa_%xSRTM!ZvywGbCTm92f)xCob7Jsk+2m4^?r1h~?@Kp$c zNZ0sOHv||VO)#{_74wZ{JapuzR)`*utm?uOL5K*GTs?nh6M)0CNIPp z8n$ucy@hYsK<9ukeCCF2b8Wp~k+ z509`{nCm;H1Tt?EN0D)FUHWA|`y~50L1W`B8rzLq>e6pegNo8_!8>+` zfiu6?vLS1Gfq8<7Xvt9T3tyu)9Dl;Pjz6S^S<(nC{BhA*ZUVH04$k_bVZ&ch#3#nw zl#Ib177Uyb_n_A_QHAmWHB@HXB?mi??UP%+Y^5*K+$!h831s1KQU8+(q^*hh_TqQ-YbZ*^o&H2|?U zETe|#kFdE3Dsq9bj?7rBYF~EO9gFX|?~bKWb)}c1;4SK0E*lYW?YFGBW!2KyU5(UR zv~S1eQB^MPIE6ZHp^hu=x)r+KvLZ8Abd0L?-pqJvS=@03b$rBukdAX?#u;k zN)H*OEIUH`X%1t7g$8DAs)=^7n$xN)0ZRB?JyS|y3LV(-{pA#wwSsKS_xOn8#O0lS zqZ!>~GP$vJCm2Gp>rW&G*tnH9zVt+5fQ{F)#_{jJb%e=impHmkvH7zB#IU8_?>{v& zL3F1?B*&8;9RFz!%yV)^$crIIvg#vYKmjuB$5ynT04 z(fNGpETqWj$0V;_^dosPI=?15?;GNsNp?`Ci~&%#Mv)}!zEO04p1KQ(;&LQL5HtI% zU9+O=?bOwfENE^Ku6nPIAtuCCv?-hk3PQVQbgqnFg;$(wJaU@v$fz#t!!r^dq2}T$ zFRl9!-lIV^7Nn14*so_ zQhzvtad;vB9H*XxpU1>zHufB=c1D#iW=P3r&??qj2}5|LhaWpa5MJZITvxzlKc-Gwnx<#6fh+k!b$IUX;BL9KhE zRt<0DT4+O7R$bKn$N+xMPxywx?_jm?Mw%;gW0jINbemJxrK>;SAeYjd4?{yf;U{8Fy%7uDHYykdxEAUXYdmwMRP6wo zjceRM(rUN#@Z16Beu+z9M7hEdJ0qgxy^*SX{4e@ssH^NIg=hpdY~b`CrZu<3Mgx7% zVXN;M>LZCO0A2K3X&8ADR=BCkuUB{ ztT`3+U9w>WF*l#8pjxWcl#`8i9y0+a&m+%87bT$!N#O&swk8mgHmtdv6ziEz<6yBy zmX-c-LFvh@RCB(iraoNx6;_6&@IG1OJ`k1H*=i0u%$g;(nyjT}xvk~{OU+7K&D)lm zCR@#`q9)@d=4Mr-!bU??1MySClMe=!gJ^f!YV$PN>WnByPiMh>ESE-4R9SN&9E0~@ zY^$7u2^uN-jVD+WK)ZddpPyLqqNURcMDQ>}C|Dzp&$>8ppiIFh|1 zgE#OxCMM0GnMlXPq!>Is%=1|_)TUoW?&B#l(u)H;A5ID1Dz|uRs|xWiA}w3D5g|rY zeir|NCke8$TL@W^xOR(~udBrNZsz+)Z$@V;V8Cx^Tv&ukd7fM&7fUMJ^kt+f!i06c9mYhma>N-UHTJ2_NYz#t zFWDIz1EsE5{SEXnSz0;1CM+5gO>K{zCvCXe8%=e`&Wr|s@T4DSh;N6VkNR=WcpjIQ zPLVr9s6d6+xUXR01tVTKq8?}`?nyV6@rBr2g=ZqP5%dzCUIzo7!xhB%>DH4kKhhGU zH*Vp{Ir+r`Yf<>D$lpXOr8JT- zFp9P2A=emhuZT(ZEsR|yj#=RmQ%&bp9Ff@fMhU{KVRz_}ii z?+#Pg_^&NKqrTn|JuRmMvpA%FZd}}3__DXCuCT|R-{_B+i0uNjwGO#fpDl2#>WrU) z$fZ!@7kAcX79=Tkn`xqwd8S@W+iGykd$Q)1m5oG!_+}xb@iz<;U5VYSB}R_@%ovq> zTb(d{!s!6YudW*~(mA;)L&3QgB5Oq2d;<$?`d5BZPHk&if)U&$rIr&oRt~c!N?2iP1(srSczyb){w{MZ zlt%6_W$t3T`7KtW^bf>KNT6)#9134rUJJYJ{%l2=+p;zs*Z=kMh=NF(32?C2@U%0S z5_p?!g@QXjHrOyCYf29ew=hhqnB2Y)WIA+p-KBVTZ@=az_2KeR`K(;P3zVg+dnm^P z6CT~TM6v0Dn_LOpTq!>*pBdfilq;O^+r;8GXT%yd)mlR4{(Fg}7pNcc#gRsTi=t3$ zYZ>9lI)~KHm`MM(r3tOyg`Ls$VgdcTk%Z@qB6%$Tm^ z%ZjFt-7L`kzU9-3y-kFe{3WD*!B%$69wAnKW-sM!?ZFo20v_)u?6nV9cy%=YH|B=9 z2?troEL6rqeZQ=}2Q-YRgDnGi!z3lwK~2lRd8p>x#d2P&@5|}tc77bm;k*F?_)i&Z zRjcl|rlSKfklMoS)vrlO48*DaGJY1hPi{p6So0=W^o~L&1`OJ0LPlg3X9O&SLBur} zmXlU%1p{H ^2;5{5)``)e>n{8>Qo8Gt5}mZv8UpR!tIdF%h!^IIpOinj=rSvGn) z4#&;iQ8k>^!f&bJPU!Y_Ynbm|z~$ky_685_2r7I3R}Vus#3@-#&R^lTs&`1q@04Kv zQnYtgZ8&8M)gMa9M?Lgj{ShA57NnQ`=7?TP#}k(+04Sz) z+M6g<%)^>93CrqmE;-j{!;6Db+BWdv>}|0c4WQLpc*bqGc)w;&T$sIY;aP zD9VYVNr~nzM{ETYb%`RF>Rm_dCs6dRC^|pU{Ch`iJ{0|46!{a)?>l0%py+*3bYY@- znkP;8q_V1q|?0eWd|jj@(7-y zPRLSU154#n$Wi}F-1IfCBi;~KMa+6AqA7x#D7Ew0qo$$5+G3Am-3cw5cWW@FZB|<1Y+M&K6l2(_vHdH?~6_; z702My_XA3oGpN!q9Bm*0ABE8f-f6V|A01NtMtq6)h*%N&2cT@+VRJ=jbDAqc8ZUDx z7$TCc^^XzDLMDrgC#?+HOke^`yFD(@diO!CaR)rU)fzv7N1xXCF+2`wjXm(_*BbZ2 ziq7lQeuA7i>7bc7uv))%b22P(_l zPG=NfFp#F?A4XYr^yCrCw|3a?@)^Q-+flh47l)|o!*#m)f!GA;VYKL1yQGJo5IuF- zAleq7SMRPvCed0PHli^?No@_8#DGgm?!vX;!KZLf7#I@|NB@t#XMv8Y$ntd(k`QoS z1`*If?Onk!BcF5(;GX_3BmKck5mdH)oj=tzpfx_O;K!n~GEoc>#4)qObe4E9?RhVy^NKGvQX83sA)81!J)?t`~gN{R~3TzuJ&3^GI7 zL3n`yOO}-qXo=uF<*qtd)X>!rTlS5=0D=#;#C?d(uo`-hZ7XqQN)?Yi1zNVyMC5Ro z4V$;bz5`W9>tkD2Ym%vHuAI^5%oN(TH3$cXa!oJxH^tF^gKql`tv;qCgC_gSh<3MD zz~VTcUz(!rOF3tha|{AgQ3p&lREeFstm)q zDj25=Qu7~Em*7;T?rp?&Ik4mL!dDXvMhW_dv$ch{@B|)t-%pbd-fDLr9K8YktRj5?Mcvd_I%+_lM zk}TJMV6caO!Sji67o03_>CeWW33Pb;tnm7eyR6WfJJ26?QZ;$M++POE6+tV@)yk$~ zb%zx8`!Qaz{Ut!T`z9f=XW`xPMTSp{?LQLqXFIlhIlQ8`;G7boP#Aw?4lb{kP&T5x z6XRg zA<`xaAJ~bXOKjf{tcAMJOT8j4udp0prZV^gte7it+!`XM^!CQGwt#_F))-JrIG)rR z_pVz2`}KOqQF%dp>Gp&fSG1b=6gSqYi9+4PFHX}nCAS@UN)z+x0kJ`Vo7@p+;A8cfTtSI(bbPa64U+fs-a7D~r3@2&yR zsX2uHbQN6&hGmJ-NAO$be3+I$F4M9w(>jy*WiqAX*Sll!i(?dgq;z`E>W%5oS`oAD z%)+0rx#unw$Cy3Uu1T0rCEInG)G3UEdOC^`ZD__p{^7D}+2e3AM~wd2d2@00xLiDW z4s(%z|HZfcK;Wh$wob*T@v|A-L-^2DzUs2YA^>hjQ?4)e!qX@k9Z}WT^Y{%iBu2r` zYb^HPklHUs!DvyP@dYeFhLx?$tqQ1 ztlWJ47Nes5dn3BN{5`kpw;5UOe(v@H{Whbs{XXvYJpDE!9NVa5w+q>A+!EfuO5!DB zSUGbah7)hHF*5L~5Ei8$3(1C{jBlVlpnSzFWhD40?ieOHxp=7cu~mbfpCcr!kn5Sy z=N)BP#>_07nQ6?-z?m6_Ov^||naPmj)Ex?Tkn+~>xs}%VN}o+!F#u+CEZw#a?<8Bt z#%ykkW62BbAE5nnKpz83z>}?E*~A^+wT4IT61P2T!sZRCOxEyel>7-vuFkNA&&(3H zJwcN0Ol$aTwzzFGNtS2XL7(qod>Gd~DSUQ{xXlN0*0UyJD^}dmYr8XyTeEFDDYHJ? z)?q({iLrI8`L(U1?sZ#7#bIms^Ph^_K-&<-eAc*a&Qt9Bgjjwo(M!6~?mc;=Q|O}X zR2SThyc$NGv|QXVLbE^a%EQ@>dLG)QevTtulQ|~GA2BT#yQm+$T<(UrLvs@QvcudRD3$(G`qbJ0!;ZB(|-!zT#0&4Ekgcf*L%g40sLE066hK{V>nrG8c-VXB|OE9rdOX7 zX4Q?ch=q-I3VZM18j~s0?k+JLpjZPEc{u#SnZCXp zd~ZyC|DmPXih88Dr5HA73pBL5n*Ig870*KBCl`)+O_EAqQ?8Y?spN)MLa&9r*jSQz z67(o~5zU+=FpYZMyHe~=me6lySn~NVAb6tUYhvb2e@Cxak|A;VN872QZHvE=wf;9+#D~1oH!QYy|-@))NN`t?H$NxCf&5eTd=&_3Y+)#w+ z<3^uPQ)H*1NH;6el%`0xp~wI$Vo6hEz)<89Rs=`JDDsJ+$gn;((i9ms6ag2D@X@br zEN~2$%!}5(Nq*tPq7r3G&%7gOJzdp2A1l9`ri10rrII3ouyVn zY7I-}LTWZk{myhR z2%3uz(;Qsza017BiL$(ekURvrN;AI;RmL}q*qS8P9>0XkSVGOAQqXbzf*m%9#>P%i z`w9tvF=)GtmL1n6FAYFY$V;oIj|NZ+#<@SY{fPQUWcQawA&jZiB-q_qr|p;azMXB{ z>RUlwH9lL!uTk0!&R8g)NNA|N(l^K6ce5=+mi><1|NJu&s^ZSM!r(l3 zn@@vvkr)N@SYT%rm(+&il_tljj0%*_ z!A^8*iWtRCTfIHx{sHCP6SzqQ$01|z^-+G09r4y#4z!1G0~9+e>5O6bNMie0c(}Aa z{xAb~UJ2$}n|91WA8Va0&?={C0H!==Ov;zEebTAp7HC?QL;IEGpcFYhvt>H=E`<#t zA8?lbR*d`wHmNYZX4f^Cl*5kr^w(lVPSZK4ac}qyp?$x404)*nQSsd7KD->lGkR== z?lqc@-gwqNU9||#m*OL-eA_rxzgb}HD&9B?WFFjuuyYuunpZi0$aPZud$V{QXUsD) z@X!D#7>iG;h&7(wOrI=|SAFI^B0079d2u^>w7(%mkEqkALfc?J^AO(!iq+~)9(eF) zZ1j#+;N_yAhdAn)-;Fbtf#)tsEMtk0TjtdN079>)n(CJF$TO zC4)|1&(1edX8S?)Ipg;i^(VCTh8YJwZ>$-mAE)bBzvohBvfY}Ip&Ka73sLwES~*Is za4CgnOdMklx*@@wWJPJMm*`95ZRJPC??L(}3}%2A*ST=dq(o0-=nO=|$-&&b?R2#@ z1buP?HUv#|7@2;eijVJN9Qx-~CXwscg+W-pWc-9e`_IVklS%2f`1BfsKX=3C4dEvP zL2S;(GQ(c_`HQLx?p`jyAqcDX8P+>-B_Gz^O9hSliTNS@3#CbqS#uN7{6utCB5F=V zZ%afA6VWA{@pU3#rAv^TW)#2sh*O3YszQF-rKlIZ1^KTQzpQ@c%*;qWoc=P&Y z;Eg_nE*F3J-P>2op9-Bd_k8QRC;P3r-!x^LE{!{#m!CgZ(D?byl{kJTl0V^Z8u;_< zRsN*q&x=%%LIKc!dsli&}ijG_I7iQ~^Zmur8apZ9iIj#y*1qq%5>QK#>(PVC;>a13S|WC3$Ey#7&)8dTjSLh@+ldi`EGhm&Y&y-- z9sXXfpqhFmZ6-Z~-HrZ7&Sa_|hBuk6QQr@5%E(i8rSvyTzxL-+H%(4LxU;mE_(l~Y z;Q!RBeZC96{|;V@(4HO<|GL|>7n*{=Lay*#^VI>!Z3p}Dl6S8|dqaC!>bD=mtuELr z#UDN9)Lt2wH-Zh^s(&uU9z7=Rcn$M1mNUTBYuS%bHa$m)snCAuD0tJR0d{4xz5QKv zu}wQ!@Ji&Qso)c>#~Gh!x9#AoN*v}3k{Zd-gq zz9SA!rb>HT?s0;rsn_Xqhbyv1Moh{Kd+Gl*J5e-4S;@&Codxei&YGH!@4*L6B}6fQ zQ|otXA7E4tt-HcB;3NVijBuJ|WMGyNzM|lm6*ai|y}_S@{x}(=LyDhs4Hci$Y>n5> zF}WgVESqbk{vPP~=+LGm4(*)o*U2h&&5*ojo!ZGrZ>D7GcSQP3{0AOu=~49vD4;mJ zhx)Sexl@B^bfVwjNszbTCV@2S1^o~$octw+ehu1d!l+~1M000+r~@37WlX4FBuJ;S zMi}p#nJSVg0j`Us#P-^R`tOCP9&rLOf;gohGWk?B5t?D!eNR!8#Hv?xMBO_0V;nyL z3d#KQ&D%R@+@mvDcTs#T|d! zLD_*Fl4K~82l_{_F^XwJJy~l0fe+C9cHGo~M*y5Rc96U1RfIhs4ZfA^KLz{0q;l)Y z1CJB%DQHHfvd4`5y_ONpPSlEG_RshCI$|NFh@T{K$9W)W=j7|89-~~6)6H&UePfVG z4ko3K@UME5{x25kVUb-)C4R~xPbU@aWRYz&LJY7Op~UDqcBlvv_oo1`j~G4U;1BzJ zp*i?mg^(^tJ6UYxSgQNaz4dWdS_Emrh(OFULIB+?cy=;rJd^(L$eShzpywrAD+t(9 z!gN8%g)16DphPCj5Cr((oocbunSKFfr|( z=rED}okOp=g0cVeE)nioaer-^ZD1c z-4pd5o9Hl+^ZC{H_t)qBJ<;Lo+U_f5UIU!-X?!33jTN$K{aG{}Mn9EaQ-$RMX~(x| z8fV}h9=-o@p;k@hmt3A__OKtIW8|bOie-0chb}Ws>BP< zlO72FDO?!+J1-Fa1@ya$ZCPGBduH(dbX=N~8G{}xT(#Kl?YPJ#cnH28Zs z{LSdMR!A?a?B(!>>8~^m{7Wg|(}iDNAUu5ADWq{|>$!2@`#JpQGk(6R&@oRCmRLv| z;MCrC(Srdeh@L#76l`q2o&l zUkX3I8YW+kYOjV%4qpwEFXf2}`SAa?klX7C1l)>eZ9pc;KrlpN!A7|ON19|00c~mW zE3)8fbGhYK+1o4&-g;la-ypjin}S|o(A`ZU`TO?bFyCg+(`G)MI`DeiiY z;@v>1Z1%~`^Y3o-Xa z%3K=^qNaNkk1tri40{j5Ucm(BjjMGT_Ta_*OfeTz4KkwM-Jqf}^&W2s|HX9MT&0#J zx5K5VkX(x4Vp&9zmc>ODc5Mwotf-`@2(HD8EsI)1BytCh6cu5ZRaOLE1lQtqy?Z>< z-ya9w4V7DNxmzW<6(PAaTP1|F5Gt2-(^9dJ`)ncikkArYLW)?WLdKGbC=<%3T*g>) ziETFRV%z)o{{DWy$K&_=pk8&xp-3WoMQ>4v2#C-u#UoJst4st6%4B`dLexQ=Qk$)pXMKW%=Va z=56wGIs7CqO07=TJKU-|N8!cA3;K06r8~Mg+eS?8Y|hrjz?u>Mga7q-x2}idHh-l@ zTzi>$TqRe%>G+oXmuBW_{(b@S^*Ooeez|x29_%`Ht)W{XOx^TTp-wC8dGGebeX8Y0 zc*R|YcaQI$+AXKK<9p1tw9yz`s79>)lydm3z7Fde)5EfrsI*bmzsjJv!#`id%vAnW z&e*j5h_CB$_JM;>Yn$DbcD&8``%i$$UaR)i+*_Pe=im79G3!Qf(5~l#u){X#zvlwC z{l2}thxv8i-fOnJa$5t0~nujBz z1N?OEo0sSJCEZ=8j<5fDE|95XQ$G|Oa;Z6B4>MrYA^6`&^Qpo*o$H~kPBEni_&2XS zzAi&s_u$0(!!KOMU%YPndq?xZr>Ks%71gh{5gW{UPTc;zMY~@AUFiL`#^3FIA!*TO zdaec~W8Uvd@{>$AnvaL_@eWIg9*OJR0sd9a|p>3q$*p?$v^2F|(5 zO*fgPmt3t-c*yW4j%Phf&3G+WofNKHT0LLi7#}frGCH{HbH;hkH0?aMf>I@qJB*Xu z@xzC|8Qwf{;0RHEQ{Y#rtP_aD1@&+j_v&VepEpTIny{ zmuQ}$doygVXk-7uJ}a(T@Fjaq&YnN(6W{jB&pX_eSJ`}V#~i2B^2&tOfX>YQE}%Ki z;{3V1H5$&*Sbxv`Tjx!-Y7ehB%5;}=3Ef?IgQ|DkH9G#QjjvkwspIK-QGGjW^Y&5R ze}T9wwH++e`?ozkd)vj#{~XARA&YBCKjS3l;A_c5KAFf*1V$?sFPG$<3q_JTO7XO7z`Vk&BFjDuS{OO04ocqpwo~jNJJ0JT7o0q)}QgNp++L zwzfZvCQ}cl&>G9J4w9#tX{rvBb#F=6JZvY^;#zPY){$2KzFnxJ50(FZvvO;w=x0K} z69lYKf9yI(ypkEO`KxF>R}6% zeI6M(E>lveS!H{+zFJpA4QWfU+yLJy-v523Yp`R=5JSw*zM<#owI@rNr*|p89Uh$Fj{znX8<35H4L617{a}aMx04Xf&!rW6j!ZtNy726&JY1$i zxgB$IZ97KRlz`}r)&N|@oXVG&XOr*4J_e*%-pC-?x)@9u8Zy_hp=?>U9{caIw`3dJ zb&mTnQ$z}W204z?ldGr~Xse$Gk1S;P2)_o=_pGdMw4s*0ZOUp~dDi-k+1wa%fJ4 zKZVu%FP!Mo^vOuEQ&P<54(_k*#Ch|t!sIKd2D*CvVqay6*_VwNixe2z=O)H9q(ehw z`|G%5dv}b}7?0vrq-x^uSAc?$y6gx9)8wIy#Ay?#-BHHuFWpQm6 zuYMqhh<;GVa-C~Ff|C(w4mM|mtn6i6sgJ_RLPqwUqs8vq035q;bMM4eB>M(C+50eg z`$NRPJki}vtSUNuBTVSh8HpmDl1XkHA~3l>vt2QrVH)&y3dAm4HK5+;*dCyylf&AL zWxGtF>cq1z#Cz}A*Qd^;oubub*&w=wa_l2H#5;%xGy6#yu`L^Vvy=(PM|E0#Gs0%z zQu?CH9z56NEp{d~EAT?iDzN*~FcwRC4Xn+A>VfRf(R<>%9KJ)Vr*R)v$eX2#NwPf; zL)1K{n@D@?VW)rUvbAe4QU!uvmhV8n?)30O*KzhQB?5*q{L*i#C^LTLV_T}RI^;jI zIc1qSOswU$3SAbF#F5P_lTDz2T;MQT#TjjK$K5 zLVVf~S{7LyU-a`KN}UG5Jf>HD)YTxa2gQDoO?hd8TwhTmkem9I)BK;zj0>k@Dj|oU zP(c*%f>Xt`Co6C{jH$qfN6`JqO>`Anvt2&mQmMWeoA@+(+uI{B=BA#sN3JvD-_7e- z-({Ja-Ez0lzG5vJoD^}NMe;h@`U}6QXC=9Ho*niEcXKaOzLfUf1m{p-T#P+gc0TB( zFPFK>re=g#fVW&g6Yw%U!550p66qW2*Q1lRh&JpUcXS4<;=59(T8cKkz5Wqzad)9D zh4=y5x0YrXqQbcJQ7!kW)c0c(F=qjl#thbHjHYM?sWq@5A9Wk^R!UR>x(V%-`9Ru3 zRNtwIa5^se=H4)Y3{(bd9glyXf>^J!z@M|0d*2ORCt0VZKe2t$>1{4A^E)`ML7h2k z_Y^jT%7qJVuoDF@ePH+$VgSYpvl5|{|60LgTv76D@;el|Ug9$sD#hqxTIsZ|T5sXo z2qy38%D}K-qT})KokOd$NT*JQcqdbmGL>X1$)2(fnmzPkxwe!ukFd!x?wg5II_P<8 zfBblJk3KEg*#EzQ}JU>^~eoicLlv9I;Oxc3!t*eN9w1} zbht?Z3gT{!>K`wBi947B?<TUnjnP^~)}{ zOG|g0nc#5-5S2zeAOJm0XI%US@kVE0BTv{%{z_eHqOS%w4R*930~E2_1iQu~owi}@ zTV7^{%9idfq5g`i?OUcy)+LmP4AHvK>V2=BkIz!cBbeO?<hoF?RwUV{uR zW6jt)-!9vL`!Glor))7gfvPIce@vfo=$+cA02`mW9) zkG!Oe zAI>(IN>EFiQJQPc%vK(_ZvSof$-k6=MsdiXo=8KQMA99PR_HcuhC&kV#gc~E2`VDjajkpFFK~7|)=@%jqaE&^cq-bl zl{i>wzEJj^L}lQLBC^yhFP4_ft*=Pu6b!pRZJsMc2n~7%BaXDL z7&0o>b(kIMGww3hg&B6DHp|(sV<0E@wUBqhR}$8i1})vNvmy~gCK8UIctEP2aoufU7irmZhgW2+samqh6Wb7@RLjwODCQsO&Bc61+yLMa_ zJ~-8*i+S2vuL#qRwCIkBLzd$#WT@Segi^a@IcgVkLlh1DZW_oDOhI>zmauXWM{e%r zJ9Qky{QjF4naO>JdHqsZ;8R|3c>*h*=f=IyJNz4NTs zFHQE9-!JzGnf_# z7mi9%ucB8||8b%gq~5-ByYBRsE|a`%{elc`P`$PzN*5rl!EMsc;zvV6m)+-imlNER zKdl9a{AG-0y2OM*63I@ple14bahxB@j^OZh<+2_gIV)@6nbVe|rWNK*EsMV~7IIEBDxnTNj zXSnxY#aBMFcBR_-q3M1`8Wr!zHLu^itseJ8dH)X2nmF6Vdi-U^qinn1X-$OZCS+<} z;iaC2p8)|0GoOZw1H5Xocd(V{(T}TJK3ww{ngZG>0W?Fx7_?yzj=iXSa^+DCZO>2 zVQixv_DM@5<@Kk~quip&0kS1_N2SzA^62i}v0@ z0cr-%?LH`ec6sCGsB+WJaucwE^hy}MZFe9pu^tsT({ZlhX85ZH9VL5@nZa-4hrdME zx2LF}mwwnRp|2|4bG)_3LXE@fet*r>TmJ+9Bm(bW!Zu{%LB`PJQmtXIpX? z2E4WhjBGkjzoS-Edv|l}#}C1+hWGtqCKHy%haO$CgPbdS3!dnS)PjkM)g+JGywkE= z4;}_GW(DH!#ztJX0{Qn|z=No{hq$mm?@`L!%jBKf4{+C>t<+Ymlyw$7;t~6zmF2V? zZ+t?38OQ#4U6q*!H-$Th?ArH!=bdkuQ9OZWYmU~W%~uZ5ih}}umt#C|KfoO*)$eGN zNngMV90M({yoVcKik(VA->ux-@wRUFve)G7S?~M9@ZODt8@rgc{9SdLde56qx`(!w zu{;+@Hnn7hXkYK(KHU8bb0deu@jEJ)#2ImGzYq}H8@I-<3%gtkj{kvZb{vSE6J#5H zzU!`}bE_|_Q?jOig&cNu+_P#;Ik&6oq(jV{V2i)$#*3Z~M(~4l-_Hhd3#Ov&%+c{TI5qFiIX9YBjpt-G(g&d{VI50Cr(G`hYZk?U^x>?trV8A>Fc zo!Hzf_MBu9xonmxWA#g)V{>AR=er!q@&rlxP>4w|z#CA*j?4z%!GlCE1#m9a(K(F^rFoLdp@pGIo{~UO9bbFikIruRA ztjoa7D8+zBt*KmE@UmjksO4)cZ;dnVx28&lr zm&;Y%{i=P>)G7ey8lN@Ry(hgnop?83IEwWl)b&C_czp8irP`k@F@B86t5L*FGygH3 zR*%G#6u0$qQ@vapXM#1@`?XsSL`Qz8cgJxapZHMkX8D6L$#@dD@28)a=g)ZGw-#q| z8r+R?uWua=%|3s0MlJu)rGeu5mRrKptPNkCHc_qz;dsYBG}PlRKI+e?ehT(-Lx3|q(&Y2#-FMj6Bm;bTN3OMGN?Y&H>$ji80fP26BLlfcm z;rx`pzcuZK?@yYVWG7v2>)Y;A;8TZV;~08oOn&=p^NIts}!R!!Ek^ zdVg*tk+|RQ%wL0?Ka&gmI^qvL43Ei=OnfNB%h0O+TmLa^zH;) zg9e|Lmi|PS&u!h=VePWo2={AA_`Pqmu6@&{<}=r>*X5Y|c7#TTzJvM?_V(UB))#23 zE*ED!5gr(qI6$(EKX74Ob*BxYZOd;s(M#T(xn1W1>Y4QEwSE1seji0U%Gdhy|5l$L z=zd{4#OMt`aJSrwLaS$@Mq1W9r(Z8+ujr|_i)!+Q#)4z#d z@hT1VCk$uBeD{i6?77Eg<~#0BW%ED&eFHf2xU-!0R{vXv;5e%Y^-QlR+KJqgb`k0H z1`T=h@mndYRpiuv9}4lAb<)XO>OZ@G5U5L0pYBaRvBx|d^j!{)iV|2&9`nvMf)3?$5S8g2sGQ1{z`b&!Jjo`0Y-%jWFpK3g5 zN-T;;-RZk&)l*;4``rD?p1Ag`%}%v_b$f#oPpZ!6K$vN2?pUqr(Fb+cTMO_Wq$aoY8kcf|xyR}H~kZmfIRQzKi`_vT>GGoff|<#%Aa z|A^NrtEcS{ell_L(Zw}m>FT?)S2h&ZKYF^ASb=S)`_~qS#xS#xIbkN`4c8jRJ;n{@a7{l(fF5*x+ zQ;mEZ6Jg6kXp5F8=m=G;B_oMWzE4ekwi8iEb*3~IO7+wFrI(kuTAZ>h-1y!}6!8yd zwZTdNrQ`1bTj@*{T$+9J=#`tJkoUVk5vbW*-`gEK3AXBp{_Q*CaH~=`_JqP@lMAL* zPK6n@R-}wS)W-(#g%c}r!Oj)tL+2^cR>E7Aq=}1jENeQMnuU9(!qk)nLb@%fPWKzs z9V@o)o0(xR%F+-w>2HVrE;NTr#MqyJ|gzyfj4nw9Obh?7+%1enrmeGEc;M5=RkIwERG#|9BWLDINXB|10P)?6?OdC6;f z0`D6nJm*DM!Y2kb%_T?Yd^4ob8uE5gLWWeQhO8~B$&g}e$nqkM45=k$g4V0nQ7GuB z1~R~X_~&A?9+*omvy?atgQvV9M7|a8Qb~yD%h`+$pZOX>IeN}AAaULp>?^rqu-e0! z>hDlH|%mEnopi$D5Xf9 zS0Wct2_b(`lnL=(s;=-6W~*rhqy+G0qiI%saw+@;Eh4;Juw@oL&UScl31hJJICU{^ zteARb4zI%G_Is?vCESzju)J46^~G6Xe(EwJ0x*X0MHBSo-+#B~$&Dqd>AO=ow+>UFe$d=))F8u(eg(qf-6)8k z*qd#eL0vR6xFLUn6i(q*OmhppBe*BMI}}KswebXrqsvUfW{%$R#C+o(w!>GGIA~-X z0%nu10BqHuajF?D=t6L3BW(0-CHchs*il?jC9;wC_zCXkAi0t^QAxWv=N7Bv zK-4wf#*A@^WbUU*8}j%Kv{bKeT--#1DyT}p$JC?FiF1~y9O4&FpEQe zbN128GpYZ}xH;3V5TA$qemxe#5v74Oky(|H7rdc-vJEfP!&3NSH!PL+E(5!rBdjJ| zn$z57X)MX3$f=Nf*k@hKS$*hWHo9&StkOrL)>g{Fvb{pjz&9YuH zSViNNeG?lQlg==V0p^sD-_6OSOz`M`68qr)Zn;FAv*?`J$4Gx{FOqoa?`iLxCIrO#Tuvw zzf(Zzd|gsu!H>-wRk%}hd&zeMy4h^*yRe*oW_7fJ#4ke{K_~i@Q(xErR3XG{5(n0>@;QT%WE0wE$<7?KEc^(k zVX8X^jbFV>ho@NjlN{&?r#SDYaQ-AUfh;{jN|}jKC8#ikP2tq%2s^>wF`KVtYj?dX z+Tvdgc~%tcc49hE2O&f;!{PL$7kppGzK2QSA-_5E_Qu~FG zMJGe$GDS%(h4>`?_rIJ`)`a;aaNe2VSWUuRWRRhVh4An~9>L!?*c z;8x;hT@fpr8}INYj@0oajs!S?J%~9Oscp$Jx0qoVgADxrZrm42nl%B7@nBIM%!EFp zTZdQ}4=iDAA|v>yl7hSVX3?F58O|H`c_V6|J2gQ%FbKR9hmzjf?;qjD&nKTBar<2l zq_Irv3#-HUDp z>MZi9c_Ts`$W!P$@ZCBZc+N^1m~qtCV_1hospC1;pz>I{fRZacQa&aD4T$A9Q;4=D z5OedPoq;9Qw0%~nF%(@vv*xi(aoUy;P+Xq<9o~emqE__VAZ^Pe9nmr+fyCQ6kZ>r~ zp4o6h=-EDGX7Hu!gfk8Xs#dO|#3=))%8+gWWry9*`;|#qLpbe*5u(ADgBLPehgAHp z%V=O}r3NgWV;uXx`&7XntUm)Xgi>Y3l1~YH<6B|IUv&%cV@4DY0{v)Q9*b^E0z@a1gO`V1{AsOs25O zql56nps0`_Ic~)Y9wRN{F<1CLQ8WEc2kc-2myT08<>%+9r=+T=6uSB44j-5*uoskt z18F*mZZHy_M)fPUQ6h!$qLChXZWWWg}MY|e7N+-FKJz*@<{7v@-2Jlt+4J{6S}jhoxQ zW42IIv5~&2tRs3yNg#YGlLaoG?@a(cDW%0Z?d=!`!(Qd~&Ha1nNznipPqEq_gurCf+?avE%4l{R6dHod>MYn*;l(M~HJKvNrjU&Y)?K(g9OW#UYxx*o zn~sqtr`r>7G~YzwS{hPIw8!mELaYSNjho7DOPJsM_DGxIQ9|T65#;R9G2z`*>Up}9 zA2Qh3bC0@v#ne_jOc9b2N;}cUlR214qX8lCK=8d9?PxMdHjm72$`B|G5%tyobT;sH z21CXar8dHw`Mjem3$XbcmLP93c3b183PldP^?z zf}r`3Szp`{_xwKqHDXAk43&;!P_%U2oCJC7b(CK6`;vg z461q<-ZCq?O?<3;tfuR`H_*z4ALDp_EI5VPDfp5@-AI(9zC;aL>Z+slbo7w!uyI7h zX{q@XPA)Ryf3prYWcPqjs2e#z-R>8GEN)x0@~+s}Q9xheyD0@gH8Cqz9HFUy(2B1s ztel|3uw3I%4F`m+<@QYG6?!>g4W!^-7e%`xHS7kIq>t&korm;w87pzKs8~|&WZL#4j`<+1lqyWbczFfv@VLnbXP@~S>Vufq20_>Tx0x3ft@QBYqc_L zY6*iUsl`dbpFu_5jSsP*3qP}eU7!qKx{86eXMA4Mvp)c<2m(#__%7ywp=ju;D^ybp7M&Nr zU5f*K(ozl~>=($(;=WBGeafNW#G^?~($f^N6T@JUA(mb`+eIx=nw8`78R??y?&QHi znyYBh9ccv(furI{z%FNCZJHxh&d(Yp@82~E#5j}Fc^cL5@XMGAbJx#nBLxb{0ujT9 z4kdpHZk)wP_e!i?!&>~s66QKmq6qxQ*ONFw+I4XkOFZxgW-fbDds z#qu6lE)T6*5Cr#W#e@j%@G#i0ua-x)B89N@~PG4r!Ub{}zr4^PqVtlWGv)ZYU0j4Z|VY2cwJ0)iG| zU?u&lA1H&C`+1`#lC5*-9Zt;Y3qxGehoM0t7~Lw8stws`>n;T2%w2I~p*NnRI};3a zSCKM6b~Wv=6r~m?GOi?C7X-PAXx^=s+n5P|EGY?CLEj(_HODv5B(fYVLU5#^e(sac zTB6nrskJlkwh|dW2by_s9TC>Jdr=u~8iKqy*RLqa^{`yq90D#LDopGf{UCl3%bhAY z2D|z|8k8y>_ux3Poivd0lQwW3Gg;2GhOk9K0HN6@a+&yb>=$-o!To;;a9 zTCih)>*^4h4_steF2QJQ-0wl)*C23huB-s`qpV;d@R30RYED-{(v=}~cc!W0de4Zu zHq66o?}!qLsb)2Jrp16S#!A5Y!VETx%bNxej3#y1gz+(9@RS;842dne3F~q3N6%QW zh(dXe3k5h*&izFn5nz@PZO(&<~935_EB zoWku6af4B{#fJ2%Y}O9&KMY3Qy&(w(^Y(P2H6hT`pe9K7cVX|NZ9{wZG# zJgMfixPBW>f1X$!Wx1=pAEC(O-i;#em@LFZ>|aRAETksg#lX%Bpy*kqt>J*8tAUO? z98afRD_#So)#OclR^%-Cf|+o1STK~H%^_}pyK)F0GgVlWQB4X;&C(k-Hf`eu+KZkV zGzDw{eGJ@THo3XOm1EaAYTBV9)~Ab;E4@6(2BHR6F;az@fX*C3r*!-%-3c-j2e+xi z+qZ3F+9&D2s)`F{$s@Cy?{mjwq7nZuOZ2pU9I zT?^$`k$sO%(0mP~VzULe3Ho2+hWXL^h@JDnz*iTb{HW+kF_n9|_0XwhOd2he(sY;C zJqtXX=H}4D`HJ~8P>H+t&@mxbi|+F0AArfFoLSVA&24#jT>x6w+Jf*eSFvvj32n!z zORM|mC2RjZXI`pi{uAYTFS~XJrs2XUT>bghcC0NX);!Cy+3g4kkXEArX9dDc)*-@r zcBzM0T{?bbUhXJ7Q}DW)fDkLt<8)vMRdOLOkJ6?JoDj}_Vg}MftIBX8+fw{=kDPv3uunJ0-{ICu#Dcc}l$le3m7;fc3tKXqNx z-0cKMt;rZl1G2dZ)A}`d@eO~HuE5`LV2{gACX0VXqkB#7lse1ic*knMSH z%Nxx%{w0`xXpWf9Klw4ExTn9VS$X8LV(cUs1(iLD}|i&IkXz^UZEsEDS7@ z?I|ijXbMgk4UC!&mxTP8me;@w|LHj64nJtdY{9PsB@eU15LQz&5ir=B9x5uor zhCGobjU`v&CI`{GoRE-kLCij-Uy-16vN zyJakm+{JU)p}~rdHG4^%k(v5YO)jCgx(d~u$#*e9lhV7Sh8<2s<54q$s^G?Mh~4f7 zbm1q0Hf-NO_JcMR#(M|j5n?U$*6snuzg-ZEX83&T_-ohJnY<|G^C%dNPvPtIqHT_Ds~lNa^ICqjZuId4LU6 z(eE?i<}d~E;-jlDvI~qH5VRuBEhH$-3!p4~{+|R5kstXMiF$@%qX#R>ims?vkO(Ob z)PikHDve+?kbwQd22MqO;lefG-YchczoB%?S&5^cnHP?SkGQQkq+rTj3`F6tr;B`G zm!^i#3y?3wWnF+{x7w6vZ{`?7xvpafXJAWDr~t8MP-`vD{YZyKwFhak;MEp)dmhV0 zTM-OudG|AYv(QFBPcZ_9@z)ludeCksFoT_enjyQV@TL8{rDtxd{Z=r3xdD+?&&%Bg zOlL@s)lk!Ui$T#cqTg*vTDK_U$20T>SVT@pPg#>$-x( zzm6ylzs~1s%qNh$EGe0T@nKGe6(|*!D|Bp-Z^g^h7F8)qwq#&Ql?WZti;Rw+gH&rC zUQ1-IAW^iTk1-AoartcHk<3Ipa>GY)tV=S9y1L3)O0tX0=c=R;jj)?Iaf(taPBw*X z#Uty8-rLNqCVjm-%0kU4ALOMeNKQG!2L=gO<~$XWYbpsB<}42iY-PzYS1`DiBHlPL zu|hY>j&S-staWe-t%XsGtiZtnMAma<1Wi`cp~y+gCP*ZV@J9=l22LFb9+n(+YR<~_ zPSn?}+vnQJl5UD($v#51uz1|TY`N=gehc%;Oi-jg+QYZE-%e3>CoKHv(ts){^znZ^}%(e z*NZzW#YkJsq@Va4d#MkuDTSL!4kzUQli|S5f|$@GH}yHrK&Sb2XjHHDq%WT5{yA(75 zK0aq%>|$OqR4&kgnJW@B6$pQ#tHiqHwFbt^(*ALjO?-W>bB87ppW+GVWk?f>>6bbQ zJ0Uoj8`RRQLtktQsvGWjIhS2CM9l2yHo5?9q|rHo?1T6_qD#HZ&GaCe+Lz45z+;KH z_ROeSa|;gDKWHK81--0OQN1V5?SzaCMnUhLk3d?8fowv zjA&GIu4n9Y1@&+R*$7gBifuozU@0-n6={1I-5CFkP zfIu;%I(O`X0ZFD7LRJmP!zr+d8%P5JG6Y9PX5-#~9Qx49sUsR3AtB;_;U6*i1ju>H zN}-q)8;X(gL3jjS3{rjtJ~<7tfB?mS%lKb2kd`UlBpKq>^+axT)VoD25_`y&W!7yy0;*&QrQfF$wYK!U#jNy?PS zW#cCNI6|PU5}gzSa-a%w5EnCI+$1$NI18v1yack{egZkD|NmsBT)GPU07(oC^4s^o zfJ<3mgVAHj){8iL;VPWdDE@2n=W^)jU{a-r- z^v(atiFpNB_y0Q7xI5S2gGoM ztSA2;j3A&x1Y++0sTQCz;~YTg<7Zhc`Oka<+%6~9=yG&&@7gx%&H;`>D-0&}u4b|d z@@z1TMi5QZ5&Tq3Ay3L2VFSlF%uWP(XGh2vUHWPX2&wF&(5eM2YYgmQpX3u8_{^Ta zbqNX=e2xdLSDbs~$pe@OYaU-qWT%eXO8Vi|iEgE~Dr~e|dv*%9hf&G*;=p7mNh?t2 za(*PZFfcPgEVV33|AJsVT(H*{cAp7OUU&I;1;S{a2zwrk08@Z{j9=yl3)BByeY3j` z|L>YRMwStcsL=$Hv$^(5RXkM`2;82Tuj%MgkZkcFD~W8>ksCwm1ZM1Fy7@D5uwjreT(o_aK?j%abNo7NJQ!V&P>dxiQ6PW^O z=k)B%GZOr*LVm$c$@!JABczP@Bs#&j{of9NsWy!W7;4^0kSI!yRKp8-pm!^oaZ@EY zi!M+IRrWpGXpecdFXG=sV)o1v4Ux5%Ry%^{j6 z#+uWkNT|(%AVm1n*jbeRd{H$HF9^uKr+K@rV_r0kECWx*#O=I8&YlrJ^X^!WIo)Ie ztb-C0igB{A=Pt!K#fmZOKHLV@uvuT3VgBEr-jhnCehcqOZD_q$F)FQj(zb8yc7G}o zwEmU4m3RO$JWCx>K#4S94vehi zdC=B#*S0$Y;Hfh?2|uG_KEzv6IN1ElJcQgfMA({a=S=gQuYUsnJy>vBBpj?&kesL? zD~jY5C72rAHc`EzM70JfBYB*GEgd4JbzC2fPo_3{OWFn@H|FHbB>rUV>>xn2eh_zK4yfcM39 zjcP1Yq>9dD@A<_iv>S8eQ=;7eZLtBK^6U;5Fv_TlWp{ec%EBMFzybc|e0g=GQb%1_ zF|mtgbM-V-8Tx&1Uvy+=VT0fx)XfgD$br^xcxUi{k2mcgzJw@9pxu1@Y8u_)4fYh~ z-b;u&#B@=v+qhSBgtJSJc#7olGcRYfUv!FLtV=`xS^pXkRzB^_?R+pg( z)iq&=qLt@v31{+F;+}}9fQ#@_-bx@*skqiou^+ANi&cTftQkefW8eK%>Hg*M?@*OE zm6^7p`}+=~Io}kxQA|U&lZ`AWfTz*3Y?0G&JW%(ell8~!0u*Q^BxDOj!~_dLGKt>s zgA)^vvjNql=zMPC&cONc6?+R@9`OmV>lB_GoBfy@*XE6#)Db(kKk0A%WrCA@*i#r4 zB-Fpyhf}>#yAs(on>OiP(Qpd{?!etGF?APitr5NcLida#ewthDcU`n##rzdZn}P1N vOFjAgCPfx4>M(mOID>fNZ#g;m?#d`mR~*v9N8RV z?@lJkfN^^il(^?gIL4EI5=PmT>}Ho4GBIz~iI;Ui_KcjIIis~&cdYgZd!P*46V0o3 zbnZ@9tE|(ys#~pFs}8TWc1+?4GZ~Tzc)Exp2m+B6>|w}?ibDt{bKm#g>z|e4Cix$UIcAA3w@1VuKG5p4eSY^IC3+5T zw3E&N-4mdv0`#mmKUAZtgr4%fD!C-->VhIkf%)k`08n)Ux0q;Cdk66nG@vr70?za5Aw=zJ# zSVi}S=t!glVsZNbQj~V96#mHN}@&^S=Y2qc`~UalIi#= zLO-|m09u?yVz0(0QCLRDnk?gy(e)%d)*wFsqxv?Q@_|0-TO{Lm*WsN03X}jmx$p_D zP834M;a(CJq5xggi|<_|Q;kCby1UQGB=;#`X~^Ne8YwVi9P+!TNk*LO&{cxxlJ7mq z{^wxHzIx=7`rY3knH!yKTINQVxH1O2=u9_X2bP#F32rOIS{K)Iyy9AHx5f2*tNJCF zwrw}wGwg)Wl8F9&OUtO_D2Kq{tCj3}l+fP?=|{%RKox}gO)V#PCpU+>4~Bo2{iS55 zPht-_jaDY`k7>$i<98(XV;Ll@Y~4>%xtXQ_0nGb5*7$DstwCk;?*o}Zrn!S^JIANB z_CHOswV&Hu3#*4e$}JJ^KQhK9@D1l#Nr1?ks?^mmsi`_#6WQdhn6KUioc_kwi<{~D zdydM?0GHYjzhw9&eGYag@c%KpWTh!XH8)vw+;m7*cvj@IjAkfZ6=m30N zM|6$hUyme_&)&5_TvnbOpu0PelT}E7Y{}r7f(NCW?VGO`vP3gf1PIL#nl|Qq!5k%@ zPC#QdL(Emks8*mI!G{RL755ZsMLJ$20QP{67mitrR>Hyv6yEQ=b zzE!@Jt3sxH19XS6n@6&62jH67mcGaxjNRK#^y^7?UcJJExMlBJ+8J!jg^vX3c#!7J z*I<00Z8o7Z&F$6q*SHMiUGyHBK_K?h+8Jm9-b(|(82sZgM@hHNX2`dcr zGr_@txd{`qaFVf27gDX_8ne?E6Oc~r|KfXe#qZdeniXV@kMZTZT~PM_;dG05V=qmz zE+qKJ@L5LBcWVnB@~sNcH+(C7z!&^1uO?6JYD1rHOeVW9l;TuX_Jg{-zi?wWa}Z2*c{d zn7Kk4T@^kF&I_{mH}JJ-Z-|izbO1cAhdc*~t{#$toxejvcM)x9TF^3fa7o9XfPUtOF~>2SRhBRKR-=ar(9byznI0geGNJ`ra58RW>GGhJ*#xxT7FsZj9AUo0 zkB~k4>3@(jZ;{x~TtdJtQ&fcZ*PSPsB%7f4PuZi{9*DA@oh+245DGQM%P>Mykfj&J z884S7(J$kw9pcjFu^eBS`C2gcckO1TMn5C^Lef2|&NV$GPmXYXA;QZ|FTU53AZE-R zECLJRmH6iXo$Qw#W=hC{$drr_3Ibk&OXPc!YOwfo#FzjPM$HsM&|~{OjOrA-4$8-ZvAg7<7O6hB)x;g7!B9A1 z3CE^z3-ToUx|p=jll%$EV_s?n4X9^K3IV#muZ_(JWKzvG~^|FzRwe) zkl2%WRByOYp2hvf;Dim%c6&FzhagLX+_quX6&Gp?L0-Yt#VPSoGmICR>^@jR(hCfI z9I?~qXg=hc~QI5?gn3k@EB-SIg?9r0i=< zZ(1JIYtwD|CB9_~!nu}Zf8z`v^DX=7wD6ID?yF;Qgmiuy1OaruMdTr&8`O*N2innz z-bY|CobzR*0t)#k8|VH&fY{~NuV&n7CuNRN%r+P}16nWmox@cJ6xR~}<8b^jrd z**)_}tbJZk4@;zRuX>1yqLhB)87{uw6QbO*rAM4kqPK!6d0ixBRA7q7>RnbvW4YQD z7qsZP?bCqHT|{4WHAmZMfS!aU<{6d}qsj0O^34n7a0ttxUvoO$eYV%LiN4WgXtUVtewhs&XI~;; z>SZR8T6F1`@>+2*&NZhYhHDeLz; z8m|jiY9o`{$Oo_njLqvP+25*=l32X}Yl;DfTAgogxGH>Ken3{2=bIa3wed9vQ{F}* zsh6Q(Jv*5iw#laGsG$uf^UaH7#Xs27ys%@9WiJ)4u^Q|!5b~wea*(viizz=)DC zvTY37e#F&1*JYQpC+=_Ti!IJxZO)sz4*1b~7Gxc4g17X$YqO)1Q@&e?a{EaG0AXaJ zXGKGH*QC9F(MDCbEBgSBnS5QJeR0y_OFR0pXSAoiA^Xp4Owx9_v|}IVQx!^LkJ54i zs2)3_4cF&WveIJU({^pxn@>5|lQ(i~b8STXzzI*;TTn~)rhn|ChG(>|AYUM2wkU~U zm6`a68QX9+I;&z}&Q@}M&^~G~$E}dW=j?Y`hLBdrgpp1%ZZlD9&$ad}M^V)<{ zX&Ye9qSC(Os>XX<53^K-@lTI<@~l)mP@?Z`Xy?Wd>i~hJbH20K$LkXDGC&Iu(&)Qo zMvgh)ml=BJ_yr98fNAJ|g_ixqOQwXRjF<0~+4Hx-bo0Pn-n$sE z^WUhRR#-oK6Y3=H%MZy)_a~sQA@3q7`yJCSfH1Dh&YS8#aMf$Gilxu<_>a7IL4|q^ z5UvQ%fmDRMd-ZY_Gf+zZ{ssHk?B6<`1)(b@?FHFim-!D+b@ocje*jL=S$jTh1Ik(YaG*FdHJFhDwQXgp2l7LhIAe= zg+o#!l}aLxqYzt#K935LqEaQY0Z6IOdm-$)^jQm6I~rFz?{7z~g;x~ajF0Z=&GVoi*cam^S%yz$c!(_ULVALdSq>xZ`dIs_#Ob^xF_)lP08F_5;IhkZs~ zf>H^yF(;N_+{>klEwUXOc;B_ee~HXrRCtjo2|Y_=MUz(jbFyU;N%yl7Pr313OlgI} zI?Von3Yj5=qUe?aFFZsc19cKq_HJkH)v|mHeKqF+tBzu?j?l{U)Yn#a&FXlk(ZnkE z3znZS`h<;uSKuSET=eCkY!>?T929`c{Ta@KbYD9+!_3YelE{|9F=h|Pg<1!@li>qq z*Q%r+JrOc~QL=Y?y#$pyZ)dWJo`XR>c*xsk^>TQ7!x=WLwr6ezx7(5qXHb9a5R!ur z)nldoCdy=)F6%$p@Q+)LZNprNHw>^F!k{u3JrBQ;%??SuH1miTY)(EcpEmn8d_+1e zoi6Q12k0q&$Q8T4P6+g~7nG-yS7P3;1hlaVRcSMI#d;2DPl2BcaJBb6Cw+Nz%qE$N3YGxmrXMWfzVFT{)JmPBhadN3Yq0Z9Vvpikr41jvztlJmLSoIS zfjPU=CH6U4G*MB&@lE1^NW8pXfm4?={1a`%JW2G|xNw9ROYq7x*PRbHn1sp%_^w$q zE*6K$Ry{shv3@=zY{qvB#TF2olRLok9b+w4ko+sl{zI^s{XFNZ`kCeR9rzErx4%Xb znIEBVGD9Zxb#_t<{@LzDN&p{{~-eyk#TC0 z6XJa$>|dHK3|oJd$-{Aec{ouX4x@L{#t=w?$>TT*#wHIXvC{2`jK8dYKQew28^2}- zCVq#Y$DUyv9w0H*?EnU~RIRaC{OZA)X&q0Nj@sj0Rf+7jj9*m=k*#ja_-wp7O^=?P z%W^5HA75vyt$aopmaQLlvd%_R7zSFX;JXCYmSGA*?V|R!ztzoKZ|~-Lk|n^=eJ@mgS^KkeH)W}U(9;u0h?$-Kk9e4@ zjaRC3gouf*wNtV-E`!6V-yL=q&)&5@iJsJRApom<{}(UK4~M zAF~-hf)kB;YJLGa67$!T&aay?9}k=J>a?PN1e54B{YbGNhqi9^(fm3VoIY*Lp+vt0 z(;mJa?yJLhi9PF)|B~2A3+)s(_ zH01`xT_AR!dj+PxOoF1opCUz`B6Oy8$IoHgKPztgp`+*9cHdlF;R=g?F1KK8=`%rk z#{BV2ke*;t@zHA2e`At;0R(RH6;cNSqNOx%BJo3WEd;I?vKmMOD`GWvtKoshK2maf3 z-Jb?P4y8L>4xk8=2dmT*Ut9=3nO4kg*w1d5eGS!={sc!vgSzs(LMvRaVB1)N@Pn<# znTPlm-2AH7?k8p?5omm?7?4MGY52s{vck-}LitD0O*=&{QkG40#kbv2#OV+Zo^^fGCCh7-$8WmR zx4I27ozw@_zFRG@VG=2R1w>+3DnY%|r9^+vc-mM$OL^p76jSP0wI}b{8R&cISN!jX zu}#-Xxf{f}ds3Z2SP=a!1L_Q}uOJ;JXFBU+H_MQklGF(Y0cmTGFz`77ZLyg<^yWov z`Zq~xq&ir6dzCAouW%ANK$9@Jp2TWzA^K{_>uYxf^jln{@<&dBHSDqnABXGou#4{Y z(HW$1xB3gw|Io%R3b&Ka0Y0omH(Ife^E3Ydyvg2W_U%f{G!WZR7od6LMSiLsotzZk z0z-k=db6MwVY+t=k2RB}zjyVm494!PTgA@6F~57;xQ!7*;Y^4Qmf6mkVIBGx^LfI5 zUt-!UJzQG(sn=kQD}2I)TvDtRK?r&lq(x=VitLDKNMGmoYxGnL6n~9T(IA2RNlE+< zZO8WMRM^>xs27O?YKgmk5Mv2#`Y!gM=4>9dydx#OJi(Ad}hPQcgx zfv^2bsn`8T>-&viU;FkuBqE*1YGUJiN~f!@-mx{UAoZOz$1lkv4Ip-%Lw7 zQqz9?YU>3Q@7sVAknQMrq!o@%5?OQ}5&{qIJHq7N3f=9CT8d5b_qA_BkwN9X@b@+8 zdZVWiMwLEaoaL`!dAM--zhk+6f9Bxl(1_l())B$aJ4PJ*oaJ%ybF!jBW3x3TRcJRx6 zu9IJ%So!7V{F*du;+Gv?lYx)=157e8KnJj{OFJRXG70w?!G(6{y6RNb!DGvT$flIdCU)38m+UB@cr)RR?gEpL6m z>q=Cz`^Smw2yN^GeE&!dK0}R{3$WWVgzJ}c2d*>b!Qm7nn}MiijL>}3JIOk`l-Ez zTv{!WecB01|Eg+lgnGFbF}t8**v;-Q_|8EUPv%@D``=>-Br^OuQpefxv&%C0$?qk( zQ2;nV^*;apmaBd3p6jnl9EY;_J#zC7nH(l3Y2mcqn!fbqxYG#p@cy-XI6o-L2>Bo~ z?O=$cv2AmBRH#Xvq ze@F5kYMBa;74d%(8ocfS?}|$sA*WSQ*GuKgB9YoXm# z-q4M1^?X!$E3!xFV?z^Kn)4EI`9GS7$s;BrwB@b>_DAX_c)}5VW2qrw;NA)CPM1}_ zZ=BMDSIq8=aHeXcvOJMz$|Z-yy>He{Yjdwoi7x!mG*F08AoG+Ule_Rw*PeA1ywnP* zZO2{u8A@CfQKunZBquv+arF2$J_`S}e{*2A-uLjv$v1ONI5*xR?=F?qR)oMi(up71 z(}hVAuCDyP{b^eX^=3q2y--+CaCo*sx-w4Xxe^ni_&F4)TY&OLSt2XcjCa)9eqG)bG%X zLE*m0cqS38B86HBJbVw)12w3haM2sP)BKx4jtOTaFYtV>yVd1NOx5a)_BEZl^~K^4 zfw!o0D_HfIxjM#Ayt-lN@Gf-IveW_JuLEZFQM(n-3tCirqm9~WbCM+L^K@HLpN zp)9tqTbL-c6%=1gq1JQ`yWR@CJ_-sF{jPdsGM!s&8X93NLK`j*n46@yL{bmdrrU%~ z-*jnW4!EIoz}Wb{R0l{kjB)1h3jwdwi8W=4Nf0vWeRW#{k*WZw5g<4;{;MJ?2vUZ*=YBz(bU4jXd%B4F2H zxV{>q*r3SpM3u-G!a1vcX zl+-*wPX1pTu8Y5{D_Y@G;utY!sy&?^ze0V?& z0pEPP4b7C46rjqFm~J%QB?0qUA*;P`I=iDcFxBOHG*GLgn*Ff5CXWmxcUEo+)^a`j z@8%sRN{&R3Dd-rMn5(^*r(^lHczE|k&NxeF=E6MC{#df{KK<~ms2=SAtC3ncwUDrM z#q{Ke;ra>^oaJi|)^3L5^5%+oTvo5!T$xx85Dm-zf&4>FR%4gajjl?KRg*dtv0GNx z%t92u1QaH!imbPExE@Y7Q-||lZ3gYpwh-idatzpD`CS~Bw~O%~vF_b%>E2+$?p2BI zO~URq*N%$ry*zB8sCf6Ry~!r)*#U;PifJwyE)NIvkz1_eQ=bO(T>kYicYNtiPlm@v z9Al0AJ{(q_Z|I|`d8BD+W)Qap^*RH$qAoxQRl)>?d8&^Z)`_{@p^}^i~k`y1iSv)f$8uT`I3p&? z;N1~lBrT4T!6^BR-kM4E#mVENck2&r9c<{pwWKlg1w2RnqYA9EiqRnAyYY~fD~dlG z@y$D^_&O~N#fzRdbgit()?3fOkFHsWFF&GIjsm^o+cHzGd5xy6*kCEIA>9V2es-o@aXnh-$>$Oo z(9mdAr^}EWv@xyguO9PNbwgvw|H+!G#qbA?Pjuz63*=xQ7(W$nmv?xX-m;UM3Nc6m z@d7QdlZq=^>~)0onnPHmHN*c~ESe@)cb3I(*)W8xX}L|(uJbT5?k>z4o80cU%MBH( z%tdJT_|7nmv-@oZJ!w+Gp-^hgITAS-BBx0&2~}6lPtE9~?a&f6KY2a<;)(~5fOrW4 z1bR`=q|;r<**RaWOwT8k6e`ZkaqxnEiJ&tB?fh0Rf^sv9&O&v3pAf@(`22}lNo{R) z_5my{7Gq$sw8*S|V(J|MQXyB;B6VGLCGk{Ut$it0p?uCg03Cb#u!a`1S4x*{RKO_5dSH?kvg&{fMSdf`2JY z+m?R&p;J^g9Xg4Lu>8kx`W55&xOITx{iy*~B3%RzW%(89U+d)`=f&l_zeO&zcc=TO_Wkg)XstM5x~eTUU>>rw-pv-2y? zy7Mc_?)(Zz=Z9G5>FR7Dl=ssUuca%cD9GGTot+Smfnc=*L7sD^6K9DD zv|2Q3GLC+$4R{=ejg));A*9@!hm?Drq)-!Nl0}fZ6657ur=Dc#Wp}r}NB=W5zm<3T zd)6@m^uhAm5~3<^_m(WXx9M&H&3gGvr7UrZu@ma_Y%W0$kWOuxBK$$OXNYi!?UqfP zheN==dxb*!O>q#%<3Wc}yCz#fx>3;+R&jFBYy-$cjmSBnizSx0!F)MUKob#idBq{K z%rhoFmU|h$mrNznZ@ zHxE$%L&Rgt0i?ZK0*KXo4-3J&rjp~Rvj2s;W*%lK$_m)y4YinBwt!CFxUn%ikFRZ?L4@`| zVJ1tjeP+15xXag2_InPl_9m<&V*MC z>Tu0*kv{^J16*^Llwtw?L#uwc6t6{=JF?H}425YUV1P-5cxSUM(4<#do1->$8L{p) zcE1cEru$r_u4sjX?sIUEdEc1M$c4OT%m^PZ8{y*)gjwq5`CJL^;$~S=OUr(QQsvGm zWH40+OOV{W&%bS5SP!Slb=E$Hx44PFg?#P3Xk34~M5-ZKWmbf21$rLD0h^7}{o=wyvx;s5|gb%7Fm&TF*^oWoP8cyh05iCR_PX&Xs$O6^Txt{6iIIP#A-e^@8u$gXJ0fm<5J1j9>2;a z>EuW*F~K$&a_`8=k>SKH-BE`Ixm9wVWGIk$S-*;a9_@j@QM`-@lR=4`7LyEJ-G#Lb z_WHNA=P?NgY+nIi`(d$)lYJQ6EZrOe)n`0~FLt(&3U5MW6qSuV)Y(?L9dsLvA8rRg z2T2<{6Ao7q8G?R->z4(&Qw5QINx2H_Jr7O#RnsaP74CmAEm#f*6=>t`*H8PjQx+-`5Z~TzM|kZ zVM{HG>}D1plS6v@Q)AD?nH;Uvrc~Jb+IgZPOm<4iqhsLYBXy-cc>3|Rx3W2QMoJ#J z%#?%%BXGZBCrC_(s*um4>KsgniV>F7bvpYi-2J{^LH$_so94M$oAc6S(N1=|GoRq0 z1R%^V8$wZVGz|&tp@qG-Ov&hF@@4vX&g|rJI6`{TyUnlEdQiR=c;(dVm>Nn>{h5A{ zs8?Me%OvJi0a6rdG>{n7Z6MJGRqcQ(B-WrlMITc5Uz>oBPvE1XzC^Q3sV|@gt*Fm> z>Bm!5^dmKiezZ-75A~_3@c+vf6!J%gwO=MZ3i%yvN1mbW$P=_3QE5Ap#CGHfY?nTt z=Ak@oPQZ@g-)c0M?cMcTJR>$(!WHxp432?M=ToVzoVq+$*39!tQgeT}`E?m1=Z&ES16v6+VlX%^P?cqglu$(gRS=V=rhC z9#zxRY0(Z^29 zZKut+!fkzK1bFx{m0Al$_r+yEj0`1*JS~f0noAnC(TFGj+8D1(xHfdccMn#aDsZf`FAC*$m4=$2a#P^hor)Msw%2ZG`#H2PC<=x3$7%t_(ih1 z1y`MP*Qk-KI(fuxnevQRTD{vYGwZxNoNl85>WL{@Ls24t+&W{0fOTQH5CBZZbMmYa z%Zq~JiNUzT&~vyner2tVU9imB!|5mpnDj@;j&u;7sJmHTVixXEFO)jI(TvQ!y6Y*n;FSHXK8I)?T*5%eQ{tc1dI)K(U zZD&#G0;sqbYu^V<$MwpKrmw*O)!wKY^^zI%ApgD-Cno5#9qc-} zBS>2Ned$4Q&)2%QMZT@iWA-q2#;rNz#l#{ zrw|g+>PUR1O%1|weLpn0X21!PRpq*x_&$EW9YXX#S3t9kTR?rPssRgTH+NM4rRnuau*(d(J~s;-|2{-fNsEpKH?4f7xtBZ-=ai>)dY$&`^i!z)CIUGFNj z`Lo`NdM5ex7(^x{3T$JUz&1L7W!Ev)rStx|)Gx4{$*1NK0Mf%YCZy-ryaxY;g(5aN zE{)M4de7iIu)ufrvtqN|nCAbXS~0A2o?fc%!K( zi1-A7o`r@qbyM0`l~~CzGr7fT8ZCL4XKWMoY-<)Kht`@MXI){Dcc(*}R-?_)J`I{H z3WHlw9Nert;8x@Z_b9c3Pz_?^p2SUhxTY92H4^DELZo}t`gTTi_QzFfvm77;Rz#w9kS`OvyWep=~xqXSH0khH@@IbTqdJk?Qt@o7n?(+zL0R#o7iZr zRMmQ%l`0xdy1O1E)o`-U)NzSxkbg&4Y+W8*Ze0eQqF5`7uR2!!=4?Be+GkZFs=KKH zI0`t5$8+ve*gu~$a9{CSI50zCMf4Gzgkl1I=;@q%5;`C_y=2R7#VSnmfqsB$>_E6n zlseVWpPD1Wh8b=$Djb}CNbbZ0^6T|(99PVGaw37fbmf4j^BSC3a@ucH+b*;UIjXb- zP3CpXK#8$!F;N%1zh;+Ei*a(L`>f!Ewx|#Cp$X}O)ay`%%+-S z`y#&eHGYVapM>W=U>sZPQ2>-rFFO_~j}sCN(vuF-ERZSOE}L|)uZZ|H8O=XgjYfNq zBLf(X=9@uyP5EEabGCFKT}<*{CtP(H0kn#T5;vL~46YNshv_H`>&`wXI$d{g9Of6i z*TK8K9GFhnb~Gd$t%OOe@)iVacm!D^AO1x1B- zz#pm4iiUwqXp7-(OrJTFkoZmr!@^6Ot;rDDaA;Q=@Y9lZB@vkZV#V$^wjPsE^g`k7^W5CVR2ME?K#Gd_Os#J1q1Bc z545ko_AQ2e!fM!?O@@8KY}otw1^dac zsh{|sg#VJx9S3Xoz|6KfB`XdTfUpNbIJO-t(!^zG)Mrh`N$iHQm&=-+7{0gi% z^rhwb=5>DW65oOFa+^HPn0PjwVZ;PnN~B9q1(R|1nDFA^O+K{>8Vy*Nh{;c4zSknY zm@wFws3KysIE{P^z(-ecLX7-Aj&&9Z?2r%G|6$c*aa;uM7v+;T#?J}))@I6Opq^Bx z+mgzcghL)dviWpzTTJ+}F>#qZd}WP(Zi!H*kPn1?uaky@)enr1fU7^_QF$<5TDH9; zCbo0vxNXPS$}qf!VT5Mt2l55fNOyU8a>O5?5(m%z;|&9vV}(@VIVehb{rt2NInqBo zfi(?D@Kqhv9hRe-M-<`+7mL6_b|$`kwNK)V?QV>wG~p%LJ1%XlSXhjZ)5ivNYH#|R z6Q%pFB}#9FL=nFgQ68<3D0BrL(Vi)BA^ORZlNXNh)ws%Qwot^}-XNM~I&yoKSj>OOv#2*_aT9)PQ|zB+B`yc+3RG zj8x4&sB;E7_{cR{(zm+EWRNpE$lf9~EDyIz31?bSBkqP=h9o~$z|9xh+ z*g&Y#LbL5@2YRmkKwoq*YGI_ET&T2N8Ru9!&WMw7o@mqdF!GRVVf{&(Eu{ z+u*AB zG;iU&2j<2XEs5oV)zdiYRVVi(Ruk~`1eet=^HEy$ z*6^f}U^&qjTpC^6SSpAQd}QFbJw>@c~C z6=fS~k2MxOHtBnWYElY%tie&vo4aJ;vc*g8B7?j)zJLsKc=<4!Adry7Fl#M34eC2Z z>ju0>DLe^ojMDwf?p<`-;zdhBG_9(BV501M#7ptp;`8S&okq%dz$Az;6qh8;ieyi= zo-&YWGj)woQNBqR0@3T2o^>h4BNO^+Luy4Kb`5(FiPv@UpY%M$aq%ydNox@c5eRpO zO{L!u$dPp1FYm6b>^s`hq42#-bh;31Z6F(-=in7>`Ey6Gb{U?mIa~g5NrD`%AN!H#DP+& z@CNu9vAyUIoVD3(s}dge=CJ%;y;W=X$ru?>ZmJl5idlFoyxF=NIzOFR{;mwVT+uXY zVy_>TMlsoj;h*s}D(stNrq00EsNaJX0k3yrLiaE(v5@?$<`g@visKk79GS@lVaU{Q zj?z>}yWpH=0IJ`E2-tZFYQqt=_;>?qL0irZ4K?Jo}NVi)3%w*6ju44GF4`Bk5 zjAkTrC#G6-C%q`wmZ7|8GGiFD?+DQt*SkXPEyCL+u!^2&5A1JiO?eOaHhj`bc<%;K zyb4h`BG z;kI+>W;~F7>@ZY}<|^%Rs8!qr+B#Tft=}^(|0Jl|Z*P|1l4y?A#mOzowffh#Ft=c~ zcoi(45&+e3N`P{j$2xwFag|gzOV-N~VY7?C!$)C=pJLh$MHY(I@jZR5sjC z%at`;@(BDaKMEs$5CC%+M=n)_5hB*qs$Xct=i=T zM2-T)Qk`DGH^d{-I^C>)X-~p+MkWFe`Di-WfN32nB$kXxm|~)rzmOM!!z2%S7^$8N zHtD%tRq#nI`Z8bYGjyuSFhiS)kKe9k7Y2aZByJ(R1G$3PVz|TPEvUJhIL^J|tNll7 z8sy6eA^qtTdeAzC1EVoK+cDMc@kEPBE++HW8ZEZn6mO7js1U2=@Jwfx!*J1#AqW3s z_XE{lFbDO>?lFrT`ojPuH)o@%)E*8@S$GyB+wdcXb~*tpI$)N+r=-n%4NIPxi2y&7 zaIz+5TP22GKkYN^(5JE()Z0GI3xzDrw?o5DNxyI)Oa5hWJ*EcSr#0QN5h-aX92O5N zPvOeQ;g5K?keaHAn1Ro_^~k`2*Y8cLaAA=$K4ZH9{mCezj+ zI4Jl198!d4S(Ygq=D~N-S!sn+J<4PlO0AMrbjbJ%Lu}qLmR^f;x6A43f&p|HwkDAH zbvj@z;@8@nRSTzF>ir^bVCNuQC5p4Dv#F{epKp5;Al2LKhMIH?hNIggkc<~Q*c!EA zui%s}H8_$^(+zlsH3@^q;uE2-OR+DpSW$1PX4dF{BC5J_WvAOma|%zjqHsB*!^x2C z@NhB&Mz3Ipm(|30gGp336P7Q=4A!n*Lpwd2qx{7y9ez_=Xm%((qjj7jd}{lH)uhg5 zK>OhH%FSU0L?unZ)VpS^&@=Qa@8_qkJ0D&)$V^Ptypp+zQ-&l95wE`4J=nrgjvZ`)lA09(iOGA!Z zhpLa#ns)jqMmKSatRW+KhP7lX(_PyY-E|1B3fkma&lOsZ5Tp z4E!Lg{bM*IPCLq#B(Vwb!>EnCpl%QV9Yh?HXW%QbmZHN zqwLl?5>`yEJB)xXC*+z?L3C8QbV@QrMYGTzf zQXkFE`re*@cag3Vv!wyIX8yKXT>LV7ctQG((+O(2pLXjXFyBQZh* zCX^{z^NDU#g~s1tV+hcwf8pCAo{-LRslh3ECE|^8DP3TN z#(Z^U121)V3&FSwy5k`RRs4ztax0tz5qZ+{yaP$dZyAh_9!S0bgO2~* zK=Kb*GIAjKTPX1*pEIzZbeBQ@iV10~P6)Ijji3mS*orjxs&T>m+T#ihzf%2dk5mRP|sj@JhZf${C7WaMRB;0>AuSKK%+Jig|#SC zcxx7O88>0lMec9Kq{=%WN-1xJlwCIPr{QfY!J?gp4>)-m{`;u)G<;Bjcu%nzz^Q;~ z=nr~bflO)?zEN5|+cQl4IGh|HYWQhzN1gaIKlO;6+%0}PxvL?g)|0ax_c&`ZPBoCx z(tR+rMMK9C3OheFXcB{f(edZju+$g?87(0LJ5*9Gc(*3nnMucM-F)Y}r3}AdXAR#u z5Or-!jarL@9W^CA%OwnsNPHk18xa3l3rJG5iTd(Pd?RoTrR@&50Z~n z*XLh9tkPbVn>2XjBsgWfio_3XIaTV*@dog4G)#J=lC$10vQ*!XFY~PeE+L=a@%6q; zKfUYgg~a62(*|i!X3bDGOFWmNhwpD4y4G&6pYrMDesBIQIW8aR`h$3o{N0rhq{kgP zXSEMHU`aAUL7X8UYe zh23Tby8u3X(G*|XvI4R&bBU{^8y#PE%Mfq$l=oF!#OLspYcw6Kh38xzgPzP9w3(!T z(JWb)-5Xy zIW%MuE_eHS(NQ5KU@B42o^AqZnCe-K(np;~_-UmoDA_}CGy5I}vlidcXHxR@g0)e4 z*>OBH74lnFYa*HgzLYb?M8!f_{2y|rRU)Z_eB()-kUoXkI)@dk+!z~PpyO}~mz5wF zy%X{b$geGcd;uYSH`%Us8N?DqLZ@rns({ju644ugq978CA^StGl zV1iH?lHaSdF*D5f8!#tZ>?L?9V~w-?3`-el{8DHUux_zgIg%771$*}=#>!YVIZ>tx zo6@TsdilxB_n0(BzTRXmf3zXJ9Yv9u3MzrTjqZSSeNdpeu)h}7-exUS?HzWdz?Dl{ zdOfRLfhZF}9qr8b6a*o4ah2ayA^DMmonlfJRs-ynoIUp%uIa{s5xxOBpdMFtMtJpZ z&gnj1cQ^OgDU4UW`Fg@IlCr(S;NBy=tv}V&TlcFz6wtMpYSZF)`GS-ym+d*|jHhaH z79KouiesV-$equy9kAjH(`L9MG`b&dezZ(Yl5v*J+ZsfkR69~G4mG#Osz=1*Cuz*a ztMe;0FFD#(=#`~DR%FAE5EnboQ5s5-S)Arzb<-#?a$*}L6LS2{|7Y)MgQKdl>`p>} zfHq=OtVMWeQU)bp5M4!(G$hbjgCGG!QQy3DzfRuJ>DTk#>xAq$yI~_WG^tp%RXba? zHCwg&W2{6}bV^ zRqQsu9zg>PFVKpTfGAJZArohoWmoN9@-ofC_<;q8D$MVtHTT8j@IxqPW)E?)}c^3BO|`O4(E zoI|<%ze#fWQOR6>6vpM}ljX9=TC@wmT;;HN_BYoo-Sg^${kXN^P^As2ZP0S2AA9{d z#x*SN&`ciF|5JpESTW12n7?<%)LSt>bH?0m#k}l{S!%_+?u=Pt#eC|Fxg+9KfWzrf z1+#P1DIfH3;?ZCZoY+rZbnnZedY1O#x}j8NJ}V?!G%hi{Fz$=M9y)9|MPf6DQv z4DWc`6m1xBJ3>wLAF1OT7k`4f*;*+}6fUupZ0(NFg>Lx@6X==m47o=QPm8@w{PWEl zXsX%Vgr@?U3QaZDWC7#YgyrJ=5OuCpK@X%J!lTpdw&B95gBaKUN?&0V?}ws+Zy&58 zfjKj%*orer5a%fmVl|8no#mmIXy^=Q=tUYj-5Gj;hF01_(LGgloPUukL#-%a7^2S6 zs4`nrZ0Je0hSP9{hXF4a39~H4dBP;C39D*w%EopJSubvBdbp+VW_)`~;lJYBHWrS? zw{9fzE_{M65fg8`$ z8=AFmU1e-&q-n4(Gu=eqFfzEE+tvHprp1O{dnh*aK(xua2M)i>@TcM-;_{xiHvz|o zadLI;qdP~5b4xoz-!Flox1yAx^XJJ$3)jZ`KEJPLIbJ*$jrX0qujkgL{X5Izedp)( z+|;x`Ssw4ZP}y^BNYoDJQI>9b(GnOOP+m~qIo4Y)K>W~ zH^zpZKXW=ZbYxYu@al~df7AcL?EYgFpH1w2EuR2Vj>h}X-V}TKy8zxvGWjQ#3Bmr& zXq=pUGxM}EW49TfJV%?$3yH$>`};`Sx#ws%Js1q=U&JgLMz+xN4uO>KAjlpiE0c}; zzg^kbH}P!uGR}9ABMKJZ<2nGPy36}drQ%yAUTBUDjY4~W8AyAhF?Nt#XgBu3=P&{s zngw#1#?Zuu)>Sf8?ux-GQp1S7h8(fgkUDm$GAHxp5HcG^9QUce?vY5)gy`$O{QfcS zh5VHdwB0Tk-bfnN+YmW$7Y2Ot433rXx|#kpSUG!5DgUM~3Xg5!I|Mgs(%e--n!Cf(v^5d85>D0YY;nx0SywTNCh2e>27n=w( z?dIbk&ml3Lk77te9Uo(Fz7!{N59P zb{}*%E9SQrK4Y{Eu8aP|^t{kA5G#B%xa}N6diYW~=#l>c@e?cs=i;2Q333gKI;6-!ZmDtQ?w4t;WK^ivy8=YRJa4CxdW=*0oS?% z=DGu};{oF}%}_7?Hd4HNO>etko=3qvCk`++4z%KxzVD)I3Ecl@-k<5Iv*;UQ4sj4+ zuGCc1qQJ^;vd8@EI2Z^wv=vbm!%R3U*MZ9a3y6 zonA-#_Gc3l!ykFLFO0?uBQ`VBX(3V2A0X)2%K}vpw9I4XlmKc@{`;N$b{mTo4adhl zm*LVAN$-=BcjltZzea;+=zXu$rC4qmUN9LfYy7d)4c}_V5_H6SeCFZz79Kvou>ZXe zvai1bHS#0fGbKNQ0GT1ZE8FJt(pVc;9!Mk2SfjKue)%(u6ukX9O}2H&c|JkOTv~KvAbgV zg#29{3CY0Rg-bn%l%MAwM8=-D==OnfF{DgfK2W9=)w}$h;8o<7Zz2w1Jk6$Nm_D=) zWj!^Le{(!B_WI|Hrqx#IT8e&NP=(m`Q7Hp z?Eo`07v_A$HgYP4WYb360kTAhg7G&5iPrjOb96V_(RlLU_M;lpv2QvqAdk)M0XeyQ%2 ztpl^kkP~Q46h3SiVJ^IU1_|tb6Orf)8s##Xp8 zWD$b-GlPao4r9K;%K30>^mM%ccTqMTp?63nZYLl8=c2Lin)&ciKM=MfYMMkoO7xJa z13|eou!F6S1(Rp#%#-L*YV2+97%#`z9EOVe=LD-g8)n_g9)rx)nVG9qN{EEUV`F!L zJ!+BfvNes8mZ9?NdHUU<(?7ft?v8q>PT9y9CA-6^9KRE`wxwOL+a-HK=OutaVt^&~ z{Fclk6+Zanhwzg)24nZL*pZh-jTv6lttLu4~#Uz zmSfl$DY56sSw^6bXKYu~=a~M?EW?&bC_w6UhcmW&_HVj`K>whP@&+GESs&C%K6~D2~EdB!IABzx@VNO4Ks}(E$8q4u6@)Uj+VA$6xN?FZb}5M*foE zFPr(x4)QXvErpXUg)y4|$R%e2o2tXEG0mPk%hvIhSW4XHgNyYkcI4n;R)O_X=b$!=MM^fHi_ z12hC*u~_e8!v{Z7#^@AvDXSRDpUPsgE0s~QvM-!P|CK<4@t#X6qLfOBx{~e4$YQ&u zq&no__>|nOByI7}y>;qfNEU(5L}X&3J1=Pl6m6HMsDtV=9V^VV;jd(WpRb2+*TwHTozwiB0c!v4$aBXe_)d7(F@~B_I*G5 zAM~Is(UF9k-(n9=p5N@k|3~b5f$g0?BR=@+ir|0Vh9Bpq+aty2f=6xm``G_`i=;o| zlfKw!h62u4ELWw}?JbR9)=sNlH0K8W!B8 zX2lL%H0YGIE-7QdyW+dmj3IT%dQf~?%Icz)>k5kROr=Czk;r8vy0qhp&*^zlHzXsk z`@<*mnkHwh?%+#%_AQA-?rET9_$esOHJ})9L(J2l$o`_*is#|{?^HjUk;H|>-MwO7 z$ts2@O*Noh;_IO`#7rdc#$wB#dIN}%1U$_ANk)LAp=d)N_#gwA& z5;Jm27n6o&tDcc`KAUWNEJ)cg?{_E79$1^$hhZEp=E@Pta_d>_-<@vqH z2{|y?>h#5eWC*pn+iNrVWwm*s zZq=&V++sdw=D^pSy;5|({NUK0{D_9CX4=)=z)Ww#xZ07GLUR?`9)=|YNREu}%Uf<1>+UPidKb!{zztZAyIS9$R-TC{fC zhDD1&VuHLo2PF%c5r~W|r9n;|sv+oVmuz$*nQ}&#&2n|{zXi8FVG=r-BBV97OXyT} zqc-JRueNGRM~6%Vh2&$~}(sNj00LB~vdz zc7j9-XNjP6WL1>F<>NuawKyJ|oDr4SynUcevctzo zwe$s*1l*J+%OH6*mjkMjozMt`9>wScwAp%64oGxLLF`MR>~FjVUfnO70~Dv*fvo@6zaJZ4*s)Pw6#dADT9>OU4K7Cpy;INb*WoU zEfrb}p+|z2ui#)G>I>%2umcGoeZ{y{hk|O)cPtgQg05kMZWl%;Yc9Qjn^K+PfW~Ks zaLOUKUZ~4y3cwh>Al}7-o^RKan$k{NE$XRmpg^w*gM;Cs1xeJA4c3QFI<%lIQ{b(- zs))YiX;1=E232#fz(*)D)(d;Npzy3RMxk>MR^C0Ga@K*>LWT7XR4{ACy3i%{n$YdC zBTsMrcI3-SpMrukq5YFFp(A4|BgjMZYY_IptkF>*3B|xJk?Y6MRX2{HVF=p zlQoQWOUmqeC_#?;W2-yZ{-9`jg}OD17Q5SzL!MSveiHTT*Ho&$Wb;MTd%N1z4EAo0 zd^TXGE0Nk^Xi`^B#SPj%a%Aa{bu$@N0PBe^pw=3`t`z+A`Fc&3F_TT(+bqkDrTe1o zMgQ_*0Nqk5rLn}cFLBBp6)K4ma)u@Z>iJFW26S@B5#ZfL@Il)3%YxEBtSK%bLywpu zBIJ3v^cdI%Xhzx5`{-qk*X$$QSlx8n`ZZ+Ir%Ma2homwgehbvMHu&mgv;WX}=i#8a zs;E98Cn8cVF2O>?0xz}xlk*ceK5^7bHJ^piM6WJdrz?a;B0Xl`?SgPHZ2w0uhWl2kRy6Z95f15zifE!ZE0%J+&l(MM|XcWvDWCm>^Nv#Ly zR47%cm6V!{s>{gQ67s3$K`Y;M+heqlo8BA7{ByW<= zk6%l^X@vq3Yf~VAKJ|>*P2|iBF^>hu!5I-7HItKXKWOV`lGJ)4)g0{((C0u0{`Pb# z(AP>(1PUFFdfUxrB!HNFtdJrhF|?Up~z7 zG6T-$yV_-KC1weoQ7X_bYGdgkoy{y_ttka2PCd{7@x*R{VP6s?RR`wfn#KO@#7;bK z#n7^Ab2_uEkv6pl@$s-mPM^OXv0*I2f15-6ST)k51}elzTeB#roweEMwOW&@i0Z+j zCe|OdwJo{0%g>iyX2#~cnvjK61@-IZ*)4XM%hR8)#r}d?2_zFO|Nrg12Ygk<);@eF zDq;aa5JB|NG?YLJU64Q$iUJ8qXri8kY7!gefqPu9CX zq9yk3)yqdgyd^Fvv4w<$nNGULSykk9bdxHJ8cZL)?cdYR`|1_)Y0`p%ITx|8fiUr^ z$4D!neDZOF3$53}u{Y(ka+2vP3D+Q&nP3KeTN_$5*T1Be%Z&k9kJ6_*(3{^yGyQEP zrOnifJDy&D*F2oGC|WnBX@4v5+q}OU+`iiy9dnr80JvDy%i52q8z6bU=vMSM1pfZ6 znO89_d7p{~(P0hrGuF-4IajXcbRqJpN;A3Vx%3QpIWVh%OkB)-RWxyz{IztLK7BaJ zW34Om?pOD$5F^oeP2411rVaEOAWBv9^^6;>L?}Z{|0zh{Of&W|MT(`+Jw+|)5u_uZ zItg)4t~;01H@N&I(x3Q(jX~3SJ~93?Wh-Xe7FI_!sn-(xHuDk{ax9!g_g>#-+8Lhy zsW}Cd_NLpT+q|(oakrGWTX2&EbAJ)-1d@AubYlW&%Uo#4;FYN zQQIZ*x?H8TW;U>FKWa;bKC)Sfj-$}*Qm0mV@xjG)cDM8Tv}cms|$;Jf(`uRecy#B4_dq^?(zH3>krmflvEvL`x)^*it!2dn5Q#V zx8r=KMRz=N>+39$oe``m_687+*zlPzBxUreF*k{EZtE)BcDqT5rtvVZMVG|K{qecE zCLwO-`GOhN7R7J_Glt}_TN_eI!_%hyYIi?V;Wm%2ii*vuOxM?^kx*iS#|pAx7+~*g z-&onX*inA^IyvD}AI44KxS!^+jZxOju?3kEBl!hm3$i1bIa4N0ozSFyXfp3@1s!Of z6fB6BD>K%!s+z_}`+hAw*NNYTavW>tZ7(0O27F2 zxas+`ca)*IahJ8F06V^D35~Ys5s!CKAEn21N^qs0#Qa++8@U(JqZBq*@0cb}nvoq> z6w~9~B!A5p_4zq$jW9@VjbQupe`oz@mTWmra!G-3LrSeZ$%JuDQEgGByQ}7UqrUm3 z4skQv^UH0+Cg%%~KyMTUhPvvJ0rPZ${U}q5**<1q-+6oeW;it6#NtS-%TX&J+ns8*3OI|FrTJYySXxaue_?n8*#*JN2O?i7aKb*V8*G&B4*}Ag8SiF z?)zT4M_Xy0wfm#A%Ka8SC$H^ZAmb7^Kjac+T0lGWaZ_RTr)_#_zr;_9_it=gR$jlR zKSBK#lutY5>;~xzSor4H`7y6t%#Bu5FFev@qL#3~p})rCI@ZoLK$fk7co}P6SWrI6 zd^aS`WV-iplycq2WA>Oa%Mc=lAbt~JCdh=-bZNcMWc}JSJuuvUQnp{ucw$|XiY%?H zuc#}J-wMv@z%1`hSyWx`Wl>QTeJQ?Wj_(_IVJ4~Xn5OMoRUTL&zCp<58b&K*@H6-edfbY65&?t9$Zu9d> zC3a<*dHhsS5iK@#PNnM-4)8y=)V}XVwu!Iz2&^xu{N}m-p7+)1WAh4Z1jBvm?T`dj zNvyuc1SA%&ud!`ueQ-azELv=PnB}E`@pE|)5XMAL**`wcn`Z3o-RwH}qYrV!2`H#u z^}ZL5l@-|@q8&dObF+@V+-sstH%Fz}4o^*Wd92#&UE7>iSuqI%zTu)r8cG&9~ks}hU#Zi3(3!$%TLO| z{P6g^oGIb4;jBsH$7kndPc2{>87=us`6$YDILWNkig-5&-5q_yUZk7(wA8DNVr8D! z7<+=QK2NgkpW9%Lh5%ko+RS`9p0CsTZpNgx-pdV|9Z62qUd2T<-T>bB44_H6 zOh% z25)9b5r1lK6B?_ltuHpgiEa1!w=JjcTXkhdZD1T-`0T0)N{eyE)1cIIO#;6oaWlb( zpFvv0wwtc%nxJF_qzhda;Xp6fDADG^^y_$ilsC((-p1$H*@9AU4CM76-LoXGrzz{P z9UA}Jp^Jwsa=gjziHtV}$EeFDC|HW%TGpE~3{ac`=SIOsb)$_bD%jEpLuw4n#)QwpHP_}4{c7M9>Px+6( zACz8=$<18F2ZY*l9TR3Y|7V}O$+db-%AK<2GTG*$t>L_(k6qUsf9&ja;EEP`KI^>! zennzszgrP3@AK`iyR;MAu7_-v#rqbDhV633rY-{d&#vA!)5v@wsaGLWP3>w^w?Hz! zVie&o;t$T%^^jI^`~i!2YNm}3W|^jbkas^*3C*xCKcH^073x7=%i&#=VKT!!U23vk zGAkNy16b?nYY6^YJ0k1JC~sqe=$m`aPR(_BwP~nLD{Y3)iF{M~#ZA7}^szdg5ycm= zvN&PFFt|Pl<_}!yf+h|w;`cy;_wSsqrulWYn{NE=QF~>}E}I@rbm+G;j~cIr*z*9R zvPr@9>A|<+y)0U);N2qTRVtIMbOT_vAh^Gi*IeoFWoq;7f?7_RPMJ&EX4bWfy3Uq! zS4%W;MYSGvz|Et*x@eR2GJWE+Xn38ezN#czTjAEf!K)4Y_Up$T&A6a^W6`j!Mo?aD z?|lwa;d`QwsgKr2OX8!3CiA=YC1$(Griz*Jd9SpI3giC%?4r(Gj^KvLoLw*n#i+*F&hS!*<#Q zN}R84(D|FT4%&0h_^fhme2&abkCg;Yk5yNh^^&q(iqDsN0f|32O>~cW$@YD3YNDMe zsdjw~&Jc^%1-EPT{C@lH#JD!*m#W!0V3m*WKRgVYjz{eNIh{P_lc3 zS7COjsx@8sDp$;6UdGz@KCM|Ze$dZ?2RqZ@4N9u*i*URLQC({xRv)E^}c5r8FaQ^@yAimD5sLns$4J>a>83W6SGdnO~34aq;f$Pw!X;f);+HY|4 z^8xWOwkf{b=6`Tcgtcdwmk8a!UTvGUI2GGkJf zZ%w$1V%SVG4sP&j!Elk87++9cZJ)2wy0TKYSlO(NN4K!p^D)mxc46ZC0p-~Eqm>&Y zeP&|Z^1rMrw;5gBZp!!xwmwNT=KoXUqk1+zsw^sw&51u}<#CxZHq*XY5O8n#%7rcO z(K`2V+!g@y&G?%`<^?0Ko8gu@+Nl*6uCnSXQ+p3=(mx(&(p(uWDK84!{hD&7cw_Y< zH-|4m(d_poVQ3 zzA4^LeKRO^P+F69uv8CJ7B!St)>pa?gIDg1-f&j+6jzCOqurjt{e}37uJ}SQ*L=m_+X)`uklwgZ*`7_d>&)D6Mm)zD z;1SG^R>ek(bxdeyYt58fWi;Y0^qkBez3~z;k%T?U5B`o`%^! z5=~VyZqn)b%&Pw=g?ZTwOWWHEn&0G4~t8gltZJ zV!UKe=<+()*ayMP7n@ia0j8dDcbVBZ!;Y+)%sVxoe#4OL?$ewpLG_f$cieMkF^-wf z#H&~dg)B<0iZChaJJ6){pxXEz4d(rC8&t2ZHe0*YmYV^u*MVjl;$Jpvl&Y&@USm}o zj(M>ura@k?FW0EpcS+p~a@93aH`zO|ZBV|7!2L(r8a!??@1@jZ&fn77NGF@MLN_3qoG zUYHv1XWA+#S|U5DJ>#>)iMqneWcz3;pg%sf+SdVaGw-~XG0VrSa8z>x2M)BC=E+^u zzAsQ2)Shlvr|AomQm?@;vb|b!4<~xkzMct!lEnI}>Av>U%n#F-J>Eou{ryaLIGTO7 z;aZC@T8n|f`_R}A!#GpT)c2kouY(cAE2Of1ZE8P$?4-%rS^9dEn(CT*Gi56D^hngN zzHz9}DE{Rp?**Fu76KY*yECOJZfu=tbNuF6OThj~<|U0mw4e8&_`cQ=(=iKPKkWTV ztd1^9)FDlFEox@nSEAyveL1^_j@wJz^zBPV_o=s)fp<%rKNm!+O1z=JEv&W$9*tI7 zd4J#Qa+X(`d~o}4#dqhTY2}KFlD=*XVb}4Pm%Ol%Ph~*+iS@!|=J_t$=j#NIranBS ze4NS@PCCTv^Y@kWK;u{=T^X1RCZ#&z+E2!Rw9=n5zc{q~HpKyj3cw-6kFn>@ry-QhNW#0}-ybYy1 z$MJ$`dKV>(zP!10>1=-i`{qD=lN$9k;q5*bfnvGcj;a^i;p^YyeI_)PgTYJsVsQU*78 zqYnIah}q~Wx*&pEI5B_SblhR?YtRJ}*?y8)Wnyps#14Re!R!B6ee?HLE=v6pm{8Jc zcEbtyylqf9&&A|X1xqRm#XPgB5C!zF-PcWbs@nd(Qo(novd&<;ceMV!;F?Q)Ufm~V zW7BN^+B`R{j@nmBG2ZbFq15$dMv4u%+aa%+Z4<=&iN60BX>DeGhA%}srYj&nRXuY5 zF6T>a&&()GoHEj6pAT0r@J5sG5SeVBAJ|Ys^X%`>Uy&%&A$8? z?`o;tC~aMzH$r6P32P4Q7MldQ;KkoG_G%Y%pWCsexxJFvMx``OTVAI<_q1O#Jpi!V z4Swnpz1ybGaj+kYTh8DLBTbjR@%s^kh zM;#Qm1V0Z&5B7c!6}KpjyqbTH*+=H=`8=EdeYXU;+kvCVEQ>Nr>*6KQEz(6-Uh(w$vGyhUnrb_!bz|7Xc+*DI>$hbzjx z!dR53G<^@K{riz5_8-(r@ZUO*jdcmh^)>39yS?{}+4r`;FGpg%wb|xauTL^*R!gm> z0^h&Ki)ySsOw@(yyc^Y=b{klGzqq@_RL12oR&4Ei-u1OLwdJvBLVpxp?r6yv-4E@b z9A7wR3V7mnbjwZ?o?^aMz;2ak)}5En^;*+~wbf1Auc>yCglS>j%cHh6%$`wTAE5c4 zpzmkb~5#&cQu;z-xn*f+Z49q0w+xMk!xDz1l?LGs-xs0^7U z>$P@!V;lQK2<`e?*Fd^GmguRFX%ZGxo3|jVW3h76ES3~iqQ!4+pM(E8aZTdA9YQ|j zN$m4(3Ic86O_^*r{l?=J`>c!Zp~TmyRC;|eUOa;Og}ffAsi=2R<)t~Xy4FqEnGQ!4 zrMM_@>VUkz83i%Bp-5D|qW1sFcylUyF1DlN&cCz%bzh9H!WNTkt{mVIU2qL8cKp!B z4S)A|S&i#omwK z)1y)T&HvT>9Ouu&fZO7~&JV0&7?e2XG~hkdY?|6MIJKE=A@|+N5{TtcFr*5c%&HihL!X2j63G(_WJUpo9v%V@5TAF*%tv9 z4)Rk6r;84gO%ibnA8ei$;;Vh#KqG#fB108LA>5YPG%+?BKeVZ9-8qP^s*;5N970hm?9igQ4`(SY)OHOuUWMovpaRf`i8Si8cf7} zY01i-F)1^9fITEgTOaOI>mCo+ntrD%h}7mL^YXDn-|tsd-LDCW*So9px<|GTXSzM6 z2OQmz`)o(DsM-04#En{ATI%*I^G1~ZdNwdRSTtCgx@5Pt2K|m7hpbbLl}I#lO{Dl6D|H zZq-y!zu-Si&y2B?r)TH;@9gcT$9+q^e|EGzHucWHi>gYt+XVZ@)rt3g zOwHr&$?U0P$4$;QgROXnyhqdLAinlB?z@>Lw)uUsZJ)iW+INtZYZ3a!7lwIVD(kfw zz6qu}^tuXWOmEm~V)5NH0_~X>RIaA)#%G%2=R+y;QMJ|e?(LY8NU7&8`4G!zHsqwu zfW?U)nhy4D-?3GR{nY$#Dl5-x{yQC+MO8($ivkm`?lbMyjj~7AM-MYwX{|PnYrh9!)Q*4TAqjo=vsOy=T!@%NPb8F4= z>cDkyf7PF9#H$RVvABuE;s)$(FZc=E6KT^s0NBqp=c#%GuvF zj-`7s;u0E3+@<<_N#OSrqtoqi{Ev-?%{+Ac+;U|edOUUvPrPB;+$5uKiqIkx$BlLK zN#?CoJ8NUR;z{WE_O;WEmGv>ZIfOYfKH1IY&5Po2o(3;_1D@lu^-KSwdhGiT4Y=O| zKL0E0SN`vFnE!7*hbga)+5bh#78V!PB-X$1^qT&mX(N*H#Iw(K_Bp^|0RB^*YzyUO zaTLckdL1isKAr6)(LS*vPVq)6X)#l25Wp!1e-1BiwW$CMQ*pu zk!GZCUTX0AedbqLt@;1L`SzWMlA=ZSqq;KlYmxb=X**2kM2^eM!t1kn1(|{MM^TAp zH(1oaMOE=vnTq4DrHlK;Cd14=*ipa7WzQKNT$1dKpWXk$ebP!snm_FS!b#H$GW#|i z&rh)HJDf8*DBQ4NM+{&6&%a0S?HXi-ggQM9Pmge;uo1&VS_;+ydKg!}Ws^J8Dc!3*v?5V9uUuc=-btxYy>HDim$o_N8b znR$k>_4bt{e6iAuo413ii&mT}R6wo{(K&7SRQl!vOpI=Is6H zrT4*o3I31zFW46=`01s8VbOopt~6Jl1?OLLf9pEB?bowvH!Ar1QAfK*nWCApoOZ)=GW2s z&kHvF>ILjH>ub=v5V|>25#!Dyv~g2%scx=p?i5G{^jTWZ*d1ecxK- zdkDOHynxN}?AtGPq~x|-KgerOqUE(EV}i?<^XFs8FsTij7yRqZvZuJv7U|x1*hb_P zMPUTfi_l0?Y3%rTE@2XXYh!^qhH)}mCsx=ec94BXroyeEH7k=6i+_?Ui`~??>!a^* zefuB1M{cv}zkI1X@ff$*M50IY_r-twzPf1?gT5s98MaBXuZ)-%bv=3ZG%W8gGf*v} zkxxxgRe7;_dt-La^u+7rP2MvkzJ7LO(@)*+A#Uf5@1@;eeoxr!%D%(vj{l4Ig@Ysd zzcSDEcRoL`kAO=TM%+$8!SkqDQzm(pNz@zFR#aCdHbY!oZ{K*NHs4Nx@O>a?!F@$} zWjP*K*>fH$qE++i%7XOUl@4aZ+WH#fG_fsaaJk6G>l_JvahFUd_0)Pat;cZ;r<;v8 zEVkQh_cRFJr}h81{Ke!>#2g)8S8rR6Sd;gon@QK8`dIBC(<~2~TV7@Vh}76e2Q&jg zcAnp?qPn6%UOCFBGtXgTu2jvd_3Da^timw|@8g=lSm$ zpXc))ujhHcp7(p<<&PLLHH177IRJsO_guRE@%B}piLgNDijVhJPeMlqDfFH=c-0ha z#=8h_htl(RjOFd=knPBrZ_U0d-#_QbXWmE09r=HaV&2w&z9)So(N!vf2GlM^{N# zcr!#igEsVXwApX&LHnV=`@5$X?-(}>TxQ=6R_gWnY1XW8ee1Ij9(mtD4$)Jd-#`CK z9McCP7-YMyBCOzVl#Jh!_se3_vw9UjRs4C2YqeV$uKT8(E|QlQ3+LaSiUfUn=yu)P z5SXLB{WW4BdKYAmhdin@r2h((&CwHkJ=ab^YRSUi3J#GaSg@ zRd}VVEG#NhCHAkvK-3QSVQ6zy;Nd)bQB6_OLl(tvftV1uq59_-*mz71l1wc_KKA_f zmcQw}Q3mr>DkkxXQ%%+rY;m@5@|#PM85tel8_KWOb1H{EFHD9!8hE45wn5%n{jYwI z9rZ8;*-4wgd>Ki~)TP{})e^l9F_iJIAp6(ByY9A`8`H6AS)oiD!J+vc%V8IEU8PYB zI{qV%T!MVzhi}!+RyV< zo9WXCZSt>VwU0jbWS1!GuLCr1KaFhwv7?nK2%H2xvanE}X|}b7&G|i@D^W;)UqwrQ z1HH~j5&WWW?MKo^m;ZweC+Zh&M|nd5XL*)_uszHQQ8OE7X2uqA>Zx zJ}4zhF!Ym;`_t`j7DVyK2apTrGVV+}zn1&9dh3^s-i`Sa*TshKr-f$?FAiGexBYfA z;AOq)m+^{ZaWBO1Mux(!v&qqo*43`?LOalQiCE2tnp(bskvot6^qlEAhudQbAi5oz zSd?zhUX@1CTzUdy|CTi#W5VmJHEJK7G0W(BAfVq|w9yLDQP}%31HL*fhuXcM;DKU6 zyY0*I3BXL!atppgu#dzMXkgv2=8N`yU~&9Fwdr~Ed(I6h(Zl8?uEzQ@8>f-o&qfy*=v>N$>HZi32PTh?4dD;VYD^{X?`Cw@n0uKNpX1DTYE4*nQiL8pe>-dFl76H_h(qvd3AVLdPENB z@2uU8!y?O?wV|tNa-V_D5zWmr*=TYha?N@>MfQh-hM}%uv4{;C&A;^E#lKgfV#H#V zF8r0F0bPVnXr9j8w=t!I&LpYZGWmtZ8kcl>WfG(i`MDy~lI<>%Cc7T|$9iAC|J4~@ z%UGQZSt9)i_gVRu_KX-F>>&tbE7a32c6}*zZZM*gI9~i)_;+ORr2NUBkK#VV!=2gtoAeGzIr?6}zVPaHNtSlfnTq& z0av#%p0Jscn5msg+o#ejU-`=l6w{`h z^v8M53;ExC9O36Tcgf_U*PZXHwnM+wo`bDN3JkhEy)?lW{6FHyE)O3_B@EU*aV)FJ z=8Bn_aa2GU#y^HVA($_^Jl^lKDS0JBDe*IIdNjD%~ z2Klt^r2RktB)+7*-3LR(POtPewSc->@`mX1j*2Hf5AIA_ml_00vgj$i);ElJ{Dcy; zyhKD7=;!gPvGUcDUUI;+tzr}M-;=r2i5{)_42@OtJO%Z^vBs63$!Ovl@GcQ|t)cfpUIdG_ zKuT-o-PXZ|;M!rvkb)zO^P;!Ic&i4$NCt;Wg}c~t?%UT2+{*2tu?7btqjX0AE~|D1Rtsz(as}Q3evCCM%YO zUam8J^v6C<26A}@{|~1xNyPVd$-_#=dj5r%yGNn$Jl^z6k^F2h9#Zg=CsRHNn9!3a z0*}s|z};cZ{4z{b8YM_(lf8Iuu z?mm!u>g6i7Id<;kOH-**O=T1MhLI98V0>&Zm7VT1UCK&UK&iPIlsvHg{*u);*4+_V zIzZQ|$b-F2gdf%K-s?LE!3v{S8{tmV7&eLpHWF;aOVP(Na!9a~&I#vgJPl!9Y%OZ1 z5Z?K)_UpFcYGOFa>77hWGxj&? zXf1vLKkfxSQ@o!z5K-{Kq=r^A^V4JS)SoNtboOVR9f%18An}blK997g9y5*QCMRJ4 zq+l$UJkuL6pckgOz0tMUc4bU$`EO0LB|gXBRPQ~ak*rU0uZyt4#=4Pa1i;_f zjhdUxATEe7vFI7~{B$Uz!Qy&h?;DXE#MNI&#{>))nXiXtF%4%Y|3qODsoFg>vFSV( z5G$$6P@jC%(?z!#p>5UE4qqlx4ZJ}-MCXP1qjOlz=>}0EuA2t#fr;$>$BJj7i4%4g z7LI067|t#StkZ~+gINaPqyL!w*$>5zCzy^RK=nRSL@$?)i8i4#A6)}ucb+`i;FI&P zK(%jgQ}~m?s-^MKH_7~n0#s_ZF@RWSN9#`paWT-xOd}GR*WM+3WF@P_jf z)Dz(Bl*ic6l!c=pQYG0}A?i(Bc(BX>P(v?7B9^rBM18D?Ct)_jCA)sA819ZRv9H0{9j*>ZVxIKBdi8g$-7xL? z*p=hq_SV+svUE<66Tg7fe*X^9!>-=W`~3_*@C=gb1s5jdW!Dp6Fhq1>=uN100-Oy| ziQULLjAtbuEl`Y*%;>Ynfm>JCr>-k4M8`I35_gu5jGGO~tkpE_)mY@!%ORHUd;nPa z1TpTo`%)9J>k!0$1GxRLU&p55#?V(F52uh?HXCZ@J?s}`czI(rtxpA2Lp9(q$YTj* zE>U6z2_@!plhtP5E!;46&R8Y-t+w z;$mn;qA*Mu;P(Fg#e>g$VFg(wPl2l|T__cREk@)>o5gDNL=nqKZv~DQAh=`6|8-`` zd61Jqti;gm&3#|4D`(`g7n!>^fL=~v(AZ4w+YK)8CueRqOfk-7w)oUhBrl|+Xi;<} z&mI;B$8MmqI2MtY`qHok{BgY74N1UEB!4Q9Z?Xmf;vk}X5q(#1Ek8;8tI3e2DT|sz@5I0!0Sr@xgs`Eb zP*RDuJqh`KyDrRN9*QPbfEk>>R3E5!$W6#e7}q-v#`gBNZOJ~jEn4_PTb3NQ4JchG zp>AJ{wqE(-jWRFmY3HF7py*c?JpfEb0E!O4WTCLFQQdgLBRYwpqhb!UZkP&z7waUz zm|wfgcBPr5C%9vB3#;;;O3EBPP*wGdG&ITDefjt$>IHjOc=Xp5r&4SRo!1CywM6U4 zIu0W(1w0>NS>z`vvEaEoRQo-^JaJ5fCjq2V4%iujZla@+06T3}2V~3&QO1lVNpu1WA+w{rxA9m!q}sTI^6I9Bq)_`hx6<)p-8^-+fQ?BA<jNTt6zI zSv&R^LyDBmG z-&p+J&3YsgOo0Rzqy%>(B`G@iQ#O(mJKb<+bkW;AA?ztE0keRUD?uHHWId54CSxJj zVqYAWDH+!XX6-3L0%$%Qgz7{LU&lA#rs;b1=E{X>fZJMqo`bYkDNpRjQWs_nQ}L|t zK)?Hh)S)T0An#B3D{8@1f+Ktlwm!pKd@6@#p}S)7Omtqo;ZQmcNi?x#k!R(8Vl*o) z7d4(h=h3U;GFeHavlOqPC5vql$nljtQy4L(OJ{DWVF1wrX1Ucs6s9!i{q%ThqQQ`bs6w!$zBQOG%}Sf_PXteNFH{%(jK95l^#$=6 zOtO0%xK5@pw+ofq4opO;HplQ59;$cIRAk(0gYJAu2<^MrzuQP_2XqZZ5VCJCd% ze@Cr0`MSxnAJOVe^fQqUl;JL{0G{HtRZkY}@{_xlC|I)ljCM^y#sOzY8C*XoRy98`5b(;#B6-6VAiY8*AC9ngta$ z{eGn%E1AbGiT(wRaA~M#a=d=n$CjyHM3r@oEKdgX#b&`9b{KV{p_OVBeTgg* z&0Kx@Pkw!#7kMC9TAB@(IFG!yoqQ6M7(Ls+2V#L0PTgMMJV|;fH<=@W3M{svIt=7p z_$W@uX%g5JdZ0JlH2e%xt08BN?iWieT??%NeG?`&aFazE1$q&upQC$1;Kj4-2bBcN6Y|+LV33#X z5l#+!m!(5yKiUA|$3;~bH9e@D!05H{tO4KAwXvCvp*K*0 z!t%OdO@!Ftu3g$NifVZ@wt(VEbd0w-juPLIp&D@^lP@34_2Wts9FgHd+h}$hDgl!S zjwt|jdVDvaK(SYzqZ3ibG|od-TYNgjB(W0qM-N+ce6TW}z(~%}Z2k-txR^2kk8;UV zzj7XIlL8!88inkzV0Dm6rO~N2XHH-r5OK?r(U-P<`zJU8XQoA{%2uyNsZjvJFsdd# zjz2t>)#%WDTMCOj)8V6gSSv*(*?_j({p!cY6cFEhCkagQqEfDic?ce59rX2f*)FjhEF-w z-%iY9LEd_k`ltv0d9=wHTb+!{bKaF4-zy7F%<4-%3{4pCkht`;VsAs9{C>WiVi$ij zMyvO5y>uE2kn6O3W#`mi1}bZMhOMT}iI%~SS&K)QTNsEZwSo!5R=lS0Sm0Vr0!kxn z%4SCpYWj(so`8d0^eWqnJz*A)9*wZ#6}L&ER=T2Y@H|34!zd6ecg!gIESIhkHfDf2 zd*?wmD_g=wVZmQ)SoLzzY6907HnOVCRQDS0N_1Or;ad-$lFU&H>X?!jU158LYD#F} z08OUu9dUdhyk(+`LAp2vfYFPWcuOD%6VByBjxJffoqos}0NqzqM?s4hs_ zV1N!EsLodw2-yjVNljF@JUZy$i)%)~nY!dA(MT78b=!lL_=E;g(iyC`6={;Cl&eE? z0e>ux-C~D55jeCZ9v`$nZcUAU*$6?auoLo3J_5gx&4xX-`XhM zGn6PsADRlmpN%F&@yz0se1>v6x`AZhsEi@)0>d$7%N>HcLny?{>Z8ux!r5bK!oT}K z)=5kA9%C-zp?kY1(aqcTAji@RF1@|6_gkS+{l~SPXsm88&3=0P`#Ys~$g`(49i(+fKb}eS??$>1@vy^3 zZ(Elqc0ZQS`qQ$1(&~&pEM7J<_~N4COMnGh;u1XR>1$1Zo`)mtGP4c!lIpG#oqqYy zotMnpjpWvwEZRFci=7a7cX|+o)#1CgH9BNl3vr@=>RhEM5Gi(yWB0KGp;M&8QD{5E zb4|i`%kI)_u#pW<^LmLm>wc+CXGuK&nr#3S`szMNm^k?A!99Vil`R`?-+1c!k8Vx_ zymvau!pwa>3!_GaPu(V0?@h&P5mxXKQvepE)1M|5V!Nrp+bd6HS-NPd(V6{BWi4Fh z9{^7m)rDyw;W)JM%T$;KP;wS&+emFRzRaH~e%2?(I)Hyk89NdBiMflH>aA)~twM1* z)ZDXuQ>t;Qud7CkPC^1HW39BniY<*7YN4!XH*T~)H;s?vA`f1t1;xBuvF#(B8GiHu zpEv>op1ZvzVJ;&+1hVM%S0%ZV7KA8jukihR3p=SDJCpaGwa?a8*d2rzfrtFfZOmsnY32*s-=g zTg2;JW^^sm;IGHQnJGAbY;OX(m!;rA5I_WRe;Q6rXz$Zd`FiU!xC%R^Oak7T@|&+_ zq@$I9O|4wFV>4(`HfksSq^j*6Q%?(DMOh84tVC;V^Vrj0Fd5G-Ta!g{PC3XWe6od{ zH+6NL7N<7At$iM)7RQDsKjUO3d-J+!_b<+)bndQS{)s=p&Lr>~4wrTaATXnX?@xE4 zpZVipw@)@w;}Sz6-AqkS^%+INF*W|L1Y)738Jh=fjew~7_Nrs3XfI-|J)k2@Zrj$p z-(O=p)IPG_o}eU5VJE;7apn^M+P%+oF5-rG^f+{Cfow>zFd~#4G43Kb52VYnsVbz4 z?CMW3Ja@it$vsE2VEIzpg1=+XOkHAY3IUxnx!m-UM$qkl_(7^YX8F3of_hP+Zqlc- zkU{3#NMELblgiz~HRe-Rkbsc3&cc&lO!HIuVydQ40Zv4cRMB6Ti{f6p$KUo&`gyT= zNl5m6#>yFf*%Xx7Cy!P;1v?Ukxx37|;dclak&Z`?H5L_SetM^^S1YIy?#4)M+})BXCT%*Bwo$ z^*$V`;f@5$TLK(!bZlF1e?|g`TV`;Y2v+K>|Mv!v*>^t~)`jP$gV$Rznx5~Dw8^~O z#CBv7fDIvh)(*xe`*e>-(#py!vvzTwGhkhLDdo5j$4(uMAd<@>I-jF0Z$ptOKwy4lOh?K1tIHQ3 zfTvrW>(lz8*bz=tW)_^PqbJmz`7Ck2x#kJD1~69z4T&u>-2H z&$vD7u$CeeO5_W-hUh8QS1)g_3#^>*)aAigh;xME?6s{$dlH=s;r`&i;j9o=w7hHM zO}xzZRaXfx?@e+N%orFgZYX|m4ia{qx?}RpACUxjkF^x0NUz`JSl}Gz{5g5#?8ifz zrUY30KrEhnj8iik+5i!gUoEI(+*5*r-d{-*;CR~~l)+JzGLU{>G;&IXHKVrne$?8tsP(V3NziDA?XiP=?CT=JV*y!F5f8gx78 zJI^=rH=qTopps{eLuh*9tc;y_P3_AY!NIj3hdKUwGAe%x(ay~W%8#YKIO9AulJV;L zhk46ZeNfLa--EI;&32EQVUWZQ#T~uvgijr#>lHP|S95yo?tPY+npK@^V`_nr{#FP{ylsQ>n1?9p*xhWSy_ts&V?$?ACD=zS3!Z4Rr_dmxz8 zQ2O!@<`0FAOUe>CvwxVe$E|hg4!u8=xwDL2D!YXWq3t#a?lvi==KVLVQbziHVO5do z%4F2j9}jaqotl-;an8%h?QNo@-FNE;YS&_X4bEo)1*htjXWNrTHXiPa;1Tr}VY8qL zzT6L0zN3?0{CEx(m1^GfcWj1tMI(O-RC)P@t8u+jQ-5?lwchT_yuDerYqmZy;4|rJ z!~R$*KS1_=%pZ#GcpOGr^M})Mpj=Z!D-fmR;BJ7v6UDRkw|}T?h7lKy=sf%O@6Gpu zthsqQPdhN4SG?VBAGe$O@wHhF*5 zhj3r2av6BY^5Px)A3Kk_=;OS}saz-ZPmeKQv>xsciWd3^bZn;IPMg~Lm@yF(|LnU~ zkzl2W*#QM86yfE~-o`s4A60ybZfL*0W-i8OC1n)XN}ZF=5vtMUbM)=R^?&=2{UyLG zGw=SX9?4OC*|R5HG}TZbzj?SC%;G-2~)PR^g%?2GyGA!yoFPJt7o?}&K1DbYP`AiyHV zz9Pil`c2Te)9GSP=erYU(_%I%FGr4FjFvBd_lA#u(rGF`LU#F)WjXtcXfN#GirS@8 zF-@hYQ;QVETOC1z1?<-%ruSH3|)t*X0k-c0!B3LS=}v5ZvWwd_!XnUQh5}@P);zZ)b5-vG^33vSnyt=*n6(Lpj zPetPwoZTq|;Skl8flH}XB%~g1|IL^MC2d5_JIjx>bI${1|177b2Xz`J=%cHWx?FVB z`|N$Jk}a7z!^EcvdPD8$+0I-ac1C-oil+Ll=Y~%IPXuQGbcJ2mtV@68hU^9Rv$o5>E^7;6gRV9#e=bo`$`^%Ny<%qlK_yV= z>2AkUt*J-{eTOiNMp-Z&vU|4{cZ7rfl5r z*{tjC9gokGPf6{N{anCBNMWt#3~aa7Y_NC^_cFM2&_PR{dU9t9dg9^H^vk)yGjuwV zqXSXyFIlVYKjc8K_*Bs`+f4Cv{>P3gd2z%4b&P!V+NHpX0Ik9JUKw`bg3ykptMXBt zRsnGm4W60v`{zDpmh~#Oj0w4(tNVicrJ|R4Yvm!&VD0(Ox5uw&tdO5?FmuMcGRWc$ zsO~D{7T*um+xP3O+;o182J39T|D5pQZur%X;W$x%N`DjT^KAD+CXQH))zm9*m5|c` zr-6&8WFfYn3{rKKKtRyWxdxE?zub)q?1$(Zgm=CC zZDyMq7~gvzgDb7ytxZBEo2*}NrTny9n?L=Ty_|lJb4Xe5;_K2KenV}}M&H$}J9=50jtYhsmW1rjKmEETmEZJCe7I152)mx1R zzbtOJJxwYsa3W(zibG`S@*f1W9x4O1kE~f|@17UBZK!E$p2<<}#GlD2bn>gBhJ7aI z(UlyK@BAU<2j@Y#^Pkzrx?lHhA}15Uze|MKY=?CF%{bziK zpX6cZ{E)>=_I&uMxlgjO zKF4T(QL=r>3qX|aI6IkswH-^HKJa>!#b!2gb;nQn{?^Nno12nW?cW969`@TN`2uFU z*noE&Y=CY!sbSixz3wukoTafU zzN)OZ)3{Y%yX9NAakcJoen*HF^G>|lf{{zebEm&W{V7C^DKIfI4vT8G2y$D6F(p66JN$Ne`VZ+(=w%R4R%5C!#5(5XMN zt5R5U&yHy1zT6J4QrYDyQGvXvZC+J4DF5cEb@FfI^ULX`W|HG=?Kj_q%tD6TT-@B7 zo&#w*$@P#`bE*?>-8lh#d{bOi<^A3OqF~7rD}k(Gd4k=LmCN6^MU@x!1U(}Yaf+f^ zK!@1p-*!Amr*FRwotFeZxSrFg>9*5W=5xX8PSsdOQj9pD#$(-V%!v8O>CIGOwOEwz zk@JCkb42iyfBGTVb#y$Bjf6e)M1(J|D z_H=*pf<=f`;ks!1cFP7#|F3a8g>-m7{e?I6NxfVPZ z3u6!eRutX+HoA3t{Fl-P8`YpQ5Z>vb&YhqL_4+$;*CL0`^GltFPCOEI!}_I7UClib zL3Bm~ip)Pxl#^V1o=sF;AT1T;9innUMB{K7D8BCn?roj%R#0%pU{K8HvOua)-rq!? zh56;zU)wxi&(|r)4;Crw>U`e1FSei@Np= zBn3~+Van2Kr~^2M)NhwKVcopNoZ}2%lPp~?>r;=QN}p5fHP0_c z_sf~TH7D*<7GO&D=T@RV>^z<^FMrbdPCB$~!8}a`TQL*i>1J7J|2>XtuK#UpU)b?_eL=F)FZ+F*0+Vge z3e+yTo&g)GQ=f9867MqFozceS}!2_oo^T6#7FdW&O&hCjOPMw>zMQcFcz#I&{`>d=i=?m-PjZ zYki9D<_mLgUi_jw$fZlPzjkwpj~_fWsoPh}KOAi;ikJP+Qdf}Y>}2EvQTciK?FY+? zZ@+rj&n@OlzE#gne*MG2eu|PzKnf`O!VWT_+Q|}1KK#LbG3Lo7VdN)jtK$NuWYA=-i zI5A&~YRKuNQ;F5&n9L<~41JD+atR6=BuBFtc99+Zkk9uh|3S{spDo#^;0H$XWP1oj z5{pGk0xi62feWgMpq~V5UV6Rneb9h_xN*izsCVm$IhplAiw!m>KR$fxM%<9$#G&VL zZXMOA85`sI8J@eemTL)JIe3)PqG%!n?}H1DA2gRYt=PbTks;vF#BnmDNn&IL+)bDh z@5)~?0$;X=gg8JJ9k)Ru2D*P>t}N>2aj@y%0NYvJe=aFmzN-b_9&6g=pDYwDtzo7} zBh0*@F*2s1(bkdhnHStc64Q)h??un(yW-e~XySgzl$oMYon^x;p5hS;xMM{yFF~Ch zraZ7$~(y+qA{p#7fo_z5?$k= z#W7!R`@w1Yk_azgQZW(!gCOxJ=}3BbyA5$Kr3h|oiawX9&IHr%MXnxaH{uhHXF^3t zH?UdS^Xn8g1B{Oz5{`VZp=DOVx7&`-2R7i~cOW!7%I=q1FfQ)ldV4#{g$dtUTZ;1_ zMEdI;&%s@guvsPL%$W#kuQ0+?7%B90q~Tq}7gTInIa^>e2+fX8j+bjfG9 zn?La~CO8}lFRE7}wcmyIp*#Xb`#j_BB?P~iW0&gE!VLK}&KDqqhMs~ea zcD`_x6orCd^tf%q$dpO4L1MpH)wPkbE$qBX3XFz?B5pO+wmd6MoLYyYj zI}CY6T%f&OiZdc{_6{TG!bbjt#3~XT{E%n_jBM5j3b2KL|6mJxK660I^3uyfTcu$7 zx5c=Tk^B>Bytuu)eFQFEaBr9~tONY#fY&l_X6)HWQOw+zN%KM3fZtbb+=7d|Ep>8!`5X zM%z@Xpb5@u{i0v1On;gCTTMiim2Djsz(i9pL02m)RdaPn8#FjVLWGE7DB9%|T`k}- zm#iviOJd~UI8cGsz=aI$#@|e&b5R^qkiSVtU&y&$!*9pr__MH7Mv(vQh_&0V?UVS( zYV3>v`yMkxaNHWx|k9;tJVr>BJgqzr8Zytq$rsD^)Fm&&49&OwKhA zbtO(|^P;^;mE5o#!kh^CMV%i6?uWdy6yw(2qDc+apvo9t*lsGI(qxiiZfa4yQp7Yn zUMwkTQnWnl#Y1RRR;lBvsKXUoR^;oYad9-#P;tz+%9A_0ek7K2#UfS-;-`VoED<95 z*@6l~rO{!I=)>*~oN&tA=~=00nMM6>^j7Ej?i^l3P`4>=c1jcRy90QiSVd9qr9NhD zq9;u$rBfq@Xu*D^9kyZ89NNYGOI|5b)W{LbKI86iy@HttAV8xSH&x2r<&wt+LigKB zgwS@<_{^hcr?LQCagkHlLqE;p>SK+RqC-V*)AhR^$>UOjMsM)BNvZptZ}$jsp#NL4 zNUKpsoV_yj`&KO5BBxY$7m88{xj(l*D%C?{C3L70&Jb+bZRH?O@NXLdeTRjsd#S;{OD4O6jA_%&q_yt3#gKPO~)`85ZG9T z*GQ29M)D6pQX+scNjMF{kTA&-l_ds|7+3YcP>@h8F+9S)4#BPQ5eu4DOxB)Csq9AyYO%frSExgjd;)GXlNB`1z@%;qO zrz1-5BHrJcdRVdL$WFhB^=GD=b-T%8`^OXU17Y?4>M0=9A$~AS7TwsRjZL^Q4=EmJ zcpjtIONt{+VPV(hR&e2-p9rNDgi-~POA0imRwP}lAHlNkJy;*2e0Ufe-JFB{ss zpOM>`1ujL=mI#@(HoyhT_Qtf|m1m4W*Jr^eMZChFg~S%)VoOnA;Gzdoj$rB?I?}R2 z3V8UmxF<}uRE}X^^qmPtX_3wDP48zAFicNcp3R^i5JB1$i~0dZSXUF- zAxpFSop;HEo-s;q9#WTP8f%Vb(e*d#WGWGYlB2q~OL$_*F`}g_^`YlTgD9jRX+^Ik z1Z@nXzJCXD>$Vjpd0{OXdPY4%i;#e^XUzTNM(6TkhPE3V8SXj`*n~7+k70uT)u#OC zM}OTzm+bY|CZiLJ;#BqqL`sxN+P&5=>PyNgV@dA7KaCb6)?JRA;@OB{IRs=xom0|^HNI@>*|gEjb2h{lz;8{Bl( zBoHU1fxBez-N7Zl(gDb#%VAvY`ibM8rmgGU&;VJF&5d3LR*)E4tVbsz^oMAie#nF+ zO52bMFYY9^Z1hAwl4d%M>!lf&!5NuuT*i(rtSs%t+$CN5c`_2pjTEL|dV%=?VqF<4 z6^0pvC6Q7SklMX`aAs1hR&jqs{(Vr|k`a>O;cUgAyElr}&k^6KPw|lR%HX+;AYLL` zNnzP%nXa=;|A<;yE!`uu#w$~7x~4tgDinvVue(Lq7RSI}dHnIoC&xamCsTZsPVo?u zQZmQ``!BkfKxW(Rw_pJa#Hp?)%ok8F>}J?*c;z3o5FyXw^iU^5n`}lYRj{D z#cjCvhSmv5L}q9Vo#jZ|olx)YUBSFuS_4ZeN*gk4Xq)ScwbU z7#4IGI|B_(gkH8MiD@DH?@GV)A*t|!GWI_CQeW|i&~i<1F}e(^DnV0N!Ccq|J*C?6 zHuw_T1#Xe9tP;gO`QMg!)!4EUd1wyzZ9Qp`;?LhKmVSZbqVzlOe%H`nnmTOwyE5Mw zGlV#9kYq>eNS}qu_wG=bB8@K-8WKQC1V94vGQl_Cb)R0C6fLnlHO>S~<+WJX1dPtyn&H(osJ@PSkTQ4TCM^xj+&egx8wfKD zOIK^Xcjlbp13cS9f#ghqE={hTxm!A3Tv83 z8=)3TaND?C>aEtIKvEifNjvF?X5JPwHJp0Bw+#_30t9InZw3BdOkRN+G#+o0V!g>) z#Yizxzt%r930sLTO1C5i!n#H_y;6!m8^D(EB)CEey>7kWJts$Ycc*%HX zvBe_{%;S;0IK{P~47th#{t01RFPRIM*s2(SMJXPy)~7^Dz}gg%6nKA_BO9^z2#}5_ zxyQa0*dO*@No=ZQCiaWFtuDi{dmDw83_*rUT{*-HhY1g=s_oXxXmfF8sUzfi`$HX# zVx%oJy&M;3hOSIU)ILSjwRV-9tm0c1t4Z+=d*r0$<10(idYh@4x228mw+80bfT;?- zC-KKki8tY(eQC#47U&CQ{=oWbRp@OI zn!z)=>oa&-4;<0+|F#)h9r3xrkre8~un_Iy3>ax_hK8D<$4zYI4m+yXPfUJeLUSpV zHq#-bi&CqfgnHXXc9*FkV>3ldeUm}%N=?T<+D5V&-m>TdDX>`2@lV8?awXNnhuuei z(h)+>WTCL{Z_s7Lk(QM;-nxmdS^N<^%=~dnig(GSL3Fqa?{0<;6M`6 zo&f){tnsXhPqpjEbeF#~7Nln+#=r)rV)hm39iNZ3cp z)~&n$7db{I_NyA$xYPyLh_%VF;(gj;i&U ziuDsa2BQF2ssim2G%CQJIPcq4N9C~z-~r!!Nas?b7Zvn87T9f$98`N_ps75uxACqi zbGVgOS@a>{P*jz2AWW0&E=^?6vU}jguj?y$b&nP~ejK~^MX;{4y;yqU!3VjcN;y{E zfZnp05<2gZd26ca_V=sG&_$R1V>L7MaXJFd11t(mP$jy(Bm4R@&I2+(j0GyHIT`wL z!P^$fp*jB&Opv8{{ls^hC=IjP+8tWC97>n1tB69i-c>vNaa4k=cNyO$jK;@vtSlWL znVt900Y~Oys~Jmj zVEps=ko%>a`*Vp)-{8-;Sf{)AQUDG3r(@zHN74!qWuNkN1h<*3)e`9CQXDLbA>#(+ zoa`V^TP|SDdd&58+a%hQa7n4Mf#J?uRJ#_1Ddiwu7OFkp0vHMDHeg&$99j9c*5!qj zph;~b`n-T%f{zGNNezY;g}E$43zm;)EL}1}gsQ+m z&J>seWu)h*B^`r!Sjs(uaoGl6r!a8Bo^%f}kB|vq;8uOhJvTX0UJ|Hk{Vrpaq@_6O z&M+_Tcm*KXeF9`q`%Q4PCZjBU&_< z-)bS*$c;HYApE8Il`YqCyKL{1loTv~4x5J;L?M^0o{W_vZ{OhG(2^r%{U3AX;gLc-r@}KFPGo_qXxG|88 zvJD|!oK>P!c6f;{d^!5(<8CLc+J!}3FqN~Ci3DNB3KUPNj%V?Va)QClb;@&n zQNDn2IVq!j0C6G5_82!b3;J3Qu47!2CD&QCb1vC_Dwj_$k4v&gv@^e4eWpfJ>;eAZ zPT4Bs-wizeSt6y|g0iSYzL_qG^|gL)qg`*WXD`+XpoCplr0!7MJ;^`M<6E0rU#Y8} zeo)$4yT!lnF>VcuVL&~}uoEjsPX0`Ds7kyxu)Me+GbbtF5IIc#YbQTna*$w{%QG(G zO0S$&-Q^h*i3U7S&8$>#F36h6NP7aC)>_@esd^&Y;?RPa7eBy53j>5lM_xI5&4ZnL zWW&Yr1j^k`ewl0T+ur&TzDsod-WS^>cXOlb{kuILmlKOEr%A#W1S9+_=Za<GwHl zm6Gl+YO|i9!G!q{I%$%%I94^wv3K%;Tge9eHhid(QygS7!t)?|602FZGOcp zQG@XlAelR}>}ZVc`S%%L-a2v__GeaX#qZL0-_a$jh4=#9SpwxS&%Pmk$-^6tE-Z1d zdUYsv;D)Ycr!MxCbTK4VxF4Ud#O=r3Hp|29Phfaomk*^>6m2Z`; zN(mrp2$JC_8s%LznsAubvZ93JHO8sZQ8taI{f7EjGQGBsr`@e#TIiP$kUAH(GFaE` zJo(vV$o<1{yOaaFvDQl6`_<~|4x83Mb-HWHoj#*8JUoil&;R^O(-P4VyMC^WOtK!m zG~nq~od0Xv=w#vp8PD)_wo2C-<(11=AR3!8d9dhKr&}(gWuQdm77(dh(5c+p*6KRy zHlH0TQr_Z8%fIVWG@m0{)r~|3TK82bnnSxLYf4rACAG7?1wl!zt5R5*@>xQU1!RHK z2e~6qEJ+XgJ@?>o`l&I0j#;+KODWPk`+G_oQ-8*zc%^=?yG~;H(gkpEhq%Z z{WkvVv}>gvjGmw(OH*3=hUY0MMdhZ}E%Lleg$bN=48K<+e{ zUROk_A=}p>%E)R}m9Hs6;gNo$q?d|0j@JVV{hrB*^ z2{!3%MUvfW=IX)k{whUSxgtIA41R+rmS6Tl?mn4Z<{*|@+Ortd zroEw8N8;bSjAu;sx)*i8akJZTmY89F7sb+A8&R@J`@N(yoIwy`J{m8eYUl3jFs zeI(-p4D*Hu)>F|7*_T2;Wge~c=7_UHxSPv3XLlF=Xi%HsU}URhI}ou-sF?B0V$#R57W#FN@gvPZLR^vNyH zQ*>l`(+XqD0^Hgz?hfLcHg)T<)YMoEEw;nF*e9)ngq-71%%i_Kj#Z4hg5sgvVR&~k zQ=mQ<<<*^cSFs^j@#6{pQo3ZPuXTH(y=b!a_uV|h%|dVav@9L(IYQ(w zu@iS!_g6nrZE)aMJB{}_4Zb~{(pvUJb)+QkpByO>iER_Id)@o~vPPSdy?Ww3g?@ck3Y*7VzIX3No`bp zOZBgA#c8uu$u^oKT(cNULR1<0$qdTg9_72&;jr*X%dz8|mX>a7T@0%6xXCZw#&9cO@2-%J-Gzd|VVCtR{;R z4pbcoRsS4S-~PlP z785OSVEu=hmRwG%+^JKBCQ)6I;-02=Sn^=kl}ZQ*)0NGc&;GH0%%(kFPZhGY(^}A$ zo;>LctGcme*lmrurm#K1c;I+dsoaUq2<{46uKwCr;?Cnc@T7?Z#KxKJX2TX;v#H-X zo|ZFE!umV|zUHrJIhoygBv)@FFp2G|`>|i{NSE7>HqR0xbzY2A@4{6N}?5ij&xCAD);2P~Dl$3B_JF*#4a_rXS%1)<`pK zUsth>LgfLHUsc9W8KcD8uY2 z`_aC+pOWK`+M7*|Jx%aIW+0KrtIV{$q3F_C{Ns zYVj+7Ikn$KcQ*ssuP8aL+37%ab0U*mj{YDN3-8NWuT)=VCmO|8^5K8hir@HeqQ42+ zz$mMR;BMgx-QB(mQRL=6dsnrMFJ8bi9_B&6Xb5$gst!_1OBKkLF5KBY>RFuMqG*{iGIhu{PJYszxo#(#e3Jj8m3GYIHVP9QLRT8giF^S4 zCuP;{eFSdzICWIclUBAVzttIb0xqqUPxx&=&YxFprsyO6C>6-U7+;FU$o7NebK{AW zgC?{;t@n2F>$38Q`X4)~z`%!$G7f9fnXN}`#oF4&?ZWEs{ZXd+_^rJE%HR+9_!)+UxR7Py97m`hg?g{Zu2h%1%TU*~Q6K z?t=C7@xl(Y+s^)QeTH=Y(K|%;aQbPwmFKI1t+@HQoa%#nU36Pc;y<0VHe;WS;I*Fz1zs1uH#tQY5Bq@Dpv&WFumJ7+n*(Rz{M{#AZ1%+}saU|QLs4i%)74r|(_O75(MS+_- zNtnLle5w3rF7C_4U4#NlBUEln3;c)$zDkIgU?eAuxxP7wbG8bAmDBs@KG}^q2Oc%n9w%#TD|1cJ@+H zgVf)uZYT`eBs6q=QJvD!nVs*#me{bnh01oG)Q4b9BN#hOI14{+;qTUYt}BvulU&$! zPT&Dx-=$7&8sBdAvp*7UC+=XH&10ZUiTW$hx+iC{ve)-%tQX{D+0nW^pkv+;+mIP! zmvY;~zCYJH>}L7mVV59vH}riAVVCiQ-4Z^`q*qe$pmssKGN?`Yoi5|Rxc=V4x|iGf zsJjRMivF%feB4Uz?c>o`<#$3Hw=(mXhCsgQK}Ro&m!HcSS^6Tu*ta|%ln}pQ|IqLK zyQ4~CR=z$~da0_G%b$rds}v2zJ45!$}a$} zf3pk7g!7TWBdp+wchO^R0q6Pl2(kDqp*Y6LTe36hz!TKcj$K@eFQ(&P%IfBRbnSMY zBJETocNEi|Dd>2U*xoKYr<7B+lZ_;OO6%Pzoa%7z`!9{yLmCduR{fGzP(z!iDZeJQ zDG&qBOww#>Nfx|nu<|B_BvIF3uZ@*%?);EL1BPZ0nf7$4xYK)H`VGaTKl)Wx*~AYt zhF!|>WyJ%s$yP_vj>gwDv|b}zZKWuoigN;OTBv%EvyNRw+mBu}0*ktuj{oY5&rMO@ z*ww`>Q_wmv6K?JI$HxED$sUpBQ4UToU8byhx6a1g2EhyZr-9FnIA30+j7tAL{H<{nn%-Ot- zlVe4*ZeO!H#VIbs);hNr6jejP%%`FW$pW@N9wtkss3k#ak|cp0@V0>`-A+I}Es^~) z?QsZqTHxgtcrVa>DkI4S0{~RF#pnE7O_LAYx)-eKKFnY@!LL5P=u!*5GfxWb)KXcp zC3e+?&Df>OcfsVAY!-jKrVS^EXwkapb|sC7zz7ZpRDWZz?$7!N<0C8W2OCi=LcqeG znyRcLyb$H@1SF4$aNFD{Ij7-ycIqU%bZ+yph5=-k3<*F3TfnDL!Wy=RI(w_m#QGtq zHd9ETngi1}d~r9P@!JCPG`+pWQ|DqkAj+p(&qCR8BT3bs;gMwsm`_f^#XB)E$QzbO z68@Jnn|Vlcn^{L3`pwg%b%vgn{wzgjs80;35mRi%$BswWSDMWi#O)P&>s>HEf^lai z$6VLpf(6-%l^rWhXjeqj)NEJn9>rcWilaM}Q%hlDW2tIswrafX7rG?R!kAgAnp={% z_~S!QXBIWG-r4a1=fk&LoFPPrM}H_@*2xJxzE1M^XBxxS`wfww9xWM4IMv2nt;;_N zLuzQ7;S(n}!zWfAf=}EsLMX0t@$Q~ujJci&EWu8?{47r#N-PG>(s^K*+Mg?#K|L)a zhx>6Uw~l-b)b+P<=?RV7Y>ms60;m6}u71~~$e!`0&Erj*#`VwzXUIHfv1uWgu@tQ< znBNI1=Od~K-oGewGN^zeCsm=j3ouuq;1)_+m2zjPcriJ6UM_SeOZm^C?EM3{O8y-z znGa}Fh`%yx8;fM)eK)=J&P}Z)7vIn26b?wwr5LMF>))=`)XATeNZ0=ceyzo@f<(}v z{5c->RdQ5~^oEJ`hl9arAl3e5N(z<#$7rfg%8h{nQ%bVaaN`#L?pZuzM?uSvjQkQx zM!1Z#MTUQ;2%B9j0H|@uOBp}diPk!K-TKnV8H5?M}` zU%Q2FAyOW8@}-C)fHow?g`7X9_}HsdfcL#uk}8SArEu7!x3yy%xTkqeks@GPPC!he{z*R!P)5QAE&_Y}5>S`*mwYN%fA3E;Vri}i(TbyGG2iw#{ z7~aoQsV*AV4auhTfF4NgDfPzhW%+8j_rBeTC(-c*JmU?b;ZL5?n~uNb8G)|I-)?Y{ zOyl=Mn(P&`K4_*lFaYperb`{r@Sd(m_1n($)@|$C7ZA{+I<9&A41~_fW|La^@Ndtd zr5T3)c+F|K?3|!%2?+44z z$U)dY9&*P~Y>NJ@dU4P~O^%A~BVr!XJ#iKezl`)^D6OEQ@*X7TjH}dFJ;+%y$94RC z-!t09j74k)SDJW=$>L|69MtaPa&EP8$_AL$(>r~RiDbh->bbY1_EG6U4T*)nI+sIT zM3!gDkCZr`lV?huS?|7|`!ODZ1kwW8xBLO+w-5~`fso=W_gq@4dkJ6mV)l}Om1@Uk-5g%kWKT-yFX5 zvR6{4`32F5qKM+*4Q%%7X$rbuqNlz08tqDe^sU!p)y_{bo|4`xsgqA{JQ{k~jB4K=3?l*7~ zuvKd6wNC681F)qmA!FFvf4nJJck6RP)nM|KHco!2oZ7Br6&(1xJC7#~B^couB__Bx zieE?TUTRg?RuwvFuHW5EjnRZLIKoAU)GkhM{mNq+P5`Ii_8>0jt?F}XbE*96Xxxqj zm{l?a-V8xU8dHV``zu3Nw8TDb7>U24eza!mKr{ZP?myRPw;oFvBQDtl6BX$;+POd{ zco5(xyL-qhSH1znpXLi7LoqxMGT+VFTRMOE78r7q*kw-=CBs6tk9(2+eXfiwhOCq z7Kvgx#F3vH#TFkKAv!Zx?1m|4t**lv<63a8K>b4Fzrc@L;0@3x{>`0!u#kC@CXdyX zs%FsT2YuxW73urBCbI`Nn6PP~Sln*Vfpmr)<4wxZ2qPQb^Dta&64mD#XQ3z+D+3b` z?j))h~4UH$3s5ylI))kt-c4QO!E}#$b%6bIyvgChDNuLAqtaDKP(x z&`!(3@O3h+?>`c#d|@{gVWkT4j;_?Zr78=$+(o8crRck(z~Ie*tJa1d)4M_F4aD;Z zIpTs;ne}Re??CkzZV_JHG~k(x@NuR9sfXc5dB!|~!DbGk1O|vF24{lO$=eesq}@rz zn~J{4IfztQ;sIan@ohbMVn5jM?TX;;c~9WB3+t~$Y1dKO zDzv3Uwf7`rw(-)SHWrMqCWE#G8 zVaEeYvm2v2VR2c~G9pq4Hy6>k=3h%dh>jDZAw2-SZ1WZj`({A0FolAWfp@CqQifL_ zs?Ye8b*!#yYmNBYp!TbF<*s(+WSd)MXe%JLyf#i#8>f1JIoD`LG@b`qJ@B>uVX54V zE~)mFELN15TJMs?aoPOD$8UBIoIOeUBcaN1Z%-ay2r7x9=F{<0rH)(1eHi2WZ|TC} zy>X?$Ddn5nKhG~W4Ve6;yfg-2CmY-qe^pXT6{!bgoZT|cezbZs%hMGgXIjuVo~3Jb z^zkJwFowcXG^V0fyy$Cj>WOz0)>@G%CXD6(+@EEat4!Y?Eje~!cTxZW+g?(;v1`MY zuDw-?id{+Ytm&YomJXC1tBQB>Mr_Egk5y%Z$?^su8zbtA86wv6d5KvD%|f#FWElxs zjpc2|Z+oD2fBD>v9&_PU!%}ZcLb1xky1nc`S8C~?Hc6K3it#IT8Q;k`+hm-*sEs|0 zbPLttcTvs_6#oiTYCM_C*?M0fUx1!F?4?b+Q^T>+yfF!2MZ5P=%}((L2O}sGJn0a@ z7-WJkMqvky2XZu6r?kPw?zf@~xSXsu{AwGr7iE~>Wfpj~1>?m+nvw8luY-`B=3b=5 z0bN$OE;*x`o94mhR~g&fhW!uL``c8yQucJ^-9S6%lfM}#xPe}F9==BycG=h{j=-d+ zdW`12lELEl6IXmC2^BtJHx#KSWM%Hy;dbS!c4f}LZiDZ~^>b@I$JpB(lMPLSb;rK$ zQN{u8-lmHs&DHeg$_%z_XgSy&&TQ*N?7GPJ2dW0OPFy5RR=oh*|7#VCixapwnTs!k z!I*}8SIl!=U$gu(*jlB+lzopPl(FWBqe!{3O}VflFO4U=O3|Jl@7 z75e&E;k2&!KfM0Ve>;~YneuJu&rzB!9(p%$dbqHRYhFLJAD#ktqqaH17zfp?#V&3r zdm=GIZmKHt=zEZyag?pFZC9qW$6r93z8tBuARx6|DG^P3FjyBbo>qZ2*$-28jHg{i z^_JLyDpXpbXxOh?c0o<8&}D@AD{HOfA5_Pl#{ZM|<$oPX(EW$1;~^4qFuWTf7O#1Z zk%I*fTve*TjNg;@X6AG|zAvCuGg#~OJ386xphNTCqbNx_Y)*-+xbfQ)U20>r3kEdI zP9e<_yK+t-5B+{Tt+}R5^TFzA{AW*_$+R=2s%>=nF<-|I%58K>@irs%=HJSL+l;NN zKj*(2=`Jwr=rpc$2p6~xzjINq_QN>41}6(I^@l$T?czr46vIsW z(d4gcJtv!HO#18`FT9~EUXI0`l=`+S$~X|AHJ6!GJiA|GZl!pEMzlxd1l=`%uA?gkC&H+;vW> zJy0^}$&d-w=(xcLMEZf%jX#tCUf*(UfK$VX-N1XR?CZW-@6p>GP^yDV_`OvLi9u{D7@Ml@i1@gj`0Gwq(D zVHzI2@>sz7%ZX)AWU;gOF?Pl;YB}4xRIR1*ppuvk>hu!DWC)sW%8#}3l-gbRtn~q+ zMe}Lb7{lg$H|1W|1Yo!k#^L&6q}>}Sf&N@jiW25f{yWe9mg0;B;*3snlVJKf4&KdF z{BK}0z=OgnDVxvYhp3z3{tQyw{EX}!2v%l@QA=B##4{HElsQp%u)YhodLAkN4bYgK z_?Tv~*Te2-R`Rir5g^tk%zPu7VC+^)2vgl9e6nvBvl4ZK&qly{A9L=taSFgY*v82l zU}k?#EN?>qyX%d221+yr=cl4xtqmQ!8`kn7A&4sfLJBhP5{K~KLwy&kq*sz2QdfC} zFS{_V3T)JDfFHr4GGQG<4#W2V{9_Q@g0T1Z5+pdY$ojOSRp_j?;#T0Doj6N@`U&SoWUPd3=sDuo?3JTVih z&=G@o%qIETheDR-P<M+=nK^?4=}Vuo^w1iNjW8Zs^mA-kC;Qpg7Yg-#z8Np zqetlY{wnagvYQBvBV3;JjR_+LEn11%KXwaMgHd6x^Yq2&B~T<#XrnaEh|N9A>GtBh zbS~OEEez*3Mo`Sw^#v;XMd73;s7o~Ml=l6M-2uQdlX5<5Bg+v>a*GgpdulfzSf~ zL5R%7pdUyVzOg1J5|Mu)Sz+eH4Zvi1)7hl-rw93IaqWqcf8iM`#GLYgno?OR-z4;~ zCrh4Tz8U)ULo&nPJ642OUaXQ34K&v&d_FsW6Q|r%IMus$&R^2QCj~j`j>rm1IT)YXSI&C+A{Koy`%z*e^KugU|r z6%G5&NRELy+%pao7Goo`Yw}L1%C02QE~)hi_W84>u@t97N@r`NPTri|Nsq#8D-uHi z-_K3@)Ua-kq#v5?f7gs)&@&u3S42ca4w_oOcMCFshtzW&$*mr>fGke|$O|mHIkLwg z9AX##dnByem#Pi}oiGm98!id(g1)+z?a!)@@%SC4_-YjD^$b2=^QzXrN0MXc@RfKg z-j?bN*|Jqk&F0nzKg`keUH~R32JEL9Xm926o_L0E(JTgUVDD@`u=4rk1y)FbtlbK^ zrhQ}E`kU-*0kesU)HWTs_e7TNFfZT2;J+vS-JK`0RSxrxT=D9wej?i-^!p&+LC4d0 zM#d?ruL94U{P5xL{SM(AC)RN$p`vVP1wt7fex9(zOtB$iXN`0gl!yyZ7(3Y(B2uL8 z=j;yK10@P3u)zKbrkSD4bxHyy*S_lF(T%A;93nT9`#MK=%z1Z%EG-9vNf&+--Tqp>S=5 z*|KVs^c2XSl>`J-mK$8@Ep&gSt}+Na@Dd%lX4uwlTtJrx0j6aTtMs(A ze~tVG?90ZY?)B^{d^rSK()S6GP&Kx{>&>7E!e3vp=>6oW2+EjU+@~8m>T?@C?8Thx z1JZ2uZP*!>-qukL+^6jxPb)!}{HCmO3(^Uu-Q3m$WI98-m>nZjCiA2m2y7f2S(G)@ zXM7T&&miiljb%ka$zq|6Dkal&4h(yo-36O2oMl^8hyddtLbr7?M>a=((8C4(3gWG0UvYtcXc zcLXIIwi9(^eOKPeV@Za9d4GBAl}SQ%);53}-FE623&_D$YvJp!)V0ucw|+U6GpKcl zj@NE!tDlHHiF|=sgWlxV9rS;lP1C%&T>_;ii(!YFEbaq}9MnTK5u=AInyarl#&m|EY~H*Z%^U-7wH}|Dr0ln#VCP21g}vVL<~1p8A9PZ~qSmYL%Fgq#T0Xqv)F zzJ_5P&|L*8{7;eueY)B3KS`{FMvV>G^F*0o!2F>7L2y>7j+uG%1t$3+to0(nAlK`^E4lvD&<*wdthwDoe=RYTKPxn?vCb#(Z5SrBLlC)}*d_PaD zh3zGmX>Q+0LJpHLcHf7Jh~jAysV_&SnY8(Q6sd)!x)21~-5}7GfMi%yq38sI##)`_ z0?Fyp+TgCeWr}Hz={eeEHJ!&UJ2r1yqkZt}iTYQ5BiVwTuP0WBzE8;mWp-feI#@4b&NSM`n5jsAphvA3K+nnV^Y~|Y{G}y1e|0Z*VqGARwXf@Q z->M9KE?mQl8s`5ewEPrdIrZV!6=7>r?i5L#;Gr6Xlp<;QlSyYfewJtS|LH>Axv}=$=6YGoiPcdl=3(QvfIoDHFZr!-!4_ztJ=9N4b^jx zWQKe;9C-29+H zGTF(mmbUKff}TzuR}$l)?kiKI2FN&cnH175@BcQlz+*c5|Bhe&S-U-2(w(DZ9jM`J zrsLm{^(}7KV-Qv5gnGIJy(S_np?Bai_r+{DFkV=uTN8|lgRl^DWXXW%ZC!XL)C`|r z->N1gWw0hgl3=F|Tb>k`B`zcs!;FH4aezgO3gtn{1C3G@^gB@vf*iqgI&AGSfizS}@&$8DKIaefuFR_DyIab{h0Vu`_W zSUj=;B42G(Q;nw!D=tXgSE)$dIIh2T$<1wD^RI6?z}QY3N49pazB%GZmk748wDte# zQTE&D#-7D{LN@Me-B{{LTFYgn0k#P%B6ibpdspJMQb&d&bv7&7g`K<5+nLF;qh`M) zRVscCOyb{Bki!*yvy0^}N1KAXq)xgmev%y!^f|QIGr8retZaR;wFN&NC9j1%TH~KF z1WNoIJ}5h(3Ufb+4UZpBq(GaFxU$|IP-vHAO4nM+*&zLD)BYnG)0wjMOxw}qngM4s zM)rVtmSf>Ks#%dEyB)6JTx?n!qK5ZC+pN2F?3pFO0AjU`E4w-ns|v*WZ|Yit#+w3A zrisx8T`zU8;sx9*)n#cEihc95hy<4go>DC*fJk>(}k=?3wxJP zv*`zeowZvi(7aY4Wf50nxCM zoacY$@%Z^%zQndxwARl&|T);q(3&wUtVXYH6 zJSohraQ;`b|G7Q>{$O(Jv>YHWEh_rY=>E}vswBJAuo3JPj-KcD&3Zrava??uy8RWi zrC2s(ClO^j&KlEu@C=(H5fcr`Sp#Py9lj&y1dS#m|BXlNweb*x9kV8AxTpPiQ3B!U z%b4m?0qaf_r@jWU&^Yi6AakpLaY;3p!VW48Vu zcc8I4Y~#A$tT6h6`M+1#Y4m+c3qY0s{VP1*()d-gb;vE$ExP_~uD2x?v%W~VC1b%* z^^bNue07W_-(7!%psy=1SViNEY`23ttwn!y>P%X`Hipow{5+6ydmUtzZAGz7XHqUi zVPyVWE98nSmB-(}%P5HAoQvXQLMkGPb3Y34y^r|a2hx}maGw)?pToS5ZxeEMq7|I4 zz@r+TMO zuv^_+jpEL)AEwfhTRMn9IeQf8!Pv>KLWx55!A`!OGA-+kr?sMmC$*t&Ay^z3pl_r2 z9mV7hUF-?z;?UXpG1e_FvrD?aGDiO1rlB zLWfUNOWT!iEF|Tbj;3VbK7B(?Rmt_w1yvJULv{Be_>g#-umYJvYQ}=Pf5R?r>X@pl zy0BEYCJ?iChLcp3VeQIvVXaxpVhjHKPaQ+H)+9IP9Yurh=c2!>LctZ_-_;QCq-^GR zD*f-!m7hmuad8j2yxZ6DPZ|it#~Zz`#c0b7WSA-9I9=qc=Y3R468QZk=Q^mln_0C4 zqli$P>Kn5>2|_UhSiUuGi!iejoRg*U6uRUYPwH{SD-3#j;CatNMDEwBV_Ul^5c;(h zckE?2u@1lmtyH{St^S$I=kUBPFQ2!cSUkO}ge|Hld;bkP?e&`i+426-L&@*Qev3dT zcH)uyGp3F4!Rm9n)!!3Xt9&H{I>TNhIIP?0>v*LcU|1`fR#d7Y(B*r5W>@O1 zg@XMAB-w@CZH^Smw9DI-X`SpfL-==SZYgUQ8Z$uoM@cX)KL3Aq^JR6JNa8{0k-3}` zZM5&uYBPK*mvgC2P>xC#W6PVjWL$1z-bK5eu?|b)nE~2f8AQLBRVdSSTH)BtX<4?E>Y8bow}8Dw<{31ec4sj8 zH?+x)9pl6XL+^6T{)R3#5aT;xk2=!Y%V6G5ME$UJ*g4~45Y%5n)M>hpYY83K|K5h* z21DjR^$gsmjcTdEL$F8nYrR@1)s~M)>|y~P_?u_oXqlzHp@!yrzdA}oo@Z&oXy!-O z7fZfdD&DPg3()~*3t{*7lH;7@mVLVSbC4rM#M;8R5Jmoz^6m!d^Wq`d(1;S4VW%m- zZvAAwEaPK%we??b`H&(T?MSiepVM6T*aM{=TR-G3am~>tcZ;r3x&d`I7@zra)~Xpn zYRN+A>Sky6Cb|X+imDVFLc0>-SPwgvu|%;KU}HGM?W)1QCl!Qz{_xGygVeNH2Br2I zg%hVgQ-hmo@Li)Eg692__Y(pr6`o&>?r4pFJatmzY0|4q%n~4T#+cUaRR5k_F8}Lx z_NkiOHfqp)TChTDWiaI#mI^tmbT@bz+!|!A#*&~P;u>6QXnyx;j2?WB{sYhOO&go} z1dncKKdd3m)$57+?rRhT`PRL!yUM*!TqrY4t~n==G9d}RJR5(UVjm0D6)REn4L?0) z_%2%d=_y#iJB{B*lR`$Vqcm>o^ug_HuUh4^(GF)#-Zev3CzW~M?XZT-bOEaD)&-fy z@a5kxRy>ucK75r8;|Deap?VgOWU?jb1KPdqN>?zkL)cRSIh9Y^D?gOA?i^I*m8z0U z5|@nW6M|~Q;da#0!%>{v3!amcHYX5Q(aYouzMM~AJQYbhhF>J)^(S8J_cOs$2VkTK zmN9vkXGqGH9Q-hrKxdqJl?Z}K6!|zgGh=Q*pt|U8kK4f%?>C8OO66ac$h{N|h2uS` z$JC4X5ngWAlC!$N)Rf%=t|yUOmvfTsz!%))lrtTQ2*e(R4d*fz4%Uurwr83DSJ!wogH2g~KWA|Ja=*CTM~K?h%SRoV^+U&e;NY%I?no)=)0% z$18(cIPf8(O_?w{gw_lu=WSK`w7j2?XX5T?{Nefrx3*b*6S?Pdxan(ek zTC-4I33;q>{Tgf@5Tw<9joJN!a=6dk0diAJ`>yS_0ilMdXudE{ZK z%9D%y3ERXY5Gq4-W6dttXsc89jeV@ruhZ}Dq~^iUq8u02ZF5REXoXgEMnNge5=%Za zsQp=%ud!`Mzh0}a z6q5bhS}ir-*xu~PozFH~)imO6W0{hsM9G z#V^0*01VmIrMmHIQ5$;(9-@BGu;v=FOtgUmT;_2zOfS7UApcP2Da!Z|I9^zyEB+4_ zmo0r}fqxC-gxDU>C&Sv~8wTq(>(*pRS?$XEE9N1~=atP#w?tJYtwh}wEBw+p^99PH z+K0YQtG?8qb45*ce%&;0I0NENuG^OOLr%8*avoGUwkB4AsoqnQDNHtCC zv#&^0_8Q2+5;ei=PY*M9dui+M;E3t=yJlDwO*=VFEfd+!;U4tHA4um{UQSw8iIQ%h zp3|k9*``Zn7gy<80@1P+{B8?A<8duSA#zF+i(fU&^Cs<5lb@k5<_4lH{#~l3(z1zV zY)WBCOt%jhY7%om3)H{}ie3g}g@WOPh5 z+Ob!Nw%f8B7v`LWox0>nB=@u^;fXA|M4%BhY(FD8Xr*jJfmUi~7HgFW^_+#@R^pv`8+Hai{?c@yb#IkUmD`y=Ths6e64Z1|@HTZ$ugTu7Z~?F#uda{dYV znrx&EYjqn{o-&lR#m~jqB|1Y0+P7uw_g(h;-hZg$EY`$+vUsF?G8#L1ieJSuY-;1f zAuHE=NNuC3>Ayo#QxYshOtHyxf)06tP&F^*xryXEGa(q zA8l(TjY@Xv+`tYTIvT%l`1xb@++^TP15@~+SgQ+6S(^4&oPXP^6$grwn|!VzvqZ5i zCPsF$nTin!Z3@saiHm5c*nPmc~P8Le9hU5McnWpb>2TGf@ZEhN`LFq`dxeU+ViNVmV4`9wFyG9OJ`zrD+D zf%lKdxrIRPwlOI*jw& zT(S7|eWO7qBM&QrV19#3YgGN2-jUP2-!$IznHeLiw}< z)qnhzU<8Y3;Iy!{!2(|`OkAI`&4fxw0YAE-=u4n6e}t9`p{(l(7u>yhq~KE3i|-mk zqDU8~qk;#$;`2!hS-0mN?PjcJ>-)yONH%~`dKO(C<162+z;<=L{V9AMqxTq_|80-k zjrWZadAXxo=mrWZ6Q>J&-Q>p(N%T^|_#FM!xfq&Lo<7yC>A#pr4!AJ<-Ph z=lr5m8IC<51sAOuI%n`QE+0(TF!<`uld)9}adj@^4LPz7_vy1{=5q1y5^(s_V6ws5 z!OasYzSbe-`*aH!UUxz3Fv>hc&VY7o!wFd!aNNDA=8C1ybPeL~g?{6L+q&Xgy7P08 z^XUFkm?4#7FJkOe7gZ}7g1Zv0ysDk??|csMXQApRw)_{UB@w}a zP=VQqBIORAH0`pQTJrz%FzEi-h|(P)b7(+pRR22{OqB(?aYX%?qaP#3EX!~_vOYZC zyqIDVF!cr){3Bm>i+aJV_v@<$d++VU;y)pyn>g*Z0)e$n83NnHv_wDoCAr%}uewHg zRQW*D^zgeDh2eqaWU6MyD=yHvD>Vk;FTJZ+EKB~Z$9dolDbc+I4OAEp(dfWznh1S+ zE(W<;qLb|GY`yk2)J5~K)3`4h{D|ibmi5$PS-gk-tZn~!*?Ft#L%L$HsFf!Tq5-imhRE%FRCwZc!xw%ZxGZTMV~e7!!_3dxgI?lVz6h}7-wY&~enNmrCv z)*?A?wGq0K<_s`V^j$dY$MP*F)A*amhl`jI zx=mJiSsU&qgoBl&u2|(|{bgzQ%7ToTTSdvC&r{=fiUlY6#^)KAOE2T!w<{xgQnD=n zUB_DsoOQFsH0770qRJy5I%qRm8y}MJg}Ud(m@c_KuJ3IwzC`yq981~Wv*yT9N3vOK zQYfv}6Lp9+q$Cf_ZJHdPb+UW(Q%BH={4rTa&MddSH@Pui2>ul3GEDfr{kifl1oinO z!3^?^ERvfEwfP3g&5Zwh9Vz!$aoh^(>Cl452Ol3XVb4SzEF`;53e3|B9=n;eh7E*% z5l_%fJoeL@>SI@eR8eQ6D}LNGCw&cC^H@2H{}pO>61pD>Dx1k!oRVG2DSgZ|<-4Lg z9>YbBrj%sGQne@})v}Vyv$ucsWm+_mjjzbSXj`yYf?t34` zy>@pcCbkav!1hFwOK$ z1ijfQ!@eF`RS)u?QNbz0ANE2`0R_`kw;9*9w{Gm=%+YUaXP>OW;n;Ck%?qwU{6pCi zqP~!uVbepq-9vL5{eJ-(0_FXaV83(EVEcAG{q{p>zEQCc3;RsiAJ;3`{C-1 zNU{G?*w2Rj_lo^*!v1L3x9%NmzejJs{bJa6QtbB^_UFQ$=AR7yQp?137X{B{xcS!} zAIuUseW9_Xz|r2U7kCZu%>qvegSeF+Zv-9|_L-e2H{Q-e@qV`>}FBAB_)V>S6 zC-4S=51@XXz(-QQPT&)%UnlSx)UOlxTZYv75{BII>&VX?E~M^e{CpHr}3YRpWW{RMF9#6yGq4>S!d^;#<9kK z+W`NI;Xf_p|0(O{Qu_JTew@BfaX3@?{R|vd~xV{nJ zZzb@I=iK+75g&ww-L)a5{Gi}$gHRK{cA=*6yHoKWe#w0?ED|RD->UfE+|&8Tu)_M^ zE5QHrz?!6ggY*B3{{7Fl^ZlT* oV}D+EmfJ9aYT~s|%ck+$Rq?;At7E-kaP$8EAIsSP2T&;l07iq}=>Px# literal 0 HcmV?d00001 diff --git a/output/rp-bromolow-3.10.108-prod.ko.gz b/output/rp-bromolow-3.10.108-prod.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..3213301db8d772d741205167175b798539153197 GIT binary patch literal 32685 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

0?OeRtzQJERR?)u|%#7v_sBF=Oew&+Q~ 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 iMWx4j2g41v9+Kfa;ra~S4tx6ixA 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 ap$^?bt>b1+^T;!RyhG}18vD1X$o~O{yiRoh literal 0 HcmV?d00001 diff --git a/output/rp-geminilake-4.4.180-dev.ko.gz b/output/rp-geminilake-4.4.180-dev.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..9a64e5dd2f8a34d26042d13e5b96d4dba839c4de GIT binary patch literal 66651 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ผ#N7c{sEb6L58IkJL@S$OI)rI~4p> zkF{Sck;(P)uOogduRXJElv4ZEW+O+q99y3vGm^E>M7;?+Ux9zh0za-_Xzs^XfM+g2tfxBhU<+zM$AqcuW{H$G)q9lj>3J z!v`8RM?(?(FMWIx{z>kk>)#TY79$kTHcHtByP*0>2!mAPPl9asuBQ`wno@j4H?84u3I#>Tb<0@^zHMvZ>&)aG3u z<5x$#CSS9MmsE gV`AvZK4h=EzJK4&gg8%>k literal 0 HcmV?d00001 diff --git a/output/rp-geminilake-4.4.180-prod.ko.gz b/output/rp-geminilake-4.4.180-prod.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..b74370eee35c0de3fd8814b5bf20db9679aff32e GIT binary patch literal 32313 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 O(u~zg2d7UfSNtFRK|Top literal 0 HcmV?d00001 diff --git a/output/rp-v1000-4.4.180-dev.ko.gz b/output/rp-v1000-4.4.180-dev.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..8b6bce37e8ef9a5d55b5323ec913ad1b38cd3cf3 GIT binary patch literal 66647 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 literal 0 HcmV?d00001 diff --git a/output/rp-v1000-4.4.180-prod.ko.gz b/output/rp-v1000-4.4.180-prod.ko.gz new file mode 100644 index 0000000000000000000000000000000000000000..00e23254a4d418474fc7bb5e435ced57cf6860d4 GIT binary patch literal 32308 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 O(u~zg2d7UfSNtDusXh<@ literal 0 HcmV?d00001 diff --git a/redpill_main.c b/redpill_main.c new file mode 100644 index 0000000..e576ea1 --- /dev/null +++ b/redpill_main.c @@ -0,0 +1,126 @@ +#include "internal/stealth.h" +#include "redpill_main.h" +#include "config/runtime_config.h" +#include "common.h" //commonly used headers in this module +#include "internal/intercept_execve.h" //Handling of execve() replacement +#include "internal/scsi/scsi_notifier.h" //the missing pub/sub handler for SCSI driver +#include "internal/ioscheduler_fixer.h" //reset_elevator() to correct elevator= boot cmdline +#include "config/cmdline_delegate.h" //Parsing of kernel cmdline +#include "shim/boot_device_shim.h" //Registering & deciding between boot device shims +#include "shim/bios_shim.h" //Shimming various mfgBIOS functions to make them happy +#include "shim/block_fw_update_shim.h" //Prevent firmware update from running +#include "shim/disable_exectutables.h" //Disable common problematic executables +#include "shim/pci_shim.h" //Handles PCI devices emulation +#include "shim/storage/smart_shim.h" //Handles emulation of SMART data for devices without it +#include "shim/storage/sata_port_shim.h" //Handles VirtIO & SAS storage devices/disks peculiarities +#include "shim/uart_fixer.h" //Various fixes for UART weirdness +#include "shim/pmu_shim.h" //Emulates the platform management unit +#include "internal/helper/symbol_helper.h" //kln_func + +//Handle versioning stuff +#ifndef RP_VERSION_POSTFIX +#define RP_VERSION_POSTFIX "(NULL)" +#endif +#define RP_VERSION_MAJOR 0 +#define RP_VERSION_MINOR 6 +#define STRINGIFY(x) #x +#define VERSIONIFY(major,minor,postfix) "v" STRINGIFY(major) "." STRINGIFY(minor) "-" postfix +#define RP_VERSION_STR VERSIONIFY(RP_VERSION_MAJOR, RP_VERSION_MINOR, RP_VERSION_POSTFIX) + +/** + * Force panic to land on a stack trace + * + * This ensures we always get this on the stack trace so that we know it was an intentional crash due to a detected + * error rather than an accidental bug. + */ +void noinline __noreturn rp_crash(void) { + //Deliberately not reveling any context in case we're running in stealth mode + //This message is a generic one from arch/x86/kernel/dumpstack.c + panic("Fatal exception"); +} + +static int __init init_(void) +{ + int out = 0; + + pr_loc_dbg("================================================================================================"); + pr_loc_inf("RedPill %s loading...", RP_VERSION_STR); + + if ( + get_kln_p() < 0 //Find pointer of kallsyms_lookup_name function, This MUST be the first entry + || (out = extract_config_from_cmdline(¤t_config)) != 0 //This MUST be the second entry + || (out = populate_runtime_config(¤t_config)) != 0 //This MUST be third + || (out = register_uart_fixer(current_config.hw_config)) != 0 //Fix consoles ASAP + || (out = register_scsi_notifier()) != 0 //Load SCSI notifier so that boot shim (& others) can use it + || (out = register_sata_port_shim()) //This should be bfr boot shim as it can fix some things need by boot + || (out = register_boot_shim(¤t_config.boot_media)) //Make sure we're quick with this one + || (out = register_execve_interceptor()) != 0 //Register this reasonably high as other modules can use it blindly + || (out = register_bios_shim(current_config.hw_config)) != 0 + || (out = register_disable_executables_shim()) != 0 + || (out = register_fw_update_shim()) != 0 +#ifndef DBG_DISABLE_UNLOADABLE + || (out = register_pci_shim(current_config.hw_config)) != 0 //it's a core hw but it's not checked early +#endif + || (out = register_disk_smart_shim()) != 0 //provide fake SMART to userspace + || (out = register_pmu_shim(current_config.hw_config)) != 0 //this is used as early as mfgBIOS loads (=late) + || (out = initialize_stealth(¤t_config)) != 0 //Should be after any shims to let shims have real stuff + || (out = reset_elevator()) != 0 //Cosmetic, can be the last one + ) + goto error_out; + + pr_loc_inf("RedPill %s loaded successfully (stealth=%d)", RP_VERSION_STR, STEALTH_MODE); + return 0; + + error_out: + pr_loc_crt("RedPill %s cannot be loaded, initializer error=%d", RP_VERSION_STR, out); +#ifdef KP_ON_LOAD_ERROR + rp_crash(); +#else + return out; +#endif +} +module_init(init_); + +#if STEALTH_MODE < STEALTH_MODE_FULL //module cannot be unloaded in full-stealth anyway +static void __exit cleanup_(void) +{ + pr_loc_inf("RedPill %s unloading...", RP_VERSION_STR); + + int (*cleanup_handlers[])(void ) = { + uninitialize_stealth, + unregister_pmu_shim, + unregister_disk_smart_shim, +#ifndef DBG_DISABLE_UNLOADABLE + unregister_pci_shim, +#endif + unregister_fw_update_shim, + unregister_disable_executables_shim, + unregister_bios_shim, + unregister_execve_interceptor, + unregister_boot_shim, + unregister_sata_port_shim, + unregister_scsi_notifier, + unregister_uart_fixer + }; + + int out; + for (int i = 0; i < ARRAY_SIZE(cleanup_handlers); i++) { + pr_loc_dbg("Calling cleanup handler %pF<%p>", cleanup_handlers[i], cleanup_handlers[i]); + out = cleanup_handlers[i](); + if (out != 0) + pr_loc_wrn("Cleanup handler %pF failed with code=%d", cleanup_handlers[i], out); + } + + free_runtime_config(¤t_config); //A special snowflake ;) + + pr_loc_inf("RedPill %s is dead", RP_VERSION_STR); + pr_loc_dbg("================================================================================================"); +} +module_exit(cleanup_); + +MODULE_AUTHOR("TTG"); +MODULE_VERSION(RP_VERSION_STR); +#endif + + +MODULE_LICENSE("GPL"); diff --git a/redpill_main.h b/redpill_main.h new file mode 100644 index 0000000..f14d536 --- /dev/null +++ b/redpill_main.h @@ -0,0 +1,4 @@ +#ifndef REDPILLLKM_REDPILL_MAIN_H +#define REDPILLLKM_REDPILL_MAIN_H + +#endif //REDPILLLKM_REDPILL_MAIN_H \ No newline at end of file diff --git a/shim/bios/bios_hwcap_shim.c b/shim/bios/bios_hwcap_shim.c new file mode 100644 index 0000000..e50c379 --- /dev/null +++ b/shim/bios/bios_hwcap_shim.c @@ -0,0 +1,117 @@ +/** + * Overrides GetHwCapability to provide additional capabilities for older platforms (e.g. 3615xs) + */ +#include "bios_hwcap_shim.h" +#include "../../common.h" +#include "../shim_base.h" +#include "../../internal/override/override_symbol.h" //overriding GetHWCapability +#include "../../config/platform_types.h" //hw_config, platform_has_hwmon_* +#include //CAPABILITY_*, CAPABILITY + +#define SHIM_NAME "mfgBIOS HW Capability" + +static const struct hw_config *hw_config = NULL; +static override_symbol_inst *GetHwCapability_ovs = NULL; + +static void dbg_compare_cap_value(SYNO_HW_CAPABILITY id, int computed_support) +{ +#ifdef DBG_HWCAP + int org_fout = -1; + CAPABILITY org_cap = { '\0' }; + org_cap.id = id; + int ovs_fout = call_overridden_symbol(org_fout, GetHwCapability_ovs, &org_cap); + + pr_loc_dbg("comparing GetHwCapability(id=%d)->support => computed=%d vs. real=%d [org_fout=%d, ovs_fout=%d]", id, + computed_support, org_cap.support, org_fout, ovs_fout); +#endif +} + +static int GetHwCapability_shim(CAPABILITY *cap) +{ + if (unlikely(!cap)) { + pr_loc_err("Got NULL-ptr to %s", __FUNCTION__); + return -EINVAL; + } + + switch (cap->id) { + case CAPABILITY_THERMAL: + cap->support = platform_has_hwmon_thermal(hw_config) ? 1 : 0; + dbg_compare_cap_value(cap->id, cap->support); + return 0; + + case CAPABILITY_CPU_TEMP: + cap->support = hw_config->has_cpu_temp; + dbg_compare_cap_value(cap->id, cap->support); + return 0; + + case CAPABILITY_FAN_RPM_RPT: + cap->support = platform_has_hwmon_fan_rpm(hw_config) ? 1 : 0; + dbg_compare_cap_value(cap->id, cap->support); + return 0; + + case CAPABILITY_DISK_LED_CTRL: + case CAPABILITY_AUTO_POWERON: + case CAPABILITY_S_LED_BREATH: + case CAPABILITY_MICROP_PWM: + case CAPABILITY_CARDREADER: + case CAPABILITY_LCM: { + if (unlikely(!GetHwCapability_ovs)) { + pr_loc_bug("%s() was called with proxy need when no OVS was available", __FUNCTION__); + return -EIO; + } + + int org_fout = -1; + int ovs_fout = call_overridden_symbol(org_fout, GetHwCapability_ovs, cap); + pr_loc_dbg("proxying GetHwCapability(id=%d)->support => real=%d [org_fout=%d, ovs_fout=%d]", cap->id, + cap->support, org_fout, ovs_fout); + + return org_fout; + } + + default: + pr_loc_err("unknown GetHwCapability(id=%d) => out=-EINVAL", cap->id); + return -EINVAL; + } +} + +int register_bios_hwcap_shim(const struct hw_config *hw) +{ + shim_reg_in(); + + if (unlikely(GetHwCapability_ovs)) + shim_reg_already(); + + hw_config = hw; + override_symbol_or_exit_int(GetHwCapability_ovs, "GetHwCapability", GetHwCapability_shim); + + shim_reg_ok(); + return 0; +} + +int unregister_bios_hwcap_shim(void) +{ + shim_ureg_in(); + + if (unlikely(!GetHwCapability_ovs)) + return 0; //this is deliberately a noop + + int out = restore_symbol(GetHwCapability_ovs); + if (unlikely(out != 0)) { + pr_loc_err("Failed to restore GetHwCapability - error=%d", out); + return out; + } + GetHwCapability_ovs = NULL; + + shim_ureg_ok(); + return 0; +} + +int reset_bios_hwcap_shim(void) +{ + shim_reset_in(); + put_overridden_symbol(GetHwCapability_ovs); + GetHwCapability_ovs = NULL; + + shim_reset_ok(); + return 0; +} \ No newline at end of file diff --git a/shim/bios/bios_hwcap_shim.h b/shim/bios/bios_hwcap_shim.h new file mode 100644 index 0000000..67308cf --- /dev/null +++ b/shim/bios/bios_hwcap_shim.h @@ -0,0 +1,23 @@ +#ifndef REDPILL_BIOS_HWCAP_SHIM_H +#define REDPILL_BIOS_HWCAP_SHIM_H + +#include //bool + +struct hw_config; +int register_bios_hwcap_shim(const struct hw_config *hw); + +/** + * This function should be called when we're unloading cleanly (=mfgBIOS is alive, we're going away). If the bios went + * away on its own call reset_bios_hwcap_shim() + */ +int unregister_bios_hwcap_shim(void); + +/** + * This function should be called when we're unloading because mfgBIOS went away. If the unload should be clean and + * restore all mfgBIOS elements to its original state (i.e. the mfgBIOS is still loaded and not currently unloading) + * call unregister_bios_hwcap_shim() instead. + */ +int reset_bios_hwcap_shim(void); + + +#endif //REDPILL_BIOS_HWCAP_SHIM_H diff --git a/shim/bios/bios_hwmon_shim.c b/shim/bios/bios_hwmon_shim.c new file mode 100644 index 0000000..1ad7dd5 --- /dev/null +++ b/shim/bios/bios_hwmon_shim.c @@ -0,0 +1,374 @@ +/** + * Responds to all HWMON ("hardware monitor") calls coming to the mfgBIOS + * + * This submodule emulates both legitimate HWMON calls as well as "legacy" hardware monitoring calls get_fan_status() + */ +#include "bios_hwmon_shim.h" +#include "../shim_base.h" //shim_reg_in(), shim_reg_ok(), shim_reset_in(), shim_reset_ok() +#include "bios_shims_collection.h" //_shim_bios_module_entry() +#include "../../common.h" +#include "../../internal/helper/math_helper.h" //prandom_int_range_stable +#include "mfgbios_types.h" //HWMON_* +#include "../../config/platform_types.h" //HWMON_*_ID + +#define SHIM_NAME "mfgBIOS HW Monitor" +#ifdef DBG_HWMON +#define hwmon_pr_loc_dbg(...) pr_loc_dbg(__VA_ARGS__) +#else +#define hwmon_pr_loc_dbg(...) //noop +#endif + +/************************************* Standards for generating fake sensor readings **********************************/ +//Standard deviations for ongoing sensor readings +#define FAN_SPEED_DEV 50 //Fan speed (RPM) deviation +#define VOLT_DEV 5 //Voltage (mV) deviation +#define TEMP_DEV 2 //Temperature (°C) deviation + +#define FAKE_SURFACE_TEMP_MIN 25 +#define FAKE_SURFACE_TEMP_MAX 35 +#define FAKE_CPU_TEMP_MIN 55 +#define FAKE_CPU_TEMP_MAX 65 +#define FAKE_RPM_MIN 980 +#define FAKE_RPM_MAX 1000 + +//These percentages are precalculated as we cannot use FPU [safely and easily] in kernel space +#define FAKE_V33_MIN 3135 // mV (-5% of 3.3V) +#define FAKE_V33_MAX 3465 // mV (+5% of 3.3V) +#define FAKE_V5_MIN 4750 // mV (-5% of 5.0V) +#define FAKE_V5_MAX 5250 // mV (+5% of 5.0V) +#define FAKE_V12_MIN 11400 // mV (-5% of 12.0V) +#define FAKE_V12_MAX 12600 // mV (+5% of 12.0V) +#define fake_volt_min(type) (hwmon_sys_vsens_type_base[(type)][0]) // mV +#define fake_volt_max(type) (hwmon_sys_vsens_type_base[(type)][1]) // mV + +/************************************* Maps between hwmon sensor types & their names **********************************/ +static const char *hwmon_sys_thermal_zone_id_map[] = { + [HWMON_SYS_TZONE_NULL_ID] = "", + [HWMON_SYS_TZONE_REMOTE1_ID] = HWMON_SYS_TZONE_REMOTE1_NAME, + [HWMON_SYS_TZONE_REMOTE2_ID] = HWMON_SYS_TZONE_REMOTE2_NAME, + [HWMON_SYS_TZONE_LOCAL_ID] = HWMON_SYS_TZONE_LOCAL_NAME, + [HWMON_SYS_TZONE_SYSTEM_ID] = HWMON_SYS_TZONE_SYSTEM_NAME, + [HWMON_SYS_TZONE_ADT1_LOC_ID] = HWMON_SYS_TZONE_ADT1_LOC_NAME, + [HWMON_SYS_TZONE_ADT2_LOC_ID] = HWMON_SYS_TZONE_ADT2_LOC_NAME, +}; + +static const char *hwmon_sys_vsens_id_map[] = { + [HWMON_SYS_VSENS_NULL_ID] = "", + [HWMON_SYS_VSENS_VCC_ID] = HWMON_SYS_VSENS_VCC_NAME, + [HWMON_SYS_VSENS_VPP_ID] = HWMON_SYS_VSENS_VPP_NAME, + [HWMON_SYS_VSENS_V33_ID] = HWMON_SYS_VSENS_V33_NAME, + [HWMON_SYS_VSENS_V5_ID] = HWMON_SYS_VSENS_V5_NAME, + [HWMON_SYS_VSENS_V12_ID] = HWMON_SYS_VSENS_V12_NAME, + [HWMON_SYS_VSENS_ADT1_V33_ID] = HWMON_SYS_VSENS_ADT1_V33_NAME, + [HWMON_SYS_VSENS_ADT2_V33_ID] = HWMON_SYS_VSENS_ADT2_V33_NAME, +}; + +static const int hwmon_sys_vsens_type_base[][2] = { + [HWMON_SYS_VSENS_NULL_ID] = {0, 0}, + [HWMON_SYS_VSENS_VCC_ID] = { FAKE_V12_MIN, FAKE_V12_MAX }, //todo: this is probably per-model + [HWMON_SYS_VSENS_VPP_ID] = { 100, 500 }, //todo: if this is really peak-to-peak it should be small + [HWMON_SYS_VSENS_V33_ID] = { FAKE_V33_MIN, FAKE_V33_MAX }, + [HWMON_SYS_VSENS_V5_ID] = { FAKE_V5_MIN, FAKE_V5_MAX }, + [HWMON_SYS_VSENS_V12_ID] = { FAKE_V12_MIN, FAKE_V12_MAX }, + [HWMON_SYS_VSENS_ADT1_V33_ID] = { FAKE_V33_MIN, FAKE_V33_MAX }, + [HWMON_SYS_VSENS_ADT2_V33_ID] = { FAKE_V33_MIN, FAKE_V33_MAX }, +}; + +static const char *hwmon_sys_fan_id_map[] = { + [HWMON_SYS_FAN_NULL_ID] = "", + [HWMON_SYS_FAN1_ID] = HWMON_SYS_FAN1_RPM, + [HWMON_SYS_FAN2_ID] = HWMON_SYS_FAN2_RPM, + [HWMON_SYS_FAN3_ID] = HWMON_SYS_FAN3_RPM, + [HWMON_SYS_FAN4_ID] = HWMON_SYS_FAN4_RPM, +}; + +static const char *hwmon_hdd_bp_id_map[] = { + [HWMON_SYS_HDD_BP_NULL_ID] = "", + [HWMON_SYS_HDD_BP_DETECT_ID] = HWMON_HDD_BP_DETECT, + [HWMON_SYS_HDD_BP_ENABLE_ID] = HWMON_HDD_BP_ENABLE, +}; + +//todo: it's defined as __used as we know the structure but don't implement it yet +static const __used char *hwmon_psu_id_map[] = { + [HWMON_PSU_NULL_ID] = "", + [HWMON_PSU_PWR_IN_ID] = HWMON_PSU_SENSOR_PIN, + [HWMON_PSU_PWR_OUT_ID] = HWMON_PSU_SENSOR_POUT, +#if RP_MODULE_TARGET_VER == 6 + [HWMON_PSU_TEMP_ID] = HWMON_PSU_SENSOR_TEMP, +#elif RP_MODULE_TARGET_VER == 7 + [HWMON_PSU_TEMP1_ID] = HWMON_PSU_SENSOR_TEMP1, + [HWMON_PSU_TEMP2_ID] = HWMON_PSU_SENSOR_TEMP2, + [HWMON_PSU_TEMP3_ID] = HWMON_PSU_SENSOR_TEMP3, + [HWMON_PSU_FAN_VOLT] = HWMON_PSU_SENSOR_FAN_VOLT, +#endif + [HWMON_PSU_FAN_RPM_ID] = HWMON_PSU_SENSOR_FAN, + [HWMON_PSU_STATUS_ID] = HWMON_PSU_SENSOR_STATUS, +}; + +//todo: it's defined as __used as we know the structure but don't implement it yet +static const __used char *hwmon_current_id_map[] = { + [HWMON_SYS_CURR_NULL_ID] = "", + [HWMON_SYS_CURR_ADC_ID] = HWMON_SYS_CURR_ADC_NAME, +}; + +/************************************************ Various small tools *************************************************/ +static const struct hw_config_hwmon *hwmon_cfg = NULL; +#define guard_hwmon_cfg() \ + if (unlikely(!hwmon_cfg)) { \ + pr_loc_bug("Called %s without hwmon_cfg context being populated", __FUNCTION__); \ + return -EIO; \ + } + +#define guarded_strscpy(dest, src, count) \ + if (unlikely(strscpy(dest, src, count) == -E2BIG)) { \ + pr_loc_err("Failed to copy %lu bytes string", count); \ + return -EFAULT; \ + } + +/******************************************* mfgBIOS LKM replacement functions ****************************************/ +/** + * Provides fan status + * + * Currently the fan is always assumed to be running + */ +static int bios_get_fan_state(int no, enum MfgCompatFanStatus *status) +{ + hwmon_pr_loc_dbg("mfgBIOS: GET_FAN_STATE(%d) => MFGC_FAN_RUNNING", no); + *status = MFGC_FAN_RUNNING; + return 0; +} + +static int cur_cpu_temp = 0; +/** + * Returns CPU temperature across all cores + * + * Currently it always returns a fake value. However, it should only do so if running under hypervisor. In bare-metal + * scenario we can simply proxy to syno_cpu_temperature() [or not override that part at all]. + */ +static int bios_get_cpu_temp(SYNOCPUTEMP *temp) +{ + int fake_temp = prandom_int_range_stable(&cur_cpu_temp, TEMP_DEV, FAKE_CPU_TEMP_MIN, FAKE_CPU_TEMP_MAX); + temp->cpu_num = MAX_CPU; + for(int i=0; i < MAX_CPU; ++i) + temp->cpu_temp[i] = fake_temp; + + hwmon_pr_loc_dbg("mfgBIOS: GET_CPU_TEMP(surf=%d, cpuNum=%d) => %d°C", temp->blSurface, temp->cpu_num, fake_temp); + + return 0; +} + +static int *hwmon_thermals = NULL; +/** + * Returns various HWMON temperatures + * + * @param reading Pointer to save results + * @return 0 on success, -E on error + */ +static int bios_hwmon_get_thermal(SYNO_HWMON_SENSOR_TYPE *reading) +{ + guard_hwmon_cfg(); + if (unlikely(!hwmon_thermals)) + kzalloc_or_exit_int(hwmon_thermals, sizeof(int) * HWMON_SYS_THERMAL_ZONE_IDS); + + guarded_strscpy(reading->type_name, HWMON_SYS_THERMAL_NAME, sizeof(reading->type_name)); + hwmon_pr_loc_dbg("mfgBIOS: => %s(type=%s)", __FUNCTION__, reading->type_name); + + for (int i = 0; i < HWMON_SYS_THERMAL_ZONE_IDS; i++) { + if (hwmon_cfg->sys_thermal[i] == HWMON_SYS_TZONE_NULL_ID) + break; + + guarded_strscpy(reading->sensor[i].sensor_name, hwmon_sys_thermal_zone_id_map[hwmon_cfg->sys_thermal[i]], + sizeof(reading->sensor[i].sensor_name)); //Save the name of the sensor + hwmon_thermals[i] = prandom_int_range_stable(&hwmon_thermals[i], TEMP_DEV, FAKE_SURFACE_TEMP_MIN, + FAKE_SURFACE_TEMP_MAX); + snprintf(reading->sensor[i].value, sizeof(reading->sensor[i].value), "%d", hwmon_thermals[i]); + ++reading->sensor_num; + + hwmon_pr_loc_dbg("mfgBIOS: <= %s() %s->%d °C", __FUNCTION__, + hwmon_sys_thermal_zone_id_map[hwmon_cfg->sys_thermal[i]], hwmon_thermals[i]); + } + + return 0; +} + +static int *hwmon_voltages = NULL; +/** + * Returns various HWMON voltages + * + * @param reading Pointer to save results + * @return 0 on success, -E on error + */ +static int bios_hwmon_get_voltages(SYNO_HWMON_SENSOR_TYPE *reading) +{ + guard_hwmon_cfg(); + if (unlikely(!hwmon_voltages)) + kzalloc_or_exit_int(hwmon_voltages, sizeof(int) * HWMON_SYS_VOLTAGE_SENSOR_IDS); + + guarded_strscpy(reading->type_name, HWMON_SYS_VOLTAGE_NAME, sizeof(reading->type_name)); + hwmon_pr_loc_dbg("mfgBIOS: => %s(type=%s)", __FUNCTION__, reading->type_name); + + for (int i = 0; i < HWMON_SYS_VOLTAGE_SENSOR_IDS; i++) { + if (hwmon_cfg->sys_voltage[i] == HWMON_SYS_VSENS_NULL_ID) + break; + + guarded_strscpy(reading->sensor[i].sensor_name, hwmon_sys_vsens_id_map[hwmon_cfg->sys_voltage[i]], + sizeof(reading->sensor[i].sensor_name)); //Save the name of the sensor + hwmon_voltages[i] = prandom_int_range_stable(&hwmon_voltages[i], VOLT_DEV, + fake_volt_min(hwmon_cfg->sys_voltage[i]), + fake_volt_max(hwmon_cfg->sys_voltage[i])); + snprintf(reading->sensor[i].value, sizeof(reading->sensor[i].value), "%d", hwmon_voltages[i]); + ++reading->sensor_num; + + hwmon_pr_loc_dbg("mfgBIOS: <= %s() %s->%d mV", __FUNCTION__, hwmon_sys_vsens_id_map[hwmon_cfg->sys_voltage[i]], + hwmon_voltages[i]); + } + + return 0; +} + +static int *hwmon_fans_rpm = NULL; +/** + * Returns HWMON fan speeds + * + * @param reading Pointer to save results + * @return 0 on success, -E on error + */ +static int bios_hwmon_get_fans_rpm(SYNO_HWMON_SENSOR_TYPE *reading) +{ + guard_hwmon_cfg(); + if (unlikely(!hwmon_fans_rpm)) + kzalloc_or_exit_int(hwmon_fans_rpm, sizeof(int) * HWMON_SYS_FAN_RPM_IDS); + + guarded_strscpy(reading->type_name, HWMON_SYS_FAN_RPM_NAME, sizeof(reading->type_name)); + hwmon_pr_loc_dbg("mfgBIOS: => %s(type=%s)", __FUNCTION__, reading->type_name); + + for (int i = 0; i < HWMON_SYS_FAN_RPM_IDS; i++) { + if (hwmon_cfg->sys_fan_speed_rpm[i] == HWMON_SYS_FAN_NULL_ID) + break; + + guarded_strscpy(reading->sensor[i].sensor_name, hwmon_sys_fan_id_map[hwmon_cfg->sys_fan_speed_rpm[i]], + sizeof(reading->sensor[i].sensor_name)); //Save the name of the sensor + hwmon_fans_rpm[i] = prandom_int_range_stable(&hwmon_fans_rpm[i], FAN_SPEED_DEV, FAKE_RPM_MIN, FAKE_RPM_MAX); + snprintf(reading->sensor[i].value, sizeof(reading->sensor[i].value), "%d", hwmon_fans_rpm[i]); + ++reading->sensor_num; + + hwmon_pr_loc_dbg("mfgBIOS: <= %s() %s->%d RPM", __FUNCTION__, + hwmon_sys_fan_id_map[hwmon_cfg->sys_fan_speed_rpm[i]], hwmon_fans_rpm[i]); + } + + return 0; +} + +/** + * Returns HWMON disk backplane status + * + * Currently values here are just a guesstimation - we don't have a platform to see the real values but based on their + * names it's assumed these are number of detected and enabled disks. + * This probably should ask the SCSI driver for the number of disks overall (as no PC architecture has any clue about + * number of disks present physically if they don't register with the system). On a real hardware it's probably checked + * by some contact switch/IR sensor to check if a given slot for a disk isn't empty. + * + * @param reading Pointer to save results + * @return 0 on success, -E on error + */ +static int bios_hwmon_get_hdd_backplane(SYNO_HWMON_SENSOR_TYPE *reading) +{ + guard_hwmon_cfg(); + const int hdd_num = 1; //todo: this should be taken from SCSI layer + + guarded_strscpy(reading->type_name, HWMON_HDD_BP_STATUS_NAME, sizeof(reading->type_name)); + hwmon_pr_loc_dbg("mfgBIOS: => %s(type=%s)", __FUNCTION__, reading->type_name); + + for (int i = 0; i < HWMON_SYS_HDD_BP_IDS; i++) { + if (hwmon_cfg->hdd_backplane[i] == HWMON_SYS_HDD_BP_NULL_ID) + break; + + guarded_strscpy(reading->sensor[i].sensor_name, hwmon_hdd_bp_id_map[hwmon_cfg->hdd_backplane[i]], + sizeof(reading->sensor[i].sensor_name)); //Save the name of the sensor + snprintf(reading->sensor[i].value, sizeof(reading->sensor[i].value), "%d", hdd_num); + ++reading->sensor_num; + + hwmon_pr_loc_dbg("mfgBIOS: <= %s() %s->%d", __FUNCTION__, hwmon_hdd_bp_id_map[hwmon_cfg->hdd_backplane[i]], + hdd_num); + } + + return 0; +} + +/** + * (Should) Return HWMON power supplies status + * + * Currently this command is not implemented and always return an error as we haven't yet seen any devices using it. + * + * @param reading Pointer to save results + * @return 0 on success, -E on error + */ +static int bios_hwmon_get_psu_status(struct hw_config_hwmon *hwc, SYNO_HWMON_SENSOR_TYPE *reading) +{ + pr_loc_wrn("mfgBIOS: **UNIMPLEMENTED** %s(type=%s)", __FUNCTION__, HWMON_PSU_STATUS_NAME); + return -EIO; //todo: we haven't [yet] seen a device using this +} + +/** + * (Should) Return HWMON power consumption + * + * Currently this command is not implemented and always return an error as we haven't yet seen any devices using it. + * + * @param hwc Platform HWMON configuration + * @param reading Pointer to save results + * + * @return 0 on success, -E on error + */ +static int bios_hwmon_get_current(struct hw_config_hwmon *hwc, SYNO_HWMON_SENSOR_TYPE *reading) +{ + pr_loc_wrn("mfgBIOS: **UNIMPLEMENTED** %s(type=%s)", __FUNCTION__, HWMON_SYS_CURRENT_NAME); + return -EIO; //todo: we haven't [yet] seen a device using this +} + + +/************************************************ mfgBIOS shim interface **********************************************/ +int shim_bios_module_hwmon_entries(const struct hw_config *hw) +{ + shim_reg_in(); + hwmon_cfg = &hw->hwmon; + + _shim_bios_module_entry(VTK_GET_FAN_STATE, bios_get_fan_state); + + if (hw->has_cpu_temp) + _shim_bios_module_entry(VTK_GET_CPU_TEMP, bios_get_cpu_temp); + + if (platform_has_hwmon_thermal(hw)) + _shim_bios_module_entry(VTK_GET_HWMON_THERMAL, bios_hwmon_get_thermal); + + if (platform_has_hwmon_voltage(hw)) + _shim_bios_module_entry(VTK_GET_HWMON_VOLTAGE, bios_hwmon_get_voltages); + + if (platform_has_hwmon_fan_rpm(hw)) + _shim_bios_module_entry(VTK_GET_HWMON_FAN_RPM, bios_hwmon_get_fans_rpm); + + if (platform_has_hwmon_hdd_bpl(hw)) + _shim_bios_module_entry(VTK_GET_HWMON_HDD_BKPLANE, bios_hwmon_get_hdd_backplane); + + if (platform_has_hwmon_psu_status(hw)) + _shim_bios_module_entry(VTK_GET_HWMON_PSU_STATUS, bios_hwmon_get_psu_status); + + if (platform_has_hwmon_current_sens(hw)) + _shim_bios_module_entry(VTK_GET_HWMON_CURRENT, bios_hwmon_get_current); + + shim_reg_ok(); + return 0; +} + +int reset_bios_module_hwmon_shim(void) +{ + shim_reset_in(); + + hwmon_cfg = NULL; + cur_cpu_temp = 0; + try_kfree(hwmon_thermals); + try_kfree(hwmon_voltages); + try_kfree(hwmon_fans_rpm); + + shim_reset_ok(); + return 0; +} \ No newline at end of file diff --git a/shim/bios/bios_hwmon_shim.h b/shim/bios/bios_hwmon_shim.h new file mode 100644 index 0000000..e9c1b41 --- /dev/null +++ b/shim/bios/bios_hwmon_shim.h @@ -0,0 +1,12 @@ +#ifndef REDPILL_BIOS_HWMON_SHIM_H +#define REDPILL_BIOS_HWMON_SHIM_H + +#include + +struct hw_config; + +//This should be called from shim_bios_module() as it depends on the state of the vtable; it can be called many times +int shim_bios_module_hwmon_entries(const struct hw_config *hw); +int reset_bios_module_hwmon_shim(void); + +#endif //REDPILL_BIOS_HWMON_SHIM_H diff --git a/shim/bios/bios_shims_collection.c b/shim/bios/bios_shims_collection.c new file mode 100644 index 0000000..10e8294 --- /dev/null +++ b/shim/bios/bios_shims_collection.c @@ -0,0 +1,309 @@ +#include "bios_shims_collection.h" +#include "../../config/platform_types.h" +#include "rtc_proxy.h" +#include "bios_hwmon_shim.h" +#include "../../common.h" +#include "../../internal/helper/symbol_helper.h" //kernel_has_symbol() +#include "../../internal/override/override_symbol.h" //shimming leds stuff + + +#define DECLARE_NULL_ZERO_INT(for_what) \ + static __used int bios_##for_what##_null_zero_int(void) { \ + pr_loc_dbg("mfgBIOS: nullify zero-int for " #for_what); \ + return 0; \ + } +#define SHIM_TO_NULL_ZERO_INT(for_what) _shim_bios_module_entry(for_what, bios_##for_what##_null_zero_int); + +/********************************************* mfgBIOS LKM static shims ***********************************************/ +static unsigned long org_shimmed_entries[VTK_SIZE] = { '\0' }; //original entries which were shimmed by custom entries +static unsigned long cust_shimmed_entries[VTK_SIZE] = { '\0' }; //custom entries which were set as shims + +static int shim_get_gpio_pin_usable(int *pin) +{ + pin[1] = 0; + return 0; +} + +static int shim_set_gpio_pin_usable(int *pin) +{ + pr_loc_dbg("set_gpio pin info 0 %d", pin[0]); + pr_loc_dbg("set_gpio pin info 1 %d", pin[1]); + pr_loc_dbg("set_gpio pin info 2 %d", pin[2]); + pr_loc_dbg("set_gpio pin info 3 %d", pin[3]); + return 0; +} + +static int bios_get_buz_clr(unsigned char *state) +{ + *state = 0; + return 0; +} + +/***************************************** Debug shims for unknown bios functions **************************************/ +DECLARE_NULL_ZERO_INT(VTK_SET_FAN_STATE); +DECLARE_NULL_ZERO_INT(VTK_SET_DISK_LED); +DECLARE_NULL_ZERO_INT(VTK_SET_PWR_LED); +// DECLARE_NULL_ZERO_INT(VTK_SET_GPIO_PIN); +DECLARE_NULL_ZERO_INT(VTK_SET_GPIO_PIN_BLINK); +DECLARE_NULL_ZERO_INT(VTK_SET_ALR_LED); +DECLARE_NULL_ZERO_INT(VTK_SET_BUZ_CLR); +DECLARE_NULL_ZERO_INT(VTK_SET_CPU_FAN_STATUS); +DECLARE_NULL_ZERO_INT(VTK_SET_PHY_LED); +DECLARE_NULL_ZERO_INT(VTK_SET_HDD_ACT_LED); +DECLARE_NULL_ZERO_INT(VTK_GET_MICROP_ID); +DECLARE_NULL_ZERO_INT(VTK_SET_MICROP_ID); + +/********************************************** mfgBIOS shimming routines *********************************************/ +static unsigned long *vtable_start = NULL; //set when shim_bios_module is called() +void _shim_bios_module_entry(const unsigned int idx, const void *new_sym_ptr) +{ + if (unlikely(!vtable_start)) { + pr_loc_bug("%s called without vtable start populated - are you calling it outside of shim_bios_module scope?!", + __FUNCTION__); + return; + } + + if (unlikely(idx > VTK_SIZE-1)) { + pr_loc_bug("Attempted shim on index %d - out of range", idx); + return; + } + + //The vtable entry is either not shimmed OR already shimmed with what we set before OR already *was* shimmed but + // external (i.e. mfgBIOS) code overrode the shimmed entry. + //We only save the original entry if it was set by the mfgBIOS (so not shimmed yet or ext. override situation) + + //it was already shimmed and the shim is still there => noop + if (cust_shimmed_entries[idx] && cust_shimmed_entries[idx] == vtable_start[idx]) + return; + + pr_loc_dbg("mfgBIOS vtable [%d] originally %ps<%p> will now be %ps<%p>", idx, (void *) vtable_start[idx], + (void *) vtable_start[idx], new_sym_ptr, new_sym_ptr); + org_shimmed_entries[idx] = vtable_start[idx]; + cust_shimmed_entries[idx] = (unsigned long)new_sym_ptr; + vtable_start[idx] = cust_shimmed_entries[idx]; +} + +/** + * Prints a table of memory between vtable_start and vtable_end, trying to resolve symbols as it goes + */ +static void print_debug_symbols(const unsigned long *vtable_end) +{ + if (unlikely(!vtable_start)) { + pr_loc_dbg("Cannot print - no vtable address"); + return; + } + + int im = vtable_end - vtable_start; //Should be multiplies of 8 in general (64 bit alignment) + pr_loc_dbg("Will print %d bytes of memory from %p", im, vtable_start); + + unsigned long *call_ptr = vtable_start; + unsigned char *byte_ptr = (char *)vtable_start; + for (int i = 0; i < im; i++, byte_ptr++) { + pr_loc_dbg_raw("%02x ", *byte_ptr); + if ((i+1) % 8 == 0) { + pr_loc_dbg_raw(" [%02d] 0x%03x \t%p\t%pS\n", i / 8, i-7, (void *) (*call_ptr), (void *) (*call_ptr)); + call_ptr++; + } + } + pr_loc_dbg_raw("\n"); + + pr_loc_dbg("Finished printing memory at %p", byte_ptr); +} + +/** + * Applies shims to the vtable used by the bios + * + * These calls may execute multiple times as the mfgBIOS is loading. + * + * @return true when shimming succeeded, false otherwise + */ +bool shim_bios_module(const struct hw_config *hw, struct module *mod, unsigned long *vt_start, unsigned long *vt_end) +{ + if (unlikely(!vt_start || !vt_end)) { + pr_loc_bug("%s called without vtable start or vt_end populated?!", __FUNCTION__); + return false; + } + + vtable_start = vt_start; + + print_debug_symbols(vt_end); + SHIM_TO_NULL_ZERO_INT(VTK_SET_FAN_STATE); + SHIM_TO_NULL_ZERO_INT(VTK_SET_DISK_LED); + SHIM_TO_NULL_ZERO_INT(VTK_SET_PWR_LED); + // SHIM_TO_NULL_ZERO_INT(VTK_SET_GPIO_PIN); + _shim_bios_module_entry(VTK_GET_GPIO_PIN, shim_get_gpio_pin_usable); + _shim_bios_module_entry(VTK_SET_GPIO_PIN, shim_set_gpio_pin_usable); + SHIM_TO_NULL_ZERO_INT(VTK_SET_GPIO_PIN_BLINK); + SHIM_TO_NULL_ZERO_INT(VTK_SET_ALR_LED); + _shim_bios_module_entry(VTK_GET_BUZ_CLR, bios_get_buz_clr); + SHIM_TO_NULL_ZERO_INT(VTK_SET_BUZ_CLR); + SHIM_TO_NULL_ZERO_INT(VTK_SET_CPU_FAN_STATUS); + SHIM_TO_NULL_ZERO_INT(VTK_SET_PHY_LED); + SHIM_TO_NULL_ZERO_INT(VTK_SET_HDD_ACT_LED); + SHIM_TO_NULL_ZERO_INT(VTK_GET_MICROP_ID); + SHIM_TO_NULL_ZERO_INT(VTK_SET_MICROP_ID); + + if (hw->emulate_rtc) { + pr_loc_dbg("Platform requires RTC proxy - enabling"); + register_rtc_proxy_shim(); + _shim_bios_module_entry(VTK_RTC_GET_TIME, rtc_proxy_get_time); + _shim_bios_module_entry(VTK_RTC_SET_TIME, rtc_proxy_set_time); + _shim_bios_module_entry(VTK_RTC_INT_APWR, rtc_proxy_init_auto_power_on); + _shim_bios_module_entry(VTK_RTC_GET_APWR, rtc_proxy_get_auto_power_on); + _shim_bios_module_entry(VTK_RTC_SET_APWR, rtc_proxy_set_auto_power_on); + _shim_bios_module_entry(VTK_RTC_UINT_APWR, rtc_proxy_uinit_auto_power_on); + } else { + pr_loc_dbg("Native RTC supported - not enabling proxy (emulate_rtc=%d)", hw->emulate_rtc ? 1:0); + } + + shim_bios_module_hwmon_entries(hw); //Shim all hardware environment stuff (temps, fans, etc.) + + print_debug_symbols(vt_end); + + return true; +} + +bool unshim_bios_module(unsigned long *vt_start, unsigned long *vt_end) +{ + for (int i = 0; i < VTK_SIZE; i++) { + //make sure to check the cust_ one as org_ may contain NULL ptrs and we should restore them as NULL if they were + // so originally + if (!cust_shimmed_entries[i]) + continue; + + pr_loc_dbg("Restoring vtable [%d] from %ps<%p> to %ps<%p>", i, (void *) vt_start[i], + (void *) vt_start[i], (void *) org_shimmed_entries[i], (void *) org_shimmed_entries[i]); + vtable_start[i] = org_shimmed_entries[i]; + } + + reset_bios_shims(); + + return true; +} + +void reset_bios_shims(void) +{ + memset(org_shimmed_entries, 0, sizeof(org_shimmed_entries)); + memset(cust_shimmed_entries, 0, sizeof(cust_shimmed_entries)); + unregister_rtc_proxy_shim(); + reset_bios_module_hwmon_shim(); +} + +/******************************** Kernel-level shims related to mfgBIOS functionality *********************************/ +extern void *funcSYNOSATADiskLedCtrl; //if this explodes one day we need to do kernel_has_symbol() on it dynamically + +/* + * Syno kernel has ifdefs for "MY_ABC_HERE" for syno_ahci_disk_led_enable() and syno_ahci_disk_led_enable_by_port() so + * we need to check if they really exist and we cannot determine it statically + */ +static override_symbol_inst *ov_funcSYNOSATADiskLedCtrl = NULL; +static override_symbol_inst *ov_syno_ahci_disk_led_enable = NULL; +static override_symbol_inst *ov_syno_ahci_disk_led_enable_by_port = NULL; + +static int funcSYNOSATADiskLedCtrl_shim(int host_num, SYNO_DISK_LED led) +{ + pr_loc_dbg("Received %s with host=%d led=%d", __FUNCTION__, host_num, led); + //exit code is not used anywhere in the public code, so this value is an educated guess based on libata-scsi.c + return 0; +} + +int syno_ahci_disk_led_enable_shim(const unsigned short host_num, const int value) +{ + pr_loc_dbg("Received %s with host=%d val=%d", __FUNCTION__, host_num, value); + return 0; +} + +int syno_ahci_disk_led_enable_by_port_shim(const unsigned short port, const int value) +{ + pr_loc_dbg("Received %s with port=%d val=%d", __FUNCTION__, port, value); + return 0; +} + +int shim_disk_leds_ctrl(const struct hw_config *hw) +{ + //we're checking this here to remove knowledge of "struct hw_config" from bios_shim letting others know it's NOT + //the place to do BIOS shimming decisions + if (!hw->fix_disk_led_ctrl) + return 0; + + pr_loc_dbg("Shimming disk led control API"); + + int out; +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) + //funcSYNOSATADiskLedCtrl exists on (almost?) all platforms, but it's null on some... go figure ;) + if (funcSYNOSATADiskLedCtrl) { + ov_funcSYNOSATADiskLedCtrl = override_symbol("funcSYNOSATADiskLedCtrl", funcSYNOSATADiskLedCtrl_shim); + if (unlikely(IS_ERR(ov_funcSYNOSATADiskLedCtrl))) { + out = PTR_ERR(ov_funcSYNOSATADiskLedCtrl); + ov_funcSYNOSATADiskLedCtrl = NULL; + pr_loc_err("Failed to shim funcSYNOSATADiskLedCtrl, error=%d", out); + return out; + } + } +#endif + + if (kernel_has_symbol("syno_ahci_disk_led_enable")) { + ov_syno_ahci_disk_led_enable = override_symbol("syno_ahci_disk_led_enable", syno_ahci_disk_led_enable_shim); + if (unlikely(IS_ERR(ov_syno_ahci_disk_led_enable))) { + out = PTR_ERR(ov_syno_ahci_disk_led_enable); + ov_syno_ahci_disk_led_enable = NULL; + pr_loc_err("Failed to shim syno_ahci_disk_led_enable, error=%d", out); + return out; + } + } + + if (kernel_has_symbol("syno_ahci_disk_led_enable_by_port")) { + ov_syno_ahci_disk_led_enable_by_port = override_symbol("syno_ahci_disk_led_enable_by_port", syno_ahci_disk_led_enable_by_port_shim); + if (unlikely(IS_ERR(ov_syno_ahci_disk_led_enable_by_port))) { + out = PTR_ERR(ov_syno_ahci_disk_led_enable_by_port); + ov_syno_ahci_disk_led_enable_by_port = NULL; + pr_loc_err("Failed to shim syno_ahci_disk_led_enable_by_port, error=%d", out); + return out; + } + } + + pr_loc_dbg("Finished %s", __FUNCTION__); + return 0; +} + +int unshim_disk_leds_ctrl(void) +{ + pr_loc_dbg("Unshimming disk led control API"); + + int out; + bool failed = false; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) + if (ov_funcSYNOSATADiskLedCtrl) { + out = restore_symbol(ov_funcSYNOSATADiskLedCtrl); + ov_funcSYNOSATADiskLedCtrl = NULL; + if (unlikely(out != 0)) { //falling through to try to unshim others too + pr_loc_err("Failed to unshim funcSYNOSATADiskLedCtrl, error=%d", out); + failed = true; + } + } +#endif + + if (ov_syno_ahci_disk_led_enable) { + out = restore_symbol(ov_syno_ahci_disk_led_enable); + ov_syno_ahci_disk_led_enable = NULL; + if (unlikely(out != 0)) { //falling through to try to unshim others too + pr_loc_err("Failed to unshim syno_ahci_disk_led_enable, error=%d", out); + failed = true; + } + } + + if (ov_syno_ahci_disk_led_enable_by_port) { + out = restore_symbol(ov_syno_ahci_disk_led_enable_by_port); + ov_syno_ahci_disk_led_enable_by_port = NULL; + if (unlikely(out != 0)) { + pr_loc_err("Failed to unshim syno_ahci_disk_led_enable_by_port, error=%d", out); + failed = true; + } + } + + out = failed ? -EINVAL : 0; + pr_loc_dbg("Finished %s (exit=%d)", __FUNCTION__, out); + + return out; +} diff --git a/shim/bios/bios_shims_collection.h b/shim/bios/bios_shims_collection.h new file mode 100644 index 0000000..7ff60e6 --- /dev/null +++ b/shim/bios/bios_shims_collection.h @@ -0,0 +1,56 @@ +#ifndef REDPILL_BIOS_SHIMS_COLLECTION_H +#define REDPILL_BIOS_SHIMS_COLLECTION_H + +#include //bool +#include //struct module + + +typedef struct hw_config hw_config_bios_shim_col; +/** + * Insert all the shims to the mfgBIOS + */ +bool shim_bios_module(const hw_config_bios_shim_col *hw, struct module *mod, unsigned long *vtable_start, unsigned long *vtable_end); + +/** + * Removes all shims from the mfgBIOS & uninitializes all components used to shim bios module + */ +bool unshim_bios_module(unsigned long *vtable_start, unsigned long *vtable_end); + +/** + * Forcefully forgets all original calls used to do unshim_bios() & cleans-up all other components + * + * This function is useful when the BIOS unloads without this module being unloaded - then there's no point in keeping + * stale entries. This will also prevent warning regarding already-shimmed BIOS when it reloads. + */ +void reset_bios_shims(void); + +/** + * Nullifies manual disks LED control + * + * The underlying reason for this isn't known but sometimes the manual LED control for disks (presumably used to blink + * to identify disks from the UI) will cause a kernel panic pointing to the internals of mfgBIOS. The functionality is + * implemented in the kernel (funcSYNOSATADiskLedCtrl) but it delegates the task to mfgBIOS via ioctl() + * To prevent the crash we replace the manual LED altering subsystem in models which support it (because not all do). + * + * The kernel panic is most likely caused by the gap between early and full bios shimming where the bios will be early + * shimmed, continue setting something and in between gets an ioctl to the LED api + * + * @return 0 on success or -E on error + */ +int shim_disk_leds_ctrl(const struct hw_config *hw); + +/** + * Reverses what shim_disk_leds_ctrl did + * + * You CAN call this function any time, if shims weren't registered (yet) it will be a noop-call. + * + * @return 0 on success or -E on error + */ +int unshim_disk_leds_ctrl(void); + +/** + * Used by mfgBIOS sub-shims. Should NOT be called from ANY other context as it depends on the internal state. + */ +void _shim_bios_module_entry(unsigned int idx, const void *new_sym_ptr); + +#endif //REDPILL_BIOS_SHIMS_COLLECTION_H diff --git a/shim/bios/mfgbios_types.h b/shim/bios/mfgbios_types.h new file mode 100644 index 0000000..35e2838 --- /dev/null +++ b/shim/bios/mfgbios_types.h @@ -0,0 +1,273 @@ +/* + * This file contains structures/types used for compatibility with the mfg bios + * + * These are not original types used by the mfg BIOS, but rather recreations from available documentation unless + * available in GPLed source (in which case they're #include'd) + */ +#ifndef REDPILL_SYNOBIOS_COMPAT_H +#define REDPILL_SYNOBIOS_COMPAT_H + +#include //SYNO_* & SYNO* types + +//Missing HWMON types... only in some toolchains +#ifndef HWMON_PSU_SENSOR_TEMP1 +#define HWMON_PSU_SENSOR_TEMP1 "temperature_1" +#endif +#ifndef HWMON_PSU_SENSOR_TEMP2 +#define HWMON_PSU_SENSOR_TEMP2 "temperature_2" +#endif +#ifndef HWMON_PSU_SENSOR_TEMP3 +#define HWMON_PSU_SENSOR_TEMP3 "temperature_3" +#endif +#ifndef HWMON_PSU_SENSOR_FAN_VOLT +#define HWMON_PSU_SENSOR_FAN_VOLT "fan_voltage" +#endif + +//These aren't defined in synobios.h (while sensors from other categories are... go figure) +#define HWMON_SYS_TZONE_REMOTE1_NAME "Remote1" +#define HWMON_SYS_TZONE_REMOTE2_NAME "Remote2" +#define HWMON_SYS_TZONE_LOCAL_NAME "Local" +#define HWMON_SYS_TZONE_SYSTEM_NAME "system" +#define HWMON_SYS_TZONE_ADT1_LOC_NAME "ADT1 Local" +#define HWMON_SYS_TZONE_ADT2_LOC_NAME "ADT2 Local" +#define HWMON_SYS_VSENS_VCC_NAME "VCC" +#define HWMON_SYS_VSENS_VPP_NAME "VPP" +#define HWMON_SYS_VSENS_V33_NAME "V33" +#define HWMON_SYS_VSENS_V5_NAME "V5" +#define HWMON_SYS_VSENS_V12_NAME "V12" +#define HWMON_SYS_VSENS_ADT1_V33_NAME "ADT1 V33" +#define HWMON_SYS_VSENS_ADT2_V33_NAME "ADT2 V33" +#define HWMON_SYS_CURR_ADC_NAME "ADC" + +struct MfgCompatTime { + unsigned char second; + unsigned char minute; + unsigned char hours; + unsigned char wkday; + unsigned char day; + unsigned char month; + unsigned char year; +}; + +enum MfgCompatFanStatus { + MFGC_FAN_UNKNOWN = -1, + MFGC_FAN_STOPPED = 0, + MFGC_FAN_RUNNING = 1, +}; + +enum MfgCompatFanSpeed { + MFGC_FAN_SPD_STOP1, + MFGC_FAN_SPD_STOP2, + + //Fan speeds in 1-8 scale + MFGC_FAN_SPD_1, + MFGC_FAN_SPD_2, + MFGC_FAN_SPD_3, + MFGC_FAN_SPD_4, + MFGC_FAN_SPD_5, + MFGC_FAN_SPD_6, + MFGC_FAN_SPD_7, + MFGC_FAN_SPD_8, + + //Fan speeds in 1-18 scale, used for testing only + MFGC_FAN_SPD_TST_1, + MFGC_FAN_SPD_TST_2, + MFGC_FAN_SPD_TST_3, + MFGC_FAN_SPD_TST_4, + MFGC_FAN_SPD_TST_5, + MFGC_FAN_SPD_TST_6, + MFGC_FAN_SPD_TST_7, + MFGC_FAN_SPD_TST_8, + MFGC_FAN_SPD_TST_9, + MFGC_FAN_SPD_TST_10, + MFGC_FAN_SPD_TST_11, + MFGC_FAN_SPD_TST_12, + MFGC_FAN_SPD_TST_13, + MFGC_FAN_SPD_TST_14, + MFGC_FAN_SPD_TST_15, + MFGC_FAN_SPD_TST_16, + MFGC_FAN_SPD_TST_17, + MFGC_FAN_SPD_TST_18, + + MFGC_FAN_SPD_PWM = 1000 +}; + +struct MfgCompatHddLedStatus { + int hdd_no; + SYNO_DISK_LED state; + int pos_name_len; //includes null terminator + char *pos_name; +}; + +enum MfgCompatGenericLedState { + MFGC_LED_OFF, + MFGC_LED_LIT, + MFGC_LED_BLINK, +}; + +struct MfgCompatMemoryByte { + unsigned char offset; + unsigned char value; +}; + +struct MfgCompatMemoryUInt { + unsigned char address; + unsigned char value; +}; + +struct MfgCompatCPLDReg { + unsigned char hddLedCtrl; + unsigned char hddPwrState; + unsigned char hwModelNum; + unsigned char fanState; +}; + +struct MfgCompatGPIOPin { + int num; + int val; +}; + +struct MfgCompatRtcEvent { + unsigned char minutes; //BCD format + unsigned char hours; //BCD format + unsigned char weekdays; //7 bit field, Sun => Sat +}; + +struct MfgCompatAutoPwrOn { + int num; + bool enabled; + struct MfgCompatRtcEvent events[100]; +}; + +struct MfgCompatPowerStatus { + bool primary_ok; + bool secondary_ok; +}; + +enum MfgCompatBackplaneStatus { + MFGC_BKPLANE_UNK = -1, + MFGC_BKPLANE_ERR = 0, + MFGC_BKPLANE_OK = 1, +}; + +struct MfgCompatPWMState { + int channel; + int freq_hz; + int duty_cycle; + int rpm; +}; + +struct MfgCompatSuperIOMem { + unsigned char ldn; + unsigned char reg; + unsigned char val; +}; + +struct MfgCompatBusPacket { + long num; + long len; + char msg[128]; +}; + +struct MfgCompatCPUState { + unsigned int cpu; + char clock[16]; +#if defined(CONFIG_SYNO_GRANTLEY) || defined(CONFIG_SYNO_PURLEY) + unsigned int core[CONFIG_SYNO_MULTI_CPU_NUM]; +#endif +}; + +enum MfgCompatCopyBtnState { + MFGC_BTN_DOWN = 0, //aka pressed + MFGC_BTN_UP = 1, //aka not pressed +}; + +typedef int (*mfgc_void_cb)(void); //int f(void) +typedef int (*mfgc_time_cb)(struct MfgCompatTime *); //int f(MfgCompatTime *) +typedef int (*mfgc_get_fan_state_cb)(int, enum MfgCompatFanStatus *); //int f(int, MfgCompatFanStatus *) +typedef int (*mfgc_set_fan_state_cb)(enum MfgCompatFanStatus, enum MfgCompatFanSpeed); //int f(MfgCompatFanStatus, MfgCompatFanSpeed) +typedef int (*mfgc_hwmon_sensor_cb)(SYNO_HWMON_SENSOR_TYPE *); //int f(SYNO_HWMON_SENSOR_TYPE *) +//TODO: this list is not complete - add all callback types + +#ifdef CONFIG_SYNO_PORT_MAPPING_V2 +typedef int (*mfgc_set_hdd_led_cb)(struct MfgCompatHddLedStatus *status); +#else +typedef int (*mfgc_set_hdd_led_cb)(int, SYNO_DISK_LED state); //int f(void) +#endif + +//List of known indexes in the mfgBIOS vtable. The table can be recovered by shim/bios_shim.c. Some of its entries are +// replaced by shim/bios/bios_shims_collection.c +//The following indexes were determined based on +// - Jun's module code +// - Looking at the symbols when BIOS is loaded +// - Observing logs from mfgBIOS +#define VTK_STRUCT_OWNER 0 //you shouldn't really modify this +#define VTK_GET_BRAND 1 //Sig: int f(void) +#define VTK_GET_MODEL 2 //Sig: int f(void) +#define VTK_GET_CPLD_VER 3 //Sig: int f(void) +#define VTK_RTC_GET_TIME 4 //Sig: int f(MfgCompatTime *) +#define VTK_RTC_SET_TIME 5 //Sig: int f(MfgCompatTime *) +#define VTK_GET_FAN_STATE 6 //Sig: int f(int, MfgCompatFanStatus *) | present in: DS918+; not: DS3615xs +#define VTK_SET_FAN_STATE 7 //Sig: int f(MfgCompatFanStatus, MfgCompatFanSpeed) +#define VTK_GET_SYS_TEMP 8 //Sig: int f(SYNO_THERMAL_TEMP *) | present in: DS3615xs; not: DS918+ +#define VTK_GET_CPU_TEMP 9 //Sig: int f(SYNOCPUTEMP *) +#define VTK_SET_DISK_LED 10 //Sig: varies, see mfgc_set_hdd_led_cb type +#define VTK_SET_PWR_LED 11 //Sig: int f(MfgCompatGenericLedState) +#define VTK_GET_CPLD_REG 12 //Sig: int f(MfgCompatCPLDReg *) +#define VTK_SET_PMU_MEM_BYTE 13 //Sig: int f(MfgCompatMemoryByte *) +#define VTK_GET_PMU_MEM_BYTE 14 //Sig: int f(MfgCompatMemoryByte *) +#define VTK_SET_GPIO_PIN 15 //Sig: int f(MfgCompatGPIOPin *) +#define VTK_GET_GPIO_PIN 16 //Sig: int f(MfgCompatGPIOPin *) +#define VTK_SET_GPIO_PIN_BLINK 17 //Sig: int f(MfgCompatGPIOPin *) +#define VTK_RTC_SET_APWR 18 //Sig: int f(MfgCompatAutoPwrOn *) | set auto power on +#define VTK_RTC_GET_APWR 19 //Sig: int f(MfgCompatAutoPwrOn *) | get auto power on +#define VTK_RTC_INT_APWR 20 //Sig: int f(void) | initialize auto power on. present in: DS918+; not: DS3615xs +#define VTK_RTC_UINT_APWR 21 //Sig: int f(void) | uninitialize auto power on. present in: DS918+; not: DS3615xs +#define VTK_SET_ALR_LED 22 //Sig: int f(MfgCompatGenericLedState) | alarm led +#define VTK_GET_BUZ_CLR 23 //Sig: int f(unsigned char *) +#define VTK_SET_BUZ_CLR 24 //Sig: int f(unsigned char) +#define VTK_GET_PWR_STATUS 25 //Sig: int f(MfgCompatPowerStatus *) +#define VTK_GET_BKPLANE_STATUS 26 //Sig: int f(MfgCompatBackplaneStatus *) | backplane status +#define VTK_INT_MOD_TPE 27 +#define VTK_UNINIT 28 //Sig: int f(void) +#define VTK_SET_CPU_FAN_STATUS 29 //Sig: int f(MfgCompatFanStatus, MfgCompatFanSpeed) +#define VTK_SET_PHY_LED 30 //Sig: int f(MfgCompatGenericLedState) | present in: DS620; not: DS3615xs, DS918+ +#define VTK_SET_HDD_ACT_LED 31 //Sig: int f(MfgCompatGenericLedState) +#define VTK_SET_PWM 32 //Sig: int f(MfgCompatPWMState *) +#define VTK_GET_MICROP_ID 33 +#define VTK_SET_MICROP_ID 34 //Sig: int f(void) +#define VTK_GET_SIO_MEM 35 //Sig: int f(MfgCompatSuperIOMem *) +#define VTK_SET_SIO_MEM 36 //Sig: int f(MfgCompatSuperIOMem *) +#define VTK_SEND_LCD_PKT 37 //Sig: int f(MfgCompatBusPacket *) +#define VTK_GET_MEM_UINT 38 //Sig: int f(MfgCompatMemoryUInt *) +#define VTK_SET_MEM_UINT 39 //Sig: int f(MfgCompatMemoryUInt *) +#define VTK_GET_CPU_INF 40 //Sig: void f(MfgCompatCPUState*, uint) +#define VTK_SET_HA_LED 41 //present in: RC18015xs+ (and other HA units? don't have other); not: DS3615xs,DS918+ +#define VTK_GET_CPY_BTN 42 //Sig: MfgCompatCopyBtnState f(void) | present in: DS718+ + +#if RP_MODULE_TARGET_VER == 6 +#define VTK_SET_SAFE_REMOVE_LED 43 //Sig: int f(bool) | present in: DS3615xs; not: DS918+ +#define VTK_GET_SYS_CURRENT 44 //Sig: int f(SYNO_DISK_INTF_INFO *) +#define VTK_GET_HWMON_FAN_RPM 45 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_PSU_STATUS 46 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_VOLTAGE 47 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_HDD_BKPLANE 48 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_THERMAL 49 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_CURRENT 50 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) + +#elif RP_MODULE_TARGET_VER == 7 //moved VTK_SET_SAFE_REMOVE_LED and VTK_GET_SYS_CURRENT below HWMON_ stuff (sic!) +#define VTK_GET_HWMON_FAN_RPM 43 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_PSU_STATUS 44 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_VOLTAGE 45 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_HDD_BKPLANE 46 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_THERMAL 47 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_GET_HWMON_CURRENT 48 //Sig: int f(SYNO_HWMON_SENSOR_TYPE *) +#define VTK_SET_SAFE_REMOVE_LED 49 //Sig: int f(bool) | present in: DS3615xs; not: DS918+ +#define VTK_GET_SYS_CURRENT 50 //Sig: int f(SYNO_DISK_INTF_INFO *) +#endif //RP_MODULE_TARGET_VER + +#define VTK_GET_HDD_IFACE 51 + +#define VTK_SIZE 52 + +#endif //REDPILL_SYNOBIOS_COMPAT_H \ No newline at end of file diff --git a/shim/bios/rtc_proxy.c b/shim/bios/rtc_proxy.c new file mode 100644 index 0000000..e7551d3 --- /dev/null +++ b/shim/bios/rtc_proxy.c @@ -0,0 +1,270 @@ +/* + * Proxy between an ACPI RTC and mfgBIOS calls + * + * Some platforms don't use a standard RTC chip but implement a custom platform-specific one. To handle different chips + * mfgBIOS uses a standardized interface. This works perfectly fine when mfgBIOS expects an ACPI-complaint RTC to be + * present. However, it does not work when a given platform is expected to contain some 3rd-party I2C clock chip. + * + * Motorola MC146818 was a de facto standard RTC chip when PC/AT emerged. Later on other clones started emulating the + * interface. This become so prevalent that ACPI standardized the basic interface of RTC on PC-compatibile systems as + * MC146818 interface. Thus, this module assumes that mfgBIOS calls can be proxied to MC146818 interface (which will + * work on any ACPI-complaint system and any sane hypervisor). + * + * As some of the functions are rarely used (and often even completely broken on many systems), like RTC wakeup they're + * not really implemented but instead mocked to look "just good enough". + * + * References: + * - https://www.kernel.org/doc/html/latest/admin-guide/rtc.html + * - https://embedded.fm/blog/2018/6/5/an-introduction-to-bcd + */ +#include "../../common.h" +#include "rtc_proxy.h" +#include "../shim_base.h" //shim_*() +#include +#include + +#define SHIM_NAME "RTC proxy" + +//Confused? See https://slate.com/technology/2016/02/the-math-behind-leap-years.html +#define year_is_leap(year) !((year)%((year)%25?4:16)) +#define mfg_year_to_full(val) ((val)+1900) //MfgCompatTime counts years as offset from 1900 +#define mfg_month_to_normal(val) ((val)+1) //MfgCompatTime has 0-based months +#define normal_month_to_mfg(val) ((val)-1) +static const unsigned char months_to_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static struct MfgCompatAutoPwrOn *auto_power_on_mock = NULL; + +inline static void debug_print_mfg_time(struct MfgCompatTime *mfgTime) +{ + pr_loc_dbg("MfgCompatTime raw data: sec=%u min=%u hr=%u wkd=%u day=%u mth=%u yr=%u", mfgTime->second, + mfgTime->minute, mfgTime->hours, mfgTime->wkday, mfgTime->day, mfgTime->month, mfgTime->year); +} + +/** + * Standardizes & abstracts RTC reading + * + * Reading & writing RTC requires conversion of values based on some registers and chips. This function simply accept + * pointers to YY-MM-DD WeekDay HHmmss values and does all the conversions for you after reading. + */ +static void read_rtc_num(unsigned char *yy, unsigned char *mm, unsigned char *dd, unsigned char *wd, unsigned char *hr, + unsigned char *mi, unsigned char *ss) +{ + //As the clock uses IRQ 8 normally we need to atomically stop it to read all values and restore it later + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); + const unsigned char rtc_control = CMOS_READ(RTC_CONTROL); + + //There are two formats how RTCs can report time: normal numbers or an ancient BCD. Currently (at least in Linux v4) + //BCD is always used for MC146818 (but this can change). This we need to handle both cases. + if (likely(RTC_ALWAYS_BCD) || (rtc_control & RTC_DM_BINARY)) { //a common idiom, search for RTC_ALWAYS_BCD in kernel + pr_loc_dbg("Reading BCD-based RTC"); + *yy = bcd2bin(CMOS_READ(RTC_YEAR)); + *mm = bcd2bin(CMOS_READ(RTC_MONTH)); + *dd = bcd2bin(CMOS_READ(RTC_DAY_OF_MONTH)); + *wd = bcd2bin(CMOS_READ(RTC_DAY_OF_WEEK)); + *hr = bcd2bin(CMOS_READ(RTC_HOURS)); + *mi = bcd2bin(CMOS_READ(RTC_MINUTES)); + *ss = bcd2bin(CMOS_READ(RTC_SECONDS)); + } else { + pr_loc_dbg("Reading binary-based RTC"); + *yy = CMOS_READ(RTC_YEAR); + *mm = CMOS_READ(RTC_MONTH); + *dd = CMOS_READ(RTC_DAY_OF_MONTH); + *wd = CMOS_READ(RTC_DAY_OF_WEEK); + *hr = CMOS_READ(RTC_HOURS); + *mi = CMOS_READ(RTC_MINUTES); + *ss = CMOS_READ(RTC_SECONDS); + } + spin_unlock_irqrestore(&rtc_lock, flags); +} + +/** + * Standardizes & abstracts RTC time setting + * + * Reading & writing RTC requires conversion of values based on some registers and chips. This function simply accepts + * values to be set in YY-MM-DD WeekDay HHmmss format and does all the conversions/locking/freq resets for you. + */ +static void write_rtc_num(unsigned char yy, unsigned char mm, unsigned char dd, unsigned char wd, unsigned char hr, + unsigned char mi, unsigned char ss) +{ + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); + unsigned char rtc_control = CMOS_READ(RTC_CONTROL); //RTC control register value locked for us + unsigned char rtc_freq_tick = CMOS_READ(RTC_FREQ_SELECT); + CMOS_WRITE((rtc_control|RTC_SET), RTC_CONTROL); //enter clock setting state + CMOS_WRITE(rtc_freq_tick|RTC_DIV_RESET2, RTC_FREQ_SELECT); //this should reset the ticks + + if (likely(RTC_ALWAYS_BCD) || (rtc_control & RTC_DM_BINARY)) { //a common idiom, search for RTC_ALWAYS_BCD in kernel + pr_loc_dbg("Writing BCD-based RTC"); + CMOS_WRITE(bin2bcd(yy), RTC_YEAR); + CMOS_WRITE(bin2bcd(mm), RTC_MONTH); + CMOS_WRITE(bin2bcd(dd), RTC_DAY_OF_MONTH); + CMOS_WRITE(bin2bcd(wd), RTC_DAY_OF_WEEK); + CMOS_WRITE(bin2bcd(hr), RTC_HOURS); + CMOS_WRITE(bin2bcd(mi), RTC_MINUTES); + CMOS_WRITE(bin2bcd(ss), RTC_SECONDS); + } else { + pr_loc_dbg("Writing binary-based RTC"); + CMOS_WRITE(yy, RTC_YEAR); + CMOS_WRITE(mm, RTC_MONTH); + CMOS_WRITE(dd, RTC_DAY_OF_MONTH); + CMOS_WRITE(wd, RTC_DAY_OF_WEEK); + CMOS_WRITE(hr, RTC_HOURS); + CMOS_WRITE(mi, RTC_MINUTES); + CMOS_WRITE(ss, RTC_SECONDS); + } + + CMOS_WRITE(rtc_control, RTC_CONTROL); //restore original control register + CMOS_WRITE(rtc_freq_tick, RTC_FREQ_SELECT); //...and the ticks too + spin_unlock_irqrestore(&rtc_lock, flags); +} + +int rtc_proxy_get_time(struct MfgCompatTime *mfgTime) +{ + if (mfgTime == NULL) { + pr_loc_wrn("Got an invalid call to %s", __FUNCTION__); + return -EPERM; + } + + debug_print_mfg_time(mfgTime); + + unsigned char rtc_year; //mfgTime uses offset from 1900 while RTC uses 2-digit format (see below) + unsigned char rtc_month; //mfgTime uses 0-11 while RTC uses 1-12 + read_rtc_num(&rtc_year, &rtc_month, &mfgTime->day, &mfgTime->wkday, &mfgTime->hours, &mfgTime->minute, + &mfgTime->second); + + //So yeah, it's 2021 and PC RTCs still use 2 digit year so we have to do a classic Y2K hack with epoch + //RTC nowadays is assumed to have a range of 1970-2069 which forces two assumptions: + // - Values 0-69 indicate 2000-2069 + // - Values 70-99 indicate 1970-1999 + //As the mfgTime->year uses value of years since 1900 without magic rollovers we need to correct it by 100 for the + //2000s epoch. Search for e.g. "mc146818_decode_year" in Linux, that's (sadly) a common method. + mfgTime->year = (likely(rtc_year < 70)) ? rtc_year + 100 : rtc_year; + mfgTime->month = normal_month_to_mfg(rtc_month); + + pr_loc_inf("Time got from RTC is %4d-%02d-%02d %2d:%02d:%02d (UTC)", mfg_year_to_full(mfgTime->year), + mfg_month_to_normal(mfgTime->month), mfgTime->day, mfgTime->hours, mfgTime->minute, mfgTime->second); + debug_print_mfg_time(mfgTime); + + return 0; +} + +int rtc_proxy_set_time(struct MfgCompatTime *mfgTime) +{ + if (mfgTime == NULL) { + pr_loc_wrn("Got an invalid call to %s", __FUNCTION__); + return -EPERM; + } + + debug_print_mfg_time(mfgTime); + + //Ok, this is PROBABLY not needed but we don't want to crash the RTC if an invalid value is passed to this function + //Also, we are aware of leap seconds but do you think 1984 hardware is? (spoiler alert: no) + if (unlikely(mfgTime->second > 59 || mfgTime->minute > 59 || mfgTime->hours > 24 || mfgTime->wkday > 6 || + mfgTime->day == 0 || mfgTime->month > 11)) { + pr_loc_wrn("Got invalid generic RTC data in %s", __FUNCTION__); + return -EINVAL; + } + + //Year validation needs to take leap years into account. This code can be shorter but it's expended for readability + if (unlikely(mfgTime->month == 1 && year_is_leap(mfgTime->year))) { + if (mfgTime->day > (months_to_days[mfgTime->month] + 1)) { + pr_loc_wrn("Invalid RTC leap year day (%u > %u) of month %u in %s", mfgTime->day, + (months_to_days[mfgTime->month] + 1), mfgTime->month, __FUNCTION__); + return -EINVAL; + } + } else if (mfgTime->day > months_to_days[mfgTime->month]) { + pr_loc_wrn("Invalid RTC regular year day (%u > %u) of month %u in %s", mfgTime->day, + months_to_days[mfgTime->month], mfgTime->month, __FUNCTION__); + return -EINVAL; + } + + //mfgTime->year uses a positive offset since 1900. However, ACPI-complain RTC cannot handle range higher than + //1970-2069 (see comment in rtc_proxy_get_time()). + unsigned char rtc_year = mfgTime->year; //mfgTime uses offset from 1900 while RTC uses 2-digit format (see below) + if (unlikely(rtc_year > 169)) { //This cannot be valid as RTC cannot handle >2069 + pr_loc_wrn("Year overflow in %s", __FUNCTION__); + return -EINVAL; + } else if(likely(rtc_year > 100)) { + rtc_year -= 100; //RTC uses 0-69 for 2000s so we need to shift mfgTime 1900-now offset by 100 + } + + unsigned char rtc_month = mfg_month_to_normal(mfgTime->month); //mfgTime uses 0-11 while RTC uses 1-12 + + write_rtc_num(rtc_year, rtc_month, mfgTime->day, mfgTime->wkday, mfgTime->hours, mfgTime->minute, mfgTime->second); + + pr_loc_inf("RTC time set to %4d-%02d-%02d %2d:%02d:%02d (UTC)", mfg_year_to_full(mfgTime->year), + mfg_month_to_normal(mfgTime->month), mfgTime->day, mfgTime->hours, mfgTime->minute, mfgTime->second); + + return 0; +} + +int rtc_proxy_init_auto_power_on(void) +{ + pr_loc_dbg("RTC power-on \"enabled\" via %s", __FUNCTION__); + + return 0; +} + +int rtc_proxy_get_auto_power_on(struct MfgCompatAutoPwrOn *mfgPwrOn) +{ + if (unlikely(!auto_power_on_mock)) { + pr_loc_bug("Auto power-on mock is not initialized - did you forget to call register?"); + return -EINVAL; + } + + pr_loc_dbg("Mocking auto-power GET on RTC"); + memcpy(mfgPwrOn, auto_power_on_mock, sizeof(struct MfgCompatAutoPwrOn)); + + return 0; +} + +int rtc_proxy_set_auto_power_on(struct MfgCompatAutoPwrOn *mfgPwrOn) +{ + if (!mfgPwrOn || mfgPwrOn->num < 0) { //That's just either a bogus call or a stupid call + pr_loc_wrn("Got an invalid call to %s", __FUNCTION__); + return -EINVAL; + } + + pr_loc_dbg("Mocking auto-power SET on RTC"); + memcpy(auto_power_on_mock, mfgPwrOn, sizeof(struct MfgCompatAutoPwrOn)); + + return 0; +} + +int rtc_proxy_uinit_auto_power_on(void) +{ + pr_loc_dbg("RTC power-on \"disabled\" via %s", __FUNCTION__); + + return 0; +} + +int unregister_rtc_proxy_shim(void) +{ + shim_ureg_in(); + + //This is not an error as bios shim collections calls unregister blindly + if (!auto_power_on_mock) { + pr_loc_dbg("The %s shim is not registered - ignoring", SHIM_NAME); + return 0; + } + + kfree(auto_power_on_mock); + auto_power_on_mock = NULL; + shim_ureg_ok(); + return 0; +} + +int register_rtc_proxy_shim(void) +{ + shim_reg_in(); + + if (unlikely(auto_power_on_mock)) { + pr_loc_wrn("The %s shim is already registered - unregistering first", SHIM_NAME); + unregister_rtc_proxy_shim(); + } + + kzalloc_or_exit_int(auto_power_on_mock, sizeof(struct MfgCompatAutoPwrOn)); + shim_reg_ok(); + return 0; +} diff --git a/shim/bios/rtc_proxy.h b/shim/bios/rtc_proxy.h new file mode 100644 index 0000000..fd82136 --- /dev/null +++ b/shim/bios/rtc_proxy.h @@ -0,0 +1,42 @@ +#ifndef REDPILL_RTC_PROXY_H +#define REDPILL_RTC_PROXY_H + +#include "mfgbios_types.h" + +/** + * Gets current RTC time (shims VTK_RTC_GET_TIME) + */ +int rtc_proxy_get_time(struct MfgCompatTime *mfgTime); + +/** + * Sets current RTC time (shims VTK_RTC_SET_TIME) + */ +int rtc_proxy_set_time(struct MfgCompatTime *mfgTime); + +/** + * Enables auto-power on functionality (shims VTK_RTC_INT_APWR). + * + * This is not REALLY implemented and only shimmed. Many motherboards don't handle it well or only support it from + * certain ACPI PSTATEs. It is even more unsupported by hypervisors. If you REALLY need it create a bug report or a PR. + */ +int rtc_proxy_init_auto_power_on(void); + +/** + * Gets time for auto-power on (shims VTK_RTC_GET_APWR). **See note for rtc_proxy_init_auto_power_on()** + */ +int rtc_proxy_get_auto_power_on(struct MfgCompatAutoPwrOn *mfgPwrOn); + +/** + * Sets time for auto-power on (shims VTK_RTC_SET_APWR). **See note for rtc_proxy_init_auto_power_on()** + */ +int rtc_proxy_set_auto_power_on(struct MfgCompatAutoPwrOn *mfgPwrOn); + +/** + * Disables auto-power on functionality (shims VTK_RTC_UINT_APWR). **See note for rtc_proxy_init_auto_power_on()** + */ +int rtc_proxy_uinit_auto_power_on(void); + +int unregister_rtc_proxy_shim(void); +int register_rtc_proxy_shim(void); + +#endif //REDPILL_RTC_PROXY_H diff --git a/shim/bios_shim.c b/shim/bios_shim.c new file mode 100644 index 0000000..b9cc85c --- /dev/null +++ b/shim/bios_shim.c @@ -0,0 +1,398 @@ +/* + * This shim is responsible for making the hardware<>DSM glue (aka mfg BIOS) happy by providing nullified + * implementations of hardware-specific calls. + * + * The process relies on the fact that the original BIOS module keeps a vtable table in memory. That vtable contains + * pointers to various functions used to communicate with the hardware. The most tricky part here is finding the vtable + * and replacing calls in it with our own. Original ELF contains unscrambled symbols for the table under "synobios_ops" + * name (see: readelf --syms /usr/lib/modules/synobios-dis.ko | grep 'synobios_ops'). However this is NOT a symbol which + * gets exported to the kernel. + * + * When the Linux kernel loads a module it does a couple of things after loading the .ko file. From the important ones + * here it reads the ELF, loads the .symtab (all symbols), processes all relocations, and then does a cleanup of stuff + * which is not needed after module is loaded. The earliest hook normally available for other modules is the access + * through modules notification API. It will provide access to the module as soon as its binary is loaded and init + * function is executing. However: + * - we only get the access to the "struct module" + * - the data available contains kallsyms + * - at this point all non-kernel symbols are discarded from memory (see kernel/module.c:simplify_symbols()) + * + * While the symbols exist in the memory the symbol table cannot be accessed (short of loading the ELF again and + * re-parsing the binary... which is way too complex). Most of the ELF parsing routines in the kernel are implemented + * in kernel/module.c in `static` functions. This unfortunately means they aren't really replaceable as they are + * inlined and mangled. However, there's one place where CPU architecture-dependent step happens: relocation of + * symbols. When module.c:apply_relocations() is called on x86_64 it calls the + * arch/x86/kernel/module.c:apply_relocate_add(). Since this function is external it can be "gently" replaced. + * + * During the lifetime of apply_relocate_add(), which is redirected to _apply_relocate_add() here, the full ELF with + * symbol table is available and thus the vtable can be located using process_bios_symbols(). However, it cannot be + * just like that modified at this moment (remember: we're way before module init is called) as 1) functions it points + * to may be relocated still, and 2) it's hardware-dependent (as seen by doing print_debug_symbols() before & after + * init). We need to hook to the module notification API and shim what's needed AFTER module started initializing. + * + * So in summary: + * 1. Redirect apply_relocate_add() => _apply_relocate_add() using internal/override_symbol.h + * 2. Setup module notifier + * 3. Look for "*_synobios" module in _apply_relocate_add() and if found iterate through symbols + * 4. Find "synobios_ops" in full symbols table and save it's start & end addresses; disable override from [1] + * 5. Wait until notified by the kernel about module started loaded (see bios_module_notifier_handler()) + * 6. Replace what's needed (see bios/bios_shims_collection.c:shim_bios_module()) + * 7. Wait until notified by the kernel about module fully loaded (and replace what was broken since 5.) + * 8. Drink a beer + * + * Additionally, this module also handles replacement of some kernel structures called by the mfgBIOS: + * - see bios_shims_collection.c:shim_disk_leds_ctrl() + * + * References: + * - https://en.wikipedia.org/wiki/Virtual_method_table + */ +#define SHIM_NAME "mfgBIOS" + +#include "bios_shim.h" +#include "shim_base.h" +#include "../common.h" +#include "../internal/override/override_symbol.h" +#include "../internal/helper/symbol_helper.h" //kernel_has_symbol() +#include "bios/bios_shims_collection.h" //shim_bios_module(), unshim_bios_module(), shim_bios_disk_leds_ctrl() +#include "bios/bios_hwcap_shim.h" //register_bios_hwcap_shim(), unregister_bios_hwcap_shim(), reset_bios_hwcap_shim() +#include //module notification +#include //struct module + +static bool bios_shimmed = false; +static bool module_notify_registered = false; +static unsigned long *vtable_start = NULL; +static unsigned long *vtable_end = NULL; +static const struct hw_config *hw_config = NULL; +static inline int enable_symbols_capture(void); +static inline int disable_symbols_capture(void); + +/********************************************* Shimming of mfgBIOS module *********************************************/ +/** + * Unified way to determine if a given module is a bios module (as this is not a simple == check) + */ +static inline bool is_bios_module(const char *name) +{ + char *separator_pos = strrchr(name, '_'); //bios will be named e.g. bromolow_synobios - find's the last _ + + //Check if it's synobios or sth else really + return (separator_pos && strcmp(separator_pos, "_synobios") == 0); +} + +/** + * Handles notifications regarding modules loading. It will only perform actions on modules matching is_bios_module() + * + * This is constantly loaded to provide useful error information in case the bios module goes away (it shouldn't). In + * non-dev builds it can probably just go away. + * + * @return NOTIFY_* const + */ +static int bios_module_notifier_handler(struct notifier_block * self, unsigned long state, void * data) +{ + struct module *mod = data; + + if (!is_bios_module(mod->name)) + return NOTIFY_OK; + + if (state == MODULE_STATE_GOING) { + //So this is actually not a problem with RP but rather with the bios module - it cannot be unloaded at will. + //As soon as you try it will cause a circular error with page faults and the kernel will demand a reboot + //We're not unregistering notifier in case one day this is fixed by the bios module ¯\_(ツ)_/¯ + pr_loc_err("%s BIOS went away - you may get a kernel panic if YOU unloaded it", mod->name); + bios_shimmed = false; + vtable_start = vtable_end = NULL; + enable_symbols_capture(); + reset_bios_shims(); + reset_bios_hwcap_shim(); + + return NOTIFY_OK; + } + + if (bios_shimmed) + return NOTIFY_OK; + + //So, this is really tricky actually. Some parts of the vtable are populated AND USED during init and some are + // populated in init but used later. This means we need to try to shim twice - as fast as possible after init call + // and just after init call finished. + + //We react to every module action by re-shimming its vtable as it might have changed. Other actions are done only + // once below. + if (!shim_bios_module(hw_config, mod, vtable_start, vtable_end)) { + bios_shimmed = false; + return NOTIFY_OK; + } + + if (state == MODULE_STATE_LIVE) { + bios_shimmed = true; + pr_loc_inf("%s BIOS *fully* shimmed", mod->name); + } else { //MODULE_STATE_COMING or MODULE_STATE_UNFORMED [but most likely actually MODULE_STATE_COMING] + if (likely(state == MODULE_STATE_COMING)) + register_bios_hwcap_shim(hw_config); + + pr_loc_inf("%s BIOS *early* shimmed", mod->name); + } + + return NOTIFY_OK; +} + +static struct notifier_block bios_notifier_block = { + .notifier_call = bios_module_notifier_handler +}; +/** + * Registers module notifier to modify vtable as soon as module finishes loading + * + * @return 0 on success, -E on failure + */ +static int register_bios_module_notifier(void) +{ + if (unlikely(module_notify_registered)) { + pr_loc_bug("%s called while notifier already registered", __FUNCTION__); + return -EALREADY; + } + + //Check if the bios module is already present in the system. If it is we have a problem as the vtable must be + // patched as it loads. It's unclear if it can be patched after it's loaded but most certainly we don't have the + // address of the table. That's why this is an error. If by any chance we have an address we can try patching but + // this scenario is unlikely to work (and re-loading of the bios is not possible as it KPs). There's also no EASY + // way of accessing list of modules (and the bios module name depends on platform etc...) + //This symbol is chosen semi-randomly (i.e. it should be stable over time) but it shouldn't be present anywhere else + if (unlikely(kernel_has_symbol("synobios_ioctl"))) { + pr_loc_err("BIOS module is already loaded (did you load this module too late?) - cannot recover!"); + return -EDEADLOCK; + } + + int out = register_module_notifier(&bios_notifier_block); + if(unlikely(out != 0)) { + pr_loc_err("Failed to register module notifier"); //Currently it's impossible to happen... currently + return out; + } + + module_notify_registered = true; + pr_loc_dbg("Registered bios module notifier"); + + return 0; +} + +/** + * Reverses what register_bios_module_notifier did + * + * @return 0 on success, -E on failure + */ +static int unregister_bios_module_notifier(void) +{ + if (unlikely(!module_notify_registered)) { + pr_loc_bug("%s called while notifier not yet registered", __FUNCTION__); + return -ENOMEDIUM; + } + + int out = unregister_module_notifier(&bios_notifier_block); + if(unlikely(out != 0)) { + pr_loc_err("Failed to unregister module notifier"); + return out; + } + + module_notify_registered = false; + pr_loc_dbg("Unregistered bios module notifier"); + + return 0; +} + +#define BIOS_CALLTABLE "synobios_ops" +/** + * Scans module ELF headers for BIOS_CALLTABLE and saves its address + */ +static void process_bios_symbols(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, struct module *mod) +{ + Elf64_Shdr *symsec = &sechdrs[symindex]; + pr_loc_dbg("Symbol section <%p> @ vaddr<%llu> size[%llu]", symsec, symsec->sh_addr, symsec->sh_size); + + Elf64_Sym *sym; + Elf64_Sym *vtable = NULL; + sym = (void *)symsec->sh_addr; //First symbol in the table + + unsigned int i; + for (i = 0; i < symsec->sh_size / sizeof(Elf64_Sym); i++) { + const char *symname = strtab + sym[i].st_name; + pr_loc_dbg("Symbol #%d in mfgBIOS \"%s\" {%s}<%p>", i, mod->name, symname, (void *)sym[i].st_value); + + //There are more than one, we're looking for THE table (not a pointer) + if (strncmp(symname, BIOS_CALLTABLE, sizeof(BIOS_CALLTABLE)) == 0 && sym[i].st_size > sizeof(void *)) { + pr_loc_dbg("Found vtable - size %llu", sym[i].st_size); + vtable = &sym[i]; + break; + } + } + + //That, to my knowledge, shouldn't happen + if (unlikely(!vtable)) { + pr_loc_wrn("Didn't find \"%s\" in \"%s\" this time - that's weird?", BIOS_CALLTABLE, mod->name); + return; + } + + vtable_start = (unsigned long *)vtable->st_value; + vtable_end = vtable_start + vtable->st_size; + pr_loc_dbg("Found \"%s\" in \"%s\" @ <%p =%llu=> %p>", (strtab + vtable->st_name), mod->name, vtable_start, + vtable->st_size, vtable_end); + disable_symbols_capture(); +} + +/**************************************************** Entrypoints *****************************************************/ +int register_bios_shim(const struct hw_config *hw) +{ + int out; + hw_config = hw; + shim_reg_in(); + + if ( + (out = shim_disk_leds_ctrl(hw)) != 0 || + (out = enable_symbols_capture()) != 0 || + (out = register_bios_module_notifier()) != 0 + ) { + return out; + } + + shim_reg_ok(); + return 0; +} + +int unregister_bios_shim(void) +{ + int out; + + shim_ureg_in(); + if (likely(bios_shimmed)) { + if (!unshim_bios_module(vtable_start, vtable_end)) + return -EINVAL; + } + + out = unregister_bios_module_notifier(); + if (unlikely(out != 0)) + return out; + + out = disable_symbols_capture(); + if (unlikely(out != 0)) + return out; + + unshim_disk_leds_ctrl(); //this will be noop if nothing was registered + unregister_bios_hwcap_shim(); //this will be noop if nothing was registered + + hw_config = NULL; + + shim_ureg_ok(); + return 0; +} + +/************************************************** Internal Helpers **************************************************/ +/** + * A modified arch/x86/kernel/module.c:apply_relocate_add() from Linux v3.10.108 to save synobios_ops address + * + * This is taken straight from Linux v3.10 and modified: + * - added call to process_bios_symbols + * - commented-out DEBUGP + * Original author notice: Copyright (C) 2001 Rusty Russell + */ +static int _apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, struct module *me) +{ + unsigned int i; + Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf64_Sym *sym; + void *loc; + u64 val; + + //Well, this is here because there isn't a good place to plug-in into modules loading to get the full symbols table + //Later on kernel removes "useless" symbols (see module.c:simplify_symbols())... but we need them + //After vtable address is found this override of apply_relocate_add() is removed + if (!vtable_start && is_bios_module(me->name)) + process_bios_symbols(sechdrs, strtab, symindex, me); + +// DEBUGP("Applying relocate section %u to %u\n", +// relsec, sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + + ELF64_R_SYM(rel[i].r_info); + +// DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", +// (int)ELF64_R_TYPE(rel[i].r_info), +// sym->st_value, rel[i].r_addend, (u64)loc); + + val = sym->st_value + rel[i].r_addend; + + switch (ELF64_R_TYPE(rel[i].r_info)) { + case R_X86_64_NONE: + break; + case R_X86_64_64: + *(u64 *)loc = val; + break; + case R_X86_64_32: + *(u32 *)loc = val; + if (val != *(u32 *)loc) + goto overflow; + break; + case R_X86_64_32S: + *(s32 *)loc = val; + if ((s64)val != *(s32 *)loc) + goto overflow; + break; + case R_X86_64_PC32: + val -= (u64)loc; + *(u32 *)loc = val; + break; + default: + pr_err("%s: Unknown rela relocation: %llu\n", + me->name, ELF64_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; + + overflow: + pr_err("overflow in relocation type %d val %Lx\n", + (int)ELF64_R_TYPE(rel[i].r_info), val); + pr_err("`%s' likely not compiled with -mcmodel=kernel\n", + me->name); + return -ENOEXEC; +} + +static override_symbol_inst *ov_apply_relocate_add = NULL; +/** + * Enables override of apply_relocate_add() to redirect it to _apply_relocate_add() in order to plug into a moment where + * process_bios_symbols() can extract the data. + * + * @return 0 on success, -E on failure + */ +static inline int enable_symbols_capture(void) +{ + if (unlikely(ov_apply_relocate_add)) + return 0; //Technically it's working so it's a non-error scenario (and it may happen with modules notification) + + ov_apply_relocate_add = override_symbol("apply_relocate_add", _apply_relocate_add); + if (unlikely(IS_ERR(ov_apply_relocate_add))) { + int out = PTR_ERR(ov_apply_relocate_add); + ov_apply_relocate_add = NULL; + pr_loc_err("Failed to override apply_relocate_add, error=%d", out); + return out; + } + + return 0; +} + +/** + * Disables override of apply_relocate_add() if enabled. + * + * @return 0 on success/noop, -E on failure + */ +static inline int disable_symbols_capture(void) +{ + if (!ov_apply_relocate_add) //may have been restored before + return 0; + + int out = restore_symbol(ov_apply_relocate_add); + ov_apply_relocate_add = NULL; + + return out; +} \ No newline at end of file diff --git a/shim/bios_shim.h b/shim/bios_shim.h new file mode 100644 index 0000000..82a216f --- /dev/null +++ b/shim/bios_shim.h @@ -0,0 +1,8 @@ +#ifndef REDPILLLKM_BIOS_SHIM_H +#define REDPILLLKM_BIOS_SHIM_H + +struct hw_config; +int register_bios_shim(const struct hw_config *hw); +int unregister_bios_shim(void); + +#endif //REDPILLLKM_BIOS_SHIM_H diff --git a/shim/block_fw_update_shim.c b/shim/block_fw_update_shim.c new file mode 100644 index 0000000..364e0e2 --- /dev/null +++ b/shim/block_fw_update_shim.c @@ -0,0 +1,88 @@ +/** + * This rather simple shim prevents execution of a firmware update program when done in a one specific way + * + * During the OS installation process one of the steps executes a command "./H2OFFT-Lx64". This is a board firmware + * update program. When executed under KVM it will crash the virtual CPU (and I wasn't brave enough to try it on bare + * metal). All in all the execution must succeed from the perspective of the user-space and the file cannot be modified + * due to checksum check. + * + * This shim hooks a execve() syscall and filter it through shim_sys_execve(). This in turn is self-explanatory for the + * most part - it simply fakes successful execution without invoking anything. While such trickery can be detected (as + * the real process is not really replaced) it is good enough for this case. + * + * Additionally, to make the firmware picking happy we need to pass a sanity check (which is presumably done to ensure + * flasher doesn't accidentally brick an incorrect board) using DMI data. This is handled here by overriding one string + * in the DMI data array (as the kernel API lacks any way of changing that). + * + * References: + * - https://linux.die.net/man/3/execve + * - https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html + * - https://help.ubuntu.com/community/FimwareUpgrade/Insyde + */ +#define SHIM_NAME "firmware update blocker" + +#include "block_fw_update_shim.h" +#include "shim_base.h" +#include "../common.h" +#include "../internal/intercept_execve.h" +#include //dmi_get_system_info(), DMI_* + +#define DMI_MAX_LEN 512 +#define FW_BOARD_NAME "\x53\x79\x6e\x6f\x64\x65\x6e" +#define FW_UPDATE_PATH "./H2OFFT-Lx64" + +static char dmi_product_name_backup[DMI_MAX_LEN] = { '\0' }; +static void patch_dmi(void) +{ + char *ptr = (char *)dmi_get_system_info(DMI_PRODUCT_NAME); + size_t org_len = strlen(ptr); + if (org_len > DMI_MAX_LEN) + pr_loc_wrn("DMI field longer than %zu - restoring on module unload will be limited to that length", org_len); + + if(strlcpy((char *)&dmi_product_name_backup, ptr, DMI_MAX_LEN) < 0) + pr_loc_wrn("Backup DMI truncated to %d", DMI_MAX_LEN); + + pr_loc_dbg("Saved backup DMI: %s", dmi_product_name_backup); + + //This TECHNICALLY can cause overflow but DMI has buffer for such a short string + if (org_len < strlen_static(FW_BOARD_NAME)) + pr_loc_bug("Shimmed DMI field will be longer than original!"); + + strcpy(ptr, FW_BOARD_NAME); +} + +static void unpatch_dmi(void) +{ + if (dmi_product_name_backup[0] == '\0') { + pr_loc_dbg("Skipping %s - DMI not patched", __FUNCTION__); + return; + } + + strcpy((char *)dmi_get_system_info(DMI_PRODUCT_NAME), dmi_product_name_backup); + pr_loc_dbg("DMI unpatched"); +} + +int register_fw_update_shim(void) +{ + shim_reg_in(); + + int out = add_blocked_execve_filename(FW_UPDATE_PATH); + if (out != 0) + return out; + + patch_dmi(); + + shim_reg_ok(); + return 0; +} + +int unregister_fw_update_shim(void) +{ + shim_ureg_in(); + + //Do not remove execve registration here - it will be cleared in one sweep during unregister of interceptor + unpatch_dmi(); + + shim_ureg_ok(); + return 0; +} \ No newline at end of file diff --git a/shim/block_fw_update_shim.h b/shim/block_fw_update_shim.h new file mode 100644 index 0000000..0eda2f5 --- /dev/null +++ b/shim/block_fw_update_shim.h @@ -0,0 +1,7 @@ +#ifndef REDPILL_BLOCK_FW_UPDATE_SHIM_H +#define REDPILL_BLOCK_FW_UPDATE_SHIM_H + +int register_fw_update_shim(void); +int unregister_fw_update_shim(void); + +#endif //REDPILL_BLOCK_FW_UPDATE_SHIM_H diff --git a/shim/boot_dev/boot_shim_base.c b/shim/boot_dev/boot_shim_base.c new file mode 100644 index 0000000..2535e25 --- /dev/null +++ b/shim/boot_dev/boot_shim_base.c @@ -0,0 +1,70 @@ +#include "boot_shim_base.h" +#include "../../common.h" +#include "../../config/runtime_config.h" //struct boot_media +#include "../../internal/scsi/scsi_toolbox.h" //is_sata_disk(), opportunistic_read_capacity() +#include //struct scsi_device +#include //struct usb_device + +//Definition of known VID/PIDs for USB-based shims +#define SBOOT_RET_VID 0xf400 //Retail boot drive VID +#define SBOOT_RET_PID 0xf400 //Retail boot drive PID +#define SBOOT_MFG_VID 0xf401 //Force-reinstall boot drive VID +#define SBOOT_MFG_PID 0xf401 //Force-reinstall boot drive PID + +void *mapped_shim_data = NULL; + +void set_shimmed_boot_dev(void *private_data) +{ + mapped_shim_data = private_data; +} + +void *get_shimmed_boot_dev(void) +{ + return mapped_shim_data; +} + +bool scsi_is_boot_dev_target(const struct boot_media *boot_dev_config, struct scsi_device *sdp) +{ + if (!is_sata_disk(&sdp->sdev_gendev)) { + pr_loc_dbg("%s: it's not a SATA disk, ignoring", __FUNCTION__); + return false; + } + + pr_loc_dbg("Checking if SATA disk is a shim target - id=%u channel=%u vendor=\"%s\" model=\"%s\"", sdp->id, + sdp->channel, sdp->vendor, sdp->model); + + long long capacity_mib = opportunistic_read_capacity(sdp); + if (unlikely(capacity_mib < 0)) { + pr_loc_dbg("Failed to estimate drive capacity (error=%lld) - it WILL NOT be shimmed", capacity_mib); + return false; + } + + if (capacity_mib > boot_dev_config->dom_size_mib) { + pr_loc_dbg("Device has capacity of ~%llu MiB - it WILL NOT be shimmed (>%lu)", capacity_mib, + boot_dev_config->dom_size_mib); + return false; + } + + if (unlikely(get_shimmed_boot_dev())) { + pr_loc_wrn("Boot device was already shimmed but a new matching device (~%llu MiB <= %lu) appeared again - " + "this may produce unpredictable outcomes! Ignoring - check your hardware", capacity_mib, + boot_dev_config->dom_size_mib); + return false; + } + + pr_loc_dbg("Device has capacity of ~%llu MiB - it is a shimmable target (<=%lu)", capacity_mib, + boot_dev_config->dom_size_mib); + + return true; +} + +void usb_shim_as_boot_dev(const struct boot_media *boot_dev_config, struct usb_device *usb_device) +{ + if (boot_dev_config->mfg_mode) { + usb_device->descriptor.idVendor = cpu_to_le16(SBOOT_MFG_VID); + usb_device->descriptor.idProduct = cpu_to_le16(SBOOT_MFG_PID); + } else { + usb_device->descriptor.idVendor = cpu_to_le16(SBOOT_RET_VID); + usb_device->descriptor.idProduct = cpu_to_le16(SBOOT_RET_PID); + } +} \ No newline at end of file diff --git a/shim/boot_dev/boot_shim_base.h b/shim/boot_dev/boot_shim_base.h new file mode 100644 index 0000000..d75e98b --- /dev/null +++ b/shim/boot_dev/boot_shim_base.h @@ -0,0 +1,57 @@ +#ifndef REDPILL_BOOT_SHIM_BASE_H +#define REDPILL_BOOT_SHIM_BASE_H + +#include //bool + +struct boot_media; +struct usb_device; +struct scsi_device; + +/** + * Modify given USB device instance to conform to syno kernel boot device specification + * + * This function takes into consideration the boot_media configuration regarding mfg vs retail mode and will change the + * device descriptors accordingly. It is safe to call this function multiple times on the same object. + * + * @param boot_dev_config Configuration to determine boot mode + * @param usb_device Device to change + */ +void usb_shim_as_boot_dev(const struct boot_media *boot_dev_config, struct usb_device *usb_device); + +/** + * Save a free-form pointer into a global storage to mark boot device as shimmed + * + * Other subsystems can determine if the boot device has been shimmed by calling get_shimmed_boot_dev(). However, the + * data passed to this function is opaque by design and only makes sense to the submodule which originally set it. + * + * @param private_data Any non-null pointer or value castable to a pointer type (e.g. unsigned long number) + */ +void set_shimmed_boot_dev(void *private_data); + +/** + * Shortcut to remove previously marked as shimmed boot device. It is an equivalent of simply calling set with NULL ptr. + */ +#define reset_shimmed_boot_dev() set_shimmed_boot_dev(NULL); + +/** + * Gets shimmed boot device private data (if any) + * + * The caller should not try to interpret the value returned beyond NULL vs. non-NULL, unless the caller is the original + * submodule which set the value using set_shimmed_boot_dev(). + * + * @return non-NULL pointer if device has been shimmed or NULL ptr if it wasn't + */ +void *get_shimmed_boot_dev(void); + +/** + * Checks if a given SCSI disk can become a boot device + * + * To fully understand the rules and intricacies of how it is used in context you should read the file comment for the + * native SATA DOM shim in shim/boot_dev/sata_boot_shim.c + * + * @param boot_dev_config User-controllable configuration with a threshold for considering an SCSI disk a boot device + * @param sdp SCSI device which ideally should be an SCSI disk (as passing any other ones doesn't make sense) + */ +bool scsi_is_boot_dev_target(const struct boot_media *boot_dev_config, struct scsi_device *sdp); + +#endif //REDPILL_BOOT_SHIM_BASE_H diff --git a/shim/boot_dev/fake_sata_boot_shim.c b/shim/boot_dev/fake_sata_boot_shim.c new file mode 100644 index 0000000..7644b8d --- /dev/null +++ b/shim/boot_dev/fake_sata_boot_shim.c @@ -0,0 +1,317 @@ +/** + * A crazy attempt to use SATA disks as proper boot devices on systems without SATA DOM support + * + * BACKGROUND + * The syno-modifed SCSI driver (sd.c) contains support for so-called boot disks. It is a logical designation for drives + * separated from normal data disks. Normally that designation is based on vendor & model of the drive. The native SATA + * boot shim uses that fact to modify user-supplied drive to match that vendor-model and be considered bootable. + * Likewise similar mechanism exists for USB boot media. Both are completely separate and work totally differently. + * While both USB storage and SATA are SCSI-based systems they different in the ways devices are identified and pretty + * much in almost everything else except the protocol. + * + * + * HOW DOES IT WORK? + * This shim performs a nearly surgical task of grabbing a SATA disk (similarly to native SATA boot shim) and modifying + * its descriptors to look like a USB drive for a short while. The descriptors cannot be left in such state for too + * long, and have to be reverted as soon as the disk type is determined by the "sd.c" driver. This is because other + * processes actually need to read & probe the drive as a SATA one (as you cannot communicate with a SATA device like + * you do with a USB stick). + * In a birds-eye view the descriptors are modified just before the sd_probe() is called and removed when ida_pre_get() + * is called by the sd_probe(). The ida_pre_get() is nearly guaranteed [even if the sd.c code changes] to be called + * very early in the process as the ID allocation needs to be done for anything else to use structures created within. + * + * + * HERE BE DRAGONS + * This code is highly experimental and may explode at any moment. We previously thought we cannot do anything with + * SATA boot due to lack of kernel support for it (and userland method being broken now). This crazy idea actually + * worked and after many tests on multiple platforms it seems to be stable. However, we advise against using it if USB + * is an option. Code here has many safety cheks and safeguards but we will never consider it bullet-proof. + * + * + * References: + * - https://www.kernel.org/doc/html/latest/core-api/idr.html (IDs assignment in the kernel) + * - drivers/scsi/sd.c in syno kernel GPL sources (look at sd_probe() and syno_disk_type_get()) + */ +#include "fake_sata_boot_shim.h" +#include "boot_shim_base.h" //set_shimmed_boot_dev(), get_shimmed_boot_dev(), scsi_is_shim_target(), usb_shim_as_boot_dev() +#include "../shim_base.h" //shim_* +#include "../../common.h" +#include "../../internal/scsi/scsi_toolbox.h" //scsi_force_replug() +#include "../../internal/scsi/scsi_notifier.h" //waiting for the drive to appear +#include "../../internal/call_protected.h" //ida_pre_get() +#include "../../internal/override/override_symbol.h" //overriding ida_pre_get() +#include //struct scsi_device +#include //struct Scsi_Host, SYNO_PORT_TYPE_* +#include //struct usb_device +#include <../drivers/usb/storage/usb.h> //struct us_data + +#define SHIM_NAME "fake SATA boot device" + +static const struct boot_media *boot_dev_config = NULL; //passed to scsi_is_shim_target() & usb_shim_as_boot_dev() +static struct scsi_device *camouflaged_sdp = NULL; //set when ANY device is under camouflage +static struct usb_device *fake_usbd = NULL; //ptr to our fake usb device scaffolding +static int org_port_type = 0; //original port type of the device which registered +static override_symbol_inst *ida_pre_get_ovs = NULL; //trap override +static unsigned long irq_flags = 0; //saved flags when IRQs are disabled (to prevent rescheduling) + +//They call each other, see their own docblocks +static int camouflage_device(struct scsi_device *sdp); +static int uncamouflage_device(struct scsi_device *sdp); + +struct ida; +/** + * Called by the sd_probe() very early after disk type is determined. We can restore the disk to its original shape + */ +static int ida_pre_get_trap(struct ida *ida, gfp_t gfp_mask) +{ + //This can happen if the kernel decides to reschedule and/or some device appears JUST between setting up the trap + // and disabling of rescheduling. We cannot reverse the order as setting up the trap requires flushing CPU caches + // which isn't really feasible in non-preempt & IRQ-disabled state... a catch-22 + //It is also possible that it happens during uncamouflage_device - this is why we force-restore here and just call + // it. + if (unlikely(!camouflaged_sdp)) { + pr_loc_bug("Hit ida_pr_get() trap without sdp saved - removing trap and calling original"); + restore_symbol(ida_pre_get_ovs); + return _ida_pre_get(ida, gfp_mask); + } + + pr_loc_dbg("Hit ida_pre_get() trap! Removing camouflage..."); + uncamouflage_device(camouflaged_sdp); + + pr_loc_dbg("Calling original ida_pre_get()"); + return _ida_pre_get(ida, gfp_mask); +} + +/** + * Checks if the device passes is "camouflaged" as a USB device + */ +static bool is_camouflaged(struct scsi_device *sdp) +{ + return likely(camouflaged_sdp) && camouflaged_sdp == sdp; +} + +/** + * Alters a SATA device to look like a USB boot disk + * + * Order of operations in camouflage/uncamouflage is VERY particular. We make sure we CANNOT fail (at least not without + * a KP resulting from pagefault) once we disable preemption & irqs AND that no changes before preemption is disabled + * are overriding anything external (as we can be rescheduled and we cannot leave stuff half-replaced) + * + * @param sdp A valid SATA disk (it's assumed it passed through scsi_is_boot_dev_target() already) to disguise as USB + * + * @return 0 on success, -E on error + */ +static int camouflage_device(struct scsi_device *sdp) +{ + //This is very serious - it means something went TERRIBLY wrong. The camouflage should last only through the + // duration of probing. If we got here again before camouflaging it means there's a device floating around which + // is a SATA device but with broken USB descriptors. This should never ever happen as it may lead to data loss and + // crashes at best. + if (unlikely(camouflaged_sdp)) { + pr_loc_crt("Attempting to camouflage when another device is undergoing camouflage"); + return -EEXIST; + } + + //Here's the kicker: most of the subsystems save a pointer to some driver-related data into sdp->host->hostdata. + // Unfortunately usb-storage saves a whole us_data structure there. It can do that as it allows them to use some + // neat container_of() tricks later on. However, it means that we must fake that arrangement. This means we have to + // practically go over the boundaries of the struct memory passed as ->pusb_dev is simply +40 bytes over the struct + // (+ 8 bytes to save the ptr). USUALLY it should be safe as there's spare empty space due to memory fragmentation. + // Since we're doing this only for a short moment it shouldn't be a problem but we are making sure here the memory + // is indeed empty where we want to make a change. There's no guarantees that we don't damage anything but with all + // the safeguards here the chance is minimal. + if (unlikely(host_to_us(sdp->host)->pusb_dev)) { + pr_loc_crt("Cannot camouflage - space on pointer not empty"); + return -EINVAL; + } + + if (unlikely(get_shimmed_boot_dev())) { + pr_loc_wrn("Refusing to camouflage. Boot device was already shimmed but a new matching device appeared again - " + "this may produce unpredictable outcomes! Ignoring - check your hardware"); + return -EEXIST; + } + + pr_loc_dbg("Camouflaging SATA disk vendor=\"%s\" model=\"%s\" to look like a USB boot device", sdp->vendor, + sdp->model); + + pr_loc_dbg("Generating fake USB descriptor"); + kzalloc_or_exit_int(fake_usbd, sizeof(struct usb_device)); + usb_shim_as_boot_dev(boot_dev_config, fake_usbd); + + pr_loc_dbg("Setting-up ida_pre_get() trap"); + ida_pre_get_ovs = override_symbol("ida_pre_get", ida_pre_get_trap); + if (unlikely(IS_ERR(ida_pre_get_ovs))) { + pr_loc_err("Failed to override ida_pre_get - error=%ld", PTR_ERR(ida_pre_get_ovs)); + ida_pre_get_ovs = NULL; + kfree(fake_usbd); + return PTR_ERR(ida_pre_get_ovs); + } + + pr_loc_dbg("Disabling rescheduling"); + preempt_disable(); + local_irq_save(irq_flags); + + pr_loc_dbg("Changing port type %d => %d", sdp->host->hostt->syno_port_type, SYNO_PORT_TYPE_USB); + org_port_type = sdp->host->hostt->syno_port_type; + sdp->host->hostt->syno_port_type = SYNO_PORT_TYPE_USB; + + pr_loc_dbg("Faking ptr to usb_device at %p", &host_to_us(sdp->host)->pusb_dev); + host_to_us(sdp->host)->pusb_dev = fake_usbd; + + camouflaged_sdp = sdp; + set_shimmed_boot_dev(sdp); + + return 0; +} + +/** + * Undoes what camouflage_device() does; i.e. restores device to its normal SATA-view + * + * @param sdp Previously camouflaged device + * + * @return 0 on success, -E on error + */ +static int uncamouflage_device(struct scsi_device *sdp) +{ + int out = 0; + pr_loc_dbg("Uncamouflaging SATA disk vendor=\"%s\" model=\"%s\"", sdp->vendor, sdp->model); + + if (unlikely(host_to_us(sdp->host)->pusb_dev != fake_usbd)) { + pr_loc_bug("Fake USB device in the scsi_device is not the same as our fake one - something changed it"); + return -EINVAL; + } + + camouflaged_sdp = NULL; + + pr_loc_dbg("Removing fake usb_device ptr at %p", &host_to_us(sdp->host)->pusb_dev); + host_to_us(sdp->host)->pusb_dev = NULL; + + pr_loc_dbg("Restoring port type %d => %d", sdp->host->hostt->syno_port_type, org_port_type); + sdp->host->hostt->syno_port_type = org_port_type; + org_port_type = 0; + + pr_loc_dbg("Re-enabling scheduling"); + local_irq_restore(irq_flags); + preempt_enable(); + + if (likely(ida_pre_get_ovs)) { //scheduling race condition may have removed that already in ida_pre_get_trap() + pr_loc_dbg("Removing ida_pre_get() trap"); + if ((out = restore_symbol(ida_pre_get_ovs)) != 0) + pr_loc_err ("Failed to restore original ida_pre_get() - error=%d", out); + ida_pre_get_ovs = NULL; + } + + pr_loc_dbg("Cleaning fake USB descriptor"); + kfree(fake_usbd); + fake_usbd = NULL; + + return out; +} + +/** + * Called for every existing SCSI disk to determine if any of them is a candidate to be a boot device. + * + * If a given device is a SATA drive which matches shim criteria it will be unplugged & replugged to be shimmed. + * + * @param sdp This "struct device" should already be guaranteed to be an scsi_device with type=TYPE_DISK (i.e. returning + * "true" from is_scsi_disk()). It will be re-checked anyway but there's no point in passing anything which + * is not a SCSI disk. + * + * @return 0 means "continue calling me" while any other value means "I found what I was looking for, stop calling me". + * This convention is based on how bus_for_each_dev() works + */ +static int on_existing_scsi_disk_device(struct scsi_device *sdp) +{ + if (!scsi_is_boot_dev_target(boot_dev_config, sdp)) + return 0; + + pr_loc_dbg("Found a shimmable SCSI device - reconnecting to trigger shimming"); + scsi_force_replug(sdp); + + return 1; +} + +/** + * Called for every new (or recently forcefully re-plugged) device to camouflage it as a USB boot disk + */ +static int scsi_disk_probe_handler(struct notifier_block *self, unsigned long state, void *data) +{ + struct scsi_device *sdp = data; + + switch (state) { + case SCSI_EVT_DEV_PROBING: + if (unlikely(camouflaged_sdp)) { + pr_loc_bug("Got device probe when other one is camouflaged - surprise reschedule happened?"); + uncamouflage_device(camouflaged_sdp); + return NOTIFY_OK; + } + + if (scsi_is_boot_dev_target(boot_dev_config, data)) + camouflage_device(sdp); + + return NOTIFY_OK; + + case SCSI_EVT_DEV_PROBED_OK: + case SCSI_EVT_DEV_PROBED_ERR: + if (is_camouflaged(sdp)) { //camouflage is expected to be removed by the ida_pre_get() trap + pr_loc_bug("Probing finished but device is still camouflages - something went terribly wrong"); + uncamouflage_device(sdp); + } + + return NOTIFY_OK; + + default: + pr_loc_dbg("Not interesting SCSI EVT %lu - ignoring", state); + return NOTIFY_DONE; + } + +} + +static struct notifier_block scsi_disk_nb = { + .notifier_call = scsi_disk_probe_handler, + .priority = INT_MIN, //we want to be FIRST so that we other things can get the correct drive type +}; + +int register_fake_sata_boot_shim(const struct boot_media *config) +{ + shim_reg_in(); + +#ifdef NATIVE_SATA_DOM_SUPPORTED + pr_loc_wrn("This platform supports native SATA DoM - usage of %s is highly discouraged", SHIM_NAME); +#else + pr_loc_inf("This %s is a prototype - if stability is desired use USB boot media instead", SHIM_NAME); +#endif + + int out; + boot_dev_config = config; + + pr_loc_dbg("Registering for new devices notifications"); + out = subscribe_scsi_disk_events(&scsi_disk_nb); + if (unlikely(out != 0)) { + pr_loc_err("Failed to register for SCSI disks notifications - error=%d", out); + boot_dev_config = NULL; + return out; + } + + pr_loc_dbg("Iterating over existing devices"); + out = for_each_scsi_disk(on_existing_scsi_disk_device); + if (unlikely(out != 0 && out != -ENXIO)) { + pr_loc_err("Failed to enumerate current SCSI disks - error=%d", out); + boot_dev_config = NULL; + return out; + } + + shim_reg_ok(); + return 0; +} + +int unregister_fake_sata_boot_shim(void) +{ + shim_ureg_in(); + + unsubscribe_scsi_disk_events(&scsi_disk_nb); + boot_dev_config = NULL; + + shim_ureg_ok(); + return 0; //noop +} \ No newline at end of file diff --git a/shim/boot_dev/fake_sata_boot_shim.h b/shim/boot_dev/fake_sata_boot_shim.h new file mode 100644 index 0000000..9799785 --- /dev/null +++ b/shim/boot_dev/fake_sata_boot_shim.h @@ -0,0 +1,8 @@ +#ifndef REDPILL_FAKE_SATA_BOOT_SHIM_H +#define REDPILL_FAKE_SATA_BOOT_SHIM_H + +struct boot_media; +int register_fake_sata_boot_shim(const struct boot_media *config); +int unregister_fake_sata_boot_shim(void); + +#endif //REDPILL_FAKE_SATA_BOOT_SHIM_H diff --git a/shim/boot_dev/native_sata_boot_shim.c b/shim/boot_dev/native_sata_boot_shim.c new file mode 100644 index 0000000..4510610 --- /dev/null +++ b/shim/boot_dev/native_sata_boot_shim.c @@ -0,0 +1,285 @@ +/** + * Implements shimming SATA device to look like a SATA DOM (Disk-on-Module) device supported by the syno kernel + * If you didn't read the docs for shim/boot_device_shim.c go there and read it first! + * + * HOW THE KERNEL ASSIGNS SYNOBOOT TYPE? + * The determination of what is or isn't the correct synoboot device for SATA is made using vendor and model *names*, as + * standard SCSI/SATA don't have any VID/PID designation like USB or PCI. + * Syno kernel uses different vendor/model names depending on the platform. They are taken from the kernel config option + * pairs CONFIG_SYNO_SATA_DOM_VENDOR/CONFIG_SYNO_SATA_DOM_MODEL and CONFIG_SYNO_SATA_DOM_VENDOR_SECOND_SRC/ + * CONFIG_SYNO_SATA_DOM_MODEL_SECOND_SRC. This gives the following supported matrix at the time of writing: + * - vendor-name="SATADOM" and model-name="TYPE D 3SE" (purley only) + * - vendor-name="SATADOM-" and model-name="TYPE D 3SE" (all except purley) + * - vendor-name="SATADOM" and model-name="3SE" (purley only) + * - vendor-name="SATADOM" and model-name="D150SH" (all other) + * + * HOW THIS SHIM MATCHES DEVICE TO SHIM? + * The decision is made based on "struct boot_media" (derived from boot config) passed to the register method. The + * only criterion used is the physical size of the disk. The *first* device which is smaller or equal to + * boot_media->dom_size_mib will be shimmed. If a consecutive device matching this rule appears a warning will be + * triggered. + * This sounds quite unusual. We considered multiple options before going that route: + * - Unlike USB we cannot easily match SATA devices using any stable identifier so any VID/PID was out of the window + * - S/N sounds like a good candidate unless you realize hypervisors use the same one for all disks + * - Vendor/Model names cannot be edited by the user and hypervisors ust the same one for all disks + * - Host/Port location can change (and good luck updating it in the boot params every time) + * - The only stable factor seems to be size + * + * HOW IT WORKS FOR HOT PLUGGED DEVICES? + * While the USB boot shim depends on a race condition (albeit a pretty stable one) there's no way to use the same + * method for SATA, despite both of them using SCSI under the hood. This is because true SCSI/SATA devices are directly + * supported by the drivers/scsi/sd.c which generates no events before the type is determined. Because of this we + * decided to exploit the dynamic nature of Linux drivers subsystem. All drivers register their buses with the kernel + * and are automatically informed by the kernel if something appears on these buses (either during boot or via hot plug) + * + * This module simply asks the kernel drivers subsystem for the driver registered for "sd" (SCSI) devices. Then it + * replaces its trigger function pointer. Normally it points to drivers/scsi/sd.c:sd_probe() which "probes" and configs + * the device. Our sd_probe_shim() first reads the capacity and if criteria are met (see section above) it replaces + * the vendor & model names and passes the control to the real sd_probe(). If nothing matches it transparently calls + * the real sd_probe(). + * + * If you're debugging you can test it without restarting the whole SD by removing and re-adding device. For example for + * "sd 6:0:0:0: [sdg] 630784 512-byte logical blocks: (322 MB/308 MiB)" you should do: + * echo 1 > /sys/block/sdg/device/delete # change SDG to the correct device + * echo "0 0 0" > /sys/class/scsi_host/host6/scan # host 6 is the same as "sd 6:..." notation in dmesg + * Warning: rescans and delete hard-yanks the device from controller so DO NOT do this on a disk with important data! + * + * HOW IT WORKS FOR EXISTING DEVICES? + * Unfortunately, our sd_probe() replacement is still a bit of a race condition. However, this time we're racing with + * SCSI driver loading which usually isn't a module. Because of this we need to expect some (probably all) devices to be + * already probed. We need to do essentially what's described above (with /sys) but from kernel space. + * To avoid any crashes and possible data loss we are never touching disks which aren't SATA and matching the size + * match criterion. In other words this shim will NOT yank a data drive from the system. + * + * WHAT IF THIS CODE LOADS BEFORE THE DRIVER?! + * Despite the SCSI driver being one of the first things loaded by the kernel and something which almost everywhere is + * baked into to kernel there's a way to load our module earlier (via ioscheduler). In such case we cannot even use + * driver_find("sd", ...) as it will return NULL (since there's no driver for "sd" *yet*). In such case we can hook + * "scsi_register_driver()" which is an exported symbol (==it will last) and keep it hooked until we find the + * registration of "sd" driver in particular (as SCSI also handles CDROMs, USBs, iSCSI and others) + * + * THE FINAL PICTURE + * Ok, it is pretty complex indeed. Here's the decision tree this submodule goes through: + * register_native_sata_boot_shim() + * => driver_find("sd", ...) + * ===FOUND=== + * + shim sd_probe() to sd_probe_shim() + * + * + probe_existing_devices() + * + * ===NOT FOUND=== + * + override scsi_register_driver() [using start_scsi_register_driver_watcher()] + * + * ===scsi_register_driver() called & drv->name is "sd"=== [see scsi_register_driver_shim()] + * + modify drv->probe to &sd_probe_shim + * + stop_scsi_register_driver_watcher() + * + * + call [now original] scsi_register_driver() + * + * + * KNOWN LIMITATIONS + * If you hot-unplug that SATA drive which is used for synoboot it will NOT be shimmed the next time you plug it without + * rebooting. This is because we were lazy and didn't implement the removal shimming (as this behavior isn't defined + * anyway with synoboot devices as they're not user-removable). + * + * This shim is only supported on kernels compiled with CONFIG_SYNO_BOOT_SATA_DOM enabled. Kernels built without that + * option will never check for the vendor/model names and will never be considered SYNOBOOT. + * + * SOURCES + * - Synology's kernel GPL source -> drivers/scsi/sd.c, search for "gSynoBootSATADOM" + * - https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf + */ +#include "native_sata_boot_shim.h" +#include "../../common.h" +#include "../../config/runtime_config.h" //consts, NATIVE_SATA_DOM_SUPPORTED + +#ifdef NATIVE_SATA_DOM_SUPPORTED +#include "boot_shim_base.h" //set_shimmed_boot_dev(), get_shimmed_boot_dev(), scsi_is_boot_dev_target() +#include "../shim_base.h" //shim_reg_*(), scsi_ureg_*() +#include "../../internal/call_protected.h" //scsi_scan_host_selected() +#include "../../internal/scsi/scsi_toolbox.h" //scsi_force_replug(), for_each_scsi_disk() +#include "../../internal/scsi/scsi_notifier.h" //watching for new devices to shim them as they appear +#include //struct scsi_device + +#define SHIM_NAME "native SATA DOM boot device" + +static const struct boot_media *boot_dev_config = NULL; //passed to scsi_is_shim_target() + +//Structure for watching for new devices (via SCSI notifier / scsi_notifier.c event system) +static int on_new_scsi_disk(struct notifier_block *self, unsigned long state, void *data); +static struct notifier_block scsi_disk_nb = { + .notifier_call = on_new_scsi_disk, + .priority = INT_MAX //We want to be LAST, after all other possible fixes has been already applied +}; + +/********************************************* Actual shimming routines ***********************************************/ +/** + * Attempts to shim the device passed + * + * @return 0 if device was successfully shimmed, -E on error + */ +static int shim_device(struct scsi_device *sdp) +{ + pr_loc_dbg("Trying to shim SCSI device vendor=\"%s\" model=\"%s\"", sdp->vendor, sdp->model); + + if (get_shimmed_boot_dev()) { + pr_loc_wrn("The device should be shimmed but another device has been already shimmed as boot dev." + "Device has been ignored."); + return -EEXIST; + } + + pr_loc_dbg("Shimming device to vendor=\"%s\" model=\"%s\"", CONFIG_SYNO_SATA_DOM_VENDOR, + CONFIG_SYNO_SATA_DOM_MODEL); + strcpy((char *)sdp->vendor, CONFIG_SYNO_SATA_DOM_VENDOR); + strcpy((char *)sdp->model, CONFIG_SYNO_SATA_DOM_MODEL); + set_shimmed_boot_dev(sdp); + + return 0; +} + +/** + * Handles registration of newly plugged SCSI/SATA devices. It's called by the SCSI notifier automatically. + * + * @return NOTIFY_* + */ +static __used int on_new_scsi_disk(struct notifier_block *self, unsigned long state, void *data) +{ + if (state != SCSI_EVT_DEV_PROBING) + return NOTIFY_DONE; + + struct scsi_device *sdp = data; + + pr_loc_dbg("Found new SCSI disk vendor=\"%s\" model=\"%s\": checking boot shim viability", sdp->vendor, sdp->model); + if (!scsi_is_boot_dev_target(boot_dev_config, sdp)) + return NOTIFY_OK; + + int err = shim_device(data); + if (unlikely(err != 0)) { + //If we let the device register it may be misinterpreted as a normal disk and possibly formatted + pr_loc_err("Shimming process failed with error=%d - " + "preventing the device from appearing in the OS to avoid possible damage", err); + return NOTIFY_BAD; + } + + return NOTIFY_OK; +} + +/** + * Processes existing device and if it's a SATA drive which matches shim criteria it will be unplugged & replugged to be + * shimmed + * + * @param sdp This "struct device" should already be guaranteed to be an scsi_device with type=TYPE_DISK (i.e. returning + * "true" from is_scsi_disk()) + * + * @return 0 means "continue calling me" while any other value means "I found what I was looking for, stop calling me". + * This convention is based on how bus_for_each_dev() works + */ +static int on_existing_scsi_disk(struct scsi_device *sdp) +{ + pr_loc_dbg("Found existing SCSI disk vendor=\"%s\" model=\"%s\": checking boot shim viability", sdp->vendor, + sdp->model); + + if (!scsi_is_boot_dev_target(boot_dev_config, sdp)) + return 0; + + //So, now we know it's a shimmable target but we cannot just call shim_device() as this will change vendor+model on + // already connected device, which will change these information but will not trigger syno type change. When we + // disconnect & reconnect the device it will reappear and go through the on_new_scsi_disk() route. + pr_loc_inf("SCSI disk vendor=\"%s\" model=\"%s\" is already connected but it's a boot dev. " + "It will be forcefully reconnected to shim it as boot dev.", sdp->vendor, sdp->model); + + int out = scsi_force_replug(sdp); + if (out < 0) + pr_loc_err("Failed to replug the SCSI device (error=%d) - it may not shim as expected", out); + else + pr_loc_dbg("SCSI device replug triggered successfully"); + + return 1; +} + +/****************************************** Standard public API of the shim *******************************************/ +static bool shim_registered = false; +int register_native_sata_boot_shim(const struct boot_media *config) +{ + shim_reg_in(); + + //Regardless of the method we must set the expected size (in config) as shim may be called any moment from now on + boot_dev_config = config; + int out = 0; + + if (unlikely(boot_dev_config->type != BOOT_MEDIA_SATA_DOM)) { + pr_loc_bug("%s doesn't support device type %d", __FUNCTION__, boot_dev_config->type); + out = -EINVAL; + goto fail; + } + + if (unlikely(shim_registered)) { + pr_loc_bug("Native SATA boot shim is already registered"); + out = -EEXIST; + goto fail; + } + + /* We always set-up watching for new devices, as the SCSI notifier is smart enough to accept new subscribers + * regardless of the driver state, but if the driver is already loaded we also need to take care of existing devs. + * Additionally, subscribing for notifications will, in the future, give us info if a device went away. + */ + out = subscribe_scsi_disk_events(&scsi_disk_nb); + if (unlikely(out != 0)) { + pr_loc_err("Failed to register for SCSI disks notifications - error=%d", out); + goto fail; + } + + //This will already check if driver is loaded and only iterate if it is + out = for_each_scsi_disk(on_existing_scsi_disk); + //0 means "call me again" or "success", 1 means "found what I wanted, stop iterating", -ENXIO is "driver not ready" + if (unlikely(out < 0 && out != -ENXIO)) { + pr_loc_dbg("SCSI driver is already loaded but iteration over existing devices failed - error=%d", out); + goto fail_unwatch; + } + + shim_registered = true; + shim_reg_ok(); + return 0; + + fail_unwatch: + unsubscribe_scsi_disk_events(&scsi_disk_nb); //we keep the original code, so this function return code is ignored + fail: + boot_dev_config = NULL; + return out; +} + +int unregister_native_sata_boot_shim(void) +{ + shim_ureg_in(); + + if (unlikely(!shim_registered)) { + pr_loc_bug("Native SATA boot shim is not registered"); + return -ENOENT; + } + + int out = unsubscribe_scsi_disk_events(&scsi_disk_nb); + if (out != 0) + pr_loc_err("Failed to unsubscribe from SCSI events"); + + + //@todo we are consciously NOT doing reset_shimmed_boot_dev(). It may be registered and we're not doing anything to + // unregister it + + shim_registered = false; + shim_ureg_ok(); + return 0; +} +#else //ifdef NATIVE_SATA_DOM_SUPPORTED +int register_native_sata_boot_shim(const struct boot_media *boot_dev_config) +{ + pr_loc_err("Native SATA boot shim cannot be registered in a kernel built without SATA DoM support"); + return -ENODEV; +} + +int unregister_native_sata_boot_shim(void) +{ + pr_loc_err("Native SATA boot shim cannot be unregistered in a kernel built without SATA DoM support"); + return -ENODEV; +} +#endif //ifdef else NATIVE_SATA_DOM_SUPPORTED \ No newline at end of file diff --git a/shim/boot_dev/native_sata_boot_shim.h b/shim/boot_dev/native_sata_boot_shim.h new file mode 100644 index 0000000..3853b7e --- /dev/null +++ b/shim/boot_dev/native_sata_boot_shim.h @@ -0,0 +1,8 @@ +#ifndef REDPILL_NATIVE_SATA_BOOT_SHIM_H +#define REDPILL_NATIVE_SATA_BOOT_SHIM_H + +struct boot_media; +int register_native_sata_boot_shim(const struct boot_media *config); +int unregister_native_sata_boot_shim(void); + +#endif //REDPILL_NATIVE_SATA_BOOT_SHIM_H diff --git a/shim/boot_dev/usb_boot_shim.c b/shim/boot_dev/usb_boot_shim.c new file mode 100644 index 0000000..2dd3b10 --- /dev/null +++ b/shim/boot_dev/usb_boot_shim.c @@ -0,0 +1,271 @@ +/** + * Implements shimming USB device to look like an embedded USB device supported by the syno kernel + * If you didn't read the docs for shim/boot_device_shim.c go there and read it first! + * + * HOW THE KERNEL ASSIGNS SYNOBOOT TYPE? + * The determination of what is or isn't the correct synoboot device for USBs is made using VID & PID of the device. + * During normal operation both of them need to equal 0xf400 to be considered a boot device. In a special "mfg" mode the + * installation is forced with 0xf401 ids instead. + * + * HOW THIS SHIM MATCHES DEVICE TO SHIM? + * The decision is made based on "struct boot_media" (derived from boot config) passed to the register method: + * - if vid/pid combo is set (i.e. not VID_PID_EMPTY) it must match the newly detected device + * - if vid/pid is not set (i.e. VID_PID_EMPTY) the first device is used (NOT recommended unless you don't use USB) + * - if a second device matching any of the criteria above appears a warning is emitted and device is ignored + * + * HOW IT WORKS? + * In order to dynamically change VID & PID of a USB device we need to modify device descriptor just after the device is + * detected by the USB subsystem. However it has to be done before the device is picked up by the SCSI subsystem, which + * is responsible for creating /dev/xxx entries. + * Since the assumption is that the USB stick is present from boot the sequence of events needs to look like that: + * 0. Kernel starts + * 1. This LKM is loaded + * 2. USB subsystem loads + * 3. Drive is detected + * 4. This LKM changes VID+PID + * 5. SCSI subsystem detects the device and creates a /dev/... node for it + * + * This poses several problems. First this module must load before USB subsystem. Then to get the device quicker than + * SCSI subsystem can a notification receiver is set up. However we need to wait to do this after the usbcore actually + * loads. To make sure it's the case a kernel module watcher is used. That's why symbols from usbcore are loaded + * dynamically, as at the moment of this LKM insertion they aren't available. In case usbcore is loaded before this LKM + * VID+PID change may not be effective (this scenario is supported pretty much for debugging only). + * This sequence is rather time sensitive. It shouldn't fail on any modern multicore system. + * + * References + * - Synology's kernel GPL source -> drivers/scsi/sd.c, search for "IS_SYNO_USBBOOT_ID_" + * - https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-4.html + * - https://lwn.net/Articles/160501/ + */ +#include "usb_boot_shim.h" +#include "boot_shim_base.h" //set_shimmed_boot_dev(), get_shimmed_boot_dev(), usb_shim_as_boot_dev() +#include "../shim_base.h" //shim_* +#include "../../common.h" +#include "../../config/runtime_config.h" //struct boot_device & consts +#include "../../internal/helper/symbol_helper.h" //kernel_has_symbol() +#include "../../internal/call_protected.h" //dynamically calling usb_* functions +#include +#include +#include //struct module + +#define SHIM_NAME "USB boot device" + +static bool module_notify_registered = false; +static bool device_notify_registered = false; +static const struct boot_media *boot_media = NULL; //passed to usb_shim_as_boot_dev() + +/** + * Responds to USB devices being added/removed + */ +static int device_notifier_handler(struct notifier_block *b, unsigned long event, void *data) +{ + struct usb_device *device = (struct usb_device*)data; + struct usb_device *prev_device = get_shimmed_boot_dev(); + + if (event == USB_DEVICE_ADD) { + //TODO: Can we even check if it matched mass storage here... (bInterfaceClass == USB_CLASS_MASS_STORAGE) + if (boot_media->vid == VID_PID_EMPTY || boot_media->pid == VID_PID_EMPTY) { + pr_loc_wrn("Your boot device VID and/or PID is not set - " + "using device found (prev_shimmed=%d)", + device->descriptor.idVendor, device->descriptor.idProduct, prev_device ? 1:0); + } else if (device->descriptor.idVendor != boot_media->vid || device->descriptor.idProduct != boot_media->pid) { + pr_loc_dbg("Found new device - " + "didn't match expected (prev_shimmed=%d)", + device->descriptor.idVendor, device->descriptor.idProduct, boot_media->vid, boot_media->pid, + prev_device ? 1:0); + + return NOTIFY_OK; + } + + //This will happen especially when VID+PID weren't set and two USB devices were detected + if (prev_device) { + pr_loc_wrn("Boot device was already shimmed but a new matching device appeared again - " + "this may produce unpredictable outcomes! Ignoring - check your hardware"); + return NOTIFY_OK; + } + + usb_shim_as_boot_dev(boot_media, device); + set_shimmed_boot_dev(device); + + pr_loc_inf("Device shimmed to ", boot_media->vid, boot_media->pid, + device->descriptor.idVendor, device->descriptor.idProduct); + + return NOTIFY_OK; + } + + + if (prev_device && event == USB_DEVICE_REMOVE && device == prev_device) { + pr_loc_wrn("Previously shimmed boot device gone away"); + reset_shimmed_boot_dev(); + return NOTIFY_OK; + } + + return NOTIFY_OK; +} + +static struct notifier_block device_notifier_block = { + .notifier_call = device_notifier_handler, + .priority = INT_MIN, //We need to be first +}; +/** + * Watches for USB events + */ +static void register_device_notifier(void) +{ + //This should never happen but there's never enough error checking. + //Even if the module was already loaded register_device_notifier() should not be called twice before module is + // unloaded and reloaded + if (unlikely(device_notify_registered)) { + pr_loc_bug("Device notify re-registration via %s w/o module unload (?!)", __FUNCTION__); + return; + } + + //This has to use dynamic calling to avoid being dependent on usbcore (since we need to load before usbcore) + _usb_register_notify(&device_notifier_block); //has no return value + + device_notify_registered = true; + pr_loc_dbg("Registered USB device notifier"); +} + +static int unregister_device_notifier(void) +{ + if (unlikely(!device_notify_registered)) { + pr_loc_bug("%s called while notifier not registered", __FUNCTION__); + return -ENOENT; + } + + //This has to use dynamic calling to avoid being dependent on usbcore (since we need to load before usbcore) + _usb_unregister_notify(&device_notifier_block); //has no return value + device_notify_registered = false; + pr_loc_dbg("Unregistered USB device notifier"); + + return 0; +} + +/** + * Responds to "usbcore" [and others] load + */ +static int ubscore_notifier_handler(struct notifier_block * self, unsigned long state, void * data) +{ + struct module *mod = data; + if (strcmp(mod->name, "usbcore") != 0) + return NOTIFY_OK; + + if (state == MODULE_STATE_GOING) { + //TODO: call unregister with some force flag? + device_notify_registered = false; + reset_shimmed_boot_dev(); + pr_loc_wrn("usbcore module unloaded - this should not happen normally"); + return NOTIFY_OK; + } + + //This may need to be changed to MODULE_STATE_LIVE if MODULE_STATE_COMING is too early for device notification + if (state != MODULE_STATE_LIVE) + return NOTIFY_OK; + + pr_loc_dbg("usbcore registered, adding device watcher"); + register_device_notifier(); + + return NOTIFY_OK; +} + +static struct notifier_block usbcore_notifier_block = { + .notifier_call = ubscore_notifier_handler +}; +/** + * Watches for "usbcore" module load + */ +static int register_usbcore_notifier(void) +{ + int error = 0; + + if (unlikely(module_notify_registered)) { + pr_loc_bug("%s called while notifier already registered", __FUNCTION__); + return 0; //technically it's not an error + } + + error = register_module_notifier(&usbcore_notifier_block); + if(unlikely(error != 0)) { + pr_loc_err("Failed to register module notifier"); //Currently it's impossible to happen... currently + return error; + } + + module_notify_registered = true; + pr_loc_dbg("Registered usbcore module notifier"); + + //check if usbcore is MAYBE already loaded and give a warning + call register_device_notifier() manually + // this state is FINE for debugging but IS NOT FINE for production use + //We're using kernel_has_symbol() to not acquire module mutex needed for module checks + if (kernel_has_symbol("usb_register_notify")) { + pr_loc_wrn("usbcore module is already loaded (did you load this module too late?) " + "-> registering device notifier right away"); + register_device_notifier(); + } + + return error; +} + +static int unregister_usbcore_notifier(void) +{ + if (unlikely(!module_notify_registered)) { //unregister should be called first if so + pr_loc_bug("%s called while notifier not registered", __FUNCTION__); + return -ENOENT; + } + + int out = unregister_module_notifier(&usbcore_notifier_block); + if(unlikely(out != 0)) { + pr_loc_err("Failed to unregister module notifier"); //Currently it's impossible to happen... currently + return out; + } + + module_notify_registered = false; + pr_loc_dbg("Unregistered usbcore module notifier"); + + return 0; +} + +int register_usb_boot_shim(const struct boot_media *boot_dev_config) +{ + shim_reg_in(); + + if (unlikely(boot_dev_config->type != BOOT_MEDIA_USB)) { + pr_loc_bug("%s doesn't support device type %d", __FUNCTION__, boot_dev_config->type); + return -EINVAL; + } + + if (unlikely(boot_media)) { + pr_loc_bug("USB boot shim is already registered"); + return -EEXIST; + } + + boot_media = boot_dev_config; + + int out = register_usbcore_notifier(); //it will register device notifier when module loads + if (out != 0) + return out; + + shim_reg_ok(); + return out; +} + +int unregister_usb_boot_shim(void) +{ + shim_ureg_in(); + + if (unlikely(!boot_media)) { + pr_loc_bug("USB boot shim is not registered"); + return -ENOENT; + } + + int out = 0; + if ( + (out = unregister_usbcore_notifier()) != 0 + || (out = unregister_device_notifier()) != 0 + ) + return out; + + boot_media = NULL; + + shim_ureg_ok(); + return out; +} diff --git a/shim/boot_dev/usb_boot_shim.h b/shim/boot_dev/usb_boot_shim.h new file mode 100644 index 0000000..1220dd0 --- /dev/null +++ b/shim/boot_dev/usb_boot_shim.h @@ -0,0 +1,8 @@ +#ifndef REDPILL_USB_BOOT_SHIM_H +#define REDPILL_USB_BOOT_SHIM_H + +struct boot_media; +int register_usb_boot_shim(const struct boot_media *boot_dev_config); +int unregister_usb_boot_shim(void); + +#endif //REDPILL_USB_BOOT_SHIM_H diff --git a/shim/boot_device_shim.c b/shim/boot_device_shim.c new file mode 100644 index 0000000..1c6bcb6 --- /dev/null +++ b/shim/boot_device_shim.c @@ -0,0 +1,109 @@ +/** + * Boot device shim ensures that DSM assigns a proper /dev/ device to our USB stick or SATA DOM + * + * WHY IS THIS NEEDED? + * In short the DSM has multiple types of SCSI devices (boot device, USB drive, eSATA drive etc). The boot device is + * always mounted to /dev/synoboot (with respective partitions at /dev/synobootN). The determination what to place there + * is made based on different factors depending on the type of device used to boot (see drivers/scsi/sd.c): + * 1) Standard USB stick + * - it has to be connected via a real USB port (i.e. not a fake-usb-over-sata like ESXi tries to do) + * - it must have VID/PID combo of 0xf400/0xf400 + * - allows for normal boot when OS is installed, or triggers OS install/repair screen + * 2) Force-install USB stick + * - it has to be connected via a real USB port + * - it must have VID/PID combo of 0xf401/0xf401 + * - always triggers OS install/repair screen + * 3) SATA DOM (Disk-on-Module) + * - kernel is compiled with SATA DOM support (NATIVE_SATA_DOM_SUPPORTED => CONFIG_SYNO_BOOT_SATA_DOM) + * - is a real SATA (i.e. not SCSI/iSCSI/VirtIO) device + * - has platform dependent vendor/model strings of CONFIG_SYNO_SATA_DOM_VENDOR/CONFIG_SYNO_SATA_DOM_MODEL + * - has platform dependent vendor/model strings of CONFIG_SYNO_SATA_DOM_VENDOR_SECOND_SRC/CONFIG_SYNO_SATA_DOM_MODEL_SECOND_SRC + * - SATA DOM *cannot* be used to force-reinstall (as there isn't an equivalent of USB's VID/PID of 0xf401/0xf401) + * - restrictions of native SATA-DOM are lifted by sata_port_shim.c and fake_sata_boot_shim.c + * + * There are other special ones (e.g. iSCSI) which aren't supported here. These only apply to small subset of platforms. + * + * HOW IT WORKS? + * Depending on the runtime configuration this shim will either engage USB-based shim or SATA-based one. See respective + * implementations in shim/boot_dev/. + * + * References: + * - See drivers/scsi/sd.c in Linux sources (especially sd_probe() method) + */ +#define SHIM_NAME "boot device router" + +#include "boot_device_shim.h" +#include "shim_base.h" +#include "../common.h" +#include "../config/runtime_config.h" +#include "boot_dev/usb_boot_shim.h" +#include "boot_dev/fake_sata_boot_shim.h" +#include "boot_dev/native_sata_boot_shim.h" + +#define BOOT_MEDIA_SHIM_NULL (-1) + +static int registered_type = BOOT_MEDIA_SHIM_NULL; +int register_boot_shim(const struct boot_media *boot_dev_config) +{ + shim_reg_in(); + + if (unlikely(registered_type != BOOT_MEDIA_SHIM_NULL)) { + pr_loc_bug("Boot shim is already registered with type=%d", registered_type); + return -EEXIST; + } + + int out; + switch (boot_dev_config->type) { + case BOOT_MEDIA_USB: + out = register_usb_boot_shim(boot_dev_config); + break; + case BOOT_MEDIA_SATA_DOM: + out = register_native_sata_boot_shim(boot_dev_config); + break; + case BOOT_MEDIA_SATA_DISK: + out = register_fake_sata_boot_shim(boot_dev_config); + break; + default: + pr_loc_bug("Failed to %s - unknown type=%d", __FUNCTION__, boot_dev_config->type); + return -EINVAL; + } + + if (out != 0) + return out; //individual shims should print what went wrong + + registered_type = boot_dev_config->type; + + shim_reg_ok(); + return 0; +} + +int unregister_boot_shim(void) +{ + shim_ureg_in(); + + int out; + switch (registered_type) { + case BOOT_MEDIA_USB: + out = unregister_usb_boot_shim(); + break; + case BOOT_MEDIA_SATA_DOM: + out = unregister_native_sata_boot_shim(); + break; + case BOOT_MEDIA_SATA_DISK: + out = unregister_fake_sata_boot_shim(); + case BOOT_MEDIA_SHIM_NULL: + pr_loc_bug("Boot shim is no registered"); + return -ENOENT; + default: //that cannot happen unless register_boot_shim() is broken + pr_loc_bug("Failed to %s - unknown type=%d", __FUNCTION__, registered_type); + return -EINVAL; + } + + if (out != 0) + return out; //individual shims should print what went wrong + + registered_type = BOOT_MEDIA_SHIM_NULL; + + shim_ureg_ok(); + return 0; +} \ No newline at end of file diff --git a/shim/boot_device_shim.h b/shim/boot_device_shim.h new file mode 100644 index 0000000..71df881 --- /dev/null +++ b/shim/boot_device_shim.h @@ -0,0 +1,8 @@ +#ifndef REDPILLLKM_BOOT_DEVICE_SHIM_H +#define REDPILLLKM_BOOT_DEVICE_SHIM_H + +struct boot_media; +int register_boot_shim(const struct boot_media *boot_dev_config); +int unregister_boot_shim(void); + +#endif //REDPILLLKM_BOOT_DEVICE_SHIM_H diff --git a/shim/disable_exectutables.c b/shim/disable_exectutables.c new file mode 100644 index 0000000..2df725c --- /dev/null +++ b/shim/disable_exectutables.c @@ -0,0 +1,37 @@ +#define SHIM_NAME "common executables disabler" + +#include "disable_exectutables.h" +#include "shim_base.h" +#include "../common.h" +#include "../internal/intercept_execve.h" + +#define PSTORE_PATH "/usr/syno/bin/syno_pstore_collect" +#define BOOTLOADER_UPDATE1_PATH "uboot_do_upd.sh" +#define BOOTLOADER_UPDATE2_PATH "./uboot_do_upd.sh" +#define SAS_FW_UPDATE_PATH "/tmpData/upd@te/sas_fw_upgrade_tool" + +int register_disable_executables_shim(void) +{ + shim_reg_in(); + + int out; + if ( + (out = add_blocked_execve_filename(BOOTLOADER_UPDATE1_PATH)) != 0 + || (out = add_blocked_execve_filename(BOOTLOADER_UPDATE2_PATH)) != 0 + || (out = add_blocked_execve_filename(PSTORE_PATH)) != 0 + || (out = add_blocked_execve_filename(SAS_FW_UPDATE_PATH)) != 0 + ) { + pr_loc_bug("Failed to disable some executables"); + return out; + } + + shim_reg_ok(); + return 0; +} + +int unregister_disable_executables_shim(void) +{ + //noop - execve entries will be cleared in one sweep during unregister of interceptor (it's much faster this way) + //this function is kept for consistency + return 0; +} \ No newline at end of file diff --git a/shim/disable_exectutables.h b/shim/disable_exectutables.h new file mode 100644 index 0000000..7ef62e6 --- /dev/null +++ b/shim/disable_exectutables.h @@ -0,0 +1,7 @@ +#ifndef REDPILL_DISABLE_EXECTUTABLES_H +#define REDPILL_DISABLE_EXECTUTABLES_H + +int register_disable_executables_shim(void); +int unregister_disable_executables_shim(void); + +#endif //REDPILL_DISABLE_EXECTUTABLES_H diff --git a/shim/pci_shim.c b/shim/pci_shim.c new file mode 100644 index 0000000..346cfb6 --- /dev/null +++ b/shim/pci_shim.c @@ -0,0 +1,243 @@ +#define SHIM_NAME "PCI devices" + +#include "pci_shim.h" +#include "shim_base.h" +#include "../common.h" +#include "../config/vpci_types.h" //MAX_VPCI_DEVS, pci_shim_device_type +#include "../config/platform_types.h" //hw_config +#include "../internal/virtual_pci.h" +#include + +unsigned int free_dev_idx = 0; +static void *devices[MAX_VPCI_DEVS] = { NULL }; + +static struct pci_dev_descriptor *allocate_vpci_dev_dsc(void) { + if (free_dev_idx >= MAX_VPCI_DEVS) { + /*index has to be at max MAX_VPCI_DEVS-1*/ + pr_loc_bug("No more device indexes are available (max devs: %d)", MAX_VPCI_DEVS); + return ERR_PTR(-ENOMEM); + } + + struct pci_dev_descriptor *dev_dsc; + kmalloc_or_exit_ptr(dev_dsc, sizeof(struct pci_dev_descriptor)); + memcpy(dev_dsc, &pci_dev_conf_default_normal_dev, sizeof(struct pci_dev_descriptor)); + devices[free_dev_idx++] = dev_dsc; + + return dev_dsc; +} +#define allocate_vpci_dev_dsc_var() \ + struct pci_dev_descriptor *dev_dsc = allocate_vpci_dev_dsc(); \ + if (IS_ERR(dev_dsc)) return PTR_ERR(dev_dsc); + +static int +add_vdev(struct pci_dev_descriptor *dev_dsc, unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, + bool is_mf) +{ + const struct virtual_device *vpci_vdev; + + if (is_mf) { + vpci_vdev = vpci_add_multifunction_device(bus_no, dev_no, fn_no, dev_dsc); + } else if(unlikely(fn_no != 0x00)) { + //Making such config will either cause the device to not show up at all or only fn_no=0 one will show u + pr_loc_bug("%s called with non-MF device but non-zero fn_no", __FUNCTION__); + return -EINVAL; + } else { + vpci_vdev = vpci_add_single_device(bus_no, dev_no, dev_dsc); + } + + return IS_ERR(vpci_vdev) ? PTR_ERR(vpci_vdev) : 0; +} + +/** + * Adds a fake Marvell controller + * + * These errors in kernlog are normal (as we don't emulate the behavior of the controller as it's not needed): + * pci 0001:0a:00.0: Can't map mv9235 registers + * ahci: probe of 0001:0a:00.0 failed with error -22 + * + * @return 0 on success or -E + */ +static inline int +vdev_add_generic_marvell_ahci(u16 dev, unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_MARVELL_EXT; + dev_dsc->dev = dev; + dev_dsc->rev_id = 0x11; //All Marvells so far use revision 11 + dev_dsc->class = U24_CLASS_TO_U8_CLASS(PCI_CLASS_STORAGE_SATA_AHCI); + dev_dsc->subclass = U24_CLASS_TO_U8_SUBCLASS(PCI_CLASS_STORAGE_SATA_AHCI); + dev_dsc->prog_if = U24_CLASS_TO_U8_PROGIF(PCI_CLASS_STORAGE_SATA_AHCI); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_MARVELL_88SE9235(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_marvell_ahci(0x9235, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_MARVELL_88SE9215(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_marvell_ahci(0x9215, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_I211(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = 0x1539; + dev_dsc->rev_id = 0x03; //Not confirmed + dev_dsc->class = U16_CLASS_TO_U8_CLASS(PCI_CLASS_NETWORK_ETHERNET); + dev_dsc->subclass = U16_CLASS_TO_U8_SUBCLASS(PCI_CLASS_NETWORK_ETHERNET); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_X552(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = 0x15ad; + dev_dsc->rev_id = 0x03; //Not confirmed + dev_dsc->class = U16_CLASS_TO_U8_CLASS(PCI_CLASS_NETWORK_ETHERNET); + dev_dsc->subclass = U16_CLASS_TO_U8_SUBCLASS(PCI_CLASS_NETWORK_ETHERNET); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + + +static int vdev_add_INTEL_CPU_AHCI_CTRL(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = 0x5ae3; + dev_dsc->class = U24_CLASS_TO_U8_CLASS(PCI_CLASS_STORAGE_SATA_AHCI); + dev_dsc->subclass = U24_CLASS_TO_U8_SUBCLASS(PCI_CLASS_STORAGE_SATA_AHCI); + dev_dsc->prog_if = U24_CLASS_TO_U8_PROGIF(PCI_CLASS_STORAGE_SATA_AHCI); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +//This technically should be a bridge but we don't have the info to recreate full tree +static inline int +vdev_add_generic_intel_pcie(u16 dev, unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) { + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = dev; + dev_dsc->class = U16_CLASS_TO_U8_CLASS(PCI_CLASS_BRIDGE_PCI); + dev_dsc->subclass = U16_CLASS_TO_U8_SUBCLASS(PCI_CLASS_BRIDGE_PCI); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_PCIE_PA(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_intel_pcie(0x5ad8, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_PCIE_PB(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_intel_pcie(0x5ad6, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_USB_XHCI(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = 0x5aa8; + dev_dsc->class = U24_CLASS_TO_U8_CLASS(PCI_CLASS_SERIAL_USB_XHCI); + dev_dsc->subclass = U24_CLASS_TO_U8_SUBCLASS(PCI_CLASS_SERIAL_USB_XHCI); + dev_dsc->prog_if = U24_CLASS_TO_U8_PROGIF(PCI_CLASS_SERIAL_USB_XHCI); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +static inline int +vdev_add_generic_intel_io(u16 dev, unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = dev; + dev_dsc->class = U16_CLASS_TO_U8_CLASS(PCI_CLASS_SP_OTHER); + dev_dsc->subclass = U16_CLASS_TO_U8_SUBCLASS(PCI_CLASS_SP_OTHER); + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_I2C(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_intel_io(0x5aac, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_HSUART(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_intel_io(0x5abc, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_SPI(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + return vdev_add_generic_intel_io(0x5ac6, bus_no, dev_no, fn_no, is_mf); +} + +static int vdev_add_INTEL_CPU_SMBUS(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) +{ + allocate_vpci_dev_dsc_var(); + dev_dsc->vid = PCI_VENDOR_ID_INTEL; + dev_dsc->dev = 0x5ad4; + dev_dsc->class = U16_CLASS_TO_U8_CLASS(PCI_CLASS_SERIAL_SMBUS); + dev_dsc->subclass = U16_CLASS_TO_U8_SUBCLASS(PCI_CLASS_SERIAL_SMBUS); + + return add_vdev(dev_dsc, bus_no, dev_no, fn_no, is_mf); +} + +static int (*dev_type_handler_map[])(unsigned char bus_no, unsigned char dev_no, unsigned char fn_no, bool is_mf) = { + [VPD_MARVELL_88SE9235] = vdev_add_MARVELL_88SE9235, + [VPD_MARVELL_88SE9215] = vdev_add_MARVELL_88SE9215, + [VPD_INTEL_I211] = vdev_add_INTEL_I211, + [VPD_INTEL_X552] = vdev_add_INTEL_X552, + [VPD_INTEL_CPU_AHCI_CTRL] = vdev_add_INTEL_CPU_AHCI_CTRL, + [VPD_INTEL_CPU_PCIE_PA] = vdev_add_INTEL_CPU_PCIE_PA, + [VPD_INTEL_CPU_PCIE_PB] = vdev_add_INTEL_CPU_PCIE_PB, + [VPD_INTEL_CPU_USB_XHCI] = vdev_add_INTEL_CPU_USB_XHCI, + [VPD_INTEL_CPU_I2C] = vdev_add_INTEL_CPU_I2C, + [VPD_INTEL_CPU_HSUART] = vdev_add_INTEL_CPU_HSUART, + [VPD_INTEL_CPU_SPI] = vdev_add_INTEL_CPU_SPI, + [VPD_INTEL_CPU_SMBUS] = vdev_add_INTEL_CPU_SMBUS, +}; + +int register_pci_shim(const struct hw_config *hw) +{ + shim_reg_in(); + + pr_loc_dbg("Creating vPCI devices for %s", hw->name); + int out; + for (int i = 0; i < MAX_VPCI_DEVS; i++) { + if (hw->pci_stubs[i].type == __VPD_TERMINATOR__) + break; + + pr_loc_dbg("Calling %ps with B:D:F=%02x:%02x:%02x mf=%d", dev_type_handler_map[hw->pci_stubs[i].type], + hw->pci_stubs[i].bus, hw->pci_stubs[i].dev, hw->pci_stubs[i].fn, + hw->pci_stubs[i].multifunction ? 1 : 0); + + out = dev_type_handler_map[hw->pci_stubs[i].type](hw->pci_stubs[i].bus, hw->pci_stubs[i].dev, + hw->pci_stubs[i].fn, hw->pci_stubs[i].multifunction); + + if (out != 0) { + pr_loc_err("Failed to create vPCI device B:D:F=%02x:%02x:%02x - error=%d", hw->pci_stubs[i].bus, + hw->pci_stubs[i].dev, hw->pci_stubs[i].fn, out); + return out; + } + + pr_loc_dbg("vPCI device %d created successfully", i+1); + } + + shim_reg_ok(); + return 0; +} + +int unregister_pci_shim(void) +{ + shim_ureg_in(); + vpci_remove_all_devices_and_buses(); + + for (int i = 0; i < free_dev_idx; i++) { + pr_loc_dbg("Free PCI dev %d @ %p", i, devices[i]); + kfree(devices[i]); + } + + shim_ureg_ok(); + return -EIO; //vpci_remove_all_devices_and_buses has a bug - this is a canary to not forget +} diff --git a/shim/pci_shim.h b/shim/pci_shim.h new file mode 100644 index 0000000..8aac673 --- /dev/null +++ b/shim/pci_shim.h @@ -0,0 +1,24 @@ +#ifndef REDPILL_PCI_SHIM_H +#define REDPILL_PCI_SHIM_H + +enum pci_shim_device_type { + __VPD_TERMINATOR__, + VPD_MARVELL_88SE9235, //1b4b:9235 + VPD_MARVELL_88SE9215, //1b4b:9215 + VPD_INTEL_I211, //8086:1539 + VPD_INTEL_X552, //8086:15ad + VPD_INTEL_CPU_AHCI_CTRL, //8086:5ae3 + VPD_INTEL_CPU_PCIE_PA, //8086:5ad8 + VPD_INTEL_CPU_PCIE_PB, //8086:5ad6 + VPD_INTEL_CPU_USB_XHCI, //8086:5aa8 + VPD_INTEL_CPU_I2C, //8086:5aac + VPD_INTEL_CPU_HSUART, //8086:5abc + VPD_INTEL_CPU_SPI, //8086:5ac6 + VPD_INTEL_CPU_SMBUS, //8086:5ad4 +}; + +typedef struct hw_config hw_config_; +int register_pci_shim(const struct hw_config *hw); +int unregister_pci_shim(void); + +#endif //REDPILL_PCI_SHIM_H diff --git a/shim/pmu_shim.c b/shim/pmu_shim.c new file mode 100644 index 0000000..3be1e49 --- /dev/null +++ b/shim/pmu_shim.c @@ -0,0 +1,387 @@ +#define SHIM_NAME "PMU emulator" + +#include "pmu_shim.h" +#include "shim_base.h" +#include "../common.h" +#include "../internal/uart/virtual_uart.h" +#include //kfifo_* + +#define PMU_TTYS_LINE 1 //so far this is hardcoded by syno, so we doubt it will ever change +#define WORK_BUFFER_LEN VUART_FIFO_LEN +#define to_hex_buf_len(len) ((len)*3+1) //2 chars for each hex + space + NULL terminator +#define HEX_BUFFER_LEN to_hex_buf_len(VUART_FIFO_LEN) + +//PMU packets are at minimum 2 bytes long (PMU_CMD_HEAD + 1-3 bytes command + optional data). If this is set to a high +// value (e.g. VUART_FIFO_LEN) in practice commands will only be delivered when the client indicates end-of-transmission) +// which may not be bad... +#define PMU_MIN_PACKET 2 +#define PMU_CMD_HEAD 0x2d //every PMU packet is delimited by containing 0x2d (ASCII "-"/dash) as its first character + +typedef struct command_definition command_definition; + +/** + * A single PMU command and its routing + */ +struct command_definition { + void (*fn) (const command_definition *t, const char *data, u8 data_len); + const u8 length; //commands are realistically 1-3 chars only + const char *name; +} __packed; + +/** + * Result for matching of command signature against known list + */ +typedef enum { + PMU_CMD_AMBIGUOUS = -1, + PMU_CMD_NOT_FOUND = 0, + PMU_CMD_FOUND = 1, +} pmu_match_status; + +/** + * Default/noop shim for a PMU command. It simply prints the command received. + */ +static void cmd_shim_noop(const command_definition *t, const char *data, u8 data_len) +{ + pr_loc_dbg("vPMU received %s using %d bytes - NOOP", t->name, data_len); +} + +//@todo when we get the physical PMU emulator we can move this to a separate library so that shim contacts an internal +// routing routine for commands which aren't shimmed here. Then we will add all PMU=>kernel commands as well. Currently +// we only define kernel=>PMU ones as these are the ones we need to listen for. +#define PMU_CMD__MIN_CODE 0x30 +#define PMU_CMD__MAX_CODE 0x75 +#define single_byte_idx(id) ((id)-PMU_CMD__MIN_CODE) +#define get_single_byte_cmd(id) single_byte_cmds[single_byte_idx(id)] //call it ONLY after has_single_byte_cmd!!! +#define has_single_byte_cmd(id) \ + (likely((id) >= PMU_CMD__MIN_CODE) && likely((id) <= PMU_CMD__MAX_CODE) && get_single_byte_cmd(id).length != 0) +#define DEFINE_SINGLE_BYTE_CMD(cnm, fp) [single_byte_idx(PMU_CMD_ ## cnm)] = { .name = #cnm, .length = 1, .fn = fp } + +#define PMU_CMD_OUT_HW_POWER_OFF 0x31 //"1" +#define PMU_CMD_OUT_BUZ_SHORT 0x32 //"2" +#define PMU_CMD_OUT_BUZ_LONG 0x33 //"3" +#define PMU_CMD_OUT_PWR_LED_ON 0x34 //"4" +#define PMU_CMD_OUT_PWR_LED_BLINK 0x35 //"5" +#define PMU_CMD_OUT_PWR_LED_OFF 0x36 //"6" +#define PMU_CMD_OUT_STATUS_LED_OFF 0x37 //"7" +#define PMU_CMD_OUT_STATUS_LED_ON_GREEN 0x38 //"8" +#define PMU_CMD_OUT_STATUS_LED_PULSE_GREEN 0x39 //"9" +#define PMU_CMD_OUT_STATUS_LED_ON_ORANGE 0x3A //":" +#define PMU_CMD_OUT_STATUS_LED_PULSE_ORANGE 0x3B //";" +//0x3C unknown (possibly not used) +#define PMU_CMD_OUT_STATUS_LED_PULSE 0x3d //"=" +//0x3E-3F unknown (possibly not used) +#define PMU_CMD_OUT_USB_LED_ON 0x40 //"@" +#define PMU_CMD_OUT_USB_LED_PULSE 0x41 //"A" +#define PMU_CMD_OUT_USB_LED_OFF 0x42 //"B" +#define PMU_CMD_OUT_HW_RESET 0x43 //"C" +//0x43-4A unknown +#define PMU_CMD_OUT_10G_LED_ON 0x4a //"J" +#define PMU_CMD_OUT_10G_LED_OFF 0x4b //"K" +//0x4C unknown +#define PMU_CMD_OUT_LED_TOG_PWR_STAT 0x4d //"M", allows for using one led for status and power and toggle between them +//0x4E unknown +#define PMU_CMD_OUT_SWITCH_UP_VER 0x4f //"O" +#define PMU_CMD_OUT_MIR_LED_OFF 0x50 //"P" +//0x51-55 unknown (except 52) +#define PMU_CMD_OUT_GET_UNIQ 0x52 //"P" +#define PMU_CMD_OUT_PWM_CYCLE 0x56 //"V" +#define PMU_CMD_OUT_PWM_HZ 0x57 //"W" +//0x58-59 unknown +//0x60-71 inputs (except 6C) +#define PMU_CMD_OUT_WOL_ON 0x6c //"l" +#define PMU_CMD_OUT_SCHED_UP_OFF 0x72 //"r" +#define PMU_CMD_OUT_SCHED_UP_ON 0x73 //"s" +#define PMU_CMD_OUT_FAN_HEALTH_OFF 0x74 //"t" +#define PMU_CMD_OUT_FAN_HEALTH_ON 0x75 //"u" + +static const command_definition single_byte_cmds[single_byte_idx(PMU_CMD__MAX_CODE)+1] = { + DEFINE_SINGLE_BYTE_CMD(OUT_HW_POWER_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_BUZ_SHORT, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_BUZ_LONG, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_PWR_LED_ON, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_PWR_LED_BLINK, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_PWR_LED_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_STATUS_LED_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_STATUS_LED_ON_GREEN, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_STATUS_LED_PULSE_GREEN, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_STATUS_LED_ON_ORANGE, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_STATUS_LED_PULSE_ORANGE, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_STATUS_LED_PULSE, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_USB_LED_ON, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_USB_LED_PULSE, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_USB_LED_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_HW_RESET, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_10G_LED_ON, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_10G_LED_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_LED_TOG_PWR_STAT, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_SWITCH_UP_VER, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_MIR_LED_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_GET_UNIQ, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_PWM_CYCLE, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_PWM_HZ, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_WOL_ON, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_SCHED_UP_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_SCHED_UP_ON, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_FAN_HEALTH_OFF, cmd_shim_noop), + DEFINE_SINGLE_BYTE_CMD(OUT_FAN_HEALTH_ON, cmd_shim_noop), +}; + + +static char *uart_buffer = NULL; //keeps data streamed directly by the vUART... todo: vUART should manage this buffer +static char *work_buffer = NULL; //collecting & operatint on the data received from vUART +static char *work_buffer_curr = NULL; //pointer to the current free space in work_buffer +static char *hex_print_buffer = NULL; //helper buffer to print char arrays in hex + +#define work_buffer_fill() ((unsigned int)(work_buffer_curr - work_buffer)) + +/** + * Free all buffers used by this submodule + * + * It is safe to call this method without checking buffers state (it has a deliberate protection against double-free) + */ +static void free_buffers(void) +{ + if (likely(uart_buffer)) + kfree(uart_buffer); + + if (likely(work_buffer)) + kfree(work_buffer); + + if (likely(hex_print_buffer)) + kfree(hex_print_buffer); + + uart_buffer = NULL; + work_buffer = NULL; + work_buffer_curr = NULL; + hex_print_buffer = NULL; +} + +/** + * Allocates space for all buffers used by this submodule + */ +static int alloc_buffers(void) +{ + kmalloc_or_exit_int(uart_buffer, VUART_FIFO_LEN); + kmalloc_or_exit_int(work_buffer, WORK_BUFFER_LEN); + kmalloc_or_exit_int(hex_print_buffer, HEX_BUFFER_LEN); + + work_buffer_curr = work_buffer; + + return 0; +} + +/** + * Converts passed char buffer into user-readable hex print of it + * + * @todo this should probably be extracted + */ +static __used const char *get_hex_print(const char *buffer, int len) +{ + if (unlikely(len == 0)) { + hex_print_buffer[0] = '\0'; + return hex_print_buffer; + } else if (unlikely(to_hex_buf_len(len) > HEX_BUFFER_LEN)) { + pr_loc_bug("Printing %d bytes as hex requires %d bytes in buffer - buffer is %d bytes", len, + to_hex_buf_len(len), HEX_BUFFER_LEN); + hex_print_buffer[0] = '\0'; + return hex_print_buffer; + } + + int hex_len = 0; + for (int i = 0; i < len; ++i) { + sprintf(&hex_print_buffer[i * 3], "%02x ", buffer[i]); + hex_len += 3; + } + + hex_print_buffer[hex_len-1] = '\0'; + return hex_print_buffer; +} + +/** + * Matches command against a list of known ones based on the signature specified + * + * @param cmd pointer to a pointer where address of command structure can be saved if found + */ +static pmu_match_status noinline +match_command(const command_definition **cmd, const char *signature, const unsigned int sig_len) +{ + if (unlikely(sig_len == 0)) { + pr_loc_dbg("Invalid zero-length command (stray head without command signature) - discarding"); + return PMU_CMD_NOT_FOUND; + } + + if (likely(sig_len == 1) //regular 1 byte + || (sig_len == 3 && signature[1] == 0x0d && signature[2] == 0x0a) //1 byte with CRLF (sic!) + ) { + if (!has_single_byte_cmd(signature[0])) + return PMU_CMD_NOT_FOUND; + + *cmd = &get_single_byte_cmd(signature[0]); + return PMU_CMD_FOUND; + } + + return PMU_CMD_NOT_FOUND; //@todo Currently we don't handle multibyte commands; it has to be a full iteration +} + +/** + * Finds command based on its signature and execute its callback if found + */ +static void route_command(const char *buffer, const unsigned int len) +{ + const command_definition *cmd = NULL; + + if (match_command(&cmd, buffer, len) != PMU_CMD_FOUND) { + pr_loc_wrn("Unknown %d byte PMU command with signature hex=\"%s\" ascii=\"%.*s\"", len, + get_hex_print(buffer, len), len, buffer); + return; + } + + pr_loc_dbg("Executing cmd %s handler %pF", cmd->name, cmd->fn); + cmd->fn(cmd, buffer, len); +} + +/** + * Scans work buffer (copied from vUART buffer) to find commands + * + * @param end_of_packet Indicates whether this command was called because the vUART transmitter assumed + * end-of-transmission/IDLE, or flushed due to its buffer being full. If this parameter is true the + * data in the work buffer is assumed to be a complete representation of the state. This becomes + * important if we cannot with 100% confidence say, after reaching the end of the buffer, if it + * will be a multibyte command (but we possibly didn't get all the bytes YET) or this is single or + * multibyte command which we don't know. + * + * This function makes an assumption that when it's called that the buffer represents the whole state of the command + * If this becomes to take too long we can move it to a separate thread, but this will require a lock. + */ +static noinline void process_work_buffer(bool end_of_packet) +{ + if (unlikely(work_buffer == work_buffer_curr)) { + //this can happen if kernel sends no data but we get IDLE... shouldn't logically happen + pr_loc_wrn("%s called on empty buffer?!", __FUNCTION__); + return; + } + + int cmd_len = -1; //number of bytes in the command (excluding header) + for(char *curr = work_buffer; curr < work_buffer_curr; ++curr) { + if (*curr == PMU_CMD_HEAD) { //got the beginning of a new command + //we've found a new command in the buffer - lets check if the previously collected data matches anything + if (cmd_len != -1) { //we only want to call it if this isn't the first byte after last cmd (or 1st in buf) + route_command(curr-cmd_len, cmd_len); + cmd_len = 0; //we've got the head so 0 and not -1 + } else { + ++cmd_len; //We've read the buffer containing head, we then expect to get something which is non-head + } + } else { + if (cmd_len == -1) { //we don't expect data before head + pr_loc_wrn("Found garbage data in PMU buffer before cmd head (\"%c\" / 0x%02x) - ignoring", *curr, + *curr); + continue; + } + + ++cmd_len; //collecting another byte for the currently processed command + } + } + + //We've finished processing the buffer. Now we need to decide what to do with that last piece of data + unsigned int processed = work_buffer_fill(); + if (cmd_len != -1) { //if it's -1 it means we didn't find any heading so we're just discarding all data + if (end_of_packet) { + route_command(work_buffer_curr-cmd_len, cmd_len); + } else { //if the packed didn't end we need to keep that piece of buffer for the next run + processed -= cmd_len + 1; //we also keep head + } + } + + unsigned int left = work_buffer_fill() - processed; + if (likely(left != 0)) { + memmove(work_buffer, work_buffer+processed, left); + } + work_buffer_curr = work_buffer + left; + +// pr_loc_dbg("Left buffer %p curr=%p with %d bytes in it (ascii=\"%.*s\" hex={%s})", work_buffer, work_buffer_curr, left, left, work_buffer, +// get_hex_print(work_buffer, left)); +} + +/** + * Callback passed to vUART. It will be called any time some data is available. + */ +static noinline void pmu_rx_callback(int line, const char *buffer, unsigned int len, vuart_flush_reason reason) +{ + pr_loc_dbg("Got %d bytes from PMU: reason=%d hex={%s} ascii=\"%.*s\"", len, reason, get_hex_print(buffer, len), len, buffer); + + int buffer_space = WORK_BUFFER_LEN - work_buffer_fill(); + if (unlikely(work_buffer_curr + len > work_buffer + WORK_BUFFER_LEN)) { //todo just remove as much as needed from the buffer to fit more data + pr_loc_err("Work buffer is full! Only %d of %d bytes will be copied from receiver", len, buffer_space); + len = buffer_space; + } + + memcpy(work_buffer_curr, buffer, len); + work_buffer_curr += len; +// pr_loc_dbg("Copied data to work buffer, now with %d bytes in it (cur=%p)", +// (unsigned int)(work_buffer_curr - work_buffer), work_buffer_curr); + + //We only want to analyze the buffer when we are sure we have the full command to process. This is because commands + // are variable length and have no end delimiter not length specified with prefixes of short commands conflicting + // with longer commands (sic!) + //For example, you have "SW1" command which when sent will look like "-SW1" (0x2d 0x53 0x57 0x31). We can capture + // this when VUART_FLUSH_IDLE happens. We can also easily capture this when multiple commands are sent at once + // (unlikely but possible) since it will be something like "-SW1-3". However, we CANNOT distinguish "-S" from + // incomplete "-SW1". So we need to rely on IDLE - if we got "-S" with IDLE it means it was "-S" and not the + // beginning of "-SW1". + //We also forcefully flush on full buffer even if no IDLE was specified, as it's technically possible for the + // software to send a long sequence of commands at once totaling more than our buffer (extremely unlikely). + //Additionally, we only process IDLE-signalled buffers when they have at least a single byte of data as some + // versions of the mfgBIOS attach head AND THEN in a separate packet send the actual commands (sic!) + if (reason == VUART_FLUSH_IDLE && work_buffer_fill() > 1) + process_work_buffer(true); + //our buffer is full [we must process] or vUART buffer was full [we should process] + else if (buffer_space <= len || reason == VUART_FLUSH_FULL) + process_work_buffer(false); +} + +int register_pmu_shim(const struct hw_config *hw) +{ + shim_reg_in(); + + int out; + if ((out = vuart_add_device(PMU_TTYS_LINE) != 0)) { + pr_loc_err("Failed to initialize vUART for PMU at ttyS%d", PMU_TTYS_LINE); + return out; + } + + if ((out = alloc_buffers()) != 0) + goto error_out; + + //We don't set the threshold as some commands are variable length but the "packets" are properly split + if ((out = vuart_set_tx_callback(PMU_TTYS_LINE, pmu_rx_callback, uart_buffer, VUART_THRESHOLD_MAX))) { + pr_loc_err("Failed to register RX callback"); + goto error_out; + } + + shim_reg_ok(); + return 0; + + error_out: + free_buffers(); + vuart_remove_device(PMU_TTYS_LINE); //this also removes callback (if set) + return out; +} + +int unregister_pmu_shim(void) +{ + shim_ureg_in(); + + int out = 0; + if (unlikely(!uart_buffer)) { + pr_loc_bug("Attempted to %s while it's not registered", __FUNCTION__); + return 0; //Technically it succeeded + } + + if ((out = vuart_remove_device(PMU_TTYS_LINE)) != 0) + pr_loc_err("Failed to remove vUART for line=%d", PMU_TTYS_LINE); + + free_buffers(); + + shim_ureg_ok(); + return out; +} \ No newline at end of file diff --git a/shim/pmu_shim.h b/shim/pmu_shim.h new file mode 100644 index 0000000..9eaebe0 --- /dev/null +++ b/shim/pmu_shim.h @@ -0,0 +1,8 @@ +#ifndef REDPILL_PMU_SHIM_H +#define REDPILL_PMU_SHIM_H + +typedef struct hw_config hw_config_; +int register_pmu_shim(const struct hw_config *hw); +int unregister_pmu_shim(void); + +#endif //REDPILL_PMU_SHIM_H diff --git a/shim/shim_base.h b/shim/shim_base.h new file mode 100644 index 0000000..cedffb3 --- /dev/null +++ b/shim/shim_base.h @@ -0,0 +1,20 @@ +#ifndef REDPILL_SHIM_BASE_H +#define REDPILL_SHIM_BASE_H + +#define shim_reg_in() pr_loc_dbg("Registering %s shim", SHIM_NAME); +#define shim_reg_ok() pr_loc_inf("Successfully registered %s shim", SHIM_NAME); +#define shim_reg_already() do { \ + pr_loc_bug("Called %s while %s() shim is already", __FUNCTION__, SHIM_NAME); \ + return -EALREADY; \ +} while(0) +#define shim_ureg_in() pr_loc_dbg("Unregistering %s shim", SHIM_NAME); +#define shim_ureg_ok() pr_loc_inf("Successfully unregistered %s shim", SHIM_NAME); +#define shim_ureg_nreg() do { \ + pr_loc_bug("Called %s() while %s shim is not registered (yet?)", __FUNCTION__, SHIM_NAME); \ + return -ENXIO; \ +} while(0) +#define shim_reset_in() pr_loc_inf("Forcefully resetting %s shim", SHIM_NAME); +#define shim_reset_ok() pr_loc_inf("Successfully reset %s", SHIM_NAME); + + +#endif //REDPILL_SHIM_BASE_H diff --git a/shim/storage/sata_port_shim.c b/shim/storage/sata_port_shim.c new file mode 100644 index 0000000..04ab24c --- /dev/null +++ b/shim/storage/sata_port_shim.c @@ -0,0 +1,149 @@ +/** + * Allows for usage of SCSI-based storage devices like they were bare standard SATA ones + * + * WHY THIS SHIM? + * Normally Linux doesn't care if something is an SCSI device or a SATA one, as SATA is a subset of SCSI (technically + * speaking SATA is an interface using SCSI protocol). However, the syno-modified SCSI driver (drivers/scsi/sd.c) adds + * a layer of logical disk types. These types determine what the disk actually is, so that the NAS can know what should + * be done with them. + * For example SYNO_DISK_USB, SYNO_DISK_SYNOBOOT, SYNO_DISK_SATA, and SYNO_DISK_ISCSI are all normally visible in the + * system as /dev/sdX and are all SCSI-based drives. However, you can only use RAID on SATA drives and not on USB ones. + * The "SYNO_DISK_SATA" is kind-of a catch-all type for all disks which are used for storing data, even if they're not + * really SATA disks. One of the exceptions set by the sd.c driver is that if VirtIO driver is used all disks connected + * via that method are treated as SYNO_DISK_SATA. Unfortunately that, very logical and useful, assumption is made ONLY + * when the kernel is compiled with CONFIG_SYNO_KVMX64 (which is a special platform for VDSM). On all other platforms + * disks connected to VirtIO will be slightly broken in old versions and unusable in newer ones (as their tpe is set to + * SYNO_DISK_UNKNOWN). This shim brings the functionality available on CONFIG_SYNO_KVMX64 to all platforms. + * In addition, it changes SAS ports to be SATA as well as syno reserves SYNO_DISK_SAS for usage with just a few FS + * devices and external enclosures. + * + * HOW DOES IT WORK? + * It simply plugs into the SCSI driver (via SCSI notifier) and waits for a new drive. When a new drive is connected it + * checks if it was connected via the VirtIO driver or through a SAS card driver and changes the port type to + * SYNO_PORT_TYPE_SATA, which will later force the driver to assume the drive is indeed a "SATA" drive (SYNO_DISK_SATA). + * While the ports can be enumerated and changed all at once, it's safer to do it per-drive basis as drivers allow for + * ports to be dynamically reconfigured and thus the type may change. This is also why we make no effort of + * restoring port types after this shim is unregistered. + * + * References + * - drivers/scsi/sd.c in Linux sources + */ +#include "sata_port_shim.h" +#include "../shim_base.h" +#include "../../common.h" +#include "../../internal/scsi/scsi_toolbox.h" //scsi_force_replug() +#include "../../internal/scsi/scsi_notifier.h" +#include //struct scsi_device +#include //struct Scsi_Host, SYNO_PORT_TYPE_* +#include "../../config/runtime_config.h" +#include "../../config/platform_types.h" + +#define SHIM_NAME "SATA port emulator" +#define VIRTIO_HOST_ID "Virtio SCSI HBA" + +/** + * Checks if we should fix a given device or ignore it + */ +static bool is_fixable(struct scsi_device *sdp) +{ + return sdp->host->hostt->syno_port_type == SYNO_PORT_TYPE_SAS || + (current_config.hw_config->is_dt == false && // Device-tree models causes a kernel panic if type is changed + sdp->host->hostt->syno_port_type != SYNO_PORT_TYPE_SATA && + strcmp(sdp->host->hostt->name, VIRTIO_HOST_ID) == 0); +} + +/** + * Processes any new devices connected to the system AND existing devices which were forcefully reconnected + * + * When a device which is deemed fixable it will replace its port to SATA to make it work as a standard SATA drive. + * + * @return 0 on success, -E on error + */ +static int on_new_scsi_disk_device(struct scsi_device *sdp) +{ + if (!is_fixable(sdp)) + return 0; + + pr_loc_dbg("Found new disk vendor=\"%s\" model=\"%s\" connected to \"%s\" HBA over non-SATA port (type=%d) - " + "fixing to SATA port (type=%d)", sdp->vendor, sdp->model, sdp->host->hostt->name, + sdp->host->hostt->syno_port_type, SYNO_PORT_TYPE_SATA); + + sdp->host->hostt->syno_port_type = SYNO_PORT_TYPE_SATA; + + return 0; +} + +/** + * Called for every existing SCSI-based disk to determine if there are any fixable devices which are already connected + * + * Every device which is fixable but still connected it will be forcefully re-connected, as this is the only way to fix + * existing device properly. + * + * @return 0 on success, -E on error + */ +static int on_existing_scsi_disk_device(struct scsi_device *sdp) +{ + if (!is_fixable(sdp)) + return 0; + + pr_loc_dbg( + "Found initialized disk vendor=\"%s\" model=\"%s\" connected to \"%s\" HBA over non-SATA port (type=%d)." + " It must be auto-replugged to fix it.", sdp->vendor, sdp->model, sdp->host->hostt->name, + sdp->host->hostt->syno_port_type); + + //After that it will land in on_new_scsi_disk_device() + scsi_force_replug(sdp); + + return 0; +} + +/** + * Tiny shim to direct SCSI notifications to on_existing_scsi_disk_device() before it's probed + */ +static int scsi_disk_probe_handler(struct notifier_block *self, unsigned long state, void *data) +{ + if (state != SCSI_EVT_DEV_PROBING) + return NOTIFY_DONE; + + on_new_scsi_disk_device(data); + return NOTIFY_OK; +} + +static struct notifier_block scsi_disk_nb = { + .notifier_call = scsi_disk_probe_handler, + .priority = INT_MIN, //we want to be FIRST so that we other things can get the correct drive type +}; + +int register_sata_port_shim(void) +{ + shim_reg_in(); + + int out; + + pr_loc_dbg("Registering for new devices notifications"); + out = subscribe_scsi_disk_events(&scsi_disk_nb); + if (unlikely(out != 0)) { + pr_loc_err("Failed to register for SCSI disks notifications - error=%d", out); + return out; + } + + pr_loc_dbg("Iterating over existing devices"); + out = for_each_scsi_disk(on_existing_scsi_disk_device); + if (unlikely(out != 0 && out != -ENXIO)) { + pr_loc_err("Failed to enumerate current SCSI disks - error=%d", out); + return out; + } + + shim_reg_ok(); + return 0; +} + +int unregister_sata_port_shim(void) +{ + shim_ureg_in(); + + unsubscribe_scsi_disk_events(&scsi_disk_nb); + + shim_ureg_ok(); + return 0; //noop +} \ No newline at end of file diff --git a/shim/storage/sata_port_shim.h b/shim/storage/sata_port_shim.h new file mode 100644 index 0000000..d1a8ea1 --- /dev/null +++ b/shim/storage/sata_port_shim.h @@ -0,0 +1,7 @@ +#ifndef REDPILL_SATA_PORT_SHIM_H +#define REDPILL_SATA_PORT_SHIM_H + +int register_sata_port_shim(void); +int unregister_sata_port_shim(void); + +#endif //REDPILL_SATA_PORT_SHIM_H diff --git a/shim/storage/smart_shim.c b/shim/storage/smart_shim.c new file mode 100644 index 0000000..b9e5509 --- /dev/null +++ b/shim/storage/smart_shim.c @@ -0,0 +1,1082 @@ +/** + * Emulates SMART capabilities on drives without SMART support + * + * WHY?! + * When running under a hypervisor some emulated drives will lack SMART support, which is required for some tools to + * operate properly. For example QEmu (e.g. in Proxmox) emulate some basic SMART support (see qemu/hw/ide/core.c), which + * is enough. However, surprisingly popular VMWare products lack any SMART support whatsoever. This is the main reason + * for this shim to exist. + * + * + * HOW IT WORKS? + * The SMART subsystem is rather simple yet contains a large amount of legacy. To understand what's going on here you + * should first read the micron.com docs and then fill-in the details from the official ATA/ATAPI-6 spec (see + * references). Overall the SMART has a few main parts: + * - live/snapshot readings (that's the table with values & thresholds you see in smartctl) + * - capabilities (static values which specify what a given drive can do, e.g. whether SMART is supported) + * - stored logs + * - API to execute tests + * + * All SMART actions are executed by the userspace, and thus delivered via ioctl call to a device. When the ioctl is + * executed a shared buffer is passed which contains a header + space for saving response data. There are two + * different ioctl commands used to execute SMART requests with several subcommands: + * - HDIO_DRIVE_CMD (ioctl, see handle_hdio_drive_cmd_ioctl() & Documentation/ioctl/hdio.txt) + * - ATA_CMD_ID_ATA (read capabilities of the drive, see handle_ata_cmd_identify()) + * # we only hook it to indicate that SMART is supported & enabled even if the ATA disk don't REALLY support it + * # if the drive supports SMART this hook is a noop + * # for non ATA-complaint disks (e.g. VirtIO SCSI) we generate a full fake IDENTIFY data (populate_ata_id()) + * - ATA_CMD_SMART (read data from SMART subsystem, see handle_ata_cmd_smart()) + * # we hook it to emulate SMART data + * # if the drive supports SMART this hook is a noop + * - ATA_SMART_READ_VALUES (read all live values from the drive, see populate_ata_smart_values()) + * - ATA_SMART_READ_THRESHOLDS (read thresholds from live data of the drive, see populate_ata_smart_thresholds()) + * - ATA_SMART_ENABLE (ask drive to enable SMART, it shouldn't really be delivered but we respond with "OK") + * - WIN_FT_SMART_READ_LOG_SECTOR (use WIN_SMART interface to read stored logs, see populate_win_smart_log()) + * - WIN_FT_SMART_IMMEDIATE_OFFLINE (use WIN_SMART iface to run SMART test, see populate_win_smart_exec_test()) + * + * - HDIO_DRIVE_TASK (ioctl, see handle_hdio_drive_task_ioctl() & Documentation/ioctl/hdio.txt) + * - WIN_CMD_SMART (use WIN_SMART to read data from SMART subsystem, see handle_ata_task_smart()) + * # this command is used by smartctl (and probably others) to read a general OK/FAIL status of a drive + * # we respond with "OK" to all commands below + * - WIN_FT_SMART_STATUS + * - WIN_FT_SMART_AUTOSAVE + * - WIN_FT_SMART_AUTO_OFFLINE + * + * Note: Most of the commands are using the standard ATA/ATAPI interface, few are using (legacy?) WIN_SMART interface. + * While WIN_SMART can theoretically be used to read values etc no tool from this century will do that (they will + * use the ATA/ATAPI interface). This shim emulates WIN_SMART only when needed. + * + * + * LIMITATIONS + * - Values are always static and the same for all drives + * - Power-on hours & other counters (e.g. start-stop count) are static + * - Ideally values should be calculated as hours from some date to ensure they increase + * - Start-stop counter (and others) can be derived from power-on hours using linear regression + * + * + * SEQUENCE OF ACTIONS FOR IOCTL REPLACEMENT + * This submodule has a rather unintuitive initialization sequence (it's multistage). It works in the following order: + * 1. Checks if "sd" driver is loaded + * - if not loaded it verifies if it exists in the kernel and overrides sd_ioctl() [see 2.] + * - it SHOULD wait for the driver instead but due to current notifier limitations we can't do that + * 2. Temporarily installs trampoline in sd_ioctl() [drivers/scsi/sd.c] to sd_ioctl_canary() + * 3. Awaits any IOCTL from userspace + * - it simply waits until sd_ioctl_canary() is called + * - sd_ioctl_canary's only role is to install a fast and permanent shim of sd_ioctl() by replacing the ioctl + * routing in SCSI driver (see details in the comment for sd_ioctl_canary()) to point to sd_ioctl_smart_shim() + * - sd_ioctl() trampoline is removed + * - after installation it triggers sd_ioctl_smart_shim() to handle that IOCTL which canary captured + * 4. sd_ioctl_smart_shim() is triggered for every ioctl to a /dev/sdX device coming from the userspace + * - it filters commands which are SMART-related (or at least what smartmontools uses as nobody uses anything else) + * - all non-SMART commands are forwarded as-is + * - SMART commands are forwarded to the drive if the drive supports SMART, if not a sensible values are faked + * + * References + * - https://www.micron.com/-/media/client/global/documents/products/technical-note/solid-state-storage/tnfd10_p400e_smart_firmware_0142.pdf + * - https://hddguru.com/documentation/2006.01.27-ATA-ATAPI-6/ (the official ATA/ATAPI-6 specs) + * - https://www.kernel.org/doc/Documentation/ioctl/hdio.txt (HDIO_* ioctls summary from Linux) + * - https://github.com/qemu/qemu/blob/266469947161aa10b1d36843580d369d5aa38589/hw/ide/core.c#L1826 (qemu SMART) + */ +#include "smart_shim.h" +#include "../shim_base.h" +#include "../../common.h" +#include "../../internal/intercept_driver_register.h" //waiting for "sd" driver to load +#include "../../internal/helper/memory_helper.h" //set_mem_addr_ro(), set_mem_addr_rw() +#include "../../internal/helper/symbol_helper.h" //kernel_has_symbol() +#include "../../internal/scsi/hdparam.h" //a ton of ATA constants +#include "../../internal/scsi/scsi_toolbox.h" //checking for "sd" driver load state +#include "../../internal/override/override_symbol.h" //installing sd_ioctl_canary() +#include //struct block_device +#include //struct gendisk +#include //struct block_device_operations +#include //spinlock_t, spin_* +#include //ATA_* + +#define SHIM_NAME "SMART emulator" + +#ifdef DBG_SMART_PRINT_ALL_IOCTL +#define pr_loc_dbg_ioctl(cmd_hex, subcmd_name, bdev) \ + pr_loc_dbg("Handling ioctl(0x%x)->%s for /dev/%s", cmd_hex, subcmd_name, (bdev)->bd_disk->disk_name); +#define pr_loc_dbg_ioctl_unk(cmd_hex, subcmd_hex, bdev) \ + pr_loc_dbg("Handling ioctl(cmd=0x%x ; sub=0x%x) for /dev/%s - not hooked (noop)", \ + cmd_hex, subcmd_hex, (bdev)->bd_disk->disk_name); +#else +#define pr_loc_dbg_ioctl(cmd_hex, subcmd_name, bdev) //noop +#define pr_loc_dbg_ioctl_unk(cmd_hex, subcmd_hex, bdev) //noop +#endif + +//address of original and unmodified sd_ioctl(); populated by the canary and after the canary trampoline is removed +static int (*sd_ioctl_org) (struct block_device *, fmode_t, unsigned, unsigned long) = NULL; +struct block_device_operations *sd_fops = NULL; //ptr to drivers/scsi/sd.c:sd_fops [to restore sd_ioctl on removal] +static struct override_symbol_inst* sd_ioctl_canary_ovs = NULL; //sd_ioctl() override for canary +static spinlock_t sd_ioctl_canary_lock; + +/********************************************* Fake SMART data definition *********************************************/ +//see "Table 4: SMART Attribute Summary" in micron.com document for a nice summary +//These values below were taken from a random WD drive and slightly modified. While there isn't a definitive list of +// "what must be in SMART" (as ATAPI spec says that everything is vendor-specific) there are some "usually available" +// params the FLAG value is split into low (LSB) and high (MSB). Really only the first 6 bits (so in LSB) are defined: +// Bit 0 - Warranty purposes +// Bit 1 - Offline collected +// Bit 2 - Performance degradation indicator +// Bit 3 - Error rate dependent +// Bit 4 - Event counter (should probably NOT be used with bit 3) +// Bit 5 - Self-preservation +//Values here are a cross-section of HDD & SSD capable ones. While reading these we don't always have easy access to +// the data used to determine whether the drive is an SSD or an HDD so we "play it cool" by only giving values which are +// valid for both. +static const int fake_smart[][ATA_SMART_RECORD_LEN] = { + /* #, lFLAG, hFLAG, VAL, WRST, RAW_DATA, RAW_ATTR_SPC, THRESH, NAME */ + { 1, 0x2d, 0x00, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 }, /* Raw_Read_Error_Rate */ + { 2, 0x04, 0x00, 0x80, 0x75, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 }, /* Throughput_Performance */ + { 3, 0x27, 0x00, 0xb1, 0xB0, 0x4f, 0x12, 0x00, 0x00, 0x00, 0x00, 0x06 }, /* Spin_Up_Time */ + { 4, 0x32, 0x00, 0x64, 0x64, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Start_Stop_Count */ + { 5, 0x33, 0x00, 0xc8, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c }, /* Reallocated_Sector_Ct */ + //Seek_Error_Rate(7) is invalid for SSDs + //deliberately not providing Seek_Time_Performance (8) to prevent fs from "recalibrating" to this + { 9, 0x32, 0x00, 0x06, 0x00, 0xad, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Power_On_Hours */ + //Spin_Retry_Count(10) and Calibration_Retry_Count(11) are invalid for SSDs + { 12, 0x32, 0x00, 0x64, 0x64, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Start_Stop_Count */ + { 13, 0x2e, 0x00, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Read_Soft_Error_Rate */ + //14-174: very vendor-specific / esoteric + //175-182: SSD only + { 183, 0x33, 0x00, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c }, /* Runtime_Bad_Block */ + { 184, 0x33, 0x00, 0xC8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c }, /* End-to-End_Error */ + //185-186: very vendor-specific / esoteric + { 187, 0x3a, 0x00, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 }, /* Reported_Uncorrect */ + { 188, 0x32, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Command_Timeout */ + //High_Fly_Writes(189) is invalid for SSDs + { 190, 0x22, 0x00, 0x3e, 0x3e, 0x1B, 0x00, 0x1E, 0x1B, 0x00, 0x00, 0x00 }, /* Airflow_Temperature_Cel */ + //Sense_Error_Rate(191) is invalid for SSDs + { 192, 0x32, 0x00, 0x64, 0x64, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Power-Off_Retract_Count */ + //Unknown_SSD_Attribute(193) is invalid for SSDs + { 194, 0x22, 0x00, 0x76, 0x62, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Temperature_Celsius */ + { 195, 0x32, 0x00, 0x80, 0x80, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Hardware_ECC_Recovered */ + { 196, 0x32, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Reallocated_Event_Count */ + { 197, 0x32, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Current_Pending_Sector */ + { 198, 0x30, 0x00, 0x64, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Offline_Uncorrectable */ + { 199, 0x32, 0x00, 0xC8, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* UDMA_CRC_Error_Count */ + //rest of the attributes are esoteric or invalid for SSDs +}; + +//SMART components versions (some of them CANNOT be changed) +#define SMART_SNAP_VERSION 0x01 //version for the live data snapshot; vendor-specific +#define WIN_SMART_DIG_LOG_VERSION 0x00 //WIN_SMART log directory version; see 8.55.6.8.1 for details +#define WIN_SMART_SUM_LOG_VERSION 0x01 //WIN_SMART summary log version; ALWAYS 1 as per ATAPI/6 sec. 8.55.6.8.2.1 +#define WIN_SMART_COMP_LOG_VERSION 0x01 //WIN_SMART comprehensive log version; ALWAYS 1 as per ATAPI/6 sec. 8.55.6.8.3.1 +#define WIN_SMART_TEST_LOG_VERSION 0x01 //WIN_SMART self-test log version; ALWAYS 1 as per ATAPI/6 sec. 8.55.6.8.4.1 + + +/********************************************* ATA/IOCTL helper functions *********************************************/ +/** + * Calculates a standard per-sector ATA checksum + * + * ATA/ATAPI-6 standard contains the same checksum references in many places. It's always saved in the last byte of a + * sector (index 511). It is described e.g. in "Table 5: SMART Attribute Entry Format". It's defined as "Two's + * complement checksum of preceding 511B[ytes]". Wikipedia has a great article about that as well. + * + * @param buff A single-sector sized buffer to compute & save checksum to + */ +static void ata_calc_sector_checksum(u8 *buff) +{ + for (int i = 0; i < (ATA_SECT_SIZE-1); i++) { + buff[(ATA_SECT_SIZE-1)] += buff[i]; + } + + buff[(ATA_SECT_SIZE-1)] = 256 - buff[(ATA_SECT_SIZE-1)]; +} + +/** + * Calculates a standard per-worded structure ATA checksum + * + * In principal it's almost the same thing as ata_calc_sector_checksum() but with some constant added to be 16 bits. + * See "8.16.64 Word 255: Integrity word". Checksum is always saved in word 255. + * + * @param word_buff A 255-word (each 16 bits) sized buffer to compute & save checksum to + */ +static void ata_calc_integrity_word(u16 *word_buff) +{ + u8 *byte_buff = (u8 *)word_buff; + + for (int i = 0; i < (ATA_SECT_SIZE-2); i++) { + byte_buff[(ATA_SECT_SIZE-2)] += byte_buff[i]; + } + + byte_buff[(ATA_SECT_SIZE-2)] = 256 - byte_buff[(ATA_SECT_SIZE-2)]; + byte_buff[(ATA_SECT_SIZE-1)] = 0xa5; +} + +/** + * ATA/ATAPI uses "strings" which are LE arranged 8 bit characters into 16 bit words padded with spaces to full length + * + * Example of 10 character ATA field: + * =normal=> "TEST12" + * =ATA====> "ETTS21 " + * + * @param dst buffer to copy the string to + * @param src standard NULL-byte terminated text + * @param length ATA field length; must be even + */ +static void set_ata_string(u8 *dst, const char *src, u8 length) +{ + if (unlikely(length % 2 != 0)) { + pr_loc_bug("Length must be even but got %d", length); + --length; + } + + memset(dst, 0x20, length); //fields in ATA/ATAPI are space-padded and not terminated by \0 + for (u8 i = 0; i < length; i += 2) + { + if (src[i] == '\0') + break; + + dst[i + 1] = src[i]; + dst[i] = src[i + 1]; + } +} + +/** + * Duplicates a user-supplied ioctl() buffer into kernel space to safely read data from it + * + * This pointer returned here is... peculiar. First 4 bytes are a header (as defined by UAPI "struct hd_drive_cmd_hdr" + * in hdreg.h). Remaining 512 bytes are 16 bits words. + * + * @param sectors How many sectors to copy + * @param src User buffer to copy from + * + * @return Pointer to a new kernel-space buffer or ERR_PTR; you need to free/put-it-back using put_ioctl_buffer + */ +static unsigned char* get_ioctl_buffer_kcopy(u8 sectors, const __user void *src) +{ + unsigned char *kbuf; + + kmalloc_or_exit_ptr(kbuf, ata_ioctl_buf_size(sectors)); + if(unlikely(copy_from_user(kbuf, src, ata_ioctl_buf_size(sectors)) != 0)) { + pr_loc_err("Failed to copy ATA user buffer from ptr=%p to kspace=%p", src, kbuf); + kfree(kbuf); + return ERR_PTR(-EFAULT); + } + + return kbuf; +} + +/** + * Releases buffer obtained from get_ioctl_buffer_*() + */ +static __always_inline void put_ioctl_buffer(unsigned char *buffer) +{ + kfree(buffer); +} + +/*************************************** ATAPI/WIN command interface handling *****************************************/ +static int populate_ata_id(const u8 *req_header, void __user *buff_ptr, const char* const disk_name) +{ + pr_loc_dbg("Generating completely fake ATA IDENTITY"); + + unsigned char *kbuf; + char disk_serial[DISK_NAME_LEN]; + kzalloc_or_exit_int(kbuf, HDIO_DRIVE_CMD_HDR_OFFSET + sizeof(struct rp_hd_driveid)); + struct rp_hd_driveid *did = (void *)(kbuf + HDIO_DRIVE_CMD_HDR_OFFSET); //did=drive ID + + //First write response header + kbuf[HDIO_DRIVE_CMD_RET_STATUS] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_ERROR] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_SEC_CNT] = ATA_CMD_ID_ATA_SECTORS; + + did->config = 0x0000; //15th bit = ATA device, rest is reserved/obsolete + strscpy(disk_serial, disk_name, DISK_NAME_LEN > 20 ? 20 : DISK_NAME_LEN); + set_ata_string(did->serial_no, disk_serial, 20); + set_ata_string(did->fw_rev, "1.13.2", 8); + set_ata_string(did->model, "Virtual HDD", 40); + did->reserved50 = (1 << 14); //"shall be set to one" + did->major_rev_num = 0xffff; + did->minor_rev_num = 0xffff; + did->command_set_1 = (1 << 3 | 1 << 0); //PM, SMART supported + did->command_set_2 = (1 << 14); //"shall be set to one" + did->cfsse = (1 << 14 | 1 << 1 | 1 << 0); //14: "shall be set to one" ; smart self-test supported ; smart error-log + did->cfs_enable_1 = (1 << 3 | 1 << 0); //PM, SMART + did->cfs_enable_2 = (1 << 14); //"shall be set to one" + did->csf_default = (1 << 14 | 1 << 1 | 1 << 0); //"shall be one" ; SMART self-test, SMART error-test + did->hw_config = (1 << 14 | 1 << 0); //both "shall be one" + did->lba_capacity = 0xffffffff; //maybe we can get away with not reading capacity? + + ata_calc_integrity_word((void *)did); + + if (unlikely(copy_to_user(buff_ptr, kbuf, HDIO_DRIVE_CMD_HDR_OFFSET + sizeof(struct rp_hd_driveid)) != 0)) { + pr_loc_err("Failed to copy fake ATA IDENTIFY packet to user ptr=%p", (void *)buff_ptr); + kfree(kbuf); + return -EFAULT; + } + + kfree(kbuf); + return 0; +} + +/** + * Handles on-the-fly modification of data related to ATA IDENTIFY DEVICE command + * + * See "8.16 IDENTIFY DEVICE" section in the ATA/ATAPI-6 manual. + * + * @param org_ioctl_exec_result exit code of the original ioctl() call which reached the drive (done by + * handle_hdio_drive_cmd_ioctl()). This command shouldn't normally fail for any drive. + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_CMD_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be read and possibly altered + * + * @return definitive exit code for the ioctl(); in practice 0 when succedded [regardless of the modifications made] or + * the same error code as org_ioctl_exec_result passed + */ +static int handle_ata_cmd_identify(int org_ioctl_exec_result, const u8 *req_header, void __user *buff_ptr, const char* const disk_name) +{ + //ATA IDENTIFY should not fail - it may mean a problem with a disk or the "disk" is a adapter (e.g. IDE>SATA) with + // no disk connected, or if executed against a USB flash drive... or it's an VirtIO SCSI disk read as ATA + if (unlikely(org_ioctl_exec_result != 0)) { + pr_loc_dbg("sd_ioctl(HDIO_DRIVE_CMD ; ATA_CMD_ID_ATA) failed with error=%d, attempting to emulate something", + org_ioctl_exec_result); + return populate_ata_id(req_header, buff_ptr, disk_name); + } + + //sanity check if requested ATA IDENTIFY sector count is really what we're planning to copy + if (unlikely(req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]) != ATA_CMD_ID_ATA_SECTORS) { + pr_loc_err("Expected %d bytes (%d sectors) DATA for ATA IDENTIFY DEVICE, got %d", + ATA_CMD_ID_ATA_SECTORS, ata_ioctl_buf_size(ATA_CMD_ID_ATA_SECTORS), + req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]); + return -EIO; + } + + //if the identity succeeded we need to check if SMART is supported & enabled. For that we need to clone + // normally user buffer from ioctl (reading it directly is risky) + unsigned char *kbuf = get_ioctl_buffer_kcopy(ATA_CMD_ID_ATA_SECTORS, buff_ptr); + if (unlikely(IS_ERR(kbuf))) + return PTR_ERR(kbuf); //it will already log error in kcopy + + u16 *ata_identity = (u16 *)(kbuf + HDIO_DRIVE_CMD_HDR_OFFSET); + if (ata_is_smart_supported(ata_identity) && ata_is_smart_enabled(ata_identity)) { + pr_loc_dbg("ATA_CMD_ID_ATA confirmed SMART support - noop"); + put_ioctl_buffer(kbuf); //we no longer need the buffer as we're not touching it, we've only read it + return 0; //SMART supported, pass identity as-is + } + + //if SMART is not supported we modify the response, retaining the original response header but changing + // SMART flags & recalculating checksum + pr_loc_dbg("ATA_CMD_ID_ATA confirmed *no* SMART support - pretending it's there"); + ata_set_smart_supported(ata_identity); + ata_set_smart_enabled(ata_identity); + ata_calc_integrity_word(ata_identity); + + if (unlikely(copy_to_user(buff_ptr, kbuf, ata_ioctl_buf_size(ATA_CMD_ID_ATA_SECTORS)) != 0)) { + pr_loc_err("Failed to copy ATA IDENTIFY packet to user ptr=%p", (void *)buff_ptr); + put_ioctl_buffer(kbuf); + return -EFAULT; + } + + put_ioctl_buffer(kbuf); + return 0; +} + +/** + * Populates user ioctl() buffer with fake SMART snapshot values + * + * This function is responsible for the generation of data which you see in a usual tabular format as a result of + * "smartctl -A" command. The data is formated from the "fake_smart" constant array present on the top of this file. + * + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_CMD_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be overwritten with data + * + * @return 0 on success, -EIO on unexpected call, -ENOMEM when memory reservation fails, or -EFAULT when data fails to + * copy to user buffer + */ +static int populate_ata_smart_values(const u8 *req_header, void __user *buff_ptr) +{ + pr_loc_dbg("Generating fake SMART values"); + + //sanity check if requested SMART READ VALUES sector count is really what we're planning to copy + if (unlikely(req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]) != ATA_SMART_READ_VALUES_SECTORS) { + pr_loc_err("Expected %d bytes (%d sectors) DATA for ATA SMART READ VALUES, got %d", + ATA_SMART_READ_VALUES_SECTORS, ata_ioctl_buf_size(ATA_SMART_READ_VALUES_SECTORS), + req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]); + return -EIO; + } + + int i, j; + unsigned char *kbuf; + kzalloc_or_exit_int(kbuf, ata_ioctl_buf_size(ATA_SMART_READ_VALUES_SECTORS)); + u8 *smart_values = (u8 *)(kbuf + HDIO_DRIVE_CMD_HDR_OFFSET); + + //First write response header + kbuf[HDIO_DRIVE_CMD_RET_STATUS] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_ERROR] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_SEC_CNT] = ATA_SMART_READ_VALUES_SECTORS; + + //See "Vendor-Specific Data Bytes 0–361" and "Table 5: SMART Attribute Entry Format" in micron.com + // document for specification of these numbers and calculations + //For full structure see "Table 59 − Device SMART data structure" in ATA/ATAPI-6 PDF + smart_values[0] = SMART_SNAP_VERSION; + + //copy ALL attribute bytes as we were asked for everything (including thresholds) + for (i = 0; i < ARRAY_SIZE(fake_smart); i++) { + for (j = 0; j < 11; j++) { + smart_values[2 + (ATA_SMART_RECORD_LEN * i) + j] = fake_smart[i][j]; + } + } + + //specify that we never ran any SMART tests and we're not running any + smart_values[362] = 0x82; //Sec. 8.55.5.8.1, Table 60 in ATA/ATAPI-6 PDF (self test ran on boot & succeeded) + smart_values[363] = 0x00; //Sec. 8.55.5.8.2, Table 61 in ATA/ATAPI-6 PDF + smart_values[364] = 0x45; //LSB of "Total time to complete Offline data collection" (seconds) + smart_values[365] = 0x00; //MSB of "Total time to complete Offline data collection" (seconds) + smart_values[367] = (1 << 3 | 1 << 4); //bitfield, see sec. 8.55.5.8.4 in ATA/ATAPI-6 PDF + smart_values[368] = (1 << 0 | 1 << 1); //bitfield, see sec. 8.55.5.8.5 in ATA/ATAPI-6 PDF + smart_values[369] = 0x01; //vendor-specific, rel. to sec. 8.55.5.8.5 in ATA/ATAPI-6 PDF + smart_values[370] = 0x01; //bitfield, current only 1st bit used for error logging (Table 59) + smart_values[372] = 0x05; //short self-test polling time (minutes), see Table 59 + smart_values[373] = 0x4B; //long self-test polling time (minutes), see Table 59 + + ata_calc_sector_checksum(smart_values); + + if (copy_to_user(buff_ptr, kbuf, ata_ioctl_buf_size(ATA_SMART_READ_VALUES_SECTORS)) != 0) { + pr_loc_err("Failed to copy SMART VALUES packet to user ptr=%p", buff_ptr); + kfree(kbuf); + return -EFAULT; + } + + kfree(kbuf); + return 0; +} + +/** + * Populates user ioctl() buffer with a subset of fake SMART snapshot values, containing only thresholds + * + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_CMD_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be overwritten with data + * + * @return 0 on success, -EIO on unexpected call, -ENOMEM when memory reservation fails, or -EFAULT when data fails to + * copy to user buffer + */ +static int populate_ata_smart_thresholds(const u8 *req_header, void __user *buff_ptr) +{ + pr_loc_dbg("Generating fake SMART thresholds"); + + //sanity check if requested SMART READ THRESHOLDS sector count is really what we're planning to copy + if (unlikely(req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]) != ATA_SMART_READ_THRESHOLDS_SECTORS) { + pr_loc_err("Expected %d bytes (%d sectors) DATA for ATA SMART READ THRESHOLDS, got %d", + ATA_SMART_READ_THRESHOLDS_SECTORS, ata_ioctl_buf_size(ATA_SMART_READ_THRESHOLDS_SECTORS), + req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]); + return -EIO; + } + + int i; + unsigned char *kbuf; + kzalloc_or_exit_int(kbuf, ata_ioctl_buf_size(ATA_SMART_READ_THRESHOLDS_SECTORS)); + u8 *smart_thresholds = (u8 *)(kbuf + HDIO_DRIVE_CMD_HDR_OFFSET); + + //First write response header + kbuf[HDIO_DRIVE_CMD_RET_STATUS] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_ERROR] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_SEC_CNT] = ATA_SMART_READ_THRESHOLDS_SECTORS; + + //See "Vendor-Specific Data Bytes 0–361" and "Table 5: SMART Attribute Entry Format" in micron.com + // document for specification of these numbers and calculations + //For full structure see "Table 59 − Device SMART data structure" in ATA/ATAPI-6 PDF + smart_thresholds[0] = SMART_SNAP_VERSION; + + //copy a subset of attribute bytes as we were asked for thresholds only + for (i = 0; i < ARRAY_SIZE(fake_smart); i++) { + smart_thresholds[2 + (ATA_SMART_RECORD_LEN * i) + 0] = fake_smart[i][0]; //entry id + smart_thresholds[2 + (ATA_SMART_RECORD_LEN * i) + 1] = fake_smart[i][11]; //threshold value + } + + ata_calc_sector_checksum(smart_thresholds); + + if (copy_to_user(buff_ptr, kbuf, ata_ioctl_buf_size(ATA_SMART_READ_THRESHOLDS_SECTORS)) != 0) { + pr_loc_err("Failed to copy SMART THRESHOLDS packet to user ptr=%p", buff_ptr); + kfree(kbuf); + return -EFAULT; + } + + kfree(kbuf); + return 0; +} + +/** + * Read stored SMART log using WIN_SMART interface + * + * This is a special command from the "WIN_SMART" subset to read the SMART offline log. To understand it see the + * "8.55.6 SMART READ LOG" in ATA/ATAPI-6 specs. It describes it as"Command code B0h with the content of the Features + * register equal to D5h" (B0h = 0xb0 = ATA_CMD_SMART; D5h = 0x05 = WIN_FT_SMART_READ_LOG_SECTOR). + * There are multiple types of logs. This function implements all non-vendor ones. + * + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_CMD_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be overwritten with data + * + * @return 0 on success, -EIO on unexpected call, -ENOMEM when memory reservation fails, or -EFAULT when data fails to + * copy to user buffer + */ +static int populate_win_smart_log(const u8 *req_header, void __user *buff_ptr) +{ + pr_loc_dbg("Generating fake WIN_SMART log=%d entries", req_header[HDIO_DRIVE_CMD_HDR_SEC_NUM]); + + //sanity check if requested SMART READ LOG sector count is really what we're planning to copy + if (unlikely(req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]) != ATA_WIN_SMART_READ_LOG_SECTORS) { + pr_loc_err("Expected %d bytes (%d sectors) DATA for ATA WIN_SMART READ LOG, got %d", + ATA_WIN_SMART_READ_LOG_SECTORS, ata_ioctl_buf_size(ATA_WIN_SMART_READ_LOG_SECTORS), + req_header[HDIO_DRIVE_CMD_HDR_SEC_CNT]); + return -EIO; + } + + unsigned char *kbuf; + kzalloc_or_exit_int(kbuf, ata_ioctl_buf_size(ATA_WIN_SMART_READ_LOG_SECTORS)); + u8 *smart_log = (u8 *)(kbuf + HDIO_DRIVE_CMD_HDR_OFFSET); + + //First write response header + kbuf[HDIO_DRIVE_CMD_RET_STATUS] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_ERROR] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_SEC_CNT] = ATA_WIN_SMART_READ_LOG_SECTORS; + + //See "Table 62 − Log address definition" in ATAPI/6 docs + switch (req_header[HDIO_DRIVE_CMD_HDR_SEC_NUM]) { + case 0x00: //log directory. While the spec says it's optional supporting it means fewer calls to other ones + //we're indicating that we DO support multi-sector logging to avoid further log-read logic complexity. If + // the support is indicated as absent all reads to logs at index 0 must return "command aborted" response + smart_log[0] = WIN_SMART_DIG_LOG_VERSION; + //if every other byte is zero we can ignore the rest of the fields according to Table 63. We also SHOULD NOT + // generate a checksum for log directory (despite all others using checksums...) + + case 0x01: //summary SMART error log (see sect. 8.55.6.8.2 Summary error log sector) + smart_log[0] = WIN_SMART_SUM_LOG_VERSION; + smart_log[1] = 0x00; //no error entries = index is 0 + smart_log[452] = 0x00; //no errors = count byte 1 is zero + smart_log[453] = 0x00; //no errors = count byte 2 is zero + ata_calc_sector_checksum(smart_log); + break; + + case 0x02: //comprehensive SMART error log + smart_log[0] = WIN_SMART_COMP_LOG_VERSION; + smart_log[1] = 0x00; //no error entries = index is 0 + smart_log[452] = 0x00; //no errors = count byte 1 is zero + smart_log[453] = 0x00; //no errors = count byte 2 is zero + ata_calc_sector_checksum(smart_log); + break; + + case 0x06: //SMART self-test log + smart_log[0] = WIN_SMART_TEST_LOG_VERSION; + smart_log[1] = 0x00; //revision (2nd byte, also defined by 8.55.6.8.4.1) + smart_log[508] = 0x00; //no errors + ata_calc_sector_checksum(smart_log); + break; + + default: //other ones are reserved/vendor/etc + pr_loc_err("Unexpected WIN_FT_SMART_READ_LOG_SECTOR with log_addr=%d", + req_header[HDIO_DRIVE_CMD_HDR_SEC_NUM]); + kfree(kbuf); + return -EIO; + } + + if (copy_to_user(buff_ptr, kbuf, ata_ioctl_buf_size(ATA_WIN_SMART_READ_LOG_SECTORS)) != 0) { + pr_loc_err("Failed to copy WIN_SMART LOG packet to user ptr=%p", buff_ptr); + kfree(kbuf); + return -EFAULT; + } + + kfree(kbuf); + return 0; +} + +/** + * Dispatches an drive-internal SMART test using WIN_SMART interface + * + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_CMD_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be overwritten with data + * + * @return 0 on success, -EIO on unexpected call, -ENOMEM when memory reservation fails, or -EFAULT when data fails to + * copy to user buffer + */ +static int populate_win_smart_exec_test(const u8 *req_header, void __user *buff_ptr) +{ + pr_loc_dbg("Generating fake WIN_SMART offline test type=%d", req_header[HDIO_DRIVE_CMD_HDR_SEC_NUM]); + + unsigned char *kbuf; + kzalloc_or_exit_int(kbuf, HDIO_DRIVE_CMD_HDR_OFFSET); + + //First write response header + kbuf[HDIO_DRIVE_CMD_RET_STATUS] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_ERROR] = 0x00; + kbuf[HDIO_DRIVE_CMD_RET_SEC_CNT] = ATA_WIN_SMART_EXEC_TEST; + + //See "Table 58 − SMART EXECUTE OFF-LINE IMMEDIATE LBA Low register values" in ATAPI/6 docs + switch (req_header[HDIO_DRIVE_CMD_HDR_SEC_NUM]) { + case 0x00: //off-line in off-line mode + case 0x01: //short in off-line mode + case 0x02: //long in off-line mode + case 0x7f: //abort previous test + case 0x81: //short in captive mode + case 0x82: //long in captive mode + break; //we only need to populate the response header + + default: //other ones are reserved/vendor/etc + pr_loc_err("Unexpected WIN_FT_SMART_READ_LOG_SECTOR with log_addr=%d", + req_header[HDIO_DRIVE_CMD_HDR_SEC_NUM]); + kfree(kbuf); + return -EIO; + } + + if (copy_to_user(buff_ptr, kbuf, HDIO_DRIVE_CMD_HDR_OFFSET) != 0) { + pr_loc_err("Failed to copy WIN_SMART TEST header to user ptr=%p", buff_ptr); + kfree(kbuf); + return -EFAULT; + } + + kfree(kbuf); + return 0; +} + +/** + * Emulates various SMART data requested via ATA_CMD_SMART method + * + * SMART responses here assume that original ioctl() failed (since otherwise it would be no point to emulate them). If + * you call this function on a drive with functioning SMART it will be ignored and fake smart will be generated for it. + * + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_CMD_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be overwritten with data + * + * @return 0 on success, -EIO on unexpected call, -ENOMEM when memory reservation fails, or -EFAULT when data fails to + * copy to user buffer + */ +static int __always_inline handle_ata_cmd_smart(const u8 *req_header, void __user *buff_ptr) +{ + pr_loc_dbg("Got SMART *command* - looking for feature=0x%x", req_header[HDIO_DRIVE_CMD_HDR_FEATURE]); + + switch (req_header[HDIO_DRIVE_CMD_HDR_FEATURE]) { + case ATA_SMART_READ_VALUES: //read all SMART values snapshot + return populate_ata_smart_values(req_header, buff_ptr); + + case ATA_SMART_READ_THRESHOLDS: //read all SMART thresholds snapshot + return populate_ata_smart_thresholds(req_header, buff_ptr); + + case ATA_SMART_ENABLE: //enable previously disabled SMART support + pr_loc_wrn("Attempted ATA_SMART_ENABLE modification!");\ + return 0; + + case WIN_FT_SMART_READ_LOG_SECTOR: //reads offline-stored drive logs + return populate_win_smart_log(req_header, buff_ptr); + + case WIN_FT_SMART_IMMEDIATE_OFFLINE: //execute a SMART test + return populate_win_smart_exec_test(req_header, buff_ptr); + + default: + pr_loc_dbg("Unknown SMART *command* read w/feature=0x%02x", req_header[HDIO_DRIVE_CMD_HDR_FEATURE]); + return -EIO; + } +} + +/** + * Shims various commands launched via HDIO_DRIVE_CMD interface, routing them to individual shims + * + * This function will shim calls which need to be modified or replaced. All ioctl()s routed here are first executed and + * then routed to individual shims. If a given ioctl() is not a one which we're interested in altering the result of a + * real ioctl() call to the driver will be returned unaltered. + * + * To fully understand this function make sure to read HDIO_DRIVE_CMD description provided by kernel developers at + * https://www.kernel.org/doc/Documentation/ioctl/hdio.txt + */ +static int handle_hdio_drive_cmd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, void __user *buff_ptr) +{ + //Before we execute ioctl we need to save the original header as ioctl will override it (they share buffer) + u8 req_header[HDIO_DRIVE_CMD_HDR_OFFSET]; + if(unlikely(copy_from_user(req_header, buff_ptr, HDIO_DRIVE_CMD_HDR_OFFSET) != 0)) { + pr_loc_err("Expected to copy HDIO_DRIVE_CMD header of %d bytes from %p - it failed", HDIO_DRIVE_CMD_HDR_OFFSET, + buff_ptr); + return -EIO; + } + + int ioctl_out = sd_ioctl_org(bdev, mode, cmd, (unsigned long)buff_ptr); + switch (req_header[HDIO_DRIVE_CMD_HDR_CMD]) { + //this command probes the disk for its overall capabilities; it may have nothing to do with SMART reading but + // we need to modify it to indicate SMART support + case ATA_CMD_ID_ATA: + pr_loc_dbg_ioctl(cmd, "ATA_CMD_ID_ATA", bdev); + return handle_ata_cmd_identify(ioctl_out, req_header, buff_ptr, bdev->bd_disk->disk_name); + + //this command asks directly for the SMART data of the drive and will fail on drives with no real SMART support + case ATA_CMD_SMART: //if the drive supports SMART it will just return the data as-is, no need to proxy + pr_loc_dbg_ioctl(cmd, "ATA_CMD_SMART", bdev); + return (ioctl_out == 0) ? 0 : handle_ata_cmd_smart(req_header, buff_ptr); + + //We're only interested in a subset of commands - rest are simply redirected back + default: + pr_loc_dbg_ioctl_unk(cmd, req_header[HDIO_DRIVE_CMD_HDR_CMD], bdev); + return ioctl_out; + } +} + + +/***************************************** ATAPI/WIN task interface handling ******************************************/ +/** + * Emulates various SMART data requested via WIN_CMD_SMART method + * + * SMART responses here assume that original ioctl() failed (since otherwise it would be no point to emulate them). If + * you call this function on a drive with functioning SMART it will be ignored and fake smart will be generated for it. + * + * @param req_header ioctl() header sent along the request, will be HDIO_DRIVE_TASK_HDR_OFFSET bytes long + * @param buff_ptr userspace pointer to a buffer passed to the ioctl() call; it will be overwritten with data. So far + * all known commands don't use any data buffer but only the response header (which, like req_header, is + * HDIO_DRIVE_TASK_HDR_OFFSET bytes long) + * + * @return 0 on success, -EIO on unexpected call, -ENOMEM when memory reservation fails, or -EFAULT when data fails to + * copy to user buffer + */ +static int __always_inline handle_ata_task_smart(const u8 *req_header, void __user *buff_ptr) +{ + pr_loc_dbg("Got SMART *task* - looking for feature=0x%x", req_header[HDIO_DRIVE_TASK_HDR_FEATURE]); + + switch (req_header[HDIO_DRIVE_TASK_HDR_FEATURE]) { + case WIN_FT_SMART_STATUS: + case WIN_FT_SMART_AUTOSAVE: + case WIN_FT_SMART_AUTO_OFFLINE: { //this must be in brackets, see https://stackoverflow.com/a/18496437 + //Status-checking commands in WIN_SMART officially work in such a way that if the buffer was unchanged it + // means that SMART is OK. However, two static values of 0x4f/0xc2 are used for OK. Here we're taking the + // easy (and probably safer) approach by returning the same values. + //Smartmontools actually verifies if it's the same as req header as well: + // https://github.com/mirror/smartmontools/blob/b63206bc12efb2ae543040b9008f42c037eb1f04/os_linux.cpp#L405 + u8 rsp_header[HDIO_DRIVE_TASK_HDR_OFFSET] = { + [HDIO_DRIVE_TASK_RET_STATUS] = 0x00, + [HDIO_DRIVE_TASK_RET_ERROR] = 0x00, + [HDIO_DRIVE_TASK_RET_SEC_CNT] = req_header[HDIO_DRIVE_TASK_HDR_SEC_CNT], + [HDIO_DRIVE_TASK_RET_SEC_NUM] = req_header[HDIO_DRIVE_TASK_HDR_SEC_NUM], + [HDIO_DRIVE_TASK_RET_LCYL] = req_header[HDIO_DRIVE_TASK_HDR_LCYL], + [HDIO_DRIVE_TASK_RET_HCYL] = req_header[HDIO_DRIVE_TASK_HDR_HCYL], + [HDIO_DRIVE_TASK_RET_SEL] = req_header[HDIO_DRIVE_TASK_HDR_SEL], + }; + + if (copy_to_user(buff_ptr, rsp_header, HDIO_DRIVE_TASK_HDR_OFFSET) != 0) { + pr_loc_err("Failed to copy WIN_SMART feature=0x%02x task result packet to user ptr=%p", + req_header[HDIO_DRIVE_TASK_HDR_FEATURE], buff_ptr); + return -EFAULT; + } + return 0; + } + default: + pr_loc_dbg("Unknown SMART *task* read w/feature=0x%02x", req_header[HDIO_DRIVE_TASK_HDR_FEATURE]); + return -EIO; //We INTENTIONALLY error-out here as there shouldn't be any other ATA SMART *tasks* requested + } +} + +/** + * Shims various commands launched via HDIO_DRIVE_TASK interface, routing them to individual shims + * + * This function will shim calls which need to be modified or replaced. All ioctl()s routed here are first executed and + * then routed to individual shims. If a given ioctl() is not a one which we're interested in altering the result of a + * real ioctl() call to the driver will be returned unaltered. + * This function is used to a very limited subset of commands in the normal circumstances, as see in the smartmontools + * code: https://github.com/mirror/smartmontools/blob/b63206bc12efb2ae543040b9008f42c037eb1f04/os_linux.cpp#L379 + * + * To fully understand this function make sure to read HDIO_DRIVE_TASK description provided by kernel developers at + * https://www.kernel.org/doc/Documentation/ioctl/hdio.txt + */ +static int +handle_hdio_drive_task_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, void __user *buff_ptr) +{ + //Before we execute ioctl we need to save the original header as ioctl will override it (they share buffer) + u8 req_header[HDIO_DRIVE_TASK_HDR_OFFSET]; + if (unlikely(copy_from_user(req_header, buff_ptr, HDIO_DRIVE_TASK_HDR_OFFSET) != 0)) { + pr_loc_err("Expected to copy HDIO_DRIVE_TASK_HDR_OFFSET header of %d bytes from %p - it failed", + HDIO_DRIVE_TASK_HDR_OFFSET, + buff_ptr); + return -EIO; + } + + int ioctl_out = sd_ioctl_org(bdev, mode, cmd, (unsigned long)buff_ptr); + switch (req_header[HDIO_DRIVE_TASK_HDR_CMD]) { + //this command asks directly for the SMART data. From our understanding it's only used for a small subset of + // commands. The normal SMART reads/logs/etc are going through HDIO_DRIVE_CMD instead. The only thing [so far] + // is the SMART self-reported status which goes via HDIO_DRIVE_TASK route + case WIN_CMD_SMART: //if the drive supports SMART it will just return the data as-is, no need to proxy + pr_loc_dbg_ioctl(cmd, "WIN_CMD_SMART", bdev); + return (ioctl_out == 0) ? 0 : handle_ata_task_smart(req_header, buff_ptr); + + //We're only interested in a subset of commands run via task IOCTL - rest are simply redirected back + default: + pr_loc_dbg("sd_ioctl(HDIO_DRIVE_TASK ; cmd=0x%02x) => %d - not a hooked cmd, noop", + req_header[HDIO_DRIVE_TASK_HDR_CMD], ioctl_out); + return ioctl_out; + } +} + +/********************************** ioctl() handling re-routing from driver to shim ***********************************/ +//These are called from each other so we need to predeclare them +int sd_ioctl_canary_install(void); +int sd_ioctl_canary_uninstall(void); + +/** + * Filters/proxies/emulates device IOCTLs as needed for emulating SMART + * + * This shim is installed just before the first IOCTL from the userspace. + */ +static int sd_ioctl_smart_shim(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +{ +#ifdef DBG_SMART_PRINT_ALL_IOCTL + pr_loc_dbg("Handling ioctl(0x%02x) for /dev/%s", cmd, bdev->bd_disk->disk_name); +#endif + + if (unlikely(!sd_ioctl_org)) { + pr_loc_bug("Called %s but no original sd_ioctl() address is known", __FUNCTION__); + return -EIO; + } + + switch (cmd) { + case HDIO_DRIVE_CMD: //"a special drive command" as per hdreg.h + return handle_hdio_drive_cmd_ioctl(bdev, mode, cmd, (void *)arg); + + case HDIO_DRIVE_TASK: //"execute task and special drive command" as per Documentation/ioctl/hdio.txt + return handle_hdio_drive_task_ioctl(bdev, mode, cmd, (void *)arg); + + default: //any other ioctls are proxied as-is +# ifdef DBG_SMART_PRINT_ALL_IOCTL + pr_loc_dbg("sd_ioctl(0x%02x) - not a hooked ioctl, noop", cmd); +# endif + return sd_ioctl_org(bdev, mode, cmd, arg); + } +} + +/** + * Installs a permanent shim into the sd driver ops + * + * Keep in mind this function works only if the sd_fops address has been populated. It's normally done by the canary + * (sd_ioctl_canary()) which is installed by sd_ioctl_canary_install(). + * + * @return 0 on success; -E on error + */ +int sd_ioctl_smart_shim_install(void) +{ + if (unlikely(!sd_fops)) { + pr_loc_bug("Gendisk has no ops (yet?)"); //this could happen if IOCTL somehow arrived before sd_probe_async() + return -EIO; + } + + //This shouldn't happen - it can only be the case if LKM is unloaded without cleanup (or cleanup is broken) + if (unlikely(sd_fops->ioctl == sd_ioctl_smart_shim)) { + pr_loc_bug("sd_ioctl() SMART shim was already installed"); + return 0; + } + + pr_loc_dbg("Rerouting sd_fops->ioctl<%p>=%pF<%p> to %pF<%p>", &sd_fops->ioctl, sd_fops->ioctl, sd_fops->ioctl, + sd_ioctl_smart_shim, sd_ioctl_smart_shim); + sd_ioctl_org = sd_fops->ioctl; + + WITH_MEM_UNLOCKED( + &sd_fops->ioctl, sizeof(void *), + sd_fops->ioctl = sd_ioctl_smart_shim; + ); + + return 0; +} + +/** + * Removes the permanent shim present in sd driver ops (if installed) + * + * If called with shim not installed it will noop by design. + * + * @return 0 on success or noop; -E on error + */ +int sd_ioctl_smart_shim_uninstall(void) +{ + //sd_fops is not saved - nothing to restore + if (unlikely(!sd_fops)) + return 0; + + if (unlikely(!sd_ioctl_org)) { + pr_loc_bug("sd_fops->ioctl is not saved - cannot restore"); + return -EIO; + } + + pr_loc_dbg("Restoring sd_fops->ioctl<%p>=%pF<%p> to %pF<%p>", &sd_fops->ioctl, sd_fops->ioctl, sd_fops->ioctl, + sd_ioctl_org, sd_ioctl_org); + + WITH_MEM_UNLOCKED( + &sd_fops->ioctl, sizeof(void *), + sd_fops->ioctl = sd_ioctl_org; + ); + + sd_ioctl_org = NULL; + sd_fops = NULL; + + return 0; +} + +/** + * Awaits any SCSI ioctl() to override the ioctl handler in sd_fops.ioctl (drivers/scsi/sd.c) + * + * What is essentially does it awaits the first call from the userspace to trigger chain landing in sd_ioctl(), which + * will be any program attempting to do an ioctl() on /dev/sdX. Then it gets gendisk from block_device passed, which in + * turn contains a pointer to the same-for-all sd_fops. Having this pointer lets us replace ->ioctl pointer to finally + * shim the sd_ioctl() pathway. This is done to AVOID using override_symbol:call_overridden_symbol() which isn't really + * that multi-thread safe and actually pretty slow. The last thing we want is slowing down IOCTLs on a storage system. + * Using this strange routine above installs a fast IOCTL filter to e.g. respond to SMARTs. + * + * While this method isn't really clear other ones are even worse. To find sd_fops we need to get at least one + * FULLY INITIALIZED gendisk, which is complicated. During sd_probe() the gendisk is only partially built (i.e. it lacks + * sd_fops...). These other parts are populated in delayed/scheduled sd_probe_async(). So the number of permutations is + * quite large, as we need to consider the following states of the system: + * - no driver loaded + * - driver loaded, no drives yet + * - driver loaded, 1 drive which is not initialized yet + * - driver loaded, >1 drive, one initialized and one not + * - driver loaded, 1 drive which is initialized + * - ...... you see the point? + * + * This whole thing would be much easier if we could get scsi_disk structure, but it's a private one (and heavily + * modified with MY_ABC_HERE). + */ +static int sd_ioctl_canary(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +{ + int out; + spin_lock(&sd_ioctl_canary_lock); + + pr_loc_dbg("%s triggered for first ioctl()", __FUNCTION__); + //if the override of the symbol is no longer present it means that before we've got the lock another canary was + // processing another IOCTL and did what the canary needed to do - we can safely redirect + if (unlikely(!sd_ioctl_canary_ovs)) { + if (unlikely(!sd_fops)) { + pr_loc_bug("Canary is already processed after obtaining lock BUT fops aren't here - the canary is broken"); + return -EIO; //we don't really know the state + } + + pr_loc_dbg("Canary is already processed after obtaining lock - proxying to sd_fops->ioctl directly"); + goto proxy_ioctl; + } + + if (unlikely(!bdev)) { + pr_loc_bug("NULL block_device passed to %s", __FUNCTION__); + return -EIO; + } + + struct gendisk *disk = bdev->bd_disk; + if (unlikely(!disk)) { + pr_loc_bug("block_device w/o gendisk found"); + return -EIO; + } + + sd_fops = (void *)disk->fops; //forcefully remove "const" protection here + out = sd_ioctl_smart_shim_install(); + if (out != 0) { + pr_loc_err("Failed to install proper SMART shim"); + return -EIO; + } + + out = sd_ioctl_canary_uninstall(); //it will log what's wrong + spin_unlock(&sd_ioctl_canary_lock); + if (out != 0) + return -EIO; //we cannot continue as the sd_ioctl() wasn't restored and calling the shim can cause infinite loop + + proxy_ioctl: + pr_loc_dbg("Canary finished - routing to sd_fops->ioctl = %pF<%p>", sd_fops->ioctl, sd_fops->ioctl); + return sd_fops->ioctl(bdev, mode, cmd, arg); +} + +/** + * Installs a temporary sd_ioctl() replacement to capture sd_fops used to install permanent shim + * + * This function is used to replace sd_ioctl() with sd_ioctl_canary(). The purpose of this is to capture sd_fops on a + * first ioctl() from userspace. Then this temporary canary is replaced with a real one (the sd_ioctl_smart_shim()). + * That two-step process is here because we don't have a sane way of obtaining sd_fops (see the function comment for + * sd_ioctl_canary() to learn about the details) and using override_symbol method makes calls to the original sd_ioctl() + * slow and potentially prone to multithreading problems. + * + * @return 0 on success; -E on error + */ +int sd_ioctl_canary_install(void) +{ + if (unlikely(sd_ioctl_canary_ovs)) { + pr_loc_bug("Canary already installed"); + return 0; //technically not a full-blown failure + } + + spin_lock_init(&sd_ioctl_canary_lock); + sd_ioctl_canary_ovs = override_symbol("sd_ioctl", sd_ioctl_canary); + if (IS_ERR(sd_ioctl_canary_ovs)) { + pr_loc_err("Failed to install sd_ioctl() canary"); + int out = PTR_ERR(sd_ioctl_canary_ovs); + sd_ioctl_canary_ovs = NULL; + return out; + } + + return 0; +} + +/** + * Removes the temporary shim installed via sd_ioctl_canary_install() (if installed) + * + * If called with shim not installed it will noop by design. It will noop if the shim was never installed or if it was + * already replaced with the permanent shim. + * + * @return 0 on success or noop; -E on error + */ +int sd_ioctl_canary_uninstall(void) +{ + //this isn't an error failure - it will most likely happen when unregistering this shim after first ioctl + if (unlikely(!sd_ioctl_canary_ovs)) + return 0; + + int out = restore_symbol(sd_ioctl_canary_ovs); + if (out != 0) { + pr_loc_err("Failed to uninstall sd_ioctl() canary"); + return out; + } + + sd_ioctl_canary_ovs = NULL; + return 0; +} + +/****************************************** Standard public API of the shim *******************************************/ +int register_disk_smart_shim(void) +{ + shim_reg_in(); + + int out; + + out = is_scsi_driver_loaded(); + if (IS_SCSI_DRIVER_ERROR(out)) { + pr_loc_err("Failed to determine SCSI driver status - error=%d", out); + return out; + } else if(out == SCSI_DRV_LOADED || kernel_has_symbol("sd_ioctl")) { + //driver is loaded, OR it's not loaded, but it's compiled-in + pr_loc_dbg("SCSI driver exists - installing canary"); + if ((out = sd_ioctl_canary_install()) != 0) + return out; + } else { //driver not loaded and doesn't exist (=not compiled in) + //normally this should call watch_scsi_driver_register() but the current implementation of driver watcher allows + // for just a single watcher per driver (as it doesn't use standard kernel notifiers, sic!). This is however + // unlikely case to ever occur + pr_loc_bug("Cannot register SMART shim - the SCSI driver \"%s\" is not loaded and it doesn't exist", + SCSI_DRV_NAME); + return -ENXIO; + } + + shim_reg_ok(); + return 0; +} + +int unregister_disk_smart_shim(void) +{ + shim_ureg_in(); + + int out; + bool is_error = false; + + out = sd_ioctl_canary_uninstall(); + if (out != 0) { + pr_loc_err("sd_ioctl_canary_uninstall failed - error=%d", out); + is_error = true; + } + + out = sd_ioctl_smart_shim_uninstall(); + if (out != 0) { + pr_loc_err("sd_ioctl_smart_shim_uninstall failed - error=%d", out); + is_error = true; + } + + if (is_error) + return -EIO; + + shim_ureg_ok(); + return 0; +} diff --git a/shim/storage/smart_shim.h b/shim/storage/smart_shim.h new file mode 100644 index 0000000..badbe5f --- /dev/null +++ b/shim/storage/smart_shim.h @@ -0,0 +1,7 @@ +#ifndef REDPILL_SMART_SHIM_H +#define REDPILL_SMART_SHIM_H + +int register_disk_smart_shim(void); +int unregister_disk_smart_shim(void); + +#endif //REDPILL_SMART_SHIM_H diff --git a/shim/uart_fixer.c b/shim/uart_fixer.c new file mode 100644 index 0000000..7f7269a --- /dev/null +++ b/shim/uart_fixer.c @@ -0,0 +1,105 @@ +#define SHIM_NAME "UART fixer" + +#include "uart_fixer.h" +#include "shim_base.h" +#include "../common.h" +#include "../config/runtime_config.h" //STD_COM* +#include "../config/platform_types.h" //hw_config +#include "../internal/call_protected.h" //early_serial_setup() +#include "../internal/override/override_symbol.h" //overriding uart_match_port() +#include //serial8250_unregister_port + +#ifdef DBG_DISABLE_UART_SWAP_FIX +static int noinline uart_swap_hw_output(unsigned int from, unsigned char to) +{ + pr_loc_wrn("UART swapping needed for the platform but forcefully disabled via DBG_DISABLE_UART_SWAP"); + return 0; +} +#elif defined(UART_BUG_SWAPPED) +#include "../internal/uart/uart_swapper.h" +#else +static int noinline uart_swap_hw_output(unsigned int from, unsigned char to) +{ + pr_loc_bug("Called %s from uart_fixer context when UART_BUG_SWAPPED is not set", __FUNCTION__); + return -EINVAL; +} +#endif + +static bool ttyS0_force_initted = false; //Was ttyS0 forcefully initialized by us? +static bool serial_swapped = false; //Whether ttyS0 and ttyS1 were swapped + +/** + * On some platforms (e.g. 918+) the first serial port appears to not be functional as it's not initialized properly. + * + * It is speculated that it has to do with "CONFIG_SYNO_X86_TTY_CONSOLE_OUTPUT=y" but it's not confirmed. If this is not + * fixed by this function setting kernel console output to ttyS0 will result in earlycon working as expected (as it + * doesn't use the normal 8250 driver) with nothing being transmitted as soon as earlycon is switched to the proper + * "console=" port. + */ +static int fix_muted_ttyS0(void) +{ + int out = 0; + struct uart_port port = { + .iobase = STD_COM1_IOBASE, + .uartclk = STD_COMX_BAUD * 16, + .irq = STD_COM1_IRQ, + .flags = STD_COMX_FLAGS + }; + + if ((out = _early_serial_setup(&port)) != 0) { + pr_loc_err("Failed to register ttyS0 to hw port @ %lx", port.iobase); + return out; + } + + pr_loc_dbg("Fixed muted ttyS0 to hw port @ %lx", port.iobase); + ttyS0_force_initted = true; + return out; +} + +/** + * Reverses what fix_muted_ttyS0() did + */ +static int mute_ttyS0(void) +{ + pr_loc_dbg("Re-muting ttyS0"); + serial8250_unregister_port(0); + + return 0; +} + +int register_uart_fixer(const hw_config_uart_fixer *hw) +{ + shim_reg_in(); + + int out = 0; + if ( + (hw->swap_serial && (out = uart_swap_hw_output(1, 0)) != 0) || + (hw->reinit_ttyS0 && (out = fix_muted_ttyS0()) != 0) + ) { + pr_loc_err("Failed to register UART fixer"); + + return out; + } + + serial_swapped = hw->swap_serial; + + shim_reg_ok(); + return out; +} + +int unregister_uart_fixer(void) +{ + shim_ureg_in(); + + int out = 0; + if ( + (serial_swapped && (out = uart_swap_hw_output(0, 1)) != 0) || + (ttyS0_force_initted && (out = mute_ttyS0()) != 0) + ) { + pr_loc_err("Failed to unregister UART fixer"); + return out; + } + + shim_ureg_ok(); + return out; +} \ No newline at end of file diff --git a/shim/uart_fixer.h b/shim/uart_fixer.h new file mode 100644 index 0000000..f8170a3 --- /dev/null +++ b/shim/uart_fixer.h @@ -0,0 +1,8 @@ +#ifndef REDPILL_UART_FIXER_H +#define REDPILL_UART_FIXER_H + +typedef struct hw_config hw_config_uart_fixer; +int register_uart_fixer(const hw_config_uart_fixer *hw); +int unregister_uart_fixer(void); + +#endif //REDPILL_UART_FIXER_H diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..c3d228c --- /dev/null +++ b/tools/README.md @@ -0,0 +1,5 @@ +# Dev Tools + +This directory contains some tools we use during development. They're not +normally used with the module in any way. They're messy, buggy, quick and +dirty but often helpful ;) \ No newline at end of file diff --git a/tools/always_serial.sh b/tools/always_serial.sh new file mode 100644 index 0000000..921ed2e --- /dev/null +++ b/tools/always_serial.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Usage: always_serial.sh +# +# Runs Proxmox serial console. If it fails it tries again... and again... and again until it succeeds. This is very +# useful when stopping and starting VMs with multiple serial ports. Without it every time you stop and start a VM you +# have to go and open all serial consoles again manually. +# To exit this script press Control+C twice (or if console is active Control+O and then Control+C twice). + +trap_cancel() { + echo "Press Control+C once more terminate the process (or wait 2s for it to restart)" + sleep 2 || exit 1 +} +trap trap_cancel SIGINT SIGTERM + +if [[ "$#" -ne 2 ]]; then + echo "Usage: $0 " + exit 2 +fi + +while true; do + clear + echo "Started serial$2 monitor for VM=$1 at" $(date) + qm terminal $1 -iface serial$2 +done \ No newline at end of file diff --git a/tools/always_telnet.sh b/tools/always_telnet.sh new file mode 100644 index 0000000..b1a7487 --- /dev/null +++ b/tools/always_telnet.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Usage: always_telnet.sh +# +# Runs telnet remote console. If it fails it tries again... and again... and again until it succeeds. This is very +# useful when stopping and starting VMs with multiple serial ports on ESXi. Without it every time you stop and start a +# VM you have to go and open all serial consoles again manually. +# To exit this script press Control+C twice (or if console is active Control+O and then Control+C twice). + +trap_cancel() { + echo "Press Control+C once more terminate the process (or wait 2s for it to restart)" + sleep 2 || exit 1 +} +trap trap_cancel SIGINT SIGTERM + +if [[ "$#" -ne 2 ]]; then + echo "Usage: $0 " + exit 2 +fi + +while true; do + clear + echo "Started telnet for $1:$2 at" $(date) + telnet $1 $2 + sleep 0.2 +done \ No newline at end of file diff --git a/tools/inject_rp_ko.sh b/tools/inject_rp_ko.sh new file mode 100644 index 0000000..4d79227 --- /dev/null +++ b/tools/inject_rp_ko.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# Injects RedPill LKM file into a ramdisk inside of an existing image (so you can test new LKM without constant full image +# rebuild & transfer) +# +# Internally we use it something like this with Proxmox pointing to /dev/loop0 as the USB source: +# rm redpill.ko ; wget https://buildsrv/redpill.ko ; \ +# IRP_LEAVE_ATTACHED=1 ./inject_rp_ko.sh rp-3615-v6.img redpill.ko ; losetup ; \ +# qm stop 101 ; sleep 1 ; qm start 101 ; qm terminal 101 -iface serial1 + +self=${0##*/} +img="$(realpath $1 2> /dev/null)" +lkm="$(realpath $2 2> /dev/null)" +if [ $# -ne 2 -o ! -f "$img" -o ! -f "$lkm" ] +then + echo "Usage: $self " + exit 2 +fi + +echo "Detaching $img from all loopdevs" +losetup -j "$img" | grep -E -o '^/dev/loop[0-9]+' | \ +while read -r loopdev; do + umount "${loopdev}p"? 2>/dev/null + losetup -d "$loopdev" + echo "Detached $loopdev" +done + +losetup -j "$img" | grep -E -q '^/dev/loop[0-9]+' +if [ $? -eq 0 ]; then + echo "$img is still attached to some loop devs!" + exit 1 +fi + +set -euo pipefail +LODEV="$(losetup --show -f -P "$img")" + +UNIQ_BASE="$PWD/__inject_rp_$(date '+%s')" +echo "Making directories in $UNIQ_BASE" +TMP_MNT_DIR="$UNIQ_BASE/img-mnt" +TMP_RDU_DIR="$UNIQ_BASE/rd-unpacked" +mkdir -p "$TMP_MNT_DIR" +mkdir -p "$TMP_RDU_DIR" + +echo "Mounting in $TMP_MNT_DIR" +mount "${LODEV}p1" "$TMP_MNT_DIR" + +echo "Unpacking $TMP_MNT_DIR/rd.gz" +cd "$TMP_RDU_DIR" +if file "$TMP_MNT_DIR/rd.gz" | grep -q 'cpio archive'; then # special case: uncompressed rd + IRP_FLAT_RD=1 + cat "$TMP_MNT_DIR/rd.gz" | cpio -idmv +else + IRP_FLAT_RD=0 + xz -dc < "$TMP_MNT_DIR/rd.gz" | cpio -idmv +fi + +echo "Copying $lkm" +cp "$lkm" "$TMP_RDU_DIR/usr/lib/modules/rp.ko" + +echo "Repacking $TMP_MNT_DIR/rd.gz" +if [[ IRP_FLAT_RD -eq 1 ]]; then # special case: uncompressed rd + find . 2>/dev/null | cpio -o -H newc -R root:root > "$TMP_MNT_DIR/rd.gz" +else + find . 2>/dev/null | cpio -o -H newc -R root:root | xz -9 --format=lzma > "$TMP_MNT_DIR/rd.gz" +fi + +echo "Unmounting & detaching (if requested)" +sync +umount "$TMP_MNT_DIR" +if [[ -z "${IRP_LEAVE_ATTACHED}" ]]; then + losetup -d "$LODEV" +fi + +echo "Cleaning up $UNIQ_BASE" +rm -rf "$UNIQ_BASE" \ No newline at end of file diff --git a/tools/make_all.sh b/tools/make_all.sh new file mode 100644 index 0000000..cd98df9 --- /dev/null +++ b/tools/make_all.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Makes all permutations of the LKM and copies them to RedPill Load directory so that we can easily rebuild all images +# Yes, it has all the paths hardcoded - change it to fit your environment. +# When you are executing this script do it from the root of the LKM dir like ./tools/make_all.sh + +LINUX_SRC_ROOT="$PWD/.." +RP_LOAD_ROOT="$HOME/build/redpill-load" + +set -euo pipefail +rm redpill-*.bin redpill-*.ko || true + +# Build for v6 for 3615xs +make LINUX_SRC="$LINUX_SRC_ROOT/linux-3.10.x-bromolow-25426" clean +make LINUX_SRC="$LINUX_SRC_ROOT/linux-3.10.x-bromolow-25426" -j dev-v6 +cp redpill.ko "$RP_LOAD_ROOT/ext/rp-lkm/redpill-linux-v3.10.105.ko" +cp redpill.ko redpill-v6-3615.bin + +# Build for v7 for 3615xs +make LINUX_SRC="$LINUX_SRC_ROOT/bromolow-DSM-7.0-toolkit/build" clean +make LINUX_SRC="$LINUX_SRC_ROOT/bromolow-DSM-7.0-toolkit/build" -j dev-v7 +cp redpill.ko "$RP_LOAD_ROOT/ext/rp-lkm/redpill-linux-v3.10.108.ko" +cp redpill.ko redpill-v7-3615.bin + +# Build for v6 for 918+ +make LINUX_SRC="$LINUX_SRC_ROOT/linux-4.4.x-apollolake-25426" clean +make LINUX_SRC="$LINUX_SRC_ROOT/linux-4.4.x-apollolake-25426" -j dev-v6 +cp redpill.ko "$RP_LOAD_ROOT/ext/rp-lkm/redpill-linux-v4.4.59+.ko" +cp redpill.ko redpill-v6-918.bin + +# Build for v7 for 918+ +make LINUX_SRC="$LINUX_SRC_ROOT/apollolake-DS-7.0-toolkit/build" clean +make LINUX_SRC="$LINUX_SRC_ROOT/apollolake-DS-7.0-toolkit/build" -j dev-v7 +cp redpill.ko "$RP_LOAD_ROOT/ext/rp-lkm/redpill-linux-v4.4.180+.ko" +cp redpill.ko redpill-v7-918.bin + +ln -s redpill-v6-3615.bin redpill-v6-3615.ko +ln -s redpill-v7-3615.bin redpill-v7-3615.ko +ln -s redpill-v6-918.bin redpill-v6-918.ko +ln -s redpill-v7-918.bin redpill-v7-918.ko + +echo "OK" \ No newline at end of file