Esempio n. 1
0
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
                int argc, char *argv[])
{
    grub_file_t file = 0;
    struct linux_kernel_header lh;
    grub_ssize_t len, start, filelen;
    void *kernel = NULL;

    grub_dl_ref (my_mod);

    if (argc == 0)
    {
        grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
        goto fail;
    }

    file = grub_file_open (argv[0]);
    if (! file)
        goto fail;

    filelen = grub_file_size (file);

    kernel = grub_malloc(filelen);

    if (!kernel)
    {
        grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
        goto fail;
    }

    if (grub_file_read (file, kernel, filelen) != filelen)
    {
        grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
        goto fail;
    }

    grub_tpm_measure (kernel, filelen, GRUB_KERNEL_PCR);

    if (! grub_linuxefi_secure_validate (kernel, filelen))
    {
        grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
        grub_free (kernel);
        goto fail;
    }

    params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));

    if (! params)
    {
        grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
        goto fail;
    }

    grub_memset (params, 0, 16384);

    grub_memcpy (&lh, kernel, sizeof (lh));

    if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
    {
        grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
        goto fail;
    }

    if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
    {
        grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
        goto fail;
    }

    if (lh.version < grub_cpu_to_le16 (0x020b))
    {
        grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
        goto fail;
    }

    if (!lh.handover_offset)
    {
        grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
        goto fail;
    }

    linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
                    BYTES_TO_PAGES(lh.cmdline_size + 1));

    if (!linux_cmdline)
    {
        grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
        goto fail;
    }

    grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
    grub_create_loader_cmdline (argc, argv,
                                linux_cmdline + sizeof (LINUX_IMAGE) - 1,
                                lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1));

    grub_pass_verity_hash(&lh, linux_cmdline);
    lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline;

    handover_offset = lh.handover_offset;

    start = (lh.setup_sects + 1) * 512;
    len = grub_file_size(file) - start;

    kernel_mem = grub_efi_allocate_pages(lh.pref_address,
                                         BYTES_TO_PAGES(lh.init_size));

    if (!kernel_mem)
        kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
                     BYTES_TO_PAGES(lh.init_size));

    if (!kernel_mem)
    {
        grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
        goto fail;
    }

    grub_memcpy (kernel_mem, (char *)kernel + start, len);
    grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
    loaded=1;

    lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
    grub_memcpy (params, &lh, 2 * 512);

    params->type_of_loader = 0x21;

fail:

    if (file)
        grub_file_close (file);

    if (kernel)
        grub_free (kernel);

    if (grub_errno != GRUB_ERR_NONE)
    {
        grub_dl_unref (my_mod);
        loaded = 0;
    }

    if (linux_cmdline && !loaded)
        grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));

    if (kernel_mem && !loaded)
        grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));

    if (params && !loaded)
        grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));

    return grub_errno;
}
Esempio n. 2
0
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
                 int argc, char *argv[])
{
    grub_file_t *files = 0;
    int i, nfiles = 0;
    grub_size_t size = 0;
    grub_uint8_t *ptr;

    if (argc == 0)
    {
        grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
        goto fail;
    }

    if (!loaded)
    {
        grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
        goto fail;
    }

    files = grub_zalloc (argc * sizeof (files[0]));
    if (!files)
        goto fail;

    for (i = 0; i < argc; i++)
    {
        grub_file_filter_disable_compression ();
        files[i] = grub_file_open (argv[i]);
        if (! files[i])
            goto fail;
        nfiles++;
        size += ALIGN_UP (grub_file_size (files[i]), 4);
    }

    initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));

    if (!initrd_mem)
    {
        grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
        goto fail;
    }

    params->ramdisk_size = size;
    params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem;

    ptr = initrd_mem;

    for (i = 0; i < nfiles; i++)
    {
        grub_ssize_t cursize = grub_file_size (files[i]);
        if (grub_file_read (files[i], ptr, cursize) != cursize)
        {
            if (!grub_errno)
                grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
                            argv[i]);
            goto fail;
        }
        grub_tpm_measure (ptr, cursize, GRUB_INITRD_PCR);
        ptr += cursize;
        grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
        ptr += ALIGN_UP_OVERHEAD (cursize, 4);
    }

    params->ramdisk_size = size;

