Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Remote processor elf helpers defines
0004  *
0005  * Copyright (C) 2020 Kalray, Inc.
0006  */
0007 
0008 #ifndef REMOTEPROC_ELF_LOADER_H
0009 #define REMOTEPROC_ELF_LOADER_H
0010 
0011 #include <linux/elf.h>
0012 #include <linux/types.h>
0013 
0014 /**
0015  * fw_elf_get_class - Get elf class
0016  * @fw: the ELF firmware image
0017  *
0018  * Note that we use elf32_hdr to access the class since the start of the
0019  * struct is the same for both elf class
0020  *
0021  * Return: elf class of the firmware
0022  */
0023 static inline u8 fw_elf_get_class(const struct firmware *fw)
0024 {
0025     struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
0026 
0027     return ehdr->e_ident[EI_CLASS];
0028 }
0029 
0030 static inline void elf_hdr_init_ident(struct elf32_hdr *hdr, u8 class)
0031 {
0032     memcpy(hdr->e_ident, ELFMAG, SELFMAG);
0033     hdr->e_ident[EI_CLASS] = class;
0034     hdr->e_ident[EI_DATA] = ELFDATA2LSB;
0035     hdr->e_ident[EI_VERSION] = EV_CURRENT;
0036     hdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
0037 }
0038 
0039 /* Generate getter and setter for a specific elf struct/field */
0040 #define ELF_GEN_FIELD_GET_SET(__s, __field, __type) \
0041 static inline __type elf_##__s##_get_##__field(u8 class, const void *arg) \
0042 { \
0043     if (class == ELFCLASS32) \
0044         return (__type) ((const struct elf32_##__s *) arg)->__field; \
0045     else \
0046         return (__type) ((const struct elf64_##__s *) arg)->__field; \
0047 } \
0048 static inline void elf_##__s##_set_##__field(u8 class, void *arg, \
0049                          __type value) \
0050 { \
0051     if (class == ELFCLASS32) \
0052         ((struct elf32_##__s *) arg)->__field = (__type) value; \
0053     else \
0054         ((struct elf64_##__s *) arg)->__field = (__type) value; \
0055 }
0056 
0057 ELF_GEN_FIELD_GET_SET(hdr, e_entry, u64)
0058 ELF_GEN_FIELD_GET_SET(hdr, e_phnum, u16)
0059 ELF_GEN_FIELD_GET_SET(hdr, e_shnum, u16)
0060 ELF_GEN_FIELD_GET_SET(hdr, e_phoff, u64)
0061 ELF_GEN_FIELD_GET_SET(hdr, e_shoff, u64)
0062 ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
0063 ELF_GEN_FIELD_GET_SET(hdr, e_machine, u16)
0064 ELF_GEN_FIELD_GET_SET(hdr, e_type, u16)
0065 ELF_GEN_FIELD_GET_SET(hdr, e_version, u32)
0066 ELF_GEN_FIELD_GET_SET(hdr, e_ehsize, u32)
0067 ELF_GEN_FIELD_GET_SET(hdr, e_phentsize, u16)
0068 ELF_GEN_FIELD_GET_SET(hdr, e_shentsize, u16)
0069 
0070 ELF_GEN_FIELD_GET_SET(phdr, p_paddr, u64)
0071 ELF_GEN_FIELD_GET_SET(phdr, p_vaddr, u64)
0072 ELF_GEN_FIELD_GET_SET(phdr, p_filesz, u64)
0073 ELF_GEN_FIELD_GET_SET(phdr, p_memsz, u64)
0074 ELF_GEN_FIELD_GET_SET(phdr, p_type, u32)
0075 ELF_GEN_FIELD_GET_SET(phdr, p_offset, u64)
0076 ELF_GEN_FIELD_GET_SET(phdr, p_flags, u32)
0077 ELF_GEN_FIELD_GET_SET(phdr, p_align, u64)
0078 
0079 ELF_GEN_FIELD_GET_SET(shdr, sh_type, u32)
0080 ELF_GEN_FIELD_GET_SET(shdr, sh_flags, u32)
0081 ELF_GEN_FIELD_GET_SET(shdr, sh_entsize, u16)
0082 ELF_GEN_FIELD_GET_SET(shdr, sh_size, u64)
0083 ELF_GEN_FIELD_GET_SET(shdr, sh_offset, u64)
0084 ELF_GEN_FIELD_GET_SET(shdr, sh_name, u32)
0085 ELF_GEN_FIELD_GET_SET(shdr, sh_addr, u64)
0086 
0087 #define ELF_STRUCT_SIZE(__s) \
0088 static inline unsigned long elf_size_of_##__s(u8 class) \
0089 { \
0090     if (class == ELFCLASS32)\
0091         return sizeof(struct elf32_##__s); \
0092     else \
0093         return sizeof(struct elf64_##__s); \
0094 }
0095 
0096 ELF_STRUCT_SIZE(shdr)
0097 ELF_STRUCT_SIZE(phdr)
0098 ELF_STRUCT_SIZE(hdr)
0099 
0100 static inline unsigned int elf_strtbl_add(const char *name, void *ehdr, u8 class, size_t *index)
0101 {
0102     u16 shstrndx = elf_hdr_get_e_shstrndx(class, ehdr);
0103     void *shdr;
0104     char *strtab;
0105     size_t idx, ret;
0106 
0107     shdr = ehdr + elf_size_of_hdr(class) + shstrndx * elf_size_of_shdr(class);
0108     strtab = ehdr + elf_shdr_get_sh_offset(class, shdr);
0109     idx = index ? *index : 0;
0110     if (!strtab || !name)
0111         return 0;
0112 
0113     ret = idx;
0114     strcpy((strtab + idx), name);
0115     idx += strlen(name) + 1;
0116     if (index)
0117         *index = idx;
0118 
0119     return ret;
0120 }
0121 
0122 #endif /* REMOTEPROC_ELF_LOADER_H */