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