fail:
    for (i = 0; i < nfiles; i++)
        grub_file_close (files[i]);
    grub_free (files);

    if (initrd_mem && grub_errno)
        grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size));

    return grub_errno;
}
Esempio n. 3
0
static grub_err_t
grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
		 int argc, char *argv[])
{
  grub_file_t file = 0;
  grub_ssize_t size;
  void *module = NULL;
  grub_addr_t target;
  grub_err_t err;
  int nounzip = 0;
  grub_uint64_t lowest_addr = 0;

  if (argc == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));

  if (grub_strcmp (argv[0], "--nounzip") == 0)
    {
      argv++;
      argc--;
      nounzip = 1;
    }

  if (argc == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));

  if (!grub_multiboot_relocator)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
		       N_("you need to load the kernel first"));

  if (nounzip)
    grub_file_filter_disable_compression ();

  file = grub_file_open (argv[0]);
  if (! file)
    return grub_errno;

#ifndef GRUB_USE_MULTIBOOT2
  lowest_addr = 0x100000;
  if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL)
    lowest_addr = ALIGN_UP (highest_load + 1048576, 4096);
#endif

  size = grub_file_size (file);
  if (size)
  {
    grub_relocator_chunk_t ch;
    err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
					    lowest_addr, (0xffffffff - size) + 1,
					    size, MULTIBOOT_MOD_ALIGN,
					    GRUB_RELOCATOR_PREFERENCE_NONE, 1);
    if (err)
      {
	grub_file_close (file);
	return err;
      }
    module = get_virtual_current_address (ch);
    target = get_physical_target_address (ch);
  }
  else
    {
      module = 0;
      target = 0;
    }

  err = grub_multiboot_add_module (target, size, argc - 1, argv + 1);
  if (err)
    {
      grub_file_close (file);
      return err;
    }

  if (size && grub_file_read (file, module, size) != size)
    {
      grub_file_close (file);
      if (!grub_errno)
	grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
		    argv[0]);
      return grub_errno;
    }

  grub_file_close (file);
  grub_tpm_measure (module, size, GRUB_BINARY_PCR, "grub_multiboot", argv[0]);
  return GRUB_ERR_NONE;
}
Esempio n. 4
0
grub_err_t
grub_multiboot_load (grub_file_t file, const char *filename)
{
  grub_properly_aligned_t *buffer;
  grub_ssize_t len;
  struct multiboot_header *header;
  grub_err_t err;
  struct multiboot_header_tag *tag;
  struct multiboot_header_tag_address *addr_tag = NULL;
  int entry_specified = 0;
  grub_addr_t entry = 0;
  grub_uint32_t console_required = 0;
  struct multiboot_header_tag_framebuffer *fbtag = NULL;
  int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;

  buffer = grub_malloc (MULTIBOOT_SEARCH);
  if (!buffer)
    return grub_errno;

  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
  if (len < 32)
    {
      grub_free (buffer);
      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename);
    }

  COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);

  grub_tpm_measure ((unsigned char *)buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename);

  header = find_header (buffer, len);

  if (header == 0)
    {
      grub_free (buffer);
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
    }

  COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % 4 == 0);

  keep_bs = 0;

  for (tag = (struct multiboot_header_tag *) (header + 1);
       tag->type != MULTIBOOT_TAG_TYPE_END;
       tag = (struct multiboot_header_tag *) ((grub_uint32_t *) tag + ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) / 4))
    switch (tag->type)
      {
      case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
	{
	  unsigned i;
	  struct multiboot_header_tag_information_request *request_tag
	    = (struct multiboot_header_tag_information_request *) tag;
	  if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
	    break;
	  for (i = 0; i < (request_tag->size - sizeof (*request_tag))
		 / sizeof (request_tag->requests[0]); i++)
	    switch (request_tag->requests[i])
	      {
	      case MULTIBOOT_TAG_TYPE_END:
	      case MULTIBOOT_TAG_TYPE_CMDLINE:
	      case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
	      case MULTIBOOT_TAG_TYPE_MODULE:
	      case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
	      case MULTIBOOT_TAG_TYPE_BOOTDEV:
	      case MULTIBOOT_TAG_TYPE_MMAP:
	      case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
	      case MULTIBOOT_TAG_TYPE_VBE:
	      case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
	      case MULTIBOOT_TAG_TYPE_APM:
	      case MULTIBOOT_TAG_TYPE_EFI32:
	      case MULTIBOOT_TAG_TYPE_EFI64:
	      case MULTIBOOT_TAG_TYPE_ACPI_OLD:
	      case MULTIBOOT_TAG_TYPE_ACPI_NEW:
	      case MULTIBOOT_TAG_TYPE_NETWORK:
	      case MULTIBOOT_TAG_TYPE_EFI_MMAP:
	      case MULTIBOOT_TAG_TYPE_EFI_BS:
		break;

	      default:
		grub_free (buffer);
		return grub_error (GRUB_ERR_UNKNOWN_OS,
				   "unsupported information tag: 0x%x",
				   request_tag->requests[i]);
	      }
	  break;
	}
	       
      case MULTIBOOT_HEADER_TAG_ADDRESS:
	addr_tag = (struct multiboot_header_tag_address *) tag;
	break;

      case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
	entry_specified = 1;
	entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
	break;

      case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
	if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
	    & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
	  accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
	if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
	    & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
	  console_required = 1;
	break;

      case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
	fbtag = (struct multiboot_header_tag_framebuffer *) tag;
	accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
	break;

	/* GRUB always page-aligns modules.  */
      case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
	break;

      case MULTIBOOT_HEADER_TAG_EFI_BS:
	keep_bs = 1;
	break;

      default:
	if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
	  {
	    grub_free (buffer);
	    return grub_error (GRUB_ERR_UNKNOWN_OS,
			       "unsupported tag: 0x%x", tag->type);
	  }
	break;
      }

  if (addr_tag && !entry_specified)
    {
      grub_free (buffer);
      return grub_error (GRUB_ERR_UNKNOWN_OS,
			 "load address tag without entry address tag");
    }
 
  if (addr_tag)
    {
      grub_uint64_t load_addr = (addr_tag->load_addr + 1)
	? addr_tag->load_addr : (addr_tag->header_addr
				 - ((char *) header - (char *) buffer));
      int offset = ((char *) header - (char *) buffer -
	   (addr_tag->header_addr - load_addr));
      int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
		       addr_tag->load_end_addr - addr_tag->load_addr);
      grub_size_t code_size;
      void *source;
      grub_relocator_chunk_t ch;

      if (addr_tag->bss_end_addr)
	code_size = (addr_tag->bss_end_addr - load_addr);
      else
	code_size = load_size;

      err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, 
					     &ch, load_addr,
					     code_size);
      if (err)
	{
	  grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
	  grub_free (buffer);
	  return err;
	}
      source = get_virtual_current_address (ch);

      if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
	{
	  grub_free (buffer);
	  return grub_errno;
	}

      grub_file_read (file, source, load_size);
      if (grub_errno)
	{
	  grub_free (buffer);
	  return grub_errno;
	}

      if (addr_tag->bss_end_addr)
	grub_memset ((grub_uint8_t *) source + load_size, 0,
		     addr_tag->bss_end_addr - load_addr - load_size);
    }
  else
    {
      err = grub_multiboot_load_elf (file, filename, buffer);
      if (err)
	{
	  grub_free (buffer);
	  return err;
	}
    }

  if (entry_specified)
    grub_multiboot_payload_eip = entry;

  if (fbtag)
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
				      accepted_consoles,
				      fbtag->width, fbtag->height,
				      fbtag->depth, console_required);
  else
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
				      accepted_consoles,
				      0, 0, 0, console_required);
  return err;
}
Esempio n. 5
0
grub_err_t
grub_multiboot_load (grub_file_t file, const char *filename)
{
  char *buffer;
  grub_ssize_t len;
  struct multiboot_header *header;
  grub_err_t err;

  buffer = grub_malloc (MULTIBOOT_SEARCH);
  if (!buffer)
    return grub_errno;

  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
  if (len < 32)
    {
      grub_free (buffer);
      if (!grub_errno)
	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
		    filename);
      return grub_errno;
    }

  grub_tpm_measure((unsigned char*)buffer, len, GRUB_KERNEL_PCR, filename);

  header = find_header (buffer, len);

  if (header == 0)
    {
      grub_free (buffer);
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
    }

  if (header->flags & UNSUPPORTED_FLAGS)
    {
      grub_free (buffer);
      return grub_error (GRUB_ERR_UNKNOWN_OS,
			 "unsupported flag: 0x%x", header->flags);
    }

  err = load_kernel (file, filename, buffer, header);
  if (err)
    {
      grub_free (buffer);
      return err;
    }

  if (header->flags & MULTIBOOT_VIDEO_MODE)
    {
      switch (header->mode_type)
	{
	case 1:
	  err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT, 
					    GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
					    | GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
					    0, 0, 0, 0);
	  break;
	case 0:
	  err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
					    GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
					    | GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
					    header->width, header->height,
					    header->depth, 0);
	  break;
	default:
	  err = grub_error (GRUB_ERR_BAD_OS, 
			    "unsupported graphical mode type %d",
			    header->mode_type);
	  break;
	}
    }
  else
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT, 
				      GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
				      0, 0, 0, 0);
  return err;
}