| /* SPDX-License-Identifier: MIT */ |
| |
| #include "proxy.h" |
| #include "cpufreq.h" |
| #include "dapf.h" |
| #include "dart.h" |
| #include "display.h" |
| #include "exception.h" |
| #include "fb.h" |
| #include "gxf.h" |
| #include "heapblock.h" |
| #include "hv.h" |
| #include "iodev.h" |
| #include "kboot.h" |
| #include "malloc.h" |
| #include "mcc.h" |
| #include "memory.h" |
| #include "nvme.h" |
| #include "pcie.h" |
| #include "pmgr.h" |
| #include "smp.h" |
| #include "string.h" |
| #include "tunables.h" |
| #include "types.h" |
| #include "uart.h" |
| #include "uartproxy.h" |
| #include "usb.h" |
| #include "utils.h" |
| #include "xnuboot.h" |
| |
| #include "minilzlib/minlzma.h" |
| #include "tinf/tinf.h" |
| |
| int proxy_process(ProxyRequest *request, ProxyReply *reply) |
| { |
| enum exc_guard_t guard_save = exc_guard; |
| |
| reply->opcode = request->opcode; |
| reply->status = S_OK; |
| reply->retval = 0; |
| switch (request->opcode) { |
| case P_NOP: |
| break; |
| case P_EXIT: |
| if (request->args[0]) |
| return request->args[0]; |
| return 1; |
| case P_CALL: { |
| generic_func *f = (generic_func *)request->args[0]; |
| reply->retval = f(request->args[1], request->args[2], request->args[3], |
| request->args[4], request->args[5]); |
| break; |
| } |
| case P_GET_BOOTARGS: |
| reply->retval = boot_args_addr; |
| break; |
| case P_GET_BASE: |
| reply->retval = (u64)_base; |
| break; |
| case P_SET_BAUD: { |
| int cnt = request->args[1]; |
| printf("Changing baud rate to %lu...\n", request->args[0]); |
| uart_setbaud(request->args[0]); |
| while (cnt--) { |
| uart_putbyte(request->args[2]); |
| uart_putbyte(request->args[2] >> 8); |
| uart_putbyte(request->args[2] >> 16); |
| uart_putbyte(request->args[2] >> 24); |
| } |
| break; |
| } |
| case P_UDELAY: |
| udelay(request->args[0]); |
| break; |
| case P_SET_EXC_GUARD: |
| exc_count = 0; |
| guard_save = request->args[0]; |
| break; |
| case P_GET_EXC_COUNT: |
| reply->retval = exc_count; |
| exc_count = 0; |
| break; |
| case P_EL0_CALL: |
| reply->retval = el0_call((void *)request->args[0], request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| break; |
| case P_EL1_CALL: |
| reply->retval = el1_call((void *)request->args[0], request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| break; |
| case P_VECTOR: |
| // forcefully restore tps6598x IRQs |
| usb_hpm_restore_irqs(1); |
| iodev_console_flush(); |
| next_stage.entry = (generic_func *)request->args[0]; |
| memcpy(next_stage.args, &request->args[1], 5 * sizeof(u64)); |
| next_stage.restore_logo = true; |
| return 1; |
| case P_GL1_CALL: |
| reply->retval = gl1_call((void *)request->args[0], request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| break; |
| case P_GL2_CALL: |
| reply->retval = gl2_call((void *)request->args[0], request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| break; |
| case P_GET_SIMD_STATE: |
| get_simd_state((void *)request->args[0]); |
| break; |
| case P_PUT_SIMD_STATE: |
| put_simd_state((void *)request->args[0]); |
| break; |
| case P_REBOOT: |
| reboot(); |
| break; |
| case P_SLEEP: |
| cpu_sleep(request->args[0]); |
| break; |
| case P_EL3_CALL: |
| reply->retval = el3_call((void *)request->args[0], request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| |
| case P_WRITE64: |
| exc_guard = GUARD_SKIP; |
| write64(request->args[0], request->args[1]); |
| break; |
| case P_WRITE32: |
| exc_guard = GUARD_SKIP; |
| write32(request->args[0], request->args[1]); |
| break; |
| case P_WRITE16: |
| exc_guard = GUARD_SKIP; |
| write16(request->args[0], request->args[1]); |
| break; |
| case P_WRITE8: |
| exc_guard = GUARD_SKIP; |
| write8(request->args[0], request->args[1]); |
| break; |
| |
| case P_READ64: |
| exc_guard = GUARD_MARK; |
| reply->retval = read64(request->args[0]); |
| break; |
| case P_READ32: |
| exc_guard = GUARD_MARK; |
| reply->retval = read32(request->args[0]); |
| break; |
| case P_READ16: |
| exc_guard = GUARD_MARK; |
| reply->retval = read16(request->args[0]); |
| break; |
| case P_READ8: |
| exc_guard = GUARD_MARK; |
| reply->retval = read8(request->args[0]); |
| break; |
| |
| case P_SET64: |
| exc_guard = GUARD_MARK; |
| reply->retval = set64(request->args[0], request->args[1]); |
| break; |
| case P_SET32: |
| exc_guard = GUARD_MARK; |
| reply->retval = set32(request->args[0], request->args[1]); |
| break; |
| case P_SET16: |
| exc_guard = GUARD_MARK; |
| reply->retval = set16(request->args[0], request->args[1]); |
| break; |
| case P_SET8: |
| exc_guard = GUARD_MARK; |
| reply->retval = set8(request->args[0], request->args[1]); |
| break; |
| |
| case P_CLEAR64: |
| exc_guard = GUARD_MARK; |
| reply->retval = clear64(request->args[0], request->args[1]); |
| break; |
| case P_CLEAR32: |
| exc_guard = GUARD_MARK; |
| reply->retval = clear32(request->args[0], request->args[1]); |
| break; |
| case P_CLEAR16: |
| exc_guard = GUARD_MARK; |
| reply->retval = clear16(request->args[0], request->args[1]); |
| break; |
| case P_CLEAR8: |
| exc_guard = GUARD_MARK; |
| reply->retval = clear8(request->args[0], request->args[1]); |
| break; |
| |
| case P_MASK64: |
| exc_guard = GUARD_MARK; |
| reply->retval = mask64(request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_MASK32: |
| exc_guard = GUARD_MARK; |
| reply->retval = mask32(request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_MASK16: |
| exc_guard = GUARD_MARK; |
| reply->retval = mask16(request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_MASK8: |
| exc_guard = GUARD_MARK; |
| reply->retval = mask8(request->args[0], request->args[1], request->args[2]); |
| break; |
| |
| case P_WRITEREAD64: |
| exc_guard = GUARD_MARK; |
| reply->retval = writeread64(request->args[0], request->args[1]); |
| break; |
| case P_WRITEREAD32: |
| exc_guard = GUARD_MARK; |
| reply->retval = writeread32(request->args[0], request->args[1]); |
| break; |
| case P_WRITEREAD16: |
| exc_guard = GUARD_MARK; |
| reply->retval = writeread16(request->args[0], request->args[1]); |
| break; |
| case P_WRITEREAD8: |
| exc_guard = GUARD_MARK; |
| reply->retval = writeread8(request->args[0], request->args[1]); |
| break; |
| |
| case P_MEMCPY64: |
| exc_guard = GUARD_RETURN; |
| memcpy64((void *)request->args[0], (void *)request->args[1], request->args[2]); |
| break; |
| case P_MEMCPY32: |
| exc_guard = GUARD_RETURN; |
| memcpy32((void *)request->args[0], (void *)request->args[1], request->args[2]); |
| break; |
| case P_MEMCPY16: |
| exc_guard = GUARD_RETURN; |
| memcpy16((void *)request->args[0], (void *)request->args[1], request->args[2]); |
| break; |
| case P_MEMCPY8: |
| exc_guard = GUARD_RETURN; |
| memcpy8((void *)request->args[0], (void *)request->args[1], request->args[2]); |
| break; |
| |
| case P_MEMSET64: |
| exc_guard = GUARD_RETURN; |
| memset64((void *)request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_MEMSET32: |
| exc_guard = GUARD_RETURN; |
| memset32((void *)request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_MEMSET16: |
| exc_guard = GUARD_RETURN; |
| memset16((void *)request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_MEMSET8: |
| exc_guard = GUARD_RETURN; |
| memset8((void *)request->args[0], request->args[1], request->args[2]); |
| break; |
| |
| case P_IC_IALLUIS: |
| ic_ialluis(); |
| break; |
| case P_IC_IALLU: |
| ic_iallu(); |
| break; |
| case P_IC_IVAU: |
| ic_ivau_range((void *)request->args[0], request->args[1]); |
| break; |
| case P_DC_IVAC: |
| dc_ivac_range((void *)request->args[0], request->args[1]); |
| break; |
| case P_DC_ISW: |
| dc_isw((void *)request->args[0]); |
| break; |
| case P_DC_CSW: |
| dc_csw((void *)request->args[0]); |
| break; |
| case P_DC_CISW: |
| dc_cisw((void *)request->args[0]); |
| break; |
| case P_DC_ZVA: |
| dc_zva_range((void *)request->args[0], request->args[1]); |
| break; |
| case P_DC_CVAC: |
| dc_cvac_range((void *)request->args[0], request->args[1]); |
| break; |
| case P_DC_CVAU: |
| dc_cvau_range((void *)request->args[0], request->args[1]); |
| break; |
| case P_DC_CIVAC: |
| dc_civac_range((void *)request->args[0], request->args[1]); |
| break; |
| case P_MMU_SHUTDOWN: |
| mmu_shutdown(); |
| break; |
| case P_MMU_INIT: |
| mmu_init(); |
| break; |
| case P_MMU_DISABLE: |
| reply->retval = mmu_disable(); |
| break; |
| case P_MMU_RESTORE: |
| mmu_restore(request->args[0]); |
| break; |
| case P_MMU_INIT_SECONDARY: |
| mmu_init_secondary(request->args[0]); |
| break; |
| |
| case P_XZDEC: { |
| uint32_t destlen, srclen; |
| destlen = request->args[3]; |
| srclen = request->args[1]; |
| if (XzDecode((void *)request->args[0], &srclen, (void *)request->args[2], &destlen)) |
| reply->retval = destlen; |
| else |
| reply->retval = ~0L; |
| break; |
| } |
| case P_GZDEC: { |
| unsigned int destlen, srclen; |
| destlen = request->args[3]; |
| srclen = request->args[1]; |
| size_t ret = tinf_gzip_uncompress((void *)request->args[2], &destlen, |
| (void *)request->args[0], &srclen); |
| if (ret != TINF_OK) |
| reply->retval = ret; |
| else |
| reply->retval = destlen; |
| break; |
| } |
| |
| case P_SMP_START_SECONDARIES: |
| smp_start_secondaries(); |
| break; |
| case P_SMP_STOP_SECONDARIES: |
| smp_stop_secondaries(request->args[0]); |
| break; |
| case P_SMP_CALL: |
| smp_call4(request->args[0], (void *)request->args[1], request->args[2], |
| request->args[3], request->args[4], request->args[5]); |
| break; |
| case P_SMP_CALL_SYNC: |
| smp_call4(request->args[0], (void *)request->args[1], request->args[2], |
| request->args[3], request->args[4], request->args[5]); |
| reply->retval = smp_wait(request->args[0]); |
| break; |
| case P_SMP_WAIT: |
| reply->retval = smp_wait(request->args[0]); |
| break; |
| case P_SMP_SET_WFE_MODE: |
| smp_set_wfe_mode(request->args[0]); |
| break; |
| case P_SMP_IS_ALIVE: |
| reply->retval = smp_is_alive(request->args[0]); |
| break; |
| case P_SMP_CALL_EL1: |
| smp_call4(request->args[0], el1_call, request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| break; |
| case P_SMP_CALL_EL1_SYNC: |
| smp_call4(request->args[0], el1_call, request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| reply->retval = smp_wait(request->args[0]); |
| break; |
| case P_SMP_CALL_EL0: |
| smp_call4(request->args[0], el0_call, request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| break; |
| case P_SMP_CALL_EL0_SYNC: |
| smp_call4(request->args[0], el0_call, request->args[1], request->args[2], |
| request->args[3], request->args[4]); |
| reply->retval = smp_wait(request->args[0]); |
| break; |
| |
| case P_HEAPBLOCK_ALLOC: |
| reply->retval = (u64)heapblock_alloc(request->args[0]); |
| break; |
| case P_MALLOC: |
| reply->retval = (u64)malloc(request->args[0]); |
| break; |
| case P_MEMALIGN: |
| reply->retval = (u64)memalign(request->args[0], request->args[1]); |
| break; |
| case P_FREE: |
| free((void *)request->args[0]); |
| break; |
| |
| case P_KBOOT_BOOT: |
| if (kboot_boot((void *)request->args[0]) == 0) |
| return 1; |
| break; |
| case P_KBOOT_SET_CHOSEN: |
| reply->retval = kboot_set_chosen((void *)request->args[0], (void *)request->args[1]); |
| break; |
| case P_KBOOT_SET_INITRD: |
| kboot_set_initrd((void *)request->args[0], request->args[1]); |
| break; |
| case P_KBOOT_PREPARE_DT: |
| reply->retval = kboot_prepare_dt((void *)request->args[0]); |
| break; |
| |
| case P_PMGR_POWER_ENABLE: |
| reply->retval = pmgr_power_enable(request->args[0]); |
| break; |
| case P_PMGR_POWER_DISABLE: |
| reply->retval = pmgr_power_enable(request->args[0]); |
| break; |
| case P_PMGR_ADT_POWER_ENABLE: |
| reply->retval = pmgr_adt_power_enable((const char *)request->args[0]); |
| break; |
| case P_PMGR_ADT_POWER_DISABLE: |
| reply->retval = pmgr_adt_power_disable((const char *)request->args[0]); |
| break; |
| case P_PMGR_RESET: |
| reply->retval = pmgr_reset(request->args[0], (const char *)request->args[1]); |
| break; |
| |
| case P_IODEV_SET_USAGE: |
| iodev_set_usage(request->args[0], request->args[1]); |
| break; |
| case P_IODEV_CAN_READ: |
| reply->retval = iodev_can_read(request->args[0]); |
| break; |
| case P_IODEV_CAN_WRITE: |
| reply->retval = iodev_can_write(request->args[0]); |
| break; |
| case P_IODEV_READ: |
| reply->retval = |
| iodev_read(request->args[0], (void *)request->args[1], request->args[2]); |
| break; |
| case P_IODEV_WRITE: |
| reply->retval = |
| iodev_write(request->args[0], (void *)request->args[1], request->args[2]); |
| break; |
| case P_IODEV_WHOAMI: |
| reply->retval = uartproxy_iodev; |
| break; |
| |
| case P_USB_IODEV_VUART_SETUP: |
| usb_iodev_vuart_setup(request->args[0]); |
| break; |
| |
| case P_TUNABLES_APPLY_GLOBAL: |
| reply->retval = tunables_apply_global((const char *)request->args[0], |
| (const char *)request->args[1]); |
| break; |
| case P_TUNABLES_APPLY_LOCAL: |
| reply->retval = tunables_apply_local((const char *)request->args[0], |
| (const char *)request->args[1], request->args[2]); |
| break; |
| case P_TUNABLES_APPLY_LOCAL_ADDR: |
| reply->retval = tunables_apply_local_addr( |
| (const char *)request->args[0], (const char *)request->args[1], request->args[2]); |
| break; |
| |
| case P_DART_INIT: |
| reply->retval = (u64)dart_init(request->args[0], request->args[1], request->args[2], |
| request->args[3]); |
| break; |
| case P_DART_SHUTDOWN: |
| dart_shutdown((dart_dev_t *)request->args[0]); |
| break; |
| case P_DART_MAP: |
| reply->retval = dart_map((dart_dev_t *)request->args[0], request->args[1], |
| (void *)request->args[2], request->args[3]); |
| break; |
| case P_DART_UNMAP: |
| dart_unmap((dart_dev_t *)request->args[0], request->args[1], request->args[2]); |
| break; |
| |
| case P_HV_INIT: |
| hv_init(); |
| break; |
| case P_HV_MAP: |
| hv_map(request->args[0], request->args[1], request->args[2], request->args[3]); |
| break; |
| case P_HV_START: |
| hv_start((void *)request->args[0], &request->args[1]); |
| break; |
| case P_HV_TRANSLATE: |
| reply->retval = hv_translate(request->args[0], request->args[1], request->args[2], |
| (void *)request->args[3]); |
| break; |
| case P_HV_PT_WALK: |
| reply->retval = hv_pt_walk(request->args[0]); |
| break; |
| case P_HV_MAP_VUART: |
| hv_map_vuart(request->args[0], request->args[1], request->args[2]); |
| break; |
| case P_HV_MAP_VIRTIO: |
| hv_map_virtio(request->args[0], (void *)request->args[1]); |
| break; |
| case P_VIRTIO_PUT_BUFFER: |
| virtio_put_buffer(request->args[0], request->args[1], request->args[2], |
| request->args[3]); |
| break; |
| case P_HV_TRACE_IRQ: |
| reply->retval = hv_trace_irq(request->args[0], request->args[1], request->args[2], |
| request->args[3]); |
| break; |
| case P_HV_WDT_START: |
| hv_wdt_start(request->args[0]); |
| break; |
| case P_HV_START_SECONDARY: |
| hv_start_secondary(request->args[0], (void *)request->args[1], &request->args[2]); |
| break; |
| case P_HV_SWITCH_CPU: |
| reply->retval = hv_switch_cpu(request->args[0]); |
| break; |
| case P_HV_SET_TIME_STEALING: |
| hv_set_time_stealing(request->args[0], request->args[1]); |
| break; |
| case P_HV_PIN_CPU: |
| hv_pin_cpu(request->args[0]); |
| break; |
| case P_HV_WRITE_HCR: |
| hv_write_hcr(request->args[0]); |
| break; |
| case P_HV_EXIT_CPU: |
| hv_exit_cpu(request->args[0]); |
| break; |
| case P_HV_ADD_TIME: |
| hv_add_time(request->args[0]); |
| break; |
| |
| case P_FB_INIT: |
| fb_init(request->args[0]); |
| break; |
| case P_FB_SHUTDOWN: |
| fb_shutdown(request->args[0]); |
| break; |
| case P_FB_BLIT: |
| // HACK: Running out of args, stash pix fmt in high bits of stride... |
| fb_blit(request->args[0], request->args[1], request->args[2], request->args[3], |
| (void *)request->args[4], (u32)request->args[5], request->args[5] >> 32); |
| break; |
| case P_FB_UNBLIT: |
| fb_unblit(request->args[0], request->args[1], request->args[2], request->args[3], |
| (void *)request->args[4], request->args[5]); |
| break; |
| case P_FB_FILL: |
| fb_fill(request->args[0], request->args[1], request->args[2], request->args[3], |
| int2rgb(request->args[4])); |
| break; |
| case P_FB_CLEAR: |
| fb_clear(int2rgb(request->args[0])); |
| break; |
| case P_FB_DISPLAY_LOGO: |
| fb_display_logo(); |
| break; |
| case P_FB_RESTORE_LOGO: |
| fb_restore_logo(); |
| break; |
| case P_FB_IMPROVE_LOGO: |
| fb_improve_logo(); |
| break; |
| |
| case P_PCIE_INIT: |
| pcie_init(); |
| break; |
| case P_PCIE_SHUTDOWN: |
| pcie_shutdown(); |
| break; |
| |
| case P_NVME_INIT: |
| reply->retval = nvme_init(); |
| break; |
| case P_NVME_SHUTDOWN: |
| nvme_shutdown(); |
| break; |
| case P_NVME_READ: |
| reply->retval = nvme_read(request->args[0], request->args[1], (void *)request->args[2]); |
| break; |
| case P_NVME_FLUSH: |
| reply->retval = nvme_flush(request->args[0]); |
| break; |
| |
| case P_MCC_GET_CARVEOUTS: |
| reply->retval = (u64)mcc_carveouts; |
| break; |
| |
| case P_DISPLAY_INIT: |
| reply->retval = display_init(); |
| break; |
| case P_DISPLAY_CONFIGURE: |
| reply->retval = display_configure((char *)request->args[0]); |
| break; |
| case P_DISPLAY_SHUTDOWN: |
| display_shutdown(request->args[0]); |
| break; |
| case P_DISPLAY_START_DCP: |
| display_start_dcp(); |
| break; |
| case P_DISPLAY_IS_EXTERNAL: |
| reply->retval = display_is_external; |
| break; |
| |
| case P_DAPF_INIT_ALL: |
| reply->retval = dapf_init_all(); |
| break; |
| case P_DAPF_INIT: |
| reply->retval = dapf_init((const char *)request->args[0], 1); |
| break; |
| |
| case P_CPUFREQ_INIT: |
| reply->retval = cpufreq_init(); |
| break; |
| |
| default: |
| reply->status = S_BADCMD; |
| break; |
| } |
| sysop("dsb sy"); |
| sysop("isb"); |
| exc_guard = guard_save; |
| return 0; |
| } |