source: grub-pc/trunk/fuentes/grub-core/lib/mips/relocator.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 4.2 KB
Line 
1/*
2 *  GRUB  --  GRand Unified Bootloader
3 *  Copyright (C) 2009  Free Software Foundation, Inc.
4 *
5 *  GRUB is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation, either version 3 of the License, or
8 *  (at your option) any later version.
9 *
10 *  GRUB is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <grub/mm.h>
20#include <grub/misc.h>
21
22#include <grub/types.h>
23#include <grub/types.h>
24#include <grub/err.h>
25#include <grub/cache.h>
26
27#include <grub/mips/relocator.h>
28#include <grub/relocator_private.h>
29
30/* Do we need mips64? */
31
32extern grub_uint8_t grub_relocator_forward_start;
33extern grub_uint8_t grub_relocator_forward_end;
34extern grub_uint8_t grub_relocator_backward_start;
35extern grub_uint8_t grub_relocator_backward_end;
36
37#define REGW_SIZEOF (2 * sizeof (grub_uint32_t))
38#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t))
39
40#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \
41                                 - &grub_relocator_##x##_start)
42#define RELOCATOR_SIZEOF(x)     (RELOCATOR_SRC_SIZEOF(x) \
43                                 + REGW_SIZEOF * 3)
44grub_size_t grub_relocator_align = sizeof (grub_uint32_t);
45grub_size_t grub_relocator_forward_size;
46grub_size_t grub_relocator_backward_size;
47grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF;
48
49void
50grub_cpu_relocator_init (void)
51{
52  grub_relocator_forward_size = RELOCATOR_SIZEOF(forward);
53  grub_relocator_backward_size = RELOCATOR_SIZEOF(backward);
54}
55
56static void
57write_reg (int regn, grub_uint32_t val, void **target)
58{
59  /* lui $r, (val+0x8000).  */
60  *(grub_uint32_t *) *target = ((0x3c00 | regn) << 16) | ((val + 0x8000) >> 16);
61  *target = ((grub_uint32_t *) *target) + 1;
62  /* addiu $r, $r, val. */
63  *(grub_uint32_t *) *target = (((0x2400 | regn << 5 | regn) << 16)
64                                | (val & 0xffff));
65  *target = ((grub_uint32_t *) *target) + 1;
66}
67
68static void
69write_jump (int regn, void **target)
70{
71  /* j $r.  */
72  *(grub_uint32_t *) *target = (regn<<21) | 0x8;
73  *target = ((grub_uint32_t *) *target) + 1;
74  /* nop.  */
75  *(grub_uint32_t *) *target = 0;
76  *target = ((grub_uint32_t *) *target) + 1;
77}
78
79void
80grub_cpu_relocator_jumper (void *rels, grub_addr_t addr)
81{
82  write_reg (1, addr, &rels);
83  write_jump (1, &rels);
84}
85
86void
87grub_cpu_relocator_backward (void *ptr0, void *src, void *dest,
88                             grub_size_t size)
89{
90  void *ptr = ptr0;
91  write_reg (8, (grub_uint32_t) src, &ptr);
92  write_reg (9, (grub_uint32_t) dest, &ptr);
93  write_reg (10, (grub_uint32_t) size, &ptr);
94  grub_memcpy (ptr, &grub_relocator_backward_start,
95               RELOCATOR_SRC_SIZEOF (backward));
96}
97
98void
99grub_cpu_relocator_forward (void *ptr0, void *src, void *dest,
100                             grub_size_t size)
101{
102  void *ptr = ptr0;
103  write_reg (8, (grub_uint32_t) src, &ptr);
104  write_reg (9, (grub_uint32_t) dest, &ptr);
105  write_reg (10, (grub_uint32_t) size, &ptr);
106  grub_memcpy (ptr, &grub_relocator_forward_start, 
107               RELOCATOR_SRC_SIZEOF (forward));
108}
109
110grub_err_t
111grub_relocator32_boot (struct grub_relocator *rel,
112                       struct grub_relocator32_state state)
113{
114  grub_relocator_chunk_t ch;
115  void *ptr;
116  grub_err_t err;
117  void *relst;
118  grub_size_t relsize;
119  grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF;
120  unsigned i;
121  grub_addr_t vtarget;
122
123  err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
124                                          (0xffffffff - stateset_size)
125                                          + 1, stateset_size,
126                                          sizeof (grub_uint32_t),
127                                          GRUB_RELOCATOR_PREFERENCE_NONE, 0);
128  if (err)
129    return err;
130
131  ptr = get_virtual_current_address (ch);
132  for (i = 1; i < 32; i++)
133    write_reg (i, state.gpr[i], &ptr);
134  write_jump (state.jumpreg, &ptr);
135
136  vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch),
137                                           stateset_size);
138
139  err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize);
140  if (err)
141    return err;
142
143  grub_arch_sync_caches ((void *) relst, relsize);
144
145  ((void (*) (void)) relst) ();
146
147  /* Not reached.  */
148  return GRUB_ERR_NONE;
149}
Note: See TracBrowser for help on using the repository browser.