]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
42ac26f2 RC |
2 | /* |
3 | * Copyright (C) 2017 Andes Technology | |
4 | * Chih-Mao Chen <[email protected]> | |
5 | * | |
42ac26f2 RC |
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 | ||
42ac26f2 RC |
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> | |
e604410d | 24 | #include <compiler.h> |
42ac26f2 RC |
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 | ||
42 | const 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 | ||
4539926a | 50 | #define PRELINK_BYTEORDER le |
42ac26f2 RC |
51 | #define PRELINK_INC_BITS 32 |
52 | #include "prelink-riscv.inc" | |
4539926a | 53 | #undef PRELINK_BYTEORDER |
42ac26f2 RC |
54 | #undef PRELINK_INC_BITS |
55 | ||
4539926a | 56 | #define PRELINK_BYTEORDER le |
42ac26f2 RC |
57 | #define PRELINK_INC_BITS 64 |
58 | #include "prelink-riscv.inc" | |
4539926a MC |
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 | |
42ac26f2 RC |
72 | #undef PRELINK_INC_BITS |
73 | ||
74 | int 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; | |
4539926a MC |
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 | } | |
42ac26f2 RC |
120 | |
121 | return 0; | |
122 | } |