diff options
author | Achin Gupta <achin.gupta@arm.com> | 2013-10-25 09:08:21 +0100 |
---|---|---|
committer | James Morrissey <james.morrissey@arm.com> | 2013-10-25 09:37:16 +0100 |
commit | 4f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a56 (patch) | |
tree | 475db5d74370cb62b02afab0900774955a59702f /lib | |
download | arm-trusted-firmware-4f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a56.tar.gz |
ARMv8 Trusted Firmware release v0.2v0.2
Diffstat (limited to 'lib')
-rw-r--r-- | lib/arch/aarch64/cache_helpers.S | 233 | ||||
-rw-r--r-- | lib/arch/aarch64/misc_helpers.S | 274 | ||||
-rw-r--r-- | lib/arch/aarch64/sysreg_helpers.S | 1154 | ||||
-rw-r--r-- | lib/arch/aarch64/tlb_helpers.S | 111 | ||||
-rw-r--r-- | lib/mmio.c | 41 | ||||
-rw-r--r-- | lib/non-semihosting/ctype.h | 60 | ||||
-rw-r--r-- | lib/non-semihosting/mem.c | 103 | ||||
-rw-r--r-- | lib/non-semihosting/std.c | 106 | ||||
-rw-r--r-- | lib/non-semihosting/strcmp.c | 49 | ||||
-rw-r--r-- | lib/non-semihosting/string.c | 40 | ||||
-rw-r--r-- | lib/non-semihosting/strlen.c | 46 | ||||
-rw-r--r-- | lib/non-semihosting/strncmp.c | 52 | ||||
-rw-r--r-- | lib/non-semihosting/strncpy.c | 62 | ||||
-rw-r--r-- | lib/non-semihosting/strsep.c | 74 | ||||
-rw-r--r-- | lib/non-semihosting/strtol.c | 146 | ||||
-rw-r--r-- | lib/non-semihosting/strtoull.c | 117 | ||||
-rw-r--r-- | lib/non-semihosting/subr_prf.c | 557 | ||||
-rw-r--r-- | lib/semihosting/aarch64/semihosting_call.S | 37 | ||||
-rw-r--r-- | lib/semihosting/semihosting.c | 234 | ||||
-rw-r--r-- | lib/sync/locks/bakery/bakery_lock.c | 104 | ||||
-rw-r--r-- | lib/sync/locks/exclusive/spinlock.S | 50 |
21 files changed, 3650 insertions, 0 deletions
diff --git a/lib/arch/aarch64/cache_helpers.S b/lib/arch/aarch64/cache_helpers.S new file mode 100644 index 0000000..b8a5608 --- /dev/null +++ b/lib/arch/aarch64/cache_helpers.S @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <arch_helpers.h> +#include <asm_macros.S> + + .globl dcisw + .globl dccisw + .globl dccsw + .globl dccvac + .globl dcivac + .globl dccivac + .globl dccvau + .globl dczva + .globl flush_dcache_range + .globl inv_dcache_range + .globl dcsw_op_louis + .globl dcsw_op_all + + .section .text, "ax"; .align 3 + +dcisw:; .type dcisw, %function + dc isw, x0 + dsb sy + isb + ret + + +dccisw:; .type dccisw, %function + dc cisw, x0 + dsb sy + isb + ret + + +dccsw:; .type dccsw, %function + dc csw, x0 + dsb sy + isb + ret + + +dccvac:; .type dccvac, %function + dc cvac, x0 + dsb sy + isb + ret + + +dcivac:; .type dcivac, %function + dc ivac, x0 + dsb sy + isb + ret + + +dccivac:; .type dccivac, %function + dc civac, x0 + dsb sy + isb + ret + + +dccvau:; .type dccvau, %function + dc cvau, x0 + dsb sy + isb + ret + + +dczva:; .type dczva, %function + dc zva, x0 + dsb sy + isb + ret + + + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +flush_dcache_range:; .type flush_dcache_range, %function + dcache_line_size x2, x3 + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +flush_loop: + dc civac, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo flush_loop + dsb sy + ret + + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +inv_dcache_range:; .type inv_dcache_range, %function + dcache_line_size x2, x3 + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +inv_loop: + dc ivac, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo inv_loop + dsb sy + ret + + + /* ------------------------------------------ + * Data cache operations by set/way to the + * level specified + * ------------------------------------------ + * ---------------------------------- + * Call this func with the clidr in + * x0, starting cache level in x10, + * last cache level in x3 & cm op in + * x14 + * ---------------------------------- + */ +dcsw_op:; .type dcsw_op, %function +all_start_at_level: + add x2, x10, x10, lsr #1 // work out 3x current cache level + lsr x1, x0, x2 // extract cache type bits from clidr + and x1, x1, #7 // mask of the bits for current cache only + cmp x1, #2 // see what cache we have at this level + b.lt skip // skip if no cache, or just i-cache + msr csselr_el1, x10 // select current cache level in csselr + isb // isb to sych the new cssr&csidr + mrs x1, ccsidr_el1 // read the new ccsidr + and x2, x1, #7 // extract the length of the cache lines + add x2, x2, #4 // add 4 (line length offset) + mov x4, #0x3ff + and x4, x4, x1, lsr #3 // find maximum number on the way size + clz w5, w4 // find bit position of way size increment + mov x7, #0x7fff + and x7, x7, x1, lsr #13 // extract max number of the index size +loop2: + mov x9, x4 // create working copy of max way size +loop3: + lsl x6, x9, x5 + orr x11, x10, x6 // factor way and cache number into x11 + lsl x6, x7, x2 + orr x11, x11, x6 // factor index number into x11 + mov x12, x0 + mov x13, x30 // lr + mov x0, x11 + blr x14 + mov x0, x12 + mov x30, x13 // lr + subs x9, x9, #1 // decrement the way + b.ge loop3 + subs x7, x7, #1 // decrement the index + b.ge loop2 +skip: + add x10, x10, #2 // increment cache number + cmp x3, x10 + b.gt all_start_at_level +finished: + mov x10, #0 // swith back to cache level 0 + msr csselr_el1, x10 // select current cache level in csselr + dsb sy + isb + ret + + +do_dcsw_op:; .type do_dcsw_op, %function + cbz x3, exit + cmp x0, #DCISW + b.eq dc_isw + cmp x0, #DCCISW + b.eq dc_cisw + cmp x0, #DCCSW + b.eq dc_csw +dc_isw: + mov x0, x9 + adr x14, dcisw + b dcsw_op +dc_cisw: + mov x0, x9 + adr x14, dccisw + b dcsw_op +dc_csw: + mov x0, x9 + adr x14, dccsw + b dcsw_op +exit: + ret + + +dcsw_op_louis:; .type dcsw_op_louis, %function + dsb sy + setup_dcsw_op_args x10, x3, x9, #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT + b do_dcsw_op + + +dcsw_op_all:; .type dcsw_op_all, %function + dsb sy + setup_dcsw_op_args x10, x3, x9, #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT + b do_dcsw_op diff --git a/lib/arch/aarch64/misc_helpers.S b/lib/arch/aarch64/misc_helpers.S new file mode 100644 index 0000000..8c1f740 --- /dev/null +++ b/lib/arch/aarch64/misc_helpers.S @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <arch_helpers.h> + + .globl enable_irq + .globl disable_irq + + .globl enable_fiq + .globl disable_fiq + + .globl enable_serror + .globl disable_serror + + .globl read_daif + .globl write_daif + + .globl read_spsr + .globl read_spsr_el1 + .globl read_spsr_el2 + .globl read_spsr_el3 + + .globl write_spsr + .globl write_spsr_el1 + .globl write_spsr_el2 + .globl write_spsr_el3 + + .globl read_elr + .globl read_elr_el1 + .globl read_elr_el2 + .globl read_elr_el3 + + .globl write_elr + .globl write_elr_el1 + .globl write_elr_el2 + .globl write_elr_el3 + + .globl get_afflvl_shift + .globl mpidr_mask_lower_afflvls + .globl dsb + .globl isb + .globl sev + .globl wfe + .globl wfi + .globl eret + .globl smc + + + .section .text, "ax" + +get_afflvl_shift:; .type get_afflvl_shift, %function + cmp x0, #3 + cinc x0, x0, eq + mov x1, #MPIDR_AFFLVL_SHIFT + lsl x0, x0, x1 + ret + +mpidr_mask_lower_afflvls:; .type mpidr_mask_lower_afflvls, %function + cmp x1, #3 + cinc x1, x1, eq + mov x2, #MPIDR_AFFLVL_SHIFT + lsl x2, x1, x2 + lsr x0, x0, x2 + lsl x0, x0, x2 + ret + + /* ----------------------------------------------------- + * Asynchronous exception manipulation accessors + * ----------------------------------------------------- + */ +enable_irq:; .type enable_irq, %function + msr daifclr, #DAIF_IRQ_BIT + ret + + +enable_fiq:; .type enable_fiq, %function + msr daifclr, #DAIF_FIQ_BIT + ret + + +enable_serror:; .type enable_serror, %function + msr daifclr, #DAIF_ABT_BIT + ret + + +disable_irq:; .type disable_irq, %function + msr daifset, #DAIF_IRQ_BIT + ret + + +disable_fiq:; .type disable_fiq, %function + msr daifset, #DAIF_FIQ_BIT + ret + + +disable_serror:; .type disable_serror, %function + msr daifset, #DAIF_ABT_BIT + ret + + +read_daif:; .type read_daif, %function + mrs x0, daif + ret + + +write_daif:; .type write_daif, %function + msr daif, x0 + ret + + +read_spsr:; .type read_spsr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_spsr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_spsr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_spsr_el3 + + +read_spsr_el1:; .type read_spsr_el1, %function + mrs x0, spsr_el1 + ret + + +read_spsr_el2:; .type read_spsr_el2, %function + mrs x0, spsr_el2 + ret + + +read_spsr_el3:; .type read_spsr_el3, %function + mrs x0, spsr_el3 + ret + + +write_spsr:; .type write_spsr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_spsr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_spsr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_spsr_el3 + + +write_spsr_el1:; .type write_spsr_el1, %function + msr spsr_el1, x0 + isb + ret + + +write_spsr_el2:; .type write_spsr_el2, %function + msr spsr_el2, x0 + isb + ret + + +write_spsr_el3:; .type write_spsr_el3, %function + msr spsr_el3, x0 + isb + ret + + +read_elr:; .type read_elr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_elr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_elr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_elr_el3 + + +read_elr_el1:; .type read_elr_el1, %function + mrs x0, elr_el1 + ret + + +read_elr_el2:; .type read_elr_el2, %function + mrs x0, elr_el2 + ret + + +read_elr_el3:; .type read_elr_el3, %function + mrs x0, elr_el3 + ret + + +write_elr:; .type write_elr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_elr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_elr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_elr_el3 + + +write_elr_el1:; .type write_elr_el1, %function + msr elr_el1, x0 + isb + ret + + +write_elr_el2:; .type write_elr_el2, %function + msr elr_el2, x0 + isb + ret + + +write_elr_el3:; .type write_elr_el3, %function + msr elr_el3, x0 + isb + ret + + +dsb:; .type dsb, %function + dsb sy + ret + + +isb:; .type isb, %function + isb + ret + + +sev:; .type sev, %function + sev + ret + + +wfe:; .type wfe, %function + wfe + ret + + +wfi:; .type wfi, %function + wfi + ret + + +eret:; .type eret, %function + eret + + +smc:; .type smc, %function + smc #0 diff --git a/lib/arch/aarch64/sysreg_helpers.S b/lib/arch/aarch64/sysreg_helpers.S new file mode 100644 index 0000000..e68192f --- /dev/null +++ b/lib/arch/aarch64/sysreg_helpers.S @@ -0,0 +1,1154 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <arch_helpers.h> + + .globl read_vbar + .globl read_vbar_el1 + .globl read_vbar_el2 + .globl read_vbar_el3 + .globl write_vbar + .globl write_vbar_el1 + .globl write_vbar_el2 + .globl write_vbar_el3 + + .globl read_sctlr + .globl read_sctlr_el1 + .globl read_sctlr_el2 + .globl read_sctlr_el3 + .globl write_sctlr + .globl write_sctlr_el1 + .globl write_sctlr_el2 + .globl write_sctlr_el3 + + .globl read_actlr + .globl read_actlr_el1 + .globl read_actlr_el2 + .globl read_actlr_el3 + .globl write_actlr + .globl write_actlr_el1 + .globl write_actlr_el2 + .globl write_actlr_el3 + + .globl read_esr + .globl read_esr_el1 + .globl read_esr_el2 + .globl read_esr_el3 + .globl write_esr + .globl write_esr_el1 + .globl write_esr_el2 + .globl write_esr_el3 + + .globl read_afsr0 + .globl read_afsr0_el1 + .globl read_afsr0_el2 + .globl read_afsr0_el3 + .globl write_afsr0 + .globl write_afsr0_el1 + .globl write_afsr0_el2 + .globl write_afsr0_el3 + + .globl read_afsr1 + .globl read_afsr1_el1 + .globl read_afsr1_el2 + .globl read_afsr1_el3 + .globl write_afsr1 + .globl write_afsr1_el1 + .globl write_afsr1_el2 + .globl write_afsr1_el3 + + .globl read_far + .globl read_far_el1 + .globl read_far_el2 + .globl read_far_el3 + .globl write_far + .globl write_far_el1 + .globl write_far_el2 + .globl write_far_el3 + + .globl read_mair + .globl read_mair_el1 + .globl read_mair_el2 + .globl read_mair_el3 + .globl write_mair + .globl write_mair_el1 + .globl write_mair_el2 + .globl write_mair_el3 + + .globl read_amair + .globl read_amair_el1 + .globl read_amair_el2 + .globl read_amair_el3 + .globl write_amair + .globl write_amair_el1 + .globl write_amair_el2 + .globl write_amair_el3 + + .globl read_rvbar + .globl read_rvbar_el1 + .globl read_rvbar_el2 + .globl read_rvbar_el3 + + .globl read_rmr + .globl read_rmr_el1 + .globl read_rmr_el2 + .globl read_rmr_el3 + .globl write_rmr + .globl write_rmr_el1 + .globl write_rmr_el2 + .globl write_rmr_el3 + + .globl read_tcr + .globl read_tcr_el1 + .globl read_tcr_el2 + .globl read_tcr_el3 + .globl write_tcr + .globl write_tcr_el1 + .globl write_tcr_el2 + .globl write_tcr_el3 + + .globl read_cptr + .globl read_cptr_el2 + .globl read_cptr_el3 + .globl write_cptr + .globl write_cptr_el2 + .globl write_cptr_el3 + + .globl read_ttbr0 + .globl read_ttbr0_el1 + .globl read_ttbr0_el2 + .globl read_ttbr0_el3 + .globl write_ttbr0 + .globl write_ttbr0_el1 + .globl write_ttbr0_el2 + .globl write_ttbr0_el3 + + .globl read_ttbr1 + .globl read_ttbr1_el1 + .globl read_ttbr1_el2 + .globl write_ttbr1 + .globl write_ttbr1_el1 + .globl write_ttbr1_el2 + + .globl read_cpacr + .globl write_cpacr + + .globl read_cntfrq + .globl write_cntfrq + + .globl read_cpuectlr + .globl write_cpuectlr + + .globl read_cnthctl_el2 + .globl write_cnthctl_el2 + + .globl read_cntfrq_el0 + .globl write_cntfrq_el0 + + .globl read_scr + .globl write_scr + + .globl read_hcr + .globl write_hcr + + .globl read_midr + .globl read_mpidr + + .globl read_current_el + .globl read_id_pfr1_el1 + .globl read_id_aa64pfr0_el1 + +#if SUPPORT_VFP + .globl enable_vfp + .globl read_fpexc + .globl write_fpexc +#endif + + + .section .text, "ax" + +read_current_el:; .type read_current_el, %function + mrs x0, CurrentEl + ret + + +read_id_pfr1_el1:; .type read_id_pfr1_el1, %function + mrs x0, id_pfr1_el1 + ret + + +read_id_aa64pfr0_el1:; .type read_id_aa64pfr0_el1, %function + mrs x0, id_aa64pfr0_el1 + ret + + + /* ----------------------------------------------------- + * VBAR accessors + * ----------------------------------------------------- + */ +read_vbar:; .type read_vbar, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_vbar_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_vbar_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_vbar_el3 + + +read_vbar_el1:; .type read_vbar_el1, %function + mrs x0, vbar_el1 + ret + + +read_vbar_el2:; .type read_vbar_el2, %function + mrs x0, vbar_el2 + ret + + +read_vbar_el3:; .type read_vbar_el3, %function + mrs x0, vbar_el3 + ret + + +write_vbar:; .type write_vbar, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_vbar_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_vbar_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_vbar_el3 + + +write_vbar_el1:; .type write_vbar_el1, %function + msr vbar_el1, x0 + isb + ret + + +write_vbar_el2:; .type write_vbar_el2, %function + msr vbar_el2, x0 + isb + ret + + +write_vbar_el3:; .type write_vbar_el3, %function + msr vbar_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * AFSR0 accessors + * ----------------------------------------------------- + */ +read_afsr0:; .type read_afsr0, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_afsr0_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_afsr0_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_afsr0_el3 + + +read_afsr0_el1:; .type read_afsr0_el1, %function + mrs x0, afsr0_el1 + ret + + +read_afsr0_el2:; .type read_afsr0_el2, %function + mrs x0, afsr0_el2 + ret + + +read_afsr0_el3:; .type read_afsr0_el3, %function + mrs x0, afsr0_el3 + ret + + +write_afsr0:; .type write_afsr0, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_afsr0_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_afsr0_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_afsr0_el3 + + +write_afsr0_el1:; .type write_afsr0_el1, %function + msr afsr0_el1, x0 + isb + ret + + +write_afsr0_el2:; .type write_afsr0_el2, %function + msr afsr0_el2, x0 + isb + ret + + +write_afsr0_el3:; .type write_afsr0_el3, %function + msr afsr0_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * FAR accessors + * ----------------------------------------------------- + */ +read_far:; .type read_far, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_far_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_far_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_far_el3 + + +read_far_el1:; .type read_far_el1, %function + mrs x0, far_el1 + ret + + +read_far_el2:; .type read_far_el2, %function + mrs x0, far_el2 + ret + + +read_far_el3:; .type read_far_el3, %function + mrs x0, far_el3 + ret + + +write_far:; .type write_far, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_far_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_far_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_far_el3 + + +write_far_el1:; .type write_far_el1, %function + msr far_el1, x0 + isb + ret + + +write_far_el2:; .type write_far_el2, %function + msr far_el2, x0 + isb + ret + + +write_far_el3:; .type write_far_el3, %function + msr far_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * MAIR accessors + * ----------------------------------------------------- + */ +read_mair:; .type read_mair, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_mair_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_mair_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_mair_el3 + + +read_mair_el1:; .type read_mair_el1, %function + mrs x0, mair_el1 + ret + + +read_mair_el2:; .type read_mair_el2, %function + mrs x0, mair_el2 + ret + + +read_mair_el3:; .type read_mair_el3, %function + mrs x0, mair_el3 + ret + + +write_mair:; .type write_mair, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_mair_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_mair_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_mair_el3 + + +write_mair_el1:; .type write_mair_el1, %function + msr mair_el1, x0 + isb + ret + + +write_mair_el2:; .type write_mair_el2, %function + msr mair_el2, x0 + isb + ret + + +write_mair_el3:; .type write_mair_el3, %function + msr mair_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * AMAIR accessors + * ----------------------------------------------------- + */ +read_amair:; .type read_amair, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_amair_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_amair_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_amair_el3 + + +read_amair_el1:; .type read_amair_el1, %function + mrs x0, amair_el1 + ret + + +read_amair_el2:; .type read_amair_el2, %function + mrs x0, amair_el2 + ret + + +read_amair_el3:; .type read_amair_el3, %function + mrs x0, amair_el3 + ret + + +write_amair:; .type write_amair, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_amair_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_amair_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_amair_el3 + + +write_amair_el1:; .type write_amair_el1, %function + msr amair_el1, x0 + isb + ret + + +write_amair_el2:; .type write_amair_el2, %function + msr amair_el2, x0 + isb + ret + + +write_amair_el3:; .type write_amair_el3, %function + msr amair_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * RVBAR accessors + * ----------------------------------------------------- + */ +read_rvbar:; .type read_rvbar, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_rvbar_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_rvbar_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_rvbar_el3 + + +read_rvbar_el1:; .type read_rvbar_el1, %function + mrs x0, rvbar_el1 + ret + + +read_rvbar_el2:; .type read_rvbar_el2, %function + mrs x0, rvbar_el2 + ret + + +read_rvbar_el3:; .type read_rvbar_el3, %function + mrs x0, rvbar_el3 + ret + + + /* ----------------------------------------------------- + * RMR accessors + * ----------------------------------------------------- + */ +read_rmr:; .type read_rmr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_rmr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_rmr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_rmr_el3 + + +read_rmr_el1:; .type read_rmr_el1, %function + mrs x0, rmr_el1 + ret + + +read_rmr_el2:; .type read_rmr_el2, %function + mrs x0, rmr_el2 + ret + + +read_rmr_el3:; .type read_rmr_el3, %function + mrs x0, rmr_el3 + ret + + +write_rmr:; .type write_rmr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_rmr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_rmr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_rmr_el3 + + +write_rmr_el1:; .type write_rmr_el1, %function + msr rmr_el1, x0 + isb + ret + + +write_rmr_el2:; .type write_rmr_el2, %function + msr rmr_el2, x0 + isb + ret + + +write_rmr_el3:; .type write_rmr_el3, %function + msr rmr_el3, x0 + isb + ret + + +read_afsr1:; .type read_afsr1, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_afsr1_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_afsr1_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_afsr1_el3 + + + /* ----------------------------------------------------- + * AFSR1 accessors + * ----------------------------------------------------- + */ +read_afsr1_el1:; .type read_afsr1_el1, %function + mrs x0, afsr1_el1 + ret + + +read_afsr1_el2:; .type read_afsr1_el2, %function + mrs x0, afsr1_el2 + ret + + +read_afsr1_el3:; .type read_afsr1_el3, %function + mrs x0, afsr1_el3 + ret + + +write_afsr1:; .type write_afsr1, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_afsr1_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_afsr1_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_afsr1_el3 + + +write_afsr1_el1:; .type write_afsr1_el1, %function + msr afsr1_el1, x0 + isb + ret + + +write_afsr1_el2:; .type write_afsr1_el2, %function + msr afsr1_el2, x0 + isb + ret + + +write_afsr1_el3:; .type write_afsr1_el3, %function + msr afsr1_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * SCTLR accessors + * ----------------------------------------------------- + */ +read_sctlr:; .type read_sctlr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_sctlr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_sctlr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_sctlr_el3 + + +read_sctlr_el1:; .type read_sctlr_el1, %function + mrs x0, sctlr_el1 + ret + + +read_sctlr_el2:; .type read_sctlr_el2, %function + mrs x0, sctlr_el2 + ret + + +read_sctlr_el3:; .type read_sctlr_el3, %function + mrs x0, sctlr_el3 + ret + + +write_sctlr:; .type write_sctlr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_sctlr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_sctlr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_sctlr_el3 + + +write_sctlr_el1:; .type write_sctlr_el1, %function + msr sctlr_el1, x0 + dsb sy + isb + ret + + +write_sctlr_el2:; .type write_sctlr_el2, %function + msr sctlr_el2, x0 + dsb sy + isb + ret + + +write_sctlr_el3:; .type write_sctlr_el3, %function + msr sctlr_el3, x0 + dsb sy + isb + ret + + + /* ----------------------------------------------------- + * ACTLR accessors + * ----------------------------------------------------- + */ +read_actlr:; .type read_actlr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_actlr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_actlr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_actlr_el3 + + +read_actlr_el1:; .type read_actlr_el1, %function + mrs x0, actlr_el1 + ret + + +read_actlr_el2:; .type read_actlr_el2, %function + mrs x0, actlr_el2 + ret + + +read_actlr_el3:; .type read_actlr_el3, %function + mrs x0, actlr_el3 + ret + + +write_actlr:; .type write_actlr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_actlr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_actlr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_actlr_el3 + + +write_actlr_el1:; .type write_actlr_el1, %function + msr actlr_el1, x0 + dsb sy + isb + ret + + +write_actlr_el2:; .type write_actlr_el2, %function + msr actlr_el2, x0 + dsb sy + isb + ret + + +write_actlr_el3:; .type write_actlr_el3, %function + msr actlr_el3, x0 + dsb sy + isb + ret + + + /* ----------------------------------------------------- + * ESR accessors + * ----------------------------------------------------- + */ +read_esr:; .type read_esr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_esr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_esr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_esr_el3 + + +read_esr_el1:; .type read_esr_el1, %function + mrs x0, esr_el1 + ret + + +read_esr_el2:; .type read_esr_el2, %function + mrs x0, esr_el2 + ret + + +read_esr_el3:; .type read_esr_el3, %function + mrs x0, esr_el3 + ret + + +write_esr:; .type write_esr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_esr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_esr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_esr_el3 + + +write_esr_el1:; .type write_esr_el1, %function + msr esr_el1, x0 + dsb sy + isb + ret + + +write_esr_el2:; .type write_esr_el2, %function + msr esr_el2, x0 + dsb sy + isb + ret + + +write_esr_el3:; .type write_esr_el3, %function + msr esr_el3, x0 + dsb sy + isb + ret + + + /* ----------------------------------------------------- + * TCR accessors + * ----------------------------------------------------- + */ +read_tcr:; .type read_tcr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_tcr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_tcr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_tcr_el3 + + +read_tcr_el1:; .type read_tcr_el1, %function + mrs x0, tcr_el1 + ret + + +read_tcr_el2:; .type read_tcr_el2, %function + mrs x0, tcr_el2 + ret + + +read_tcr_el3:; .type read_tcr_el3, %function + mrs x0, tcr_el3 + ret + + +write_tcr:; .type write_tcr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_tcr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_tcr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_tcr_el3 + + +write_tcr_el1:; .type write_tcr_el1, %function + msr tcr_el1, x0 + dsb sy + isb + ret + + +write_tcr_el2:; .type write_tcr_el2, %function + msr tcr_el2, x0 + dsb sy + isb + ret + + +write_tcr_el3:; .type write_tcr_el3, %function + msr tcr_el3, x0 + dsb sy + isb + ret + + + /* ----------------------------------------------------- + * CPTR accessors + * ----------------------------------------------------- + */ +read_cptr:; .type read_cptr, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_cptr_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_cptr_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_cptr_el3 + + +read_cptr_el1:; .type read_cptr_el1, %function + b read_cptr_el1 + ret + + +read_cptr_el2:; .type read_cptr_el2, %function + mrs x0, cptr_el2 + ret + + +read_cptr_el3:; .type read_cptr_el3, %function + mrs x0, cptr_el3 + ret + + +write_cptr:; .type write_cptr, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_cptr_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_cptr_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_cptr_el3 + + +write_cptr_el1:; .type write_cptr_el1, %function + b write_cptr_el1 + + +write_cptr_el2:; .type write_cptr_el2, %function + msr cptr_el2, x0 + dsb sy + isb + ret + + +write_cptr_el3:; .type write_cptr_el3, %function + msr cptr_el3, x0 + dsb sy + isb + ret + + + /* ----------------------------------------------------- + * TTBR0 accessors + * ----------------------------------------------------- + */ +read_ttbr0:; .type read_ttbr0, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_ttbr0_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_ttbr0_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_ttbr0_el3 + + +read_ttbr0_el1:; .type read_ttbr0_el1, %function + mrs x0, ttbr0_el1 + ret + + +read_ttbr0_el2:; .type read_ttbr0_el2, %function + mrs x0, ttbr0_el2 + ret + + +read_ttbr0_el3:; .type read_ttbr0_el3, %function + mrs x0, ttbr0_el3 + ret + + +write_ttbr0:; .type write_ttbr0, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_ttbr0_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_ttbr0_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_ttbr0_el3 + + +write_ttbr0_el1:; .type write_ttbr0_el1, %function + msr ttbr0_el1, x0 + isb + ret + + +write_ttbr0_el2:; .type write_ttbr0_el2, %function + msr ttbr0_el2, x0 + isb + ret + + +write_ttbr0_el3:; .type write_ttbr0_el3, %function + msr ttbr0_el3, x0 + isb + ret + + + /* ----------------------------------------------------- + * TTBR1 accessors + * ----------------------------------------------------- + */ +read_ttbr1:; .type read_ttbr1, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq read_ttbr1_el1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq read_ttbr1_el2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq read_ttbr1_el3 + + +read_ttbr1_el1:; .type read_ttbr1_el1, %function + mrs x0, ttbr1_el1 + ret + + +read_ttbr1_el2:; .type read_ttbr1_el2, %function + b read_ttbr1_el2 + + +read_ttbr1_el3:; .type read_ttbr1_el3, %function + b read_ttbr1_el3 + + +write_ttbr1:; .type write_ttbr1, %function + mrs x1, CurrentEl + cmp x1, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq write_ttbr1_el1 + cmp x1, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq write_ttbr1_el2 + cmp x1, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq write_ttbr1_el3 + + +write_ttbr1_el1:; .type write_ttbr1_el1, %function + msr ttbr1_el1, x0 + isb + ret + + +write_ttbr1_el2:; .type write_ttbr1_el2, %function + b write_ttbr1_el2 + + +write_ttbr1_el3:; .type write_ttbr1_el3, %function + b write_ttbr1_el3 + + +read_hcr:; .type read_hcr, %function + mrs x0, hcr_el2 + ret + + +write_hcr:; .type write_hcr, %function + msr hcr_el2, x0 + dsb sy + isb + ret + + +read_cpacr:; .type read_cpacr, %function + mrs x0, cpacr_el1 + ret + + +write_cpacr:; .type write_cpacr, %function + msr cpacr_el1, x0 + ret + + +read_cntfrq_el0:; .type read_cntfrq_el0, %function + mrs x0, cntfrq_el0 + ret + + +write_cntfrq_el0:; .type write_cntfrq_el0, %function + msr cntfrq_el0, x0 + ret + + +read_cpuectlr:; .type read_cpuectlr, %function + mrs x0, CPUECTLR_EL1 + ret + + +write_cpuectlr:; .type write_cpuectlr, %function + msr CPUECTLR_EL1, x0 + dsb sy + isb + ret + + +read_cnthctl_el2:; .type read_cnthctl_el2, %function + mrs x0, cnthctl_el2 + ret + + +write_cnthctl_el2:; .type write_cnthctl_el2, %function + msr cnthctl_el2, x0 + ret + + +read_cntfrq:; .type read_cntfrq, %function + mrs x0, cntfrq_el0 + ret + + +write_cntfrq:; .type write_cntfrq, %function + msr cntfrq_el0, x0 + ret + + +write_scr:; .type write_scr, %function + msr scr_el3, x0 + dsb sy + isb + ret + + +read_scr:; .type read_scr, %function + mrs x0, scr_el3 + ret + + +read_midr:; .type read_midr, %function + mrs x0, midr_el1 + ret + + +read_mpidr:; .type read_mpidr, %function + mrs x0, mpidr_el1 + ret + + +#if SUPPORT_VFP +enable_vfp:; .type enable_vfp, %function + mrs x0, cpacr_el1 + orr x0, x0, #CPACR_VFP_BITS + msr cpacr_el1, x0 + mrs x0, cptr_el3 + mov x1, #AARCH64_CPTR_TFP + bic x0, x0, x1 + msr cptr_el3, x0 + ret + + + // int read_fpexc(void) +read_fpexc:; .type read_fpexc, %function + b read_fpexc + ret + + + // void write_fpexc(int fpexc) +write_fpexc:; .type write_fpexc, %function + b write_fpexc + ret + +#endif diff --git a/lib/arch/aarch64/tlb_helpers.S b/lib/arch/aarch64/tlb_helpers.S new file mode 100644 index 0000000..8377f2c --- /dev/null +++ b/lib/arch/aarch64/tlb_helpers.S @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <arch_helpers.h> + + .globl tlbiall + .globl tlbiallis + .globl tlbialle1 + .globl tlbialle1is + .globl tlbialle2 + .globl tlbialle2is + .globl tlbialle3 + .globl tlbialle3is + .globl tlbivmalle1 + + + .section .text, "ax" + +tlbiall:; .type tlbiall, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq tlbialle1 + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq tlbialle2 + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq tlbialle3 + + +tlbiallis:; .type tlbiallis, %function + mrs x0, CurrentEl + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq tlbialle1is + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq tlbialle2is + cmp x0, #(MODE_EL3 << MODE_EL_SHIFT) + b.eq tlbialle3is + + +tlbialle1:; .type tlbialle1, %function + tlbi alle1 + dsb sy + isb + ret + + +tlbialle1is:; .type tlbialle1is, %function + tlbi alle1is + dsb sy + isb + ret + + +tlbialle2:; .type tlbialle2, %function + tlbi alle2 + dsb sy + isb + ret + + +tlbialle2is:; .type tlbialle2is, %function + tlbi alle2is + dsb sy + isb + ret + + +tlbialle3:; .type tlbialle3, %function + tlbi alle3 + dsb sy + isb + ret + + +tlbialle3is:; .type tlbialle3is, %function + tlbi alle3is + dsb sy + isb + ret + +tlbivmalle1:; .type tlbivmalle1, %function + tlbi vmalle1 + dsb sy + isb + ret diff --git a/lib/mmio.c b/lib/mmio.c new file mode 100644 index 0000000..bf35e36 --- /dev/null +++ b/lib/mmio.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <stdint.h> + +void mmio_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t*)addr = value; +} + +unsigned mmio_read_32(uintptr_t addr) +{ + return *(volatile uint32_t*)addr; +} diff --git a/lib/non-semihosting/ctype.h b/lib/non-semihosting/ctype.h new file mode 100644 index 0000000..88e7da1 --- /dev/null +++ b/lib/non-semihosting/ctype.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1982, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: include/lib/ctype.h + */ + +#ifndef _SYS_CTYPE_H_ +#define _SYS_CTYPE_H_ + +#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r')) +#define isascii(c) (((c) & ~0x7f) == 0) +#define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#define islower(c) ((c) >= 'a' && (c) <= 'z') +#define isalpha(c) (isupper(c) || islower(c)) +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#define isxdigit(c) (isdigit(c) \ + || ((c) >= 'A' && (c) <= 'F') \ + || ((c) >= 'a' && (c) <= 'f')) +#define isprint(c) ((c) >= ' ' && (c) <= '~') + +#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) +#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z'))) + +#endif /* !_SYS_CTYPE_H_ */ diff --git a/lib/non-semihosting/mem.c b/lib/non-semihosting/mem.c new file mode 100644 index 0000000..bca9ab5 --- /dev/null +++ b/lib/non-semihosting/mem.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <stddef.h> /* size_t */ + +/* + * Fill @count bytes of memory pointed to by @dst with @val + */ +void *memset(void *dst, int val, size_t count) +{ + char *ptr = dst; + + while (count--) + *ptr++ = val; + + return dst; +} + +/* + * Compare @len bytes of @s1 and @s2 + */ +int memcmp(const void *s1, const void *s2, size_t len) +{ + const char *s = s1; + const char *d = s2; + char dc; + char sc; + + while (len--) { + sc = *s++; + dc = *d++; + if (sc - dc) + return (sc - dc); + } + + return 0; +} + + +/* + * Move @len bytes from @src to @dst + */ +void *memmove(void *dst, const void *src, size_t len) +{ + const char *s = src; + char *d = dst; + + while (len--) + *d++ = *s++; + return d; +} + +/* + * Copy @len bytes from @src to @dst + */ +void *memcpy(void *dst, const void *src, size_t len) +{ + return memmove(dst, src, len); +} + + +/* + * Scan @len bytes of @src for value @c + */ +void *memchr(const void *src, int c, size_t len) +{ + const char *s = src; + + while (len--) { + if (*s == c) + return (void *) s; + s++; + } + + return NULL; +} diff --git a/lib/non-semihosting/std.c b/lib/non-semihosting/std.c new file mode 100644 index 0000000..ea91d5f --- /dev/null +++ b/lib/non-semihosting/std.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <stdio.h> +#include <console.h> + +#if defined (__GNUC__) + +#include <stdio.h> +#include <stddef.h> /* size_t */ +#include <stdarg.h> /* va_list */ + +// Code from VTB. +#include "mem.c" + +// Make mem functions that will operate on DEV mem. "memset_io"? + + +//Code from VTB +#include "strlen.c" + +int puts(const char *s) +{ + int count = 0; + while(*s) + { + if (console_putc(*s++)) { + count++; + } else { + count = EOF; // -1 in stdio.h + break; + } + } + return count; +} + +// From VTB +#include "ctype.h" +#include "subr_prf.c" + + // Choose max of 128 chars for now. +#define PRINT_BUFFER_SIZE 128 +int printf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + char buf[PRINT_BUFFER_SIZE]; + vsnprintf(buf, sizeof(buf) - 1, fmt, args); + buf[PRINT_BUFFER_SIZE - 1] = '\0'; + return puts(buf); +} + + +// I just made this up. Probably make it beter. +void __assert_func (const char *file, int l, const char *func, const char *error) +{ + printf("ASSERT: %s <%d> : %s\n\r", func, l, error); + while(1); +} + +extern void __assert_fail (const char *assertion, const char *file, + unsigned int line, const char *function) +{ + printf("ASSERT: %s <%d> : %s\n\r", function, line, assertion); + while(1); +} + + +// I just made this up. Probably make it beter. +void abort (void) +{ + printf("ABORT\n\r"); + while(1); +} + + +#else +#error "No standard library binding defined." +#endif diff --git a/lib/non-semihosting/strcmp.c b/lib/non-semihosting/strcmp.c new file mode 100644 index 0000000..e5921ba --- /dev/null +++ b/lib/non-semihosting/strcmp.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strcmp.c + */ + +/* + * Compare strings. + */ +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2++) + if (*s1++ == '\0') + return (0); + return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); +} diff --git a/lib/non-semihosting/string.c b/lib/non-semihosting/string.c new file mode 100644 index 0000000..5bb01a1 --- /dev/null +++ b/lib/non-semihosting/string.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + + +#include "ctype.h" + +/* Return pointer to the first non-space character */ +const char *skip_spaces(const char *str) +{ + while (isspace(*str)) + ++str; + return str; +} diff --git a/lib/non-semihosting/strlen.c b/lib/non-semihosting/strlen.c new file mode 100644 index 0000000..5c1e7a6 --- /dev/null +++ b/lib/non-semihosting/strlen.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strlen.c + */ + +#include <stddef.h> + +size_t +strlen(str) + const char *str; +{ + register const char *s; + + for (s = str; *s; ++s); + return(s - str); +} diff --git a/lib/non-semihosting/strncmp.c b/lib/non-semihosting/strncmp.c new file mode 100644 index 0000000..984b7a0 --- /dev/null +++ b/lib/non-semihosting/strncmp.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strncmp.c + */ + +#include "types.h" + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(const unsigned char *)s1 - + *(const unsigned char *)(s2 - 1)); + if (*s1++ == '\0') + break; + } while (--n != 0); + return (0); +} diff --git a/lib/non-semihosting/strncpy.c b/lib/non-semihosting/strncpy.c new file mode 100644 index 0000000..56a8a69 --- /dev/null +++ b/lib/non-semihosting/strncpy.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strncpy.c + */ + +#include "types.h" + +/* + * Copy src to dst, truncating or null-padding to always copy n bytes. + * Return dst. + */ +char * +strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) { + char *d = dst; + const char *s = src; + + do { + if ((*d++ = *s++) == '\0') { + /* NUL pad the remaining n-1 bytes */ + while (--n != 0) + *d++ = '\0'; + break; + } + } while (--n != 0); + } + return (dst); +} diff --git a/lib/non-semihosting/strsep.c b/lib/non-semihosting/strsep.c new file mode 100644 index 0000000..1f80af4 --- /dev/null +++ b/lib/non-semihosting/strsep.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strsep.c + */ + +#include "types.h" + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) +{ + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/non-semihosting/strtol.c b/lib/non-semihosting/strtol.c new file mode 100644 index 0000000..4a5a404 --- /dev/null +++ b/lib/non-semihosting/strtol.c @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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: @(#)strtol.c 8.1 (Berkeley) 6/4/93 + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strtol.c + */ + +#include "types.h" +#include "ctype.h" +#include "limits.h" + +/* + * Convert a string to a long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +static long +bsd_strtol(nptr, endptr, base) + const char *nptr; + char **endptr; + int base; +{ + const char *s = nptr; + unsigned long acc; + unsigned char c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (!isascii(c)) + break; + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != 0) + *((const char **)endptr) = any ? s - 1 : nptr; + return (acc); +} + +int strict_strtol(const char *str, unsigned int base, long *result) +{ + if (*str == '-') + *result = 0 - bsd_strtol(str + 1, NULL, base); + else + *result = bsd_strtol(str, NULL, base); + return 0; +} + +int strict_strtoul(const char *str, unsigned int base, unsigned long *result) +{ + *result = bsd_strtol(str, NULL, base); + return 0; +} diff --git a/lib/non-semihosting/strtoull.c b/lib/non-semihosting/strtoull.c new file mode 100644 index 0000000..e46ef4c --- /dev/null +++ b/lib/non-semihosting/strtoull.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/strtoull.c + */ + +#include "types.h" +#include "ctype.h" +#include "limits.h" + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +static unsigned long long +bsd_strtoull(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + +int strict_strtoull(const char *str, unsigned int base, long long *result) +{ + *result = bsd_strtoull(str, NULL, base); + return 0; +} diff --git a/lib/non-semihosting/subr_prf.c b/lib/non-semihosting/subr_prf.c new file mode 100644 index 0000000..6e2a1ac --- /dev/null +++ b/lib/non-semihosting/subr_prf.c @@ -0,0 +1,557 @@ +/*- + * Copyright (c) 1986, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + */ + +/* + * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved. + * --------------------------------------------------------------- + * File: lib/subr_prf.c + */ + +/* +#include "types.h" +#include "varargs.h" +#include "ctype.h" +#include "string.h" +*/ +#include <stddef.h> +#include <sys/types.h> /* For ssize_t */ +#include <stdint.h> +#include <string.h> + +#include "ctype.h" + +typedef uint64_t uintmax_t; +typedef int64_t intmax_t; +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef int64_t quad_t; +typedef uint64_t u_quad_t; +typedef unsigned long u_long; +typedef unsigned short u_short; + +static inline int imax(int a, int b) { return (a > b ? a : b); } + +/* + * Note that stdarg.h and the ANSI style va_start macro is used for both + * ANSI and traditional C compilers. + */ + +#define TOCONS 0x01 +#define TOTTY 0x02 +#define TOLOG 0x04 + +/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ +#define MAXNBUF (sizeof(intmax_t) * 8 + 1) + +struct putchar_arg { + int flags; + int pri; + struct tty *tty; + char *p_bufr; + size_t n_bufr; + char *p_next; + size_t remain; +}; + +struct snprintf_arg { + char *str; + size_t remain; +}; + +extern int log_open; + +static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); +static void snprintf_func(int ch, void *arg); +static int kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap); + +int vsnprintf(char *str, size_t size, const char *format, va_list ap); + +static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +#define hex2ascii(hex) (hex2ascii_data[hex]) + +/* + * Scaled down version of sprintf(3). + */ +int +sprintf(char *buf, const char *cfmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, cfmt); + retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); + buf[retval] = '\0'; + va_end(ap); + return (retval); +} + +/* + * Scaled down version of vsprintf(3). + */ +int +vsprintf(char *buf, const char *cfmt, va_list ap) +{ + int retval; + + retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); + buf[retval] = '\0'; + return (retval); +} + +/* + * Scaled down version of snprintf(3). + */ +int +snprintf(char *str, size_t size, const char *format, ...) +{ + int retval; + va_list ap; + + va_start(ap, format); + retval = vsnprintf(str, size, format, ap); + va_end(ap); + return(retval); +} + +/* + * Scaled down version of vsnprintf(3). + */ +int +vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + struct snprintf_arg info; + int retval; + + info.str = str; + info.remain = size; + retval = kvprintf(format, snprintf_func, &info, 10, ap); + if (info.remain >= 1) + *info.str++ = '\0'; + return (retval); +} + +static void +snprintf_func(int ch, void *arg) +{ + struct snprintf_arg *const info = arg; + + if (info->remain >= 2) { + *info->str++ = ch; + info->remain--; + } +} + + +/* + * Kernel version which takes radix argument vsnprintf(3). + */ +int +vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) +{ + struct snprintf_arg info; + int retval; + + info.str = str; + info.remain = size; + retval = kvprintf(format, snprintf_func, &info, radix, ap); + if (info.remain >= 1) + *info.str++ = '\0'; + return (retval); +} + + +/* + * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse + * order; return an optional length and a pointer to the last character + * written in the buffer (i.e., the first character of the string). + * The buffer pointed to by `nbuf' must have length >= MAXNBUF. + */ +static char * +ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) +{ + char *p, c; + + p = nbuf; + *p = '\0'; + do { + c = hex2ascii(num % base); + *++p = upper ? toupper(c) : c; + } while (num /= base); + if (lenp) + *lenp = p - nbuf; + return (p); +} + +/* + * Scaled down version of printf(3). + * + * Two additional formats: + * + * The format %b is supported to decode error registers. + * Its usage is: + * + * printf("reg=%b\n", regval, "<base><arg>*"); + * + * where <base> is the output base expressed as a control character, e.g. + * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, + * the first of which gives the bit number to be inspected (origin 1), and + * the next characters (up to a control character, i.e. a character <= 32), + * give the name of the register. Thus: + * + * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); + * + * would produce output: + * + * reg=3<BITTWO,BITONE> + * + * XXX: %D -- Hexdump, takes pointer and separator string: + * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX + * ("%*D", len, ptr, " " -> XX XX XX XX ... + */ +int +kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) +{ +#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } + char nbuf[MAXNBUF]; + char *d; + const char *p, *percent, *q; + u_char *up; + int ch, n; + uintmax_t num; + int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + int cflag, hflag, jflag, tflag, zflag; + int dwidth, upper; + char padc; + int stop = 0, retval = 0; + + num = 0; + if (!func) + d = (char *) arg; + else + d = NULL; + + if (fmt == NULL) + fmt = "(fmt null)\n"; + + if (radix < 2 || radix > 36) + radix = 10; + + for (;;) { + padc = ' '; + width = 0; + while ((ch = (u_char)*fmt++) != '%' || stop) { + if (ch == '\0') + return (retval); + PCHAR(ch); + } + percent = fmt - 1; + qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; + sign = 0; dot = 0; dwidth = 0; upper = 0; + cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; +reswitch: switch (ch = (u_char)*fmt++) { + case '.': + dot = 1; + goto reswitch; + case '#': + sharpflag = 1; + goto reswitch; + case '+': + sign = 1; + goto reswitch; + case '-': + ladjust = 1; + goto reswitch; + case '%': + PCHAR(ch); + break; + case '*': + if (!dot) { + width = va_arg(ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + } else { + dwidth = va_arg(ap, int); + } + goto reswitch; + case '0': + if (!dot) { + padc = '0'; + goto reswitch; + } + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + for (n = 0;; ++fmt) { + n = n * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + if (dot) + dwidth = n; + else + width = n; + goto reswitch; + case 'b': + num = (u_int)va_arg(ap, int); + p = va_arg(ap, char *); + for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) + PCHAR(*q--); + + if (num == 0) + break; + + for (tmp = 0; *p;) { + n = *p++; + if (num & (1 << (n - 1))) { + PCHAR(tmp ? ',' : '<'); + for (; (n = *p) > ' '; ++p) + PCHAR(n); + tmp = 1; + } else + for (; *p > ' '; ++p) + continue; + } + if (tmp) + PCHAR('>'); + break; + case 'c': + PCHAR(va_arg(ap, int)); + break; + case 'D': + up = va_arg(ap, u_char *); + p = va_arg(ap, char *); + if (!width) + width = 16; + while(width--) { + PCHAR(hex2ascii(*up >> 4)); + PCHAR(hex2ascii(*up & 0x0f)); + up++; + if (width) + for (q=p;*q;q++) + PCHAR(*q); + } + break; + case 'd': + case 'i': + base = 10; + sign = 1; + goto handle_sign; + case 'h': + if (hflag) { + hflag = 0; + cflag = 1; + } else + hflag = 1; + goto reswitch; + case 'j': + jflag = 1; + goto reswitch; + case 'l': + if (lflag) { + lflag = 0; + qflag = 1; + } else + lflag = 1; + goto reswitch; + case 'n': + if (jflag) + *(va_arg(ap, intmax_t *)) = retval; + else if (qflag) + *(va_arg(ap, quad_t *)) = retval; + else if (lflag) + *(va_arg(ap, long *)) = retval; + else if (zflag) + *(va_arg(ap, size_t *)) = retval; + else if (hflag) + *(va_arg(ap, short *)) = retval; + else if (cflag) + *(va_arg(ap, char *)) = retval; + else + *(va_arg(ap, int *)) = retval; + break; + case 'o': + base = 8; + goto handle_nosign; + case 'p': + base = 16; + sharpflag = (width == 0); + sign = 0; + num = (uintptr_t)va_arg(ap, void *); + goto number; + case 'q': + qflag = 1; + goto reswitch; + case 'r': + base = radix; + if (sign) + goto handle_sign; + goto handle_nosign; + case 's': + p = va_arg(ap, char *); + if (p == NULL) + p = "(null)"; + if (!dot) + n = strlen (p); + else + for (n = 0; n < dwidth && p[n]; n++) + continue; + + width -= n; + + if (!ladjust && width > 0) + while (width--) + PCHAR(padc); + while (n--) + PCHAR(*p++); + if (ladjust && width > 0) + while (width--) + PCHAR(padc); + break; + case 't': + tflag = 1; + goto reswitch; + case 'u': + base = 10; + goto handle_nosign; + case 'X': + upper = 1; + case 'x': + base = 16; + goto handle_nosign; + case 'y': + base = 16; + sign = 1; + goto handle_sign; + case 'z': + zflag = 1; + goto reswitch; +handle_nosign: + sign = 0; + if (jflag) + num = va_arg(ap, uintmax_t); + else if (qflag) + num = va_arg(ap, u_quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, u_long); + else if (zflag) + num = va_arg(ap, size_t); + else if (hflag) + num = (u_short)va_arg(ap, int); + else if (cflag) + num = (u_char)va_arg(ap, int); + else + num = va_arg(ap, u_int); + goto number; +handle_sign: + if (jflag) + num = va_arg(ap, intmax_t); + else if (qflag) + num = va_arg(ap, quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, long); + else if (zflag) + num = va_arg(ap, ssize_t); + else if (hflag) + num = (short)va_arg(ap, int); + else if (cflag) + num = (char)va_arg(ap, int); + else + num = va_arg(ap, int); +number: + if (sign && (intmax_t)num < 0) { + neg = 1; + num = -(intmax_t)num; + } + p = ksprintn(nbuf, num, base, &n, upper); + tmp = 0; + if (sharpflag && num != 0) { + if (base == 8) + tmp++; + else if (base == 16) + tmp += 2; + } + if (neg) + tmp++; + + if (!ladjust && padc == '0') + dwidth = width - tmp; + width -= tmp + imax(dwidth, n); + dwidth -= n; + if (!ladjust) + while (width-- > 0) + PCHAR(' '); + if (neg) + PCHAR('-'); + if (sharpflag && num != 0) { + if (base == 8) { + PCHAR('0'); + } else if (base == 16) { + PCHAR('0'); + PCHAR('x'); + } + } + while (dwidth-- > 0) + PCHAR('0'); + + while (*p) + PCHAR(*p--); + + if (ladjust) + while (width-- > 0) + PCHAR(' '); + + break; + default: + while (percent < fmt) + PCHAR(*percent++); + /* + * Since we ignore an formatting argument it is no + * longer safe to obey the remaining formatting + * arguments as the arguments will no longer match + * the format specs. + */ + stop = 1; + break; + } + } +#undef PCHAR +} diff --git a/lib/semihosting/aarch64/semihosting_call.S b/lib/semihosting/aarch64/semihosting_call.S new file mode 100644 index 0000000..cc72ec2 --- /dev/null +++ b/lib/semihosting/aarch64/semihosting_call.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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 semihosting_call + + .section .text, "ax" + +semihosting_call:; .type semihosting_call, %function + hlt #0xf000 + ret diff --git a/lib/semihosting/semihosting.c b/lib/semihosting/semihosting.c new file mode 100644 index 0000000..558973a --- /dev/null +++ b/lib/semihosting/semihosting.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <semihosting.h> + +#ifndef SEMIHOSTING_SUPPORTED +#define SEMIHOSTING_SUPPORTED 1 +#endif + +extern int semihosting_call(unsigned int operation, + void *system_block_address); + +typedef struct { + const char *file_name; + unsigned int mode; + unsigned int name_length; +} smh_file_open_block; + +typedef struct { + int handle; + void *buffer; + unsigned int length; +} smh_file_read_write_block; + +typedef struct { + int handle; + unsigned int location; +} smh_file_seek_block; + +typedef struct { + char *command_line; + unsigned int command_length; +} smh_system_block; + +int semihosting_connection_supported(void) +{ + return SEMIHOSTING_SUPPORTED; +} + +int semihosting_file_open(const char *file_name, unsigned int mode) +{ + smh_file_open_block open_block; + + open_block.file_name = file_name; + open_block.mode = mode; + open_block.name_length = strlen(file_name); + + return semihosting_call(SEMIHOSTING_SYS_OPEN, + (void *) &open_block); +} + +int semihosting_file_seek(int file_handle, unsigned int offset) +{ + smh_file_seek_block seek_block; + int result; + + seek_block.handle = file_handle; + seek_block.location = offset; + + result = semihosting_call(SEMIHOSTING_SYS_SEEK, + (void *) &seek_block); + + if (result) + result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0); + + return result; +} + +int semihosting_file_read(int file_handle, int *length, void *buffer) +{ + smh_file_read_write_block read_block; + int result = -EINVAL; + + if ((length == NULL) || (buffer == NULL)) + return result; + + read_block.handle = file_handle; + read_block.buffer = buffer; + read_block.length = *length; + + result = semihosting_call(SEMIHOSTING_SYS_READ, + (void *) &read_block); + + if (result == *length) { + return -EINVAL; + } else if (result < *length) { + *length -= result; + return 0; + } else + return result; +} + +int semihosting_file_write(int file_handle, int *length, void *buffer) +{ + smh_file_read_write_block write_block; + + if ((length == NULL) || (buffer == NULL)) + return -EINVAL; + + write_block.handle = file_handle; + write_block.buffer = buffer; + write_block.length = *length; + + *length = semihosting_call(SEMIHOSTING_SYS_WRITE, + (void *) &write_block); + + return *length; +} + +int semihosting_file_close(int file_handle) +{ + return semihosting_call(SEMIHOSTING_SYS_CLOSE, + (void *) &file_handle); +} + +int semihosting_file_length(int file_handle) +{ + return semihosting_call(SEMIHOSTING_SYS_FLEN, + (void *) &file_handle); +} + +char semihosting_read_char(void) +{ + return semihosting_call(SEMIHOSTING_SYS_READC, NULL); +} + +void semihosting_write_char(char character) +{ + semihosting_call(SEMIHOSTING_SYS_WRITEC, (void *) &character); +} + +void semihosting_write_string(char *string) +{ + semihosting_call(SEMIHOSTING_SYS_WRITE0, (void *) string); +} + +int semihosting_system(char *command_line) +{ + smh_system_block system_block; + + system_block.command_line = command_line; + system_block.command_length = strlen(command_line); + + return semihosting_call(SEMIHOSTING_SYS_SYSTEM, + (void *) &system_block); +} + +int semihosting_get_flen(const char *file_name) +{ + int file_handle, length; + + assert(semihosting_connection_supported()); + + file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB); + if (file_handle == -1) + return file_handle; + + /* Find the length of the file */ + length = semihosting_file_length(file_handle); + + return semihosting_file_close(file_handle) ? -1 : length; +} + +int semihosting_download_file(const char *file_name, + int buf_size, + void *buf) +{ + int ret = -EINVAL, file_handle, length; + + /* Null pointer check */ + if (!buf) + return ret; + + assert(semihosting_connection_supported()); + + file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB); + if (file_handle == -1) + return ret; + + /* Find the actual length of the file */ + length = semihosting_file_length(file_handle); + if (length == -1) + goto semihosting_fail; + + /* Signal error if we do not have enough space for the file */ + if (length > buf_size) + goto semihosting_fail; + + /* + * A successful read will return 0 in which case we pass back + * the actual number of bytes read. Else we pass a negative + * value indicating an error. + */ + ret = semihosting_file_read(file_handle, &length, buf); + if (ret) + goto semihosting_fail; + else + ret = length; + +semihosting_fail: + semihosting_file_close(file_handle); + return ret; +} diff --git a/lib/sync/locks/bakery/bakery_lock.c b/lib/sync/locks/bakery/bakery_lock.c new file mode 100644 index 0000000..d3c780c --- /dev/null +++ b/lib/sync/locks/bakery/bakery_lock.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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. + */ + +#include <assert.h> +#include <string.h> + +#include <bakery_lock.h> + +#define assert_bakery_entry_valid(entry, bakery) do { \ + assert(bakery); \ + assert(entry < BAKERY_LOCK_MAX_CPUS); \ +} while(0) + +void bakery_lock_init(bakery_lock * bakery) +{ + assert(bakery); + memset(bakery, 0, sizeof(*bakery)); + bakery->owner = NO_OWNER; +} + +void bakery_lock_get(unsigned long mpidr, bakery_lock * bakery) +{ + unsigned int i, max = 0, my_full_number, his_full_number, entry; + + entry = platform_get_core_pos(mpidr); + + assert_bakery_entry_valid(entry, bakery); + + // Catch recursive attempts to take the lock under the same entry: + assert(bakery->owner != entry); + + // Get a ticket + bakery->entering[entry] = 1; + for (i = 0; i < BAKERY_LOCK_MAX_CPUS; ++i) { + if (bakery->number[i] > max) { + max = bakery->number[i]; + } + } + ++max; + bakery->number[entry] = max; + bakery->entering[entry] = 0; + + // Wait for our turn + my_full_number = (max << 8) + entry; + for (i = 0; i < BAKERY_LOCK_MAX_CPUS; ++i) { + while (bakery->entering[i]) ; /* Wait */ + do { + his_full_number = bakery->number[i]; + if (his_full_number) { + his_full_number = (his_full_number << 8) + i; + } + } + while (his_full_number && (his_full_number < my_full_number)); + } + + bakery->owner = entry; +} + +void bakery_lock_release(unsigned long mpidr, bakery_lock * bakery) +{ + unsigned int entry = platform_get_core_pos(mpidr); + + assert_bakery_entry_valid(entry, bakery); + assert(bakery_lock_held(entry, bakery)); + + bakery->owner = NO_OWNER; + bakery->number[entry] = 0; +} + +int bakery_lock_held(unsigned long mpidr, const bakery_lock * bakery) +{ + unsigned int entry = platform_get_core_pos(mpidr); + + assert_bakery_entry_valid(entry, bakery); + + return bakery->owner == entry; +} diff --git a/lib/sync/locks/exclusive/spinlock.S b/lib/sync/locks/exclusive/spinlock.S new file mode 100644 index 0000000..4269d95 --- /dev/null +++ b/lib/sync/locks/exclusive/spinlock.S @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013, ARM Limited. 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 ARM 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 HOLDER 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 spin_lock + .globl spin_unlock + + + .section .text, "ax"; + +spin_lock:; .type spin_lock, %function + mov w2, #1 + sevl +l1: wfe +l2: ldaxr w1, [x0] + cbnz w1, l1 + stxr w1, w2, [x0] + cbnz w1, l2 + ret + + +spin_unlock:; .type spin_unlock, %function + stlr wzr, [x0] + ret |