Esempio n. 1
0
/* Find the optimal number of pages for the memory map. Is it better to
   move this code to efi/mm.c?  */
static void
find_efi_mmap_size (void)
{
  efi_mmap_size = (1 << 12);
  while (1)
    {
      int ret;
      grub_efi_memory_descriptor_t *mmap;
      grub_efi_uintn_t desc_size;
      grub_efi_uintn_t cur_mmap_size = efi_mmap_size;

      mmap = grub_malloc (cur_mmap_size);
      if (! mmap)
	return;

      ret = grub_efi_get_memory_map (&cur_mmap_size, mmap, 0, &desc_size, 0);
      grub_free (mmap);

      if (ret < 0)
	return;
      else if (ret > 0)
	break;

      if (efi_mmap_size < cur_mmap_size)
	efi_mmap_size = cur_mmap_size;
      efi_mmap_size += (1 << 12);
    }

  /* Increase the size a bit for safety, because GRUB allocates more on
     later, and EFI itself may allocate more.  */
  efi_mmap_size += (3 << 12);

  efi_mmap_size = ALIGN_UP (efi_mmap_size, 4096);
}
Esempio n. 2
0
int
grub_efi_finish_boot_services (void)
{
  grub_efi_uintn_t mmap_size = 0;
  grub_efi_uintn_t map_key;
  grub_efi_uintn_t desc_size;
  grub_efi_uint32_t desc_version;
  void *mmap_buf = 0;

  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
			       &desc_size, &desc_version) < 0)
    return 0;

  mmap_buf = grub_malloc (mmap_size);

  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
			       &desc_size, &desc_version) <= 0)
    return 0;

  return grub_efi_exit_boot_services (map_key);
}
Esempio n. 3
0
static void
update_e820_map (struct e820_entry *e820_map,
		 int *e820_nr_map)
{
  grub_efi_uintn_t desc_size;

  if (grub_efi_get_memory_map (0, &desc_size, 0) < 0)
    {
      grub_printf ("cannot get memory map");
      return;
    }

  e820_map_from_efi_map (e820_map, e820_nr_map,
			 mmap_buf, desc_size, mmap_size);
}
Esempio n. 4
0
/* Find the optimal number of pages for the memory map. Is it better to
   move this code to efi/mm.c?  */
static grub_efi_uintn_t
find_efi_mmap_size (void)
{
  static grub_efi_uintn_t mmap_size = 0;

  if (mmap_size != 0)
    return mmap_size;

  mmap_size = (1 << 12);
  while (1)
    {
      int ret;
      grub_efi_memory_descriptor_t *mmap;
      grub_efi_uintn_t desc_size;
      grub_efi_uintn_t cur_mmap_size = mmap_size;

      mmap = grub_malloc (cur_mmap_size);
      if (! mmap)
	return 0;

      ret = grub_efi_get_memory_map (&cur_mmap_size, mmap, 0, &desc_size, 0);
      grub_free (mmap);

      if (ret < 0)
	{
	  grub_error (GRUB_ERR_IO, "cannot get memory map");
	  return 0;
	}
      else if (ret > 0)
	break;

      if (mmap_size < cur_mmap_size)
	mmap_size = cur_mmap_size;
      mmap_size += (1 << 12);
    }

  /* Increase the size a bit for safety, because GRUB allocates more on
     later, and EFI itself may allocate more.  */
  mmap_size += (3 << 12);

  mmap_size = page_align (mmap_size);
  return mmap_size;
}
Esempio n. 5
0
grub_err_t
grub_multiboot_make_mbi (grub_uint32_t *target)
{
  grub_properly_aligned_t *ptrorig;
  grub_properly_aligned_t *mbistart;
  grub_err_t err;
  grub_size_t bufsize;
  grub_relocator_chunk_t ch;

  bufsize = grub_multiboot_get_mbi_size ();

  COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);

  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
					  0, 0xffffffff - bufsize,
					  bufsize, MULTIBOOT_TAG_ALIGN,
					  GRUB_RELOCATOR_PREFERENCE_NONE, 1);
  if (err)
    return err;

  ptrorig = get_virtual_current_address (ch);
#if defined (__i386__) || defined (__x86_64__)
  *target = get_physical_target_address (ch);
#elif defined (__mips)
  *target = get_physical_target_address (ch) | 0x80000000;
