1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2017 Andes Technology 4 * Chih-Mao Chen <cmchen@andestech.com> 5 * 6 * Statically process runtime relocations on RISC-V ELF images 7 * so that it can be directly executed when loaded at LMA 8 * without fixup. Both RV32 and RV64 are supported. 9 */ 10 11#include <errno.h> 12#include <stdbool.h> 13#include <stdint.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17 18#include <elf.h> 19#include <fcntl.h> 20#include <sys/mman.h> 21#include <sys/stat.h> 22#include <sys/types.h> 23#include <unistd.h> 24#include <compiler.h> 25 26#ifndef EM_RISCV 27#define EM_RISCV 243 28#endif 29 30#ifndef R_RISCV_32 31#define R_RISCV_32 1 32#endif 33 34#ifndef R_RISCV_64 35#define R_RISCV_64 2 36#endif 37 38#ifndef R_RISCV_RELATIVE 39#define R_RISCV_RELATIVE 3 40#endif 41 42const char *argv0; 43 44#define die(fmt, ...) \ 45 do { \ 46 fprintf(stderr, "%s: " fmt "\n", argv0, ## __VA_ARGS__); \ 47 exit(EXIT_FAILURE); \ 48 } while (0) 49 50#define PRELINK_BYTEORDER le 51#define PRELINK_INC_BITS 32 52#include "prelink-riscv.inc" 53#undef PRELINK_BYTEORDER 54#undef PRELINK_INC_BITS 55 56#define PRELINK_BYTEORDER le 57#define PRELINK_INC_BITS 64 58#include "prelink-riscv.inc" 59#undef PRELINK_BYTEORDER 60#undef PRELINK_INC_BITS 61 62#define PRELINK_BYTEORDER be 63#define PRELINK_INC_BITS 32 64#include "prelink-riscv.inc" 65#undef PRELINK_BYTEORDER 66#undef PRELINK_INC_BITS 67 68#define PRELINK_BYTEORDER be 69#define PRELINK_INC_BITS 64 70#include "prelink-riscv.inc" 71#undef PRELINK_BYTEORDER 72#undef PRELINK_INC_BITS 73 74int main(int argc, const char *const *argv) 75{ 76 argv0 = argv[0]; 77 78 if (argc < 2) { 79 fprintf(stderr, "Usage: %s <u-boot>\n", argv0); 80 exit(EXIT_FAILURE); 81 } 82 83 int fd = open(argv[1], O_RDWR, 0); 84 85 if (fd < 0) 86 die("Cannot open %s: %s", argv[1], strerror(errno)); 87 88 struct stat st; 89 90 if (fstat(fd, &st) < 0) 91 die("Cannot stat %s: %s", argv[1], strerror(errno)); 92 93 void *data = 94 mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 95 96 if (data == MAP_FAILED) 97 die("Cannot mmap %s: %s", argv[1], strerror(errno)); 98 99 close(fd); 100 101 unsigned char *e_ident = (unsigned char *)data; 102 103 if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) 104 die("Invalid ELF file %s", argv[1]); 105 106 bool is64 = e_ident[EI_CLASS] == ELFCLASS64; 107 bool isbe = e_ident[EI_DATA] == ELFDATA2MSB; 108 109 if (is64) { 110 if (isbe) 111 prelink_be64(data); 112 else 113 prelink_le64(data); 114 } else { 115 if (isbe) 116 prelink_be32(data); 117 else 118 prelink_le32(data); 119 } 120 121 munmap(data, st.st_size); 122 123 return 0; 124} 125