Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions arch/mips/include/elf.h
Original file line number Diff line number Diff line change
@@ -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 */
2 changes: 2 additions & 0 deletions arch/mips/src/jz4780/jz4780_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
1 change: 1 addition & 0 deletions arch/mips/src/jz4780/jz4780_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/src/mips32/Toolchain.defs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions libs/libc/machine/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions libs/libc/machine/mips/Kconfig
Original file line number Diff line number Diff line change
@@ -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.
#

28 changes: 28 additions & 0 deletions libs/libc/machine/mips/Make.defs
Original file line number Diff line number Diff line change
@@ -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
212 changes: 212 additions & 0 deletions libs/libc/machine/mips/arch_elf.c
Original file line number Diff line number Diff line change
@@ -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 <nuttx/config.h>

#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <nuttx/debug.h>
#include <assert.h>

#include <nuttx/elf.h>

/****************************************************************************
* 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;
}

Loading