warning fixes. new function dnode_get_fullpath
[grub2/phcoder.git] / efiemu / symbols.c
blobec508d97535b6f0cba95bd1ed766fb85a7166b3b
1 /* Code for managing symbols and pointers in efiemu */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/err.h>
21 #include <grub/mm.h>
22 #include <grub/misc.h>
23 #include <grub/efiemu/efiemu.h>
24 #include <grub/efiemu/runtime.h>
26 static int ptv_written = 0;
27 static int ptv_alloc = 0;
28 static int ptv_handle = 0;
29 static int ptv_requested = 0;
30 static struct grub_efiemu_sym *efiemu_syms = 0;
32 struct grub_efiemu_sym
34 struct grub_efiemu_sym *next;
35 char *name;
36 int handle;
37 grub_off_t off;
40 void
41 grub_efiemu_free_syms (void)
43 struct grub_efiemu_sym *cur, *d;
44 for (cur = efiemu_syms; cur;)
46 d = cur->next;
47 grub_free (cur->name);
48 grub_free (cur);
49 cur = d;
51 efiemu_syms = 0;
52 ptv_written = 0;
53 ptv_alloc = 0;
54 ptv_requested = 0;
55 grub_efiemu_mm_return_request (ptv_handle);
56 ptv_handle = 0;
59 /* Announce that the module will need NUM allocators */
60 /* Because of deferred memory allocation all the relocators have to be
61 announced during phase 1*/
62 grub_err_t
63 grub_efiemu_request_symbols (int num)
65 if (ptv_alloc)
66 return grub_error (GRUB_ERR_BAD_ARGUMENT,
67 "symbols have already been allocated");
68 if (num < 0)
69 return grub_error (GRUB_ERR_BAD_ARGUMENT,
70 "can't request negative symbols");
71 ptv_requested += num;
72 return GRUB_ERR_NONE;
75 /* Resolve the symbol name NAME and set HANDLE and OFF accordingly */
76 grub_err_t
77 grub_efiemu_resolve_symbol (const char *name, int *handle, grub_off_t *off)
79 struct grub_efiemu_sym *cur;
80 for (cur = efiemu_syms; cur; cur = cur->next)
81 if (!grub_strcmp (name, cur->name))
83 *handle = cur->handle;
84 *off = cur->off;
85 return GRUB_ERR_NONE;
87 grub_dprintf ("efiemu", "%s not found\n", name);
88 return grub_error (GRUB_ERR_BAD_OS, "symbol %s isn't found", name);
91 /* Register symbol named NAME in memory handle HANDLE at offset OFF */
92 grub_err_t
93 grub_efiemu_register_symbol (const char *name, int handle, grub_off_t off)
95 struct grub_efiemu_sym *cur;
96 cur = (struct grub_efiemu_sym *) grub_malloc (sizeof (*cur));
97 grub_dprintf ("efiemu", "registering symbol '%s'\n", name);
98 if (!cur)
99 return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't register symbol");
100 cur->name = grub_strdup (name);
101 cur->next = efiemu_syms;
102 cur->handle = handle;
103 cur->off = off;
104 efiemu_syms = cur;
106 return 0;
109 /* Go from phase 1 to phase 2. Must be called before similar function in mm.c */
110 grub_err_t
111 grub_efiemu_alloc_syms (void)
113 ptv_alloc = ptv_requested;
114 ptv_handle = grub_efiemu_request_memalign
115 (1, (ptv_requested + 1) * sizeof (struct grub_efiemu_ptv_rel),
116 GRUB_EFI_RUNTIME_SERVICES_DATA);
117 grub_efiemu_register_symbol ("efiemu_ptv_relloc", ptv_handle, 0);
118 return grub_errno;
121 /* Write value (pointer to memory PLUS_HANDLE)
122 - (pointer to memory MINUS_HANDLE) + VALUE to ADDR assuming that the
123 size SIZE bytes. If PTV_NEEDED is 1 then announce it to runtime that this
124 value needs to be recomputed before going to virtual mode
126 grub_err_t
127 grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
128 int minus_handle, int ptv_needed, int size)
130 /* Announce relocator to runtime */
131 if (ptv_needed)
133 struct grub_efiemu_ptv_rel *ptv_rels
134 = grub_efiemu_mm_obtain_request (ptv_handle);
136 if (ptv_needed && ptv_written >= ptv_alloc)
137 return grub_error (GRUB_ERR_OUT_OF_MEMORY,
138 "your module didn't declare efiemu "
139 " relocators correctly");
141 if (minus_handle)
142 ptv_rels[ptv_written].minustype
143 = grub_efiemu_mm_get_type (minus_handle);
144 else
145 ptv_rels[ptv_written].minustype = 0;
147 if (plus_handle)
148 ptv_rels[ptv_written].plustype
149 = grub_efiemu_mm_get_type (plus_handle);
150 else
151 ptv_rels[ptv_written].plustype = 0;
153 ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr);
154 ptv_rels[ptv_written].size = size;
155 ptv_written++;
157 /* memset next value to zero to mark the end */
158 grub_memset (&ptv_rels[ptv_written], 0, sizeof (ptv_rels[ptv_written]));
161 /* Compute the value */
162 if (minus_handle)
163 value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle));
165 if (plus_handle)
166 value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle));
168 /* Write the value */
169 switch (size)
171 case 8:
172 *((grub_uint64_t *) addr) = value;
173 break;
174 case 4:
175 *((grub_uint32_t *) addr) = value;
176 break;
177 case 2:
178 *((grub_uint16_t *) addr) = value;
179 break;
180 case 1:
181 *((grub_uint8_t *) addr) = value;
182 break;
183 default:
184 return grub_error (GRUB_ERR_BAD_ARGUMENT, "wrong symbol size");
187 return GRUB_ERR_NONE;