summaryrefslogtreecommitdiffstats
path: root/include/grub/dl.h
blob: b3753c9ca2628d6c077eaa30ff24ada3b0c1219e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/* dl.h - types and prototypes for loadable module support */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2002,2004,2005,2007,2008,2009  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef GRUB_DL_H
#define GRUB_DL_H	1

#include <grub/symbol.h>
#ifndef ASM_FILE
#include <grub/err.h>
#include <grub/types.h>
#include <grub/elf.h>
#include <grub/list.h>
#include <grub/misc.h>
#endif

/*
 * Macros GRUB_MOD_INIT and GRUB_MOD_FINI are also used by build rules
 * to collect module names, so we define them only when they are not
 * defined already.
 */
#ifndef ASM_FILE

#ifndef GRUB_MOD_INIT

#if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_KERNEL)

#define GRUB_MOD_INIT(name)	\
static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
static void \
grub_mod_init (grub_dl_t mod __attribute__ ((unused)))

#define GRUB_MOD_FINI(name)	\
static void grub_mod_fini (void) __attribute__ ((used)); \
static void \
grub_mod_fini (void)

#elif defined (GRUB_KERNEL)

#define GRUB_MOD_INIT(name)	\
static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
void \
grub_##name##_init (void) { grub_mod_init (0); } \
static void \
grub_mod_init (grub_dl_t mod __attribute__ ((unused)))

#define GRUB_MOD_FINI(name)	\
static void grub_mod_fini (void) __attribute__ ((used)); \
void \
grub_##name##_fini (void) { grub_mod_fini (); } \
static void \
grub_mod_fini (void)

#else

#define GRUB_MOD_INIT(name)	\
static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
void grub_##name##_init (void); \
void \
grub_##name##_init (void) { grub_mod_init (0); } \
static void \
grub_mod_init (grub_dl_t mod __attribute__ ((unused)))

#define GRUB_MOD_FINI(name)	\
static void grub_mod_fini (void) __attribute__ ((used)); \
void grub_##name##_fini (void); \
void \
grub_##name##_fini (void) { grub_mod_fini (); } \
static void \
grub_mod_fini (void)

#endif

#endif

#endif

#ifndef ASM_FILE
#ifdef __APPLE__
#define GRUB_MOD_SECTION(x) "_" #x ", _" #x ""
#else
#define GRUB_MOD_SECTION(x) "." #x
#endif
#else
#ifdef __APPLE__
#define GRUB_MOD_SECTION(x) _ ## x , _ ##x 
#else
#define GRUB_MOD_SECTION(x) . ## x
#endif
#endif

/* Me, Vladimir Serbinenko, hereby I add this module check as per new
   GNU module policy. Note that this license check is informative only.
   Modules have to be licensed under GPLv3 or GPLv3+ (optionally
   multi-licensed under other licences as well) independently of the
   presence of this check and solely by linking (module loading in GRUB
   constitutes linking) and GRUB core being licensed under GPLv3+.
   Be sure to understand your license obligations.
*/
#ifndef ASM_FILE
#if GNUC_PREREQ (3,2)
#define ATTRIBUTE_USED __used__
#else
#define ATTRIBUTE_USED __unused__
#endif
#define GRUB_MOD_LICENSE(license)	\
  static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license;
#define GRUB_MOD_DEP(name)	\
static const char grub_module_depend_##name[] \
 __attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name
#define GRUB_MOD_NAME(name)	\
static const char grub_module_name_##name[] \
 __attribute__((section(GRUB_MOD_SECTION(modname)), __used__)) = #name
#else
#ifdef __APPLE__
.macro GRUB_MOD_LICENSE
  .section GRUB_MOD_SECTION(module_license)
  .ascii "LICENSE="
  .ascii $0
  .byte 0
.endm
#else
.macro GRUB_MOD_LICENSE license
  .section GRUB_MOD_SECTION(module_license), "a"
  .ascii "LICENSE="
  .ascii "\license"
  .byte 0
.endm
#endif
#endif

/* Under GPL license obligations you have to distribute your module
   under GPLv3(+). However, you can also distribute the same code under
   another license as long as GPLv3(+) version is provided.
*/
#define GRUB_MOD_DUAL_LICENSE(x)

