Exemplo n.º 1
0
grub_err_t
grub_relocator16_boot (struct grub_relocator *rel,
		       struct grub_relocator16_state state)
{
  grub_err_t err;
  void *relst;
  grub_relocator_chunk_t ch;

  /* Put it higher than the byte it checks for A20 check.  */
  err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
					  0xa0000 - RELOCATOR_SIZEOF (16)
					  - GRUB_RELOCATOR16_STACK_SIZE,
					  RELOCATOR_SIZEOF (16)
					  + GRUB_RELOCATOR16_STACK_SIZE, 16,
					  GRUB_RELOCATOR_PREFERENCE_NONE,
					  0);
  if (err)
    return err;

  grub_relocator16_cs = state.cs;  
  grub_relocator16_ip = state.ip;

  grub_relocator16_ds = state.ds;
  grub_relocator16_es = state.es;
  grub_relocator16_fs = state.fs;
  grub_relocator16_gs = state.gs;

  grub_relocator16_ss = state.ss;
  grub_relocator16_sp = state.sp;

  grub_relocator16_ebp = state.ebp;
  grub_relocator16_ebx = state.ebx;
  grub_relocator16_edx = state.edx;
  grub_relocator16_esi = state.esi;
#ifdef GRUB_MACHINE_PCBIOS
  grub_relocator16_idt = *grub_realidt;
#else
  grub_relocator16_idt.base = 0;
  grub_relocator16_idt.limit = 0;
#endif

  grub_relocator16_keep_a20_enabled = state.a20;

  grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start,
		RELOCATOR_SIZEOF (16));

  err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch),
				       &relst, NULL);
  if (err)
    return err;

  asm volatile ("cli");
  ((void (*) (void)) relst) ();

  /* Not reached.  */
  return GRUB_ERR_NONE;
}
Exemplo n.º 2
0
grub_err_t
grub_relocator32_boot (struct grub_relocator *rel,
		       struct grub_relocator32_state state,
		       int avoid_efi_bootservices)
{
  grub_err_t err;
  void *relst;
  grub_relocator_chunk_t ch;

  err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
					  (0xffffffff - RELOCATOR_SIZEOF (32))
					  + 1, RELOCATOR_SIZEOF (32), 16,
					  GRUB_RELOCATOR_PREFERENCE_NONE,
					  avoid_efi_bootservices);
  if (err)
    return err;

  grub_relocator32_eax = state.eax;
  grub_relocator32_ebx = state.ebx;
  grub_relocator32_ecx = state.ecx;
  grub_relocator32_edx = state.edx;
  grub_relocator32_eip = state.eip;
  grub_relocator32_esp = state.esp;
  grub_relocator32_ebp = state.ebp;
  grub_relocator32_esi = state.esi;
  grub_relocator32_edi = state.edi;

  grub_memmove (get_virtual_current_address (ch), &grub_relocator32_start,
		RELOCATOR_SIZEOF (32));

  err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch),
				       &relst, NULL);
  if (err)
    return err;

  asm volatile ("cli");
  ((void (*) (void)) relst) ();

  /* Not reached.  */
  return GRUB_ERR_NONE;
}
Exemplo n.º 3
0
grub_err_t
grub_relocator64_boot (struct grub_relocator *rel,
		       struct grub_relocator64_state state,
		       grub_addr_t min_addr, grub_addr_t max_addr)
{
  grub_err_t err;
  void *relst;
  grub_relocator_chunk_t ch;

  err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr,
					  max_addr - RELOCATOR_SIZEOF (64),
					  RELOCATOR_SIZEOF (64), 16,
					  GRUB_RELOCATOR_PREFERENCE_NONE,
					  0);
  if (err)
    return err;

  grub_relocator64_rax = state.rax;
  grub_relocator64_rbx = state.rbx;
  grub_relocator64_rcx = state.rcx;
  grub_relocator64_rdx = state.rdx;
  grub_relocator64_rip = state.rip;
  grub_relocator64_rsp = state.rsp;
  grub_relocator64_rsi = state.rsi;
  grub_relocator64_cr3 = state.cr3;

  grub_memmove (get_virtual_current_address (ch), &grub_relocator64_start,
		RELOCATOR_SIZEOF (64));

  err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch),
				       &relst, NULL);
  if (err)
    return err;

  asm volatile ("cli");
  ((void (*) (void)) relst) ();

  /* Not reached.  */
  return GRUB_ERR_NONE;
}
Exemplo n.º 4
0
void
grub_cpu_relocator_init (void)
{
  grub_relocator_forward_size = RELOCATOR_SIZEOF(forward);
  grub_relocator_backward_size = RELOCATOR_SIZEOF(backward);
}
Exemplo n.º 5
0
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 - PRE_REGION_SIZE;
  size = *(grub_size_t *) playground;

  grub_dprintf ("relocator",
		"Relocator: source: %p, destination: 0x%x, size: 0x%lx\n",
		relocator, (unsigned) dest, (unsigned long) size);

  /* Very unlikely condition: Relocator may risk overwrite itself.
     Just move it a bit up.  */
  if ((grub_addr_t) dest < (grub_addr_t) relocator
      + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN)
      && (grub_addr_t) dest + (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
      > (grub_addr_t) relocator)
    {
      void *relocator_new = ((grub_uint8_t *) relocator)
	+ (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
	+ (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN);
      grub_dprintf ("relocator", "Overwrite condition detected moving "
		    "relocator from %p to %p\n", relocator, relocator_new);
      grub_memmove (relocator_new, relocator,
		    (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
		    + size
		    + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN));
      relocator = relocator_new;
    }

  if ((grub_addr_t) dest >= (grub_addr_t) relocator)
    {
      int overhead;
      overhead = dest -
	ALIGN_UP (dest - RELOCATOR_SIZEOF (backward) - RELOCATOR_ALIGN,
		  RELOCATOR_ALIGN);
      grub_dprintf ("relocator",
		    "Backward relocator: code %p, source: %p, "
		    "destination: 0x%x, size: 0x%lx\n",
		    (char *) relocator - overhead,
		    (char *) relocator - overhead,
		    (unsigned) dest - overhead,
		    (unsigned long) size + overhead);

      write_call_relocator_bw ((char *) relocator - overhead,
			       (char *) relocator - overhead,
			       dest - overhead, size + overhead, state);
    }
  else
    {
      int overhead;

      overhead = ALIGN_UP (dest + size, RELOCATOR_ALIGN)
	+ RELOCATOR_SIZEOF (forward) - (dest + size);
      grub_dprintf ("relocator",
		    "Forward relocator: code %p, source: %p, "
		    "destination: 0x%x, size: 0x%lx\n",
		    (char *) relocator + size + overhead
		    - RELOCATOR_SIZEOF (forward),
		    relocator, (unsigned) dest,
		    (unsigned long) size + overhead);

      write_call_relocator_fw ((char *) relocator + size + overhead
			       - RELOCATOR_SIZEOF (forward),
			       relocator, dest, size + overhead, state);
    }

  /* Not reached.  */
  return GRUB_ERR_NONE;
}