From 9d12ac8b2d415b2965da943b53788d6b4c8ed64b Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sat, 16 Jan 2021 23:18:32 +0100 Subject: [PATCH 01/50] hmm --- Makefile | 2 +- src/boot/entry.S | 13 +- src/boot/stage3.c | 1 + src/kernel/entry.c | 11 ++ src/kernel/int.S | 284 +++++++++++++++++++++++++++++++++++++---- src/kernel/lowlevel.c | 43 ++++++- src/kernel/main_task.c | 1 + src/kernel/mm.c | 50 +++++++- src/kernel/pongo.h | 16 ++- 9 files changed, 386 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index d0f02bd4..8a9cadc3 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ EMBEDDED_CC_FLAGS ?= --target=arm64-apple-ios12.0 -Wall -Wunused-label -We # Pongo options PONGO_LDFLAGS ?= -L$(LIB)/lib -lc -lm -Wl,-preload -Wl,-no_uuid -Wl,-e,start -Wl,-order_file,$(SRC)/sym_order.txt -Wl,-image_base,0x100000000 -Wl,-sectalign,__DATA,__common,0x8 -Wl,-segalign,0x4000 -PONGO_CC_FLAGS ?= -DPONGO_VERSION='"$(PONGO_VERSION)"' -DAUTOBOOT -DPONGO_PRIVATE=1 -I$(SRC)/lib -I$(INC) -Iapple-include -I$(INC)/modules/linux/ -I$(SRC)/kernel -I$(SRC)/drivers -I$(SRC)/modules/linux/libfdt $(PONGO_LDFLAGS) -DDER_TAG_SIZE=8 +PONGO_CC_FLAGS ?= -DPONGO_VERSION='"$(PONGO_VERSION)"' -DAUTOBOOT -DPONGO_PRIVATE=1 -I$(SRC)/lib -I$(INC) -Iapple-include -I$(INC)/modules/linux/ -I$(SRC)/kernel -I$(SRC)/drivers -I$(SRC)/modules/linux/libfdt $(PONGO_LDFLAGS) -DDER_TAG_SIZE=8 -mcpu=cortex-a76 # KPF options CHECKRA1N_LDFLAGS ?= -Wl,-kext diff --git a/src/boot/entry.S b/src/boot/entry.S index 99e2caca..389b1458 100644 --- a/src/boot/entry.S +++ b/src/boot/entry.S @@ -1,4 +1,4 @@ -/* + /* * pongoOS - https://checkra.in * * Copyright (C) 2019-2020 checkra1n team @@ -39,6 +39,8 @@ start: b.eq start$l0 add x6, x4, #0x200000 + + copyloop: ldr x3, [x4], #8 str x3, [x5], #8 @@ -81,29 +83,34 @@ start$l0: bl _trampoline_entry b . + + .globl _setup_el1 _setup_el1: stp x29, x30, [sp, #-0x10]! mov x20, x1 mov x21, x2 mrs x16, currentel + cmp x16, #0x8 + b.eq el2_entry cmp x16, #0x4 b.eq el1_entry cmp x16, #0xc + b.ne . el3_entry: - adr x16, _exception_vector_el3 msr vbar_el3, x16 mov x16, #0x430 msr scr_el3, x16 mov x16, #4 msr spsr_el3, x16 - adr x16, el1_entry msr elr_el3, x0 eret + +el2_entry: el1_entry: blr x0 b . diff --git a/src/boot/stage3.c b/src/boot/stage3.c index 4e11fd5d..2a370843 100644 --- a/src/boot/stage3.c +++ b/src/boot/stage3.c @@ -156,6 +156,7 @@ void trampoline_entry(void* boot_image, void* boot_args) extern volatile void smemset(void*, uint8_t, uint64_t); smemset(&__bss_start, 0, ((uint64_t)__bss_end) - ((uint64_t)__bss_start)); + extern void main (void); setup_el1(main, (uint64_t)boot_image, (uint64_t)boot_args); } diff --git a/src/kernel/entry.c b/src/kernel/entry.c index 2f84df8d..a651b9aa 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -270,6 +270,14 @@ extern uint64_t gPongoSlide; void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)(void *boot_args, void *boot_entry_point)) { + + uint64_t hcr_el2 = 0, hcr_el2_orig = 0; + asm volatile("mrs %0, hcr_el2" : "=r"(hcr_el2)); + hcr_el2_orig = hcr_el2; + hcr_el2 |= 1ULL << 27; // TGE + hcr_el2 |= 1ULL << 34; // E2H + asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2)); + gBootArgs = (boot_args*)kernel_args; gEntryPoint = entryp; lowlevel_setup(gBootArgs->physBase & 0xFFFFFFFF, gBootArgs->memSize); @@ -283,6 +291,9 @@ void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)( set_exception_stack_core0(); gFramebuffer = (uint32_t*)gBootArgs->Video.v_baseAddr; lowlevel_cleanup(); + + asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2_orig)); + if(gBootFlag == BOOT_FLAG_RAW) { jump_to_image_extended(((uint64_t)loader_xfer_recv_data) - kCacheableView + 0x800000000, (uint64_t)gBootArgs, (uint64_t)gEntryPoint); diff --git a/src/kernel/int.S b/src/kernel/int.S index 91f90a38..0d188f41 100644 --- a/src/kernel/int.S +++ b/src/kernel/int.S @@ -158,6 +158,139 @@ _exception_vector: b . /* SError/vSError */ +.globl _exception_vector_el2 +_exception_vector_el2: + /* Current EL with SP0, handle within SP0 */ + msr spsel, #1 + sub sp, sp, #0x340 + stp x0,x1,[sp] + msr spsel, #0 + mov x1, sp + msr spsel, #1 + adr x0, Jsync_exc + b exc_handler /* Synchronous */ +.balign 128 + msr spsel, #1 + sub sp, sp, #0x340 + stp x0,x1,[sp] + msr spsel, #0 + mov x1, sp + msr spsel, #1 + adr x0, Jirq_exc + b exc_handler /* IRQ/vIRQ */ +.balign 128 + msr spsel, #1 + sub sp, sp, #0x340 + stp x0,x1,[sp] + msr spsel, #0 + mov x1, sp + msr spsel, #1 + adr x0, Jfiq_exc + b exc_handler /* FIQ/vFIQ */ +.balign 128 + msr spsel, #1 + sub sp, sp, #0x340 + stp x0,x1,[sp] + msr spsel, #0 + mov x1, sp + msr spsel, #1 + adr x0, Jserror_exc + b exc_handler /* SError/vSError */ +.balign 128 + + /* Current EL with SPn */ + sub sp, sp, #0x340 + stp x0,x1,[sp] + adr x0, Jsync_exc + add x1, sp, #0x340 + b exc_handler /* Synchronous */ +.balign 128 + sub sp, sp, #0x340 + stp x0,x1,[sp] + adr x0, Jirq_exc_el1sp1 + add x1, sp, #0x340 + b exc_handler /* IRQ/vIRQ */ +.balign 128 + sub sp, sp, #0x340 + stp x0,x1,[sp] + adr x0, Jfiq_exc_el1sp1 + add x1, sp, #0x340 + b exc_handler /* FIQ/vFIQ */ +.balign 128 + sub sp, sp, #0x340 + stp x0,x1,[sp] + adr x0, Jserror_exc + add x1, sp, #0x340 + b exc_handler /* SError/vSError */ +.balign 128 + + /* Lower EL with Aarch64 */ + msr spsel, #1 + str x0, [sp, #-0x10] + mrs x0, tpidr_el2 + ldr x0, [x0, #0x210] // struct task -> kernel_stack + str x1, [x0, #8] + ldr x1, [sp, #-0x10] + str x1, [x0] + msr spsel, #0 + mov x1, sp + mov sp, x0 + adr x0, Jsync_exc_el0 + b exc_handler /* Synchronous */ +.balign 128 + msr spsel, #1 + str x0, [sp, #-0x10] + mrs x0, tpidr_el2 + ldr x0, [x0, #0x210] // struct task -> kernel_stack + str x1, [x0, #8] + ldr x1, [sp, #-0x10] + str x1, [x0] + msr spsel, #0 + mov x1, sp + mov sp, x0 + adr x0, Jirq_exc + b exc_handler /* IRQ/vIRQ */ +.balign 128 + msr spsel, #1 + str x0, [sp, #-0x10] + mrs x0, tpidr_el2 + ldr x0, [x0, #0x210] // struct task -> kernel_stack + str x1, [x0, #8] + ldr x1, [sp, #-0x10] + str x1, [x0] + msr spsel, #0 + mov x1, sp + mov sp, x0 + adr x0, Jfiq_exc + b exc_handler /* FIQ/vFIQ */ +.balign 128 + msr spsel, #1 + str x0, [sp, #-0x10] + mrs x0, tpidr_el2 + ldr x0, [x0, #0x210] // struct task -> kernel_stack + str x1, [x0, #8] + ldr x1, [sp, #-0x10] + str x1, [x0] + msr spsel, #0 + mov x1, sp + msr spsel, #1 + mov sp, x0 + adr x0, Jserror_exc + b exc_handler /* SError/vSError */ +.balign 128 + + /* Lower EL with Aarch32 */ + +.balign 128 + b . /* Synchronous */ +.balign 128 + b . /* IRQ/vIRQ */ +.balign 128 + b . /* FIQ/vFIQ */ +.balign 128 + b . /* SError/vSError */ + + Jsync_exc: b _sync_exc Jserror_exc: @@ -219,13 +352,18 @@ exc_handler: str d30, [sp,#0x310] str d31, [sp,#0x320] - mrs x29, esr_el1 - stp x30,x29,[sp,#0xf0] - mrs x0, elr_el1 - mrs x1, far_el1 - stp x0,x1,[sp,#0x100] - mrs x1, spsr_el1 - str x1, [sp, #0x110] + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f + msr elr_el1, x0 + msr spsr_el1, x3 + mrs x0, tpidr_el1 + b 1f +2: + msr elr_el2, x0 + msr spsr_el2, x3 + mrs x0, tpidr_el2 +1: // Need to keep x29 valid for panic() add x29, sp, #0xe8 @@ -310,30 +448,67 @@ exc_done: .globl __task_switch_asserted .globl _task_load .globl _task_load_asserted + _task_current: + mrs x0, currentel + cmp x0, #0x8 + b.eq task_current_el2 mrs x0, tpidr_el1 ret + +task_current_el2: + mrs x0, tpidr_el2 + ret + + + __task_set_current: + mrs x16, currentel + cmp x16, #0x8 + b.eq task_set_current_el2 + msr tpidr_el1, x0 ret +task_set_current_el2: + msr tpidr_el2, x0 + ret + + __task_switch: mov x16, x0 - mov x17, x1 + mov x17, x30 bl _disable_interrupts - mrs x2, tpidr_el1 + bl _task_current + mov x2, x0 mov x0, x16 - mov x1, x17 + mov x30, x17 __task_switch_asserted: isb dmb sy + + mrs x2, currentel + cmp x2, #0x8 + b.eq 2f mrs x2, tpidr_el1 + b 1f +2: + mrs x2, tpidr_el2 +1: + stp x2, x3, [x2,#0x10] stp x4, x5, [x2,#0x20] stp x6, x7, [x2,#0x30] stp x8, x9, [x2,#0x40] + mrs x1, currentel + cmp x1, #0x8 + b.eq 2f mrs x1, ttbr1_el1 + b 1f +2: + mrs x1, ttbr1_el2 +1: str x1, [x2, #0x1C8] mrs x1, spsel str w1, [x2, #0x1C0] @@ -360,17 +535,46 @@ __task_switch_asserted: stp d10, d11, [x2,#0x140] stp d12, d13, [x2,#0x160] stp d14, d15, [x2,#0x180] + + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr tpidr_el1, x0 + b 1f +2: + msr tpidr_el2, x0 +1: msr spsel, #1 ldr x8, [x0, #0x1B8] mov sp, x8 msr spsel, #0 + + + mrs x2, currentel + cmp x2, #0x8 + b.eq 2f mrs x2, ttbr1_el1 + b 1f +2: + mrs x2, ttbr1_el2 +1: + + ldr x1, [x0, #0x1C8] cmp x2, x1 isb + + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr ttbr1_el1, x1 + b 1f +2: + msr ttbr1_el2, x1 +1: + + dsb sy ldp x2, x3, [x0,#0x10] ldp x4, x5, [x0,#0x20] @@ -379,7 +583,6 @@ __task_switch_asserted: ldp x10, x11, [x0,#0x50] ldp x12, x13, [x0,#0x60] ldp x14, x15, [x0,#0x70] - ldp x16, x17, [x0,#0x80] ldp x18, x19, [x0,#0x90] ldp x20, x21, [x0,#0xa0] ldp x22, x23, [x0,#0xb0] @@ -393,7 +596,17 @@ __task_switch_asserted: ldp d12, d13, [x0,#0x160] ldp d14, d15, [x0,#0x180] + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr tpidr_el1, x0 + b 1f +2: + msr tpidr_el2, x0 +1: + + ldp x16, x17, [x0,#0x80] + mov sp, x1 ldr x1, [x0, #0x100] add x1, x1, #1 @@ -408,13 +621,21 @@ _task_load: mov x16, x0 mov x17, x1 bl _disable_interrupts - mrs x2, tpidr_el1 + bl _task_current + mov x2, x0 mov x0, x16 mov x1, x17 b _task_load_asserted _task_load_asserted: + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr tpidr_el1, x0 + b 1f +2: + msr tpidr_el2, x0 +1: msr spsel, #1 ldr x8, [x0, #0x1B8] @@ -423,7 +644,15 @@ _task_load_asserted: ldr x1, [x0, #0x1C8] isb + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr ttbr1_el1, x1 + b 1f +2: + msr ttbr1_el2, x1 +1: + dsb sy ldp x2, x3, [x0,#0x10] @@ -433,7 +662,6 @@ _task_load_asserted: ldp x10, x11, [x0,#0x50] ldp x12, x13, [x0,#0x60] ldp x14, x15, [x0,#0x70] - ldp x16, x17, [x0,#0x80] ldp x18, x19, [x0,#0x90] ldp x20, x21, [x0,#0xa0] @@ -448,7 +676,18 @@ _task_load_asserted: ldp d12, d13, [x0,#0x160] ldp d14, d15, [x0,#0x180] + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr tpidr_el1, x0 + b 1f +2: + msr tpidr_el2, x0 +1: + + ldp x16, x17, [x0,#0x80] + + mov sp, x1 ldr x1, [x0, #0x100] add x1, x1, #1 @@ -462,12 +701,21 @@ _task_load_asserted: .globl _task_entry_j _task_entry_j: + mrs x16, currentel + cmp x16, #0x8 + b.eq 2f msr elr_el1, x0 msr spsr_el1, x3 + mrs x0, tpidr_el1 + b 1f +2: + msr elr_el2, x0 + msr spsr_el2, x3 + mrs x0, tpidr_el2 +1: mov sp, x1 mov lr, x2 mov x29, xzr - mrs x0, tpidr_el1 add x0, x0, #0x220 // -> struct task initial_state ldp x2, x3, [x0,#0x10] @@ -504,14 +752,6 @@ _set_timer_ctr: isb ret -.globl _get_spsr_el1 -_get_spsr_el1: - mrs x0, spsr_el1 - ret -.globl _set_spsr_el1 -_set_spsr_el1: - msr spsr_el1, x0 - ret #if 0 .globl _set_l2c_err_sts .globl _get_l2c_err_sts diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index f4b76077..3aa988ea 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -33,6 +33,7 @@ __asm__( ".globl _get_el\n" ".globl _rebase_pc\n" ".globl _set_vbar_el1\n" + ".globl _set_vbar_el2\n" ".globl __enable_interrupts\n" ".globl __disable_interrupts\n" ".globl _get_mpidr\n" @@ -42,6 +43,8 @@ __asm__( ".globl _invalidate_icache\n" ".globl _enable_mmu_el1\n" ".globl _disable_mmu_el1\n" + ".globl _enable_mmu_el2\n" + ".globl _disable_mmu_el2\n" ".globl _get_ticks\n" ".globl _panic_new_fp\n" ".globl _copy_safe_internal\n" @@ -63,7 +66,10 @@ __asm__( " msr vbar_el1, x0\n" " isb\n" " ret\n" - + "_set_vbar_el2:\n" + " msr vbar_el2, x0\n" + " isb\n" + " ret\n" "__enable_interrupts:\n" " msr daifclr,#0xf\n" " isb\n" @@ -114,6 +120,28 @@ __asm__( " isb sy\n" " ret\n" + "_enable_mmu_el2:\n" + " dsb sy\n" + " msr mair_el2, x2\n" + " msr tcr_el2, x1\n" + " msr ttbr0_el2, x0\n" + ".long 0xd51c2023\n" // " msr ttbr1_el2, x3\n" iphonesdk is not a fan of this opcode for some reason? + " isb sy\n" + " tlbi alle2\n" + " isb sy\n" + " ic iallu\n" + " isb sy\n" + " mrs x3, sctlr_el2\n" + " orr x3, x3, #1\n" + " orr x3, x3, #4\n" + " orr x3, x3, #0x800000\n" // enable SPAN if possible + " and x3, x3, #(~2)\n" + " msr sctlr_el2, x3\n" + " ic iallu\n" + " dsb sy\n" + " isb sy\n" + " ret\n" + "_disable_mmu_el1:\n" " dsb sy\n" " isb sy\n" @@ -127,6 +155,19 @@ __asm__( " isb sy\n" " ret\n" + "_disable_mmu_el2:\n" + " dsb sy\n" + " isb sy\n" + " mrs x3, sctlr_el2\n" + " and x3, x3, #(~1)\n" + " and x3, x3, #(~4)\n" + " msr sctlr_el2, x3\n" + " tlbi alle2\n" + " ic iallu\n" + " dsb sy\n" + " isb sy\n" + " ret\n" + "_get_ticks:\n" " isb sy\n" " mrs x0, cntpct_el0\n" diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index dc6d56b7..2490d7c0 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -45,6 +45,7 @@ void shell_main(); uint64_t gBootTimeTicks; void pongo_main_task() { + *(uint64_t*)0x414141 = 0x41414142; gBootTimeTicks = get_ticks(); // Setup GPIO Base diff --git a/src/kernel/mm.c b/src/kernel/mm.c index 7c24286c..ed225ae7 100644 --- a/src/kernel/mm.c +++ b/src/kernel/mm.c @@ -328,10 +328,15 @@ void lowlevel_setup(uint64_t phys_off, uint64_t phys_size) ram_phys_off = kCacheableView + phys_off; ram_phys_size = phys_size; - if (!(get_el() == 1)) panic("pongoOS runs in EL1 only! did you skip pongoMon?"); - - set_vbar_el1((uint64_t)&exception_vector); - enable_mmu_el1((uint64_t)ttbr0, 0x13A402A00 | (tg0 << 14) | (tg1 << 30) | (t1sz << 16) | t0sz, 0x04ff00, (uint64_t)ttbr1); + if (get_el() == 2) { + set_vbar_el2((uint64_t)&exception_vector_el2); + enable_mmu_el2((uint64_t)ttbr0, 0x13A402A00 | (tg0 << 14) | (tg1 << 30) | (t1sz << 16) | t0sz, 0x04ff00, (uint64_t)ttbr1); + } else if (get_el() == 1) { + set_vbar_el1((uint64_t)&exception_vector); + enable_mmu_el1((uint64_t)ttbr0, 0x13A402A00 | (tg0 << 14) | (tg1 << 30) | (t1sz << 16) | t0sz, 0x04ff00, (uint64_t)ttbr1); + } else { + panic("pongoOS runs in EL1/2 only! did you skip pongoMon?"); + } kernel_vm_space.ttbr0 = (uint64_t)ttbr0; kernel_vm_space.ttbr1 = (uint64_t)ttbr1; @@ -344,7 +349,13 @@ void lowlevel_set_identity(void) void lowlevel_cleanup(void) { cache_clean_and_invalidate((void*)ram_phys_off, ram_phys_size); - disable_mmu_el1(); + if (get_el() == 2) { + disable_mmu_el2(); + } else if (get_el() == 1) { + disable_mmu_el1(); + } else { + panic("pongoOS runs in EL1/2 only! did you skip pongoMon?"); + } } struct vm_space* task_vm_space(struct task* task) { return task->vm_space; @@ -556,21 +567,50 @@ void asid_free(uint64_t asid) { fiprintf(stderr, "freeing asid: %llx\n", asid); #endif asid_table[index >> 3] &= ~(1 << (index&0x7)); + + if (get_el() == 2) { + __asm__ volatile("isb"); + __asm__ volatile("tlbi alle2\n"); + __asm__ volatile("dsb sy"); + return; + } + asm volatile("ISB"); asm volatile("TLBI ASIDE1IS, %0" : : "r"(asid)); asm volatile("DSB SY"); } void vm_flush(struct vm_space* fl) { + if (get_el() == 2) { + __asm__ volatile("isb"); + __asm__ volatile("tlbi alle2\n"); + __asm__ volatile("dsb sy"); + return; + } + asm volatile("ISB"); asm volatile("TLBI ASIDE1IS, %0" : : "r"(fl->asid)); asm volatile("DSB SY"); } void vm_flush_by_addr(struct vm_space* fl, uint64_t va) { + if (get_el() == 2) { + __asm__ volatile("isb"); + __asm__ volatile("tlbi alle2\n"); + __asm__ volatile("dsb sy"); + return; + } + asm volatile("ISB"); asm volatile("TLBI VAE1, %0" : : "r"(fl->asid | ((va >> 12) & 0xFFFFFFFFFFF))); asm volatile("DSB SY"); } void vm_flush_by_addr_all_asid(uint64_t va) { + if (get_el() == 2) { + __asm__ volatile("isb"); + __asm__ volatile("tlbi alle2\n"); + __asm__ volatile("dsb sy"); + return; + } + asm volatile("ISB"); asm volatile("TLBI VAAE1, %0" : : "r"((va >> 12) & 0xFFFFFFFFFFF)); asm volatile("DSB SY"); diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index b42a4028..df01f250 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -475,6 +475,8 @@ extern void interrupt_init(); extern void interrupt_teardown(); extern void task_irq_teardown(); extern uint32_t exception_vector[]; +extern uint32_t exception_vector_el2[]; +extern void set_vbar_el2(uint64_t vec); extern void set_vbar_el1(uint64_t vec); extern void rebase_pc(uint64_t vec); extern void rebase_sp(uint64_t vec); @@ -484,6 +486,8 @@ extern uint64_t get_mpidr(void); extern void set_migsts(uint64_t val); extern void enable_mmu_el1(uint64_t ttbr0, uint64_t tcr, uint64_t mair, uint64_t ttbr1); extern void disable_mmu_el1(); +extern void enable_mmu_el2(uint64_t ttbr0, uint64_t tcr, uint64_t mair, uint64_t ttbr1); +extern void disable_mmu_el2(); extern void lowlevel_cleanup(void); extern void lowlevel_setup(uint64_t phys_off, uint64_t phys_size); extern void map_full_ram(uint64_t phys_off, uint64_t phys_size); @@ -494,9 +498,15 @@ static inline _Bool is_16k(void) } static inline void flush_tlb(void) { - __asm__ volatile("isb"); - __asm__ volatile("tlbi vmalle1\n"); - __asm__ volatile("dsb sy"); + if (get_el() == 2) { + __asm__ volatile("isb"); + __asm__ volatile("tlbi alle2\n"); + __asm__ volatile("dsb sy"); + } else { + __asm__ volatile("isb"); + __asm__ volatile("tlbi vmalle1\n"); + __asm__ volatile("dsb sy"); + } } extern void task_real_unlink(struct task* task); #include "hal/hal.h" From 976932357786611168fef8245182b12800a93489 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 00:41:03 +0100 Subject: [PATCH 02/50] m1 support --- machopack.c | 128 +++++++++++++++++++++++++++++++++ src/drivers/aes/aes.c | 5 +- src/drivers/usb/synopsys_otg.c | 12 ++-- src/kernel/entry.c | 5 +- src/kernel/int.S | 77 +++++++++++++------- src/kernel/main_task.c | 5 +- src/kernel/task.c | 6 +- src/shell/main.c | 5 ++ 8 files changed, 207 insertions(+), 36 deletions(-) create mode 100644 machopack.c diff --git a/machopack.c b/machopack.c new file mode 100644 index 00000000..fc1b762d --- /dev/null +++ b/machopack.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "apple-include/mach-o/loader.h" + + +int main(int argc, char** argv) { + if (argc != 3) { + puts("usage: machopack [in (PongoConsolidated.bin)] [out (PongoAppleSilicon)]"); + return -1; + } + + int pongo = open(argv[1], O_RDONLY); + if (pongo < 0) { + puts("in file could not be found!"); + return -2; + } + int out = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0755); + if (out < 0) { + puts("out file could not be nd!"); + return -2; + } + + struct stat s; + if (fstat(pongo, &s) == -1) { + perror("fstat"); + return -3; + } + + struct mach_header_64 mh = {0}; + mh.magic = MH_MAGIC_64; + mh.cputype = CPU_TYPE_ARM64; + mh.cpusubtype = 0x00000002; + mh.filetype = 12; + mh.ncmds = 3; + mh.flags = MH_DYLDLINK; + + uint32_t siz = 0; + + struct { + struct segment_command_64 sh; + struct segment_command_64 sc; + struct section_64 se[1]; + } sc = {0}; +#define BASE_ADDR 0xFFFFFE0007040000 + sc.sh.cmd = LC_SEGMENT_64; + sc.sh.cmdsize = sizeof(struct segment_command_64); + sc.sh.initprot = 1; + sc.sh.maxprot = 1; + sc.sh.nsects = 0; + sc.sh.fileoff = 0; + sc.sh.filesize = 0x4000; + sc.sh.vmsize = 0x4000; + sc.sh.vmaddr = BASE_ADDR; + strcpy(sc.sh.segname, "__HEADER"); + + sc.sc.cmd = LC_SEGMENT_64; + sc.sc.cmdsize = sizeof(struct section_64) + sizeof(struct segment_command_64); + sc.sc.initprot = 7; + sc.sc.maxprot = 7; + sc.sc.nsects = 1; + sc.sc.fileoff = 0x4000; + sc.sc.filesize = s.st_size; + sc.sc.vmsize = s.st_size; + sc.sc.vmsize += 0x3fff; + sc.sc.vmsize &= ~0x3fff; + sc.sc.vmaddr = BASE_ADDR + 0x4000; + strcpy(sc.sc.segname, "__TEXT"); + + sc.se[0].flags = S_ATTR_SOME_INSTRUCTIONS; + sc.se[0].align = 16; + sc.se[0].addr = sc.sc.vmaddr; + sc.se[0].size = s.st_size; + sc.se[0].offset = 0x4000; + strcpy(sc.se[0].sectname, "__pongo"); + strcpy(sc.se[0].segname, "__TEXT"); + + siz += sizeof(sc); + + struct __attribute__ ((packed)) __arm_thread_state64 { + uint64_t x[29]; + uint64_t fp; + uint64_t lr; + uint64_t sp; + uint64_t pc; + uint32_t cpsr; + uint32_t _pad; + }; + + struct thread_command_arm64 { + uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */ + uint32_t cmdsize; /* total size of this command */ + uint32_t flavor; /* flavor of thread state */ + uint32_t count; /* count of uint32_t's in thread state */ + struct __arm_thread_state64 s64; + }; + + struct thread_command_arm64 tc = { 0 }; + + tc.cmd = LC_UNIXTHREAD; + tc.cmdsize = sizeof(tc); + tc.flavor = ARM_THREAD_STATE64; + tc.count = 68; + tc.s64.pc = sc.se[0].addr; + + + siz += sizeof(tc); + + mh.sizeofcmds = siz; + + write(out, &mh, sizeof(mh)); + write(out, &sc, sizeof(sc)); + write(out, &tc, sizeof(tc)); + lseek(out, 0x4000, SEEK_SET); + + char* buf = malloc(s.st_size); + assert(s.st_size == read(pongo, buf, s.st_size)); + write(out, buf, s.st_size); + free(buf); + + return 0; +} diff --git a/src/drivers/aes/aes.c b/src/drivers/aes/aes.c index 371bc375..c38a8193 100644 --- a/src/drivers/aes/aes.c +++ b/src/drivers/aes/aes.c @@ -167,13 +167,16 @@ void aes_init(void) aes_impl = &aes_a9; break; default: - panic("AES: Unsupported SoC"); + puts("AES: Unsupported SoC"); + return; } command_register("aes", "performs AES operations", aes_cmd); } int aes(uint32_t op, const void *src, void *dst, size_t len, const void *iv, const void *key) { + if (!aes_impl) panic("AES: not initialized"); + if((op & ~AES_ALL_MASK) != 0) { return EINVAL; diff --git a/src/drivers/usb/synopsys_otg.c b/src/drivers/usb/synopsys_otg.c index 2b215132..dd8aba1b 100644 --- a/src/drivers/usb/synopsys_otg.c +++ b/src/drivers/usb/synopsys_otg.c @@ -1781,6 +1781,13 @@ void usb_bringup() { } void usb_init() { + struct usb_regs regs; + size_t plsz = sizeof(struct usb_regs); + if (!hal_get_platform_value("usb_regs", ®s, &plsz)) { + puts("synopsys_otg: need usb_regs platform value! not initializing.."); + return; + } + gSynopsysOTGBase = 0; uint32_t sz = 0; uint64_t *reg = dt_get_prop("otgphyctrl", "reg", &sz); @@ -1806,11 +1813,6 @@ void usb_init() { gSynopsysBase = (gSynopsysOTGBase & ~0xfffULL) + 0x00100000; uint32_t otg_irq; - struct usb_regs regs; - size_t plsz = sizeof(struct usb_regs); - if (!hal_get_platform_value("usb_regs", ®s, &plsz)) { - panic("synopsys_otg: need usb_regs platform value!"); - } reg1 = gIOBase + regs.reg1; reg2 = gIOBase + regs.reg2; diff --git a/src/kernel/entry.c b/src/kernel/entry.c index a651b9aa..c9ea067a 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -141,6 +141,7 @@ __attribute__((noinline)) void pongo_entry_cached() else if(strcmp(soc_name, "t8011") == 0) socnum = 0x8011; else if(strcmp(soc_name, "t8012") == 0) socnum = 0x8012; else if(strcmp(soc_name, "t8015") == 0) socnum = 0x8015; + else if(strcmp(soc_name, "t8103") == 0) socnum = 0x8103; else if(strcmp(soc_name, "s8000") == 0) { const char *sgx = dt_get_prop("sgx", "compatible", NULL); @@ -274,8 +275,8 @@ void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)( uint64_t hcr_el2 = 0, hcr_el2_orig = 0; asm volatile("mrs %0, hcr_el2" : "=r"(hcr_el2)); hcr_el2_orig = hcr_el2; - hcr_el2 |= 1ULL << 27; // TGE - hcr_el2 |= 1ULL << 34; // E2H + hcr_el2 |= (1ULL << 27); // VHE + hcr_el2 |= (1ULL << 34); // E2H asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2)); gBootArgs = (boot_args*)kernel_args; diff --git a/src/kernel/int.S b/src/kernel/int.S index 0d188f41..d04708e9 100644 --- a/src/kernel/int.S +++ b/src/kernel/int.S @@ -352,35 +352,64 @@ exc_handler: str d30, [sp,#0x310] str d31, [sp,#0x320] - mrs x16, currentel - cmp x16, #0x8 + mrs x0, currentel + cmp x0, #0x8 b.eq 2f - msr elr_el1, x0 - msr spsr_el1, x3 - mrs x0, tpidr_el1 - b 1f -2: - msr elr_el2, x0 - msr spsr_el2, x3 - mrs x0, tpidr_el2 -1: - // Need to keep x29 valid for panic() - add x29, sp, #0xe8 - mov x0, sp - blr x16 +mrs x29, esr_el1 +stp x30,x29,[sp,#0xf0] +mrs x0, elr_el1 +mrs x1, far_el1 +stp x0,x1,[sp,#0x100] +mrs x1, spsr_el1 +str x1, [sp, #0x110] - cmp x0, #1 - b.ne exc_done - bl _task_yield_preemption +// Need to keep x29 valid for panic() +add x29, sp, #0xe8 +mov x0, sp +blr x16 -exc_done: - ldp x0,x1,[sp,#0x100] - msr elr_el1, x0 - msr far_el1, x1 +cmp x0, #1 +b.ne 6f +bl _task_yield_preemption + +6: +ldp x0,x1,[sp,#0x100] +msr elr_el1, x0 +msr far_el1, x1 + +ldr x1, [sp, #0x110] +msr spsr_el1, x1 - ldr x1, [sp, #0x110] - msr spsr_el1, x1 + + b 1f +2: + +mrs x29, esr_el2 +stp x30,x29,[sp,#0xf0] +mrs x0, elr_el2 +mrs x1, far_el2 +stp x0,x1,[sp,#0x100] +mrs x1, spsr_el2 +str x1, [sp, #0x110] + +// Need to keep x29 valid for panic() +add x29, sp, #0xe8 +mov x0, sp +blr x16 + +cmp x0, #1 +b.ne 6f +bl _task_yield_preemption + +6: +ldp x0,x1,[sp,#0x100] +msr elr_el2, x0 +msr far_el2, x1 + +ldr x1, [sp, #0x110] +msr spsr_el2, x1 +1: mov x0, sp diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 2490d7c0..33c6978e 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -45,7 +45,10 @@ void shell_main(); uint64_t gBootTimeTicks; void pongo_main_task() { - *(uint64_t*)0x414141 = 0x41414142; + if (!socnum) { + iprintf("unknown platform: %s, will likely crash soon...\n", soc_name); + } + gBootTimeTicks = get_ticks(); // Setup GPIO Base diff --git a/src/kernel/task.c b/src/kernel/task.c index 28f158e2..d90fac9b 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -60,10 +60,10 @@ void task_timer_fired() { task_timer_ctr ++; } -struct task* irqvecs[0x200]; +struct task* irqvecs[0x800]; void register_irq_handler(uint16_t irq_v, struct task* irq_handler) { - if (irq_v >= 0x1ff) panic("invalid irq"); + if (irq_v >= 0x7ff) panic("invalid irq"); if (irqvecs[irq_v]) task_release(irqvecs[irq_v]); if (irq_handler) task_reference(irq_handler); irqvecs[irq_v] = irq_handler; @@ -393,7 +393,7 @@ void task_entry() { } if (task->vm_space == &kernel_vm_space) { - task->cpsr = 0x4; // EL1 SP0 + task->cpsr = get_el() << 2; // ELn SP0 void (*entry)() = (void*)task->entry; task_entry_j(entry, task->entry_stack, task_exit, task->cpsr); diff --git a/src/shell/main.c b/src/shell/main.c index 74425ea9..75e7eb83 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -290,4 +290,9 @@ void shell_main() { task_register(&pongo_lock_test2, pongo_lock_test2_entry); #endif // gBootFlag = BOOT_FLAG_HOOK; + + while (1) { + queue_rx_string("ps\n"); + sleep(1); + } } From c6df623be1055a002aac103e34a0178ca0e5300a Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 00:41:14 +0100 Subject: [PATCH 03/50] m1 support --- src/drivers/plat/t8103.c | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/drivers/plat/t8103.c diff --git a/src/drivers/plat/t8103.c b/src/drivers/plat/t8103.c new file mode 100644 index 00000000..5fdeaeca --- /dev/null +++ b/src/drivers/plat/t8103.c @@ -0,0 +1,62 @@ +/* + * pongoOS - https://checkra.in + * + * Copyright (C) 2019-2020 checkra1n team + * + * This file is part of pongoOS. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#import + +static bool t8103_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { + if (device->cpid == 0x8103) { + return true; + } + return false; +} +/* +static struct usb_regs t8103_usb_regs = { + .reg1 = 0x32080270, + .reg2 = 0x32080278, + .reg3 = 0x32080270, + .otg_irq = 324 +}; +*/ +static bool t8103_get_platform_value(const char* name, void* value, size_t* size) { + /*if (strcmp(name, "usb_regs") == 0 && *size == sizeof(struct usb_regs)) { + memcpy(value, &t8103_usb_regs, sizeof(struct usb_regs)); + return true; + }*/ + return false; +} + +static struct hal_platform_driver t8103_plat = { + .name = "Apple M1 (T8103)", + .context = NULL, + .probe = t8103_probe, + .get_platform_value = t8103_get_platform_value +}; + +static void t8103_init(struct driver* driver) { + hal_register_platform_driver(&t8103_plat); +} + +REGISTER_DRIVER(t8103, t8103_init, NULL, DRIVER_FLAGS_PLATFORM); From 09c13eaf50b383e5a7132cbbe66a855057366f5b Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Sun, 17 Jan 2021 00:54:43 +0100 Subject: [PATCH 04/50] Remove IMG4 parser. And temporarily disable pongoConsolidated build. --- Makefile | 2 +- src/lib/img4/img4.c | 856 -------------------------------------------- src/lib/img4/img4.h | 135 ------- 3 files changed, 1 insertion(+), 992 deletions(-) delete mode 100644 src/lib/img4/img4.c delete mode 100644 src/lib/img4/img4.h diff --git a/Makefile b/Makefile index 8a9cadc3..112810f2 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ CHECKRA1N_CC ?= $(EMBEDDED_CC) .PHONY: all always clean distclean -all: $(BUILD)/PongoConsolidated.bin | $(BUILD) +all: $(BUILD)/Pongo.bin | $(BUILD) $(BUILD)/PongoConsolidated.bin: $(BUILD)/Pongo.bin $(BUILD)/checkra1n-kpf-pongo | $(BUILD) bash -c "echo 6175746F626F6F740000200000000000 | xxd -ps -r | cat $(BUILD)/Pongo.bin <(dd if=/dev/zero bs=1 count="$$(((8 - ($$($(STAT) $(BUILD)/Pongo.bin) % 8)) % 8))") /dev/stdin $(BUILD)/checkra1n-kpf-pongo > $@" diff --git a/src/lib/img4/img4.c b/src/lib/img4/img4.c deleted file mode 100644 index a38678b2..00000000 --- a/src/lib/img4/img4.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * pongoOS - https://checkra.in - * - * Copyright (C) 2019-2020 checkra1n team - * - * This file is part of pongoOS. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#import -const DERItemSpec DERImg4ItemSpecs[4] = { - { 0 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "IMG4" - { 1 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, DER_ENC_WRITE_DER|DER_DEC_SAVE_DER }, // SEQUENCE(payload) - { 2 * sizeof(DERItem), ASN1_CONSTRUCTED|ASN1_CONTEXT_SPECIFIC | 0, DER_DEC_OPTIONAL }, // CONS(SEQUENCE(manifest)) - { 3 * sizeof(DERItem), ASN1_CONSTRUCTED|ASN1_CONTEXT_SPECIFIC | 1, DER_DEC_OPTIONAL } // CONS(SEQUENCE(restoreInfo)) -}; - -const DERItemSpec DERImg4PayloadItemSpecs[5] = { - { 0 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "IM4P" - { 1 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "illb" - { 2 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "iBoot-2261.3.33" - { 3 * sizeof(DERItem), ASN1_OCTET_STRING, 0 }, // binary data - { 4 * sizeof(DERItem), ASN1_OCTET_STRING, DER_DEC_OPTIONAL } // keybag -}; - -const DERItemSpec DERImg4ManifestItemSpecs[5] = { - { 0 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "IM4M" - { 1 * sizeof(DERItem), ASN1_INTEGER, 0 }, // 0 - { 2 * sizeof(DERItem), ASN1_CONSTR_SET, DER_DEC_SAVE_DER }, // SET(things) - { 3 * sizeof(DERItem), ASN1_OCTET_STRING, 0 }, // RSA - { 4 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 } // chain -}; - -const DERItemSpec DERImg4RestoreInfoItemSpecs[2] = { - { 0 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "IM4R" - { 1 * sizeof(DERItem), ASN1_CONSTR_SET, 0 } // SET(nonce) -}; - -const DERItemSpec DERSignedCertCrlItemSpecs[3] = { - { 0 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, DER_DEC_SAVE_DER }, - { 1 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 2 * sizeof(DERItem), ASN1_BIT_STRING, 0 } -}; - -const DERItemSpec DERTBSCertItemSpecs[10] = { - { 0 * sizeof(DERItem), ASN1_CONSTRUCTED|ASN1_CONTEXT_SPECIFIC | 0, DER_DEC_OPTIONAL }, - { 1 * sizeof(DERItem), ASN1_INTEGER, 0 }, - { 2 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 3 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 4 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 5 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 6 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 7 * sizeof(DERItem), ASN1_CONTEXT_SPECIFIC | 1, DER_DEC_OPTIONAL }, - { 8 * sizeof(DERItem), ASN1_CONTEXT_SPECIFIC | 2, DER_DEC_OPTIONAL }, - { 9 * sizeof(DERItem), ASN1_CONSTRUCTED|ASN1_CONTEXT_SPECIFIC | 3, DER_DEC_OPTIONAL } -}; - -const DERItemSpec DERAttributeTypeAndValueItemSpecs[2] = { - { 0 * sizeof(DERItem), ASN1_OBJECT_ID, 0 }, - { 1 * sizeof(DERItem), 0, DER_DEC_ASN_ANY | DER_DEC_SAVE_DER } -}; - -const DERItemSpec DERExtensionItemSpecs[3] = { - { 0 * sizeof(DERItem), ASN1_OBJECT_ID, 0 }, - { 1 * sizeof(DERItem), ASN1_BOOLEAN, DER_DEC_OPTIONAL }, - { 2 * sizeof(DERItem), ASN1_OCTET_STRING, 0 } -}; - -const DERItemSpec DERAlgorithmIdItemSpecs[2] = { - { 0 * sizeof(DERItem), ASN1_OBJECT_ID, 0 }, - { 1 * sizeof(DERItem), 0, DER_DEC_OPTIONAL | DER_DEC_ASN_ANY | DER_DEC_SAVE_DER } -}; - -const DERItemSpec DERSubjPubKeyInfoItemSpecs[2] = { - { 0 * sizeof(DERItem), ASN1_CONSTR_SEQUENCE, 0 }, - { 1 * sizeof(DERItem), ASN1_BIT_STRING, 0 } -}; - -const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[2] = { - { 0 * sizeof(DERItem), ASN1_INTEGER, 0x100 }, - { 1 * sizeof(DERItem), ASN1_INTEGER, 0x100 } -}; - -const DERByte _oidAppleImg4ManifestCertSpec[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x63, 0x64, 6, 1, 0xF }; -const DERItem oidAppleImg4ManifestCertSpec = { (DERByte *)_oidAppleImg4ManifestCertSpec, sizeof(_oidAppleImg4ManifestCertSpec) }; - -const DERItem AppleSecureBootCA = { (DERByte *)"\x13)Apple Secure Boot Certification Authority", 0x2B }; - -const DERItemSpec kbagSpecs[] = { - { 0 * sizeof(DERItem), ASN1_INTEGER, 0 }, - { 1 * sizeof(DERItem), ASN1_OCTET_STRING, 0 }, - { 2 * sizeof(DERItem), ASN1_OCTET_STRING, 0 }, -}; - -const DERItemSpec nonceItemSpecs[2] = { - { 0 * sizeof(DERItem), ASN1_IA5_STRING, 0 }, // "BNCN" - { 1 * sizeof(DERItem), ASN1_OCTET_STRING, 0 } // nonce -}; - - -int -DERImg4DecodeFindInSequence(unsigned char *a1, unsigned char *a2, DERTag tag, DERItem *a5) -{ - DERDecodedInfo currDecoded; - DERSequence derSeq; - - derSeq.nextItem = a1; - derSeq.end = a2; - - do { - int rv = DERDecodeSeqNext(&derSeq, &currDecoded); - if (rv) { - return rv; - } - } while (currDecoded.tag != tag); - - *a5 = currDecoded.content; - return 0; -} - -int -DERImg4DecodeContentFindItemWithTag(const DERItem *a1, DERTag tag, DERItem *a4) -{ - int rv; - DERSequence derSeq; - - rv = DERDecodeSeqContentInit(a1, &derSeq); - if (rv) { - return rv; - } - return DERImg4DecodeFindInSequence(derSeq.nextItem, derSeq.end, tag, a4); -} - -int -DERImg4DecodeTagCompare(const DERItem *a1, uint32_t nameTag) -{ - uint32_t var_14; - - if (a1->length < 4) { - return -1; - } - if (a1->length > 4) { - return 1; - } - - if (DERParseInteger(a1, &var_14)) { - return -2; - } - - if (var_14 < nameTag) { - return -1; - } - if (var_14 > nameTag) { - return 1; - } - return 0; -} - -int -DERImg4Decode(const DERItem *a1, DERItem *a2) -{ - int rv; - DERDecodedInfo var_38; - - if (a1 == NULL || a2 == NULL) { - return DR_ParamErr; - } - - rv = DERDecodeItem(a1, &var_38); - if (rv) { - return rv; - } - - if (var_38.tag != ASN1_CONSTR_SEQUENCE) { - return DR_UnexpectedTag; - } - - if (a1->data + a1->length < var_38.content.data + var_38.content.length) { - return DR_BufOverflow; - } - - rv = DERParseSequenceContent(&var_38.content, 4, DERImg4ItemSpecs, a2, 0); - if (rv) { - return rv; - } - - if (DERImg4DecodeTagCompare(a2, 'IMG4')) { - return DR_UnexpectedTag; - } - - return 0; -} - -int -DERImg4DecodePayload(const DERItem *a1, TheImg4Payload *a2) -{ - int rv; - - if (a1 == NULL || a2 == NULL) { - return DR_ParamErr; - } - -#ifdef iOS10 - rv = DERParseSequence(a1, 6, DERImg4PayloadItemSpecs, a2, 0); -#else - rv = DERParseSequence(a1, 5, DERImg4PayloadItemSpecs, a2, 0); -#endif - if (rv) { - return rv; - } - - if (DERImg4DecodeTagCompare(&a2->magic, 'IM4P')) { - return DR_UnexpectedTag; - } - - return 0; -} - -int -DERImg4DecodeManifest(const DERItem *a1, TheImg4Manifest *a2) -{ - int rv; - uint32_t var_14; - - if (a1 == NULL || a2 == NULL) { - return DR_ParamErr; - } - if (a1->data == NULL || a1->length == 0) { - return 0; - } - - rv = DERParseSequence(a1, 5, DERImg4ManifestItemSpecs, a2, 0); - if (rv) { - return rv; - } - - if (DERImg4DecodeTagCompare(&a2->magic, 'IM4M')) { - return DR_UnexpectedTag; - } - - rv = DERParseInteger(&a2->version, &var_14); - if (rv) { - return rv; - } - - if (var_14) { - return DR_UnexpectedTag; - } - return 0; -} - -int -DERImg4DecodeRestoreInfo(const DERItem *a1, TheImg4RestoreInfo *a2) -{ - int rv; - - if (a1 == NULL) { - return 0; - } - if (a2 == NULL) { - return DR_ParamErr; - } - if (a1->data == NULL || a1->length == 0) { - return 0; - } - - rv = DERParseSequence(a1, 2, DERImg4RestoreInfoItemSpecs, a2, 0); - if (rv) { - return rv; - } - - if (DERImg4DecodeTagCompare(&a2->magic, 'IM4R')) { - return DR_UnexpectedTag; - } - - return 0; -} - -int -DERImg4DecodeProperty(const DERItem *a1, DERTag etag, DERMonster *a4) -{ - int rv; - uint32_t var_6C; - DERTag tag; - DERSequence var_60; - DERDecodedInfo var_50; - DERDecodedInfo var_38; - - if (a1 == NULL || a4 == NULL) { - return DR_ParamErr; - } - - rv = DERDecodeSeqInit(a1, &tag, &var_60); - if (rv) { - return rv; - } - - if (tag != ASN1_CONSTR_SEQUENCE) { - return DR_UnexpectedTag; - } - - rv = DERDecodeSeqNext(&var_60, &var_38); - if (rv) { - return rv; - } - - if (var_38.tag != ASN1_IA5_STRING) { - return DR_UnexpectedTag; - } - - rv = DERParseInteger(&var_38.content, &var_6C); - if (rv) { - return rv; - } - - if ((E000000000000000 | var_6C) != etag) { - return DR_UnexpectedTag; - } - - a4[0].item = var_38.content; - - rv = DERDecodeSeqNext(&var_60, &var_50); - if (rv) { - return rv; - } - - a4[1].tag = var_50.tag; - a4[1].item = var_50.content; - - rv = DERDecodeSeqNext(&var_60, &var_50); - if (rv != DR_EndOfSequence) { - return DR_UnexpectedTag; - } - return 0; -} - -int -DERImg4DecodeFindProperty(const DERItem *a1, DERTag etag, DERTag atag, DERMonster *dest) -{ - int rv; - DERItemSpec var_70[2]; - uint32_t var_3C; - DERItem var_38; - - rv = DERImg4DecodeContentFindItemWithTag(a1, etag, &var_38); - if (rv) { - return rv; - } - - var_70[0].offset = 0; - var_70[0].tag = ASN1_IA5_STRING; - var_70[0].options = 0; - var_70[1].offset = sizeof(DERMonster); - var_70[1].tag = atag; - var_70[1].options = 0; - - rv = DERParseSequence(&var_38, 2, var_70, dest, 0); - if (rv) { - return rv; - } - - rv = DERParseInteger(&dest[0].item, &var_3C); - if (rv) { - return rv; - } - - if ((E000000000000000 | var_3C) != etag) { - return DR_UnexpectedTag; - } - - dest[0].tag = etag | E000000000000000; - dest[1].tag = atag; - return 0; -} - -int -Img4DecodeGetPayload(TheImg4 *img4, DERItem *a2) -{ - if (img4 == NULL || a2 == NULL) { - return DR_ParamErr; - } - if (img4->payload.imageData.data == NULL || img4->payload.imageData.length == 0) { - return DR_EndOfSequence; - } - *a2 = img4->payload.imageData; - return 0; -} - -int -Img4DecodeGetPayloadType(TheImg4 *img4, unsigned int *a2) -{ - if (img4 == NULL || a2 == NULL) { - return DR_ParamErr; - } - if (img4->payload.imageData.data == NULL || img4->payload.imageData.length == 0) { - return DR_EndOfSequence; - } - return DERParseInteger(&img4->payload.type, a2); -} - -int -Img4DecodeGetPayloadKeybag(TheImg4 *img4, DERItem *a2) -{ - if (img4 == NULL || a2 == NULL) { - return DR_ParamErr; - } - if (img4->payload.imageData.data == NULL || img4->payload.imageData.length == 0) { - return DR_EndOfSequence; - } - *a2 = img4->payload.keybag; - return 0; -} - -int -Img4DecodeCopyPayloadHash(TheImg4 *img4, void *hash, DERSize length) -{ - //unsigned char var_3C[20]; - - if (img4 == NULL || hash == NULL || length != 20) { - return DR_ParamErr; - } - if (img4->payload.imageData.data == NULL || img4->payload.imageData.length == 0) { - return DR_EndOfSequence; - } - if (!img4->payloadHashed) { - panic("can't actually do this without sha1 impl"); -// sha1_digest(img4->payloadRaw.data, img4->payloadRaw.length, var_3C); - // memmove(hash, &var_3C, length); - return 0; - } - if (length != 20) { - return DR_BufOverflow; - } - memcpy(hash, img4->payload.full_digest, 20); - return 0; -} - -int -Img4DecodeManifestExists(TheImg4 *img4, bool *exists) -{ - if (img4 == NULL || exists == NULL) { - return DR_ParamErr; - } - *exists = (img4->manifestRaw.data != NULL); - return 0; -} - -int -Img4DecodeCopyManifestHash(TheImg4 *img4, void *hash, DERSize length) -{ - //unsigned char var_3C[20]; - - if (img4 == NULL || hash == NULL || length != 20) { - return DR_ParamErr; - } - if (img4->manifestRaw.data == NULL) { - return DR_EndOfSequence; - } - if (!img4->manifestHashed) { - panic("can't actually do this without sha1 impl"); -// sha1_digest(img4->manifestRaw.data, img4->manifestRaw.length, var_3C); -// memmove(hash, var_3C, length); - return 0; - } - if (length != 20) { - return DR_BufOverflow; - } - memcpy(hash, img4->manifest.full_digest, 20); - return 0; -} - -int -Img4DecodeGetRestoreInfoNonce(TheImg4 *img4, DERTag etag, DERTag atag, DERMonster *dest) -{ - if (img4 == NULL || dest == NULL) { - return DR_ParamErr; - } - if (img4->restoreInfo.nonce.data == NULL || img4->restoreInfo.nonce.length == 0) { - return 0; - } - return DERImg4DecodeFindProperty(&img4->restoreInfo.nonce, etag, atag, dest); -} - -int -Img4DecodeGetRestoreInfoData(TheImg4 *img4, DERTag tag, DERByte **a4, DERSize *a5) -{ - int rv; - DERMonster var_40[2]; - - if (img4 == NULL || a4 == NULL || a5 == NULL) { - return DR_ParamErr; - } - rv = Img4DecodeGetRestoreInfoNonce(img4, E000000000000000 | tag, ASN1_OCTET_STRING, var_40); - if (rv) { - return rv; - } - *a4 = var_40[1].item.data; - *a5 = var_40[1].item.length; - return 0; -} - -int -Img4DecodeGetPropertyInteger64(const DERItem *a1, DERTag tag, uint64_t *value) -{ - int rv; - DERItem var_50; - DERMonster var_40[2]; - - var_50.data = a1->data; - var_50.length = a1->length; - - rv = DERImg4DecodeProperty(&var_50, E000000000000000 | tag, var_40); - if (rv) { - return rv; - } - - if (var_40[1].tag != ASN1_INTEGER) { - return DR_UnexpectedTag; - } - - return DERParseInteger64(&var_40[1].item, value); -} - -int -Img4DecodeGetPropertyBoolean(const DERItem *a1, DERTag tag, bool *value) -{ - int rv; - DERItem var_50; - DERMonster var_40[2]; - - var_50.data = a1->data; - var_50.length = a1->length; - - rv = DERImg4DecodeProperty(&var_50, E000000000000000 | tag, var_40); - if (rv) { - return rv; - } - - if (var_40[1].tag != ASN1_BOOLEAN) { - return DR_UnexpectedTag; - } - - return DERParseBoolean(&var_40[1].item, value); -} - -int -Img4DecodeGetPropertyData(const DERItem *a1, DERTag tag, DERByte **a4, DERSize *a5) -{ - int rv; - DERItem var_50; - DERMonster var_40[2]; - - var_50.data = a1->data; - var_50.length = a1->length; - - rv = DERImg4DecodeProperty(&var_50, E000000000000000 | tag, var_40); - if (rv) { - return rv; - } - - if (var_40[1].tag != ASN1_OCTET_STRING) { - return DR_UnexpectedTag; - } - - *a4 = var_40[1].item.data; - *a5 = var_40[1].item.length; - return 0; -} - -int -Img4DecodeEvaluateCertificateProperties(TheImg4 *img4) -{ - int rv; - DERItem var_130; - DERItem var_118; - DERMonster var_108[2]; - DERMonster var_D8[2]; - DERDecodedInfo var_A8; - DERDecodedInfo var_90; - DERTag tag; - DERSequence var_70; - DERSequence var_60; - - if (img4 == NULL) { - return DR_ParamErr; - } - rv = DERDecodeSeqInit(&img4->manifest.img4_blob, &tag, &var_60); - if (rv) { - return rv; - } - - if (tag != ASN1_CONSTR_SET) { - return DR_UnexpectedTag; - } - - while (!DERDecodeSeqNext(&var_60, &var_90)) { - if (var_90.tag != (E000000000000000 | 'OBJP')) { - if (var_90.tag != (E000000000000000 | 'MANP')) { - return DR_UnexpectedTag; - } - var_130 = img4->manp; - } else { - var_130 = img4->objp; - } - - rv = DERImg4DecodeProperty(&var_90.content, var_90.tag, var_D8); - if (rv) { - return rv; - } - - if (var_D8[1].tag != ASN1_CONSTR_SET) { - return DR_UnexpectedTag; - } - - rv = DERDecodeSeqContentInit(&var_D8[1].item, &var_70); - if (rv) { - return rv; - } - - while (!DERDecodeSeqNext(&var_70, &var_A8)) { - rv = DERImg4DecodeProperty(&var_A8.content, var_A8.tag, var_108); - if (rv) { - return rv; - } - - rv = DERImg4DecodeContentFindItemWithTag(&var_130, var_A8.tag, &var_118); - if ((var_108[1].tag & (ASN1_CLASS_MASK | ASN1_METHOD_MASK)) > ASN1_CONTEXT_SPECIFIC) { - if (var_108[1].tag != (ASN1_CONSTRUCTED|ASN1_CONTEXT_SPECIFIC)) { - if (var_108[1].tag != (ASN1_CONSTRUCTED|ASN1_CONTEXT_SPECIFIC | 1)) { - return DR_UnexpectedTag; - } - if (rv == DR_EndOfSequence) { - rv = 0; - } - } - if (rv) { - return rv; - } - } else { - if (var_108[1].tag != ASN1_OCTET_STRING && var_108[1].tag != ASN1_INTEGER && var_108[1].tag != ASN1_BOOLEAN) { - return DR_UnexpectedTag; - } - if (rv) { - return rv; - } - if (!IS_EQUAL(var_A8.content, var_118)) { - return -1; - } - } - } - } - return 0; -} - -int -Img4DecodeEvaluateDictionaryProperties(const DERItem *a1, DictType what, int (*property_cb)(DERTag, DERItem *, DictType, void *), void *ctx) -{ - int rv; - DERMonster var_98[2]; - DERItem var_68; - DERSequence var_58; - DERDecodedInfo var_48; - - if (!property_cb) { - return DR_ParamErr; - } - - rv = DERDecodeSeqContentInit(a1, &var_58); - if (rv) { - return rv; - } - - while (1) { - rv = DERDecodeSeqNext(&var_58, &var_48); - if (rv == DR_EndOfSequence) { - return 0; - } - if (rv) { - return rv; - } - rv = DERImg4DecodeProperty(&var_48.content, var_48.tag, var_98); - if (rv) { - return rv; - } - - if (var_98[1].tag != ASN1_OCTET_STRING && var_98[1].tag != ASN1_INTEGER && var_98[1].tag != ASN1_BOOLEAN) { - return DR_UnexpectedTag; - } - - if ((var_48.tag & E000000000000000) == 0) { - return DR_UnexpectedTag; - } - - var_68.data = var_48.content.data; - var_68.length = var_48.content.length; - rv = property_cb(var_48.tag, &var_68, what, ctx); - if (rv) { - return rv; - } - } -} - -int -Img4DecodeInit(DERByte *data, DERSize length, TheImg4 *img4) -{ - int rv; - DERItem var_70[4]; - DERItem var_30; - - if (data == NULL || img4 == NULL) { - return DR_ParamErr; - } - - var_30.data = data; - var_30.length = length; - - memset(var_70, 0, sizeof(var_70)); - memset(img4, 0, sizeof(TheImg4)); - - rv = DERImg4Decode(&var_30, var_70); - if (rv) { - return rv; - } - rv = DERImg4DecodePayload(&var_70[1], &img4->payload); - if (rv) { - return rv; - } - rv = DERImg4DecodeManifest(&var_70[2], &img4->manifest); - if (rv) { - return rv; - } - rv = DERImg4DecodeRestoreInfo(&var_70[3], &img4->restoreInfo); - if (rv) { - return rv; - } - - img4->payloadRaw = var_70[1]; - img4->manifestRaw = var_70[2]; - return 0; -} - -static DERReturn -aDEREncodeItem(DERItem *item, DERTag tag, DERSize length, DERByte *src, bool freeOld) -{ - DERReturn rv; - DERByte *old = freeOld ? src : NULL; - DERSize inOutLen = DER_MAX_ENCODED_SIZE(length); - DERByte *der = malloc(inOutLen); - if (!der) { - if (old) - free(old); - return -1; - } - - rv = DEREncodeItem(tag, length, src, der, &inOutLen); - if (old) - free(old); - if (rv) { - if (der) - free(der); - return rv; - } - - item->data = der; - item->length = inOutLen; - return 0; -} - -static DERReturn -aDEREncodeSequence(DERItem *where, DERTag topTag, const void *src, DERShort numItems, const DERItemSpec *itemSpecs, int freeElt) -{ - int i; - DERReturn rv; - DERByte *der; - DERSize inOutLen; - DERByte *old = NULL; - - inOutLen = 1000; // XXX blah - for (i = numItems - 1; i >= 0; i--) { - const DERItem *item = (DERItem *)((char *)src + itemSpecs[i].offset); - inOutLen += DER_MAX_ENCODED_SIZE(item->length); - if (i == freeElt) { - old = item->data; - } - } - der = malloc(inOutLen); - if (!der) { - if (old) - free(old); - return -1; - } - - rv = DEREncodeSequence(topTag, src, numItems, itemSpecs, der, &inOutLen); - if (old) - free(old); - if (rv) { - if (der) - free(der); - return rv; - } - - where->data = der; - where->length = inOutLen; - return 0; -} -DERReturn Img4Encode(DERItem* out, DERItem* items, int itemLen) { - return aDEREncodeSequence(out, ASN1_CONSTR_SEQUENCE, items, itemLen, DERImg4ItemSpecs, -1); -} -int -makeRestoreInfo(DERItem *where, void* nonceBytes, size_t nonceLength) -{ - int rv; - char IM4R[] = "IM4R"; - char BNCN[] = "BNCN"; - - DERItem item; - DERItem elements[2]; - DERItem restoreInfo[2]; - - elements[0].data = (DERByte *)BNCN; - elements[0].length = sizeof(BNCN) - 1; - elements[1].data = nonceBytes; - elements[1].length = nonceLength; - - rv = aDEREncodeSequence(&item, ASN1_CONSTR_SEQUENCE, elements, 2, nonceItemSpecs, -1); - if (rv) { - return rv; - } - - rv = aDEREncodeItem(restoreInfo + 1, ASN1_CONSTRUCTED | ASN1_PRIVATE | 'BNCN', item.length, item.data, true); - if (rv) { - return rv; - } - - restoreInfo[0].data = (DERByte *)IM4R; - restoreInfo[0].length = sizeof(IM4R) - 1; - - return aDEREncodeSequence(where, ASN1_CONSTR_SEQUENCE, restoreInfo, 2, DERImg4RestoreInfoItemSpecs, 1); -} diff --git a/src/lib/img4/img4.h b/src/lib/img4/img4.h deleted file mode 100644 index b44dc9e4..00000000 --- a/src/lib/img4/img4.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * pongoOS - https://checkra.in - * - * Copyright (C) 2019-2020 checkra1n team - * - * This file is part of pongoOS. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#define RESERVE_DIGEST_SPACE 20 -#define E000000000000000 (ASN1_CONSTRUCTED | ASN1_PRIVATE) - -#define IS_EQUAL(a, b) ((a).length == (b).length && !memcmp((a).data, (b).data, (a).length)) - -#define FOURCC(tag) (unsigned char)((tag) >> 24), (unsigned char)((tag) >> 16), (unsigned char)((tag) >> 8), (unsigned char)(tag) - - -typedef enum { - DictMANP, - DictOBJP -} DictType; - -typedef struct { - DERItem item; - DERTag tag; -} DERMonster; - -typedef struct { - DERItem magic; // "IM4P" - DERItem type; // "illb" - DERItem version; // "iBoot-2261.3.33" - DERItem imageData; - DERItem keybag; -#ifdef iOS10 - DERItem compression; -#endif - DERByte full_digest[RESERVE_DIGEST_SPACE]; -} TheImg4Payload; - -typedef struct { - DERItem magic; // "IM4M" - DERItem version; // 0 - DERItem theset; // MANB + MANP - DERItem sig_blob; // RSA - DERItem chain_blob; // cert chain - DERItem img4_blob; - DERByte full_digest[RESERVE_DIGEST_SPACE]; - DERByte theset_digest[RESERVE_DIGEST_SPACE]; -} TheImg4Manifest; - -typedef struct { - DERItem magic; // "IM4R" - DERItem nonce; -} TheImg4RestoreInfo; - -typedef struct { - bool payloadHashed; - bool manifestHashed; - DERItem payloadRaw; - DERItem manifestRaw; - DERItem manb; - DERItem manp; - DERItem objp; - TheImg4Payload payload; - TheImg4Manifest manifest; - TheImg4RestoreInfo restoreInfo; -} TheImg4; - -typedef struct { - uint64_t CHIP; - uint64_t ECID; - uint64_t SEPO; - uint64_t SDOM; - uint64_t BORD; - unsigned char CPRO; - unsigned char CSEC; - unsigned char field_2A; - unsigned char field_2B; - unsigned char field_2C; - unsigned char field_2D; - unsigned char field_2E; - unsigned char field_2F; - uint64_t field_30; - unsigned char boot_manifest_hash[20]; - unsigned char hashvalid; - unsigned char field_4D; - unsigned char field_4E; - unsigned char field_4F; -} ContextH; - -typedef struct { - unsigned char field_0; - unsigned char field_1; - unsigned char field_2; - unsigned char field_3; - unsigned char field_4; - unsigned char field_5; - unsigned char field_6; - unsigned char field_7; - unsigned char manifest_hash[20]; - bool has_manifest; - unsigned char field_1D; - unsigned char payload_hash[20]; -} ContextU; - -typedef struct { - TheImg4 *img4; - ContextH *hardware; - ContextU *unknown; -} CTX; - -int Img4DecodeGetPayload(TheImg4 *img4, DERItem *a2); -int Img4DecodeGetPayloadType(TheImg4 *img4, unsigned int *a2); -int Img4DecodeGetPayloadKeybag(TheImg4 *img4, DERItem *a2); -int Img4DecodeInit(DERByte *data, DERSize length, TheImg4 *img4); -int makeRestoreInfo(DERItem *where, void* nonceBytes, size_t nonceLength); -DERReturn Img4Encode(DERItem* out, DERItem* items, int itemLen); From 122ad0df4fdde8eb3bf2321397981932d2063734 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 00:59:27 +0100 Subject: [PATCH 05/50] irq --- src/kernel/task.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/kernel/task.c b/src/kernel/task.c index d90fac9b..e393b2ab 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -93,7 +93,7 @@ void task_list(const char* cmd, char* arg) { } cur_task = cur_task->next; } while (cur_task != &sched_task); - for (int i=0; i<0x1ff; i++) { + for (int i=0; i<0x7ff; i++) { if (irqvecs[i]) { ++nirq; } @@ -129,7 +129,7 @@ retry:; } cur_task = cur_task->next; } while (cur_task != &sched_task); - for (int i=0; i<0x1ff; i++) { + for (int i=0; i<0x7ff; i++) { if (irqvecs[i]) { ++ni; } @@ -166,7 +166,7 @@ retry:; cur_task = cur_task->next; } while (cur_task != &sched_task); ni = 0; - for (int i=0; i<0x1ff; i++) { + for (int i=0; i<0x7ff; i++) { if (irqvecs[i]) { strlcpy(irq_copy[ni].name, irqvecs[i]->name, sizeof(irq_copy[ni].name)); irq_copy[ni].runcnt = irqvecs[i]->irq_count; @@ -214,7 +214,7 @@ retry:; free(irq_copy); } void task_irq_teardown() { - for (int i=0; i<0x1ff; i++) { + for (int i=0; i<0x7ff; i++) { if (irqvecs[i]) { mask_interrupt(i); } @@ -246,9 +246,9 @@ __attribute__((noinline)) void task_switch_irq(struct task* new) served_irqs++; } __attribute__((noinline)) void task_irq_dispatch(uint32_t intr) { - struct task* irq_handler = irqvecs[intr & 0x1FF]; + struct task* irq_handler = irqvecs[intr & 0x7FF]; if (irq_handler) { - irq_handler->irq_type = intr & 0x1ff; + irq_handler->irq_type = intr & 0x7FF; task_switch_irq(irq_handler); } else { iprintf("couldn't find irq handler for %x\n", intr); From 3a16e96e499be3a31c88f196558f521870228c52 Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Sun, 17 Jan 2021 01:00:23 +0100 Subject: [PATCH 06/50] Remove img4 parser part II. --- src/kernel/pongo.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index df01f250..2a3f321a 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -46,7 +46,6 @@ #include "libDER/DER_Decode.h" #include "libDER/asn1Types.h" #include "libDER/oids.h" -#include "img4/img4.h" #include "mipi/mipi.h" #include "aes/aes.h" #endif From b4ceaba1c341bfd6ac1514d6b73586d5cae4d7eb Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Sun, 17 Jan 2021 01:14:13 +0100 Subject: [PATCH 07/50] Integration to build system for M1. --- Makefile | 8 +++++++- machopack.c => tools/machopack.c | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) rename machopack.c => tools/machopack.c (97%) diff --git a/Makefile b/Makefile index 112810f2..e9fef28d 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,10 @@ CHECKRA1N_CC ?= $(EMBEDDED_CC) .PHONY: all always clean distclean -all: $(BUILD)/Pongo.bin | $(BUILD) +all: $(BUILD)/Pongo.bin $(BUILD)/pongoOS.AppleSi.macho | $(BUILD) + +$(BUILD)/pongoOS.AppleSi.macho: $(BUILD)/Pongo.bin $(BUILD)/machopack | $(BUILD) + $(BUILD)/machopack $(BUILD)/Pongo.bin $@ $(BUILD)/PongoConsolidated.bin: $(BUILD)/Pongo.bin $(BUILD)/checkra1n-kpf-pongo | $(BUILD) bash -c "echo 6175746F626F6F740000200000000000 | xxd -ps -r | cat $(BUILD)/Pongo.bin <(dd if=/dev/zero bs=1 count="$$(((8 - ($$($(STAT) $(BUILD)/Pongo.bin) % 8)) % 8))") /dev/stdin $(BUILD)/checkra1n-kpf-pongo > $@" @@ -107,6 +110,9 @@ $(BUILD)/checkra1n-kpf-pongo: $(CHECKRA1N_C) $(LIB)/lib/libc.a | $(BUILD) $(BUILD)/vmacho: $(AUX)/vmacho.c | $(BUILD) $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) +$(BUILD)/machopack: $(AUX)/machopack.c | $(BUILD) + $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) + $(BUILD): mkdir -p $@ diff --git a/machopack.c b/tools/machopack.c similarity index 97% rename from machopack.c rename to tools/machopack.c index fc1b762d..2af65d6c 100644 --- a/machopack.c +++ b/tools/machopack.c @@ -7,8 +7,11 @@ #include #include #include -#include "apple-include/mach-o/loader.h" - +#ifdef __APPLE__ +#include +#else +#include "../apple-include/mach-o/loader.h" +#endif int main(int argc, char** argv) { if (argc != 3) { From b1a69f701b91b93f59cbc4a1e53bb602a2213597 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 01:26:27 +0100 Subject: [PATCH 08/50] el1 --- src/kernel/entry.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/kernel/entry.c b/src/kernel/entry.c index c9ea067a..e2c183ae 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -273,11 +273,13 @@ void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)( { uint64_t hcr_el2 = 0, hcr_el2_orig = 0; - asm volatile("mrs %0, hcr_el2" : "=r"(hcr_el2)); - hcr_el2_orig = hcr_el2; - hcr_el2 |= (1ULL << 27); // VHE - hcr_el2 |= (1ULL << 34); // E2H - asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2)); + if (get_el() == 2) { + asm volatile("mrs %0, hcr_el2" : "=r"(hcr_el2)); + hcr_el2_orig = hcr_el2; + hcr_el2 |= (1ULL << 27); // VHE + hcr_el2 |= (1ULL << 34); // E2H + asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2)); + } gBootArgs = (boot_args*)kernel_args; gEntryPoint = entryp; @@ -293,8 +295,10 @@ void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)( gFramebuffer = (uint32_t*)gBootArgs->Video.v_baseAddr; lowlevel_cleanup(); - asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2_orig)); - + if (get_el() == 2) { + asm volatile("msr hcr_el2, %0" : : "r"(hcr_el2_orig)); + } + if(gBootFlag == BOOT_FLAG_RAW) { jump_to_image_extended(((uint64_t)loader_xfer_recv_data) - kCacheableView + 0x800000000, (uint64_t)gBootArgs, (uint64_t)gEntryPoint); From dc49ffba26210b3b99ea7c3a4c7ead614e79094f Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 12:40:52 +0100 Subject: [PATCH 09/50] change some MM stuff to not horribly break on >4GB devices --- src/drivers/plat/t8103.c | 22 +++++++--- src/drivers/usb/synopsys_otg.c | 77 ++++++++++++++++++++++------------ src/drivers/usb/usb.h | 4 ++ src/kernel/main_task.c | 2 +- src/kernel/mm.c | 14 +++++-- src/shell/main.c | 5 +-- 6 files changed, 84 insertions(+), 40 deletions(-) diff --git a/src/drivers/plat/t8103.c b/src/drivers/plat/t8103.c index 5fdeaeca..842aff51 100644 --- a/src/drivers/plat/t8103.c +++ b/src/drivers/plat/t8103.c @@ -32,19 +32,31 @@ static bool t8103_probe(struct hal_platform_driver* device_driver, struct hal_pl } return false; } -/* + static struct usb_regs t8103_usb_regs = { .reg1 = 0x32080270, .reg2 = 0x32080278, .reg3 = 0x32080270, - .otg_irq = 324 + .otg_irq = 0x307 +}; + +static struct usb_dart_regs t8103_usb_dart_regs = { + //.synopsysOTGBase = 0x239000000, }; -*/ + static bool t8103_get_platform_value(const char* name, void* value, size_t* size) { - /*if (strcmp(name, "usb_regs") == 0 && *size == sizeof(struct usb_regs)) { + if (strcmp(name, "usb_regs") == 0 && *size == sizeof(struct usb_regs)) { + return false; // not yet + memcpy(value, &t8103_usb_regs, sizeof(struct usb_regs)); return true; - }*/ + } else + if (strcmp(name, "usb_dart") == 0 && *size == sizeof(struct usb_dart_regs)) { + return false; // not yet + + memcpy(value, &t8103_usb_dart_regs, sizeof(struct usb_dart_regs)); + return true; + } return false; } diff --git a/src/drivers/usb/synopsys_otg.c b/src/drivers/usb/synopsys_otg.c index 385b5318..3497da7a 100644 --- a/src/drivers/usb/synopsys_otg.c +++ b/src/drivers/usb/synopsys_otg.c @@ -1741,23 +1741,31 @@ void usb_main() { static uint64_t reg1=0, reg2=0, reg3=0; void usb_bringup() { - clock_gate(reg1, 0); - clock_gate(reg2, 0); - clock_gate(reg3, 0); + if (reg1) + clock_gate(reg1, 0); + if (reg2) + clock_gate(reg2, 0); + if (reg3) + clock_gate(reg3, 0); spin(1000); - clock_gate(reg1, 1); - clock_gate(reg2, 1); - clock_gate(reg3, 1); + if (reg1) + clock_gate(reg1, 1); + if (reg2) + clock_gate(reg2, 1); + if (reg3) + clock_gate(reg3, 1); // t8011 is really just cursed... - if (socnum == 0x8011) { - *(volatile uint32_t*)(gSynopsysComplexBase + 0x00) = 1; - *(volatile uint32_t*)(gSynopsysComplexBase + 0x24) = 0x3000088; - } else { - *(volatile uint32_t*)(gSynopsysComplexBase + 0x1c) = 0x108; - *(volatile uint32_t*)(gSynopsysComplexBase + 0x5c) = 0x108; + if (gSynopsysComplexBase) { + if (socnum == 0x8011) { + *(volatile uint32_t*)(gSynopsysComplexBase + 0x00) = 1; + *(volatile uint32_t*)(gSynopsysComplexBase + 0x24) = 0x3000088; + } else { + *(volatile uint32_t*)(gSynopsysComplexBase + 0x1c) = 0x108; + *(volatile uint32_t*)(gSynopsysComplexBase + 0x5c) = 0x108; + } } - *(volatile uint32_t *)(gSynopsysOTGBase + 0x8) = dt_get_u32_prop("otgphyctrl", "cfg0-device"); - *(volatile uint32_t *)(gSynopsysOTGBase + 0xc) = dt_get_u32_prop("otgphyctrl", "cfg1-device"); + //*(volatile uint32_t *)(gSynopsysOTGBase + 0x8) = dt_get_u32_prop("otgphyctrl", "cfg0-device"); + //*(volatile uint32_t *)(gSynopsysOTGBase + 0xc) = dt_get_u32_prop("otgphyctrl", "cfg1-device"); *(volatile uint32_t*)(gSynopsysOTGBase) |= 1; spin(20); *(volatile uint32_t*)(gSynopsysOTGBase) &= 0xFFFFFFF3; @@ -1767,15 +1775,9 @@ void usb_bringup() { *(volatile uint32_t*)(gSynopsysOTGBase + 0x4) &= ~2; spin(1500); } +uint32_t otg_irq; -void usb_init() { - struct usb_regs regs; - size_t plsz = sizeof(struct usb_regs); - if (!hal_get_platform_value("usb_regs", ®s, &plsz)) { - puts("synopsys_otg: need usb_regs platform value! not initializing.."); - return; - } - +void usb_legacy_init() { gSynopsysOTGBase = 0; uint32_t sz = 0; uint64_t *reg = dt_get_prop("otgphyctrl", "reg", &sz); @@ -1799,13 +1801,31 @@ void usb_init() { gSynopsysComplexBase = gIOBase + dt_get_u32_prop("usb-complex", "reg"); // Can't trust "usb-device" dtre entry, because that can be USB3 and we want USB2 gSynopsysBase = (gSynopsysOTGBase & ~0xfffULL) + 0x00100000; - uint32_t otg_irq; - - +} + +void usb_init() { + struct usb_regs regs; + size_t plsz = sizeof(struct usb_regs); + if (!hal_get_platform_value("usb_regs", ®s, &plsz)) { + puts("synopsys_otg: need usb_regs platform value! not initializing.."); + return; + } reg1 = gIOBase + regs.reg1; reg2 = gIOBase + regs.reg2; reg3 = gIOBase + regs.reg3; otg_irq = regs.otg_irq; + + bool isUSBDART = false; + struct usb_dart_regs dartregs; + plsz = sizeof(struct usb_dart_regs); + + if (hal_get_platform_value("usb_dart", &dartregs, &plsz)) { + gSynopsysOTGBase = dartregs.synopsysOTGBase; + gSynopsysBase = (gSynopsysOTGBase & ~0xfffULL) + 0x00100000; + isUSBDART = true; + } else { + usb_legacy_init(); + } uint64_t dma_page_v = (uint64_t) alloc_contig(4 * DMA_BUFFER_SIZE); uint64_t dma_page_p = vatophys_static((void*)dma_page_v); @@ -1815,7 +1835,12 @@ void usb_init() { disable_interrupts(); usb_irq_mode = 1; usb_usbtask_handoff_mode = 0; - usb_bringup(); + + if (isUSBDART) { + + } else { + usb_bringup(); + } gSynopsysCoreVersion = reg_read(rGSNPSID) & 0xffff; USB_DEBUG(USB_DEBUG_STANDARD, "gSynopsysCoreVersion: 0x%x", gSynopsysCoreVersion); diff --git a/src/drivers/usb/usb.h b/src/drivers/usb/usb.h index fdce721a..6fad7fdc 100644 --- a/src/drivers/usb/usb.h +++ b/src/drivers/usb/usb.h @@ -44,6 +44,10 @@ struct usb_regs { int otg_irq; }; +struct usb_dart_regs { + uint64_t synopsysOTGBase; +}; + struct setup_packet { uint8_t bmRequestType; uint8_t bRequest; diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 33c6978e..c4f91b82 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -92,7 +92,7 @@ void pongo_main_task() { puts(""); puts("#=================="); puts("#"); - puts("# pongoOS " PONGO_VERSION); + iprintf("# pongoOS " PONGO_VERSION " (EL%d)\n", get_el()); puts("#"); puts("# https://checkra.in"); puts("#"); diff --git a/src/kernel/mm.c b/src/kernel/mm.c index ed225ae7..dc7d48de 100644 --- a/src/kernel/mm.c +++ b/src/kernel/mm.c @@ -830,11 +830,17 @@ void phys_dereference(uint64_t pa, uint64_t size) { } enable_interrupts(); } - +uint64_t gMemSize = 0; void alloc_init() { if (alloc_static_base) return; uint64_t memory_size = gBootArgs->memSize; + if (memory_size > 0x100000000) memory_size = 0x100000000; // force pongo to use at most 4GB (FIXME: remove when we support >4G ram) + gMemSize = memory_size; + + uint64_t pbase = gBootArgs->physBase; + memory_size -= pbase - 0x800000000; + ppages = memory_size >> 14; uint64_t early_heap = early_heap_base; @@ -867,7 +873,7 @@ void alloc_init() { } uint64_t alloc_heap_base = (((uint64_t)early_heap) + 0x7fff) & (~0x3fff); - uint64_t alloc_heap_end = (((uint64_t)(phystokv(gBootArgs->physBase) + gBootArgs->memSize)) + 0x3fff) & (~0x3fff) - 1024*1024; + uint64_t alloc_heap_end = (((uint64_t)(phystokv(gBootArgs->physBase) + memory_size)) + 0x3fff) & (~0x3fff) - 1024*1024; phys_force_free(vatophys_static((void*)alloc_heap_base), alloc_heap_end - alloc_heap_base); } @@ -935,8 +941,8 @@ void* phystokv(uint64_t paddr) { } uint64_t vatophys_static(void* kva) { uint64_t kva_check = (uint64_t) kva; - if (!((kva_check >= kCacheableView) && (kva_check < (kCacheableView + 0x100000000)))) { - panic("vatophys_static must be called on kCacheableView map addresses"); + if (!((kva_check >= kCacheableView) && (kva_check < (kCacheableView + gMemSize)))) { + panic("vatophys_static must be called on kCacheableView map addresses! addr = %llx", kva_check); } return (((uint64_t)kva) - kCacheableView + 0x800000000); } diff --git a/src/shell/main.c b/src/shell/main.c index 75e7eb83..1ab04ca0 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -291,8 +291,5 @@ void shell_main() { #endif // gBootFlag = BOOT_FLAG_HOOK; - while (1) { - queue_rx_string("ps\n"); - sleep(1); - } + queue_rx_string("ps\n"); } From 75adb03b3ce7018300f5899726f9d9c4c8799ae4 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 17:23:37 +0100 Subject: [PATCH 10/50] dart --- src/drivers/dart/dart.c | 119 ++++++++++++++++++++++++++++++++++++++++ src/drivers/dart/dart.h | 2 + src/drivers/hal/hal.c | 107 ++++++++++++++++++++++++++++++++++-- src/drivers/hal/hal.h | 10 +++- src/dynamic/modload.c | 4 ++ src/kernel/dtree.c | 24 ++++++-- src/kernel/pongo.h | 2 + src/shell/main.c | 8 ++- 8 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 src/drivers/dart/dart.c create mode 100644 src/drivers/dart/dart.h diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c new file mode 100644 index 00000000..ea2d1847 --- /dev/null +++ b/src/drivers/dart/dart.c @@ -0,0 +1,119 @@ +/* + * pongoOS - https://checkra.in + * + * Copyright (C) 2019-2020 checkra1n team + * + * This file is part of pongoOS. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#import +#import "dart.h" + +struct t8020_dart { + uint64_t dart_type; + uint64_t dart_regbase; +}; + +struct dart_regs { + uint64_t base; + uint64_t size; +}; + +static bool register_dart_mapper(struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + dt_node_t* pnode = device->parent->node; + + if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { + void* val = dt_prop(node, "name", &len); + + uint32_t reglen = 0; + struct dart_regs* regs = dt_prop(pnode, "reg", ®len); + if (!regs) return false; + if (reglen & 0xf) { + panic("invalid dtre! reglen %x not aligned", reglen); + } + reglen /= 0x10; + + uint32_t reg_index = device->phandle - device->parent->phandle; + reg_index--; + + if (reg_index >= reglen) { + iprintf("invalid dtre! %s: reg_index > reglen (%d > %d)\n", val, reg_index, reglen); + return false; + } + + struct t8020_dart* dart = calloc(sizeof(struct t8020_dart), 1); + dart->dart_type = 0x8020; + dart->dart_regbase = regs[reg_index].base + gIOBase; + iprintf("Found 8020 dart-mapper: %s @ %llx\n", val, dart->dart_regbase); + + *context = dart; + return true; + } + + return false; +} + + + +static bool dart_probe(struct hal_service* svc, struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (node) { + void* val = dt_prop(node, "device_type", &len); + if (val && strcmp(val, "dart-mapper") == 0) { + return register_dart_mapper(device, context); + } + } + return false; +} + +static int dart_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + struct t8020_dart* dart = ((struct t8020_dart*)svc->context); + if (method == DART_ENTER_BYPASS_MODE) { + if (dart->dart_type == 0x8020) { + *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x10; + return dart_service_op(svc, device, DART_FLUSH_CACHE, NULL, 0, NULL, 0); + } + } else if (method == DART_FLUSH_CACHE) { + if (dart->dart_type == 0x8020) { + *(volatile uint32_t*)(dart->dart_regbase + 0x34) = 0; + *(volatile uint32_t*)(dart->dart_regbase + 0x20) = 0; + while(*(volatile uint32_t*)(dart->dart_regbase + 0x20) & 4) {} + + return 0; + } + } + return -1; +} + +static struct hal_service dart_svc = { + .name = "dart", + .probe = dart_probe, + .service_op = dart_service_op +}; + +static void dart_init(struct driver* driver) { + hal_register_hal_service(&dart_svc); +} + +REGISTER_DRIVER(dart, dart_init, NULL, 0); diff --git a/src/drivers/dart/dart.h b/src/drivers/dart/dart.h new file mode 100644 index 00000000..8b1e77c4 --- /dev/null +++ b/src/drivers/dart/dart.h @@ -0,0 +1,2 @@ +#define DART_ENTER_BYPASS_MODE 0 +#define DART_FLUSH_CACHE 1 diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index b944a7c6..b013ae47 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -33,6 +33,7 @@ struct hal_device* gRootDevice, * gDeviceTreeDevice; #define HAL_LOAD_XNU_DTREE 0 #define HAL_LOAD_DTREE_CHILDREN 1 #define HAL_CREATE_CHILD_DEVICE 2 +#define HAL_GET_MAPPER 3 void hal_probe_hal_services(struct hal_device* device) ; @@ -45,6 +46,7 @@ static int hal_load_dtree_child_node(void* arg, dt_node_t* node) { if (val) { struct hal_device* device = malloc(sizeof(struct hal_device)); device->next = parentDevice->down; + device->parent = parentDevice; parentDevice->down = device; device->node = node; device->down = NULL; @@ -58,16 +60,17 @@ static int hal_load_dtree_child_node(void* arg, dt_node_t* node) { return 0; } -static int hal_service_op(struct hal_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { +static int hal_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_LOAD_XNU_DTREE) { device->node = gDeviceTree; return 0; } else if (method == HAL_LOAD_DTREE_CHILDREN && device->node) { // int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg) - return dt_parse(device->node, 0, NULL, hal_load_dtree_child_node, device, NULL, NULL); + return dt_parse_ex(device->node, 0, NULL, hal_load_dtree_child_node, device, NULL, NULL, 1); } else if (method == HAL_CREATE_CHILD_DEVICE && data_out_size && *data_out_size == 8) { struct hal_device* ndevice = malloc(sizeof(struct hal_device)); ndevice->next = device->down; + ndevice->parent = device; device->down = ndevice; ndevice->node = NULL; ndevice->down = NULL; @@ -77,12 +80,42 @@ static int hal_service_op(struct hal_service* svc, struct hal_device* device, ui *(void**)data_out = ndevice; + return 0; + } else if (method == HAL_GET_MAPPER && data_in && data_in_size == 4 && data_out && *data_out_size == 8) { + uint32_t index = *(uint32_t*)data_in; + *(void**)data_out = NULL; + + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return -1; + + uint32_t* val = dt_prop(node, "iommu-parent", &len); + if (!val) { + return -1; + } + + if (index >= len / 4) { + return -1; + } + + uint32_t phandle = val[index]; + *(struct hal_device **)data_out = hal_get_phandle_device(phandle); return 0; } return -1; } +struct hal_device * hal_get_mapper(struct hal_device* device, uint32_t index) { + struct hal_device * rv = NULL; + size_t osz = 8; + + if (hal_invoke_service_op(device, "hal", HAL_GET_MAPPER, &index, 4, &rv, &osz)) { + return NULL; + } + return rv; +} + static bool hal_service_probe(struct hal_service* svc, struct hal_device* device, void** context) { return true; } @@ -96,7 +129,9 @@ int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint3 struct hal_device_service* svc = device->services; while (svc) { if (svc_name == svc->name || strcmp(svc_name, svc->name) == 0) { - return svc->service->service_op(svc->service, device, method, data_in, data_in_size, data_out, data_out_size); + if (svc->service->service_op) { + return svc->service->service_op(svc, device, method, data_in, data_in_size, data_out, data_out_size); + } } svc = svc->next; } @@ -113,6 +148,16 @@ void hal_register_hal_service(struct hal_service* svc) { } void hal_probe_hal_services(struct hal_device* device) { lock_take(&hal_service_lock); + + if (device && device->node) { + uint32_t llen = 0; + uint32_t* phandle = dt_prop(device->node, "AAPL,phandle", &llen); + if (phandle && llen == 4) { + hal_register_phandle_device(*phandle, device); + device->phandle = *phandle; + } + } + struct hal_service* svc = hal_service_head; while (svc) { if (svc->probe) { @@ -176,6 +221,55 @@ void lsdev_cmd(const char *cmd, char *args) { recurse_device(gRootDevice, 0, lsdev_cb); } +static struct hal_device * hal_device_by_name_recursive(struct hal_device* dev, int depth, const char* name) { + struct hal_device* nxt = dev->down; + if (strcmp(dev->name, name) == 0) { + return dev; + } + + while (nxt) { + struct hal_device* rv = hal_device_by_name_recursive(nxt, depth+1, name); + if (rv) { + return rv; + } + nxt = nxt->next; + } + return NULL; +} +struct hal_device * hal_device_by_name(const char* name) { + return hal_device_by_name_recursive(gRootDevice, 0, name); +} + +struct hal_device** phandle_table; +uint32_t phandle_table_size; + +void hal_register_phandle_device(uint32_t phandle, struct hal_device* dev) { + if (!phandle_table_size) { + phandle_table_size = 0x100; + phandle_table = calloc(phandle_table_size, 8); + } + + uint32_t phandle_table_size_new = phandle_table_size; + while (phandle > phandle_table_size_new) { + phandle_table_size_new *= 2; + } + + if (phandle_table_size != phandle_table_size_new) { + struct hal_device** phandle_table_new = calloc(phandle_table_size_new, 8); + memcpy(phandle_table_new, phandle_table, phandle_table_size_new * 8); + phandle_table = phandle_table_new; + phandle_table_size = phandle_table_size_new; + } + + phandle_table[phandle] = dev; +} +struct hal_device* hal_get_phandle_device(uint32_t phandle) { + while (phandle < phandle_table_size) { + return phandle_table[phandle]; + } + return NULL; +} + void hal_init() { gPlatform = NULL; @@ -216,13 +310,16 @@ void hal_init() { if (0 != hal_invoke_service_op(gRootDevice, "hal", HAL_CREATE_CHILD_DEVICE, "dtree", 6, &gDeviceTreeDevice, &ssz)) panic("hal_init: HAL_CREATE_CHILD_DEVICE failed!"); - if (0 != hal_invoke_service_op(gDeviceTreeDevice, "hal", HAL_LOAD_XNU_DTREE, NULL, 0, NULL, NULL)) panic("hal_init: HAL_LOAD_XNU_DTREE failed!"); if (0 != hal_invoke_service_op(gDeviceTreeDevice, "hal", HAL_LOAD_DTREE_CHILDREN, NULL, 0, NULL, NULL)) panic("hal_init: HAL_LOAD_DTREE_CHILDREN failed!"); + + if (gPlatform->bound_platform_driver->late_init) { + gPlatform->bound_platform_driver->late_init(); + } + command_register("lsdev", "prints hal devices tree", lsdev_cmd); - } diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index 2b6a0949..2717d1e9 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -47,14 +47,18 @@ struct hal_platform_driver { void* context; bool (*probe)(struct hal_platform_driver* device_driver, struct hal_platform* device); bool (*get_platform_value)(const char* name, void* value, size_t* size); + void (*late_init)(); }; struct hal_device { struct hal_device* next; struct hal_device* down; + struct hal_device* parent; const char* name; dt_node_t* node; struct hal_device_service* services; + + uint32_t phandle; }; struct hal_device_service { @@ -68,10 +72,12 @@ struct hal_service { struct hal_service* next; const char* name; bool (*probe)(struct hal_service* svc, struct hal_device* device, void** context); - int (*service_op)(struct hal_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size); + int (*service_op)(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size); }; extern void hal_register_hal_service(struct hal_service* svc); +extern void hal_register_phandle_device(uint32_t phandle, struct hal_device* dev); +extern struct hal_device* hal_get_phandle_device(uint32_t phandle); struct hal_platform { uint32_t cpid; @@ -87,3 +93,5 @@ extern void hal_register_platform_driver(struct hal_platform_driver* driver); extern const char* hal_platform_name(); extern bool hal_get_platform_value(const char* name, void* value, size_t* size); extern int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size); +extern struct hal_device * hal_get_mapper(struct hal_device* device, uint32_t index); +extern struct hal_device * hal_device_by_name(const char* name); diff --git a/src/dynamic/modload.c b/src/dynamic/modload.c index 1e0bd9bd..ba4fbe6a 100644 --- a/src/dynamic/modload.c +++ b/src/dynamic/modload.c @@ -211,6 +211,10 @@ struct pongo_exports public_api[] = { EXPORT_SYMBOL_P(ramdisk_size), EXPORT_SYMBOL_P(autoboot_count), EXPORT_SYMBOL_P(sep_boot_hook), + EXPORT_SYMBOL_P(gFramebuffer), + EXPORT_SYMBOL_P(gWidth), + EXPORT_SYMBOL_P(gHeight), + EXPORT_SYMBOL_P(gRowPixels), EXPORT_SYMBOL_P(aes), EXPORT_SYMBOL_P(_impure_ptr), EXPORT_SYMBOL_P(loader_xfer_recv_size), diff --git a/src/kernel/dtree.c b/src/kernel/dtree.c index 3a8f84b4..da6ad982 100644 --- a/src/kernel/dtree.c +++ b/src/kernel/dtree.c @@ -53,12 +53,21 @@ int dt_check(void* mem, uint32_t size, uint32_t* offp) return 0; } -int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg) + +int dt_parse_ex(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg, uint32_t flags) { if (cb_node) { - int r = cb_node(cbn_arg, node); - if (r != 0) - return r; + if (flags & 1) { // only enumerate children in cb_node + if (depth == 1) { + int r = cb_node(cbn_arg, node); + if (r != 0) + return r; + } + } else { + int r = cb_node(cbn_arg, node); + if (r != 0) + return r; + } } if (depth >= 0 || cb_prop) { uint32_t off = sizeof(dt_node_t); @@ -75,7 +84,7 @@ int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, d if (depth >= 0) { for (uint32_t i = 0, max = node->nchld; i < max; ++i) { uint32_t add = 0; - int r = dt_parse((dt_node_t*)((uintptr_t)node + off), depth + 1, &add, cb_node, cbn_arg, cb_prop, cbp_arg); + int r = dt_parse_ex((dt_node_t*)((uintptr_t)node + off), depth + 1, &add, cb_node, cbn_arg, cb_prop, cbp_arg, flags); if (r != 0) return r; off += add; @@ -86,7 +95,10 @@ int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, d } return 0; } - +int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg) +{ + return dt_parse_ex(node,depth,offp,cb_node,cbn_arg,cb_prop,cbp_arg,0); +} static int dt_find_cb(void* a, dt_node_t* node, int depth, const char* key, void* val, uint32_t len) { dt_find_cb_t* arg = a; diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 2a3f321a..8eeb838c 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -37,6 +37,7 @@ #ifdef PONGO_PRIVATE #include "framebuffer/fb.h" #include "usb/usb.h" +#include "dart/dart.h" #include "uart/uart.h" #include "gpio/gpio.h" #include "timer/timer.h" @@ -133,6 +134,7 @@ extern void lock_release(lock* lock); // releases ownership on a lock extern int dt_check(void* mem, uint32_t size, uint32_t* offp); extern int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg); +extern int dt_parse_ex(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg, uint32_t flags); extern dt_node_t* dt_find(dt_node_t* node, const char* name); extern void* dt_prop(dt_node_t* node, const char* key, uint32_t* lenp); extern void* dt_get_prop(const char* device, const char* prop, uint32_t* size); diff --git a/src/shell/main.c b/src/shell/main.c index 1ab04ca0..89bb5a74 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -291,5 +291,11 @@ void shell_main() { #endif // gBootFlag = BOOT_FLAG_HOOK; - queue_rx_string("ps\n"); +#ifdef DART_TEST + sleep(4); + struct hal_device* dev = hal_device_by_name("disp0"); + struct hal_device* mapper = hal_get_mapper(dev, 0); + + hal_invoke_service_op(mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); +#endif } From b281309f07a8eeff7f35a13bbc3a66107f66ddc6 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 18:17:23 +0100 Subject: [PATCH 11/50] mapper --- src/drivers/dart/dart.c | 23 +++++-------------- src/drivers/hal/hal.c | 51 +++++++++++++++++++++++++++++++++++++++++ src/drivers/hal/hal.h | 1 + src/shell/main.c | 2 ++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index ea2d1847..c762fda8 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -32,11 +32,6 @@ struct t8020_dart { uint64_t dart_regbase; }; -struct dart_regs { - uint64_t base; - uint64_t size; -}; - static bool register_dart_mapper(struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; @@ -45,25 +40,19 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { void* val = dt_prop(node, "name", &len); - uint32_t reglen = 0; - struct dart_regs* regs = dt_prop(pnode, "reg", ®len); - if (!regs) return false; - if (reglen & 0xf) { - panic("invalid dtre! reglen %x not aligned", reglen); - } - reglen /= 0x10; - uint32_t reg_index = device->phandle - device->parent->phandle; reg_index--; + + void* regs = hal_map_registers(device->parent, reg_index, NULL); - if (reg_index >= reglen) { - iprintf("invalid dtre! %s: reg_index > reglen (%d > %d)\n", val, reg_index, reglen); + if (!regs) { + iprintf("Couldn't map MMIO for 8020 dart-mapper: %s\n", val); return false; } - + struct t8020_dart* dart = calloc(sizeof(struct t8020_dart), 1); dart->dart_type = 0x8020; - dart->dart_regbase = regs[reg_index].base + gIOBase; + dart->dart_regbase = (uint64_t) regs; iprintf("Found 8020 dart-mapper: %s @ %llx\n", val, dart->dart_regbase); *context = dart; diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index b013ae47..1715b6c1 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -34,6 +34,7 @@ struct hal_device* gRootDevice, * gDeviceTreeDevice; #define HAL_LOAD_DTREE_CHILDREN 1 #define HAL_CREATE_CHILD_DEVICE 2 #define HAL_GET_MAPPER 3 +#define HAL_MAP_REGISTERS 4 void hal_probe_hal_services(struct hal_device* device) ; @@ -100,12 +101,62 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev uint32_t phandle = val[index]; *(struct hal_device **)data_out = hal_get_phandle_device(phandle); + return 0; + } else if (method == HAL_MAP_REGISTERS && data_in && data_in_size == 4 && data_out && *data_out_size == 16) { + uint32_t index = *(uint32_t*)data_in; + ((void**)data_out)[0] = NULL; + ((void**)data_out)[1] = NULL; + + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return -1; + + void* val = dt_prop(node, "reg", &len); + if (!val) { + return -1; + } + + if (index * 0x10 >= len) { + return -1; + } + + struct device_regs { + uint64_t base; + uint64_t size; + }* regs = val; + + uint64_t size = regs[index].size; + size += 0x3FFF; + size &= ~0x3FFF; + uint64_t va = linear_kvm_alloc(size); + + uint64_t regbase = regs[index].base + gIOBase; + + map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!va & 0x7000000000000000); + + ((void**)data_out)[0] = (void*)va; + ((void**)data_out)[1] = (void*)regs[index].size; + return 0; } return -1; } +void * hal_map_registers(struct hal_device* device, uint32_t index, size_t *size) { + struct { + void* base; + size_t size; + } rv; + size_t osz = 0x10; + if (size) *size = 0; + + if (hal_invoke_service_op(device, "hal", HAL_MAP_REGISTERS, &index, 4, &rv, &osz)) { + return NULL; + } + if (size) *size = rv.size; + return rv.base; +} struct hal_device * hal_get_mapper(struct hal_device* device, uint32_t index) { struct hal_device * rv = NULL; size_t osz = 8; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index 2717d1e9..d28ee0ed 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -95,3 +95,4 @@ extern bool hal_get_platform_value(const char* name, void* value, size_t* size); extern int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size); extern struct hal_device * hal_get_mapper(struct hal_device* device, uint32_t index); extern struct hal_device * hal_device_by_name(const char* name); +extern void * hal_map_registers(struct hal_device* device, uint32_t index, size_t *size); diff --git a/src/shell/main.c b/src/shell/main.c index 89bb5a74..69a405c9 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -291,6 +291,8 @@ void shell_main() { #endif // gBootFlag = BOOT_FLAG_HOOK; +#define DART_TEST + #ifdef DART_TEST sleep(4); struct hal_device* dev = hal_device_by_name("disp0"); From cc6af866d562a800fdff104ee58698e096c72cae Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 19:57:43 +0100 Subject: [PATCH 12/50] use mapper more widely --- src/drivers/gpio/gpio.c | 6 ++++-- src/drivers/hal/hal.c | 31 ++++++++++++++++++++------- src/drivers/hal/hal.h | 2 ++ src/drivers/mipi/mipi.c | 9 ++++---- src/drivers/uart/uart.c | 10 +++++---- src/dynamic/modload_macho.c | 2 +- src/kernel/lowlevel.c | 42 ++++++++++++++++++++++--------------- src/kernel/main_task.c | 6 +++--- src/shell/main.c | 5 +++-- 9 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/drivers/gpio/gpio.c b/src/drivers/gpio/gpio.c index 67d8fdb9..7e960dd3 100644 --- a/src/drivers/gpio/gpio.c +++ b/src/drivers/gpio/gpio.c @@ -36,8 +36,10 @@ struct task gpio_task = {.name = "gpio"}; uint64_t gGpioBase; void gpio_early_init() { - gGpioBase = dt_get_u32_prop("gpio", "reg"); - gGpioBase += gIOBase; + struct hal_device* gpio_dev = hal_device_by_name("gpio"); + if (gpio_dev) { + gGpioBase = (uint64_t) hal_map_registers(gpio_dev, 0, NULL); + } } void gpio_init() { diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 1715b6c1..1b80b612 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -35,6 +35,7 @@ struct hal_device* gRootDevice, * gDeviceTreeDevice; #define HAL_CREATE_CHILD_DEVICE 2 #define HAL_GET_MAPPER 3 #define HAL_MAP_REGISTERS 4 +#define HAL_GET_IRQNR 5 void hal_probe_hal_services(struct hal_device* device) ; @@ -124,17 +125,11 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev uint64_t base; uint64_t size; }* regs = val; - - uint64_t size = regs[index].size; - size += 0x3FFF; - size &= ~0x3FFF; - uint64_t va = linear_kvm_alloc(size); uint64_t regbase = regs[index].base + gIOBase; + uint64_t size = regs[index].size; - map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!va & 0x7000000000000000); - - ((void**)data_out)[0] = (void*)va; + ((void**)data_out)[0] = (void*)hal_map_physical_mmio(regbase, size); ((void**)data_out)[1] = (void*)regs[index].size; return 0; @@ -142,6 +137,26 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev return -1; } +uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { + size += 0x3FFF; + size &= ~0x3FFF; + uint64_t va = linear_kvm_alloc(size); + + map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!va & 0x7000000000000000); + + return va; +} +int32_t hal_get_irqno(struct hal_device* device, uint32_t index) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return -1; + + int32_t* val = dt_prop(node, "interrupts", &len); + if (!val || index * 4 >= len) { + return -1; + } + return val[index]; +} void * hal_map_registers(struct hal_device* device, uint32_t index, size_t *size) { struct { diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index d28ee0ed..b3fed53a 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -96,3 +96,5 @@ extern int hal_invoke_service_op(struct hal_device* device, const char* svc_name extern struct hal_device * hal_get_mapper(struct hal_device* device, uint32_t index); extern struct hal_device * hal_device_by_name(const char* name); extern void * hal_map_registers(struct hal_device* device, uint32_t index, size_t *size); +extern int32_t hal_get_irqno(struct hal_device* device, uint32_t index); +extern uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size); diff --git a/src/drivers/mipi/mipi.c b/src/drivers/mipi/mipi.c index 8444ce09..e647bf09 100644 --- a/src/drivers/mipi/mipi.c +++ b/src/drivers/mipi/mipi.c @@ -95,11 +95,10 @@ void mipi_cmd(const char* cmd, char* args) { } } -void mipi_init() { - if(dt_find(gDeviceTree, "mipi-dsim")) { - uint64_t mipi_reg = dt_get_u32_prop("mipi-dsim", "reg"); - mipi_reg += gIOBase; - gmipi_reg = mipi_reg; +void mipi_init() { + struct hal_device* mipi_dev = hal_device_by_name("mipi-dsim"); + if (mipi_dev) { + gmipi_reg = (uint64_t) hal_map_registers(mipi_dev, 0, NULL); command_register("mipi", "mipi tools", mipi_cmd); } } diff --git a/src/drivers/uart/uart.c b/src/drivers/uart/uart.c index 7bd4efc1..e112fe71 100644 --- a/src/drivers/uart/uart.c +++ b/src/drivers/uart/uart.c @@ -90,11 +90,13 @@ static inline void put_serial_modifier(const char* str) { } uint64_t gUartBase; +struct hal_device* gUartDevice; extern uint32_t gLogoBitmap[32]; void serial_early_init() { + gUartDevice = hal_device_by_name("uart0"); + gUartBase = (uint64_t) hal_map_registers(gUartDevice, 0, NULL); + disable_interrupts(); - gUartBase = dt_get_u32_prop("uart0", "reg"); - gUartBase += gIOBase; rULCON0 = 3; rUCON0 = 0x405; rUFCON0 = 0; @@ -140,9 +142,9 @@ void serial_enable_rx() { char uart_irq_driven = 0; void serial_init() { struct task* irq_task = task_create_extended("uart", uart_main, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - + disable_interrupts(); - uart_irq = dt_get_u32_prop("uart0", "interrupts"); + uart_irq = hal_get_irqno(gUartDevice, 0); serial_disable_rx(); task_bind_to_irq(irq_task, uart_irq); uart_irq_driven = 0; diff --git a/src/dynamic/modload_macho.c b/src/dynamic/modload_macho.c index 9d04814c..f7880231 100644 --- a/src/dynamic/modload_macho.c +++ b/src/dynamic/modload_macho.c @@ -69,7 +69,7 @@ void modload_cmd() { vmsz_needed -= base_vmaddr; //iprintf("need %llx, got %llx\n", filesz_expected, loader_xfer_recv_count); if (!(filesz_expected > loader_xfer_recv_count)) { - uint64_t entrypoint; + uint64_t entrypoint = 0; uint8_t * allocto = alloc_contig((vmsz_needed + 0x3FFF) & ~0x3FFF); uint64_t vma_base = linear_kvm_alloc(vmsz_needed); struct pongo_module_info* module = pongo_module_create(segmentCount); diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 3aa988ea..0e09438d 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -475,8 +475,6 @@ void sleep(uint32_t sec) { usleep((uint64_t)sec * 1000000ULL); } -int gAICVersion = -1; -int gAICStyle = -1; __attribute__((used)) static void interrupt_or_config(uint32_t bits) { *(volatile uint32_t*)(gInterruptBase + 0x10) |= bits; @@ -577,23 +575,33 @@ static pmgr_dev_t *gPMGRdev = NULL; void pmgr_init() { - dt_node_t *pmgr = dt_find(gDeviceTree, "pmgr"); - gPMGRreg = dt_prop(pmgr, "reg", &gPMGRreglen); - gPMGRmap = dt_prop(pmgr, "ps-regs", &gPMGRmaplen); - gPMGRdev = dt_prop(pmgr, "devices", &gPMGRdevlen); - gPMGRreglen /= sizeof(*gPMGRreg); - gPMGRmaplen /= sizeof(*gPMGRmap); - gPMGRdevlen /= sizeof(*gPMGRdev); - gPMGRBase = gIOBase + gPMGRreg[0].addr; - gWDTBase = gIOBase + dt_get_u64_prop("wdt", "reg"); + struct hal_device* pmgrdevice = hal_device_by_name("pmgr"); + if (pmgrdevice) { + void* pmreg = dt_prop(pmgrdevice->node, "reg", &gPMGRreglen); + gPMGRreg = malloc(gPMGRreglen); + memcpy(gPMGRreg, pmreg, gPMGRreglen); + + gPMGRmap = dt_prop(pmgrdevice->node, "ps-regs", &gPMGRmaplen); + gPMGRdev = dt_prop(pmgrdevice->node, "devices", &gPMGRdevlen); + gPMGRreglen /= sizeof(*gPMGRreg); + gPMGRmaplen /= sizeof(*gPMGRmap); + gPMGRdevlen /= sizeof(*gPMGRdev); + + for (int i=0; i < gPMGRreglen; i++) { + gPMGRreg[i].addr = (uint64_t) hal_map_physical_mmio(gPMGRreg[i].addr, gPMGRreg[i].size); + } + gPMGRBase = gPMGRreg[0].addr; + } + struct hal_device* wdtdevice = hal_device_by_name("wdt"); + if (wdtdevice) { + gWDTBase = (uint64_t) hal_map_registers(wdtdevice, 0, NULL); + } command_register("reset", "resets the device", wdt_reset); command_register("crash", "branches to an invalid address", (void*)0x41414141); } void interrupt_init() { - gInterruptBase = dt_get_u32_prop("aic", "reg"); - gInterruptBase += gIOBase; - - gAICVersion = dt_get_u32_prop("aic", "aic-version"); + struct hal_device* aic = hal_device_by_name("aic"); + gInterruptBase = (uint64_t) hal_map_registers(aic, 0, NULL); interrupt_or_config(0xE0000000); interrupt_or_config(1); // enable interrupt @@ -622,7 +630,7 @@ uint64_t device_clock_by_id(uint32_t id) { break; } - return gIOBase + r->addr + m->off + (d->idx << 3); + return r->addr + m->off + (d->idx << 3); } return 0; } @@ -646,7 +654,7 @@ uint64_t device_clock_by_name(const char *name) { break; } - return gIOBase + r->addr + m->off + (d->idx << 3); + return r->addr + m->off + (d->idx << 3); } return 0; } diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index c4f91b82..43e08005 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -50,6 +50,9 @@ void pongo_main_task() { } gBootTimeTicks = get_ticks(); + + // Setup HAL + hal_init(); // Setup GPIO Base gpio_early_init(); @@ -60,9 +63,6 @@ void pongo_main_task() { // Enable serial TX serial_early_init(); - // Setup HAL - hal_init(); - // Turn on IRQ controller interrupt_init(); diff --git a/src/shell/main.c b/src/shell/main.c index 69a405c9..9e93ae2d 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -291,8 +291,9 @@ void shell_main() { #endif // gBootFlag = BOOT_FLAG_HOOK; -#define DART_TEST - + sleep(5); + queue_rx_string("ps\n"); + #ifdef DART_TEST sleep(4); struct hal_device* dev = hal_device_by_name("disp0"); From 5e4c602063cd205484f3fa2bcdecb2cff785373e Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 20:05:01 +0100 Subject: [PATCH 13/50] mapper tlbi --- src/drivers/hal/hal.c | 4 ++++ src/kernel/mm.c | 28 ---------------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 1b80b612..cc8a9da9 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -144,6 +144,10 @@ uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!va & 0x7000000000000000); + for (uint32_t i=0; i < size; i+=0x1000) { + vm_flush_by_addr_all_asid(va + i); + } + return va; } int32_t hal_get_irqno(struct hal_device* device, uint32_t index) { diff --git a/src/kernel/mm.c b/src/kernel/mm.c index dc7d48de..8d3bfd89 100644 --- a/src/kernel/mm.c +++ b/src/kernel/mm.c @@ -568,49 +568,21 @@ void asid_free(uint64_t asid) { #endif asid_table[index >> 3] &= ~(1 << (index&0x7)); - if (get_el() == 2) { - __asm__ volatile("isb"); - __asm__ volatile("tlbi alle2\n"); - __asm__ volatile("dsb sy"); - return; - } - asm volatile("ISB"); asm volatile("TLBI ASIDE1IS, %0" : : "r"(asid)); asm volatile("DSB SY"); } void vm_flush(struct vm_space* fl) { - if (get_el() == 2) { - __asm__ volatile("isb"); - __asm__ volatile("tlbi alle2\n"); - __asm__ volatile("dsb sy"); - return; - } - asm volatile("ISB"); asm volatile("TLBI ASIDE1IS, %0" : : "r"(fl->asid)); asm volatile("DSB SY"); } void vm_flush_by_addr(struct vm_space* fl, uint64_t va) { - if (get_el() == 2) { - __asm__ volatile("isb"); - __asm__ volatile("tlbi alle2\n"); - __asm__ volatile("dsb sy"); - return; - } - asm volatile("ISB"); asm volatile("TLBI VAE1, %0" : : "r"(fl->asid | ((va >> 12) & 0xFFFFFFFFFFF))); asm volatile("DSB SY"); } void vm_flush_by_addr_all_asid(uint64_t va) { - if (get_el() == 2) { - __asm__ volatile("isb"); - __asm__ volatile("tlbi alle2\n"); - __asm__ volatile("dsb sy"); - return; - } - asm volatile("ISB"); asm volatile("TLBI VAAE1, %0" : : "r"((va >> 12) & 0xFFFFFFFFFFF)); asm volatile("DSB SY"); From bbbe986f18d5fce11b3bc6cf921ad4134e7dceb1 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 20:15:00 +0100 Subject: [PATCH 14/50] derp --- src/drivers/hal/hal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index cc8a9da9..9746717a 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -142,7 +142,7 @@ uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { size &= ~0x3FFF; uint64_t va = linear_kvm_alloc(size); - map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!va & 0x7000000000000000); + map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!(va & 0x7000000000000000)); for (uint32_t i=0; i < size; i+=0x1000) { vm_flush_by_addr_all_asid(va + i); From 72accf5357b6217615701823a12057e0ab6dd25c Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 21:08:50 +0100 Subject: [PATCH 15/50] respect io-ranges --- src/drivers/dart/dart.c | 2 -- src/drivers/hal/hal.c | 45 ++++++++++++++++++++++++++++++++++++++--- src/kernel/lowlevel.c | 3 ++- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index c762fda8..0e17aadd 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -62,8 +62,6 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { return false; } - - static bool dart_probe(struct hal_service* svc, struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 9746717a..320fcfd1 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -126,7 +126,7 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev uint64_t size; }* regs = val; - uint64_t regbase = regs[index].base + gIOBase; + uint64_t regbase = regs[index].base; uint64_t size = regs[index].size; ((void**)data_out)[0] = (void*)hal_map_physical_mmio(regbase, size); @@ -137,11 +137,31 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev return -1; } + +struct range_translation_entry { + uint64_t reg_base; + uint64_t phys_base; + uint64_t size; +} range_translation [64]; + +uint32_t range_translation_entries = 0; + +uint64_t translate_register_address(uint64_t address) { + for (int i=0; i < range_translation_entries; i++) { + if (address >= range_translation[i].reg_base && address < range_translation[i].reg_base + range_translation[i].size) { + return address - range_translation[i].reg_base + range_translation[i].phys_base; + } + } + panic("couldn't find address %llx in arm-io map", address); + return -1; +} + uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { size += 0x3FFF; size &= ~0x3FFF; uint64_t va = linear_kvm_alloc(size); - + regbase = translate_register_address(regbase); + map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!(va & 0x7000000000000000)); for (uint32_t i=0; i < size; i+=0x1000) { @@ -333,6 +353,8 @@ void hal_register_phandle_device(uint32_t phandle, struct hal_device* dev) { phandle_table[phandle] = dev; } + + struct hal_device* hal_get_phandle_device(uint32_t phandle) { while (phandle < phandle_table_size) { return phandle_table[phandle]; @@ -340,11 +362,28 @@ struct hal_device* hal_get_phandle_device(uint32_t phandle) { return NULL; } - void hal_init() { gPlatform = NULL; gRootDevice = &_gRootDevice; + dt_node_t* dev = dt_find(gDeviceTree, "arm-io"); + if (!dev) panic("invalid devicetree: no arm-io!"); + uint32_t len = 0; + + uint64_t* val = dt_prop(dev, "ranges", &len); + if (!val) panic("invalid devicetree: no prop!"); + + len /= 0x18; + + for (int i=0; i < len; i++) { // basically a memcpy but for clarity... + range_translation[i].reg_base = val[i*3]; + range_translation[i].phys_base = val[i*3 + 1]; + range_translation[i].size = val[i*3 + 2]; + range_translation_entries++; + if (range_translation_entries > 64) panic("too many entries in arm-io"); + } + + extern struct driver drivers[] __asm("section$start$__DATA$__drivers"); extern struct driver drivers_end[] __asm("section$end$__DATA$__drivers"); struct driver* driver = &drivers[0]; diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 0e09438d..2b7f8e27 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -120,12 +120,13 @@ __asm__( " isb sy\n" " ret\n" + ".arch v8.4a\n" "_enable_mmu_el2:\n" " dsb sy\n" " msr mair_el2, x2\n" " msr tcr_el2, x1\n" " msr ttbr0_el2, x0\n" - ".long 0xd51c2023\n" // " msr ttbr1_el2, x3\n" iphonesdk is not a fan of this opcode for some reason? + " msr ttbr1_el2, x3\n" " isb sy\n" " tlbi alle2\n" " isb sy\n" From f23da17184ded977d0fbbc0d9392d2fcc27cf02c Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 23:29:12 +0100 Subject: [PATCH 16/50] begin work on synopsys dwc3, moved AIC, PMGR, WDT to HAL model --- src/drivers/dart/dart.c | 18 +++++ src/drivers/dart/dart.h | 2 + src/drivers/hal/hal.c | 16 +++- src/drivers/hal/hal.h | 1 + src/drivers/usb/synopsys_drd.c | 132 +++++++++++++++++++++++++++++++++ src/kernel/lowlevel.c | 107 ++++++++++++++++++-------- src/kernel/main_task.c | 6 -- src/kernel/pongo.h | 1 + src/shell/main.c | 1 - 9 files changed, 244 insertions(+), 40 deletions(-) create mode 100644 src/drivers/usb/synopsys_drd.c diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 0e17aadd..903131b0 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -38,10 +38,17 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { dt_node_t* pnode = device->parent->node; if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { + uint32_t* regid = dt_prop(node, "reg", &len); + if (len != 4) regid = NULL; + void* val = dt_prop(node, "name", &len); uint32_t reg_index = device->phandle - device->parent->phandle; reg_index--; + + if (regid) { + reg_index = *regid; + } void* regs = hal_map_registers(device->parent, reg_index, NULL); @@ -76,6 +83,7 @@ static bool dart_probe(struct hal_service* svc, struct hal_device* device, void* static int dart_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { struct t8020_dart* dart = ((struct t8020_dart*)svc->context); + if (method == DART_ENTER_BYPASS_MODE) { if (dart->dart_type == 0x8020) { *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x10; @@ -89,6 +97,16 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de return 0; } + } else if (method == DART_CLOCK_GATE_ON || method == DART_CLOCK_GATE_OFF) { + int32_t clock_gate_id = hal_get_clock_gate_id(device->parent, 0); + if (clock_gate_id > 0) { + uint64_t clock = device_clock_by_id(clock_gate_id); + if (clock) { + clock_gate(clock, method == DART_CLOCK_GATE_ON); + return 0; + } + } + return -1; } return -1; } diff --git a/src/drivers/dart/dart.h b/src/drivers/dart/dart.h index 8b1e77c4..a200c752 100644 --- a/src/drivers/dart/dart.h +++ b/src/drivers/dart/dart.h @@ -1,2 +1,4 @@ #define DART_ENTER_BYPASS_MODE 0 #define DART_FLUSH_CACHE 1 +#define DART_CLOCK_GATE_ON 2 +#define DART_CLOCK_GATE_OFF 3 diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 320fcfd1..5f6e514f 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -170,6 +170,19 @@ uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { return va; } + +int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return -1; + + int32_t* val = dt_prop(node, "clock-gates", &len); + if (!val || index * 4 >= len) { + return -1; + } + return val[index]; +} + int32_t hal_get_irqno(struct hal_device* device, uint32_t index) { uint32_t len = 0; dt_node_t* node = device->node; @@ -372,7 +385,7 @@ void hal_init() { uint64_t* val = dt_prop(dev, "ranges", &len); if (!val) panic("invalid devicetree: no prop!"); - + len /= 0x18; for (int i=0; i < len; i++) { // basically a memcpy but for clarity... @@ -383,7 +396,6 @@ void hal_init() { if (range_translation_entries > 64) panic("too many entries in arm-io"); } - extern struct driver drivers[] __asm("section$start$__DATA$__drivers"); extern struct driver drivers_end[] __asm("section$end$__DATA$__drivers"); struct driver* driver = &drivers[0]; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index b3fed53a..e705f626 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -98,3 +98,4 @@ extern struct hal_device * hal_device_by_name(const char* name); extern void * hal_map_registers(struct hal_device* device, uint32_t index, size_t *size); extern int32_t hal_get_irqno(struct hal_device* device, uint32_t index); extern uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size); +extern int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index); diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c new file mode 100644 index 00000000..6d206f03 --- /dev/null +++ b/src/drivers/usb/synopsys_drd.c @@ -0,0 +1,132 @@ +// +// Project: KTRW Synopsys OTG USB controller driver +// Authors: Brandon Azad +// and qwertyuiop, Siguza, et al from the checkra1n team +// +// Copyright 2019 Google LLC +// Copyright 2019-2020 checkra1n team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +struct atc { + uint64_t regBase; +}; + +struct drd { + uint64_t regBase; + struct task* irq_task; + struct hal_device* atc_device; + struct hal_device* mapper; + struct hal_device* device; +}; + + +static void drd_irq_handle() { + puts("drd irq"); +} + +static void drd_irq_task() { + while (1) { + disable_interrupts(); + drd_irq_handle(); + enable_interrupts(); + task_exit_irq(); + } + +} +static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + return -1; +} +static int atc_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + return -1; +} +static bool register_drd(struct hal_device* device, void** context) { + // DesignWare DWC3 Dual Role Device + struct drd* drd = calloc(sizeof(struct drd), 1); + drd->mapper = hal_get_mapper(device, 0); + + hal_invoke_service_op(drd->mapper, "dart", DART_CLOCK_GATE_ON, NULL, 0, NULL, NULL); + + clock_gate(0x23b700420, 1); + clock_gate(0x23d280088, 1); + clock_gate(0x23d280098, 1); + + hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); + drd->regBase = (uint64_t)hal_map_registers(device, 0, NULL); + drd->device = device; + drd->irq_task = task_create_extended("uart", drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); + + task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); + + uint32_t len = 0; + uint32_t* val = dt_prop(device->node, "atc-phy-parent", &len); + + if (val && len >= 4) { + drd->atc_device = hal_get_phandle_device(*val); + } else { + panic("unknown atc-phy-parent!"); + } + + *context = drd; + return true; +} + +static bool register_atc(struct hal_device* device, void** context) { + // Apple Type C PHY + + return false; +} + +static bool atc_probe(struct hal_service* svc, struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (node) { + void* val = dt_prop(node, "device_type", &len); + if (val && strcmp(val, "atc-phy") == 0) { + return register_atc(device, context); + } + } + return false; +} + +static bool drd_probe(struct hal_service* svc, struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (node) { + void* val = dt_prop(node, "device_type", &len); + if (val && strcmp(val, "usb-drd") == 0) { + return register_drd(device, context); + } + } + return false; +} +static struct hal_service drd_svc = { + .name = "drd", + .probe = drd_probe, + .service_op = drd_service_op +}; +static struct hal_service atc_svc = { + .name = "atc", + .probe = atc_probe, + .service_op = atc_service_op +}; + +static void drd_init(struct driver* driver) { + hal_register_hal_service(&drd_svc); + hal_register_hal_service(&atc_svc); +} + +REGISTER_DRIVER(drd, drd_init, NULL, 0); diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 2b7f8e27..217ffca8 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -574,42 +574,87 @@ static pmgr_reg_t *gPMGRreg = NULL; static pmgr_map_t *gPMGRmap = NULL; static pmgr_dev_t *gPMGRdev = NULL; -void pmgr_init() -{ - struct hal_device* pmgrdevice = hal_device_by_name("pmgr"); - if (pmgrdevice) { - void* pmreg = dt_prop(pmgrdevice->node, "reg", &gPMGRreglen); - gPMGRreg = malloc(gPMGRreglen); - memcpy(gPMGRreg, pmreg, gPMGRreglen); - - gPMGRmap = dt_prop(pmgrdevice->node, "ps-regs", &gPMGRmaplen); - gPMGRdev = dt_prop(pmgrdevice->node, "devices", &gPMGRdevlen); - gPMGRreglen /= sizeof(*gPMGRreg); - gPMGRmaplen /= sizeof(*gPMGRmap); - gPMGRdevlen /= sizeof(*gPMGRdev); - - for (int i=0; i < gPMGRreglen; i++) { - gPMGRreg[i].addr = (uint64_t) hal_map_physical_mmio(gPMGRreg[i].addr, gPMGRreg[i].size); + +void interrupt_teardown() { + wdt_disable(); + task_irq_teardown(); +} + +static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (node) { + void* val = dt_prop(node, "name", &len); + if (val && strcmp(val, "aic") == 0) { + if (gInterruptBase) panic("multiple aic probes! unsupported."); + + gInterruptBase = (uint64_t) hal_map_registers(device, 0, NULL); + + interrupt_or_config(0xE0000000); + interrupt_or_config(1); // enable interrupt + return true; + } else + if (val && strcmp(val, "pmgr") == 0) { + if (gPMGRreg) panic("multiple pmgr probes! unsupported."); + + void* pmreg = dt_prop(device->node, "reg", &gPMGRreglen); + gPMGRreg = malloc(gPMGRreglen); + memcpy(gPMGRreg, pmreg, gPMGRreglen); + + gPMGRmap = dt_prop(device->node, "ps-regs", &gPMGRmaplen); + gPMGRdev = dt_prop(device->node, "devices", &gPMGRdevlen); + gPMGRreglen /= sizeof(*gPMGRreg); + gPMGRmaplen /= sizeof(*gPMGRmap); + gPMGRdevlen /= sizeof(*gPMGRdev); + + for (int i=0; i < gPMGRreglen; i++) { + gPMGRreg[i].addr = (uint64_t) hal_map_physical_mmio(gPMGRreg[i].addr, gPMGRreg[i].size); + } + gPMGRBase = gPMGRreg[0].addr; + + return true; + } else + if (val && strcmp(val, "wdt") == 0) { + if (gWDTBase) panic("multiple wdt probes! unsupported."); + + gWDTBase = (uint64_t) hal_map_registers(device, 0, NULL); + command_register("reset", "resets the device", wdt_reset); + command_register("crash", "branches to an invalid address", (void*)0x41414141); + return true; } - gPMGRBase = gPMGRreg[0].addr; - } - struct hal_device* wdtdevice = hal_device_by_name("wdt"); - if (wdtdevice) { - gWDTBase = (uint64_t) hal_map_registers(wdtdevice, 0, NULL); } - command_register("reset", "resets the device", wdt_reset); - command_register("crash", "branches to an invalid address", (void*)0x41414141); + return false; } -void interrupt_init() { - struct hal_device* aic = hal_device_by_name("aic"); - gInterruptBase = (uint64_t) hal_map_registers(aic, 0, NULL); - interrupt_or_config(0xE0000000); - interrupt_or_config(1); // enable interrupt +static int lowlevel_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + return -1; } -void interrupt_teardown() { - wdt_disable(); - task_irq_teardown(); + +static struct hal_service lowlevel_svc = { + .name = "lowlevel", + .probe = lowlevel_probe, + .service_op = lowlevel_service_op +}; + +static void lowlevel_init(struct driver* driver) { + hal_register_hal_service(&lowlevel_svc); +} + +REGISTER_DRIVER(lowlevel, lowlevel_init, NULL, 0); + +const char* device_clock_name_by_id(uint32_t idx) +{ + for(uint32_t i = 0; i < gPMGRdevlen; ++i) + { + pmgr_dev_t *d = &gPMGRdev[i]; + if(d->id != idx) + { + continue; + } + + return d->name; + } + return NULL; } uint64_t device_clock_by_id(uint32_t id) diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 43e08005..3a1843b1 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -63,15 +63,9 @@ void pongo_main_task() { // Enable serial TX serial_early_init(); - // Turn on IRQ controller - interrupt_init(); - // Enable IRQ serial RX serial_init(); - // Initialize pmgr - pmgr_init(); - /* Initialize display */ diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 8eeb838c..2b06f181 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -333,6 +333,7 @@ extern uint64_t xnu_rebase_va(uint64_t va); extern uint64_t kext_rebase_va(uint64_t va); extern struct mach_header_64* xnu_pf_get_kext_header(struct mach_header_64* kheader, const char* kext_bundle_id); extern void xnu_pf_apply_each_kext(struct mach_header_64* kheader, xnu_pf_patchset_t* patchset); +extern const char* device_clock_name_by_id(uint32_t idx); #ifdef OVERRIDE_CACHEABLE_VIEW # define kCacheableView OVERRIDE_CACHEABLE_VIEW diff --git a/src/shell/main.c b/src/shell/main.c index 9e93ae2d..c1cceedd 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -298,7 +298,6 @@ void shell_main() { sleep(4); struct hal_device* dev = hal_device_by_name("disp0"); struct hal_device* mapper = hal_get_mapper(dev, 0); - hal_invoke_service_op(mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); #endif } From 366cf4132a91aa5bb0dfa62bd7760e7904fb815f Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sun, 17 Jan 2021 23:30:00 +0100 Subject: [PATCH 17/50] pongo license header makes sense here --- src/drivers/usb/synopsys_drd.c | 47 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 6d206f03..6183f971 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -1,24 +1,29 @@ -// -// Project: KTRW Synopsys OTG USB controller driver -// Authors: Brandon Azad -// and qwertyuiop, Siguza, et al from the checkra1n team -// -// Copyright 2019 Google LLC -// Copyright 2019-2020 checkra1n team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - +/* + * pongoOS - https://checkra.in + * + * Copyright (C) 2019-2020 checkra1n team + * + * This file is part of pongoOS. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ #include struct atc { From dcdbba669a375d4cd84597f1c14a428017bef0d4 Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Sun, 17 Jan 2021 23:59:54 +0100 Subject: [PATCH 18/50] Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e9fef28d..507069bb 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ $(BUILD)/vmacho: $(AUX)/vmacho.c | $(BUILD) $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) $(BUILD)/machopack: $(AUX)/machopack.c | $(BUILD) - $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) + $(CC) -Wall -Iapple-include -O3 -o $@ $^ $(CFLAGS) $(BUILD): mkdir -p $@ From 761e202b9b7a95ca88b470c62a5c5d150413913e Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Mon, 18 Jan 2021 00:11:27 +0100 Subject: [PATCH 19/50] Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 507069bb..4b94fb97 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ RA1N := $(ROOT)/checkra1n/kpf # General options EMBEDDED_LD_FLAGS ?= -nostdlib -static -Wl,-fatal_warnings -Wl,-dead_strip -Wl,-Z $(EMBEDDED_LDFLAGS) -EMBEDDED_CC_FLAGS ?= --target=arm64-apple-ios12.0 -Wall -Wunused-label -Werror -O3 -flto -ffreestanding -U__nonnull -nostdlibinc -I$(LIB)/include $(EMBEDDED_LD_FLAGS) $(EMBEDDED_CFLAGS) +EMBEDDED_CC_FLAGS ?= --target=arm64-apple-ios12.0 -mcpu=cyclone -mtune=cyclone -Wall -Wunused-label -Werror -O3 -ffreestanding -U__nonnull -nostdlibinc -I$(LIB)/include $(EMBEDDED_LD_FLAGS) $(EMBEDDED_CFLAGS) # Pongo options PONGO_LDFLAGS ?= -L$(LIB)/lib -lc -lm -Wl,-preload -Wl,-no_uuid -Wl,-e,start -Wl,-order_file,$(SRC)/sym_order.txt -Wl,-image_base,0x100000000 -Wl,-sectalign,__DATA,__common,0x8 -Wl,-segalign,0x4000 From 2855f243df651d3e3eb332298dd7014c579fa0b2 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 00:49:52 +0100 Subject: [PATCH 20/50] fix pmgr aliased accesses, usb bringup --- src/drivers/dart/dart.c | 10 -------- src/drivers/hal/hal.c | 29 ++++++++++++++++------ src/drivers/hal/hal.h | 12 ++++++++++ src/drivers/usb/synopsys_drd.c | 22 ++++++++--------- src/kernel/lowlevel.c | 44 +++++++++++++++++++++++++++------- 5 files changed, 80 insertions(+), 37 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 903131b0..06436d02 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -97,16 +97,6 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de return 0; } - } else if (method == DART_CLOCK_GATE_ON || method == DART_CLOCK_GATE_OFF) { - int32_t clock_gate_id = hal_get_clock_gate_id(device->parent, 0); - if (clock_gate_id > 0) { - uint64_t clock = device_clock_by_id(clock_gate_id); - if (clock) { - clock_gate(clock, method == DART_CLOCK_GATE_ON); - return 0; - } - } - return -1; } return -1; } diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 5f6e514f..f0f0d4e4 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -30,13 +30,6 @@ struct hal_device _gRootDevice = { }; struct hal_device* gRootDevice, * gDeviceTreeDevice; -#define HAL_LOAD_XNU_DTREE 0 -#define HAL_LOAD_DTREE_CHILDREN 1 -#define HAL_CREATE_CHILD_DEVICE 2 -#define HAL_GET_MAPPER 3 -#define HAL_MAP_REGISTERS 4 -#define HAL_GET_IRQNR 5 - void hal_probe_hal_services(struct hal_device* device) ; static int hal_load_dtree_child_node(void* arg, dt_node_t* node) { @@ -133,6 +126,21 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev ((void**)data_out)[1] = (void*)regs[index].size; return 0; + } else if (method == HAL_DEVICE_CLOCK_GATE_ON || method == HAL_DEVICE_CLOCK_GATE_OFF) { + int32_t count = hal_get_clock_gate_size(device); + if (count > 0) { + for (int i=0; i < count; i++) { + int32_t clock_gate_id = hal_get_clock_gate_id(device, i); + if (clock_gate_id > 0) { + uint64_t clock = device_clock_by_id(clock_gate_id); + if (clock) { + clock_gate(clock, method == HAL_DEVICE_CLOCK_GATE_ON); + } + } + } + return 0; + } + return -1; } return -1; @@ -182,6 +190,13 @@ int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index) { } return val[index]; } +int32_t hal_get_clock_gate_size(struct hal_device* device) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return -1; + dt_prop(node, "clock-gates", &len); + return len / 4; +} int32_t hal_get_irqno(struct hal_device* device, uint32_t index) { uint32_t len = 0; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index e705f626..d90ee5bb 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -99,3 +99,15 @@ extern void * hal_map_registers(struct hal_device* device, uint32_t index, size_ extern int32_t hal_get_irqno(struct hal_device* device, uint32_t index); extern uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size); extern int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index); +extern int32_t hal_get_clock_gate_size(struct hal_device* device); + + +#define HAL_LOAD_XNU_DTREE 0 +#define HAL_LOAD_DTREE_CHILDREN 1 +#define HAL_CREATE_CHILD_DEVICE 2 +#define HAL_GET_MAPPER 3 +#define HAL_MAP_REGISTERS 4 +#define HAL_GET_IRQNR 5 +#define HAL_DEVICE_CLOCK_GATE_ON 6 +#define HAL_DEVICE_CLOCK_GATE_OFF 7 + diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 6183f971..ba00c31f 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -62,19 +62,7 @@ static bool register_drd(struct hal_device* device, void** context) { // DesignWare DWC3 Dual Role Device struct drd* drd = calloc(sizeof(struct drd), 1); drd->mapper = hal_get_mapper(device, 0); - - hal_invoke_service_op(drd->mapper, "dart", DART_CLOCK_GATE_ON, NULL, 0, NULL, NULL); - - clock_gate(0x23b700420, 1); - clock_gate(0x23d280088, 1); - clock_gate(0x23d280098, 1); - - hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); - drd->regBase = (uint64_t)hal_map_registers(device, 0, NULL); drd->device = device; - drd->irq_task = task_create_extended("uart", drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - - task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); uint32_t len = 0; uint32_t* val = dt_prop(device->node, "atc-phy-parent", &len); @@ -84,6 +72,16 @@ static bool register_drd(struct hal_device* device, void** context) { } else { panic("unknown atc-phy-parent!"); } + + hal_invoke_service_op(drd->mapper->parent, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); + hal_invoke_service_op(drd->atc_device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); + hal_invoke_service_op(drd->device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); + + hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); + drd->regBase = (uint64_t)hal_map_registers(device, 0, NULL); + drd->irq_task = task_create_extended(device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); + + task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); *context = drd; return true; diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 217ffca8..54b0c939 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -552,9 +552,9 @@ typedef struct typedef struct { - uint32_t flg : 8, + uint32_t flg : 8, a : 16, - id : 8; + id1 : 8; uint32_t b; uint32_t c : 16, idx : 8, @@ -562,7 +562,8 @@ typedef struct uint32_t d; uint32_t e; uint32_t f; - uint32_t g; + uint32_t g : 16, + id2 : 16; uint32_t h; char name[0x10]; } pmgr_dev_t; @@ -647,11 +648,18 @@ const char* device_clock_name_by_id(uint32_t idx) for(uint32_t i = 0; i < gPMGRdevlen; ++i) { pmgr_dev_t *d = &gPMGRdev[i]; - if(d->id != idx) + uint32_t cid = 0; + + if (d->id1) { + cid = d->id1; + } else { + cid = d->id2; + } + if(cid != idx) { continue; } - + return d->name; } return NULL; @@ -662,11 +670,25 @@ uint64_t device_clock_by_id(uint32_t id) for(uint32_t i = 0; i < gPMGRdevlen; ++i) { pmgr_dev_t *d = &gPMGRdev[i]; - if(d->id != id) + uint32_t cid = 0; + + if (d->id1) { + cid = d->id1; + } else { + cid = d->id2; + } + if(cid != id) { continue; } - if((d->flg & 0x10) || d->map >= gPMGRmaplen) + + if(d->flg & 0x10) { + if (d->b) { + return device_clock_by_id(d->b); + } + break; + } + if (d->map >= gPMGRmaplen) { break; } @@ -690,7 +712,13 @@ uint64_t device_clock_by_name(const char *name) { continue; } - if((d->flg & 0x10) || d->map >= gPMGRmaplen) + if(d->flg & 0x10) { + if (d->b) { + return device_clock_by_id(d->b); + } + break; + } + if(d->map >= gPMGRmaplen) { break; } From 9175436f1ef3fa2507187f95622b402f62324bb6 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 01:46:39 +0100 Subject: [PATCH 21/50] bring up usb phy --- src/drivers/usb/synopsys_drd.c | 92 ++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index ba00c31f..98d5702a 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -26,18 +26,43 @@ */ #include -struct atc { - uint64_t regBase; -}; - struct drd { uint64_t regBase; + uint64_t atcRegBase; + struct task* irq_task; struct hal_device* atc_device; struct hal_device* mapper; struct hal_device* device; }; +__unused static uint32_t drd_reg_read(struct drd* drd, uint32_t offset) { + return *(volatile uint32_t *)(drd->regBase + offset); +} +__unused static uint32_t atc_reg_read(struct drd* drd, uint32_t offset) { + return *(volatile uint32_t *)(drd->atcRegBase + offset); +} + +__unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(drd->regBase + offset) = value; +} +__unused static void atc_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(drd->atcRegBase + offset) = value; +} + +__unused static void drd_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(drd->regBase + offset) &= value; +} +__unused static void atc_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(drd->atcRegBase + offset) &= value; +} + +__unused static void drd_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(drd->regBase + offset) |= value; +} +__unused static void atc_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { + *(volatile uint32_t *)(drd->atcRegBase + offset) |= value; +} static void drd_irq_handle() { puts("drd irq"); @@ -52,10 +77,32 @@ static void drd_irq_task() { } } -static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { - return -1; + +static void atc_enable_device(struct drd* drd, bool enable) { + uint32_t reg = 0; + if (enable) { + reg = atc_reg_read(drd, 0) & 0xFFFFFFF8; + } else { + spin(5 * 1000); + reg = (atc_reg_read(drd, 0) & 0xFFFFFFF8) | 4; + } + atc_reg_write(drd, 0, reg); +} +static void atc_bringup(struct drd* drd) { + atc_reg_or(drd, 0x8, 0x3); + atc_reg_or(drd, 0x8, 0xc); + spin(10 * 1000); + atc_reg_and(drd, 0x4, 0xfffffff7); + spin(10); + atc_reg_and(drd, 0x4, 0xfffffffC); + atc_reg_or(drd, 0x4, 0x4); + atc_reg_or(drd, 0x1c, 0x9fffffff); + spin(30); + + atc_enable_device(drd, true); } -static int atc_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + +static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { return -1; } static bool register_drd(struct hal_device* device, void** context) { @@ -78,33 +125,18 @@ static bool register_drd(struct hal_device* device, void** context) { hal_invoke_service_op(drd->device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); - drd->regBase = (uint64_t)hal_map_registers(device, 0, NULL); - drd->irq_task = task_create_extended(device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); + drd->regBase = (uint64_t)hal_map_registers(drd->device, 0, NULL); + drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); + drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); + atc_bringup(drd); + task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); *context = drd; return true; } -static bool register_atc(struct hal_device* device, void** context) { - // Apple Type C PHY - - return false; -} - -static bool atc_probe(struct hal_service* svc, struct hal_device* device, void** context) { - uint32_t len = 0; - dt_node_t* node = device->node; - if (node) { - void* val = dt_prop(node, "device_type", &len); - if (val && strcmp(val, "atc-phy") == 0) { - return register_atc(device, context); - } - } - return false; -} - static bool drd_probe(struct hal_service* svc, struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; @@ -121,15 +153,9 @@ static struct hal_service drd_svc = { .probe = drd_probe, .service_op = drd_service_op }; -static struct hal_service atc_svc = { - .name = "atc", - .probe = atc_probe, - .service_op = atc_service_op -}; static void drd_init(struct driver* driver) { hal_register_hal_service(&drd_svc); - hal_register_hal_service(&atc_svc); } REGISTER_DRIVER(drd, drd_init, NULL, 0); From 48d7ec641fe0940a5cb68367693e1277b1edc16d Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 02:42:07 +0100 Subject: [PATCH 22/50] fix build --- Makefile | 2 +- tools/machopack.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 4b94fb97..5734c116 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ $(BUILD)/vmacho: $(AUX)/vmacho.c | $(BUILD) $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) $(BUILD)/machopack: $(AUX)/machopack.c | $(BUILD) - $(CC) -Wall -Iapple-include -O3 -o $@ $^ $(CFLAGS) + $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) $(BUILD): mkdir -p $@ diff --git a/tools/machopack.c b/tools/machopack.c index 2af65d6c..cfda7d72 100644 --- a/tools/machopack.c +++ b/tools/machopack.c @@ -7,11 +7,7 @@ #include #include #include -#ifdef __APPLE__ -#include -#else #include "../apple-include/mach-o/loader.h" -#endif int main(int argc, char** argv) { if (argc != 3) { From 7da8a59b74172ecc490c5653325f699ee8604aff Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 03:08:43 +0100 Subject: [PATCH 23/50] drd bringup attempt --- src/drivers/hal/hal.c | 9 +++- src/drivers/usb/synopsys_drd.c | 76 +++++++++++++++++++++++++++-- src/drivers/usb/synopsys_drd_regs.h | 40 +++++++++++++++ 3 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 src/drivers/usb/synopsys_drd_regs.h diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index f0f0d4e4..41e9e940 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -165,10 +165,15 @@ uint64_t translate_register_address(uint64_t address) { } uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { + regbase = translate_register_address(regbase); + uint64_t offset = regbase & 0x3fff; + regbase &= ~0x3fff; + + size += offset; + size += 0x3FFF; size &= ~0x3FFF; uint64_t va = linear_kvm_alloc(size); - regbase = translate_register_address(regbase); map_range_map((uint64_t*)kernel_vm_space.ttbr0, va, regbase, size, 3, 0, 1, 0, PROT_READ|PROT_WRITE, !!(va & 0x7000000000000000)); @@ -176,7 +181,7 @@ uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { vm_flush_by_addr_all_asid(va + i); } - return va; + return va + offset; } int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index) { diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 98d5702a..13e1baac 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -24,10 +24,20 @@ * SOFTWARE. * */ + +// cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/ + #include +//#define REG_LOG struct drd { uint64_t regBase; + uint64_t configRegBase; + uint64_t pipeHandlerRegBase; + uint64_t coreEvtRegBase; + uint64_t ausbCtlRegBase; + uint64_t ausbBulkFabricRegBase; + uint64_t atcLinkRegBase; uint64_t atcRegBase; struct task* irq_task; @@ -37,33 +47,70 @@ struct drd { }; __unused static uint32_t drd_reg_read(struct drd* drd, uint32_t offset) { - return *(volatile uint32_t *)(drd->regBase + offset); + uint32_t rv = *(volatile uint32_t *)(drd->regBase + offset); +#ifdef REG_LOG + fiprintf(stderr, "drd_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; } __unused static uint32_t atc_reg_read(struct drd* drd, uint32_t offset) { - return *(volatile uint32_t *)(drd->atcRegBase + offset); + uint32_t rv = *(volatile uint32_t *)(drd->atcRegBase + offset); +#ifdef REG_LOG + fiprintf(stderr, "atc_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; } __unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "drd_reg_write(%x) = %x\n", offset, value); +#endif *(volatile uint32_t *)(drd->regBase + offset) = value; } __unused static void atc_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "atc_reg_write(%x) = %x\n", offset, value); +#endif *(volatile uint32_t *)(drd->atcRegBase + offset) = value; } __unused static void drd_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "drd_reg_and(%x) = %x\n", offset, value); +#endif *(volatile uint32_t *)(drd->regBase + offset) &= value; } __unused static void atc_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "atc_reg_and(%x) = %x\n", offset, value); +#endif *(volatile uint32_t *)(drd->atcRegBase + offset) &= value; } __unused static void drd_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "drd_reg_or(%x) = %x\n", offset, value); +#endif *(volatile uint32_t *)(drd->regBase + offset) |= value; } __unused static void atc_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "atc_reg_or(%x) = %x\n", offset, value); +#endif *(volatile uint32_t *)(drd->atcRegBase + offset) |= value; } +#include "synopsys_drd_regs.h" + +static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { + disable_interrupts(); +#define USB_DEBUG_REG_VALUE(reg) fiprintf(stderr, ""#reg " = 0x%x\n", drd_reg_read(drd, reg)); + USB_DEBUG_REG_VALUE(G_GSNPSID); + USB_DEBUG_REG_VALUE(G_GCTL); + USB_DEBUG_REG_VALUE(G_GSTS); + enable_interrupts(); +} + static void drd_irq_handle() { puts("drd irq"); } @@ -101,6 +148,13 @@ static void atc_bringup(struct drd* drd) { atc_enable_device(drd, true); } +static void drd_bringup(struct drd* drd) { + drd_reg_or(drd, G_GCTL, G_GCTL_DSBLCLKGTNG); + drd_reg_or(drd, G_GCTL, G_GCTL_CORESOFTRESET); + drd_reg_and(drd, G_GCTL, ~G_GCTL_CORESOFTRESET); +} + + static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { return -1; @@ -125,7 +179,19 @@ static bool register_drd(struct hal_device* device, void** context) { hal_invoke_service_op(drd->device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); - drd->regBase = (uint64_t)hal_map_registers(drd->device, 0, NULL); + + if (strcmp(dt_prop(device->node, "compatible", &len), "usb-drd,t8103") == 0) { + drd->regBase = (uint64_t)hal_map_registers(drd->device, 2, NULL); + drd->configRegBase = (uint64_t)hal_map_registers(drd->device, 1, NULL); + drd->pipeHandlerRegBase = (uint64_t)hal_map_registers(drd->device, 3, NULL); + drd->coreEvtRegBase = (uint64_t)hal_map_registers(drd->device, 4, NULL); + drd->ausbCtlRegBase = (uint64_t)hal_map_registers(drd->device, 6, NULL); + drd->ausbBulkFabricRegBase = (uint64_t)hal_map_registers(drd->device, 7, NULL); + drd->atcLinkRegBase = (uint64_t)hal_map_registers(drd->device, 8, NULL); + } else { + panic("unsupported usb-drd"); + } + drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); @@ -133,6 +199,10 @@ static bool register_drd(struct hal_device* device, void** context) { task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); + drd_bringup(drd); + + USB_DEBUG_PRINT_REGISTERS(drd); + *context = drd; return true; } diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h new file mode 100644 index 00000000..b82b797c --- /dev/null +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -0,0 +1,40 @@ +/* + * pongoOS - https://checkra.in + * + * Copyright (C) 2019-2020 checkra1n team + * + * This file is part of pongoOS. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +// cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/ + +#ifndef SYNOPSYS_DRD_REGS__H_ +#define SYNOPSYS_DRD_REGS__H_ + +#define G_GCTL 0x110 +#define G_GCTL_DSBLCLKGTNG (1 << 0) +#define G_GCTL_CORESOFTRESET (1 << 11) + +#define G_GSTS 0x118 +#define G_GSNPSID 0x120 + +#endif From ea32b9a729817fa30e3edab6c5f9dd490817fe7d Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 03:56:36 +0100 Subject: [PATCH 24/50] dwc3 bringup actually working!!! --- src/drivers/usb/synopsys_drd.c | 67 +++++++++++++++++++++++++++-- src/drivers/usb/synopsys_drd_regs.h | 25 +++++++++-- 2 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 13e1baac..f296e702 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -28,7 +28,7 @@ // cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/ #include -//#define REG_LOG +#define REG_LOG struct drd { uint64_t regBase; @@ -60,6 +60,13 @@ __unused static uint32_t atc_reg_read(struct drd* drd, uint32_t offset) { #endif return rv; } +__unused static uint32_t pipehandler_reg_read(struct drd* drd, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset); +#ifdef REG_LOG + fiprintf(stderr, "pipehandler_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; +} __unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -73,6 +80,12 @@ __unused static void atc_reg_write(struct drd* drd, uint32_t offset, uint32_t va #endif *(volatile uint32_t *)(drd->atcRegBase + offset) = value; } +__unused static void pipehandler_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "pipehandler_reg_write(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset) = value; +} __unused static void drd_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -86,6 +99,12 @@ __unused static void atc_reg_and(struct drd* drd, uint32_t offset, uint32_t valu #endif *(volatile uint32_t *)(drd->atcRegBase + offset) &= value; } +__unused static void pipehandler_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "pipehandler_reg_and(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset) &= value; +} __unused static void drd_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -99,6 +118,12 @@ __unused static void atc_reg_or(struct drd* drd, uint32_t offset, uint32_t value #endif *(volatile uint32_t *)(drd->atcRegBase + offset) |= value; } +__unused static void pipehandler_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "pipehandler_reg_or(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset) |= value; +} #include "synopsys_drd_regs.h" @@ -149,9 +174,43 @@ static void atc_bringup(struct drd* drd) { atc_enable_device(drd, true); } static void drd_bringup(struct drd* drd) { - drd_reg_or(drd, G_GCTL, G_GCTL_DSBLCLKGTNG); - drd_reg_or(drd, G_GCTL, G_GCTL_CORESOFTRESET); - drd_reg_and(drd, G_GCTL, ~G_GCTL_CORESOFTRESET); + uint32_t reg; + + pipehandler_reg_and(drd, P_PHY_MUX_SELECT, ~PIPE_CLK_EN); + + pipehandler_reg_and(drd, P_PHY_MUX_SELECT, ~PIPE_MODE); + + reg = pipehandler_reg_read(drd, P_PHY_MUX_SELECT); + reg &= ~PIPE_CLK_EN; + reg |= 0x8; + pipehandler_reg_write(drd, P_PHY_MUX_SELECT, reg); + + reg = pipehandler_reg_read(drd, P_PHY_MUX_SELECT); + reg &= ~PIPE_MODE; + reg |= 0x2; + pipehandler_reg_write(drd, P_PHY_MUX_SELECT, reg); + + reg = pipehandler_reg_read(drd, P_PHY_MUX_SELECT); + reg &= ~PIPE_CLK_EN; + reg |= 0x20; + pipehandler_reg_write(drd, P_PHY_MUX_SELECT, reg); + + pipehandler_reg_and(drd, P_LOCK_PIPE_IF_REQ, ~1); + + while (pipehandler_reg_read(drd, P_LOCK_PIPE_IF_ACK) & 1) { + ;; + } + + drd_reg_and(drd, G_GUSB2PHYCFG, ~SUSPENDUSB20); + drd_reg_and(drd, G_GUSB3PIPECTL, ~SUSPENDENABLE); + + pipehandler_reg_and(drd, P_AON_GENERAL_REGS, ~ATC_USB31_DRD_FORCE_CLAMP_EN); + + pipehandler_reg_or(drd, P_AON_GENERAL_REGS, ATC_USB31_DRD_SW_VCC_RESET); + + drd_reg_or(drd, G_GCTL, GCTL_DSBLCLKGTNG); + drd_reg_or(drd, G_GCTL, GCTL_CORESOFTRESET); + drd_reg_and(drd, G_GCTL, ~GCTL_CORESOFTRESET); } diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index b82b797c..6e158010 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -25,16 +25,35 @@ * */ -// cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/ +// cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/, ausb regs re'd from AppleUSBXDCIARM #ifndef SYNOPSYS_DRD_REGS__H_ #define SYNOPSYS_DRD_REGS__H_ +// AUSBC_PIPE_HANDLER + +#define P_PHY_MUX_SELECT 0xC // register + +#define PIPE_MODE 3 // bits within P_PHY_MUX_SELECT +#define PIPE_CLK_EN 0x38 // bits within P_PHY_MUX_SELECT + +#define P_LOCK_PIPE_IF_REQ 0x10 +#define P_LOCK_PIPE_IF_ACK 0x14 +#define P_AON_GENERAL_REGS 0x1c +#define ATC_USB31_DRD_FORCE_CLAMP_EN 0x10 // bits within P_AON_GENERAL_REGS +#define ATC_USB31_DRD_SW_VCC_RESET 0x1 // bits within P_AON_GENERAL_REGS + + #define G_GCTL 0x110 -#define G_GCTL_DSBLCLKGTNG (1 << 0) -#define G_GCTL_CORESOFTRESET (1 << 11) +#define GCTL_DSBLCLKGTNG (1 << 0) +#define GCTL_CORESOFTRESET (1 << 11) #define G_GSTS 0x118 #define G_GSNPSID 0x120 +#define G_GUSB2PHYCFG 0x200 +#define SUSPENDUSB20 0x40 // bits within G_GUSB2PHYCFG +#define G_GUSB3PIPECTL 0x2C0 +#define SUSPENDENABLE 0x20000 + #endif From 2fc787cea82155a5499c881ac96a1c6d9e9b686c Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Mon, 18 Jan 2021 23:32:12 +0100 Subject: [PATCH 25/50] Update Makefile Testing inclusion of apple-include for Linux builds --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5734c116..d81022ce 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ $(BUILD)/vmacho: $(AUX)/vmacho.c | $(BUILD) $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) $(BUILD)/machopack: $(AUX)/machopack.c | $(BUILD) - $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) + $(CC) -Wall -O3 -Iapple-include -o $@ $^ $(CFLAGS) $(BUILD): mkdir -p $@ From fe2cb1debbe7331093b9a009b3aa8cbbf6419d3d Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 23:41:41 +0100 Subject: [PATCH 26/50] drd --- src/drivers/framebuffer/fb.c | 5 +- src/drivers/usb/synopsys_drd.c | 171 ++++++++++++++++++++++++---- src/drivers/usb/synopsys_drd_regs.h | 142 ++++++++++++++++++++++- src/kernel/main_task.c | 2 +- src/kernel/pongo.h | 1 + 5 files changed, 297 insertions(+), 24 deletions(-) diff --git a/src/drivers/framebuffer/fb.c b/src/drivers/framebuffer/fb.c index 1cf86b9f..c8e4d9a1 100644 --- a/src/drivers/framebuffer/fb.c +++ b/src/drivers/framebuffer/fb.c @@ -125,7 +125,10 @@ uint32_t colors_mix_alpha(uint32_t color1, uint32_t color2) { return color_compose_v32(componentsw); } - +void fb_reset_cursor() { + y_cursor = bannerHeight; + x_cursor = LEFT_MARGIN; +} void screen_putc(uint8_t c) { if (!gFramebuffer) return; diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index f296e702..e24f7308 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -25,8 +25,6 @@ * */ -// cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/ - #include #define REG_LOG @@ -39,6 +37,10 @@ struct drd { uint64_t ausbBulkFabricRegBase; uint64_t atcLinkRegBase; uint64_t atcRegBase; + uint64_t ausbUSB2PhyRegBase; + + uint64_t physBaseDMA; + void* virtBaseDMA; struct task* irq_task; struct hal_device* atc_device; @@ -67,6 +69,13 @@ __unused static uint32_t pipehandler_reg_read(struct drd* drd, uint32_t offset) #endif return rv; } +__unused static uint32_t ausb_reg_read(struct drd* drd, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(drd->ausbCtlRegBase + offset); +#ifdef REG_LOG + fiprintf(stderr, "ausb_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; +} __unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -86,6 +95,12 @@ __unused static void pipehandler_reg_write(struct drd* drd, uint32_t offset, uin #endif *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset) = value; } +__unused static void ausb_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "ausb_reg_write(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->ausbCtlRegBase + offset) = value; +} __unused static void drd_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -105,6 +120,12 @@ __unused static void pipehandler_reg_and(struct drd* drd, uint32_t offset, uint3 #endif *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset) &= value; } +__unused static void ausb_reg_and(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "ausb_reg_and(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->ausbCtlRegBase + offset) &= value; +} __unused static void drd_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -124,18 +145,87 @@ __unused static void pipehandler_reg_or(struct drd* drd, uint32_t offset, uint32 #endif *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset) |= value; } +__unused static void ausb_reg_or(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "ausb_reg_or(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->ausbCtlRegBase + offset) |= value; +} #include "synopsys_drd_regs.h" static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { disable_interrupts(); #define USB_DEBUG_REG_VALUE(reg) fiprintf(stderr, ""#reg " = 0x%x\n", drd_reg_read(drd, reg)); +#define PHY_DEBUG_REG_VALUE(reg) fiprintf(stderr, ""#reg " = 0x%x\n", drd_reg_read(drd, reg)); + + PHY_DEBUG_REG_VALUE(AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL); + + USB_DEBUG_REG_VALUE(G_DCFG); + USB_DEBUG_REG_VALUE(G_DCTL); + USB_DEBUG_REG_VALUE(G_DSTS); USB_DEBUG_REG_VALUE(G_GSNPSID); USB_DEBUG_REG_VALUE(G_GCTL); USB_DEBUG_REG_VALUE(G_GSTS); + USB_DEBUG_REG_VALUE(G_GPMSTS); + USB_DEBUG_REG_VALUE(G_GUSB2PHYCFG); + USB_DEBUG_REG_VALUE(G_GEVNTCOUNT(0)); + USB_DEBUG_REG_VALUE(G_GEVNTSIZ(0)); + enable_interrupts(); } + +__unused static int8_t drd_device_generic_command(struct drd* drd, uint32_t cmd, uint32_t arg) { + drd_reg_write(drd, G_DGCMDPAR, arg); + drd_reg_write(drd, G_DGCMD, (cmd & DGCMD_CMDMASK) | DGCMD_CMDACT); + while (1) { + uint32_t rd = drd_reg_read(drd, G_DGCMD); + if (! (rd & DGCMD_CMDACT)) { + return (rd & DGCMD_CMDSTSMASK) >> DGCMD_CMDSTSSHIFT; + } + } +} +__unused static int8_t drd_endpoint_command(struct drd* drd, uint32_t ep, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2) { + USB_DEBUG_REG_VALUE(G_GSTS); + drd_reg_write(drd, G_DEPCMDPAR0(ep), arg0); + USB_DEBUG_REG_VALUE(G_GSTS); + drd_reg_write(drd, G_DEPCMDPAR1(ep), arg1); + USB_DEBUG_REG_VALUE(G_GSTS); + drd_reg_write(drd, G_DEPCMDPAR2(ep), arg2); + USB_DEBUG_REG_VALUE(G_GSTS); + drd_reg_write(drd, G_DEPCMD(ep), (cmd & DGCMD_CMDMASK)); + USB_DEBUG_REG_VALUE(G_GSTS); + + drd_reg_or(drd, G_DEPCMD(ep), DEPCMD_CMDACT); + + uint32_t maxtries = 0x1000000; + while (maxtries --) { + uint32_t rd = drd_reg_read(drd, G_DEPCMD(ep)); + if (! (rd & DEPCMD_CMDACT)) { + return (rd & DGCMD_CMDSTSMASK) >> DGCMD_CMDSTSSHIFT; + } + } + return 0; +} + + +#define ENDPOINT_EP0_OUT 0 +#define ENDPOINT_EP0_IN 1 +#define ENDPOINT_EP1_OUT 2 +#define ENDPOINT_EP1_IN 3 + +void drd_endpoint_start_configuration(struct drd* drd, uint32_t ep, uint32_t rsrc) { + if (drd_endpoint_command(drd, ep, DEPSTARTCFG | DEPCMD_RESOURCE_INDEX(rsrc) , 0, 0, 0)) { + panic("drd_endpoint_set_configuration: drd_endpoint_command failed!"); + } +} +void drd_endpoint_set_configuration(struct drd* drd, uint32_t ep, uint32_t ep_type, uint32_t packetsz) { + if (drd_endpoint_command(drd, ep, DEPCFG, DEPCFG_ACTION_INITIALIZE | DEPCFG_MAX_PACKET_SIZE(packetsz) | DEPCFG_EP_TYPE(ep_type), DEPCFG_FIFO_BASED | DEPCFG_EP_NUMBER(ep) | DEPCFG_XFER_NOT_READY_EN | DEPCFG_XFER_COMPLETE_EN | DEPCFG_INTR_NUM(0), 0)) { + panic("drd_endpoint_set_configuration: drd_endpoint_command failed!"); + } +} + static void drd_irq_handle() { puts("drd irq"); } @@ -153,7 +243,7 @@ static void drd_irq_task() { static void atc_enable_device(struct drd* drd, bool enable) { uint32_t reg = 0; if (enable) { - reg = atc_reg_read(drd, 0) & 0xFFFFFFF8; + reg = (atc_reg_read(drd, 0) & 0xFFFFFFF8) | 2; } else { spin(5 * 1000); reg = (atc_reg_read(drd, 0) & 0xFFFFFFF8) | 4; @@ -161,21 +251,29 @@ static void atc_enable_device(struct drd* drd, bool enable) { atc_reg_write(drd, 0, reg); } static void atc_bringup(struct drd* drd) { - atc_reg_or(drd, 0x8, 0x3); - atc_reg_or(drd, 0x8, 0xc); + atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG, VBUS_DETECT_FORCE_VAL | VBUS_DETECT_FORCE_EN | VBUS_VALID_EXT_FORCE_VAL | VBUS_VALID_EXT_FORCE_EN); spin(10 * 1000); - atc_reg_and(drd, 0x4, 0xfffffff7); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, 0xfffffff7); spin(10); - atc_reg_and(drd, 0x4, 0xfffffffC); - atc_reg_or(drd, 0x4, 0x4); - atc_reg_or(drd, 0x1c, 0x9fffffff); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, ~(USB2PHY_RESET|USB2PHY_PORT_RESET)); + atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, USB2PHY_APB_RESETN); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, 0x9fffffff); spin(30); + + atc_enable_device(drd, false); +} - atc_enable_device(drd, true); +__unused static void enable_endpoint(struct drd* drd, uint8_t index) { + drd_endpoint_start_configuration(drd, index, 0); + drd_endpoint_set_configuration(drd, index, USB_ENDPOINT_CONTROL, EP0_MAX_PACKET_SIZE); + USB_DEBUG_REG_VALUE(G_GSTS); + drd_reg_or(drd, G_DALEPENA, 1 << index); + USB_DEBUG_REG_VALUE(G_GSTS); } + static void drd_bringup(struct drd* drd) { uint32_t reg; - + pipehandler_reg_and(drd, P_PHY_MUX_SELECT, ~PIPE_CLK_EN); pipehandler_reg_and(drd, P_PHY_MUX_SELECT, ~PIPE_MODE); @@ -201,18 +299,53 @@ static void drd_bringup(struct drd* drd) { ;; } + usleep(1000); + + pipehandler_reg_or(drd, P_AON_GENERAL_REGS, ATC_USB31_DRD_SW_VCC_RESET); + pipehandler_reg_and(drd, P_AON_GENERAL_REGS, ~ATC_USB31_DRD_FORCE_CLAMP_EN); + drd_reg_and(drd, G_GUSB2PHYCFG, ~SUSPENDUSB20); drd_reg_and(drd, G_GUSB3PIPECTL, ~SUSPENDENABLE); - pipehandler_reg_and(drd, P_AON_GENERAL_REGS, ~ATC_USB31_DRD_FORCE_CLAMP_EN); + ausb_reg_and(drd, AUSBC_FORCE_CLK_ON, ~0x1f); + + pipehandler_reg_or(drd, P_NON_SELECTED_OVERRIDE, 0x8000); + + while (pipehandler_reg_read(drd, P_NON_SELECTED_OVERRIDE) & 0x40000000) { + ;; + } - pipehandler_reg_or(drd, P_AON_GENERAL_REGS, ATC_USB31_DRD_SW_VCC_RESET); + drd_reg_write(drd, G_DCTL, 0x40000001); + while (drd_reg_read(drd, G_DCTL) & 0x40000000) { + ;; + } + + drd_reg_write(drd, G_GCTL, GCTL_PWRDNSCALE(2)); + + drd_reg_write(drd, G_DCFG, (drd_reg_read(drd, G_DCFG) & ~DCFG_DEVSPD) | DCFG_HIGH_SPEED | (1 << DCFG_INTRNUM_SHIFT)); - drd_reg_or(drd, G_GCTL, GCTL_DSBLCLKGTNG); - drd_reg_or(drd, G_GCTL, GCTL_CORESOFTRESET); - drd_reg_and(drd, G_GCTL, ~GCTL_CORESOFTRESET); -} + uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; + + drd->virtBaseDMA = alloc_contig(eventc * 0x4000); + uint64_t dartBaseDMA = drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); + + dartBaseDMA -= 0x800000000; + + for (int i=0; i < eventc; i++) { + uint64_t eventBufferBase = dartBaseDMA + i * 0x4000; + drd_reg_write(drd, G_GEVNTADRLO(i), eventBufferBase & 0xffffffff); + drd_reg_write(drd, G_GEVNTADRHI(i), (eventBufferBase >> 32ULL) & 0xffffffff); + drd_reg_write(drd, G_GEVNTSIZ(i), 0x4000); // implicitly unmask interrupt + } + + USB_DEBUG_REG_VALUE(G_GSTS); + + enable_endpoint(drd, ENDPOINT_EP0_OUT); + drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); + + drd_reg_write(drd, G_DCTL, DCTL_RUN_STOP); +} static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { @@ -254,9 +387,9 @@ static bool register_drd(struct hal_device* device, void** context) { drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - atc_bringup(drd); - task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); + + atc_bringup(drd); drd_bringup(drd); diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index 6e158010..9d623de7 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -25,11 +25,31 @@ * */ -// cleanroom from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/, ausb regs re'd from AppleUSBXDCIARM +// usb regs from https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/global-core-control-gctl-offset-c110/, , depcmd stuff from https://github.com/manux81/zircon.ext4/blob/8c1cb41b970722711477a5f4c709b9bc91f71bc6/system/dev/usb/dwc3/dwc3-regs.h (fuchsia project, Copyright 2016 The Fuchsia Authors). #ifndef SYNOPSYS_DRD_REGS__H_ #define SYNOPSYS_DRD_REGS__H_ +#define AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL 4 + +#define USB2PHY_RESET 1 +#define USB2PHY_PORT_RESET 2 +#define USB2PHY_APB_RESETN 4 +#define USB2PHY_SIDDQ 8 + +#define AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG 8 +#define VBUS_DETECT_FORCE_VAL 1 +#define VBUS_DETECT_FORCE_EN 2 +#define VBUS_VALID_EXT_FORCE_VAL 4 +#define VBUS_VALID_EXT_FORCE_EN 8 + +#define AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE 0x1c +#define USB2PHY_REFCLK_GATEOFF 0x40000000 + +// AUSBC_CTRLREG_BLK + +#define AUSBC_FORCE_CLK_ON 0xf0 + // AUSBC_PIPE_HANDLER #define P_PHY_MUX_SELECT 0xC // register @@ -40,20 +60,136 @@ #define P_LOCK_PIPE_IF_REQ 0x10 #define P_LOCK_PIPE_IF_ACK 0x14 #define P_AON_GENERAL_REGS 0x1c +#define P_NON_SELECTED_OVERRIDE 0x20 #define ATC_USB31_DRD_FORCE_CLAMP_EN 0x10 // bits within P_AON_GENERAL_REGS #define ATC_USB31_DRD_SW_VCC_RESET 0x1 // bits within P_AON_GENERAL_REGS +// Device Configuration Register +#define G_DCFG 0x700 + +#define DCFG_DEVSPD 0b111 +#define DCFG_DEVSPD_SHIFT 0 +#define DCFG_FULL_SPEED 0b001 +#define DCFG_HIGH_SPEED 0b000 +#define DCFG_SUPER_SPEED 0b100 +#define DCFG_DEVADDR 0x3F8 +#define DCFG_DEVADDR_SHIFT 3 +#define DCFG_INTRNUM 0x1FC00 +#define DCFG_INTRNUM_SHIFT 10 +#define DCFG_NUMP 0x3E0000 +#define DCFG_NUMP_SHIFT 17 +#define DCFG_LPMCAP 0x400000 + +// Device Control Register +#define G_DCTL 0x704 +#define DCTL_RUN_STOP (1 << 31) + +// Device Event Enable Register +#define G_DEVTEN 0x708 +#define DEVTEN_VENDEVTSTRCVDEN (1 << 12) +#define DEVTEN_ERRTICERREVTEN (1 << 9) +#define DEVTEN_WKUPEVTEN (1 << 4) +#define DEVTEN_ULSTCNGEN (1 << 3) +#define DEVTEN_CONNECTDONEEVTEN (1 << 2) +#define DEVTEN_USBRSTEVTEN (1 << 1) +#define DEVTEN_DISSCONNEVTEN (1 << 0) + +// Device Status Register +#define G_DSTS 0x70c +#define DSTS_DEVCTRLHLT (1 << 22) + +// Device Generic Command (DGCMD) – Offset c714 +#define G_DGCMDPAR 0x710 +#define G_DGCMD 0x714 +#define DGCMD_CMDACT (1 << 10) +#define DGCMD_CMDMASK 0xf +#define DGCMD_CMDSTSMASK 0xF000 +#define DGCMD_CMDSTSSHIFT 12 + +#define CMDTYP_SET_PERIODIC_REMINDERS 0x02 +#define CMDTYP_SCRATCHPAD_LO 0x04 +#define CMDTYP_SCRATCHPAD_HI 0x05 +#define CMDTYP_TRANSMIT_DEVICE 0x07 +#define CMDTYP_FIFO_FLUSH 0x09 +#define CMDTYP_FIFO_FLUSH_ALL 0x0A +#define CMDTYP_EP_NRDY 0x0C +#define CMDTYP_EP_LOOPBACK_TEST 0x10 + +// Device Active USB Endpoint Enable (DALEPENA) – Offset c720 +#define G_DALEPENA 0x720 #define G_GCTL 0x110 -#define GCTL_DSBLCLKGTNG (1 << 0) -#define GCTL_CORESOFTRESET (1 << 11) +#define GCTL_DSBLCLKGTNG 1 +#define GCTL_PWRDNSCALE(n) (((n) & 0x1fff) << 19) + +#define G_GPMSTS 0x114 #define G_GSTS 0x118 #define G_GSNPSID 0x120 #define G_GUSB2PHYCFG 0x200 +#define PHYSOFTRST (1 << 31) + #define SUSPENDUSB20 0x40 // bits within G_GUSB2PHYCFG #define G_GUSB3PIPECTL 0x2C0 #define SUSPENDENABLE 0x20000 +#define G_GEVNTADRLO(n) (0x400 + 0x10 * (n)) +#define G_GEVNTADRHI(n) (0x404 + 0x10 * (n)) +#define G_GEVNTSIZ(n) (0x408 + 0x10 * (n)) +#define G_GEVNTCOUNT(n) (0x40c + 0x10 * (n)) +#define GEVNTSIZ_EVNTINTRPTMASK (1 << 31) +#define G_GHWPARAMS(n) (0x140 + n * 4) + +#define G_DEPCMDPAR2(n) (0x800 + 0x10 * (n)) +#define G_DEPCMDPAR1(n) (0x804 + 0x10 * (n)) +#define G_DEPCMDPAR0(n) (0x808 + 0x10 * (n)) +#define G_DEPCMD(n) (0x80c + 0x10 * (n)) + +// Command Types for DEPCMD +#define DEPCFG 1 // Set Endpoint Configuration +#define DEPXFERCFG 2 // Set Endpoint Transfer Resource Configuration +#define DEPGETSTATE 3 // Get EndpointState +#define DEPSSTALL 4 // Set Stall +#define DEPCSTALL 5 // Clear Stall +#define DEPSTRTXFER 6 // Start Transfer +#define DEPUPDXFER 7 // Update Transfer +#define DEPENDXFER 8 // End Transfer +#define DEPSTARTCFG 9 // Start New Configuration + +#define DEPCMD_RESOURCE_INDEX(n) (((n) & 0x7f) << 16) + +// DEPCFG Params 0 +#define DEPCFG_ACTION_INITIALIZE (0 << 30) +#define DEPCFG_ACTION_RESTORE (1 << 30) +#define DEPCFG_ACTION_MODIFY (2 << 30) +#define DEPCFG_BURST_SIZE(n) ((((n) - 1) & 0xf) << 22) +#define DEPCFG_FIFO_NUM(n) (((n) & 0x1f) << 17) +#define DEPCFG_INTERNAL_RETRY (1 << 15) +#define DEPCFG_MAX_PACKET_SIZE(n) (((n) & 0x7ff) << 3) +#define DEPCFG_EP_TYPE(n) (((n) & 0x3) << 1) + +// DEPCFG Params 1 +#define DEPCFG_FIFO_BASED (1 << 31) +#define DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) +#define DEPCFG_STREAM_CAPABLE (1 << 24) +#define DEPCFG_INTERVAL(n) (((n) & 0xff) << 16) +#define DEPCFG_EBC (1 << 15) // External Buffer Control +#define DEPCFG_EBC_NO_WRITE_BACK (1 << 14) // Don't write back HWO bit to the TRB descriptor +#define DEPCFG_STREAM_EVT_EN (1 << 13) +#define DEPCFG_XFER_NOT_READY_EN (1 << 10) +#define DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) +#define DEPCFG_XFER_COMPLETE_EN (1 << 8) +#define DEPCFG_INTR_NUM(n) (((n) & 0x1f) << 0) + +#define DEPCMD_CMDIOC (1 << 8) // Command Interrupt on Complete +#define DEPCMD_CMDACT (1 << 10) // Command Active + +#define USB_ENDPOINT_CONTROL 0x00 +#define USB_ENDPOINT_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_BULK 0x02 +#define USB_ENDPOINT_INTERRUPT 0x03 + + + #endif diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 3a1843b1..e2859149 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -82,7 +82,7 @@ void pongo_main_task() { // Set up AES aes_init(); - + fb_reset_cursor(); puts(""); puts("#=================="); puts("#"); diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 2b06f181..e8763fdd 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -226,6 +226,7 @@ extern void proc_reference(struct proc*); extern void proc_release(struct proc*); extern struct task* proc_create_task(struct proc* proc, void* entrypoint); #define PROC_NO_VM 1 +extern void fb_reset_cursor(); extern uint32_t loader_xfer_recv_size; extern void resize_loader_xfer_data(uint32_t newsz); extern bool vm_fault(struct vm_space* vmspace, uint64_t vma, vm_protect_t fault_prot); From 203f79d9fd2a25428156aeda5b1fc4f2ce35c2fa Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Mon, 18 Jan 2021 23:42:22 +0100 Subject: [PATCH 27/50] move copyright --- src/drivers/usb/synopsys_drd_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index 9d623de7..c0f88407 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -1,7 +1,7 @@ /* * pongoOS - https://checkra.in * - * Copyright (C) 2019-2020 checkra1n team + * Copyright (C) 2019-2020 checkra1n team, Copyright (c) 2016 The Fuchsia Authors * * This file is part of pongoOS. * From 4e9d20797db14765094c809647f4ef5127a886ff Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 02:02:59 +0100 Subject: [PATCH 28/50] ok, now drd tells me its trying to reach out for an irq --- src/drivers/usb/synopsys_drd.c | 61 ++++++++++++++--------------- src/drivers/usb/synopsys_drd_regs.h | 9 +++++ 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index e24f7308..934f6efd 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -26,7 +26,6 @@ */ #include -#define REG_LOG struct drd { uint64_t regBase; @@ -160,6 +159,7 @@ static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { #define PHY_DEBUG_REG_VALUE(reg) fiprintf(stderr, ""#reg " = 0x%x\n", drd_reg_read(drd, reg)); PHY_DEBUG_REG_VALUE(AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL); + PHY_DEBUG_REG_VALUE(AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE); USB_DEBUG_REG_VALUE(G_DCFG); USB_DEBUG_REG_VALUE(G_DCTL); @@ -187,25 +187,20 @@ __unused static int8_t drd_device_generic_command(struct drd* drd, uint32_t cmd, } } __unused static int8_t drd_endpoint_command(struct drd* drd, uint32_t ep, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2) { - USB_DEBUG_REG_VALUE(G_GSTS); drd_reg_write(drd, G_DEPCMDPAR0(ep), arg0); - USB_DEBUG_REG_VALUE(G_GSTS); drd_reg_write(drd, G_DEPCMDPAR1(ep), arg1); - USB_DEBUG_REG_VALUE(G_GSTS); drd_reg_write(drd, G_DEPCMDPAR2(ep), arg2); - USB_DEBUG_REG_VALUE(G_GSTS); drd_reg_write(drd, G_DEPCMD(ep), (cmd & DGCMD_CMDMASK)); - USB_DEBUG_REG_VALUE(G_GSTS); drd_reg_or(drd, G_DEPCMD(ep), DEPCMD_CMDACT); - uint32_t maxtries = 0x1000000; - while (maxtries --) { + while (!(cmd & DEPCMD_CMDIOC)) { uint32_t rd = drd_reg_read(drd, G_DEPCMD(ep)); if (! (rd & DEPCMD_CMDACT)) { return (rd & DGCMD_CMDSTSMASK) >> DGCMD_CMDSTSSHIFT; } } + return 0; } @@ -221,7 +216,7 @@ void drd_endpoint_start_configuration(struct drd* drd, uint32_t ep, uint32_t rsr } } void drd_endpoint_set_configuration(struct drd* drd, uint32_t ep, uint32_t ep_type, uint32_t packetsz) { - if (drd_endpoint_command(drd, ep, DEPCFG, DEPCFG_ACTION_INITIALIZE | DEPCFG_MAX_PACKET_SIZE(packetsz) | DEPCFG_EP_TYPE(ep_type), DEPCFG_FIFO_BASED | DEPCFG_EP_NUMBER(ep) | DEPCFG_XFER_NOT_READY_EN | DEPCFG_XFER_COMPLETE_EN | DEPCFG_INTR_NUM(0), 0)) { + if (drd_endpoint_command(drd, ep, DEPCFG, DEPCFG_ACTION_INITIALIZE | DEPCFG_MAX_PACKET_SIZE(packetsz) | DEPCFG_EP_TYPE(ep_type), DEPCFG_EP_NUMBER(ep) | DEPCFG_XFER_NOT_READY_EN | DEPCFG_XFER_COMPLETE_EN | DEPCFG_INTR_NUM(0), 0)) { panic("drd_endpoint_set_configuration: drd_endpoint_command failed!"); } } @@ -243,32 +238,30 @@ static void drd_irq_task() { static void atc_enable_device(struct drd* drd, bool enable) { uint32_t reg = 0; if (enable) { - reg = (atc_reg_read(drd, 0) & 0xFFFFFFF8) | 2; + reg = (atc_reg_read(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL) & ~USB_MODE_MASK) | 2; } else { spin(5 * 1000); - reg = (atc_reg_read(drd, 0) & 0xFFFFFFF8) | 4; + reg = (atc_reg_read(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL) & ~USB_MODE_MASK) | 0; } - atc_reg_write(drd, 0, reg); + atc_reg_write(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL, reg); } static void atc_bringup(struct drd* drd) { atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG, VBUS_DETECT_FORCE_VAL | VBUS_DETECT_FORCE_EN | VBUS_VALID_EXT_FORCE_VAL | VBUS_VALID_EXT_FORCE_EN); spin(10 * 1000); - atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, 0xfffffff7); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, ~USB2PHY_SIDDQ); spin(10); atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, ~(USB2PHY_RESET|USB2PHY_PORT_RESET)); atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, USB2PHY_APB_RESETN); - atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, 0x9fffffff); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, ~(USB2PHY_REFCLK_GATEOFF | USB2PHY_APBCLK_GATEOFF)); spin(30); - atc_enable_device(drd, false); + atc_enable_device(drd, true); } __unused static void enable_endpoint(struct drd* drd, uint8_t index) { drd_endpoint_start_configuration(drd, index, 0); drd_endpoint_set_configuration(drd, index, USB_ENDPOINT_CONTROL, EP0_MAX_PACKET_SIZE); - USB_DEBUG_REG_VALUE(G_GSTS); drd_reg_or(drd, G_DALEPENA, 1 << index); - USB_DEBUG_REG_VALUE(G_GSTS); } static void drd_bringup(struct drd* drd) { @@ -295,34 +288,33 @@ static void drd_bringup(struct drd* drd) { pipehandler_reg_and(drd, P_LOCK_PIPE_IF_REQ, ~1); + while (pipehandler_reg_read(drd, P_LOCK_PIPE_IF_ACK) & 1) { ;; } - usleep(1000); - - pipehandler_reg_or(drd, P_AON_GENERAL_REGS, ATC_USB31_DRD_SW_VCC_RESET); - pipehandler_reg_and(drd, P_AON_GENERAL_REGS, ~ATC_USB31_DRD_FORCE_CLAMP_EN); - drd_reg_and(drd, G_GUSB2PHYCFG, ~SUSPENDUSB20); drd_reg_and(drd, G_GUSB3PIPECTL, ~SUSPENDENABLE); - ausb_reg_and(drd, AUSBC_FORCE_CLK_ON, ~0x1f); +// ausb_reg_and(drd, AUSBC_FORCE_CLK_ON, ~0x1f); + +// pipehandler_reg_or(drd, P_NON_SELECTED_OVERRIDE, 0x8000); - pipehandler_reg_or(drd, P_NON_SELECTED_OVERRIDE, 0x8000); + pipehandler_reg_and(drd, P_AON_GENERAL_REGS, ~ATC_USB31_DRD_FORCE_CLAMP_EN); + pipehandler_reg_or(drd, P_AON_GENERAL_REGS, ATC_USB31_DRD_SW_VCC_RESET); while (pipehandler_reg_read(drd, P_NON_SELECTED_OVERRIDE) & 0x40000000) { ;; } - drd_reg_write(drd, G_DCTL, 0x40000001); - while (drd_reg_read(drd, G_DCTL) & 0x40000000) { + drd_reg_write(drd, G_DCTL, DCTL_SOFTRESET); + while (drd_reg_read(drd, G_DCTL) & DCTL_SOFTRESET) { ;; } - drd_reg_write(drd, G_GCTL, GCTL_PWRDNSCALE(2)); + drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); - drd_reg_write(drd, G_DCFG, (drd_reg_read(drd, G_DCFG) & ~DCFG_DEVSPD) | DCFG_HIGH_SPEED | (1 << DCFG_INTRNUM_SHIFT)); + drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17) | (1 << DCFG_INTRNUM_SHIFT)); uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; @@ -339,9 +331,8 @@ static void drd_bringup(struct drd* drd) { drd_reg_write(drd, G_GEVNTSIZ(i), 0x4000); // implicitly unmask interrupt } - USB_DEBUG_REG_VALUE(G_GSTS); - enable_endpoint(drd, ENDPOINT_EP0_OUT); + drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); drd_reg_write(drd, G_DCTL, DCTL_RUN_STOP); @@ -387,14 +378,20 @@ static bool register_drd(struct hal_device* device, void** context) { drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - task_bind_to_irq(drd->irq_task, hal_get_irqno(device, 0)); + for (int i=0; i < 5; i++) { + task_bind_to_irq(drd->irq_task, hal_get_irqno(device, i)); + } atc_bringup(drd); drd_bringup(drd); USB_DEBUG_PRINT_REGISTERS(drd); - + sleep(1); + USB_DEBUG_PRINT_REGISTERS(drd); + sleep(1); + USB_DEBUG_PRINT_REGISTERS(drd); + *context = drd; return true; } diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index c0f88407..42d88de4 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -30,6 +30,9 @@ #ifndef SYNOPSYS_DRD_REGS__H_ #define SYNOPSYS_DRD_REGS__H_ +#define AUSBC_CFG_USB2PHY_BLK_USB_CTL 0 +#define USB_MODE_MASK 0x7 + #define AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL 4 #define USB2PHY_RESET 1 @@ -45,6 +48,9 @@ #define AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE 0x1c #define USB2PHY_REFCLK_GATEOFF 0x40000000 +#define USB2PHY_APBCLK_GATEOFF 0x20000000 + +#define AUSBC_C0_UTMI_CLK_ACTIVE_EVT_CNT 0x20 // AUSBC_CTRLREG_BLK @@ -82,7 +88,9 @@ // Device Control Register #define G_DCTL 0x704 +#define DCTL_SOFTRESET (1 << 30) #define DCTL_RUN_STOP (1 << 31) +#define DCTL_CORESOFTRESET (1 << 11) // Device Event Enable Register #define G_DEVTEN 0x708 @@ -120,6 +128,7 @@ #define G_GCTL 0x110 #define GCTL_DSBLCLKGTNG 1 +#define GCTL_PRTCAPDIR(isDevice) ((isDevice ? 0b10 : 0b00) << 12) #define GCTL_PWRDNSCALE(n) (((n) & 0x1fff) << 19) #define G_GPMSTS 0x114 From eca1486d478a2d6c22d90bf9d86c4a1ed770e26c Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 04:05:38 +0100 Subject: [PATCH 29/50] improve irq handling, add dart irq handler, improve HAL probing --- src/drivers/dart/dart.c | 22 ++++++++++++++ src/drivers/hal/hal.c | 43 ++++++++++++++++++++++----- src/drivers/hal/hal.h | 4 +++ src/drivers/usb/synopsys_drd.c | 13 +++++---- src/drivers/usb/synopsys_drd_regs.h | 3 +- src/kernel/lowlevel.c | 45 +++++++++++++++++++++++++++-- src/kernel/pongo.h | 4 +++ src/kernel/task.c | 24 ++++++++++----- 8 files changed, 135 insertions(+), 23 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 06436d02..61ae048a 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -32,6 +32,16 @@ struct t8020_dart { uint64_t dart_regbase; }; +struct task* dart_irq_task; + +void dart_irq_handler() { + while (1) { + // struct t8020_dart* dart = task_current_interrupt_context(); + panic("DART IRQ received!"); + task_exit_irq(); + } +} + static bool register_dart_mapper(struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; @@ -60,6 +70,18 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { struct t8020_dart* dart = calloc(sizeof(struct t8020_dart), 1); dart->dart_type = 0x8020; dart->dart_regbase = (uint64_t) regs; + + int dart_irq = hal_get_irqno(device->parent, 0); + if (dart_irq > 0) { + if (!interrupt_context(dart_irq)) { + if (!dart_irq_task) { + dart_irq_task = task_create_extended("dart", dart_irq_handler, TASK_IRQ_HANDLER, 0); + } + task_bind_to_irq(dart_irq_task, dart_irq); + interrupt_associate_context(dart_irq, dart); + } + } + iprintf("Found 8020 dart-mapper: %s @ %llx\n", val, dart->dart_regbase); *context = dart; diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 41e9e940..00537b8b 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -30,7 +30,7 @@ struct hal_device _gRootDevice = { }; struct hal_device* gRootDevice, * gDeviceTreeDevice; -void hal_probe_hal_services(struct hal_device* device) ; +void hal_probe_hal_services(struct hal_device* device, bool isEarlyProbe) ; static int hal_load_dtree_child_node(void* arg, dt_node_t* node) { struct hal_device* parentDevice = arg; @@ -47,7 +47,7 @@ static int hal_load_dtree_child_node(void* arg, dt_node_t* node) { device->down = NULL; device->name = strdup(val); - hal_probe_hal_services(device); + hal_probe_hal_services(device, true); if (0 != hal_invoke_service_op(device, "hal", HAL_LOAD_DTREE_CHILDREN, NULL, 0, NULL, NULL)) panic("hal_load_dtree_child_node: HAL_LOAD_DTREE_CHILDREN failed!"); @@ -71,7 +71,7 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev ndevice->down = NULL; ndevice->name = strdup(data_in); - hal_probe_hal_services(ndevice); + hal_probe_hal_services(ndevice, false); *(void**)data_out = ndevice; @@ -245,7 +245,8 @@ static bool hal_service_probe(struct hal_service* svc, struct hal_device* device struct hal_service hal_service = { .name = "hal", .probe = hal_service_probe, - .service_op = hal_service_op + .service_op = hal_service_op, + .flags = SERVICE_FLAGS_EARLY_PROBE }; int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { @@ -269,7 +270,7 @@ void hal_register_hal_service(struct hal_service* svc) { hal_service_head = svc; lock_release(&hal_service_lock); } -void hal_probe_hal_services(struct hal_device* device) { +void hal_probe_hal_services(struct hal_device* device, bool isEarlyProbe) { lock_take(&hal_service_lock); if (device && device->node) { @@ -283,6 +284,17 @@ void hal_probe_hal_services(struct hal_device* device) { struct hal_service* svc = hal_service_head; while (svc) { + if (!(svc->flags & SERVICE_FLAGS_EARLY_PROBE)) { + if (isEarlyProbe) { + svc = svc->next; + continue; + } + } else { + if (device->flags & DEVICE_HAS_BEEN_PROBED_EARLY) { + svc = svc->next; + continue; + } + } if (svc->probe) { void* ctx = NULL; if (svc->probe(svc, device, &ctx)) { @@ -296,6 +308,11 @@ void hal_probe_hal_services(struct hal_device* device) { } svc = svc->next; } + + if (isEarlyProbe) { + device->flags |= DEVICE_HAS_BEEN_PROBED_EARLY; + } + lock_release(&hal_service_lock); } struct hal_platform _gPlatform; @@ -344,6 +361,17 @@ void lsdev_cmd(const char *cmd, char *args) { recurse_device(gRootDevice, 0, lsdev_cb); } + + +void hal_late_probe_hal_services_cb(struct hal_device* dev, int depth) { + if (gDeviceTreeDevice == dev) return; + + hal_probe_hal_services(dev, false); +} +void hal_late_probe_hal_services() { + recurse_device(gDeviceTreeDevice, 0, hal_late_probe_hal_services_cb); +} + static struct hal_device * hal_device_by_name_recursive(struct hal_device* dev, int depth, const char* name) { struct hal_device* nxt = dev->down; if (strcmp(dev->name, name) == 0) { @@ -446,7 +474,7 @@ void hal_init() { hal_init_late(); hal_register_hal_service(&hal_service); - hal_probe_hal_services(gRootDevice); + hal_probe_hal_services(gRootDevice, true); size_t ssz = 8; if (0 != hal_invoke_service_op(gRootDevice, "hal", HAL_CREATE_CHILD_DEVICE, "dtree", 6, &gDeviceTreeDevice, &ssz)) @@ -456,11 +484,12 @@ void hal_init() { if (0 != hal_invoke_service_op(gDeviceTreeDevice, "hal", HAL_LOAD_DTREE_CHILDREN, NULL, 0, NULL, NULL)) panic("hal_init: HAL_LOAD_DTREE_CHILDREN failed!"); - if (gPlatform->bound_platform_driver->late_init) { gPlatform->bound_platform_driver->late_init(); } + hal_late_probe_hal_services(); + command_register("lsdev", "prints hal devices tree", lsdev_cmd); } diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index d90ee5bb..f2cf10d6 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -59,7 +59,9 @@ struct hal_device { struct hal_device_service* services; uint32_t phandle; + uint32_t flags; }; +#define DEVICE_HAS_BEEN_PROBED_EARLY 1 struct hal_device_service { struct hal_device_service* next; @@ -73,7 +75,9 @@ struct hal_service { const char* name; bool (*probe)(struct hal_service* svc, struct hal_device* device, void** context); int (*service_op)(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size); + int flags; }; +#define SERVICE_FLAGS_EARLY_PROBE 1 extern void hal_register_hal_service(struct hal_service* svc); extern void hal_register_phandle_device(uint32_t phandle, struct hal_device* dev); diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 934f6efd..e85b55d7 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -171,7 +171,10 @@ static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { USB_DEBUG_REG_VALUE(G_GUSB2PHYCFG); USB_DEBUG_REG_VALUE(G_GEVNTCOUNT(0)); USB_DEBUG_REG_VALUE(G_GEVNTSIZ(0)); - + USB_DEBUG_REG_VALUE(G_GPMSTS); + USB_DEBUG_REG_VALUE(BUSERRADDR_LO); + USB_DEBUG_REG_VALUE(BUSERRADDR_HI); + enable_interrupts(); } @@ -216,7 +219,7 @@ void drd_endpoint_start_configuration(struct drd* drd, uint32_t ep, uint32_t rsr } } void drd_endpoint_set_configuration(struct drd* drd, uint32_t ep, uint32_t ep_type, uint32_t packetsz) { - if (drd_endpoint_command(drd, ep, DEPCFG, DEPCFG_ACTION_INITIALIZE | DEPCFG_MAX_PACKET_SIZE(packetsz) | DEPCFG_EP_TYPE(ep_type), DEPCFG_EP_NUMBER(ep) | DEPCFG_XFER_NOT_READY_EN | DEPCFG_XFER_COMPLETE_EN | DEPCFG_INTR_NUM(0), 0)) { + if (drd_endpoint_command(drd, ep, DEPCFG, DEPCFG_ACTION_INITIALIZE | DEPCFG_MAX_PACKET_SIZE(packetsz) | DEPCFG_EP_TYPE(ep_type), DEPCFG_FIFO_BASED | DEPCFG_EP_NUMBER(ep) | DEPCFG_XFER_NOT_READY_EN | DEPCFG_XFER_COMPLETE_EN | DEPCFG_INTR_NUM(0), 0)) { panic("drd_endpoint_set_configuration: drd_endpoint_command failed!"); } } @@ -314,16 +317,16 @@ static void drd_bringup(struct drd* drd) { drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); - drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17) | (1 << DCFG_INTRNUM_SHIFT)); + drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17) | (hal_get_irqno(drd->device, 0) << DCFG_INTRNUM_SHIFT)); uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; drd->virtBaseDMA = alloc_contig(eventc * 0x4000); uint64_t dartBaseDMA = drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); - dartBaseDMA -= 0x800000000; - + + for (int i=0; i < eventc; i++) { uint64_t eventBufferBase = dartBaseDMA + i * 0x4000; drd_reg_write(drd, G_GEVNTADRLO(i), eventBufferBase & 0xffffffff); diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index 42d88de4..79861130 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -198,7 +198,8 @@ #define USB_ENDPOINT_BULK 0x02 #define USB_ENDPOINT_INTERRUPT 0x03 - +#define BUSERRADDR_LO 0x130 +#define BUSERRADDR_HI 0x134 #endif diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 54b0c939..969beaea 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -375,9 +375,11 @@ int sync_exc_el0(uint64_t* state) { dis_int_count = 0; return sync_exc(state); } + uint32_t interrupt_vector() { return (*(volatile uint32_t *)(gInterruptBase + 0x2004)); } + uint64_t interruptCount = 0, fiqCount = 0; uint32_t do_preempt = 1; void disable_preemption() { @@ -477,6 +479,10 @@ void sleep(uint32_t sec) usleep((uint64_t)sec * 1000000ULL); } +struct task** irqvecs; +void** irqctx; +uint32_t irq_count; + __attribute__((used)) static void interrupt_or_config(uint32_t bits) { *(volatile uint32_t*)(gInterruptBase + 0x10) |= bits; } @@ -484,13 +490,27 @@ __attribute__((used)) static void interrupt_and_config(uint32_t bits) { *(volatile uint32_t*)(gInterruptBase + 0x10) &= bits; } uint32_t interrupt_masking_base = 0; +void set_interrupt_affinity(uint32_t reg, uint32_t cpunr) { + if (reg > irq_count) { + panic("set_interrupt_affinity: irqno out of bounds (%d > %d)", reg, irq_count); + } + (*(volatile uint32_t *)(gInterruptBase + 0x3000 + reg * 4)) = (1 << ((reg) & 0x1F)); +} void unmask_interrupt(uint32_t reg) { + if (reg > irq_count) { + panic("unmask_interrupt: irqno out of bounds (%d > %d)", reg, irq_count); + } (*(volatile uint32_t *)(gInterruptBase + 0x4180 + ((reg >> 5) * 4))) = (1 << ((reg) & 0x1F)); - } void mask_interrupt(uint32_t reg) { + if (reg > irq_count) { + panic("mask_interrupt: irqno out of bounds (%d > %d)", reg, irq_count); + } (*(volatile uint32_t *)(gInterruptBase + 0x4100 + ((reg >> 3) * 4))) = (1 << ((reg) & 0x1F)); } +uint32_t count_interrupts() { + return *(volatile uint32_t *)(gInterruptBase + 4); +} #define WDT_CHIP_TMR (*(volatile uint32_t*)(gWDTBase + 0x0)) #define WDT_CHIP_RST (*(volatile uint32_t*)(gWDTBase + 0x4)) @@ -581,6 +601,21 @@ void interrupt_teardown() { task_irq_teardown(); } +void interrupt_associate_context(uint32_t irqno, void* context) { + if (irqno > irq_count) { + panic("interrupt_associate_context: irqno out of bounds (%d > %d)", irqno, irq_count); + } + + irqctx[irqno] = context; +} +void* interrupt_context(uint32_t irqno) { + if (irqno > irq_count) { + panic("interrupt_context: irqno out of bounds (%d > %d)", irqno, irq_count); + } + + return irqctx[irqno]; +} + static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; @@ -591,8 +626,13 @@ static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, v gInterruptBase = (uint64_t) hal_map_registers(device, 0, NULL); + irq_count = count_interrupts(); + irqvecs = calloc(irq_count, sizeof(struct task*)); + irqctx = calloc(irq_count, sizeof(void*)); + interrupt_or_config(0xE0000000); interrupt_or_config(1); // enable interrupt + return true; } else if (val && strcmp(val, "pmgr") == 0) { @@ -634,7 +674,8 @@ static int lowlevel_service_op(struct hal_device_service* svc, struct hal_device static struct hal_service lowlevel_svc = { .name = "lowlevel", .probe = lowlevel_probe, - .service_op = lowlevel_service_op + .service_op = lowlevel_service_op, + .flags = SERVICE_FLAGS_EARLY_PROBE }; static void lowlevel_init(struct driver* driver) { diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 420d02ec..75eef952 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -267,6 +267,10 @@ extern void mark_phys_wired(uint64_t pa, uint64_t size); extern void phys_force_free(uint64_t pa, uint64_t size); extern void phys_reference(uint64_t pa, uint64_t size); extern void phys_dereference(uint64_t pa, uint64_t size); +extern void interrupt_associate_context(uint32_t irqno, void* context); +extern void* interrupt_context(uint32_t irqno); +extern void* task_interrupt_context(); +extern void* task_current_interrupt_context(); typedef struct xnu_pf_range { uint64_t va; diff --git a/src/kernel/task.c b/src/kernel/task.c index e393b2ab..7718acf4 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -60,10 +60,13 @@ void task_timer_fired() { task_timer_ctr ++; } -struct task* irqvecs[0x800]; +extern struct task** irqvecs; +extern uint32_t irq_count; + void register_irq_handler(uint16_t irq_v, struct task* irq_handler) { - if (irq_v >= 0x7ff) panic("invalid irq"); + if (irq_v >= irq_count) panic("invalid irq"); + if (irqvecs[irq_v]) task_release(irqvecs[irq_v]); if (irq_handler) task_reference(irq_handler); irqvecs[irq_v] = irq_handler; @@ -214,13 +217,15 @@ retry:; free(irq_copy); } void task_irq_teardown() { - for (int i=0; i<0x7ff; i++) { + for (int i=0; iirq_type); +} __attribute__((noinline)) void task_switch_irq(struct task* new) { if (!(new->flags & TASK_IRQ_HANDLER)) panic("we are not entering an irq task"); @@ -237,7 +242,7 @@ __attribute__((noinline)) void task_switch_irq(struct task* new) _task_switch(new); if (new->irq_ret != task_current()) { puts("======== IRQ SCHEDULER FAULT ========"); - iprintf("cur_task: %p != irq_ret: %p\n", task_current(), new->irq_ret); + fiprintf(stderr, "cur_task: %p != irq_ret: %p\n", task_current(), new->irq_ret); panic("task_current() is not set correctly"); } new->irq_ret = NULL; @@ -246,12 +251,15 @@ __attribute__((noinline)) void task_switch_irq(struct task* new) served_irqs++; } __attribute__((noinline)) void task_irq_dispatch(uint32_t intr) { - struct task* irq_handler = irqvecs[intr & 0x7FF]; + if (intr > irq_count) { + panic("unmask_interrupt: irqno out of bounds (%d > %d)", intr, irq_count); + } + struct task* irq_handler = irqvecs[intr]; if (irq_handler) { - irq_handler->irq_type = intr & 0x7FF; + irq_handler->irq_type = intr; task_switch_irq(irq_handler); } else { - iprintf("couldn't find irq handler for %x\n", intr); + fiprintf(stderr, "couldn't find irq handler for %x\n", intr); panic("task_irq_dispatch"); } } From 2172e5986927f59f47e04f27d876d56645b133b5 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 07:33:24 +0100 Subject: [PATCH 30/50] improve drd bringup, fix dart --- src/drivers/dart/dart.c | 12 ++----- src/drivers/usb/synopsys_drd.c | 53 +++++++++++++++++++---------- src/drivers/usb/synopsys_drd_regs.h | 8 +++-- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 61ae048a..14060e64 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -48,18 +48,10 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { dt_node_t* pnode = device->parent->node; if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { - uint32_t* regid = dt_prop(node, "reg", &len); - if (len != 4) regid = NULL; - void* val = dt_prop(node, "name", &len); - uint32_t reg_index = device->phandle - device->parent->phandle; - reg_index--; + uint32_t reg_index = 0; - if (regid) { - reg_index = *regid; - } - void* regs = hal_map_registers(device->parent, reg_index, NULL); if (!regs) { @@ -108,7 +100,7 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de if (method == DART_ENTER_BYPASS_MODE) { if (dart->dart_type == 0x8020) { - *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x10; + *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x100; return dart_service_op(svc, device, DART_FLUSH_CACHE, NULL, 0, NULL, 0); } } else if (method == DART_FLUSH_CACHE) { diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index e85b55d7..06dc769c 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -75,6 +75,20 @@ __unused static uint32_t ausb_reg_read(struct drd* drd, uint32_t offset) { #endif return rv; } +__unused static uint32_t configreg_reg_read(struct drd* drd, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(drd->configRegBase + offset); +#ifdef REG_LOG + fiprintf(stderr, "configreg_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; +} +__unused static uint32_t coreevt_reg_read(struct drd* drd, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(drd->coreEvtRegBase + offset); + #ifdef REG_LOG + fiprintf(stderr, "coreevt_reg_read(%x) = %x\n", offset, rv); + #endif + return rv; +} __unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -169,6 +183,8 @@ static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { USB_DEBUG_REG_VALUE(G_GSTS); USB_DEBUG_REG_VALUE(G_GPMSTS); USB_DEBUG_REG_VALUE(G_GUSB2PHYCFG); + USB_DEBUG_REG_VALUE(G_GEVNTADRLO(0)); + USB_DEBUG_REG_VALUE(G_GEVNTADRHI(0)); USB_DEBUG_REG_VALUE(G_GEVNTCOUNT(0)); USB_DEBUG_REG_VALUE(G_GEVNTSIZ(0)); USB_DEBUG_REG_VALUE(G_GPMSTS); @@ -299,17 +315,20 @@ static void drd_bringup(struct drd* drd) { drd_reg_and(drd, G_GUSB2PHYCFG, ~SUSPENDUSB20); drd_reg_and(drd, G_GUSB3PIPECTL, ~SUSPENDENABLE); -// ausb_reg_and(drd, AUSBC_FORCE_CLK_ON, ~0x1f); + ausb_reg_and(drd, AUSBC_FORCE_CLK_ON, ~0x1f); -// pipehandler_reg_or(drd, P_NON_SELECTED_OVERRIDE, 0x8000); + pipehandler_reg_or(drd, BLK_PIPE_HANDLER_NON_SELECTED_OVERRIDE, DUMMY_PHY_READY); pipehandler_reg_and(drd, P_AON_GENERAL_REGS, ~ATC_USB31_DRD_FORCE_CLAMP_EN); pipehandler_reg_or(drd, P_AON_GENERAL_REGS, ATC_USB31_DRD_SW_VCC_RESET); - - while (pipehandler_reg_read(drd, P_NON_SELECTED_OVERRIDE) & 0x40000000) { + + drd_reg_and(drd, G_GUSB2PHYCFG, ~SUSPENDUSB20); + drd_reg_and(drd, G_GUSB3PIPECTL, ~SUSPENDENABLE); + + while (!(configreg_reg_read(drd, USB31DRD_PIPE) & PHY_READY)) { ;; } - + drd_reg_write(drd, G_DCTL, DCTL_SOFTRESET); while (drd_reg_read(drd, G_DCTL) & DCTL_SOFTRESET) { ;; @@ -317,23 +336,17 @@ static void drd_bringup(struct drd* drd) { drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); - drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17) | (hal_get_irqno(drd->device, 0) << DCFG_INTRNUM_SHIFT)); - + drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17)); - uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; - - drd->virtBaseDMA = alloc_contig(eventc * 0x4000); + drd->virtBaseDMA = alloc_contig(0x4000); uint64_t dartBaseDMA = drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); dartBaseDMA -= 0x800000000; - - for (int i=0; i < eventc; i++) { - uint64_t eventBufferBase = dartBaseDMA + i * 0x4000; - drd_reg_write(drd, G_GEVNTADRLO(i), eventBufferBase & 0xffffffff); - drd_reg_write(drd, G_GEVNTADRHI(i), (eventBufferBase >> 32ULL) & 0xffffffff); - drd_reg_write(drd, G_GEVNTSIZ(i), 0x4000); // implicitly unmask interrupt - } - + drd_reg_write(drd, G_GEVNTADRLO(0), dartBaseDMA & 0xffffffff); + drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); + drd_reg_write(drd, G_GEVNTSIZ(0), 0x4000); + drd_reg_write(drd, G_GEVNTCOUNT(0), 0); + enable_endpoint(drd, ENDPOINT_EP0_OUT); drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); @@ -394,6 +407,10 @@ static bool register_drd(struct hal_device* device, void** context) { USB_DEBUG_PRINT_REGISTERS(drd); sleep(1); USB_DEBUG_PRINT_REGISTERS(drd); + + + cache_invalidate(drd->virtBaseDMA, 0x4000); + iprintf("evq: %x\n", *(uint32_t*)drd->virtBaseDMA); *context = drd; return true; diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index 79861130..3b1a29c8 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -40,6 +40,9 @@ #define USB2PHY_APB_RESETN 4 #define USB2PHY_SIDDQ 8 +#define BLK_PIPE_HANDLER_NON_SELECTED_OVERRIDE 0x20 +#define DUMMY_PHY_READY 0x8000 + #define AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG 8 #define VBUS_DETECT_FORCE_VAL 1 #define VBUS_DETECT_FORCE_EN 2 @@ -50,7 +53,7 @@ #define USB2PHY_REFCLK_GATEOFF 0x40000000 #define USB2PHY_APBCLK_GATEOFF 0x20000000 -#define AUSBC_C0_UTMI_CLK_ACTIVE_EVT_CNT 0x20 +#define C0_UTMI_CLK_ACTIVE_EVT_CNT 0x20 // AUSBC_CTRLREG_BLK @@ -66,9 +69,10 @@ #define P_LOCK_PIPE_IF_REQ 0x10 #define P_LOCK_PIPE_IF_ACK 0x14 #define P_AON_GENERAL_REGS 0x1c -#define P_NON_SELECTED_OVERRIDE 0x20 #define ATC_USB31_DRD_FORCE_CLAMP_EN 0x10 // bits within P_AON_GENERAL_REGS #define ATC_USB31_DRD_SW_VCC_RESET 0x1 // bits within P_AON_GENERAL_REGS +#define USB31DRD_PIPE 0x20 +#define PHY_READY 0x40000000 // Device Configuration Register #define G_DCFG 0x700 From 87a3ea93687b2e523a83422981598f9949cac97b Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 09:22:03 +0100 Subject: [PATCH 31/50] tunables --- src/drivers/dart/dart.c | 2 +- src/drivers/hal/hal.c | 78 +++++++++++++++++++++++++++++++--- src/drivers/hal/hal.h | 10 ++++- src/drivers/usb/synopsys_drd.c | 8 +++- src/kernel/lowlevel.c | 5 ++- 5 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 14060e64..40216624 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -100,7 +100,7 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de if (method == DART_ENTER_BYPASS_MODE) { if (dart->dart_type == 0x8020) { - *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x100; +// *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x100; return dart_service_op(svc, device, DART_FLUSH_CACHE, NULL, 0, NULL, 0); } } else if (method == DART_FLUSH_CACHE) { diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 00537b8b..de8af822 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -101,6 +101,13 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev ((void**)data_out)[0] = NULL; ((void**)data_out)[1] = NULL; + if (index < device->nr_device_maps && device->device_maps[index].size) { + struct device_regs * regs = &device->device_maps[index]; + ((void**)data_out)[0] = (void*)regs->base; + ((void**)data_out)[1] = (void*)regs->size; + return 0; + } + uint32_t len = 0; dt_node_t* node = device->node; if (!node) return -1; @@ -114,17 +121,35 @@ static int hal_service_op(struct hal_device_service* svc, struct hal_device* dev return -1; } - struct device_regs { - uint64_t base; - uint64_t size; - }* regs = val; + struct device_regs * regs = val; uint64_t regbase = regs[index].base; uint64_t size = regs[index].size; - ((void**)data_out)[0] = (void*)hal_map_physical_mmio(regbase, size); + void* pmap = ((void**)data_out)[0] = (void*)hal_map_physical_mmio(regbase, size); ((void**)data_out)[1] = (void*)regs[index].size; + uint32_t old_maps_size = device->nr_device_maps; + uint32_t new_maps_size = old_maps_size; + if (!new_maps_size) new_maps_size = 8; + + while (index >= new_maps_size) { + new_maps_size *= 2; + } + + if (old_maps_size != new_maps_size) { + struct device_regs * new_map_regs = calloc(sizeof(struct device_regs), new_maps_size); + if (old_maps_size) { + memcpy(new_map_regs, device->device_maps, sizeof(struct device_regs) * old_maps_size); + } + device->device_maps = new_map_regs; + device->nr_device_maps = new_maps_size; + } + + device->device_maps[index].base = (uint64_t)pmap; + device->device_maps[index].size = size; + + return 0; } else if (method == HAL_DEVICE_CLOCK_GATE_ON || method == HAL_DEVICE_CLOCK_GATE_OFF) { int32_t count = hal_get_clock_gate_size(device); @@ -164,6 +189,49 @@ uint64_t translate_register_address(uint64_t address) { return -1; } +int hal_apply_tunables(struct hal_device* device, const char* tunable_dt_entry_name) { + if (!tunable_dt_entry_name) { + tunable_dt_entry_name = "tunables"; + } + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return -1; + + struct tunable_array { + uint32_t reg_index; + uint32_t reg_offset; + uint32_t reg_bits_to_clear; + uint32_t reg_bits_to_set; + }; + + struct tunable_array* val = dt_prop(node, tunable_dt_entry_name, &len); + if (!val) { + return -1; + } + if (len & 0xf) { + panic("hal_apply_tunables: my understanding of tunables is 4x uint32_t, but len is not a multiple of 0x10..."); + } + + uint32_t tunable_cnt = len / 0x10; + for (uint32_t i=0; i < tunable_cnt; i++) { + size_t sz = 0; + uint64_t regbase = (uint64_t) hal_map_registers(device, val[i].reg_index, &sz); + if (!regbase) { + panic("hal_apply_tunables: invalid reg_index (%d)", val[i].reg_index); + } + if ((val[i].reg_offset + 4) > sz) { + panic("hal_apply_tunables: OOB access (%d > %d)", val[i].reg_offset, sz); + } + uint32_t value = *(volatile uint32_t*)(regbase + val[i].reg_offset); + + value &= ~val[i].reg_bits_to_clear; + value |= val[i].reg_bits_to_set; + + *(volatile uint32_t*)(regbase + val[i].reg_offset) = value; + } + return 0; +} + uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size) { regbase = translate_register_address(regbase); uint64_t offset = regbase & 0x3fff; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index f2cf10d6..f226de8c 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -49,7 +49,10 @@ struct hal_platform_driver { bool (*get_platform_value)(const char* name, void* value, size_t* size); void (*late_init)(); }; - +struct device_regs { + uint64_t base; + uint64_t size; +}; struct hal_device { struct hal_device* next; struct hal_device* down; @@ -58,6 +61,9 @@ struct hal_device { dt_node_t* node; struct hal_device_service* services; + struct device_regs * device_maps; + uint32_t nr_device_maps; + uint32_t phandle; uint32_t flags; }; @@ -78,7 +84,6 @@ struct hal_service { int flags; }; #define SERVICE_FLAGS_EARLY_PROBE 1 - extern void hal_register_hal_service(struct hal_service* svc); extern void hal_register_phandle_device(uint32_t phandle, struct hal_device* dev); extern struct hal_device* hal_get_phandle_device(uint32_t phandle); @@ -104,6 +109,7 @@ extern int32_t hal_get_irqno(struct hal_device* device, uint32_t index); extern uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size); extern int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index); extern int32_t hal_get_clock_gate_size(struct hal_device* device); +extern int hal_apply_tunables(struct hal_device* device, const char* tunable_dt_entry_name); #define HAL_LOAD_XNU_DTREE 0 diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 06dc769c..247f5d6f 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -263,6 +263,9 @@ static void atc_enable_device(struct drd* drd, bool enable) { reg = (atc_reg_read(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL) & ~USB_MODE_MASK) | 0; } atc_reg_write(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL, reg); + + hal_apply_tunables(drd->atc_device, "tunable-device"); + } static void atc_bringup(struct drd* drd) { atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG, VBUS_DETECT_FORCE_VAL | VBUS_DETECT_FORCE_EN | VBUS_VALID_EXT_FORCE_VAL | VBUS_VALID_EXT_FORCE_EN); @@ -311,7 +314,7 @@ static void drd_bringup(struct drd* drd) { while (pipehandler_reg_read(drd, P_LOCK_PIPE_IF_ACK) & 1) { ;; } - + drd_reg_and(drd, G_GUSB2PHYCFG, ~SUSPENDUSB20); drd_reg_and(drd, G_GUSB3PIPECTL, ~SUSPENDENABLE); @@ -335,7 +338,6 @@ static void drd_bringup(struct drd* drd) { } drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); - drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17)); drd->virtBaseDMA = alloc_contig(0x4000); @@ -351,6 +353,8 @@ static void drd_bringup(struct drd* drd) { drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); + hal_apply_tunables(drd->device, "tunables"); + drd_reg_write(drd, G_DCTL, DCTL_RUN_STOP); } diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 969beaea..3857cc15 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -490,16 +490,17 @@ __attribute__((used)) static void interrupt_and_config(uint32_t bits) { *(volatile uint32_t*)(gInterruptBase + 0x10) &= bits; } uint32_t interrupt_masking_base = 0; -void set_interrupt_affinity(uint32_t reg, uint32_t cpunr) { +void set_interrupt_affinity(uint32_t reg, uint32_t cpus) { if (reg > irq_count) { panic("set_interrupt_affinity: irqno out of bounds (%d > %d)", reg, irq_count); } - (*(volatile uint32_t *)(gInterruptBase + 0x3000 + reg * 4)) = (1 << ((reg) & 0x1F)); + (*(volatile uint32_t *)(gInterruptBase + 0x3000 + reg * 4)) = 1 << cpus; } void unmask_interrupt(uint32_t reg) { if (reg > irq_count) { panic("unmask_interrupt: irqno out of bounds (%d > %d)", reg, irq_count); } + set_interrupt_affinity(reg, 0); (*(volatile uint32_t *)(gInterruptBase + 0x4180 + ((reg >> 5) * 4))) = (1 << ((reg) & 0x1F)); } void mask_interrupt(uint32_t reg) { From 735312e0ceb577ebb4497a5c119b962c10c3e34c Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 09:25:11 +0100 Subject: [PATCH 32/50] fix irq --- src/kernel/lowlevel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 3857cc15..87c44928 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -402,7 +402,7 @@ int irq_exc() { } uint32_t intr = interrupt_vector(); while (intr) { - task_irq_dispatch(intr); + task_irq_dispatch(intr & 0xfff); intr = interrupt_vector(); } if (dis_int_count != 1) panic("IRQ handler left interrupts disabled..."); From 8f570b350e8523da8ea2696ff74e95f7fd1ebb7c Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 09:32:17 +0100 Subject: [PATCH 33/50] drd irqzzzzzz --- src/drivers/usb/synopsys_drd.c | 2 +- src/kernel/lowlevel.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 247f5d6f..4db1dfc4 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -241,7 +241,7 @@ void drd_endpoint_set_configuration(struct drd* drd, uint32_t ep, uint32_t ep_ty } static void drd_irq_handle() { - puts("drd irq"); + fiprintf(stderr, "drd irq\n"); } static void drd_irq_task() { diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 87c44928..1533db93 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -500,7 +500,6 @@ void unmask_interrupt(uint32_t reg) { if (reg > irq_count) { panic("unmask_interrupt: irqno out of bounds (%d > %d)", reg, irq_count); } - set_interrupt_affinity(reg, 0); (*(volatile uint32_t *)(gInterruptBase + 0x4180 + ((reg >> 5) * 4))) = (1 << ((reg) & 0x1F)); } void mask_interrupt(uint32_t reg) { @@ -631,9 +630,15 @@ static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, v irqvecs = calloc(irq_count, sizeof(struct task*)); irqctx = calloc(irq_count, sizeof(void*)); - interrupt_or_config(0xE0000000); - interrupt_or_config(1); // enable interrupt + disable_interrupts(); + interrupt_or_config(0xE0000000); + interrupt_or_config(1); // enable interrupts + for (int i=0; i < irq_count; i++) { + mask_interrupt(i); + set_interrupt_affinity(i, 0); + } + enable_interrupts(); return true; } else if (val && strcmp(val, "pmgr") == 0) { From 060d6f00b322d10d074c5ea59c445c87cbca90b7 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 09:34:11 +0100 Subject: [PATCH 34/50] maybe not --- src/kernel/lowlevel.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 1533db93..87c44928 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -500,6 +500,7 @@ void unmask_interrupt(uint32_t reg) { if (reg > irq_count) { panic("unmask_interrupt: irqno out of bounds (%d > %d)", reg, irq_count); } + set_interrupt_affinity(reg, 0); (*(volatile uint32_t *)(gInterruptBase + 0x4180 + ((reg >> 5) * 4))) = (1 << ((reg) & 0x1F)); } void mask_interrupt(uint32_t reg) { @@ -630,15 +631,9 @@ static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, v irqvecs = calloc(irq_count, sizeof(struct task*)); irqctx = calloc(irq_count, sizeof(void*)); - disable_interrupts(); - interrupt_or_config(0xE0000000); - interrupt_or_config(1); // enable interrupts - for (int i=0; i < irq_count; i++) { - mask_interrupt(i); - set_interrupt_affinity(i, 0); - } - enable_interrupts(); + interrupt_or_config(1); // enable interrupt + return true; } else if (val && strcmp(val, "pmgr") == 0) { From 55b21ef904eb46c0110a8750d46107576ed4654c Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 12:21:54 +0100 Subject: [PATCH 35/50] improve hal logic --- src/drivers/dart/dart.c | 25 ++++++++-- src/drivers/dart/dart.h | 3 +- src/drivers/hal/hal.c | 16 ++++++- src/drivers/hal/hal.h | 4 ++ src/drivers/usb/synopsys_drd.c | 72 ++++++++++++++++------------- src/drivers/usb/synopsys_drd_regs.h | 5 +- src/kernel/main_task.c | 7 ++- 7 files changed, 91 insertions(+), 41 deletions(-) diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 40216624..172811b1 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -30,14 +30,20 @@ struct t8020_dart { uint64_t dart_type; uint64_t dart_regbase; + uint64_t dart_flags; + uint64_t dart_bypass_base; }; +#define DART_FLAGS_MODE_MASK 3 +#define DART_FLAGS_MODE_BYPASS 1 + struct task* dart_irq_task; void dart_irq_handler() { while (1) { - // struct t8020_dart* dart = task_current_interrupt_context(); + __unused struct t8020_dart* dart = task_current_interrupt_context(); panic("DART IRQ received!"); + task_exit_irq(); } } @@ -97,10 +103,13 @@ static bool dart_probe(struct hal_service* svc, struct hal_device* device, void* static int dart_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { struct t8020_dart* dart = ((struct t8020_dart*)svc->context); - if (method == DART_ENTER_BYPASS_MODE) { if (dart->dart_type == 0x8020) { -// *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x100; + *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x100; + + dart->dart_flags &= ~DART_FLAGS_MODE_MASK; + dart->dart_flags |= DART_FLAGS_MODE_BYPASS; + return dart_service_op(svc, device, DART_FLUSH_CACHE, NULL, 0, NULL, 0); } } else if (method == DART_FLUSH_CACHE) { @@ -108,9 +117,17 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de *(volatile uint32_t*)(dart->dart_regbase + 0x34) = 0; *(volatile uint32_t*)(dart->dart_regbase + 0x20) = 0; while(*(volatile uint32_t*)(dart->dart_regbase + 0x20) & 4) {} - return 0; } + } else if (method == DART_BYPASS_CONVERT_PTR && data_in_size == 8 && data_out_size && *data_out_size == 8) { + if ((dart->dart_flags & DART_FLAGS_MODE_MASK) == DART_FLAGS_MODE_BYPASS) { + uint64_t inptr = *(uint64_t*)data_in; + + if (inptr >= dart->dart_bypass_base) { + *(uint64_t*)data_out = inptr; // - dart->dart_bypass_base; + return 0; + } + } } return -1; } diff --git a/src/drivers/dart/dart.h b/src/drivers/dart/dart.h index a200c752..9c214cd8 100644 --- a/src/drivers/dart/dart.h +++ b/src/drivers/dart/dart.h @@ -1,4 +1,3 @@ #define DART_ENTER_BYPASS_MODE 0 #define DART_FLUSH_CACHE 1 -#define DART_CLOCK_GATE_ON 2 -#define DART_CLOCK_GATE_OFF 3 +#define DART_BYPASS_CONVERT_PTR 2 diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index de8af822..bf10ebc2 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -319,8 +319,14 @@ struct hal_service hal_service = { int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { struct hal_device_service* svc = device->services; + + bool metaservice_lookup = false; + if (((method & METASERVICE_TAG_MASK) == HAL_METASERVICE_TAG)) { + metaservice_lookup = true; + } + while (svc) { - if (svc_name == svc->name || strcmp(svc_name, svc->name) == 0) { + if (strcmp(svc_name, svc->name) == 0 || metaservice_lookup) { if (svc->service->service_op) { return svc->service->service_op(svc, device, method, data_in, data_in_size, data_out, data_out_size); } @@ -329,6 +335,7 @@ int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint3 } return -0xfe; } + struct hal_service* hal_service_head; lock hal_service_lock; @@ -338,6 +345,7 @@ void hal_register_hal_service(struct hal_service* svc) { hal_service_head = svc; lock_release(&hal_service_lock); } + void hal_probe_hal_services(struct hal_device* device, bool isEarlyProbe) { lock_take(&hal_service_lock); @@ -439,6 +447,12 @@ void hal_late_probe_hal_services_cb(struct hal_device* dev, int depth) { void hal_late_probe_hal_services() { recurse_device(gDeviceTreeDevice, 0, hal_late_probe_hal_services_cb); } +void hal_issue_recursive_start_cb(struct hal_device* dev, int depth) { + hal_invoke_service_op(dev, "hal", HAL_METASERVICE_START, NULL, 0, NULL, NULL); +} +void hal_issue_recursive_start() { + recurse_device(gDeviceTreeDevice, 0, hal_issue_recursive_start_cb); +} static struct hal_device * hal_device_by_name_recursive(struct hal_device* dev, int depth, const char* name) { struct hal_device* nxt = dev->down; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index f226de8c..ee04391b 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -121,3 +121,7 @@ extern int hal_apply_tunables(struct hal_device* device, const char* tunable_dt_ #define HAL_DEVICE_CLOCK_GATE_ON 6 #define HAL_DEVICE_CLOCK_GATE_OFF 7 +#define METASERVICE_TAG_MASK 0xf0000000 + +#define HAL_METASERVICE_TAG 0x80000000 +#define HAL_METASERVICE_START (HAL_METASERVICE_TAG | 0x1) diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 4db1dfc4..1bb557bb 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -82,13 +82,6 @@ __unused static uint32_t configreg_reg_read(struct drd* drd, uint32_t offset) { #endif return rv; } -__unused static uint32_t coreevt_reg_read(struct drd* drd, uint32_t offset) { - uint32_t rv = *(volatile uint32_t *)(drd->coreEvtRegBase + offset); - #ifdef REG_LOG - fiprintf(stderr, "coreevt_reg_read(%x) = %x\n", offset, rv); - #endif - return rv; -} __unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG @@ -188,9 +181,10 @@ static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { USB_DEBUG_REG_VALUE(G_GEVNTCOUNT(0)); USB_DEBUG_REG_VALUE(G_GEVNTSIZ(0)); USB_DEBUG_REG_VALUE(G_GPMSTS); - USB_DEBUG_REG_VALUE(BUSERRADDR_LO); - USB_DEBUG_REG_VALUE(BUSERRADDR_HI); - + USB_DEBUG_REG_VALUE(G_BUSERRADDR_LO); + USB_DEBUG_REG_VALUE(G_BUSERRADDR_HI); + USB_DEBUG_REG_VALUE(G_GSBUSCFG0); + enable_interrupts(); } @@ -242,6 +236,15 @@ void drd_endpoint_set_configuration(struct drd* drd, uint32_t ep, uint32_t ep_ty static void drd_irq_handle() { fiprintf(stderr, "drd irq\n"); + struct drd* drd = task_current_interrupt_context(); + + while (1) { + uint32_t elements = drd_reg_read(drd, G_GEVNTCOUNT(0)); + if (!elements) { + break; + } + drd_reg_write(drd, G_GEVNTCOUNT(0), elements); + } } static void drd_irq_task() { @@ -340,9 +343,16 @@ static void drd_bringup(struct drd* drd) { drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17)); + drd_reg_write(drd, G_GSBUSCFG0, (1 << 6)); + drd->virtBaseDMA = alloc_contig(0x4000); - uint64_t dartBaseDMA = drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); - dartBaseDMA -= 0x800000000; + drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); + + uint64_t dartBaseDMA = 0; + size_t dartBaseDMASize = 8; + + if (hal_invoke_service_op(drd->mapper, "dart", DART_BYPASS_CONVERT_PTR, &drd->physBaseDMA, 8, &dartBaseDMA, &dartBaseDMASize)) + panic("failed to translate address to DART address"); drd_reg_write(drd, G_GEVNTADRLO(0), dartBaseDMA & 0xffffffff); drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); @@ -359,12 +369,11 @@ static void drd_bringup(struct drd* drd) { } -static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { - return -1; -} -static bool register_drd(struct hal_device* device, void** context) { +static bool register_drd(struct hal_device* device, void* context) { // DesignWare DWC3 Dual Role Device - struct drd* drd = calloc(sizeof(struct drd), 1); + + struct drd* drd = context; + drd->mapper = hal_get_mapper(device, 0); drd->device = device; @@ -381,7 +390,8 @@ static bool register_drd(struct hal_device* device, void** context) { hal_invoke_service_op(drd->atc_device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); hal_invoke_service_op(drd->device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); - hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); + if (hal_invoke_service_op(drd->mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL)) + panic("drd: could not enter bypass mode"); if (strcmp(dt_prop(device->node, "compatible", &len), "usb-drd,t8103") == 0) { drd->regBase = (uint64_t)hal_map_registers(drd->device, 2, NULL); @@ -398,27 +408,24 @@ static bool register_drd(struct hal_device* device, void** context) { drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - for (int i=0; i < 5; i++) { - task_bind_to_irq(drd->irq_task, hal_get_irqno(device, i)); - } + task_bind_to_irq(drd->irq_task, hal_get_irqno(device,0)); + interrupt_associate_context(hal_get_irqno(device,0), drd); atc_bringup(drd); drd_bringup(drd); USB_DEBUG_PRINT_REGISTERS(drd); - sleep(1); - USB_DEBUG_PRINT_REGISTERS(drd); - sleep(1); - USB_DEBUG_PRINT_REGISTERS(drd); - - cache_invalidate(drd->virtBaseDMA, 0x4000); - iprintf("evq: %x\n", *(uint32_t*)drd->virtBaseDMA); - - *context = drd; return true; } +static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == HAL_METASERVICE_START) { + register_drd(device, svc->context); + return 0; + } + return -1; +} static bool drd_probe(struct hal_service* svc, struct hal_device* device, void** context) { uint32_t len = 0; @@ -426,7 +433,10 @@ static bool drd_probe(struct hal_service* svc, struct hal_device* device, void** if (node) { void* val = dt_prop(node, "device_type", &len); if (val && strcmp(val, "usb-drd") == 0) { - return register_drd(device, context); + + *context = calloc(sizeof(struct drd), 1); + + return true; } } return false; diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index 3b1a29c8..e57c1c4a 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -202,8 +202,9 @@ #define USB_ENDPOINT_BULK 0x02 #define USB_ENDPOINT_INTERRUPT 0x03 -#define BUSERRADDR_LO 0x130 -#define BUSERRADDR_HI 0x134 +#define G_BUSERRADDR_LO 0x130 +#define G_BUSERRADDR_HI 0x134 +#define G_GSBUSCFG0 0x100 #endif diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index e2859149..3382c9e4 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -92,7 +92,7 @@ void pongo_main_task() { puts("#"); puts("#=================="); screen_mark_banner(); - + iprintf("Booted by: %s\n", dt_get_prop("chosen", "firmware-version", NULL)); strcpy(dt_get_prop("chosen", "firmware-version", NULL), "pongoOS-"); strcat(dt_get_prop("chosen", "firmware-version", NULL), PONGO_VERSION); @@ -103,5 +103,10 @@ void pongo_main_task() { #endif iprintf("Running on: %s\n", hal_platform_name()); + // start HAL device services + extern void hal_issue_recursive_start(); + + hal_issue_recursive_start(); + shell_main(); } From 92d2d5db1b7e49903cbf01a60547f84edf73fcb1 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Tue, 19 Jan 2021 21:43:02 +0100 Subject: [PATCH 36/50] HABEMUS USB --- Makefile | 2 +- src/drivers/dart/dart.c | 83 +++++++++++++++++++++++++---- src/drivers/usb/synopsys_drd.c | 23 +++++++- src/drivers/usb/synopsys_drd_regs.h | 1 + 4 files changed, 96 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index d81022ce..5734c116 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ $(BUILD)/vmacho: $(AUX)/vmacho.c | $(BUILD) $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) $(BUILD)/machopack: $(AUX)/machopack.c | $(BUILD) - $(CC) -Wall -O3 -Iapple-include -o $@ $^ $(CFLAGS) + $(CC) -Wall -O3 -o $@ $^ $(CFLAGS) $(BUILD): mkdir -p $@ diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 172811b1..3e7bb5f7 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -27,6 +27,23 @@ #import #import "dart.h" +#define DART1_ERROR_STATUS 0x0040 +#define DART1_ERROR_FLAG (1 << 30) +#define DART1_ERROR_SID_MASK (15 << 24) +#define DART1_ERROR_APF_REJECT (1 << 11) +#define DART1_ERROR_UNKNOWN (1 << 9) +#define DART1_ERROR_CTRR_WRITE_PROT (1 << 8) +#define DART1_ERROR_REGION_PROT (1 << 7) +#define DART1_ERROR_AXI_SLV_ERR (1 << 6) +#define DART1_ERROR_AXI_SLV_DECODE (1 << 5) +#define DART1_ERROR_READ_PROT (1 << 4) +#define DART1_ERROR_WRITE_PROT (1 << 3) +#define DART1_ERROR_PTE_INVLD (1 << 2) +#define DART1_ERROR_L2E_INVLD (1 << 1) +#define DART1_ERROR_TTBR_INVLD (1 << 0) +#define DART1_ERROR_ADDRESS_LO 0x0050 +#define DART1_ERROR_ADDRESS_HI 0x0054 + struct t8020_dart { uint64_t dart_type; uint64_t dart_regbase; @@ -34,6 +51,21 @@ struct t8020_dart { uint64_t dart_bypass_base; }; +__unused static uint32_t dart8020_reg_read(struct t8020_dart* dart, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(dart->dart_regbase + offset); +#ifdef REG_LOG + fiprintf(stderr, "dart8020_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; +} +__unused static void dart8020_reg_write(struct t8020_dart* dart, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "dart8020_reg_write(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(dart->dart_regbase + offset) = value; +} + + #define DART_FLAGS_MODE_MASK 3 #define DART_FLAGS_MODE_BYPASS 1 @@ -42,8 +74,24 @@ struct task* dart_irq_task; void dart_irq_handler() { while (1) { __unused struct t8020_dart* dart = task_current_interrupt_context(); - panic("DART IRQ received!"); + + uint32_t dart_error_status = dart8020_reg_read(dart, DART1_ERROR_STATUS); + uint32_t dart_error_addr_lo = dart8020_reg_read(dart, DART1_ERROR_ADDRESS_LO); + uint32_t dart_error_addr_hi = dart8020_reg_read(dart, DART1_ERROR_ADDRESS_HI); + + uint64_t dart_error_addr = dart_error_addr_lo; + dart_error_addr |= ((uint64_t)dart_error_addr_hi) << 32ULL; + for (int i=0; i < 256; i++) { + fiprintf(stderr, "%02x: %08x ", i*4, dart8020_reg_read(dart, i*4)); + if (3 == (i & 3)) { + fiprintf(stderr, "\n"); + } + } + fiprintf(stderr, "\n"); + panic("DART error! ERRSTS: %x, ERRADDR: %llx", dart_error_status, dart_error_addr); + + task_exit_irq(); } } @@ -56,7 +104,13 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { void* val = dt_prop(node, "name", &len); + uint32_t* regid = dt_prop(node, "reg", &len); + if (len != 4) regid = NULL; + uint32_t reg_index = 0; + if (regid) { + reg_index = *regid; + } void* regs = hal_map_registers(device->parent, reg_index, NULL); @@ -73,7 +127,7 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { if (dart_irq > 0) { if (!interrupt_context(dart_irq)) { if (!dart_irq_task) { - dart_irq_task = task_create_extended("dart", dart_irq_handler, TASK_IRQ_HANDLER, 0); + dart_irq_task = task_create_extended("dart", dart_irq_handler, TASK_IRQ_HANDLER, 0); // can't be preempt since we map the same task to many different IRQs, which means task_current_interrupt_context is UB } task_bind_to_irq(dart_irq_task, dart_irq); interrupt_associate_context(dart_irq, dart); @@ -100,23 +154,32 @@ static bool dart_probe(struct hal_service* svc, struct hal_device* device, void* } return false; } - +#define DART_TTBR(n) (0x200 + n*4) +#define DART_MODE(n) (0x100 + n*4) +#define DART_MODE_BYPASS(high_byte) ((high_byte << 16) | 0x100) static int dart_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { struct t8020_dart* dart = ((struct t8020_dart*)svc->context); if (method == DART_ENTER_BYPASS_MODE) { if (dart->dart_type == 0x8020) { - *(volatile uint32_t*)(dart->dart_regbase + 0x100) = 0x80000 | 0x100; + for (int i=0; i < 32; i++) { + dart8020_reg_write(dart, DART_MODE(i), DART_MODE_BYPASS(0x8)); + } + for (int i=0; i < 32; i++) { + dart8020_reg_write(dart, DART_TTBR(i), 0); + } + dart->dart_bypass_base = 0x800000000; + dart->dart_flags &= ~DART_FLAGS_MODE_MASK; - dart->dart_flags |= DART_FLAGS_MODE_BYPASS; - + dart->dart_flags |= DART_FLAGS_MODE_BYPASS; + return dart_service_op(svc, device, DART_FLUSH_CACHE, NULL, 0, NULL, 0); } } else if (method == DART_FLUSH_CACHE) { if (dart->dart_type == 0x8020) { - *(volatile uint32_t*)(dart->dart_regbase + 0x34) = 0; - *(volatile uint32_t*)(dart->dart_regbase + 0x20) = 0; - while(*(volatile uint32_t*)(dart->dart_regbase + 0x20) & 4) {} + dart8020_reg_write(dart, 0x34, 0); + dart8020_reg_write(dart, 0x20, 0); + while(dart8020_reg_read(dart, 0x20) & 4) {} return 0; } } else if (method == DART_BYPASS_CONVERT_PTR && data_in_size == 8 && data_out_size && *data_out_size == 8) { @@ -124,7 +187,7 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de uint64_t inptr = *(uint64_t*)data_in; if (inptr >= dart->dart_bypass_base) { - *(uint64_t*)data_out = inptr; // - dart->dart_bypass_base; + *(uint64_t*)data_out = inptr - dart->dart_bypass_base; return 0; } } diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 1bb557bb..34f5540f 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -89,6 +89,12 @@ __unused static void drd_reg_write(struct drd* drd, uint32_t offset, uint32_t va #endif *(volatile uint32_t *)(drd->regBase + offset) = value; } +__unused static void drd_reg_write64(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "drd_reg_write64(%x) = %x\n", offset, value); +#endif + *(volatile uint64_t *)(drd->regBase + offset) = value; +} __unused static void atc_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG fiprintf(stderr, "atc_reg_write(%x) = %x\n", offset, value); @@ -176,6 +182,7 @@ static void USB_DEBUG_PRINT_REGISTERS(struct drd* drd) { USB_DEBUG_REG_VALUE(G_GSTS); USB_DEBUG_REG_VALUE(G_GPMSTS); USB_DEBUG_REG_VALUE(G_GUSB2PHYCFG); + USB_DEBUG_REG_VALUE(G_GDBGFIFOSPACE); USB_DEBUG_REG_VALUE(G_GEVNTADRLO(0)); USB_DEBUG_REG_VALUE(G_GEVNTADRHI(0)); USB_DEBUG_REG_VALUE(G_GEVNTCOUNT(0)); @@ -354,11 +361,23 @@ static void drd_bringup(struct drd* drd) { if (hal_invoke_service_op(drd->mapper, "dart", DART_BYPASS_CONVERT_PTR, &drd->physBaseDMA, 8, &dartBaseDMA, &dartBaseDMASize)) panic("failed to translate address to DART address"); - drd_reg_write(drd, G_GEVNTADRLO(0), dartBaseDMA & 0xffffffff); - drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); + uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; + + for (uint32_t i=0; i < eventc; i++) { + drd_reg_write(drd, G_GEVNTSIZ(i), 0); + } + + drd_reg_write64(drd, G_GEVNTADRLO(0), dartBaseDMA); + //drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); drd_reg_write(drd, G_GEVNTSIZ(0), 0x4000); drd_reg_write(drd, G_GEVNTCOUNT(0), 0); + dartBaseDMA += 0x4000; + + drd_device_generic_command(drd, 4, dartBaseDMA & 0xffffffff); + drd_device_generic_command(drd, 5, (dartBaseDMA >> 32ULL) & 0xffffffff); + + enable_endpoint(drd, ENDPOINT_EP0_OUT); drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index e57c1c4a..3774a520 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -152,6 +152,7 @@ #define G_GEVNTCOUNT(n) (0x40c + 0x10 * (n)) #define GEVNTSIZ_EVNTINTRPTMASK (1 << 31) #define G_GHWPARAMS(n) (0x140 + n * 4) +#define G_GDBGFIFOSPACE 0x160 #define G_DEPCMDPAR2(n) (0x800 + 0x10 * (n)) #define G_DEPCMDPAR1(n) (0x804 + 0x10 * (n)) From 3c14f2986fae2b5db79a367b15523ccc3d2384d8 Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Tue, 19 Jan 2021 22:53:01 +0100 Subject: [PATCH 37/50] Update synopsys_drd_regs.h --- src/drivers/usb/synopsys_drd_regs.h | 45 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/drivers/usb/synopsys_drd_regs.h b/src/drivers/usb/synopsys_drd_regs.h index 3774a520..cc3bcc4e 100644 --- a/src/drivers/usb/synopsys_drd_regs.h +++ b/src/drivers/usb/synopsys_drd_regs.h @@ -1,27 +1,36 @@ /* * pongoOS - https://checkra.in * - * Copyright (C) 2019-2020 checkra1n team, Copyright (c) 2016 The Fuchsia Authors + * Copyright (C) 2019-2020 checkra1n team + * Copyright (c) 2016 The Fuchsia Authors * * This file is part of pongoOS. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ From 71c27102f16f2b41079cc4b394347e382f9d8ad0 Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Wed, 20 Jan 2021 00:52:31 +0100 Subject: [PATCH 38/50] Update LICENSE.md --- LICENSE.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index 54c95918..da15cafb 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -11,7 +11,7 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**License for USB controller drivers: src/drivers/usb/synopsys** +**License for USB controller drivers: src/drivers/usb/synopsys_otg** Apache License @@ -67,6 +67,36 @@ You may add Your own copyright statement to Your modifications and may provide a END OF TERMS AND CONDITIONS +**License for USB controller header: src/drivers/usb/synopsys_drd_regs.h** + +Copyright 2016 The Fuchsia Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **License for Apple provided components**: (apple-include, src/lib/libDER) From c71208699b68f96ff3a4b952007dbd81b2e41ec5 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Wed, 20 Jan 2021 01:50:17 +0100 Subject: [PATCH 39/50] linux load, osx module load --- linuxloader-crlm/dtree-dict.c | 195 ++++++++ linuxloader-crlm/dtree.c | 646 +++++++++++++++++++++++++++ linuxloader-crlm/dtree.h | 67 +++ linuxloader-crlm/main.c | 63 +++ linuxloader-crlm/make-pongo-image.sh | 1 + linuxloader-crlm/make.sh | 24 + linuxloader-crlm/pongo.h | 199 +++++++++ linuxloader-crlm/preboot-c.c | 106 +++++ src/boot/entry.S | 339 ++++++++++++-- src/boot/stage3.c | 27 +- src/drivers/dart/dart.c | 8 +- src/drivers/usb/synopsys_drd.c | 12 +- src/dynamic/modload.c | 12 + src/kernel/entry.c | 22 +- src/kernel/main_task.c | 1 - src/kernel/mm.c | 6 +- src/kernel/pongo.h | 7 + src/shell/autoboot.c | 2 +- src/shell/main.c | 7 - tools/machopack.c | 62 ++- 20 files changed, 1741 insertions(+), 65 deletions(-) create mode 100644 linuxloader-crlm/dtree-dict.c create mode 100644 linuxloader-crlm/dtree.c create mode 100644 linuxloader-crlm/dtree.h create mode 100644 linuxloader-crlm/main.c create mode 100755 linuxloader-crlm/make-pongo-image.sh create mode 100755 linuxloader-crlm/make.sh create mode 100644 linuxloader-crlm/pongo.h create mode 100644 linuxloader-crlm/preboot-c.c diff --git a/linuxloader-crlm/dtree-dict.c b/linuxloader-crlm/dtree-dict.c new file mode 100644 index 00000000..ee184611 --- /dev/null +++ b/linuxloader-crlm/dtree-dict.c @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * + * Copyright (C) 2017-21 Corellium LLC + * All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include "dtree.h" + +typedef struct dt_elem_s { + unsigned depth; + struct dt_elem_s *left, *right, *parent, **up; + char *str; +} dt_elem; + +struct dt_dict_s { + int size; + dt_elem *root; +}; + +dt_dict *dt_dict_new(int size) +{ + dt_dict *dict = calloc(1, sizeof(dt_dict)); + if(!dict) + return dict; + dict->size = size; + return dict; +} + +static int dt_dict_delta(dt_elem *elem) +{ + int res = 0; + if(elem->left) + res -= elem->left->depth + 1; + if(elem->right) + res += elem->right->depth + 1; + return res; +} + +static void dt_dict_update(dt_elem *elem) +{ + elem->depth = 0; + if(elem->left) + elem->depth = elem->left->depth + 1; + if(elem->right && elem->depth < elem->right->depth + 1) + elem->depth = elem->right->depth + 1; +} + +static void dt_dict_pivot(dt_elem *root, dt_elem *pivot) +{ + pivot->parent = root->parent; + pivot->up = root->up; + *(pivot->up) = pivot; + + if(pivot == root->left) { + root->left = pivot->right; + if(root->left) { + root->left->parent = root; + root->left->up = &(root->left); + } + + root->parent = pivot; + root->up = &(pivot->right); + pivot->right = root; + } else { + root->right = pivot->left; + if(root->right) { + root->right->parent = root; + root->right->up = &(root->right); + } + + root->parent = pivot; + root->up = &(pivot->left); + pivot->left = root; + } + + dt_dict_update(root); + dt_dict_update(pivot); +} + +static void dt_dict_rebalance(dt_elem *elem) +{ + int delta; + + dt_dict_update(elem); + + for(; elem; elem=elem->parent) { + delta = dt_dict_delta(elem); + if(delta < -1 || delta > 1) { + if(delta < -2 || delta > 2) + return; + + if(delta < -1) { + if(dt_dict_delta(elem->left) > 0) + dt_dict_pivot(elem->left, elem->left->right); + dt_dict_pivot(elem, elem->left); + } else { + if(dt_dict_delta(elem->right) < 0) + dt_dict_pivot(elem->right, elem->right->left); + dt_dict_pivot(elem, elem->right); + } + elem = elem->parent; + } + + if(!elem || !elem->parent) + break; + + dt_dict_update(elem->parent); + } +} + +void *dt_dict_find(dt_dict *_dict, char *str, unsigned mode) +{ + dt_dict *dict = _dict; + dt_elem **pelem = &(dict->root), *parent = NULL; + int cmp; + + while(*pelem) { + cmp = strcmp(str, (*pelem)->str); + if(!cmp) { + if(!(mode & DT_DICT_FIND)) + return NULL; + return (*pelem) + 1; + } + + parent = *pelem; + if(cmp < 0) + pelem = &(*pelem)->left; + else + pelem = &(*pelem)->right; + } + + if(!(mode & DT_DICT_ADD)) + return NULL; + + (*pelem) = calloc(1, sizeof(dt_elem) + dict->size); + if(!*pelem) + return NULL; + + (*pelem)->str = strdup(str); + (*pelem)->up = pelem; + (*pelem)->parent = parent; + + parent = *pelem; + dt_dict_rebalance(*pelem); + + return parent + 1; +} + +static void dt_dict_iter_recurse(dt_elem *elem, void(*func)(void *param, char *str, void *elem), void *param) +{ + if(elem->left) + dt_dict_iter_recurse(elem->left, func, param); + func(param, elem->str, elem + 1); + if(elem->right) + dt_dict_iter_recurse(elem->right, func, param); +} + +void dt_dict_iter(dt_dict *_dict, void(*func)(void *param, char *str, void *elem), void *param) +{ + dt_dict *dict = _dict; + if(dict->root) + dt_dict_iter_recurse(dict->root, func, param); +} + +char *dt_dict_str(void *_elem) +{ + dt_elem *elem = _elem; + return elem[-1].str; +} + +static void dt_dict_free_recurse(dt_elem *elem) +{ + if(elem->left) + dt_dict_free_recurse(elem->left); + if(elem->right) + dt_dict_free_recurse(elem->right); + free(elem->str); + free(elem); +} + +void dt_dict_free(dt_dict *_dict) +{ + dt_dict *dict = _dict; + if(dict->root) + dt_dict_free_recurse(dict->root); + free(dict); +} diff --git a/linuxloader-crlm/dtree.c b/linuxloader-crlm/dtree.c new file mode 100644 index 00000000..8aaa57cc --- /dev/null +++ b/linuxloader-crlm/dtree.c @@ -0,0 +1,646 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * + * Copyright (C) 2017-21 Corellium LLC + * All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include "dtree.h" + +#define OF_DT_HEADER 0xD00DFEED +#define OF_DT_BEGIN_NODE 0x1 +#define OF_DT_END_NODE 0x2 +#define OF_DT_PROP 0x3 +#define OF_DT_NOP 0x4 +#define OF_DT_END 0x9 + +typedef struct dt_name_s { + unsigned offset, refcount; +} dt_name; + +dtree *dt_new(void) +{ + dtree *tree = calloc(1, sizeof(dtree)); + tree->names = dt_dict_new(sizeof(dt_name)); + if(!tree->names) { + free(tree); + return NULL; + } + return tree; +} + +unsigned dt_get32be(void *ptr) +{ + unsigned char *buf = ptr; + return ((unsigned)buf[0] << 24) | ((unsigned)buf[1] << 16) | ((unsigned)buf[2] << 8) | buf[3]; +} + +void dt_put32be(void *ptr, unsigned val) +{ + unsigned char *buf = ptr; + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; +} + +unsigned long dt_get64be(void *ptr) +{ + unsigned char *buf = ptr; + return ((unsigned long)buf[0] << 56) | ((unsigned long)buf[1] << 48) | ((unsigned long)buf[2] << 40) | ((unsigned long)buf[3] << 32) | + ((unsigned long)buf[4] << 24) | ((unsigned long)buf[5] << 16) | ((unsigned long)buf[6] << 8) | buf[7]; +} + +void dt_put64be(void *ptr, unsigned long val) +{ + unsigned char *buf = ptr; + buf[0] = val >> 56; + buf[1] = val >> 48; + buf[2] = val >> 40; + buf[3] = val >> 32; + buf[4] = val >> 24; + buf[5] = val >> 16; + buf[6] = val >> 8; + buf[7] = val; +} + +static int dt_parse_dtb_node(unsigned char *data, unsigned datal, unsigned char *str, unsigned strl, dt_node **pnode, dt_node *parent, dt_dict *names) +{ + unsigned ptr, tkn, nptr; + int res; + dt_node **pchild; + dt_prop **pprop; + dt_name *pname; + + while(1) { + if(datal < 8) { + printf("[dtree] Invalid device tree binary (%d bytes left in node).\n", datal); + return -1; + } + if(dt_get32be(data) == OF_DT_NOP) { + data += 4; + datal -= 4; + continue; + } + if(dt_get32be(data) != OF_DT_BEGIN_NODE) { + printf("[dtree] Invalid device tree binary (start node token: 0x%08X).\n", dt_get32be(data)); + return -1; + } + break; + } + + ptr = 4; + while(data[ptr]) { + if(ptr >= datal - 4) { + printf("[dtree] Invalid device tree binary (unterminated node name).\n"); + return -1; + } + ptr ++; + } + ptr ++; + + *pnode = calloc(1, sizeof(dt_node)); + if(!*pnode) { + printf("[dtree] Failed to allocate node.\n"); + return -1; + } + (*pnode)->name = strdup((char *)data + 4); + (*pnode)->parent = parent; + ptr = (ptr + 3) & ~3; + pchild = &(*pnode)->child; + pprop = &(*pnode)->prop; + + while(1) { + if(datal - ptr < 4) { + printf("[dtree] Invalid device tree binary (%d bytes left in node).\n", datal - ptr); + return -1; + } + tkn = dt_get32be(data + ptr); + if(tkn == OF_DT_BEGIN_NODE) { + res = dt_parse_dtb_node(data + ptr, datal - ptr, str, strl, pchild, *pnode, names); + if(res < 0) + return res; + ptr += res; + pchild = &(*pchild)->next; + } else if(tkn == OF_DT_END_NODE) { + ptr += 4; + break; + } else if(tkn == OF_DT_PROP) { + if(datal - ptr < 12) { + printf("[dtree] Invalid device tree binary (%d bytes left in property).\n", datal - ptr); + return -1; + } + *pprop = calloc(1, sizeof(dt_prop)); + if(!*pprop) { + printf("[dtree] Failed to allocate property.\n"); + return -1; + } + (*pprop)->parent = *pnode; + (*pprop)->size = dt_get32be(data + ptr + 4); + nptr = dt_get32be(data + ptr + 8); + if(nptr >= strl || !memchr(str + nptr, 0, strl - nptr)) { + printf("[dtree] Invalid device tree binary (property name outside string block).\n"); + return -1; + } + pname = dt_dict_find(names, (char *)str + nptr, DT_DICT_ANY); + if(!pname) { + printf("[dtree] Failed to find property name '%s' in dictionary.\n", str + nptr); + return -1; + } + pname->refcount ++; + (*pprop)->name = pname; + if((*pprop)->size) { + (*pprop)->buf = malloc((*pprop)->size); + if(!(*pprop)->buf) { + printf("[dtree] Failed to allocate property data of size %d.\n", (*pprop)->size); + return -1; + } + memcpy((*pprop)->buf, data + ptr + 12, (*pprop)->size); + } + ptr += ((*pprop)->size + 15) & ~3; + pprop = &(*pprop)->next; + } else if(tkn == OF_DT_NOP) { + ptr += 4; + } else { + printf("[dtree] Invalid device tree binary (node token: 0x%08X).\n", tkn); + return -1; + } + } + + return ptr; +} + +dtree *dt_parse_dtb(void *_dtb, unsigned dtblen) +{ + unsigned char *dtb = _dtb; + dtree *tree; + unsigned totalsize, off_struct, off_string, off_memrsv, len_struct, len_string, len_memrsv; + unsigned i; + + if(dt_get32be(dtb) != OF_DT_HEADER) { + printf("[dtree] Invalid device tree binary (signature: 0x%08X).\n", dt_get32be(dtb)); + return NULL; + } + + totalsize = dt_get32be(dtb + 4); + off_struct = dt_get32be(dtb + 8); + off_string = dt_get32be(dtb + 12); + off_memrsv = dt_get32be(dtb + 16); + + if(totalsize > dtblen) { + printf("[dtree] Invalid device tree binary (length %d exceeds buffer size %d).\n", totalsize, dtblen); + return NULL; + } + + tree = dt_new(); + if(!tree) + return NULL; + + len_memrsv = totalsize - off_memrsv; + if(off_string > off_memrsv && len_memrsv > off_string - off_memrsv) + len_memrsv = off_string - off_memrsv; + if(off_struct > off_memrsv && len_memrsv > off_struct - off_memrsv) + len_memrsv = off_struct - off_memrsv; + + len_struct = totalsize - off_struct; + if(off_string > off_struct && len_struct > off_string - off_struct) + len_struct = off_string - off_struct; + if(off_memrsv > off_struct && len_struct > off_memrsv - off_struct) + len_struct = off_memrsv - off_struct; + + len_string = totalsize - off_string; + if(off_struct > off_string && len_string > off_struct - off_string) + len_string = off_struct - off_string; + if(off_memrsv > off_string && len_string > off_memrsv - off_string) + len_string = off_memrsv - off_string; + + tree->bootcpuid = dt_get32be(dtb + 28); + + len_memrsv >>= 4; + for(i=0; inmemrsv = i; + if(tree->nmemrsv) { + tree->memrsv = calloc(sizeof(struct dt_memrsv_s), tree->nmemrsv); + if(!tree->memrsv) { + dt_free(tree); + return NULL; + } + for(i=0; inmemrsv; i++) { + tree->memrsv[i].base = dt_get64be(dtb + off_memrsv + i * 16); + tree->memrsv[i].size = dt_get64be(dtb + off_memrsv + i * 16 + 8); + } + } + + if(dt_parse_dtb_node(dtb + off_struct, len_struct, dtb + off_string, len_string, &tree->root, NULL, tree->names) < 0) { + dt_free(tree); + return NULL; + } + return tree; +} + +static void dt_write_dtb_offset_func(void *_param, char *str, void *_elem) +{ + unsigned *param = _param; + dt_name *elem = _elem; + + if(!elem->refcount) { + elem->offset = 0xFFFFFFFF; + return; + } + elem->offset = *param; + *param += strlen(dt_dict_str(elem)) + 1; +} + +static void dt_write_dtb_write_func(void *_param, char *str, void *_elem) +{ + char *param = _param; + dt_name *elem = _elem; + + if(elem->offset == 0xFFFFFFFF) + return; + strcpy(param + elem->offset, dt_dict_str(elem)); +} + +static int dt_write_dtb_node(dt_node *node, unsigned char *dtb, unsigned dtbmaxlen) +{ + dt_name *name; + dt_prop *prop; + dt_node *child; + unsigned offset; + int res; + + if(!node) + return 0; + + offset = 4 + ((strlen(node->name) + 4) & ~3); + if(dtbmaxlen < offset + 4) + return -1; + + dt_put32be(dtb, OF_DT_BEGIN_NODE); + strcpy((char *) dtb + 4, node->name); + + for(prop=node->prop; prop; prop=prop->next) { + if(((prop->size + 15) & ~3) > dtbmaxlen - offset) + return -1; + name = prop->name; + if(name->offset == 0xFFFFFFFF) + return -1; + dt_put32be(dtb + offset, OF_DT_PROP); + dt_put32be(dtb + offset + 4, prop->size); + dt_put32be(dtb + offset + 8, name->offset); + if(prop->size) + memcpy(dtb + offset + 12, prop->buf, prop->size); + offset += (prop->size + 15) & ~3; + } + + for(child=node->child; child; child=child->next) { + res = dt_write_dtb_node(child, dtb + offset, dtbmaxlen - offset); + if(res < 0) + return res; + offset += (res + 3) & ~3; + } + + if(dtbmaxlen - offset < 4) + return -1; + dt_put32be(dtb + offset, OF_DT_END_NODE); + + return offset + 4; +} + +unsigned dt_write_dtb(dtree *tree, void *_dtb, unsigned dtbmaxlen) +{ + unsigned char *dtb = _dtb; + unsigned len_string = 0; + int len_struct, len_memrsv, i; + + dt_dict_iter(tree->names, dt_write_dtb_offset_func, &len_string); + len_string = (len_string + 3) & ~3; + + len_memrsv = (tree->nmemrsv + 1) * 16; + + if(dtbmaxlen < 44 + len_memrsv + len_string) + return 0; + + len_struct = dt_write_dtb_node(tree->root, dtb + 40 + len_memrsv, dtbmaxlen - len_string - 44 - len_memrsv); + if(len_struct < 0) + return -1; + dt_put32be(dtb + 40 + len_memrsv + len_struct, OF_DT_END); + len_struct += 4; + + dt_dict_iter(tree->names, dt_write_dtb_write_func, dtb + 40 + len_memrsv + len_struct); + + for(i=0; inmemrsv; i++) { + dt_put64be(dtb + 40 + 16 * i, tree->memrsv[i].base); + dt_put64be(dtb + 48 + 16 * i, tree->memrsv[i].size); + } + memset(dtb + 40 + 16 * tree->nmemrsv, 0, 16); + + dt_put32be(dtb, OF_DT_HEADER); + dt_put32be(dtb + 4, 40 + len_memrsv + len_struct + len_string); + dt_put32be(dtb + 8, 40 + len_memrsv); + dt_put32be(dtb + 12, 40 + len_memrsv + len_struct); + dt_put32be(dtb + 16, 40); + dt_put32be(dtb + 20, 17); /* version */ + dt_put32be(dtb + 24, 16); /* last compatible version */ + dt_put32be(dtb + 28, tree->bootcpuid); + dt_put32be(dtb + 32, len_string); + dt_put32be(dtb + 36, len_struct); + + return 40 + len_memrsv + len_struct + len_string; +} + +static int dt_is_string(char *str, unsigned len) +{ + unsigned cnt; + if(len < 2) + return 0; + if(str[len - 1]) + return 0; + cnt = 0; + while(len) { + if((*str < ' ' || *str > '~') && *str) + return 0; + if(*str) + cnt ++; + else if(!cnt) + return 0; + len --; + str ++; + } + return 1; +} + +dt_node *dt_find_node_idx(dtree *tree, dt_node *start, char *path, int index) +{ + char *sep; + + if(!tree) + return NULL; + + if(!start || (path && path[0] == '/')) + start = tree->root; + if(!start) + return NULL; + + if(!path) { + start = start->child; + while(start) { + if(!index) + return start; + index --; + start = start->next; + } + return NULL; + } + + if(path[0] == '/') + path ++; + + while(*path) { + sep = strchr(path, '/'); + if(!sep) + sep = path + strlen(path); + start = start->child; + while(start) { + if(!strncmp(path, start->name, sep - path) && (!start->name[sep-path] || start->name[sep-path] == '@')) { + if(!*sep) { + if(!index) + break; + index --; + } else + break; + } + start = start->next; + } + if(!start) + return NULL; + path = *sep ? sep + 1 : sep; + } + return start; +} + +dt_prop *dt_find_prop(dtree *tree, dt_node *node, char *name) +{ + void *key; + dt_prop *prop; + if(!tree || !node) + return NULL; + + key = dt_dict_find(tree->names, name, DT_DICT_FIND); + if(!key) + return NULL; + + for(prop=node->prop; prop; prop=prop->next) + if(prop->name == key) + break; + return prop; +} + +dt_node *dt_add_node(dt_node *parent, char *name) +{ + dt_node *node = calloc(1, sizeof(dt_node)), **pnode; + if(!node) + return NULL; + + node->name = strdup(name); + node->parent = parent; + for(pnode=&parent->child; *pnode; pnode=&(*pnode)->next) ; + *pnode = node; + return node; +} + +int dt_delete_node(dt_node *node) +{ + dt_node **pnode; + dt_prop *prop; + if(!node->parent) + return 1; + + for(pnode=&node->parent->child; *pnode; pnode=&(*pnode)->next) + if(*pnode == node) + break; + if(!*pnode) + return 1; + + while(node->child) + if(dt_delete_node(node->child)) + return 1; + + while(node->prop) { + prop = node->prop; + node->prop = prop->next; + ((dt_name *)prop->name)->refcount --; + free(prop->buf); + free(prop); + } + + *pnode = node->next; + free(node); + return 0; +} + +dt_prop *dt_set_prop(dtree *tree, dt_node *node, char *name, void *buf, int size) +{ + dt_name *key = dt_dict_find(tree->names, name, DT_DICT_ANY); + dt_prop **pprop; + void *nbuf; + if(!key) + return NULL; + + if(size < 0 && buf) + size = strlen(buf) + 1; + + for(pprop=&node->prop; *pprop; pprop=&(*pprop)->next) + if((*pprop)->name == key) + break; + if(!*pprop) { + *pprop = calloc(1, sizeof(dt_prop)); + (*pprop)->parent = node; + (*pprop)->name = key; + key->refcount ++; + } + + if((*pprop)->size >= size) { + if(buf) + memcpy((*pprop)->buf, buf, size); + (*pprop)->size = size; + } else { + nbuf = malloc(size); + if(!nbuf) + return NULL; + free((*pprop)->buf); + if(buf) + memcpy(nbuf, buf, size); + (*pprop)->buf = nbuf; + (*pprop)->size = size; + } + + return *pprop; +} + +int dt_delete_prop(dt_prop *prop) +{ + dt_prop **pprop; + + for(pprop=&prop->parent->prop; *pprop; pprop=&(*pprop)->next) + if(*pprop == prop) + break; + if(!*pprop) + return 1; + + ((dt_name *)prop->name)->refcount --; + free(prop->buf); + + *pprop = prop->next; + free(prop); + return 0; +} + +dt_node *dt_copy_node(dtree *tree, dt_node *parent, dt_node *source) +{ + dt_node **pnode, *iter; + dt_prop *prop; + + if(!parent || !source) + return NULL; + + for(pnode=&parent->child; *pnode; pnode=&(*pnode)->next) + if(!strcmp((*pnode)->name, source->name)) + break; + if(!*pnode) { + *pnode = calloc(1, sizeof(dt_node)); + if(!*pnode) + return NULL; + (*pnode)->name = strdup(source->name); + (*pnode)->parent = parent; + } + + for(iter=source->child; iter; iter=iter->next) + if(!dt_copy_node(tree, *pnode, iter)) + return NULL; + + for(prop=source->prop; prop; prop=prop->next) + if(!dt_set_prop(tree, *pnode, dt_dict_str(prop->name), prop->buf, prop->size)) + return NULL; + + return *pnode; +} + +static void dt_dump_node(dt_node *node, unsigned indent) +{ + dt_node *child; + dt_prop *prop; + unsigned i, v; + + printf("%*s%s {\n", indent, "", node->name[0] ? node->name : "/"); + for(prop=node->prop; prop; prop=prop->next) { + printf("%*s%s", indent + 2, "", dt_dict_str(prop->name)); + if(prop->size) { + printf(" = "); + if(!dt_is_string(prop->buf, prop->size)) { + if(prop->size & 3) { + printf("["); + for(i=0; isize; i++) + printf(" %02x", ((unsigned char *)prop->buf)[i]); + printf(" ]"); + } else { + for(i=0; isize/4; i++) { + v = dt_get32be(((unsigned char *)prop->buf) + i * 4); + printf(v >= 16 ? "%s0x%x" : "%s%d", i ? ", " : "", v); + } + } + } else + for(i=0; isize; i+=strlen(prop->buf+i)+1) + printf("%s\"%s\"", i ? ", " : "", (char *) prop->buf + i); + } + printf("\n"); + } + for(child=node->child; child; child=child->next) + dt_dump_node(child, indent + 2); + printf("%*s}\n", indent, ""); +} + +void dt_dump(dtree *tree) +{ + unsigned i; + for(i=0; inmemrsv; i++) + printf("/memreserve/ 0x%lx 0x%lx;\n", tree->memrsv[i].base, tree->memrsv[i].size); + dt_dump_node(tree->root, 0); +} + +static void dt_free_node(dt_node *node) +{ + dt_node *child; + dt_prop *prop; + + while(node->child) { + child = node->child; + node->child = child->next; + dt_free_node(child); + } + while(node->prop) { + prop = node->prop; + node->prop = prop->next; + free(prop->buf); + free(prop); + } + + free(node->name); + free(node); +} + +void dt_free(dtree *tree) +{ + dt_free_node(tree->root); + dt_dict_free(tree->names); + free(tree); +} diff --git a/linuxloader-crlm/dtree.h b/linuxloader-crlm/dtree.h new file mode 100644 index 00000000..0b34a760 --- /dev/null +++ b/linuxloader-crlm/dtree.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * + * Copyright (C) 2017-21 Corellium LLC + * All rights reserved. + * + */ + +#ifndef _DTREE_H +#define _DTREE_H + +typedef struct dt_dict_s dt_dict; + +#define DT_DICT_ADD 1 +#define DT_DICT_FIND 2 +#define DT_DICT_ANY 3 + +dt_dict *dt_dict_new(int size); +void *dt_dict_find(dt_dict *dict, char *str, unsigned mode); +void dt_dict_iter(dt_dict *dict, void(*func)(void *param, char *str, void *elem), void *param); +char *dt_dict_str(void *elem); +void dt_dict_free(dt_dict *dict); + +typedef struct dt_prop_s { + void *name; + void *buf; + unsigned size; + struct dt_prop_s *next; + struct dt_node_s *parent; +} dt_prop; + +typedef struct dt_node_s { + dt_prop *prop; + char *name; + struct dt_node_s *child, *next, *parent; +} dt_node; + +typedef struct dtree_s { + dt_dict *names; + dt_node *root; + struct dt_memrsv_s { + unsigned long base, size; + } *memrsv; + unsigned nmemrsv; + unsigned bootcpuid; +} dtree; + +dtree *dt_new(void); +dtree *dt_parse_dtb(void *dtb, unsigned dtblen); +unsigned dt_write_dtb(dtree *tree, void *dtb, unsigned dtbmaxlen); +dt_node *dt_find_node_idx(dtree *tree, dt_node *start, char *path, int index); +static inline dt_node *dt_find_node(dtree *tree, char *path) { return dt_find_node_idx(tree, (void *)0, path, 0); } +dt_prop *dt_find_prop(dtree *tree, dt_node *node, char *name); +dt_node *dt_add_node(dt_node *parent, char *name); +int dt_delete_node(dt_node *node); +dt_prop *dt_set_prop(dtree *tree, dt_node *node, char *name, void *buf, int size); +int dt_delete_prop(dt_prop *prop); +dt_node *dt_copy_node(dtree *tree, dt_node *parent, dt_node *source); +void dt_dump(dtree *tree); +void dt_free(dtree *tree); + +unsigned dt_get32be(void *ptr); +void dt_put32be(void *ptr, unsigned val); +unsigned long dt_get64be(void *ptr); +void dt_put64be(void *ptr, unsigned long val); + +#endif diff --git a/linuxloader-crlm/main.c b/linuxloader-crlm/main.c new file mode 100644 index 00000000..398ef764 --- /dev/null +++ b/linuxloader-crlm/main.c @@ -0,0 +1,63 @@ + +#import + +#define BOOT_FLAG_JUMP 5 +extern char gBootFlag; +extern uint64_t gBootJumpTo; +extern uint64_t gBootJumpArgs[4]; +extern uint64_t gBootJumpToReloc; +extern uint64_t gBootJumpToRelocSize; +extern uint64_t gBootJumpToRelocFrom; + +extern uint64_t gIORVBAR; +extern uint64_t vatophys_static(void* kva); // only safe to use with phystokva or alloc_contig's return value +extern void* alloc_contig(uint32_t size); + +extern void loader_main(void *linux_dtb, void *bootargs, uint64_t rvbar); + +extern uint8_t __linux_kernel_start[] __asm__("section$start$__LINUX$__kernel"), + __linux_kernel_end[] __asm__("section$end$__LINUX$__kernel"); +extern uint8_t __linux_dtree_start[] __asm__("section$start$__LINUX$__dtree"), + __linux_dtree_end[] __asm__("section$end$__LINUX$__dtree"); + +void module_entry() { + puts("sandcastle linux loader"); + + uint64_t linux_size = ((uint64_t)__linux_kernel_end) - ((uint64_t)__linux_kernel_start); + uint64_t dtree_size = ((uint64_t)__linux_dtree_end) - ((uint64_t)__linux_dtree_start); + + void* rregion = alloc_contig(0x80000 + linux_size); + + void* dtb_copy = rregion + 0x60000; + + memcpy(dtb_copy, __linux_dtree_start, dtree_size); + + loader_main(dtb_copy, (void*)gBootArgs, gIORVBAR); + + puts("... done, booting!"); + sleep(10); + + disable_interrupts(); + + gBootFlag = BOOT_FLAG_JUMP; + + memcpy(rregion + 0x80000, __linux_kernel_start, linux_size); + + gBootJumpToRelocFrom = vatophys_static(rregion); + gBootJumpToReloc = 0x880000000; + gBootJumpToRelocSize = 0x80000 + linux_size; + + gBootJumpArgs[0] = 0x880000000 + 0x60000; + gBootJumpArgs[1] = 0; + gBootJumpArgs[2] = 0; + gBootJumpArgs[3] = 0; + gBootJumpTo = 0x880000000 + 0x80000; + + task_yield_asserted(); +} +char* module_name = "sandcastle-loader"; + +struct pongo_exports exported_symbols[] = { + {.name = 0, .value = 0} +}; + diff --git a/linuxloader-crlm/make-pongo-image.sh b/linuxloader-crlm/make-pongo-image.sh new file mode 100755 index 00000000..b9b2d7e2 --- /dev/null +++ b/linuxloader-crlm/make-pongo-image.sh @@ -0,0 +1 @@ +../build/machopack ../build/Pongo.bin ../pongoOS.AppleSi.macho-module ./test_module diff --git a/linuxloader-crlm/make.sh b/linuxloader-crlm/make.sh new file mode 100755 index 00000000..b1162e53 --- /dev/null +++ b/linuxloader-crlm/make.sh @@ -0,0 +1,24 @@ +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# +# Copyright (c) 2019-2020 checkra1n team +# This file is part of pongoOS. +# +cd "$(dirname $0)" +xcrun -sdk iphoneos gcc main.c preboot-c.c -o test_module -arch arm64 -mabi=aapcs -Xlinker -kext -nostdlib -Xlinker -fatal_warnings -I. -D_SECURE__STRING_H_ -O3 dtree.c dtree-dict.c -sectcreate __LINUX __kernel linux.bin -sectcreate __LINUX __dtree hx.dtb diff --git a/linuxloader-crlm/pongo.h b/linuxloader-crlm/pongo.h new file mode 100644 index 00000000..98edd457 --- /dev/null +++ b/linuxloader-crlm/pongo.h @@ -0,0 +1,199 @@ +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// +// Copyright (c) 2019-2020 checkra1n team +// This file is part of pongoOS. +// + +#include +#include +#include +#include +#include + +#define DT_KEY_LEN 0x20 + +struct Boot_Video { + unsigned long v_baseAddr; /* Base address of video memory */ + unsigned long v_display; /* Display Code (if Applicable */ + unsigned long v_rowBytes; /* Number of bytes per pixel row */ + unsigned long v_width; /* Width */ + unsigned long v_height; /* Height */ + unsigned long v_depth; /* Pixel Depth and other parameters */ +}; + +typedef struct boot_args { + uint16_t Revision; /* Revision of boot_args structure */ + uint16_t Version; /* Version of boot_args structure */ + uint64_t virtBase; /* Virtual base of memory */ + uint64_t physBase; /* Physical base of memory */ + uint64_t memSize; /* Size of memory */ + uint64_t topOfKernelData; /* Highest physical address used in kernel data area */ + struct Boot_Video Video; /* Video Information */ + uint32_t machineType; /* Machine Type */ + void *deviceTreeP; /* Base of flattened device tree */ + uint32_t deviceTreeLength; /* Length of flattened tree */ + char CommandLine[256]; /* Passed in command line */ + uint64_t bootFlags; /* Additional flags specified by the bootloader */ + uint64_t memSizeActual; /* Actual size of memory */ +} boot_args; + +typedef struct +{ + uint32_t nprop; + uint32_t nchld; + char prop[]; +} dt_node_t; + +typedef struct +{ + char key[DT_KEY_LEN]; + uint32_t len; + char val[]; +} dt_prop_t; + +typedef struct +{ + const char* name; + dt_node_t* node; +} dt_find_cb_t; + +typedef struct +{ + const char* key; + void* val; + uint32_t len; +} dt_prop_cb_t; +struct memmap { + uint64_t addr; + uint64_t size; +}; + +/* Device Tree manipulation */ + +extern int dt_check(void* mem, uint32_t size, uint32_t* offp); +extern int dt_parse(dt_node_t* node, int depth, uint32_t* offp, int (*cb_node)(void*, dt_node_t*), void* cbn_arg, int (*cb_prop)(void*, dt_node_t*, int, const char*, void*, uint32_t), void* cbp_arg); +extern dt_node_t* dt_find(dt_node_t* node, const char* name); +extern void* dt_prop(dt_node_t* node, const char* key, uint32_t* lenp); +extern struct memmap* dt_alloc_memmap(dt_node_t* node, const char* name); +extern uint32_t dt_get_u32_prop(const char* device, const char* prop); +extern uint64_t dt_get_u64_prop(const char* device, const char* prop); +extern uint64_t dt_get_u64_prop_i(const char* device, const char* prop, uint32_t idx); + +/* Task management */ + +#define TASK_CAN_CRASH 1 +#define TASK_LINKED 2 +#define TASK_IRQ_HANDLER 4 +#define TASK_PREEMPT 8 +#define TASK_MASK_NEXT_IRQ 16 +#define TASK_HAS_EXITED 32 +#define TASK_WAS_LINKED 64 +#define TASK_HAS_CRASHED 128 + +struct event { + struct task* task_head; +}; + +struct task { + uint64_t x[30]; + uint64_t lr; + uint64_t sp; + uint64_t runcnt; + uint64_t real_lr; + uint64_t fp[18]; + struct task* irq_ret; + uint64_t entry; + void* task_ctx; + uint64_t stack[0x2000 / 8]; + uint64_t irq_count; + uint32_t irq_type; + uint64_t wait_until; + uint32_t sched_count; + uint32_t pid; + struct task* eq_next; + uint64_t anchor[0]; + uint64_t t_flags; + char name[32]; + uint32_t flags; + struct task* next; + struct task* prev; + void (*crash_callback)(); +}; + +extern void task_switch_irq(struct task* to_task); +extern void task_exit_irq(); +extern void task_switch(struct task* to_task); +extern void task_link(struct task* to_task); +extern void task_unlink(struct task* to_task); +extern void task_irq_dispatch(uint32_t intr); +extern void task_yield_asserted(); +extern void task_register_unlinked(struct task* task, void (*entry)()); +extern void register_irq_handler(uint16_t irq_v, struct task* irq_handler); + +/* Core functions */ + +struct pongo_exports { + const char* name; + void * value; +}; + +extern void panic(const char* string); +extern void spin(uint32_t usec); +extern uint64_t get_ticks(); +extern void usleep(uint32_t usec); +extern void sleep(uint32_t sec); +extern volatile uint8_t get_el(void); +extern void cache_invalidate(void *address, size_t size); +extern void cache_clean_and_invalidate(void *address, size_t size); +extern void clock_gate(uint64_t addr, char val); +extern void disable_preemption(); +extern void enable_preemption(); +extern void enable_interrupts(); +extern void disable_interrupts(); + + +/* Shell */ + +extern void command_putc(char val); +extern void command_puts(const char* val); +extern void command_register(const char* name, const char* desc, void (*cb)(const char* cmd, char* args)); +extern char* command_tokenize(char* str, uint32_t strbufsz); +extern void queue_rx_string(char* string); + +/* WDT */ + +extern void wdt_reset(); +extern void wdt_enable(); +extern void wdt_disable(); + +/* Global variables */ + +extern void (*preboot_hook)(); +extern boot_args * gBootArgs; +extern void* gEntryPoint; +extern dt_node_t *gDeviceTree; +extern uint64_t gIOBase; +extern uint64_t gPMGRBase; +extern char* gDevType; +extern void* ramdisk_buf; +extern uint32_t ramdisk_size; +extern uint32_t autoboot_count; +extern uint8_t * loader_xfer_recv_data; +extern uint32_t loader_xfer_recv_count; diff --git a/linuxloader-crlm/preboot-c.c b/linuxloader-crlm/preboot-c.c new file mode 100644 index 00000000..0626a761 --- /dev/null +++ b/linuxloader-crlm/preboot-c.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include + +#include "dtree.h" + +#define BOOT_LINE_LENGTH 256 +struct iphone_boot_args { + uint16_t revision; + uint16_t version; + uint64_t virt_base; + uint64_t phys_base; + uint64_t mem_size; + uint64_t top_of_kernel; + struct { + uint64_t phys, display, stride; + uint64_t width, height, depth; + } video; + uint32_t machine_type; + uint64_t dtree_virt; + uint32_t dtree_size; + char cmdline[BOOT_LINE_LENGTH]; +}; + +void loader_main(void *linux_dtb, struct iphone_boot_args *bootargs, uint64_t rvbar) +{ + dtree *linux_dt; + dt_node *node; + dt_prop *prop; + uint64_t memsize, base; + unsigned i; + + memsize = (bootargs->mem_size + 0x3ffffffful) & ~0x3ffffffful; + + printf("Starting Linux loader stub.\n"); + + linux_dt = dt_parse_dtb(linux_dtb, 0x20000); + if(!linux_dt) { + printf("Failed parsing Linux device-tree.\n"); + return; + } + + node = dt_find_node(linux_dt, "/framebuffer"); + if(node) { + prop = dt_find_prop(linux_dt, node, "reg"); + if(prop) { + dt_put64be(prop->buf, bootargs->video.phys); + dt_put64be(prop->buf + 8, (bootargs->video.height * bootargs->video.stride * 4 + 0x3FFFul) & ~0x3FFFul); + } + + prop = dt_find_prop(linux_dt, node, "width"); + if(prop) + dt_put32be(prop->buf, bootargs->video.width); + + prop = dt_find_prop(linux_dt, node, "height"); + if(prop) + dt_put32be(prop->buf, bootargs->video.height); + + prop = dt_find_prop(linux_dt, node, "stride"); + if(prop) + dt_put32be(prop->buf, bootargs->video.stride); + } + + node = dt_find_node(linux_dt, "/memory"); + if(node) { + prop = dt_find_prop(linux_dt, node, "reg"); + if(prop) + dt_put64be(prop->buf + 8, memsize); + } + + for(i=0; ; i++) { + node = dt_find_node_idx(linux_dt, NULL, "/reserved-memory/fw_area", i); + if(!node) + break; + + prop = dt_find_prop(linux_dt, node, "reg"); + if(prop) { + base = dt_get64be(prop->buf); + if(base >= 0x900000000ul) { + base += memsize - 0x200000000ul; + dt_put64be(prop->buf, base); + } + } + } + + node = dt_find_node(linux_dt, "/reserved-memory/smpentry"); + if(node) { + prop = dt_find_prop(linux_dt, node, "reg"); + if(prop) + dt_put64be(prop->buf, rvbar & ~0xfff); + } + + node = dt_find_node(linux_dt, "/soc/applestart"); + if(node) { + prop = dt_find_prop(linux_dt, node, "reg"); + if(prop) + for(i=0; isize/48; i++) + dt_put64be(prop->buf + 48 * i + 16, rvbar + 8 * i); + } + + printf("Loader complete, relocating kernel...\n"); + dt_write_dtb(linux_dt, linux_dtb, 0x20000); + dt_free(linux_dt); +} diff --git a/src/boot/entry.S b/src/boot/entry.S index 389b1458..de81fb2e 100644 --- a/src/boot/entry.S +++ b/src/boot/entry.S @@ -27,19 +27,310 @@ .globl start .align 4 start: -// branch from x27 will end up here mov x9, x8 -// branch from x29 here + b common_start // entry point for raw pongo images + +iorvbar_start: +.align 12 + b iorvbar_core_start // entry point for secondary cores + +.align 8 +macho_start: + b simple_start // entry point for macho pongo images + + +.globl _iorvbar_table +_iorvbar_table: +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 + +.align 8 +iorvbar_core_start: + dsb sy + +#if SMP_DEBUG + mrs x1, mpidr_el1 + lsr x0, x1, #14 + bfxil x0, x1, #0, #2 + and x0, x0, #7 + mov x1, #0x870 + lsl x1, x1, #24 + sub x1, x1, x0, lsl #18 + mov sp, x1 + bl smp_main +#endif + + mrs x1, mpidr_el1 + lsr x0, x1, #14 + bfxil x0, x1, #0, #2 + and x0, x0, #7 + adr x1, _iorvbar_table +2: dsb sy + ldr x2, [x1, x0, lsl #3] + tbz x2, #0, 1f + and x2, x2, #0xFFFFFFFFFC + + bl _cpuinit + + blr x2 +3: wfe + b 3b +1: wfe + b 2b + +#define SR_H13_MIGSTS s3_4_c15_c0_4 +#define SR_H13_HID0 s3_0_c15_c0_0 +#define SR_H13_HID1 s3_0_c15_c1_0 +#define SR_H13_HID3 s3_0_c15_c3_0 +#define SR_H13_HID4 s3_0_c15_c4_0 +#define SR_H13_EHID4 s3_0_c15_c4_1 +#define SR_H13_HID5 s3_0_c15_c5_0 +#define SR_H13_HID6 s3_0_c15_c6_0 +#define SR_H13_HID7 s3_0_c15_c7_0 +#define SR_H13_HID9 s3_0_c15_c9_0 +#define SR_H13_EHID10 s3_0_c15_c10_1 +#define SR_H13_HID11 s3_0_c15_c11_0 +#define SR_H13_CYC_CFG s3_5_c15_c4_0 +#define SR_H13_CYC_OVRD s3_5_c15_c5_0 +#define SR_H13_LLC_ERR_STS s3_3_c15_c8_0 +#define SR_H13_LLC_ERR_ADR s3_3_c15_c9_0 +#define SR_H13_LLC_ERR_INF s3_3_c15_c10_0 +#define SR_H13_LSU_ERR_STS s3_3_c15_c2_0 +#define SR_H13_LSU_ERR_STS_P s3_3_c15_c0_0 +#define SR_H13_FED_ERR_STS s3_4_c15_c0_2 +#define SR_H13_FED_ERR_STS_P s3_4_c15_c0_0 +#define SR_H13_MMU_ERR_STS s3_6_c15_c2_0 +#define SR_H13_MMU_ERR_STS_P s3_6_c15_c0_0 +#define SR_H13_DPC_ERR_STS s3_5_c15_c0_5 +#define SR_H13_KTRR_LOCK s3_4_c15_c2_2 +#define SR_H13_KTRR_MODE s3_4_c15_c2_5 +#define SR_H13_KTRR_LOWER s3_4_c15_c2_3 +#define SR_H13_KTRR_UPPER s3_4_c15_c2_4 + +.globl _cpuinit +_cpuinit: + msr oslar_el1, xzr + + mrs x18, midr_el1 + and x18, x18, #0xfff0 + cmp x18, #0x0220 + beq cpuinit_h13e + cmp x18, #0x0230 + beq cpuinit_h13p + + ret + +cpuinit_h13e: + msr oslar_el1, xzr + mov x0, #1 + msr s3_6_c15_c1_0, x0 + tlbi vmalle1 + ldr x0, =0x2020a505f020f0f0 + msr s3_6_c15_c1_6, x0 + msr s3_6_c15_c1_0, xzr + tlbi vmalle1 +1: mrs x0, s3_6_c15_c12_4 + tbz x0, #0, 1b + mrs x0, SR_H13_MIGSTS + bic x0, x0, #6 + orr x0, x0, #0x10 + orr x0, x0, #0x1 + msr SR_H13_MIGSTS, x0 + mrs x0, SR_H13_MIGSTS + tbnz x0, #4, 1f + orr x0, x0, #2 + msr SR_H13_MIGSTS, x0 +1: mrs x0, SR_H13_EHID4 + orr x0, x0, #0x800 + orr x0, x0, #0x100000000000 + msr SR_H13_EHID4, x0 + mrs x0, SR_H13_HID5 + orr x0, x0, #0x2000000000000000 + msr SR_H13_HID5, x0 + mrs x0, SR_H13_EHID10 + orr x0, x0, #0x100000000 + orr x0, x0, #0x2000000000000 + msr SR_H13_EHID10, x0 + mrs x0, s3_0_c15_c1_2 + orr x0, x0, #0x100 + msr s3_0_c15_c1_2, x0 + mrs x0, s3_0_c15_c9_1 + bic x0, x0, #0x20 + msr s3_0_c15_c9_1, x0 + mrs x0, s3_0_c15_c1_2 + orr x0, x0, #0x8000 + msr s3_0_c15_c1_2, x0 + mrs x0, s3_0_c15_c1_2 + orr x0, x0, #0x10000 + msr s3_0_c15_c1_2, x0 + mrs x0, s3_0_c15_c1_2 + orr x0, x0, #0x600000 + msr s3_0_c15_c1_2, x0 + mrs x0, mpidr_el1 + and x0, x0, #3 + msr s3_4_c15_c5_0, x0 + mov x0, #0x100 + msr s3_4_c15_c1_4, x0 + mrs x0, SR_H13_CYC_OVRD + bic x0, x0, #0xf00000 + msr SR_H13_CYC_OVRD, x0 + mrs x0, actlr_el1 + orr x0, x0, #0x200 /* something to do with dsb? */ + msr actlr_el1, x0 + mrs x0, SR_H13_CYC_CFG + orr x0, x0, #12 + msr SR_H13_CYC_CFG, x0 + msr SR_H13_LLC_ERR_STS, xzr + + ret + +cpuinit_h13p: + msr oslar_el1, xzr + mov x0, #1 + msr s3_6_c15_c1_0, x0 + tlbi vmalle1 + ldr x0, =0x2020a505f020f0f0 + msr s3_6_c15_c1_6, x0 + msr s3_6_c15_c1_0, xzr + tlbi vmalle1 + mrs x0, s3_0_c15_c14_0 + bic x0, x0, 0xf000000000000000 + orr x0, x0, 0xc000000000000000 + msr s3_0_c15_c14_0, x0 + mrs x0, s3_0_c15_c15_0 + orr x0, x0, 0x100000000 + msr s3_0_c15_c15_0, x0 +1: mrs x0, s3_6_c15_c12_4 + tbz x0, #0, 1b + mrs x0, SR_H13_MIGSTS + bic x0, x0, #6 + orr x0, x0, #0x10 + orr x0, x0, #0x1 + msr SR_H13_MIGSTS, x0 + mrs x0, SR_H13_MIGSTS + tbnz x0, #4, 1f + orr x0, x0, #2 + msr SR_H13_MIGSTS, x0 +1: mrs x0, SR_H13_HID4 + orr x0, x0, #0x800 + orr x0, x0, #0x100000000000 + msr SR_H13_HID4, x0 + mrs x0, SR_H13_HID5 + orr x0, x0, #0x2000000000000000 + msr SR_H13_HID5, x0 + mrs x0, s3_0_c15_c14_0 + bic x0, x0, #0x3c000 + orr x0, x0, #0x10000 + msr s3_0_c15_c14_0, x0 + mrs x0, SR_H13_HID0 + orr x0, x0, #0x200000000000 + msr SR_H13_HID0, x0 + mrs x0, SR_H13_HID3 + bic x0, x0, #0x8000000000000000 + bic x0, x0, #0x100000000000 + msr SR_H13_HID3, x0 + mrs x0, SR_H13_HID1 + orr x0, x0, #0x40000000000000 + msr SR_H13_HID1, x0 + mrs x0, s3_0_c15_c15_2 + orr x0, x0, #0x100000000000000 + orr x0, x0, #0x800000000000000 + orr x0, x0, #0x2000000000000000 + orr x0, x0, #0x4000000000000000 + msr s3_0_c15_c15_2, x0 + mrs x0, SR_H13_HID9 + orr x0, x0, #0x4000000 + msr SR_H13_HID9, x0 + mrs x0, SR_H13_HID4 + orr x0, x0, #0x30000000000 + msr SR_H13_HID4, x0 + mrs x0, SR_H13_HID11 + orr x0, x0, #0x800000000000000 + msr SR_H13_HID11, x0 + mrs x0, SR_H13_HID0 + orr x0, x0, #0x10000000 + orr x0, x0, #0x1000000000 + msr SR_H13_HID0, x0 + mrs x0, SR_H13_HID6 + bic x0, x0, #0x3e0 + msr SR_H13_HID6, x0 + mrs x0, SR_H13_HID7 + orr x0, x0, #0x100000 + orr x0, x0, #0x80000 + orr x0, x0, #0x3000000 + msr SR_H13_HID7, x0 + mrs x0, SR_H13_HID9 + orr x0, x0, #0x1000000000000 + orr x0, x0, #0x20000000 + msr SR_H13_HID9, x0 + mrs x0, s3_0_c15_c11_2 + orr x0, x0, #0x4000 + msr s3_0_c15_c11_2, x0 + mrs x0, s3_0_c15_c1_3 + bic x0, x0, #0x80000 + msr s3_0_c15_c1_3, x0 + mrs x0, SR_H13_HID4 + orr x0, x0, #0x2000000000000 + orr x0, x0, #0x20000000000000 + msr SR_H13_HID4, x0 + mrs x0, SR_H13_HID9 + orr x0, x0, #0x80000000000000 + msr SR_H13_HID9, x0 + mrs x0, SR_H13_HID11 + orr x0, x0, #0x8000 + msr SR_H13_HID11, x0 + mrs x0, SR_H13_HID1 + orr x0, x0, #0x400000000000000 + orr x0, x0, #0x1000000000000000 + msr SR_H13_HID1, x0 + mrs x0, s3_0_c15_c1_3 + orr x0, x0, #0x2000000000000 + msr s3_0_c15_c1_3, x0 + mrs x0, mpidr_el1 + and x0, x0, #3 + msr s3_4_c15_c5_0, x0 + mov x0, #0x100 + msr s3_4_c15_c1_4, x0 + mrs x0, SR_H13_CYC_OVRD + bic x0, x0, #0xf00000 + msr SR_H13_CYC_OVRD, x0 + mrs x0, actlr_el1 + orr x0, x0, #0x200 /* something to do with dsb? */ + msr actlr_el1, x0 + mrs x0, SR_H13_CYC_CFG + orr x0, x0, #12 + msr SR_H13_CYC_CFG, x0 + msr SR_H13_LLC_ERR_STS, xzr + + ret + + + + +.align 14 +common_start: adr x4, start mov x5, #0x800000000 movk x5, #0x1800, lsl#16 - and x30, x30, 0x4 - orr x30, x30, x5 cmp x4, x5 - b.eq start$l0 - add x6, x4, #0x200000 - + b.eq direct_start + mov x30, x5 + add x6, x4, #0x200000 copyloop: ldr x3, [x4], #8 @@ -47,34 +338,9 @@ copyloop: cmp x4, x6 b.ne copyloop -#ifdef AUTOBOOT - ldr x3, [x6] - mov x4, #0x800000000 - movk x4, #0x1900, lsl#16 - mov x2, #0x7561 - movk x2, #0x6f74, lsl#16 - movk x2, #0x6f62, lsl#32 - movk x2, #0x746f, lsl#48 - cmp x3, x2 - b.ne nullsub - ldr w2, [x6, #8] - add w2, w2, #16 - and w2, w2, #(~15) - -copyloop_2: - cbz w2, copyloop_3 - sub w2, w2, #16 - ldp x10,x15, [x4], #16 - stp x10,x15, [x5], #16 - b copyloop_2 -#endif -copyloop_3: -#ifdef AUTOBOOT - str xzr, [x6] -#endif ret -start$l0: +direct_start: mov x1, x0 mov x0, x9 mov x29, xzr @@ -83,6 +349,13 @@ start$l0: bl _trampoline_entry b . +simple_start: + mov x29, xzr + bl _set_exception_stack_core0 + bl _set_execution_stack_core0 + bl _simple_entry + b . + .globl _setup_el1 diff --git a/src/boot/stage3.c b/src/boot/stage3.c index 2a370843..200354df 100644 --- a/src/boot/stage3.c +++ b/src/boot/stage3.c @@ -131,11 +131,34 @@ void stage3_exit_to_el1_image(void* boot_args, void* boot_entry_point) { } jump_to_image((uint64_t)gboot_entry_point, (uint64_t)gboot_args); } +extern uint64_t __bss_start[] __asm__("section$start$__DATA$__common"), + __bss_end[] __asm__("segment$end$__DATA"); + +void simple_entry(void* boot_args) { + if (__bss_start[0] == 0x746F6F626F747561) { + uint32_t autoboot_sz = (uint32_t)(__bss_start[1]); + extern volatile void smemcpy128(void*,void*,uint32_t); + smemcpy128 ((void*)0x819000000, __bss_start, (autoboot_sz + 64)/16); + extern volatile void smemset(void*, uint8_t, uint64_t); + smemset(__bss_start, 0, autoboot_sz + 0x20); + } + + gboot_args = boot_args; + gboot_entry_point = NULL; + extern volatile void setup_el1(void * entryp,uint64_t,uint64_t); + + extern volatile void smemset(void*, uint8_t, uint64_t); + smemset(&__bss_start, 0, ((uint64_t)__bss_end) - ((uint64_t)__bss_start)); + + extern void cpuinit(); + cpuinit(); + + extern void main (void); + setup_el1(main, 0, (uint64_t)boot_args); +} void trampoline_entry(void* boot_image, void* boot_args) { - extern uint64_t __bss_start[] __asm__("section$start$__DATA$__common"), - __bss_end[] __asm__("segment$end$__DATA"); if (__bss_start[0] == 0x746F6F626F747561) { uint32_t autoboot_sz = (uint32_t)(__bss_start[1]); extern volatile void smemcpy128(void*,void*,uint32_t); diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 3e7bb5f7..5a925ecf 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -102,7 +102,7 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { dt_node_t* pnode = device->parent->node; if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { - void* val = dt_prop(node, "name", &len); + __unused void* val = dt_prop(node, "name", &len); uint32_t* regid = dt_prop(node, "reg", &len); if (len != 4) regid = NULL; @@ -115,7 +115,7 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { void* regs = hal_map_registers(device->parent, reg_index, NULL); if (!regs) { - iprintf("Couldn't map MMIO for 8020 dart-mapper: %s\n", val); + //iprintf("Couldn't map MMIO for 8020 dart-mapper: %s\n", val); return false; } @@ -134,7 +134,7 @@ static bool register_dart_mapper(struct hal_device* device, void** context) { } } - iprintf("Found 8020 dart-mapper: %s @ %llx\n", val, dart->dart_regbase); + // iprintf("Found 8020 dart-mapper: %s @ %llx\n", val, dart->dart_regbase); *context = dart; return true; @@ -171,7 +171,7 @@ static int dart_service_op(struct hal_device_service* svc, struct hal_device* de dart->dart_bypass_base = 0x800000000; dart->dart_flags &= ~DART_FLAGS_MODE_MASK; - dart->dart_flags |= DART_FLAGS_MODE_BYPASS; + dart->dart_flags |= DART_FLAGS_MODE_BYPASS; return dart_service_op(svc, device, DART_FLUSH_CACHE, NULL, 0, NULL, 0); } diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 34f5540f..83e1c1af 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -250,6 +250,16 @@ static void drd_irq_handle() { if (!elements) { break; } + + cache_invalidate(drd->virtBaseDMA, ((elements * 4) + 0x3f) & ~0x3f); + + volatile uint32_t* eventbuffer = drd->virtBaseDMA; + + for (uint32_t i = 0; i < elements; i++) { + uint32_t event = eventbuffer[0xfff - i]; + fiprintf(stderr, "drd event: %x\n", event); + } + drd_reg_write(drd, G_GEVNTCOUNT(0), elements); } } @@ -368,7 +378,7 @@ static void drd_bringup(struct drd* drd) { } drd_reg_write64(drd, G_GEVNTADRLO(0), dartBaseDMA); - //drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); + drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); drd_reg_write(drd, G_GEVNTSIZ(0), 0x4000); drd_reg_write(drd, G_GEVNTCOUNT(0), 0); diff --git a/src/dynamic/modload.c b/src/dynamic/modload.c index ba4fbe6a..863ab7e6 100644 --- a/src/dynamic/modload.c +++ b/src/dynamic/modload.c @@ -105,6 +105,9 @@ struct pongo_exports public_api[] = { EXPORT_SYMBOL(vm_allocate), EXPORT_SYMBOL(strcmp), EXPORT_SYMBOL(queue_rx_string), + EXPORT_SYMBOL(strchr), + EXPORT_SYMBOL(strdup), + EXPORT_SYMBOL(strncmp), EXPORT_SYMBOL(strlen), EXPORT_SYMBOL(strcpy), EXPORT_SYMBOL(task_create), @@ -185,7 +188,9 @@ struct pongo_exports public_api[] = { EXPORT_SYMBOL(phystokv), EXPORT_SYMBOL(free), EXPORT_SYMBOL(hexdump), + EXPORT_SYMBOL(calloc), EXPORT_SYMBOL(memcmp), + EXPORT_SYMBOL(memchr), EXPORT_SYMBOL(map_range), EXPORT_SYMBOL(linear_kvm_alloc), EXPORT_SYMBOL(vm_flush_by_addr_all_asid), @@ -218,6 +223,13 @@ struct pongo_exports public_api[] = { EXPORT_SYMBOL_P(aes), EXPORT_SYMBOL_P(_impure_ptr), EXPORT_SYMBOL_P(loader_xfer_recv_size), + EXPORT_SYMBOL_P(gIORVBAR), + EXPORT_SYMBOL_P(gBootJumpToRelocFrom), + EXPORT_SYMBOL_P(gBootJumpToRelocSize), + EXPORT_SYMBOL_P(gBootJumpToReloc), + EXPORT_SYMBOL_P(gBootJumpArgs), + EXPORT_SYMBOL_P(gBootJumpTo), + EXPORT_SYMBOL_P(gBootFlag), {.name = "___stack_chk_guard", .value = &f_stack_chk_guard}, {.name = "___stack_chk_fail", .value = &f_stack_chk_fail}, {.name = "_iprintf", .value = iprintf}, diff --git a/src/kernel/entry.c b/src/kernel/entry.c index e2c183ae..70ce0b4e 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -268,10 +268,19 @@ __attribute__((noinline)) void pongo_entry_cached() */ volatile void jump_to_image_extended(uint64_t image, uint64_t args, uint64_t original_image); extern uint64_t gPongoSlide; +uint64_t gIORVBAR; +uint64_t gBootJumpTo; +uint64_t gBootJumpArgs[4]; + +uint64_t gBootJumpToReloc; +uint64_t gBootJumpToRelocFrom; +uint64_t gBootJumpToRelocSize; void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)(void *boot_args, void *boot_entry_point)) { - + extern void iorvbar_table(); + gIORVBAR = (uint64_t) iorvbar_table; + uint64_t hcr_el2 = 0, hcr_el2_orig = 0; if (get_el() == 2) { asm volatile("mrs %0, hcr_el2" : "=r"(hcr_el2)); @@ -307,6 +316,17 @@ void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)( { linux_boot(); } + else if(gBootFlag == BOOT_FLAG_JUMP) + { + if (gBootJumpToReloc) { + screen_puts("relocating..."); + extern volatile void smemcpy128(void*,void*,uint32_t); + smemcpy128 ((void*)gBootJumpToReloc, (void*)gBootJumpToRelocFrom, gBootJumpToRelocSize/16); + screen_puts("done relocating"); + } + + ((void (*)(uint64_t,uint64_t,uint64_t,uint64_t))gBootJumpTo)(gBootJumpArgs[0], gBootJumpArgs[1], gBootJumpArgs[2], gBootJumpArgs[3]); + } else { tz_lockdown(); diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 3382c9e4..4701b093 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -82,7 +82,6 @@ void pongo_main_task() { // Set up AES aes_init(); - fb_reset_cursor(); puts(""); puts("#=================="); puts("#"); diff --git a/src/kernel/mm.c b/src/kernel/mm.c index 8d3bfd89..4db1945d 100644 --- a/src/kernel/mm.c +++ b/src/kernel/mm.c @@ -816,8 +816,10 @@ void alloc_init() { ppages = memory_size >> 14; uint64_t early_heap = early_heap_base; + early_heap = ((early_heap + 0x3fff) & (~0x3fff)); + #ifdef AUTOBOOT - uint64_t* _autoboot_block = (uint64_t*)0x419000000; + uint64_t* _autoboot_block = (uint64_t*)(kCacheableView + 0x19000000); extern uint64_t* autoboot_block; if (_autoboot_block[0] == 0x746F6F626F747561) { autoboot_block = (void*) early_heap; @@ -837,7 +839,7 @@ void alloc_init() { } alloc_static_current = alloc_static_base = (kCacheableView - 0x800000000 + gBootArgs->topOfKernelData) & (~0x3fff); - alloc_static_end = 0x417fe0000; + alloc_static_end = (kCacheableView + 0x17fe0000); uint64_t alloc_static_hardcap = alloc_static_base + (1024 * 1024 * 64); if (alloc_static_end > alloc_static_hardcap) { phys_force_free(vatophys_static((void*)alloc_static_hardcap), alloc_static_end - alloc_static_hardcap); diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 75eef952..bba5f68c 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -124,6 +124,12 @@ extern volatile char gBootFlag; #define BOOT_FLAG_HOOK 2 #define BOOT_FLAG_LINUX 3 #define BOOT_FLAG_RAW 4 +#define BOOT_FLAG_JUMP 5 +extern uint64_t gBootJumpTo; +extern uint64_t gBootJumpArgs[4]; +extern uint64_t gBootJumpToReloc; +extern uint64_t gBootJumpToRelocSize; +extern uint64_t gBootJumpToRelocFrom; #define LINUX_DTREE_SIZE 262144 #define LINUX_CMDLINE_SIZE 4096 @@ -271,6 +277,7 @@ extern void interrupt_associate_context(uint32_t irqno, void* context); extern void* interrupt_context(uint32_t irqno); extern void* task_interrupt_context(); extern void* task_current_interrupt_context(); +extern uint64_t gIORVBAR; typedef struct xnu_pf_range { uint64_t va; diff --git a/src/shell/autoboot.c b/src/shell/autoboot.c index 587e337e..99c64334 100644 --- a/src/shell/autoboot.c +++ b/src/shell/autoboot.c @@ -34,7 +34,7 @@ void pongo_autoboot() memcpy(loader_xfer_recv_data, &autoboot_block[2], (uint32_t)autoboot_block[1]); loader_xfer_recv_count = (uint32_t)autoboot_block[1]; autoboot_count = loader_xfer_recv_count; - phys_force_free(vatophys((uint64_t)autoboot_block), (autoboot_block[1] + 0x20 + 0x3fff) & ~0x3fff); + //phys_force_free(vatophys((uint64_t)autoboot_block), (autoboot_block[1] + 0x20 + 0x3fff) & ~0x3fff); queue_rx_string("modload\nautoboot\n"); } diff --git a/src/shell/main.c b/src/shell/main.c index bc08fdf5..cf96b1b3 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -293,11 +293,4 @@ void shell_main() { sleep(5); queue_rx_string("ps\n"); - -#ifdef DART_TEST - sleep(4); - struct hal_device* dev = hal_device_by_name("disp0"); - struct hal_device* mapper = hal_get_mapper(dev, 0); - hal_invoke_service_op(mapper, "dart", DART_ENTER_BYPASS_MODE, NULL, 0, NULL, NULL); -#endif } diff --git a/tools/machopack.c b/tools/machopack.c index cfda7d72..a5e04212 100644 --- a/tools/machopack.c +++ b/tools/machopack.c @@ -10,27 +10,49 @@ #include "../apple-include/mach-o/loader.h" int main(int argc, char** argv) { - if (argc != 3) { - puts("usage: machopack [in (PongoConsolidated.bin)] [out (PongoAppleSilicon)]"); + if (argc != 3 && argc != 4) { + puts("usage: machopack [in (PongoConsolidated.bin)] [out (PongoAppleSilicon)] [optional, module to autoboot]"); return -1; } int pongo = open(argv[1], O_RDONLY); if (pongo < 0) { - puts("in file could not be found!"); + puts("in file could not be opened!"); return -2; } int out = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0755); if (out < 0) { - puts("out file could not be nd!"); + puts("out file could not be opened!"); return -2; } + struct stat ms; + int module = -1; + + uint64_t pongoimgsz = 0; + uint32_t modulesize = 0; + + if (argc == 4) { + module = open(argv[3], O_RDONLY); + if (module < 0) { + puts("module file could not be opened!"); + return -3; + } + + if (fstat(module, &ms) == -1) { + perror("fstat"); + return -4; + } + + pongoimgsz += ms.st_size + 0x20; + modulesize = ms.st_size + 0x20; + } struct stat s; if (fstat(pongo, &s) == -1) { perror("fstat"); - return -3; + return -4; } + pongoimgsz += s.st_size; struct mach_header_64 mh = {0}; mh.magic = MH_MAGIC_64; @@ -47,7 +69,10 @@ int main(int argc, char** argv) { struct segment_command_64 sc; struct section_64 se[1]; } sc = {0}; -#define BASE_ADDR 0xFFFFFE0007040000 + +#define VPOFFS (0xfffffe0004000000ull - 0x800000000ull) +#define BASE_ADDR (0x818000000 + VPOFFS) + sc.sh.cmd = LC_SEGMENT_64; sc.sh.cmdsize = sizeof(struct segment_command_64); sc.sh.initprot = 1; @@ -65,8 +90,8 @@ int main(int argc, char** argv) { sc.sc.maxprot = 7; sc.sc.nsects = 1; sc.sc.fileoff = 0x4000; - sc.sc.filesize = s.st_size; - sc.sc.vmsize = s.st_size; + sc.sc.filesize = pongoimgsz; + sc.sc.vmsize = pongoimgsz + (64 * 1024 * 1024); // reserve at least 64M of kerneldata sc.sc.vmsize += 0x3fff; sc.sc.vmsize &= ~0x3fff; sc.sc.vmaddr = BASE_ADDR + 0x4000; @@ -75,13 +100,13 @@ int main(int argc, char** argv) { sc.se[0].flags = S_ATTR_SOME_INSTRUCTIONS; sc.se[0].align = 16; sc.se[0].addr = sc.sc.vmaddr; - sc.se[0].size = s.st_size; + sc.se[0].size = pongoimgsz; sc.se[0].offset = 0x4000; strcpy(sc.se[0].sectname, "__pongo"); strcpy(sc.se[0].segname, "__TEXT"); siz += sizeof(sc); - + struct __attribute__ ((packed)) __arm_thread_state64 { uint64_t x[29]; uint64_t fp; @@ -91,7 +116,7 @@ int main(int argc, char** argv) { uint32_t cpsr; uint32_t _pad; }; - + struct thread_command_arm64 { uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */ uint32_t cmdsize; /* total size of this command */ @@ -106,8 +131,7 @@ int main(int argc, char** argv) { tc.cmdsize = sizeof(tc); tc.flavor = ARM_THREAD_STATE64; tc.count = 68; - tc.s64.pc = sc.se[0].addr; - + tc.s64.pc = sc.se[0].addr + 0x1100; // pongo entrypoint for macho is at +0x1004 in order to leave space for IORVBAR siz += sizeof(tc); @@ -116,6 +140,7 @@ int main(int argc, char** argv) { write(out, &mh, sizeof(mh)); write(out, &sc, sizeof(sc)); write(out, &tc, sizeof(tc)); + lseek(out, 0x4000, SEEK_SET); char* buf = malloc(s.st_size); @@ -123,5 +148,16 @@ int main(int argc, char** argv) { write(out, buf, s.st_size); free(buf); + if (module != -1) { + uint64_t autoboot_block[2] = {0x746F6F626F747561, ms.st_size}; + + write(out, &autoboot_block, 0x10); + + char* buf = malloc(ms.st_size); + assert(ms.st_size == read(module, buf, ms.st_size)); + write(out, buf, ms.st_size); + free(buf); + } + return 0; } From 434afb2a3cab09fc52ea0afe0a41e29fbfd01b4d Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Wed, 20 Jan 2021 02:00:15 +0100 Subject: [PATCH 40/50] add crlm copyright --- src/boot/entry.S | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/boot/entry.S b/src/boot/entry.S index de81fb2e..e45372ca 100644 --- a/src/boot/entry.S +++ b/src/boot/entry.S @@ -1,7 +1,7 @@ /* * pongoOS - https://checkra.in * - * Copyright (C) 2019-2020 checkra1n team + * Copyright (C) 2019-2020 checkra1n team, Corellium LLC * * This file is part of pongoOS. * @@ -62,18 +62,6 @@ _iorvbar_table: iorvbar_core_start: dsb sy -#if SMP_DEBUG - mrs x1, mpidr_el1 - lsr x0, x1, #14 - bfxil x0, x1, #0, #2 - and x0, x0, #7 - mov x1, #0x870 - lsl x1, x1, #24 - sub x1, x1, x0, lsl #18 - mov sp, x1 - bl smp_main -#endif - mrs x1, mpidr_el1 lsr x0, x1, #14 bfxil x0, x1, #0, #2 From 23d449e876bc4915032748fffd101a77ac043e04 Mon Sep 17 00:00:00 2001 From: woachk <24752637+woachk@users.noreply.github.com> Date: Wed, 20 Jan 2021 02:08:11 +0100 Subject: [PATCH 41/50] Update entry.S --- src/boot/entry.S | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/boot/entry.S b/src/boot/entry.S index e45372ca..579838a9 100644 --- a/src/boot/entry.S +++ b/src/boot/entry.S @@ -1,29 +1,39 @@ /* * pongoOS - https://checkra.in * - * Copyright (C) 2019-2020 checkra1n team, Corellium LLC + * Copyright (c) 2019-2020 checkra1n team + * Copyright (c) 2017-2021 Corellium LLC * * This file is part of pongoOS. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the checkra1n team or Corellium LLC nor the names + * of their contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + .globl start .align 4 start: From ab70867441c421a89470391e2381873e078ed0fe Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Wed, 20 Jan 2021 03:45:44 +0100 Subject: [PATCH 42/50] linux boot frfr --- linuxloader-crlm/preboot-c.c | 4 ++- src/boot/entry.S | 44 +++++++++++++----------- src/drivers/usb/synopsys_drd.c | 61 +++++++++++++++++++++++++++++----- src/kernel/entry.c | 18 ++++++---- tools/machopack.c | 2 +- 5 files changed, 92 insertions(+), 37 deletions(-) diff --git a/linuxloader-crlm/preboot-c.c b/linuxloader-crlm/preboot-c.c index 0626a761..99ce9ecc 100644 --- a/linuxloader-crlm/preboot-c.c +++ b/linuxloader-crlm/preboot-c.c @@ -96,8 +96,10 @@ void loader_main(void *linux_dtb, struct iphone_boot_args *bootargs, uint64_t rv if(node) { prop = dt_find_prop(linux_dt, node, "reg"); if(prop) - for(i=0; isize/48; i++) + for(i=0; isize/48; i++) { + printf("RVBAR(%d) = %llx\n", i, rvbar + 8 * i); dt_put64be(prop->buf + 48 * i + 16, rvbar + 8 * i); + } } printf("Loader complete, relocating kernel...\n"); diff --git a/src/boot/entry.S b/src/boot/entry.S index e45372ca..fc71b115 100644 --- a/src/boot/entry.S +++ b/src/boot/entry.S @@ -38,26 +38,6 @@ iorvbar_start: macho_start: b simple_start // entry point for macho pongo images - -.globl _iorvbar_table -_iorvbar_table: -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 -.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 - .align 8 iorvbar_core_start: dsb sy @@ -80,6 +60,30 @@ iorvbar_core_start: 1: wfe b 2b +.align 12 + +.globl _iorvbar_table +_iorvbar_table: +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 +.long 0xDEADB070, 0xDEADB070, 0xDEADB070, 0xDEADB070 + + #define SR_H13_MIGSTS s3_4_c15_c0_4 #define SR_H13_HID0 s3_0_c15_c0_0 #define SR_H13_HID1 s3_0_c15_c1_0 diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 83e1c1af..bd99167c 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -36,7 +36,7 @@ struct drd { uint64_t ausbBulkFabricRegBase; uint64_t atcLinkRegBase; uint64_t atcRegBase; - uint64_t ausbUSB2PhyRegBase; + uint64_t atcRegBasePipe; uint64_t physBaseDMA; void* virtBaseDMA; @@ -61,6 +61,13 @@ __unused static uint32_t atc_reg_read(struct drd* drd, uint32_t offset) { #endif return rv; } +__unused static uint32_t atc3_reg_read(struct drd* drd, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(drd->atcRegBasePipe + offset); +#ifdef REG_LOG + fiprintf(stderr, "atc3_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; +} __unused static uint32_t pipehandler_reg_read(struct drd* drd, uint32_t offset) { uint32_t rv = *(volatile uint32_t *)(drd->pipeHandlerRegBase + offset); #ifdef REG_LOG @@ -101,6 +108,12 @@ __unused static void atc_reg_write(struct drd* drd, uint32_t offset, uint32_t va #endif *(volatile uint32_t *)(drd->atcRegBase + offset) = value; } +__unused static void atc3_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "atc3_reg_write(%x) = %x\n", offset, value); +#endif + *(volatile uint32_t *)(drd->atcRegBasePipe + offset) = value; +} __unused static void pipehandler_reg_write(struct drd* drd, uint32_t offset, uint32_t value) { #ifdef REG_LOG fiprintf(stderr, "pipehandler_reg_write(%x) = %x\n", offset, value); @@ -274,7 +287,7 @@ static void drd_irq_task() { } -static void atc_enable_device(struct drd* drd, bool enable) { +__unused static void atc_enable_device(struct drd* drd, bool enable) { uint32_t reg = 0; if (enable) { reg = (atc_reg_read(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL) & ~USB_MODE_MASK) | 2; @@ -287,7 +300,37 @@ static void atc_enable_device(struct drd* drd, bool enable) { hal_apply_tunables(drd->atc_device, "tunable-device"); } -static void atc_bringup(struct drd* drd) { + +__unused static void atc_enable_host(struct drd* drd, bool enable) { + uint32_t reg = 0; + if (enable) { + atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG, VBUS_DETECT_FORCE_VAL | VBUS_DETECT_FORCE_EN | VBUS_VALID_EXT_FORCE_VAL | VBUS_VALID_EXT_FORCE_EN); + spin(10 * 1000); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, ~USB2PHY_SIDDQ); + spin(10 * 1000); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, 0xFFFFFFFC); + atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG, USB2PHY_APB_RESETN); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, 0x9FFFFFFFLL); + + reg = (atc_reg_read(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL) & ~USB_MODE_MASK) | 2; + atc_reg_write(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL, reg); + + } else { + spin(5 * 1000); + reg = (atc_reg_read(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL) & ~USB_MODE_MASK) | 4; + atc_reg_write(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL, reg); + + atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, 0xb); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, 0xFFFFFFFB); + spin(10); + atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, 0x60000000LL); + + } + + hal_apply_tunables(drd->atc_device, "tunable-host"); + +} +__unused static void atc_bringup(struct drd* drd) { atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_SIG, VBUS_DETECT_FORCE_VAL | VBUS_DETECT_FORCE_EN | VBUS_VALID_EXT_FORCE_VAL | VBUS_VALID_EXT_FORCE_EN); spin(10 * 1000); atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, ~USB2PHY_SIDDQ); @@ -296,8 +339,6 @@ static void atc_bringup(struct drd* drd) { atc_reg_or(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_CTL, USB2PHY_APB_RESETN); atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, ~(USB2PHY_REFCLK_GATEOFF | USB2PHY_APBCLK_GATEOFF)); spin(30); - - atc_enable_device(drd, true); } __unused static void enable_endpoint(struct drd* drd, uint8_t index) { @@ -306,7 +347,7 @@ __unused static void enable_endpoint(struct drd* drd, uint8_t index) { drd_reg_or(drd, G_DALEPENA, 1 << index); } -static void drd_bringup(struct drd* drd) { +__unused static void drd_bringup(struct drd* drd) { uint32_t reg; pipehandler_reg_and(drd, P_PHY_MUX_SELECT, ~PIPE_CLK_EN); @@ -435,14 +476,18 @@ static bool register_drd(struct hal_device* device, void* context) { } drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); + drd->atcRegBasePipe = (uint64_t)hal_map_registers(drd->atc_device, 1, NULL); + drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); task_bind_to_irq(drd->irq_task, hal_get_irqno(device,0)); interrupt_associate_context(hal_get_irqno(device,0), drd); atc_bringup(drd); - - drd_bringup(drd); + atc_enable_host(drd, false); + + //atc_enable_device(drd, true); + //drd_bringup(drd); USB_DEBUG_PRINT_REGISTERS(drd); diff --git a/src/kernel/entry.c b/src/kernel/entry.c index 70ce0b4e..c6210890 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -236,6 +236,17 @@ __attribute__((noinline)) void pongo_entry_cached() while (gBootFlag) { + if (gBootFlag == BOOT_FLAG_JUMP) { + if (gBootJumpToReloc) { + screen_puts("relocating..."); + extern volatile void smemcpy128(void*,void*,uint32_t); + smemcpy128 ((void*)gBootJumpToReloc, (void*)gBootJumpToRelocFrom, gBootJumpToRelocSize/16); + screen_puts("done relocating"); + } + + screen_puts("Jumping to image..."); + return; + } if (gBootFlag == BOOT_FLAG_RAW) { screen_fill_basecolor(); return; @@ -318,13 +329,6 @@ void pongo_entry(uint64_t *kernel_args, void *entryp, void (*exit_to_el1_image)( } else if(gBootFlag == BOOT_FLAG_JUMP) { - if (gBootJumpToReloc) { - screen_puts("relocating..."); - extern volatile void smemcpy128(void*,void*,uint32_t); - smemcpy128 ((void*)gBootJumpToReloc, (void*)gBootJumpToRelocFrom, gBootJumpToRelocSize/16); - screen_puts("done relocating"); - } - ((void (*)(uint64_t,uint64_t,uint64_t,uint64_t))gBootJumpTo)(gBootJumpArgs[0], gBootJumpArgs[1], gBootJumpArgs[2], gBootJumpArgs[3]); } else diff --git a/tools/machopack.c b/tools/machopack.c index a5e04212..cc53b07c 100644 --- a/tools/machopack.c +++ b/tools/machopack.c @@ -91,7 +91,7 @@ int main(int argc, char** argv) { sc.sc.nsects = 1; sc.sc.fileoff = 0x4000; sc.sc.filesize = pongoimgsz; - sc.sc.vmsize = pongoimgsz + (64 * 1024 * 1024); // reserve at least 64M of kerneldata + sc.sc.vmsize = pongoimgsz + (128 * 1024 * 1024); // reserve at least 64M of kerneldata sc.sc.vmsize += 0x3fff; sc.sc.vmsize &= ~0x3fff; sc.sc.vmaddr = BASE_ADDR + 0x4000; From 46b518e7a1f2b34af14703a317ff156e7fbb6c96 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 12:36:50 +0100 Subject: [PATCH 43/50] WFI power gating, I2C starting point, HAL support for virtual service providers --- src/drivers/hal/hal.c | 16 +++--- src/drivers/hal/hal.h | 2 +- src/drivers/i2c/i2c.c | 54 ++++++++++++++++++++ src/drivers/i2c/i2c.h | 15 ++++++ src/drivers/i2c/i2c_8940x.c | 93 ++++++++++++++++++++++++++++++++++ src/drivers/i2c/i2c_8940x.h | 0 src/drivers/usb/synopsys_drd.c | 82 +++++++++++++++++------------- src/kernel/entry.c | 3 +- src/kernel/int.S | 92 ++++++++++++++++----------------- src/kernel/main_task.c | 1 + 10 files changed, 266 insertions(+), 92 deletions(-) create mode 100644 src/drivers/i2c/i2c.c create mode 100644 src/drivers/i2c/i2c.h create mode 100644 src/drivers/i2c/i2c_8940x.c create mode 100644 src/drivers/i2c/i2c_8940x.h diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index bf10ebc2..563f4d42 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -345,7 +345,14 @@ void hal_register_hal_service(struct hal_service* svc) { hal_service_head = svc; lock_release(&hal_service_lock); } - +void hal_associate_service(struct hal_device* device, struct hal_service* svc, void* ctx) { + struct hal_device_service* hds = malloc(sizeof(struct hal_device_service)); + hds->name = svc->name; + hds->service = svc; + hds->context = ctx; + hds->next = device->services; + device->services = hds; +} void hal_probe_hal_services(struct hal_device* device, bool isEarlyProbe) { lock_take(&hal_service_lock); @@ -374,12 +381,7 @@ void hal_probe_hal_services(struct hal_device* device, bool isEarlyProbe) { if (svc->probe) { void* ctx = NULL; if (svc->probe(svc, device, &ctx)) { - struct hal_device_service* hds = malloc(sizeof(struct hal_device_service)); - hds->name = svc->name; - hds->service = svc; - hds->context = ctx; - hds->next = device->services; - device->services = hds; + hal_associate_service(device, svc, ctx); } } svc = svc->next; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index ee04391b..b8782332 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -110,7 +110,7 @@ extern uint64_t hal_map_physical_mmio(uint64_t regbase, uint64_t size); extern int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index); extern int32_t hal_get_clock_gate_size(struct hal_device* device); extern int hal_apply_tunables(struct hal_device* device, const char* tunable_dt_entry_name); - +extern void hal_associate_service(struct hal_device* device, struct hal_service* svc, void* ctx); #define HAL_LOAD_XNU_DTREE 0 #define HAL_LOAD_DTREE_CHILDREN 1 diff --git a/src/drivers/i2c/i2c.c b/src/drivers/i2c/i2c.c new file mode 100644 index 00000000..81519651 --- /dev/null +++ b/src/drivers/i2c/i2c.c @@ -0,0 +1,54 @@ +/* + * pongoOS - https://checkra.in + * + * Copyright (C) 2019-2020 checkra1n team + * + * This file is part of pongoOS. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#import +#import "i2c.h" + +static bool i2c_probe(struct hal_service* svc, struct hal_device* device, void** context) { + panic("i2c_probe: i2c service is a virtual service provider that is not registered to HAL!"); + return false; +} + +static int i2c_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == HAL_METASERVICE_START) { + return 0; + } + return -1; +} + +static struct hal_service i2c_svc = { + .name = "i2c", + .probe = i2c_probe, + .service_op = i2c_service_op +}; + +bool i2c_provide_service(struct hal_device* device, struct i2c_ops* ops, void* context) { + struct i2c_ctx* ctx = calloc(sizeof(struct i2c_ctx), 1); + ctx->ops = ops; + ctx->context = context; + hal_associate_service(device, &i2c_svc, ctx); + return true; +} diff --git a/src/drivers/i2c/i2c.h b/src/drivers/i2c/i2c.h new file mode 100644 index 00000000..134e8ed5 --- /dev/null +++ b/src/drivers/i2c/i2c.h @@ -0,0 +1,15 @@ +struct i2c_8940x_ctx { + uint64_t i2c_regbase; + struct hal_device* device; +}; + +struct i2c_ops { + +}; + +struct i2c_ctx { + void* context; + struct i2c_ops* ops; +}; + +bool i2c_provide_service(struct hal_device* device, struct i2c_ops* ops, void* context); diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c new file mode 100644 index 00000000..d276cf12 --- /dev/null +++ b/src/drivers/i2c/i2c_8940x.c @@ -0,0 +1,93 @@ +#import +#import "i2c.h" + +struct i2c_ops i2c_8940x_ops; + +__unused static uint32_t i2c_8940x_reg_read(struct i2c_8940x_ctx* i2c, uint32_t offset) { + uint32_t rv = *(volatile uint32_t *)(i2c->i2c_regbase + offset); +#ifdef REG_LOG + fiprintf(stderr, "i2c_8940x_8940x_reg_read(%x) = %x\n", offset, rv); +#endif + return rv; +} + +__unused static void i2c_8940x_reg_write(struct i2c_8940x_ctx* i2c, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "i2c_8940x_8940x_reg_write(%x) = %x\n", offset, rv); +#endif + *(volatile uint32_t *)(i2c->i2c_regbase + offset) = value; +} + +__unused static void i2c_8940x_reg_or(struct i2c_8940x_ctx* i2c, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "i2c_8940x_reg_or(%x) = %x\n", offset, rv); +#endif + *(volatile uint32_t *)(i2c->i2c_regbase + offset) |= value; +} + +__unused static void i2c_8940x_reg_and(struct i2c_8940x_ctx* i2c, uint32_t offset, uint32_t value) { +#ifdef REG_LOG + fiprintf(stderr, "i2c_8940x_reg_and(%x) = %x\n", offset, rv); +#endif + *(volatile uint32_t *)(i2c->i2c_regbase + offset) &= value; +} + +static bool register_8940x_i2c(struct hal_device* device, void* context) { + // S5L8940x I2C controller + dt_node_t* node = device->node; + + uint32_t len = 0; + void* name = dt_prop(node, "name", &len); + + fiprintf(stderr, "S5L8940xI2C device found: %s\n", name); + + struct i2c_8940x_ctx* i2c = context; + + i2c->device = device; + i2c->i2c_regbase = (uint64_t)hal_map_registers(i2c->device, 0, NULL); + + return true; +} + +static int i2c_8940x_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == HAL_METASERVICE_START) { + return 0; + } + return -1; +} + +static bool i2c_8940x_probe(struct hal_service* svc, struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (node) { + void* val = dt_prop(node, "device_type", &len); + if (val && strcmp(val, "i2c") == 0) { + char* compat = dt_prop(node, "compatible", &len); + char* compatend = compat + len; + + while (compat < compatend) { + if (strcmp(compat, "i2c,s5l8940x") == 0) { + *context = calloc(sizeof(struct i2c_8940x_ctx), 1); + if (register_8940x_i2c(device, *context)) { + return i2c_provide_service(device, &i2c_8940x_ops, *context); + } + return false; + } + compat += strlen(compat) + 1; + } + } + } + return false; +} + +static struct hal_service i2c_8940x_svc = { + .name = "i2c8940x", + .probe = i2c_8940x_probe, + .service_op = i2c_8940x_service_op +}; + +static void i2c_8940x_init(struct driver* driver) { + hal_register_hal_service(&i2c_8940x_svc); +} + +REGISTER_DRIVER(i2c_8940x, i2c_8940x_init, NULL, 0); diff --git a/src/drivers/i2c/i2c_8940x.h b/src/drivers/i2c/i2c_8940x.h new file mode 100644 index 00000000..e69de29b diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index bd99167c..e5f48aad 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -286,6 +286,7 @@ static void drd_irq_task() { } } +bool is_in_host_mode = false; // default value __unused static void atc_enable_device(struct drd* drd, bool enable) { uint32_t reg = 0; @@ -298,7 +299,7 @@ __unused static void atc_enable_device(struct drd* drd, bool enable) { atc_reg_write(drd, AUSBC_CFG_USB2PHY_BLK_USB_CTL, reg); hal_apply_tunables(drd->atc_device, "tunable-device"); - + is_in_host_mode = false; } __unused static void atc_enable_host(struct drd* drd, bool enable) { @@ -326,7 +327,8 @@ __unused static void atc_enable_host(struct drd* drd, bool enable) { atc_reg_and(drd, AUSBC_CFG_USB2PHY_BLK_USB2PHY_MISC_TUNE, 0x60000000LL); } - + is_in_host_mode = true; + hal_apply_tunables(drd->atc_device, "tunable-host"); } @@ -398,44 +400,49 @@ __unused static void drd_bringup(struct drd* drd) { ;; } - drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); - drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17)); + if (is_in_host_mode) { + hal_apply_tunables(drd->device, "tunables"); + atc_enable_host(drd, true); + } else { + drd_reg_write(drd, G_GCTL, GCTL_DSBLCLKGTNG | GCTL_PRTCAPDIR(true) | GCTL_PWRDNSCALE(2)); + drd_reg_write(drd, G_DCFG, DCFG_HIGH_SPEED | (8 << 17)); - drd_reg_write(drd, G_GSBUSCFG0, (1 << 6)); - - drd->virtBaseDMA = alloc_contig(0x4000); - drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); - - uint64_t dartBaseDMA = 0; - size_t dartBaseDMASize = 8; - - if (hal_invoke_service_op(drd->mapper, "dart", DART_BYPASS_CONVERT_PTR, &drd->physBaseDMA, 8, &dartBaseDMA, &dartBaseDMASize)) - panic("failed to translate address to DART address"); - - uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; + drd_reg_write(drd, G_GSBUSCFG0, (1 << 6)); + + drd->virtBaseDMA = alloc_contig(0x4000); + drd->physBaseDMA = vatophys_static((void*)drd->virtBaseDMA); + + uint64_t dartBaseDMA = 0; + size_t dartBaseDMASize = 8; + + if (hal_invoke_service_op(drd->mapper, "dart", DART_BYPASS_CONVERT_PTR, &drd->physBaseDMA, 8, &dartBaseDMA, &dartBaseDMASize)) + panic("failed to translate address to DART address"); + + uint32_t eventc = (drd_reg_read(drd, G_GHWPARAMS(1)) >> 15) & 0x3f; - for (uint32_t i=0; i < eventc; i++) { - drd_reg_write(drd, G_GEVNTSIZ(i), 0); - } - - drd_reg_write64(drd, G_GEVNTADRLO(0), dartBaseDMA); - drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); - drd_reg_write(drd, G_GEVNTSIZ(0), 0x4000); - drd_reg_write(drd, G_GEVNTCOUNT(0), 0); + for (uint32_t i=0; i < eventc; i++) { + drd_reg_write(drd, G_GEVNTSIZ(i), 0); + } + + drd_reg_write64(drd, G_GEVNTADRLO(0), dartBaseDMA); + drd_reg_write(drd, G_GEVNTADRHI(0), (dartBaseDMA >> 32ULL) & 0xffffffff); + drd_reg_write(drd, G_GEVNTSIZ(0), 0x4000); + drd_reg_write(drd, G_GEVNTCOUNT(0), 0); - dartBaseDMA += 0x4000; - - drd_device_generic_command(drd, 4, dartBaseDMA & 0xffffffff); - drd_device_generic_command(drd, 5, (dartBaseDMA >> 32ULL) & 0xffffffff); + dartBaseDMA += 0x4000; + + drd_device_generic_command(drd, 4, dartBaseDMA & 0xffffffff); + drd_device_generic_command(drd, 5, (dartBaseDMA >> 32ULL) & 0xffffffff); - - enable_endpoint(drd, ENDPOINT_EP0_OUT); + + enable_endpoint(drd, ENDPOINT_EP0_OUT); - drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); + drd_reg_or(drd, G_DEVTEN, DEVTEN_USBRSTEVTEN|DEVTEN_DISSCONNEVTEN|DEVTEN_CONNECTDONEEVTEN|DEVTEN_ULSTCNGEN|DEVTEN_WKUPEVTEN|DEVTEN_ERRTICERREVTEN|DEVTEN_VENDEVTSTRCVDEN); - hal_apply_tunables(drd->device, "tunables"); + hal_apply_tunables(drd->device, "tunables"); - drd_reg_write(drd, G_DCTL, DCTL_RUN_STOP); + drd_reg_write(drd, G_DCTL, DCTL_RUN_STOP); + } } @@ -484,10 +491,13 @@ static bool register_drd(struct hal_device* device, void* context) { interrupt_associate_context(hal_get_irqno(device,0), drd); atc_bringup(drd); - atc_enable_host(drd, false); + if (is_in_host_mode) { + atc_enable_host(drd, true); + } else { + atc_enable_device(drd, true); + } - //atc_enable_device(drd, true); - //drd_bringup(drd); + drd_bringup(drd); USB_DEBUG_PRINT_REGISTERS(drd); diff --git a/src/kernel/entry.c b/src/kernel/entry.c index c6210890..18009983 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -119,6 +119,7 @@ char pongo_sched_tick() { char soc_name[9] = {}; uint32_t socnum = 0x0; void (*sep_boot_hook)(void); +extern void quiesce_core(); __attribute__((noinline)) void pongo_entry_cached() { @@ -226,7 +227,7 @@ __attribute__((noinline)) void pongo_entry_cached() // current task was not to be scheduled or we got volountarily yielded } if (should_wfe) { - __asm__("wfe"); + quiesce_core(); } } timer_disable(); diff --git a/src/kernel/int.S b/src/kernel/int.S index d04708e9..60981e91 100644 --- a/src/kernel/int.S +++ b/src/kernel/int.S @@ -781,51 +781,49 @@ _set_timer_ctr: isb ret -#if 0 -.globl _set_l2c_err_sts -.globl _get_l2c_err_sts -.globl _set_l2c_err_adr -.globl _get_l2c_err_adr -.globl _set_l2c_err_inf -.globl _get_l2c_err_inf -.globl _set_lsu_err_sts -.globl _get_lsu_err_sts - -// TODO: this is whack, and some were probably copied wrong... -_set_l2c_err_sts: - .long 0xd51bf800 - isb sy - ret -_get_l2c_err_sts: - .long 0xd53bf800 - isb sy - ret -_set_l2c_err_adr: - .long 0xd51bf000 - isb sy - ret -_get_l2c_err_adr: - .long 0xd53bf900 - isb sy - ret -_set_l2c_err_inf: - .long 0xd51bf000 - isb sy - ret -_get_l2c_err_inf: - .long 0xd53bf900 - isb sy - ret -set_lsu_err_sts: - .long 0xd51bf000 - isb sy - ret -get_lsu_err_sts: - .long 0xd53bf000 - isb sy +.global _quiesce_core +_quiesce_core: + sub sp, sp, #0x120 + + stp x10, x11, [sp] + stp x12, x13, [sp,#0x10] + stp x14, x15, [sp,#0x20] + + stp x18, x19, [sp,#0x30] + stp x20, x21, [sp,#0x40] + stp x22, x23, [sp,#0x50] + stp x24, x25, [sp,#0x60] + stp x26, x27, [sp,#0x70] + stp x28, x29, [sp,#0x80] + stp x30, x1, [sp, #0x90] + + stp d8, d9, [sp,#0xa0] + stp d10, d11, [sp,#0xc0] + stp d12, d13, [sp,#0xe0] + stp d14, d15, [sp,#0x100] + + wfi + cmp x30, xzr + b.ne 1f // no need to restore registers since we didn't lose state. + + + ldp x10, x11, [sp] + ldp x12, x13, [sp,#0x10] + ldp x14, x15, [sp,#0x20] + + ldp x18, x19, [sp,#0x30] + ldp x20, x21, [sp,#0x40] + ldp x22, x23, [sp,#0x50] + ldp x24, x25, [sp,#0x60] + ldp x26, x27, [sp,#0x70] + ldp x28, x29, [sp,#0x80] + ldp x30, x1, [sp, #0x90] + + ldp d8, d9, [sp,#0xa0] + ldp d10, d11, [sp,#0xc0] + ldp d12, d13, [sp,#0xe0] + ldp d14, d15, [sp,#0x100] + +1: + add sp, sp, #0x120 ret -.align 3 -spsel_err: -.ascii "task_switch/load called on exception stack" -.align 3 -#endif diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 4701b093..3382c9e4 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -82,6 +82,7 @@ void pongo_main_task() { // Set up AES aes_init(); + fb_reset_cursor(); puts(""); puts("#=================="); puts("#"); From 8cf5e72a4494912d7e6b525ab20f243322d12838 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 18:04:12 +0100 Subject: [PATCH 44/50] add 8940x I2C driver for pongo --- src/drivers/hal/hal.h | 3 + src/drivers/i2c/i2c.c | 1 + src/drivers/i2c/i2c.h | 41 +++++++- src/drivers/i2c/i2c_8940x.c | 182 ++++++++++++++++++++++++++++++--- src/drivers/usb/synopsys_drd.c | 2 +- src/kernel/main_task.c | 2 +- 6 files changed, 212 insertions(+), 19 deletions(-) diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index b8782332..3ec16d69 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -66,6 +66,8 @@ struct hal_device { uint32_t phandle; uint32_t flags; + + struct hal_service* ioprovider; }; #define DEVICE_HAS_BEEN_PROBED_EARLY 1 @@ -111,6 +113,7 @@ extern int32_t hal_get_clock_gate_id(struct hal_device* device, uint32_t index); extern int32_t hal_get_clock_gate_size(struct hal_device* device); extern int hal_apply_tunables(struct hal_device* device, const char* tunable_dt_entry_name); extern void hal_associate_service(struct hal_device* device, struct hal_service* svc, void* ctx); +extern void hal_device_set_io_provider(struct hal_device* device, struct hal_service* svc); #define HAL_LOAD_XNU_DTREE 0 #define HAL_LOAD_DTREE_CHILDREN 1 diff --git a/src/drivers/i2c/i2c.c b/src/drivers/i2c/i2c.c index 81519651..11721335 100644 --- a/src/drivers/i2c/i2c.c +++ b/src/drivers/i2c/i2c.c @@ -52,3 +52,4 @@ bool i2c_provide_service(struct hal_device* device, struct i2c_ops* ops, void* c hal_associate_service(device, &i2c_svc, ctx); return true; } + diff --git a/src/drivers/i2c/i2c.h b/src/drivers/i2c/i2c.h index 134e8ed5..277c4c75 100644 --- a/src/drivers/i2c/i2c.h +++ b/src/drivers/i2c/i2c.h @@ -1,10 +1,43 @@ -struct i2c_8940x_ctx { - uint64_t i2c_regbase; - struct hal_device* device; +struct i2c_ctx; + +struct i2c_tx { + void* buf; + uint16_t size; + uint16_t addr; + bool readwrite; // true = write, false = read }; -struct i2c_ops { +struct i2c_cmd { + uint16_t txno; + struct i2c_tx txes[]; +}; + +inline static struct i2c_cmd* i2c_cmd_create(uint16_t txno) { + struct i2c_cmd* cmd = calloc(sizeof(struct i2c_cmd) + sizeof(struct i2c_tx) * txno, 1); + cmd->txno = txno; + return cmd; +} +inline static void i2c_cmd_destroy(struct i2c_cmd* cmd) { + free(cmd); +} + +inline static void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { + cmd->txes[index].buf = base; + cmd->txes[index].size = size; + cmd->txes[index].addr = address; + cmd->txes[index].readwrite = true; +} + +inline static void i2c_cmd_set_read_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { + cmd->txes[index].buf = base; + cmd->txes[index].size = size; + cmd->txes[index].addr = address; + cmd->txes[index].readwrite = false; +} + +struct i2c_ops { + bool (*i2c_command_perform)(struct i2c_ctx* ctx, struct i2c_cmd* cmd); }; struct i2c_ctx { diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c index d276cf12..987d69bd 100644 --- a/src/drivers/i2c/i2c_8940x.c +++ b/src/drivers/i2c/i2c_8940x.c @@ -1,7 +1,20 @@ #import #import "i2c.h" -struct i2c_ops i2c_8940x_ops; + +struct i2c_8940x_ctx { + uint64_t i2c_regbase; + struct hal_device* device; + lock i2c_lock; + + uint8_t* data_in; + uint16_t data_in_size; + + struct event irq_event; + struct task* irq_task; + + uint32_t rdreg; +}; __unused static uint32_t i2c_8940x_reg_read(struct i2c_8940x_ctx* i2c, uint32_t offset) { uint32_t rv = *(volatile uint32_t *)(i2c->i2c_regbase + offset); @@ -25,32 +38,176 @@ __unused static void i2c_8940x_reg_or(struct i2c_8940x_ctx* i2c, uint32_t offset *(volatile uint32_t *)(i2c->i2c_regbase + offset) |= value; } -__unused static void i2c_8940x_reg_and(struct i2c_8940x_ctx* i2c, uint32_t offset, uint32_t value) { -#ifdef REG_LOG - fiprintf(stderr, "i2c_8940x_reg_and(%x) = %x\n", offset, rv); -#endif - *(volatile uint32_t *)(i2c->i2c_regbase + offset) &= value; +static void i2c_8940x_init_regs(struct i2c_ctx* ctx) { + struct i2c_8940x_ctx* i2c = ctx->context; + + i2c_8940x_reg_write(i2c, 0x1c, 4); + i2c_8940x_reg_write(i2c, 0x14, 0xAA00040); + i2c_8940x_reg_write(i2c, 0x18, 0); + i2c_8940x_reg_write(i2c, 0x10, 0x80000000); + + uint32_t hwrev = i2c_8940x_reg_read(i2c, 0x28); + if (hwrev >= 6) { + i2c_8940x_reg_or(i2c, 0x1c, 0x800); + } + + /* + TBD: filter-tunable and tbuf-tunable impl + */ +} + +__unused static void i2c_8940x_lockunlock(struct i2c_8940x_ctx* i2c, bool lockunlock) { + if (lockunlock) { + i2c_8940x_reg_write(i2c, 0x44, 1); + } else { + i2c_8940x_reg_write(i2c, 0x44, 0); + } +} + +static void i2c_8940x_irq_task() { + while (1) { + fiprintf(stderr, "i2c irq\n"); + struct i2c_8940x_ctx* i2c = task_current_interrupt_context(); + i2c_8940x_reg_write(i2c, 0x18, 0); + i2c->rdreg = i2c_8940x_reg_read(i2c, 0x14); + i2c_8940x_reg_write(i2c, 0x14, i2c->rdreg); + event_fire(&i2c->irq_event); + + task_exit_irq(); + } + +} + +static bool i2c_8940x_read(struct i2c_ctx* ctx, uint16_t addr, void* data_in, uint16_t size) { + struct i2c_8940x_ctx* i2c = ctx->context; + + uint32_t rg = i2c_8940x_reg_read(i2c, 0x2C); + rg &= 0xFFFF00FF; + rg |= ((size << 8) & 0xFF00); + i2c_8940x_reg_write(i2c, 0x2C, rg); + + i2c_8940x_reg_write(i2c, 0, ((addr << 1) & 0xFE) | 0x101); + i2c_8940x_reg_write(i2c, 0, size | 0x600); + + uint8_t* data_in_c = data_in; + uint16_t data_cursor = 0; + + while (1) { + disable_interrupts(); + i2c_8940x_reg_write(i2c, 0x18, 0xB00040); + i2c->rdreg = 0; + event_wait_asserted(&i2c->irq_event); + + if (i2c->rdreg & 0xA00040) { + return false; + } + + uint8_t readb = i2c_8940x_reg_read(i2c, 0x8) >> 8; + for (uint8_t i = 0; i < readb; i++) { + if (data_cursor >= size) { + panic("i2c_8940x_read: ???"); + } + data_in_c[data_cursor++] = i2c_8940x_reg_read(i2c, 4); + } + + if (data_cursor >= size) { + break; + } + } + + return true; } -static bool register_8940x_i2c(struct hal_device* device, void* context) { +static bool i2c_8940x_write(struct i2c_ctx* ctx, uint16_t addr, void* data_out, uint16_t size) { + struct i2c_8940x_ctx* i2c = ctx->context; + uint8_t* data_out_c = data_out; + + i2c_8940x_reg_write(i2c, 0, ((addr << 1) & 0xFE) | 0x100); + for (int i=0; i < size; i++) { + i2c_8940x_reg_write(i2c, 0, data_out_c[i] | (i+1 == size ? 0x200 : 0)); + } + + return true; +} + +static bool i2c_8960x_command_perform(struct i2c_ctx* ctx, struct i2c_cmd* cmd) { + struct i2c_8940x_ctx* i2c = ctx->context; + + lock_take(&i2c->i2c_lock); + + i2c_8940x_init_regs(ctx); + + for (uint16_t i = 0; i < cmd->txno; i++) { + if (cmd->txes[i].readwrite) { + // write + if (!i2c_8940x_write(ctx, cmd->txes[i].addr, cmd->txes[i].buf, cmd->txes[i].size)) { + lock_release(&i2c->i2c_lock); + return false; + } + } else { + // read + if (!i2c_8940x_read(ctx, cmd->txes[i].addr, cmd->txes[i].buf, cmd->txes[i].size)) { + lock_release(&i2c->i2c_lock); + return false; + } + } + } + + lock_release(&i2c->i2c_lock); + return true; +} + + +struct i2c_ops i2c_8940x_ops = { + .i2c_command_perform = i2c_8960x_command_perform +}; + +static bool register_8940x_i2c(struct hal_device* device, void** context) { // S5L8940x I2C controller + + struct i2c_8940x_ctx* i2c = calloc(sizeof(struct i2c_8940x_ctx), 1); + dt_node_t* node = device->node; uint32_t len = 0; void* name = dt_prop(node, "name", &len); - fiprintf(stderr, "S5L8940xI2C device found: %s\n", name); - - struct i2c_8940x_ctx* i2c = context; - i2c->device = device; i2c->i2c_regbase = (uint64_t)hal_map_registers(i2c->device, 0, NULL); + + hal_invoke_service_op(i2c->device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); // turn on I2C controller + + i2c->irq_task = task_create_extended(name, i2c_8940x_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); + interrupt_associate_context(hal_get_irqno(device,0), i2c); + task_bind_to_irq(i2c->irq_task, hal_get_irqno(device,0)); + + *context = i2c; return true; } static int i2c_8940x_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_METASERVICE_START) { + + /* + test i2c by doing a register read on the usb controller's VID + */ + + struct i2c_cmd* cmd = i2c_cmd_create(2); + uint8_t regid = 0x00; + i2c_cmd_set_write_tx(cmd, 0, 0x38, ®id, 1); + uint32_t readreg = 0; + i2c_cmd_set_read_tx(cmd, 1, 0x38, &readreg, 4); + + struct i2c_ctx fake = {0}; + fake.context = svc->context; + + bool rv = i2c_8960x_command_perform(&fake, cmd); + + i2c_cmd_destroy(cmd); + + fiprintf(stderr, "I2C READ: %x (%d)\n", readreg, rv); + return 0; } return -1; @@ -67,8 +224,7 @@ static bool i2c_8940x_probe(struct hal_service* svc, struct hal_device* device, while (compat < compatend) { if (strcmp(compat, "i2c,s5l8940x") == 0) { - *context = calloc(sizeof(struct i2c_8940x_ctx), 1); - if (register_8940x_i2c(device, *context)) { + if (register_8940x_i2c(device, context)) { return i2c_provide_service(device, &i2c_8940x_ops, *context); } return false; diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index e5f48aad..eaf0936a 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -286,7 +286,7 @@ static void drd_irq_task() { } } -bool is_in_host_mode = false; // default value +bool is_in_host_mode = true; // default value __unused static void atc_enable_device(struct drd* drd, bool enable) { uint32_t reg = 0; diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 3382c9e4..e5b4ec32 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -82,7 +82,7 @@ void pongo_main_task() { // Set up AES aes_init(); - fb_reset_cursor(); + // fb_reset_cursor(); puts(""); puts("#=================="); puts("#"); From b4c28e5c2b23f5efed80c7c83056edfc573eee83 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 18:25:01 +0100 Subject: [PATCH 45/50] cleanup i2c stack --- src/drivers/i2c/i2c.c | 71 +++++++++++++------------------------ src/drivers/i2c/i2c.h | 42 +++++----------------- src/drivers/i2c/i2c_8940x.c | 55 ++++++++-------------------- src/kernel/main_task.c | 20 ++++++++++- src/kernel/pongo.h | 33 +++++++++-------- 5 files changed, 81 insertions(+), 140 deletions(-) diff --git a/src/drivers/i2c/i2c.c b/src/drivers/i2c/i2c.c index 11721335..b78916a8 100644 --- a/src/drivers/i2c/i2c.c +++ b/src/drivers/i2c/i2c.c @@ -1,55 +1,32 @@ -/* - * pongoOS - https://checkra.in - * - * Copyright (C) 2019-2020 checkra1n team - * - * This file is part of pongoOS. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ + #import #import "i2c.h" -static bool i2c_probe(struct hal_service* svc, struct hal_device* device, void** context) { - panic("i2c_probe: i2c service is a virtual service provider that is not registered to HAL!"); - return false; +struct i2c_cmd* i2c_cmd_create(uint16_t txno) { + struct i2c_cmd* cmd = calloc(sizeof(struct i2c_cmd) + sizeof(struct i2c_tx) * txno, 1); + cmd->txno = txno; + return cmd; } - -static int i2c_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { - if (method == HAL_METASERVICE_START) { - return 0; - } - return -1; +void i2c_cmd_destroy(struct i2c_cmd* cmd) { + free(cmd); } -static struct hal_service i2c_svc = { - .name = "i2c", - .probe = i2c_probe, - .service_op = i2c_service_op -}; - -bool i2c_provide_service(struct hal_device* device, struct i2c_ops* ops, void* context) { - struct i2c_ctx* ctx = calloc(sizeof(struct i2c_ctx), 1); - ctx->ops = ops; - ctx->context = context; - hal_associate_service(device, &i2c_svc, ctx); - return true; +void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { + cmd->txes[index].buf = base; + cmd->txes[index].size = size; + cmd->txes[index].addr = address; + cmd->txes[index].readwrite = true; } +void i2c_cmd_set_read_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { + cmd->txes[index].buf = base; + cmd->txes[index].size = size; + cmd->txes[index].addr = address; + cmd->txes[index].readwrite = false; +} +bool i2c_cmd_perform(struct hal_device* i2c_dev, struct i2c_cmd* cmd){ + if ( ! hal_invoke_service_op(i2c_dev, "i2c", I2C_CMD_PERFORM, (void*)cmd, I2C_CMD_PERFORM_SIZE, NULL, NULL) ) { + return true; + } + return false; +} diff --git a/src/drivers/i2c/i2c.h b/src/drivers/i2c/i2c.h index 277c4c75..804296d5 100644 --- a/src/drivers/i2c/i2c.h +++ b/src/drivers/i2c/i2c.h @@ -12,37 +12,11 @@ struct i2c_cmd { struct i2c_tx txes[]; }; -inline static struct i2c_cmd* i2c_cmd_create(uint16_t txno) { - struct i2c_cmd* cmd = calloc(sizeof(struct i2c_cmd) + sizeof(struct i2c_tx) * txno, 1); - cmd->txno = txno; - return cmd; -} - -inline static void i2c_cmd_destroy(struct i2c_cmd* cmd) { - free(cmd); -} - -inline static void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { - cmd->txes[index].buf = base; - cmd->txes[index].size = size; - cmd->txes[index].addr = address; - cmd->txes[index].readwrite = true; -} - -inline static void i2c_cmd_set_read_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { - cmd->txes[index].buf = base; - cmd->txes[index].size = size; - cmd->txes[index].addr = address; - cmd->txes[index].readwrite = false; -} - -struct i2c_ops { - bool (*i2c_command_perform)(struct i2c_ctx* ctx, struct i2c_cmd* cmd); -}; - -struct i2c_ctx { - void* context; - struct i2c_ops* ops; -}; - -bool i2c_provide_service(struct hal_device* device, struct i2c_ops* ops, void* context); +#define I2C_CMD_PERFORM 1 +#define I2C_CMD_PERFORM_SIZE 0xFFFFFFFF + +struct i2c_cmd* i2c_cmd_create(uint16_t txno); +extern void i2c_cmd_destroy(struct i2c_cmd* cmd); +extern void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size); +extern void i2c_cmd_set_read_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size); +extern bool i2c_cmd_perform(struct hal_device* i2c_dev, struct i2c_cmd* cmd); diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c index 987d69bd..600e953d 100644 --- a/src/drivers/i2c/i2c_8940x.c +++ b/src/drivers/i2c/i2c_8940x.c @@ -1,7 +1,6 @@ #import #import "i2c.h" - struct i2c_8940x_ctx { uint64_t i2c_regbase; struct hal_device* device; @@ -38,9 +37,7 @@ __unused static void i2c_8940x_reg_or(struct i2c_8940x_ctx* i2c, uint32_t offset *(volatile uint32_t *)(i2c->i2c_regbase + offset) |= value; } -static void i2c_8940x_init_regs(struct i2c_ctx* ctx) { - struct i2c_8940x_ctx* i2c = ctx->context; - +static void i2c_8940x_init_regs(struct i2c_8940x_ctx* i2c) { i2c_8940x_reg_write(i2c, 0x1c, 4); i2c_8940x_reg_write(i2c, 0x14, 0xAA00040); i2c_8940x_reg_write(i2c, 0x18, 0); @@ -78,9 +75,7 @@ static void i2c_8940x_irq_task() { } -static bool i2c_8940x_read(struct i2c_ctx* ctx, uint16_t addr, void* data_in, uint16_t size) { - struct i2c_8940x_ctx* i2c = ctx->context; - +static bool i2c_8940x_read(struct i2c_8940x_ctx* i2c, uint16_t addr, void* data_in, uint16_t size) { uint32_t rg = i2c_8940x_reg_read(i2c, 0x2C); rg &= 0xFFFF00FF; rg |= ((size << 8) & 0xFF00); @@ -118,8 +113,7 @@ static bool i2c_8940x_read(struct i2c_ctx* ctx, uint16_t addr, void* data_in, ui return true; } -static bool i2c_8940x_write(struct i2c_ctx* ctx, uint16_t addr, void* data_out, uint16_t size) { - struct i2c_8940x_ctx* i2c = ctx->context; +static bool i2c_8940x_write(struct i2c_8940x_ctx* i2c, uint16_t addr, void* data_out, uint16_t size) { uint8_t* data_out_c = data_out; i2c_8940x_reg_write(i2c, 0, ((addr << 1) & 0xFE) | 0x100); @@ -130,23 +124,21 @@ static bool i2c_8940x_write(struct i2c_ctx* ctx, uint16_t addr, void* data_out, return true; } -static bool i2c_8960x_command_perform(struct i2c_ctx* ctx, struct i2c_cmd* cmd) { - struct i2c_8940x_ctx* i2c = ctx->context; - +static bool i2c_8960x_command_perform(struct i2c_8940x_ctx* i2c, struct i2c_cmd* cmd) { lock_take(&i2c->i2c_lock); - i2c_8940x_init_regs(ctx); + i2c_8940x_init_regs(i2c); for (uint16_t i = 0; i < cmd->txno; i++) { if (cmd->txes[i].readwrite) { // write - if (!i2c_8940x_write(ctx, cmd->txes[i].addr, cmd->txes[i].buf, cmd->txes[i].size)) { + if (!i2c_8940x_write(i2c, cmd->txes[i].addr, cmd->txes[i].buf, cmd->txes[i].size)) { lock_release(&i2c->i2c_lock); return false; } } else { // read - if (!i2c_8940x_read(ctx, cmd->txes[i].addr, cmd->txes[i].buf, cmd->txes[i].size)) { + if (!i2c_8940x_read(i2c, cmd->txes[i].addr, cmd->txes[i].buf, cmd->txes[i].size)) { lock_release(&i2c->i2c_lock); return false; } @@ -158,10 +150,6 @@ static bool i2c_8960x_command_perform(struct i2c_ctx* ctx, struct i2c_cmd* cmd) } -struct i2c_ops i2c_8940x_ops = { - .i2c_command_perform = i2c_8960x_command_perform -}; - static bool register_8940x_i2c(struct hal_device* device, void** context) { // S5L8940x I2C controller @@ -188,27 +176,12 @@ static bool register_8940x_i2c(struct hal_device* device, void** context) { static int i2c_8940x_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_METASERVICE_START) { - - /* - test i2c by doing a register read on the usb controller's VID - */ - - struct i2c_cmd* cmd = i2c_cmd_create(2); - uint8_t regid = 0x00; - i2c_cmd_set_write_tx(cmd, 0, 0x38, ®id, 1); - uint32_t readreg = 0; - i2c_cmd_set_read_tx(cmd, 1, 0x38, &readreg, 4); - - struct i2c_ctx fake = {0}; - fake.context = svc->context; - - bool rv = i2c_8960x_command_perform(&fake, cmd); - - i2c_cmd_destroy(cmd); - - fiprintf(stderr, "I2C READ: %x (%d)\n", readreg, rv); - return 0; + } else if (method == I2C_CMD_PERFORM && data_in && data_in_size == I2C_CMD_PERFORM_SIZE){ + if (i2c_8960x_command_perform(svc->context, data_in)) { + return 0; + } + return -1; } return -1; } @@ -225,7 +198,7 @@ static bool i2c_8940x_probe(struct hal_service* svc, struct hal_device* device, while (compat < compatend) { if (strcmp(compat, "i2c,s5l8940x") == 0) { if (register_8940x_i2c(device, context)) { - return i2c_provide_service(device, &i2c_8940x_ops, *context); + return true; } return false; } @@ -237,7 +210,7 @@ static bool i2c_8940x_probe(struct hal_service* svc, struct hal_device* device, } static struct hal_service i2c_8940x_svc = { - .name = "i2c8940x", + .name = "i2c", .probe = i2c_8940x_probe, .service_op = i2c_8940x_service_op }; diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index e5b4ec32..67f785a9 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -82,7 +82,7 @@ void pongo_main_task() { // Set up AES aes_init(); - // fb_reset_cursor(); + fb_reset_cursor(); puts(""); puts("#=================="); puts("#"); @@ -109,4 +109,22 @@ void pongo_main_task() { hal_issue_recursive_start(); shell_main(); + +#define TRY_I2C +#ifdef TRY_I2C + /* + test i2c by doing a register read on the usb controller's VID + */ + + struct i2c_cmd* cmd = i2c_cmd_create(2); + uint8_t regid = 0x00; + i2c_cmd_set_write_tx(cmd, 0, 0x38, ®id, 1); + uint32_t readreg = 0; + i2c_cmd_set_read_tx(cmd, 1, 0x38, &readreg, 4); + + bool rv = i2c_cmd_perform(hal_device_by_name("i2c0"), cmd); + i2c_cmd_destroy(cmd); + + fiprintf(stderr, "I2C READ: %x (%d)\n", readreg, rv); +#endif } diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index bba5f68c..4648559c 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -34,23 +34,6 @@ #include #include -#ifdef PONGO_PRIVATE -#include "framebuffer/fb.h" -#include "usb/usb.h" -#include "dart/dart.h" -#include "uart/uart.h" -#include "gpio/gpio.h" -#include "timer/timer.h" -#include "xnu/xnu.h" -#include "tz/tz.h" -#include "libDER/DER_Encode.h" -#include "libDER/DER_Decode.h" -#include "libDER/asn1Types.h" -#include "libDER/oids.h" -#include "mipi/mipi.h" -#include "aes/aes.h" -#endif - #define DT_KEY_LEN 0x20 extern int service_cmd(const char* name, int cmd_id, void* data_in, size_t in_size, void* data_out, size_t* out_size); @@ -524,7 +507,23 @@ static inline void flush_tlb(void) } } extern void task_real_unlink(struct task* task); + #include "hal/hal.h" +#include "framebuffer/fb.h" +#include "usb/usb.h" +#include "dart/dart.h" +#include "uart/uart.h" +#include "gpio/gpio.h" +#include "timer/timer.h" +#include "xnu/xnu.h" +#include "tz/tz.h" +#include "libDER/DER_Encode.h" +#include "libDER/DER_Decode.h" +#include "libDER/asn1Types.h" +#include "libDER/oids.h" +#include "mipi/mipi.h" +#include "aes/aes.h" +#include "i2c/i2c.h" #endif From b950229a707d5642f5d5e009973dcb53767e63e0 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 19:24:27 +0100 Subject: [PATCH 46/50] begin cd3217 driver --- src/drivers/cd3217/cd3217.c | 128 ++++++++++++++++++++++++++++++++++++ src/drivers/dart/dart.c | 3 +- src/drivers/hal/hal.c | 19 ++++++ src/drivers/hal/hal.h | 1 + src/drivers/i2c/i2c.h | 2 +- src/drivers/i2c/i2c_8940x.c | 22 ++----- 6 files changed, 154 insertions(+), 21 deletions(-) create mode 100644 src/drivers/cd3217/cd3217.c diff --git a/src/drivers/cd3217/cd3217.c b/src/drivers/cd3217/cd3217.c new file mode 100644 index 00000000..27843d97 --- /dev/null +++ b/src/drivers/cd3217/cd3217.c @@ -0,0 +1,128 @@ +#import + +/* + -------------------------------------------------------------------------------------------------------------------------------- + transports-supported 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 |................| + 05 00 00 00 |....| + port-location back-left + compatible usbc,cd3217 + acio-parent 0x00000043 + iicProvider 0x00000093 + AAPL,phandle 0x00000094 + dock 0x000000fd + rid 0x00000000 + hpm-class-type 0x0000000a + hpm-iic-addr 0x00000038 + port-type 0x00000002 + usbc-flash-update 0x00000001 + usbc-fw-personality HPM,27 + port-number 0x00000001 + name hpm0 + -------------------------------------------------------------------------------------------------------------------------------- + */ + +struct cd3217_ctx { + struct hal_device* bus; + struct hal_device* device; + + lock cd3217_lock; + + uint16_t i2c_addr; + struct i2c_cmd* i2ccmd; +}; + +__unused static bool cd3217_reg_read(struct cd3217_ctx* cd, uint8_t regid, void* readout, uint16_t outsz) { + lock_take(&cd->cd3217_lock); + + i2c_cmd_set_write_tx(cd->i2ccmd, 0, cd->i2c_addr, ®id, 1); + i2c_cmd_set_read_tx(cd->i2ccmd, 1, cd->i2c_addr, readout, outsz); + bool rv = i2c_cmd_perform(cd->bus, cd->i2ccmd); + + lock_release(&cd->cd3217_lock); + + iprintf("cd3217_reg_read(%s:%x, reg %x, %x bytes): %d\n", cd->bus->name, cd->i2c_addr, regid, outsz, rv); + return rv; +} + +__unused static bool cd3217_reg_write(struct cd3217_ctx* cd, uint8_t regid, void* readout, uint16_t insz) { + lock_take(&cd->cd3217_lock); + + i2c_cmd_set_write_tx(cd->i2ccmd, 0, cd->i2c_addr, ®id, 1); + i2c_cmd_set_write_tx(cd->i2ccmd, 1, cd->i2c_addr, readout, insz); + bool rv = i2c_cmd_perform(cd->bus, cd->i2ccmd); + + lock_release(&cd->cd3217_lock); + iprintf("cd3217_reg_write(%s:%x, reg %x, %x bytes): %d\n", cd->bus->name, cd->i2c_addr, regid, insz, rv); + + return rv; +} + +static bool cd3217_register(struct hal_device* device, void** context) { + // cd3217 USBC PD controller + + uint32_t len = 0; + dt_node_t* node = device->node; + + uint32_t* val = dt_prop(node, "iicProvider", &len); + if (!val || len != 4) panic("cd3217_register: dt looks broken"); + uint32_t i2c_bus_phandle = *val; + val = dt_prop(node, "hpm-iic-addr", &len); + if (!val || len != 4) panic("cd3217_register: dt looks broken"); + uint32_t i2c_addr = *val; + + struct hal_device* bus = hal_get_phandle_device(i2c_bus_phandle); + if (!bus) panic("cd3217_register: invalid iicProvider"); + bus = bus->parent; + if (!bus) panic("cd3217_register: invalid iicProvider"); + + struct cd3217_ctx* cdctx = calloc(sizeof(struct cd3217_ctx), 1); + + cdctx->bus = bus; + cdctx->device = device; + cdctx->i2ccmd = i2c_cmd_create(2); + cdctx->i2c_addr = i2c_addr; + + *context = cdctx; + + return true; +} + +static int cd3217_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == HAL_METASERVICE_START) { + struct cd3217_ctx* cd = (struct cd3217_ctx*)(svc->context); + + uint32_t vendorID = 0, deviceID = 0; + bool success = false; + success = cd3217_reg_read(cd, 0, &vendorID, 4); + if (!success) panic("cd3217: couldn't fetch VID"); + success = cd3217_reg_read(cd, 1, &deviceID, 4); + if (!success) panic("cd3217: couldn't fetch DID"); + + iprintf("cd3217 device found (%s:%x)! pid = %x, vid = %x\n", cd->bus->name, cd->i2c_addr, vendorID, deviceID); + + return 0; + } + return -1; +} + +static bool cd3217_probe(struct hal_service* svc, struct hal_device* device, void** context) { + if (hal_device_is_compatible(device, "usbc,cd3217")) { + if (cd3217_register(device, context)) { + return true; + } + } + return false; +} + +static struct hal_service cd3217_svc = { + .name = "cd3217", + .probe = cd3217_probe, + .service_op = cd3217_service_op +}; + +static void cd3217_init(struct driver* driver) { + hal_register_hal_service(&cd3217_svc); +} + +REGISTER_DRIVER(cd3217, cd3217_init, NULL, 0); + diff --git a/src/drivers/dart/dart.c b/src/drivers/dart/dart.c index 5a925ecf..a6f2f224 100644 --- a/src/drivers/dart/dart.c +++ b/src/drivers/dart/dart.c @@ -99,9 +99,8 @@ void dart_irq_handler() { static bool register_dart_mapper(struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; - dt_node_t* pnode = device->parent->node; - if (strcmp(dt_prop(pnode, "compatible", &len), "dart,t8020") == 0) { + if (hal_device_is_compatible(device->parent, "dart,t8020")) { __unused void* val = dt_prop(node, "name", &len); uint32_t* regid = dt_prop(node, "reg", &len); diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index 563f4d42..20601cfd 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -577,3 +577,22 @@ void hal_init() { command_register("lsdev", "prints hal devices tree", lsdev_cmd); } +bool hal_device_is_compatible(struct hal_device* device, const char* name) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (!node) return false; + + char* compat = dt_prop(node, "compatible", &len); + if (!compat) { + return false; + } + + char* compatend = compat + len; + while (compat < compatend) { + if (strcmp(compat, name) == 0) { + return true; + } + compat += strlen(compat) + 1; + } + return false; +} diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index 3ec16d69..052abe4f 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -114,6 +114,7 @@ extern int32_t hal_get_clock_gate_size(struct hal_device* device); extern int hal_apply_tunables(struct hal_device* device, const char* tunable_dt_entry_name); extern void hal_associate_service(struct hal_device* device, struct hal_service* svc, void* ctx); extern void hal_device_set_io_provider(struct hal_device* device, struct hal_service* svc); +extern bool hal_device_is_compatible(struct hal_device* device, const char* name); #define HAL_LOAD_XNU_DTREE 0 #define HAL_LOAD_DTREE_CHILDREN 1 diff --git a/src/drivers/i2c/i2c.h b/src/drivers/i2c/i2c.h index 804296d5..74bd2f1e 100644 --- a/src/drivers/i2c/i2c.h +++ b/src/drivers/i2c/i2c.h @@ -15,7 +15,7 @@ struct i2c_cmd { #define I2C_CMD_PERFORM 1 #define I2C_CMD_PERFORM_SIZE 0xFFFFFFFF -struct i2c_cmd* i2c_cmd_create(uint16_t txno); +extern struct i2c_cmd* i2c_cmd_create(uint16_t txno); extern void i2c_cmd_destroy(struct i2c_cmd* cmd); extern void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size); extern void i2c_cmd_set_read_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size); diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c index 600e953d..8a8c41c0 100644 --- a/src/drivers/i2c/i2c_8940x.c +++ b/src/drivers/i2c/i2c_8940x.c @@ -1,5 +1,4 @@ #import -#import "i2c.h" struct i2c_8940x_ctx { uint64_t i2c_regbase; @@ -187,26 +186,13 @@ static int i2c_8940x_service_op(struct hal_device_service* svc, struct hal_devic } static bool i2c_8940x_probe(struct hal_service* svc, struct hal_device* device, void** context) { - uint32_t len = 0; - dt_node_t* node = device->node; - if (node) { - void* val = dt_prop(node, "device_type", &len); - if (val && strcmp(val, "i2c") == 0) { - char* compat = dt_prop(node, "compatible", &len); - char* compatend = compat + len; - - while (compat < compatend) { - if (strcmp(compat, "i2c,s5l8940x") == 0) { - if (register_8940x_i2c(device, context)) { - return true; - } - return false; - } - compat += strlen(compat) + 1; - } + if (hal_device_is_compatible(device, "i2c,s5l8940x")) { + if (register_8940x_i2c(device, context)) { + return true; } } return false; + } static struct hal_service i2c_8940x_svc = { From 6429312065ad614240cbcb49ff148d45158a60d7 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 19:25:39 +0100 Subject: [PATCH 47/50] cleanup --- src/kernel/main_task.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 67f785a9..3382c9e4 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -109,22 +109,4 @@ void pongo_main_task() { hal_issue_recursive_start(); shell_main(); - -#define TRY_I2C -#ifdef TRY_I2C - /* - test i2c by doing a register read on the usb controller's VID - */ - - struct i2c_cmd* cmd = i2c_cmd_create(2); - uint8_t regid = 0x00; - i2c_cmd_set_write_tx(cmd, 0, 0x38, ®id, 1); - uint32_t readreg = 0; - i2c_cmd_set_read_tx(cmd, 1, 0x38, &readreg, 4); - - bool rv = i2c_cmd_perform(hal_device_by_name("i2c0"), cmd); - i2c_cmd_destroy(cmd); - - fiprintf(stderr, "I2C READ: %x (%d)\n", readreg, rv); -#endif } From bbc46131efedff95fe3fc1c632d12c9542b78ece Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 20:10:33 +0100 Subject: [PATCH 48/50] try to improve i2c driver a bit --- src/drivers/cd3217/cd3217.c | 26 ++++++++++++++++++++++--- src/drivers/i2c/i2c_8940x.c | 35 ++++++++++++++++++++++++++++++---- src/drivers/usb/synopsys_drd.c | 2 +- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/drivers/cd3217/cd3217.c b/src/drivers/cd3217/cd3217.c index 27843d97..136354ba 100644 --- a/src/drivers/cd3217/cd3217.c +++ b/src/drivers/cd3217/cd3217.c @@ -39,8 +39,9 @@ __unused static bool cd3217_reg_read(struct cd3217_ctx* cd, uint8_t regid, void* bool rv = i2c_cmd_perform(cd->bus, cd->i2ccmd); lock_release(&cd->cd3217_lock); - +#ifdef CD3217_REG_LOG iprintf("cd3217_reg_read(%s:%x, reg %x, %x bytes): %d\n", cd->bus->name, cd->i2c_addr, regid, outsz, rv); +#endif return rv; } @@ -52,8 +53,23 @@ __unused static bool cd3217_reg_write(struct cd3217_ctx* cd, uint8_t regid, void bool rv = i2c_cmd_perform(cd->bus, cd->i2ccmd); lock_release(&cd->cd3217_lock); +#ifdef CD3217_REG_LOG iprintf("cd3217_reg_write(%s:%x, reg %x, %x bytes): %d\n", cd->bus->name, cd->i2c_addr, regid, insz, rv); +#endif + return rv; +} + +static bool cd3217_enter_system_power_state(struct cd3217_ctx* cd, uint8_t p_state) { + if (p_state > 5) { + panic("cd3217: invalid pstate requested\n"); + } + + bool rv = cd3217_reg_write(cd, 0x20, &p_state, 1); + if (!rv) { + iprintf("cd3217: couldn't enter power state\n"); + } + return rv; } @@ -97,9 +113,13 @@ static int cd3217_service_op(struct hal_device_service* svc, struct hal_device* if (!success) panic("cd3217: couldn't fetch VID"); success = cd3217_reg_read(cd, 1, &deviceID, 4); if (!success) panic("cd3217: couldn't fetch DID"); + uint64_t cd3217_uid[2]; + success = cd3217_reg_read(cd, 5, cd3217_uid, 16); + if (!success) panic("cd3217: couldn't fetch UID"); + + iprintf("cd3217 device found (%s:%x)! uid: %016llx%016llx, pid = %x, vid = %x\n", cd->bus->name, cd->i2c_addr, cd3217_uid[0], cd3217_uid[1], vendorID, deviceID); - iprintf("cd3217 device found (%s:%x)! pid = %x, vid = %x\n", cd->bus->name, cd->i2c_addr, vendorID, deviceID); - + cd3217_enter_system_power_state(cd, 0); return 0; } return -1; diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c index 8a8c41c0..c1b5a9d3 100644 --- a/src/drivers/i2c/i2c_8940x.c +++ b/src/drivers/i2c/i2c_8940x.c @@ -62,13 +62,12 @@ __unused static void i2c_8940x_lockunlock(struct i2c_8940x_ctx* i2c, bool lockun static void i2c_8940x_irq_task() { while (1) { - fiprintf(stderr, "i2c irq\n"); + // fiprintf(stderr, "i2c irq\n"); struct i2c_8940x_ctx* i2c = task_current_interrupt_context(); i2c_8940x_reg_write(i2c, 0x18, 0); i2c->rdreg = i2c_8940x_reg_read(i2c, 0x14); i2c_8940x_reg_write(i2c, 0x14, i2c->rdreg); event_fire(&i2c->irq_event); - task_exit_irq(); } @@ -93,6 +92,9 @@ static bool i2c_8940x_read(struct i2c_8940x_ctx* i2c, uint16_t addr, void* data_ event_wait_asserted(&i2c->irq_event); if (i2c->rdreg & 0xA00040) { + uint32_t rdreg = i2c_8940x_reg_read(i2c, 0x14); + i2c_8940x_reg_write(i2c, 0x14, rdreg); + i2c_8940x_reg_write(i2c, 0x10, 0x80000000); return false; } @@ -116,10 +118,35 @@ static bool i2c_8940x_write(struct i2c_8940x_ctx* i2c, uint16_t addr, void* data uint8_t* data_out_c = data_out; i2c_8940x_reg_write(i2c, 0, ((addr << 1) & 0xFE) | 0x100); - for (int i=0; i < size; i++) { + + i2c_8940x_lockunlock(i2c, true); + for (uint32_t i=0; i < size; i++) { + if (i && !(i & 0xF)) { + // fifo depth is not too great + i2c_8940x_lockunlock(i2c, false); + + while (1) { + disable_interrupts(); + i2c_8940x_reg_write(i2c, 0x18, 0x8800040); + i2c->rdreg = 0; + event_wait_asserted(&i2c->irq_event); + if (i2c->rdreg & 0x800040) { + uint32_t rdreg = i2c_8940x_reg_read(i2c, 0x14); + i2c_8940x_reg_write(i2c, 0x14, rdreg); + i2c_8940x_reg_write(i2c, 0x10, 0x80000000); + return false; + } + if (i2c->rdreg & 0x08000000) { + // tx queue space available + break; + } + } + + i2c_8940x_lockunlock(i2c, true); + } i2c_8940x_reg_write(i2c, 0, data_out_c[i] | (i+1 == size ? 0x200 : 0)); } - + i2c_8940x_lockunlock(i2c, false); return true; } diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index eaf0936a..6734eac7 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -485,7 +485,7 @@ static bool register_drd(struct hal_device* device, void* context) { drd->atcRegBase = (uint64_t)hal_map_registers(drd->atc_device, 0, NULL); drd->atcRegBasePipe = (uint64_t)hal_map_registers(drd->atc_device, 1, NULL); - drd->irq_task = task_create_extended(drd->device->name, drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); + drd->irq_task = task_create_extended(&drd->device->name[4], drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); task_bind_to_irq(drd->irq_task, hal_get_irqno(device,0)); interrupt_associate_context(hal_get_irqno(device,0), drd); From aeee4d238a90679222f6ea4d3807cbcef9ddbe85 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Fri, 22 Jan 2021 23:38:22 +0100 Subject: [PATCH 49/50] usbc --- src/drivers/cd3217/cd3217.c | 131 +++++++++++++++++++++++++++++++----- src/drivers/i2c/i2c.c | 4 +- src/drivers/i2c/i2c.h | 2 +- src/drivers/i2c/i2c_8940x.c | 6 +- 4 files changed, 121 insertions(+), 22 deletions(-) diff --git a/src/drivers/cd3217/cd3217.c b/src/drivers/cd3217/cd3217.c index 136354ba..aaa5de99 100644 --- a/src/drivers/cd3217/cd3217.c +++ b/src/drivers/cd3217/cd3217.c @@ -19,6 +19,9 @@ port-number 0x00000001 name hpm0 -------------------------------------------------------------------------------------------------------------------------------- + + https://www.ti.com/lit/ug/slvuan1a/slvuan1a.pdf + */ struct cd3217_ctx { @@ -26,33 +29,52 @@ struct cd3217_ctx { struct hal_device* device; lock cd3217_lock; - + lock cd3217_reg_lock; + uint16_t i2c_addr; struct i2c_cmd* i2ccmd; }; -__unused static bool cd3217_reg_read(struct cd3217_ctx* cd, uint8_t regid, void* readout, uint16_t outsz) { - lock_take(&cd->cd3217_lock); +__unused static bool cd3217_reg_read(struct cd3217_ctx* cd, uint8_t regid, void* readout, uint8_t outsz) { + uint8_t buf[64] = {0}; + + lock_take(&cd->cd3217_reg_lock); i2c_cmd_set_write_tx(cd->i2ccmd, 0, cd->i2c_addr, ®id, 1); - i2c_cmd_set_read_tx(cd->i2ccmd, 1, cd->i2c_addr, readout, outsz); + i2c_cmd_set_read_tx(cd->i2ccmd, 1, cd->i2c_addr, buf, 64); bool rv = i2c_cmd_perform(cd->bus, cd->i2ccmd); - lock_release(&cd->cd3217_lock); + if (rv) { + if (buf[0] > outsz) { + buf[0] = outsz; + } + memcpy(readout, &buf[1], buf[0]); + } + + lock_release(&cd->cd3217_reg_lock); #ifdef CD3217_REG_LOG - iprintf("cd3217_reg_read(%s:%x, reg %x, %x bytes): %d\n", cd->bus->name, cd->i2c_addr, regid, outsz, rv); + iprintf("cd3217_reg_read(%s:%x, reg %x, %x bytes): %d (%d)\n", cd->bus->name, cd->i2c_addr, regid, outsz, rv, buf[0]); #endif return rv; } -__unused static bool cd3217_reg_write(struct cd3217_ctx* cd, uint8_t regid, void* readout, uint16_t insz) { - lock_take(&cd->cd3217_lock); +__unused static bool cd3217_reg_write(struct cd3217_ctx* cd, uint8_t regid, const void* readout, uint8_t insz) { + uint8_t buf[64] = {0}; + + lock_take(&cd->cd3217_reg_lock); + + if (insz > 63) { + panic("cd3217: OOB write"); + } + + buf[0] = insz; + memcpy(&buf[1], readout, insz); i2c_cmd_set_write_tx(cd->i2ccmd, 0, cd->i2c_addr, ®id, 1); - i2c_cmd_set_write_tx(cd->i2ccmd, 1, cd->i2c_addr, readout, insz); + i2c_cmd_set_write_tx(cd->i2ccmd, 1, cd->i2c_addr, buf, insz + 1); bool rv = i2c_cmd_perform(cd->bus, cd->i2ccmd); - lock_release(&cd->cd3217_lock); + lock_release(&cd->cd3217_reg_lock); #ifdef CD3217_REG_LOG iprintf("cd3217_reg_write(%s:%x, reg %x, %x bytes): %d\n", cd->bus->name, cd->i2c_addr, regid, insz, rv); #endif @@ -60,7 +82,7 @@ __unused static bool cd3217_reg_write(struct cd3217_ctx* cd, uint8_t regid, void } -static bool cd3217_enter_system_power_state(struct cd3217_ctx* cd, uint8_t p_state) { +__unused static bool cd3217_enter_system_power_state(struct cd3217_ctx* cd, uint8_t p_state) { if (p_state > 5) { panic("cd3217: invalid pstate requested\n"); } @@ -73,6 +95,51 @@ static bool cd3217_enter_system_power_state(struct cd3217_ctx* cd, uint8_t p_sta return rv; } +__unused static int8_t cd3217_get_system_power_state(struct cd3217_ctx* cd) { + uint8_t p_state = 0; + if (! cd3217_reg_read(cd, 0x20, &p_state, 1)) { + iprintf("cd3217: couldn't get power state\n"); + return -1; + } + + return p_state; +} + +__unused static bool cd3217_issue_cmd(struct cd3217_ctx* cd, const char* cmdname, void* data_in, uint8_t data_in_sz, void* data_out, uint8_t data_out_sz) { + bool status; + lock_take(&cd->cd3217_lock); + + if (data_in_sz) { + status = cd3217_reg_write(cd, 9, data_in, data_in_sz); + if (!status) goto failout; + } + + status = cd3217_reg_write(cd, 8, cmdname, 4); + if (!status) goto failout; + + uint32_t rdcmd = -1; + + while (1) { + status = cd3217_reg_read(cd, 8, &rdcmd, 4); + if (!status || rdcmd == 0x444d4321) goto failout; + if (!rdcmd) { + break; // successfully ran + } + } + + if (data_out_sz) { + status = cd3217_reg_read(cd, 9, data_out, data_out_sz); + if (!status) goto failout; + } + + lock_release(&cd->cd3217_lock); + return true; + +failout: + lock_release(&cd->cd3217_lock); + return false; +} + static bool cd3217_register(struct hal_device* device, void** context) { // cd3217 USBC PD controller @@ -106,20 +173,52 @@ static bool cd3217_register(struct hal_device* device, void** context) { static int cd3217_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_METASERVICE_START) { struct cd3217_ctx* cd = (struct cd3217_ctx*)(svc->context); - + uint32_t vendorID = 0, deviceID = 0; bool success = false; success = cd3217_reg_read(cd, 0, &vendorID, 4); if (!success) panic("cd3217: couldn't fetch VID"); success = cd3217_reg_read(cd, 1, &deviceID, 4); if (!success) panic("cd3217: couldn't fetch DID"); - uint64_t cd3217_uid[2]; + uint32_t cd3217_uid[4]; success = cd3217_reg_read(cd, 5, cd3217_uid, 16); if (!success) panic("cd3217: couldn't fetch UID"); - - iprintf("cd3217 device found (%s:%x)! uid: %016llx%016llx, pid = %x, vid = %x\n", cd->bus->name, cd->i2c_addr, cd3217_uid[0], cd3217_uid[1], vendorID, deviceID); - + char sts[5]; + bzero(sts, 5); + success = cd3217_reg_read(cd, 3, sts, 4); + if (!success) panic("cd3217: couldn't fetch mode"); + + uint32_t bsts = cd3217_get_system_power_state(cd); + cd3217_enter_system_power_state(cd, 0); + + if (bsts == 7) { + uint16_t win = 0; + success = cd3217_issue_cmd(cd, "SSPS", &win, 2, NULL, 0); + if (!success) { + iprintf("SSPS fail!\n"); + } else { + iprintf("SSPS success\n"); + } + } + + iprintf("cd3217 device found (%s:%x)! uid: %x, pid = %x, vid = %x, mode = %s, pstate = %d\n", cd->bus->name, cd->i2c_addr, cd3217_uid[0], vendorID, deviceID, sts, bsts); + + + success = cd3217_issue_cmd(cd, "SWDF", NULL, 0, NULL, 0); + if (!success) { + iprintf("SWDF fail!\n"); + } else { + iprintf("SWDF success\n"); + } + + success = cd3217_issue_cmd(cd, "SWsr", NULL, 0, NULL, 0); + if (!success) { + iprintf("SWsr fail!\n"); + } else { + iprintf("SWsr success\n"); + } + return 0; } return -1; diff --git a/src/drivers/i2c/i2c.c b/src/drivers/i2c/i2c.c index b78916a8..4b0649de 100644 --- a/src/drivers/i2c/i2c.c +++ b/src/drivers/i2c/i2c.c @@ -11,8 +11,8 @@ void i2c_cmd_destroy(struct i2c_cmd* cmd) { free(cmd); } -void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size) { - cmd->txes[index].buf = base; +void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, const void* base, uint16_t size) { + cmd->txes[index].buf = (void*)base; cmd->txes[index].size = size; cmd->txes[index].addr = address; cmd->txes[index].readwrite = true; diff --git a/src/drivers/i2c/i2c.h b/src/drivers/i2c/i2c.h index 74bd2f1e..f44011b3 100644 --- a/src/drivers/i2c/i2c.h +++ b/src/drivers/i2c/i2c.h @@ -17,6 +17,6 @@ struct i2c_cmd { extern struct i2c_cmd* i2c_cmd_create(uint16_t txno); extern void i2c_cmd_destroy(struct i2c_cmd* cmd); -extern void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size); +extern void i2c_cmd_set_write_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, const void* base, uint16_t size); extern void i2c_cmd_set_read_tx(struct i2c_cmd* cmd, uint16_t index, uint16_t address, void* base, uint16_t size); extern bool i2c_cmd_perform(struct hal_device* i2c_dev, struct i2c_cmd* cmd); diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c index c1b5a9d3..a85459db 100644 --- a/src/drivers/i2c/i2c_8940x.c +++ b/src/drivers/i2c/i2c_8940x.c @@ -17,21 +17,21 @@ struct i2c_8940x_ctx { __unused static uint32_t i2c_8940x_reg_read(struct i2c_8940x_ctx* i2c, uint32_t offset) { uint32_t rv = *(volatile uint32_t *)(i2c->i2c_regbase + offset); #ifdef REG_LOG - fiprintf(stderr, "i2c_8940x_8940x_reg_read(%x) = %x\n", offset, rv); + fiprintf(stderr, "i2c_8940x_8940x_reg_read(%x) == %x\n", offset, rv); #endif return rv; } __unused static void i2c_8940x_reg_write(struct i2c_8940x_ctx* i2c, uint32_t offset, uint32_t value) { #ifdef REG_LOG - fiprintf(stderr, "i2c_8940x_8940x_reg_write(%x) = %x\n", offset, rv); + fiprintf(stderr, "i2c_8940x_8940x_reg_write(%x) = %x\n", offset, value); #endif *(volatile uint32_t *)(i2c->i2c_regbase + offset) = value; } __unused static void i2c_8940x_reg_or(struct i2c_8940x_ctx* i2c, uint32_t offset, uint32_t value) { #ifdef REG_LOG - fiprintf(stderr, "i2c_8940x_reg_or(%x) = %x\n", offset, rv); + fiprintf(stderr, "i2c_8940x_reg_or(%x) |= %x\n", offset, value); #endif *(volatile uint32_t *)(i2c->i2c_regbase + offset) |= value; } From 5ce5f28e5d8308ae5e0ff2e1d6558f35b4109b00 Mon Sep 17 00:00:00 2001 From: qwertyoruiop Date: Sat, 23 Jan 2021 03:03:18 +0100 Subject: [PATCH 50/50] begin GPIO, add virtual IRQ dispatching, redesign IRQ binding, begin HPM --- src/drivers/cd3217/cd3217.c | 38 +++++++++- src/drivers/gpio/gpio.c | 104 ++++++++++++++++++++----- src/drivers/gpio/gpio.h | 30 -------- src/drivers/hal/hal.c | 134 ++++++++++++++++++++++++++++++++- src/drivers/hal/hal.h | 26 +++++++ src/drivers/i2c/i2c_8940x.c | 9 ++- src/drivers/uart/uart.c | 3 + src/drivers/usb/synopsys_drd.c | 11 ++- src/kernel/lowlevel.c | 29 +++++-- src/kernel/main_task.c | 5 +- src/kernel/pongo.h | 6 +- src/kernel/task.c | 60 ++++++++++++--- src/kernel/task.h | 3 + 13 files changed, 374 insertions(+), 84 deletions(-) delete mode 100644 src/drivers/gpio/gpio.h diff --git a/src/drivers/cd3217/cd3217.c b/src/drivers/cd3217/cd3217.c index aaa5de99..87b069dc 100644 --- a/src/drivers/cd3217/cd3217.c +++ b/src/drivers/cd3217/cd3217.c @@ -164,7 +164,6 @@ static bool cd3217_register(struct hal_device* device, void** context) { cdctx->device = device; cdctx->i2ccmd = i2c_cmd_create(2); cdctx->i2c_addr = i2c_addr; - *context = cdctx; return true; @@ -173,7 +172,7 @@ static bool cd3217_register(struct hal_device* device, void** context) { static int cd3217_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_METASERVICE_START) { struct cd3217_ctx* cd = (struct cd3217_ctx*)(svc->context); - + uint32_t vendorID = 0, deviceID = 0; bool success = false; success = cd3217_reg_read(cd, 0, &vendorID, 4); @@ -232,14 +231,49 @@ static bool cd3217_probe(struct hal_service* svc, struct hal_device* device, voi } return false; } +struct hpm_ctx { + struct task* irq_task; +}; + +static void hpm_irq_main() { + while (1) { + fiprintf(stderr, "hpm irq\n"); + task_exit_irq(); + } +} +static int hpm_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == HAL_METASERVICE_START) { + struct hpm_ctx* hpm = (struct hpm_ctx*)(svc->context); + if (!hal_register_interrupt(device, hpm->irq_task, 0, hpm)) + panic("hpm_start: hal_register_interrupt failed!"); + + return 0; + } + return -1; +} +static bool hpm_probe(struct hal_service* svc, struct hal_device* device, void** context) { + if (hal_device_is_compatible(device, "usbc,manager")) { + struct hpm_ctx* ctx = calloc(sizeof(struct hpm_ctx), 1); + ctx->irq_task = task_create_extended("hpm", hpm_irq_main, TASK_IRQ_HANDLER | TASK_PREEMPT, 0); + *context = ctx; + return true; + } + return false; +} static struct hal_service cd3217_svc = { .name = "cd3217", .probe = cd3217_probe, .service_op = cd3217_service_op }; +static struct hal_service hpm_svc = { + .name = "hpm", + .probe = hpm_probe, + .service_op = hpm_service_op +}; static void cd3217_init(struct driver* driver) { + hal_register_hal_service(&hpm_svc); hal_register_hal_service(&cd3217_svc); } diff --git a/src/drivers/gpio/gpio.c b/src/drivers/gpio/gpio.c index 7e960dd3..0ad9cdb7 100644 --- a/src/drivers/gpio/gpio.c +++ b/src/drivers/gpio/gpio.c @@ -26,31 +26,95 @@ */ #include -void gpio_main() { - while(1) { - iprintf("gpio irq %x\n", task_current()->irq_type); +/* + #interrupt-cells 0x00000002 + interrupt-controller || + compatible gpio,t8101 + interrupt-parent 0x0000005c + interrupts be 00 00 00 bf 00 00 00 c0 00 00 00 c1 00 00 00 |................| + c2 00 00 00 c3 00 00 00 c4 00 00 00 |............| + #gpio-int-groups 0x00000007 + reg 00 00 10 3c 00 00 00 00 00 00 10 00 00 00 00 00 |...<............| + #gpio-pins 0x000000d4 + AAPL,phandle 0x00000063 + device_type interrupt-controller + #address-cells 0x00000000 + role AP + name gpio + + + */ + + +struct t8101_gpio_ctx { + struct task* irq_task; + uint64_t gpio_base; +}; + +static int gpio_irqctrl_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == IRQ_MASK && data_in_size == 4) { + __unused uint32_t irq_index = *(uint32_t*)data_in; + } else if (method == IRQ_UNMASK && data_in_size == 4) { + __unused uint32_t irq_index = *(uint32_t*)data_in; + } else if (method == IRQ_ACK) { + __unused uint32_t irq_index = *(uint32_t*)data_in; + } else if (method == IRQ_REGISTER && data_in_size == sizeof(struct irq_register_args)) { + __unused struct irq_register_args* args = data_in; + return 0; + } + return -1; +} + +static struct hal_service gpio_irqctrl_svc = { + .name = "irqctrl", + .probe = NULL, + .service_op = gpio_irqctrl_service_op +}; + +static void gpio_t8101_irq() { + while (1) { + fiprintf(stderr, "GPIO IRQ\n"); task_exit_irq(); } } -struct task gpio_task = {.name = "gpio"}; -uint64_t gGpioBase; -void gpio_early_init() { - struct hal_device* gpio_dev = hal_device_by_name("gpio"); - if (gpio_dev) { - gGpioBase = (uint64_t) hal_map_registers(gpio_dev, 0, NULL); +static bool gpio_register_t8101(struct hal_device* device, void** context) { + struct t8101_gpio_ctx* gpioctx = calloc(sizeof(struct t8101_gpio_ctx), 1); + gpioctx->gpio_base = (uint64_t) hal_map_registers(device, 0, NULL); + gpioctx->irq_task = task_create_extended(device->name, gpio_t8101_irq, TASK_IRQ_HANDLER, 0); + hal_associate_service(device, &gpio_irqctrl_svc, gpioctx); + *context = gpioctx; + return true; +} + + +static bool gpio_t8101_probe(struct hal_service* svc, struct hal_device* device, void** context) { + if (hal_device_is_compatible(device, "gpio,t8101")) { + return gpio_register_t8101(device, context); + } + return false; +} + +static int gpio_t8101_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == HAL_METASERVICE_START) { + struct t8101_gpio_ctx* gpioctx = svc->context; + if (!hal_register_interrupt(device, gpioctx->irq_task, 0, gpioctx)) + panic("gpio_t8101_start: hal_register_interrupt failed!"); + + return 0; } + return -1; } -void gpio_init() { - /* - uint32_t len = 0; - dt_node_t* buttons = dt_find(gDeviceTree, "buttons"); - if (!buttons) panic("invalid devicetree: no buttons!"); - uint32_t* interrupts = dt_prop(buttons, "interrupts", &len); - if (!interrupts) panic("invalid devicetree: no interrupts!"); - - for (int i=0; inode; if (!node) return -1; +#if 0 + int32_t* pval = dt_prop(node, "interrupt-parent", &len); + int32_t irqparent = *pval; + + if (hal_get_phandle_device(irqparent) != gInterruptDevice) { + panic("hal_get_irqno: only supported for AIC interrupt children"); + } +#endif + int32_t* val = dt_prop(node, "interrupts", &len); if (!val || index * 4 >= len) { return -1; } return val[index]; } +bool hal_unmask_interrupt(struct hal_device* device, uint32_t reg) { + if (hal_invoke_service_op(device, "irq", IRQ_UNMASK, ®, 4, NULL, 0)) { + return false; + } + return true; +} +bool hal_mask_interrupt(struct hal_device* device, uint32_t reg) { + if (hal_invoke_service_op(device, "irq", IRQ_MASK, ®, 4, NULL, 0)) { + return false; + } + return true; +} +bool hal_ack_interrupt(struct hal_device* device, uint32_t reg) { + if (hal_invoke_service_op(device, "irq", IRQ_ACK, ®, 4, NULL, 0)) { + return false; + } + return true; +} +bool hal_register_interrupt(struct hal_device* device, struct task* task, uint32_t irqno, void* context) { + struct irq_register_args args = { + .irq = irqno, + .task = task, + .context = context + }; + if (hal_invoke_service_op(device, "irq", IRQ_REGISTER, &args, sizeof(args), NULL, 0)) { + return false; + } + return true; +} +bool hal_controller_unmask_interrupt(struct hal_device* device, uint32_t reg) { + if (hal_invoke_service_op(device, "irqctrl", IRQ_UNMASK, ®, 4, NULL, 0)) { + return false; + } + return true; +} +bool hal_controller_mask_interrupt(struct hal_device* device, uint32_t reg) { + if (hal_invoke_service_op(device, "irqctrl", IRQ_MASK, ®, 4, NULL, 0)) { + return false; + } + return true; +} +bool hal_controller_ack_interrupt(struct hal_device* device, uint32_t reg) { + if (hal_invoke_service_op(device, "irqctrl", IRQ_ACK, ®, 4, NULL, 0)) { + return false; + } + return true; +} +bool hal_controller_register_interrupt(struct hal_device* device, struct task* task, uint32_t irqno, void* context) { + struct irq_register_args args = { + .irq = irqno, + .task = task, + .context = context + }; + if (hal_invoke_service_op(device, "irqctrl", IRQ_REGISTER, &args, sizeof(args), NULL, 0)) { + return false; + } + return true; +} void * hal_map_registers(struct hal_device* device, uint32_t index, size_t *size) { struct { @@ -328,7 +395,10 @@ int hal_invoke_service_op(struct hal_device* device, const char* svc_name, uint3 while (svc) { if (strcmp(svc_name, svc->name) == 0 || metaservice_lookup) { if (svc->service->service_op) { - return svc->service->service_op(svc, device, method, data_in, data_in_size, data_out, data_out_size); + int rv = svc->service->service_op(svc, device, method, data_in, data_in_size, data_out, data_out_size); + if (!metaservice_lookup) { + return rv; + } } } svc = svc->next; @@ -507,6 +577,65 @@ struct hal_device* hal_get_phandle_device(uint32_t phandle) { return NULL; } +static bool irq_probe(struct hal_service* svc, struct hal_device* device, void** context) { + uint32_t len = 0; + dt_node_t* node = device->node; + if (node) { + int32_t* pval = dt_prop(node, "interrupt-parent", &len); + if (pval) { + int32_t irqparent = *pval; + *context = (void*)(uintptr_t)irqparent; + return true; + } + } + return false; +} + +static int irq_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + struct hal_device* irq_ctrl_parent = hal_get_phandle_device((uint32_t) svc->context); + if (irq_ctrl_parent) { + if (method == IRQ_MASK && data_in_size == 4) { + uint32_t irq_index = *(uint32_t*)data_in; + int32_t irq_number = hal_get_irqno(device, irq_index); + if (irq_number < 0) { + return -1; + } + + return hal_controller_mask_interrupt(irq_ctrl_parent, irq_number) == 0 ? true : false; // redirect request to interrupt controller + } else if (method == IRQ_UNMASK && data_in_size == 4) { + uint32_t irq_index = *(uint32_t*)data_in; + int32_t irq_number = hal_get_irqno(device, irq_index); + if (irq_number < 0) { + return -1; + } + return hal_controller_unmask_interrupt(irq_ctrl_parent, irq_number) == 0 ? true : false; // redirect request to interrupt controller + } else if (method == IRQ_ACK) { + uint32_t irq_index = *(uint32_t*)data_in; + int32_t irq_number = hal_get_irqno(device, irq_index); + if (irq_number < 0) { + return -1; + } + return hal_controller_ack_interrupt(irq_ctrl_parent, irq_number) == 0 ? true : false; // redirect request to interrupt controller + } else if (method == IRQ_REGISTER && data_in_size == sizeof(struct irq_register_args)) { + struct irq_register_args* args = data_in; + + int32_t irq_number = hal_get_irqno(device, args->irq); + if (irq_number < 0) { + return -1; + } + return hal_controller_register_interrupt(irq_ctrl_parent, args->task, irq_number, args->context) == 0 ? true : false; // redirect request to interrupt controller + } + } + return -1; +} + +static struct hal_service irq_svc = { + .name = "irq", + .probe = irq_probe, + .service_op = irq_service_op +}; + + void hal_init() { gPlatform = NULL; gRootDevice = &_gRootDevice; @@ -557,6 +686,7 @@ void hal_init() { } hal_init_late(); hal_register_hal_service(&hal_service); + hal_register_hal_service(&irq_svc); hal_probe_hal_services(gRootDevice, true); size_t ssz = 8; diff --git a/src/drivers/hal/hal.h b/src/drivers/hal/hal.h index 052abe4f..63849b48 100644 --- a/src/drivers/hal/hal.h +++ b/src/drivers/hal/hal.h @@ -116,6 +116,16 @@ extern void hal_associate_service(struct hal_device* device, struct hal_service* extern void hal_device_set_io_provider(struct hal_device* device, struct hal_service* svc); extern bool hal_device_is_compatible(struct hal_device* device, const char* name); +extern bool hal_unmask_interrupt(struct hal_device* device, uint32_t reg); +extern bool hal_mask_interrupt(struct hal_device* device, uint32_t reg); +extern bool hal_ack_interrupt(struct hal_device* device, uint32_t reg); +extern bool hal_register_interrupt(struct hal_device* device, struct task* task, uint32_t irqno, void* context); + +extern bool hal_controller_unmask_interrupt(struct hal_device* device, uint32_t reg); +extern bool hal_controller_mask_interrupt(struct hal_device* device, uint32_t reg); +extern bool hal_controller_ack_interrupt(struct hal_device* device, uint32_t reg); +extern bool hal_controller_register_interrupt(struct hal_device* device, struct task* task, uint32_t irqno, void* context); + #define HAL_LOAD_XNU_DTREE 0 #define HAL_LOAD_DTREE_CHILDREN 1 #define HAL_CREATE_CHILD_DEVICE 2 @@ -125,7 +135,23 @@ extern bool hal_device_is_compatible(struct hal_device* device, const char* name #define HAL_DEVICE_CLOCK_GATE_ON 6 #define HAL_DEVICE_CLOCK_GATE_OFF 7 + +// Abstract IRQ interface + +#define IRQ_REGISTER 0 +#define IRQ_MASK 1 +#define IRQ_UNMASK 2 +#define IRQ_ACK 3 + +struct irq_register_args { + struct task* task; + uint32_t irq; + void* context; +}; + + #define METASERVICE_TAG_MASK 0xf0000000 #define HAL_METASERVICE_TAG 0x80000000 #define HAL_METASERVICE_START (HAL_METASERVICE_TAG | 0x1) + diff --git a/src/drivers/i2c/i2c_8940x.c b/src/drivers/i2c/i2c_8940x.c index a85459db..64a8e876 100644 --- a/src/drivers/i2c/i2c_8940x.c +++ b/src/drivers/i2c/i2c_8940x.c @@ -192,9 +192,7 @@ static bool register_8940x_i2c(struct hal_device* device, void** context) { hal_invoke_service_op(i2c->device, "hal", HAL_DEVICE_CLOCK_GATE_ON, NULL, 0, NULL, NULL); // turn on I2C controller i2c->irq_task = task_create_extended(name, i2c_8940x_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - interrupt_associate_context(hal_get_irqno(device,0), i2c); - task_bind_to_irq(i2c->irq_task, hal_get_irqno(device,0)); - + *context = i2c; return true; @@ -202,6 +200,11 @@ static bool register_8940x_i2c(struct hal_device* device, void** context) { static int i2c_8940x_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_METASERVICE_START) { + struct i2c_8940x_ctx* i2c = svc->context; + + if (!hal_register_interrupt(device, i2c->irq_task, 0, i2c)) + panic("i2c_8940x_start: hal_register_interrupt failed!"); + return 0; } else if (method == I2C_CMD_PERFORM && data_in && data_in_size == I2C_CMD_PERFORM_SIZE){ if (i2c_8960x_command_perform(svc->context, data_in)) { diff --git a/src/drivers/uart/uart.c b/src/drivers/uart/uart.c index e112fe71..709f385b 100644 --- a/src/drivers/uart/uart.c +++ b/src/drivers/uart/uart.c @@ -127,6 +127,9 @@ void serial_pinmux_init() { // Pinmux debug UART on ATV4K // This will also pinmux uart0 on iPad Pro 2G if((strcmp(soc_name, "t8011") == 0)) { + struct hal_device* gpio_dev = hal_device_by_name("gpio"); + uint64_t gGpioBase = (uint64_t) hal_map_registers(gpio_dev, 0, NULL); + rT8011TX = UART_TX_MUX; rT8011RX = UART_RX_MUX; } diff --git a/src/drivers/usb/synopsys_drd.c b/src/drivers/usb/synopsys_drd.c index 6734eac7..1c56cee0 100644 --- a/src/drivers/usb/synopsys_drd.c +++ b/src/drivers/usb/synopsys_drd.c @@ -487,9 +487,6 @@ static bool register_drd(struct hal_device* device, void* context) { drd->irq_task = task_create_extended(&drd->device->name[4], drd_irq_task, TASK_IRQ_HANDLER|TASK_PREEMPT, 0); - task_bind_to_irq(drd->irq_task, hal_get_irqno(device,0)); - interrupt_associate_context(hal_get_irqno(device,0), drd); - atc_bringup(drd); if (is_in_host_mode) { atc_enable_host(drd, true); @@ -505,7 +502,13 @@ static bool register_drd(struct hal_device* device, void* context) { } static int drd_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { if (method == HAL_METASERVICE_START) { - register_drd(device, svc->context); + struct drd* drd = svc->context; + + register_drd(device, drd); + + task_bind_to_irq(drd->irq_task, hal_get_irqno(drd->device,0)); + interrupt_associate_context(hal_get_irqno(drd->device,0), drd); + return 0; } return -1; diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 87c44928..81904900 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -617,6 +617,8 @@ void* interrupt_context(uint32_t irqno) { return irqctx[irqno]; } +struct hal_device* gInterruptDevice; + static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, void** context) { uint32_t len = 0; dt_node_t* node = device->node; @@ -625,6 +627,8 @@ static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, v if (val && strcmp(val, "aic") == 0) { if (gInterruptBase) panic("multiple aic probes! unsupported."); + gInterruptDevice = device; + gInterruptBase = (uint64_t) hal_map_registers(device, 0, NULL); irq_count = count_interrupts(); @@ -636,7 +640,7 @@ static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, v return true; } else - if (val && strcmp(val, "pmgr") == 0) { + if (val && strcmp(val, "pmgr") == 0) { // move this to its own driver if (gPMGRreg) panic("multiple pmgr probes! unsupported."); void* pmreg = dt_prop(device->node, "reg", &gPMGRreglen); @@ -654,26 +658,41 @@ static bool lowlevel_probe(struct hal_service* svc, struct hal_device* device, v } gPMGRBase = gPMGRreg[0].addr; - return true; + return false; } else - if (val && strcmp(val, "wdt") == 0) { + if (val && strcmp(val, "wdt") == 0) { // move this to its own driver if (gWDTBase) panic("multiple wdt probes! unsupported."); gWDTBase = (uint64_t) hal_map_registers(device, 0, NULL); command_register("reset", "resets the device", wdt_reset); command_register("crash", "branches to an invalid address", (void*)0x41414141); - return true; + return false; } } return false; } static int lowlevel_service_op(struct hal_device_service* svc, struct hal_device* device, uint32_t method, void* data_in, size_t data_in_size, void* data_out, size_t *data_out_size) { + if (method == IRQ_MASK && data_in_size == 4) { + mask_interrupt(*(uint32_t*)data_in); + return 0; + } else if (method == IRQ_UNMASK && data_in_size == 4) { + unmask_interrupt(*(uint32_t*)data_in); + return 0; + } else if (method == IRQ_ACK) { + return 0; + } else if (method == IRQ_REGISTER && data_in_size == sizeof(struct irq_register_args)) { + struct irq_register_args* args = data_in; + uint32_t irq_number = args->irq; + interrupt_associate_context(irq_number, args->context); + task_bind_to_irq(args->task, irq_number); + return 0; + } return -1; } static struct hal_service lowlevel_svc = { - .name = "lowlevel", + .name = "irqctrl", .probe = lowlevel_probe, .service_op = lowlevel_service_op, .flags = SERVICE_FLAGS_EARLY_PROBE diff --git a/src/kernel/main_task.c b/src/kernel/main_task.c index 3382c9e4..e044da99 100644 --- a/src/kernel/main_task.c +++ b/src/kernel/main_task.c @@ -54,9 +54,6 @@ void pongo_main_task() { // Setup HAL hal_init(); - // Setup GPIO Base - gpio_early_init(); - // Setup serial pinmux serial_pinmux_init(); @@ -82,7 +79,7 @@ void pongo_main_task() { // Set up AES aes_init(); - fb_reset_cursor(); + //fb_reset_cursor(); puts(""); puts("#=================="); puts("#"); diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 4648559c..5f168693 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -217,6 +217,7 @@ extern void proc_release(struct proc*); extern struct task* proc_create_task(struct proc* proc, void* entrypoint); #define PROC_NO_VM 1 extern void fb_reset_cursor(); +extern void task_exit_irq_continuation(struct task* continue_to_task, struct hal_device* spoofed_irq_controller, uint32_t spoofed_irq_type, void* spoofed_context); extern uint32_t loader_xfer_recv_size; extern void resize_loader_xfer_data(uint32_t newsz); extern bool vm_fault(struct vm_space* vmspace, uint64_t vma, vm_protect_t fault_prot); @@ -385,7 +386,7 @@ extern void event_wait_asserted(struct event* ev); extern void event_wait(struct event* ev); extern void event_fire(struct event* ev); extern void* alloc_static(uint32_t size); // memory returned by this will be added to the xnu static region, thus will persist after xnu boot -extern void task_bind_to_irq(struct task* task, int irq); +extern void task_bind_to_irq(struct task* task, uint32_t irq); extern struct event command_handler_iter; #ifdef memset @@ -437,7 +438,7 @@ extern void* phystokv(uint64_t paddr); extern void cache_invalidate(void *address, size_t size); extern void cache_clean_and_invalidate(void *address, size_t size); extern void cache_clean(void *address, size_t size); -extern void register_irq_handler(uint16_t irq_v, struct task* irq_handler); +extern void register_irq_handler(uint32_t irq_v, struct task* irq_handler); extern uint64_t device_clock_by_id(uint32_t id); extern uint64_t device_clock_by_name(const char *name); extern void clock_gate(uint64_t addr, char val); @@ -513,7 +514,6 @@ extern void task_real_unlink(struct task* task); #include "usb/usb.h" #include "dart/dart.h" #include "uart/uart.h" -#include "gpio/gpio.h" #include "timer/timer.h" #include "xnu/xnu.h" #include "tz/tz.h" diff --git a/src/kernel/task.c b/src/kernel/task.c index 7718acf4..77c26198 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -63,7 +63,7 @@ void task_timer_fired() { extern struct task** irqvecs; extern uint32_t irq_count; -void register_irq_handler(uint16_t irq_v, struct task* irq_handler) +void register_irq_handler(uint32_t irq_v, struct task* irq_handler) { if (irq_v >= irq_count) panic("invalid irq"); @@ -200,14 +200,14 @@ retry:; for(int i = 0; i < ntasks; ++i) { task_info_t *t = &tasks_copy[i]; - iprintf(" | %7s | task %d | runcnt = %llx | flags = %s, %s\n", t->name[0] ? t->name : "unknown", t->pid, t->runcnt, t->flags & TASK_PREEMPT ? "preempt" : "coop", t->flags & TASK_LINKED ? "run" : "wait"); + iprintf(" | %13s | task %d | runcnt = %llx | flags = %s, %s\n", t->name[0] ? t->name : "unknown", t->pid, t->runcnt, t->flags & TASK_PREEMPT ? "preempt" : "coop", t->flags & TASK_LINKED ? "run" : "wait"); } iprintf("=+= IRQ Handlers ===\n"); for(int i = 0; i < nirq; ++i) { task_info_t *t = &irq_copy[i]; char* nm = t->name[0] ? t->name : "unknown"; - iprintf(" | %7s (%d) | runcnt: %lld | irq: %d | irqcnt: %llu | flags: %s, %s\n", nm, t->pid, t->runcnt, i, t->irq_count, t->flags & TASK_PREEMPT ? "preempt" : "coop", t->flags & TASK_LINKED ? "run" : "wait"); + iprintf(" | %13s (%d) | runcnt: %lld | irq: %d | irqcnt: %llu | flags: %s, %s\n", nm, t->pid, t->runcnt, i, t->irq_count, t->flags & TASK_PREEMPT ? "preempt" : "coop", t->flags & TASK_LINKED ? "run" : "wait"); } iprintf("=+= Loaded modules ===\n"); extern void pongo_module_print_list(); @@ -223,8 +223,10 @@ void task_irq_teardown() { } } } +extern struct hal_device* gInterruptDevice; void* task_current_interrupt_context() { - return interrupt_context(task_current()->irq_type); + struct task* irqh = task_current(); + return irqh->irq_context; } __attribute__((noinline)) void task_switch_irq(struct task* new) { @@ -247,23 +249,38 @@ __attribute__((noinline)) void task_switch_irq(struct task* new) } new->irq_ret = NULL; if (new->flags & TASK_MASK_NEXT_IRQ) new->flags &= ~TASK_MASK_NEXT_IRQ; - else unmask_interrupt(new->irq_type); // re-arm IRQ + else { + if (!new->irq_controller || new->irq_controller == gInterruptDevice) { // fastpath + unmask_interrupt(new->irq_type); + } else { + hal_controller_unmask_interrupt(new->irq_controller, new->irq_type); // re-arm IRQ + } + } served_irqs++; + + struct task* continuation = new->irq_continue; + if (continuation) { + new->irq_continue = NULL; + new->irq_context = NULL; + new->irq_controller = NULL; + return task_switch_irq(continuation); + } } -__attribute__((noinline)) void task_irq_dispatch(uint32_t intr) { +__attribute__((noinline)) void task_irq_dispatch(uint32_t intr) { // AIC irq dispatch if (intr > irq_count) { - panic("unmask_interrupt: irqno out of bounds (%d > %d)", intr, irq_count); + panic("task_irq_dispatch: irqno out of bounds (%d > %d)", intr, irq_count); } struct task* irq_handler = irqvecs[intr]; if (irq_handler) { + irq_handler->irq_controller = gInterruptDevice; // AIC irq_handler->irq_type = intr; + irq_handler->irq_context = interrupt_context(intr); task_switch_irq(irq_handler); } else { fiprintf(stderr, "couldn't find irq handler for %x\n", intr); panic("task_irq_dispatch"); } } - extern struct task sched_task; extern uint32_t preempt_ctr; void task_yield_preemption() { @@ -603,7 +620,7 @@ struct task* task_create_extended(const char* name, void (*entry)(), int task_ty return task; } -void task_bind_to_irq(struct task* task, int irq) { +void task_bind_to_irq(struct task* task, uint32_t irq) { disable_interrupts(); register_irq_handler(irq, task); unmask_interrupt(irq); @@ -651,9 +668,15 @@ void task_exit_irq() if (task_current()->flags & TASK_PREEMPT) { disable_interrupts(); if (!(task_current()->flags & TASK_LINKED)) panic("task_exit_irq on unlinked preempt irq handler?"); - task_unlink(task_current()); if (task_current()->flags & TASK_MASK_NEXT_IRQ) task_current()->flags &= ~TASK_MASK_NEXT_IRQ; - else unmask_interrupt(task_current()->irq_type); // re-arm IRQ + else { + if (!task_current()->irq_controller || task_current()->irq_controller == gInterruptDevice) { + unmask_interrupt(task_current()->irq_type); + } else { + hal_controller_unmask_interrupt(task_current()->irq_controller, task_current()->irq_type); // re-arm IRQ + } + } + task_unlink(task_current()); if (dis_int_count != 1) { panic("irq handler yielded with interrupts held"); } @@ -663,6 +686,21 @@ void task_exit_irq() if (!task_current()->irq_ret) panic("task_exit_irq must be invoked from enabled irq context"); _task_switch(task_current()->irq_ret); } +void task_exit_irq_continuation(struct task* continue_to_task, struct hal_device* spoofed_irq_controller, uint32_t spoofed_irq_type, void* spoofed_context) { + if (task_current()->flags & TASK_PREEMPT) { + panic("task_irq_continuation must be invoked on cooperative IRQ handlers only!"); + } + + continue_to_task->irq_controller = spoofed_irq_controller; + continue_to_task->irq_type = spoofed_irq_type; + continue_to_task->irq_context = spoofed_context; + task_current()->irq_continue = continue_to_task; + + if (!(task_current()->flags & TASK_IRQ_HANDLER)) return task_yield(); + if (!task_current()->irq_ret) panic("task_exit_irq must be invoked from enabled irq context"); + _task_switch(task_current()->irq_ret); +} + extern uint64_t dis_int_count; void task_switch(struct task* new) { diff --git a/src/kernel/task.h b/src/kernel/task.h index 0af72478..e5a18681 100644 --- a/src/kernel/task.h +++ b/src/kernel/task.h @@ -128,6 +128,9 @@ struct task { // a task is a thread-like execution environment, executing under lock task_lock; struct proc* proc; struct task* proc_task_list_next; // only tasks created with proc_create_task are queued here + struct task* irq_continue; + void* irq_context; + struct hal_device* irq_controller; }; extern void task_alloc_fast_stacks(struct task* task);