diff --git a/arch/mips/include/elf.h b/arch/mips/include/elf.h new file mode 100644 index 0000000000000..ce1cc86dea6a1 --- /dev/null +++ b/arch/mips/include/elf.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * arch/mips/include/elf.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_MIPS_INCLUDE_ELF_H +#define __ARCH_MIPS_INCLUDE_ELF_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define R_MIPS_NONE 0 +#define R_MIPS_32 2 +#define R_MIPS_26 4 +#define R_MIPS_HI16 5 +#define R_MIPS_LO16 6 + +#define MIPS_HI16_COUNT 10 +#define ARCH_ELFDATA 1 + +/**************************************************************************** + * Private Data Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +struct arch_elfdata_s +{ + struct hi_rel_s + { + Elf_Addr ahi; + Elf32_Addr *p; + } + hi[MIPS_HI16_COUNT]; + int pos; + + Elf_Addr ahi; /* The newest ahi */ +}; + +typedef struct arch_elfdata_s arch_elfdata_t; + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_MIPS_INCLUDE_ELF_H */ diff --git a/arch/mips/src/jz4780/jz4780_cache.c b/arch/mips/src/jz4780/jz4780_cache.c index 3777118e9330e..96a78cd4bb043 100644 --- a/arch/mips/src/jz4780/jz4780_cache.c +++ b/arch/mips/src/jz4780/jz4780_cache.c @@ -437,6 +437,8 @@ void up_disable_dcache(void) void up_coherent_dcache(uintptr_t addr, size_t len) { + m32_dcache_clean(addr, len); + m32_clean_icache(addr, len); } #endif /* CONFIG_ARCH_DCACHE */ diff --git a/arch/mips/src/jz4780/jz4780_cache.h b/arch/mips/src/jz4780/jz4780_cache.h index 21c8b234ea81b..eeb5c35017bdb 100644 --- a/arch/mips/src/jz4780/jz4780_cache.h +++ b/arch/mips/src/jz4780/jz4780_cache.h @@ -66,6 +66,7 @@ void m32_size_cache(void); void m32_flush_dcache(void); void m32_flush_icache(void); void m32_clean_cache(uint32_t kva, size_t n); +void m32_clean_icache(uint32_t kva, size_t n); void m32_sync_icache(uint32_t kva, size_t n); void m32_dcache_clean_invalidate(uint32_t kva, size_t n); void m32_dcache_invalidate(uint32_t kva, size_t n); diff --git a/arch/mips/src/mips32/Toolchain.defs b/arch/mips/src/mips32/Toolchain.defs index 67a8b28e6ca5e..5b09c374a1e45 100644 --- a/arch/mips/src/mips32/Toolchain.defs +++ b/arch/mips/src/mips32/Toolchain.defs @@ -325,7 +325,7 @@ endif # Loadable module definitions CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden -LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld) +LDMODULEFLAGS = -EL -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld) # ELF module definitions diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index fefcdff5c4e74..73e34fecccba8 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -32,6 +32,9 @@ endif ifeq ($(CONFIG_ARCH_ARM64),y) include $(TOPDIR)/libs/libc/machine/arm64/Make.defs endif +ifeq ($(CONFIG_ARCH_MIPS),y) +include $(TOPDIR)/libs/libc/machine/mips/Make.defs +endif ifeq ($(CONFIG_ARCH_RISCV),y) include $(TOPDIR)/libs/libc/machine/risc-v/Make.defs endif diff --git a/libs/libc/machine/mips/Kconfig b/libs/libc/machine/mips/Kconfig new file mode 100644 index 0000000000000..18c7905aed7cf --- /dev/null +++ b/libs/libc/machine/mips/Kconfig @@ -0,0 +1,5 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + diff --git a/libs/libc/machine/mips/Make.defs b/libs/libc/machine/mips/Make.defs new file mode 100644 index 0000000000000..48efd78426db1 --- /dev/null +++ b/libs/libc/machine/mips/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# libs/libc/machine/mips/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifeq ($(CONFIG_LIBC_ARCH_ELF),y) +CSRCS += arch_elf.c +endif + +DEPPATH += --dep-path machine/mips +VPATH += :machine/mips diff --git a/libs/libc/machine/mips/arch_elf.c b/libs/libc/machine/mips/arch_elf.c new file mode 100644 index 0000000000000..198dfdb90865d --- /dev/null +++ b/libs/libc/machine/mips/arch_elf.c @@ -0,0 +1,212 @@ +/**************************************************************************** + * libs/libc/machine/mips/arch_elf.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkarch + * + * Description: + * Given the ELF header in 'hdr', verify that the ELF file is appropriate + * for the current, configured architecture. Every architecture that uses + * the ELF loader must provide this function. + * + * Input Parameters: + * hdr - The ELF header read from the ELF file. + * + * Returned Value: + * True if the architecture supports this ELF file. + * + ****************************************************************************/ + +bool up_checkarch(const Elf32_Ehdr *ehdr) +{ + /* Make sure it's a MIPS executable */ + + if (ehdr->e_machine != EM_MIPS) + { + berr("ERROR: Not for MIPS: e_machine=%04x\n", ehdr->e_machine); + return false; + } + + /* Make sure that 32-bit objects are supported */ + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) + { + berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n", + ehdr->e_ident[EI_CLASS]); + return false; + } + + /* Verify endian-ness */ + +#ifdef CONFIG_ENDIAN_BIG + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) +#else + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) +#endif + { + berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n", + ehdr->e_ident[EI_DATA]); + return false; + } + + /* Make sure the entry point address is properly aligned */ + + if ((ehdr->e_entry & 3) != 0) + { + berr("ERROR: Entry point is not properly aligned: %08" PRIx32 "\n", + ehdr->e_entry); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: up_relocate and up_relocateadd + * + * Description: + * Perform an architecture-specific ELF relocation. Every architecture + * that uses the ELF loader must provide this function. + * + * Input Parameters: + * rel - The relocation type + * sym - The ELF symbol structure containing the fully resolved + * value. There are a few relocation types for a few + * architectures that do not require symbol information. + * For those, this value will be NULL. Implementations of + * these functions must be able to handle that case. + * addr - The address that requires the relocation. + * arch_data - Pointer to architecture specific elf data container. + * + * Returned Value: + * Zero (OK) if the relocation was successful. Otherwise, a negated errno + * value indicating the cause of the relocation failure. + * + ****************************************************************************/ + +int up_relocate(const Elf_Rel *rel, const Elf_Sym *sym, uintptr_t addr, + void *arch_data) +{ + /* Variable names correspond to the MIPS ABI specification symbols + * (A, AHI, AHL, P, S) in lowercase. + */ + + Elf32_Addr *p = (Elf32_Addr *)addr; + Elf_Word r_type = ELF_R_TYPE(rel->r_info); + Elf_Addr s = (sym != NULL) ? sym->st_value : 0; + arch_elfdata_t *data = (arch_elfdata_t *)arch_data; + + if ((sym == NULL && r_type != R_MIPS_NONE) || !data) + { + return -EINVAL; + } + + switch (r_type) + { + case R_MIPS_NONE: + break; + + case R_MIPS_32: + *p = s + *p; + break; + + case R_MIPS_26: + { + Elf_Addr a = *p & 0x03ffffff; + Elf_Addr val = ((a << 2) | ((Elf_Addr)p & 0xf0000000)) + s; + val = (val >> 2) & 0x03ffffff; + *p &= 0xfc000000; + *p |= val; + } + break; + + case R_MIPS_HI16: + if (data->pos >= MIPS_HI16_COUNT) + { + return -EINVAL; + } + + data->ahi = *p; + data->hi[data->pos].ahi = *p; + data->hi[data->pos].p = p; + + data->pos++; + + break; + + case R_MIPS_LO16: + { + int i; + int16_t a = *p; + Elf_Addr ahl = (data->ahi << 16) + a; + Elf32_Addr iword = *p & 0xffff0000; + iword |= (uint16_t)(ahl + s); + *p = iword; + + for (i = 0; i < data->pos; i++) + { + ahl = (data->hi[i].ahi << 16) + a; + + iword = *(data->hi[i].p) & 0xffff0000; + iword |= ((ahl + s) - (int16_t)(ahl + s)) >> 16; + *(data->hi[i].p) = iword; + } + + data->pos = 0; + } + break; + + default: + berr("ERROR: Unsupported relocation: %" PRIu32 "\n", + ELF_R_TYPE(rel->r_info)); + return -EINVAL; + } + + return OK; +} + +int up_relocateadd(const Elf32_Rela *rela, const Elf32_Sym *sym, + uintptr_t addr, void *arch_data) +{ + berr("Not implemented\n"); + PANIC(); + return -ENOSYS; +} +