#ifndef ASM_FILE

struct grub_dl_segment
{
  struct grub_dl_segment *next;
  void *addr;
  grub_size_t size;
  unsigned section;
};
typedef struct grub_dl_segment *grub_dl_segment_t;

struct grub_dl;

struct grub_dl_dep
{
  struct grub_dl_dep *next;
  struct grub_dl *mod;
};
typedef struct grub_dl_dep *grub_dl_dep_t;

#ifndef GRUB_UTIL
struct grub_dl
{
  char *name;
  int ref_count;
  int persistent;
  grub_dl_dep_t dep;
  grub_dl_segment_t segment;
  Elf_Sym *symtab;
  grub_size_t symsize;
  void (*init) (struct grub_dl *mod);
  void (*fini) (void);
#if !defined (__i386__) && !defined (__x86_64__)
  void *got;
  void *gotptr;
  void *tramp;
  void *trampptr;
#endif
#ifdef __mips__
  grub_uint32_t *reginfo;
#endif
  void *base;
  grub_size_t sz;
  struct grub_dl *next;
};
#endif
typedef struct grub_dl *grub_dl_t;

grub_dl_t grub_dl_load_file (const char *filename);
grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
extern void grub_dl_unload_unneeded (void);
extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);

extern grub_dl_t EXPORT_VAR(grub_dl_head);

#ifndef GRUB_UTIL

#define FOR_DL_MODULES(var) FOR_LIST_ELEMENTS ((var), (grub_dl_head))

#ifdef GRUB_MACHINE_EMU
void *
grub_osdep_dl_memalign (grub_size_t align, grub_size_t size);
void
grub_dl_osdep_dl_free (void *ptr);
#endif

static inline void
grub_dl_init (grub_dl_t mod)
{
  if (mod->init)
    (mod->init) (mod);

  mod->next = grub_dl_head;
  grub_dl_head = mod;
}

static inline grub_dl_t
grub_dl_get (const char *name)
{
  grub_dl_t l;

  FOR_DL_MODULES(l)
    if (grub_strcmp (name, l->name) == 0)
      return l;

  return 0;
}

static inline void
grub_dl_set_persistent (grub_dl_t mod)
{
  mod->persistent = 1;
}

static inline int
grub_dl_is_persistent (grub_dl_t mod)
{
  return mod->persistent;
}

#endif

grub_err_t grub_dl_register_symbol (const char *name, void *addr,
				    int isfunc, grub_dl_t mod);

grub_err_t grub_arch_dl_check_header (void *ehdr);
#ifndef GRUB_UTIL
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
			       Elf_Shdr *s, grub_dl_segment_t seg);
#endif

#if defined (_mips)
#define GRUB_LINKER_HAVE_INIT 1
void grub_arch_dl_init_linker (void);
#endif

#define GRUB_IA64_DL_TRAMP_ALIGN 16
#define GRUB_IA64_DL_GOT_ALIGN 16

grub_err_t
grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
				 grub_size_t *got);
grub_err_t
grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
				  grub_size_t *got);

#if defined (__ia64__)
#define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_IA64_DL_TRAMP_ALIGN
#define GRUB_ARCH_DL_GOT_ALIGN GRUB_IA64_DL_GOT_ALIGN
#define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size
#elif defined (__aarch64__)
#define grub_arch_dl_get_tramp_got_size grub_arm64_dl_get_tramp_got_size
#else
grub_err_t
grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
				 grub_size_t *got);
#endif

#if defined (__powerpc__) || defined (__mips__) || defined (__arm__) || \
    (defined(__riscv) && (__riscv_xlen == 32))
#define GRUB_ARCH_DL_TRAMP_ALIGN 4
#define GRUB_ARCH_DL_GOT_ALIGN 4
#endif

#if defined (__aarch64__) || defined (__sparc__) || \
    (defined(__riscv) && (__riscv_xlen == 64))
#define GRUB_ARCH_DL_TRAMP_ALIGN 8
#define GRUB_ARCH_DL_GOT_ALIGN 8
#endif

#endif

#endif /* ! GRUB_DL_H */