#else
#error Please complete this
#endif

  mbistart = ptrorig;
  COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t))
		       % sizeof (grub_properly_aligned_t) == 0);
  COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
		       % sizeof (grub_properly_aligned_t) == 0);
  ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t);

  {
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
    tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; 
    grub_memcpy (tag->string, cmdline, cmdline_size);
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
       / sizeof (grub_properly_aligned_t);
  }

  {
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
    tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); 
    grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

#ifdef GRUB_MACHINE_PCBIOS
  {
    struct grub_apm_info info;
    if (grub_apm_get_info (&info))
      {
	struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig;

	tag->type = MULTIBOOT_TAG_TYPE_APM;
	tag->size = sizeof (struct multiboot_tag_apm); 

	tag->cseg = info.cseg;
	tag->offset = info.offset;
	tag->cseg_16 = info.cseg_16;
	tag->dseg = info.dseg;
	tag->flags = info.flags;
	tag->cseg_len = info.cseg_len;
	tag->dseg_len = info.dseg_len;
	tag->cseg_16_len = info.cseg_16_len;
	tag->version = info.version;

	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }
#endif

  {
    unsigned i;
    struct module *cur;

    for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
      {
	struct multiboot_tag_module *tag
	  = (struct multiboot_tag_module *) ptrorig;
	tag->type = MULTIBOOT_TAG_TYPE_MODULE;
	tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
	tag->mod_start = cur->start;
	tag->mod_end = tag->mod_start + cur->size;
	grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }

  {
    struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
    grub_fill_multiboot_mmap (tag);
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  {
    struct multiboot_tag_elf_sections *tag
      = (struct multiboot_tag_elf_sections *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS;
    tag->size = sizeof (struct multiboot_tag_elf_sections)
      + elf_sec_entsize * elf_sec_num;
    grub_memcpy (tag->sections, elf_sections, elf_sec_entsize * elf_sec_num);
    tag->num = elf_sec_num;
    tag->entsize = elf_sec_entsize;
    tag->shndx = elf_sec_shstrndx;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  {
    struct multiboot_tag_basic_meminfo *tag
      = (struct multiboot_tag_basic_meminfo *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
    tag->size = sizeof (struct multiboot_tag_basic_meminfo); 

    /* Convert from bytes to kilobytes.  */
    tag->mem_lower = grub_mmap_get_lower () / 1024;
    tag->mem_upper = grub_mmap_get_upper () / 1024;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
       / sizeof (grub_properly_aligned_t);
  }

  {
    struct grub_net_network_level_interface *net;

    FOR_NET_NETWORK_LEVEL_INTERFACES(net)
      if (net->dhcp_ack)
	{
	  struct multiboot_tag_network *tag
	    = (struct multiboot_tag_network *) ptrorig;
	  tag->type = MULTIBOOT_TAG_TYPE_NETWORK;
	  tag->size = sizeof (struct multiboot_tag_network) + net->dhcp_acklen;
	  grub_memcpy (tag->dhcpack, net->dhcp_ack, net->dhcp_acklen);
	  ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	    / sizeof (grub_properly_aligned_t);
	}
  }

  if (bootdev_set)
    {
      struct multiboot_tag_bootdev *tag
	= (struct multiboot_tag_bootdev *) ptrorig;
      tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
      tag->size = sizeof (struct multiboot_tag_bootdev); 

      tag->biosdev = biosdev;
      tag->slice = slice;
      tag->part = part;
      ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	/ sizeof (grub_properly_aligned_t);
    }

  {
    err = retrieve_video_parameters (&ptrorig);
    if (err)
      {
	grub_print_error ();
	grub_errno = GRUB_ERR_NONE;
      }
  }

#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
  {
    struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi64 *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_EFI64;
    tag->size = sizeof (*tag);
    tag->pointer = (grub_addr_t) grub_efi_system_table;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }
#endif

#if defined (GRUB_MACHINE_EFI) && defined (__i386__)
  {
    struct multiboot_tag_efi32 *tag = (struct multiboot_tag_efi32 *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_EFI32;
    tag->size = sizeof (*tag);
    tag->pointer = (grub_addr_t) grub_efi_system_table;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }
#endif

#if GRUB_MACHINE_HAS_ACPI
  {
    struct multiboot_tag_old_acpi *tag = (struct multiboot_tag_old_acpi *)
      ptrorig;
    struct grub_acpi_rsdp_v10 *a = grub_acpi_get_rsdpv1 ();
    if (a)
      {
	tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
	tag->size = sizeof (*tag) + sizeof (*a);
	grub_memcpy (tag->rsdp, a, sizeof (*a));
	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }

  {
    struct multiboot_tag_new_acpi *tag = (struct multiboot_tag_new_acpi *)
      ptrorig;
    struct grub_acpi_rsdp_v20 *a = grub_acpi_get_rsdpv2 ();
    if (a)
      {
	tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
	tag->size = sizeof (*tag) + a->length;
	grub_memcpy (tag->rsdp, a, a->length);
	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }
#endif

#ifdef GRUB_MACHINE_EFI
  {
    struct multiboot_tag_efi_mmap *tag = (struct multiboot_tag_efi_mmap *) ptrorig;
    grub_efi_uintn_t efi_desc_size;
    grub_efi_uint32_t efi_desc_version;

    tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
    tag->size = sizeof (*tag) + efi_mmap_size;

    if (!keep_bs)
      err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
					   &efi_desc_size, &efi_desc_version);
    else
      {
	if (grub_efi_get_memory_map (&efi_mmap_size, (void *) tag->efi_mmap,
				     NULL,
				     &efi_desc_size, &efi_desc_version) <= 0)
	  err = grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
      }
    if (err)
      return err;
    tag->descr_size = efi_desc_size;
    tag->descr_vers = efi_desc_version;
    tag->size = sizeof (*tag) + efi_mmap_size;

    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  if (keep_bs)
    {
      struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
      tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
      tag->size = sizeof (struct multiboot_tag);
      ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	/ sizeof (grub_properly_aligned_t);
    }
#endif

  {
    struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_END;
    tag->size = sizeof (struct multiboot_tag);
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  ((grub_uint32_t *) mbistart)[0] = (char *) ptrorig - (char *) mbistart;
  ((grub_uint32_t *) mbistart)[1] = 0;

  return GRUB_ERR_NONE;
}
Esempio n. 6
0
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
  grub_efi_uintn_t mmap_size = 0;
  grub_efi_memory_descriptor_t *map_buf = 0;
  grub_efi_uintn_t map_key = 0;
  grub_efi_uintn_t desc_size = 0;
  grub_efi_uint32_t desc_version = 0;
  grub_efi_memory_descriptor_t *desc;

  if (grub_efi_get_memory_map (&mmap_size, map_buf,
			       &map_key, &desc_size,
			       &desc_version) < 0)
    return grub_errno;

  map_buf = grub_malloc (mmap_size);
  if (! map_buf)
    return grub_errno;

  if (grub_efi_get_memory_map (&mmap_size, map_buf,
			       &map_key, &desc_size,
			       &desc_version) <= 0)
    {
      grub_free (map_buf);
      return grub_errno;
    }

  for (desc = map_buf;
       desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size);
       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
    {
      grub_dprintf ("mmap", "EFI memory region 0x%llx-0x%llx: %d\n",
		    (unsigned long long) desc->physical_start,
		    (unsigned long long) desc->physical_start
		    + desc->num_pages * 4096, desc->type);
      switch (desc->type)
	{
	case GRUB_EFI_RUNTIME_SERVICES_CODE:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_CODE);
	  break;

	case GRUB_EFI_UNUSABLE_MEMORY:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_BADRAM);
	  break;

	default:
	  grub_printf ("Unknown memory type %d, considering reserved\n",
		       desc->type);

	case GRUB_EFI_RESERVED_MEMORY_TYPE:
	case GRUB_EFI_RUNTIME_SERVICES_DATA:
	case GRUB_EFI_MEMORY_MAPPED_IO:
	case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
	case GRUB_EFI_PAL_CODE:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_RESERVED);
	  break;

	case GRUB_EFI_LOADER_CODE:
	case GRUB_EFI_LOADER_DATA:
	case GRUB_EFI_BOOT_SERVICES_CODE:
	case GRUB_EFI_BOOT_SERVICES_DATA:
	case GRUB_EFI_CONVENTIONAL_MEMORY:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_AVAILABLE);
	  break;

	case GRUB_EFI_ACPI_RECLAIM_MEMORY:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_ACPI);
	  break;

	case GRUB_EFI_ACPI_MEMORY_NVS:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_NVS);
	  break;
	}
    }

  return GRUB_ERR_NONE;
}