#define RELOCATOR_SIZEOF(x) (&grub_relocator32_##x##_end - &grub_relocator32_##x##_start)
#define RELOCATOR_ALIGN 16
+#define PREFIX(x) grub_relocator32_ ## x
-void *
-grub_relocator32_alloc (grub_size_t size)
+static void
+write_relocator_bw (void *ptr, void *src, grub_uint32_t dest,
+ grub_size_t size, struct grub_relocator32_state state)
{
- char *playground;
-
- playground = grub_malloc ((RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
- + size
- + (RELOCATOR_SIZEOF (backward) +
- RELOCATOR_ALIGN));
- if (!playground)
- return 0;
-
- *(grub_size_t *) playground = size;
-
- return playground + RELOCATOR_SIZEOF (forward);
-}
-
-void *
-grub_relocator32_realloc (void *relocator, grub_size_t size)
-{
- char *playground;
-
- playground = (char *) relocator - RELOCATOR_SIZEOF (forward);
-
- playground = grub_realloc (playground,
- (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
- + size
- + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN));
- if (!playground)
- return 0;
-
- *(grub_size_t *) playground = size;
-
- return playground + RELOCATOR_SIZEOF (forward);
-}
+ void (*entry) ();
-void
-grub_relocator32_free (void *relocator)
-{
- if (relocator)
- grub_free ((char *) relocator - RELOCATOR_SIZEOF (forward));
+ grub_relocator32_backward_dest = dest;
+ grub_relocator32_backward_src = PTR_TO_UINT64 (src);
+ grub_relocator32_backward_size = size;
+
+ grub_relocator32_backward_eax = state.eax;
+ grub_relocator32_backward_ebx = state.ebx;
+ grub_relocator32_backward_ecx = state.ecx;
+ grub_relocator32_backward_edx = state.edx;
+ grub_relocator32_backward_eip = state.eip;
+ grub_relocator32_backward_esp = state.esp;
+
+ grub_memmove (ptr,
+ &grub_relocator32_backward_start,
+ RELOCATOR_SIZEOF (backward));
+ entry = (void (*)()) (ptr);
+ entry ();
}
-
-grub_err_t
-grub_relocator32_boot (void *relocator, grub_uint32_t dest,
- struct grub_relocator32_state state)
+static void
+write_relocator_bw (void *ptr, void *src, grub_uint32_t dest,
+ grub_size_t size, struct grub_relocator32_state state)
{
- grub_size_t size;
- char *playground;
- void (*entry) ();
-
- playground = (char *) relocator - RELOCATOR_SIZEOF (forward);
- size = *(grub_size_t *) playground;
-
- if (UINT_TO_PTR (dest) >= relocator)
- {
- int overhead;
-
- overhead =
- ALIGN_UP (dest - RELOCATOR_SIZEOF (backward) - RELOCATOR_ALIGN,
- RELOCATOR_ALIGN);
- grub_relocator32_backward_dest = dest - overhead;
- grub_relocator32_backward_src = PTR_TO_UINT64 (relocator - overhead);
- grub_relocator32_backward_size = size + overhead;
- grub_relocator32_backward_eax = state.eax;
- grub_relocator32_backward_ebx = state.ebx;
- grub_relocator32_backward_ecx = state.ecx;
- grub_relocator32_backward_edx = state.edx;
- grub_relocator32_backward_eip = state.eip;
- grub_relocator32_backward_esp = state.esp;
-
- grub_memmove (relocator - overhead,
- &grub_relocator32_backward_start,
- RELOCATOR_SIZEOF (backward));
- entry = (void (*)()) (relocator - overhead);
- }
- else
- {
- int overhead;
-
- overhead = ALIGN_UP (dest + size, RELOCATOR_ALIGN)
- + RELOCATOR_SIZEOF (forward) - (dest + size);
-
- grub_relocator32_forward_dest = dest;
- grub_relocator32_forward_src = PTR_TO_UINT64 (relocator);
- grub_relocator32_forward_size = size + overhead;
-
- grub_relocator32_forward_eax = state.eax;
- grub_relocator32_forward_ebx = state.ebx;
- grub_relocator32_forward_ecx = state.ecx;
- grub_relocator32_forward_edx = state.edx;
- grub_relocator32_forward_eip = state.eip;
- grub_relocator32_forward_esp = state.esp;
-
- grub_memmove (relocator + size + overhead - RELOCATOR_SIZEOF (forward),
- &grub_relocator32_forward_start,
- RELOCATOR_SIZEOF (forward));
- entry =
- (void (*)()) (relocator + size + overhead -
- RELOCATOR_SIZEOF (forward));
- }
+ grub_relocator32_forward_dest = dest;
+ grub_relocator32_forward_src = PTR_TO_UINT64 (src);
+ grub_relocator32_forward_size = size;
+
+ grub_relocator32_forward_eax = state.eax;
+ grub_relocator32_forward_ebx = state.ebx;
+ grub_relocator32_forward_ecx = state.ecx;
+ grub_relocator32_forward_edx = state.edx;
+ grub_relocator32_forward_eip = state.eip;
+ grub_relocator32_forward_esp = state.esp;
+
+ grub_memmove (ptr,
+ &grub_relocator32_forward_start,
+ RELOCATOR_SIZEOF (forward));
+ entry = (void (*)()) ptr;
entry ();
-
- /* Not reached. */
- return GRUB_ERR_NONE;
}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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/>.
+ */
+
+void *
+PREFIX (alloc) (grub_size_t size)
+{
+ char *playground;
+
+ playground = grub_malloc ((RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
+ + size
+ + (RELOCATOR_SIZEOF (backward) +
+ RELOCATOR_ALIGN));
+ if (!playground)
+ return 0;
+
+ *(grub_size_t *) playground = size;
+
+ return playground + RELOCATOR_SIZEOF (forward);
+}
+
+void *
+PREFIX (realloc) (void *relocator, grub_size_t size)
+{
+ char *playground;
+
+ playground = (char *) relocator - RELOCATOR_SIZEOF (forward);
+
+ playground = grub_realloc (playground,
+ (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
+ + size
+ + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN));
+ if (!playground)
+ return 0;
+
+ *(grub_size_t *) playground = size;
+
+ return playground + RELOCATOR_SIZEOF (forward);
+}
+
+void
+PREFIX(free) (void *relocator)
+{
+ if (relocator)
+ grub_free ((char *) relocator - RELOCATOR_SIZEOF (forward));
+}
+
+grub_err_t
+PREFIX (boot) (void *relocator, grub_uint32_t dest,
+ struct grub_relocator32_state state)
+{
+ grub_size_t size;
+ char *playground;
+
+ playground = (char *) relocator - RELOCATOR_SIZEOF (forward);
+ size = *(grub_size_t *) playground;
+
+ if (UINT_TO_PTR (dest) >= relocator)
+ {
+ int overhead;
+ void *reldest = relocator - overhead;
+ overhead =
+ ALIGN_UP (dest - RELOCATOR_SIZEOF (backward) - RELOCATOR_ALIGN,
+ RELOCATOR_ALIGN);
+ write_call_relocator_bw (relocator - overhead,
+ relocator - overhead,
+ dest - overhead, size + overhead, state);
+ }
+ else
+ {
+ int overhead;
+
+ overhead = ALIGN_UP (dest + size, RELOCATOR_ALIGN)
+ + RELOCATOR_SIZEOF (forward) - (dest + size);
+
+ write_call_relocator_fw (relocator + size + overhead
+ - RELOCATOR_SIZEOF (forward),
+ relocator, dest, size + overhead, state);
+ }
+
+ /* Not reached. */
+ return GRUB_ERR_NONE;
+}