Beispiel #1
0
/* This function creates a new scaled version of the bitmap SRC.  The new
   bitmap has dimensions DST_WIDTH by DST_HEIGHT.  The scaling algorithm
   is given by SCALE_METHOD.  If an error is encountered, the return code is
   not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or
   it is destroyed before this function returns.

   Supports only direct color modes which have components separated
   into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
   But because of this simplifying assumption, the implementation is
   greatly simplified.  */
grub_err_t
grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
                                 int dst_width, int dst_height,
                                 struct grub_video_bitmap *src,
                                 enum grub_video_bitmap_scale_method
                                 scale_method)
{
  *dst = 0;

  /* Verify the simplifying assumptions. */
  if (src == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       "null src bitmap in grub_video_bitmap_create_scaled");
  if (src->mode_info.red_field_pos % 8 != 0
      || src->mode_info.green_field_pos % 8 != 0
      || src->mode_info.blue_field_pos % 8 != 0
      || src->mode_info.reserved_field_pos % 8 != 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       "src format not supported for scale");
  if (src->mode_info.width == 0 || src->mode_info.height == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       "source bitmap has a zero dimension");
  if (dst_width <= 0 || dst_height <= 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       "requested to scale to a size w/ a zero dimension");
  if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       "bitmap to scale has inconsistent Bpp and bpp");

  /* Create the new bitmap. */
  grub_err_t ret;
  ret = grub_video_bitmap_create (dst, dst_width, dst_height,
                                  src->mode_info.blit_format);
  if (ret != GRUB_ERR_NONE)
    return ret;                 /* Error. */

  switch (scale_method)
    {
    case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST:
    case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST:
      ret = scale_nn (*dst, src);
      break;
    case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST:
    case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR:
      ret = scale_bilinear (*dst, src);
      break;
    default:
      ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale_method value");
      break;
    }

  if (ret == GRUB_ERR_NONE)
    {
      /* Success:  *dst is now a pointer to the scaled bitmap. */
      return GRUB_ERR_NONE;
    }
  else
    {
      /* Destroy the bitmap and return the error code. */
      grub_video_bitmap_destroy (*dst);
      *dst = 0;
      return ret;
    }
}
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
		    grub_disk_addr_t *start_sector)
{
  grub_disk_addr_t sector = 0;
  grub_uint64_t size;
  struct grub_raid_super_1x sb;
  grub_uint8_t minor_version;

  /* The sector where the mdraid 0.90 superblock is stored, if available.  */
  size = grub_disk_get_size (disk);

  /* Check for an 1.x superblock.
   * It's always aligned to a 4K boundary
   * and depending on the minor version it can be:
   * 0: At least 8K, but less than 12K, from end of device
   * 1: At start of device
   * 2: 4K from start of device.
   */

  for (minor_version = 0; minor_version < 3; ++minor_version)
    {
      if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0)
	continue;
	
      switch (minor_version)
	{
	case 0:
	  sector = (size - 8 * 2) & ~(4 * 2 - 1);
	  break;
	case 1:
	  sector = 0;
	  break;
	case 2:
	  sector = 4 * 2;
	  break;
	}

      if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
			  &sb))
	return grub_errno;

      if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
	  || grub_le_to_cpu64 (sb.super_offset) != sector)
	continue;

      {
	grub_uint64_t sb_size;
	struct grub_raid_super_1x *real_sb;
	grub_uint32_t level;

	if (grub_le_to_cpu32 (sb.major_version) != 1)
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
			     "Unsupported RAID version: %d",
			     grub_le_to_cpu32 (sb.major_version));

	level = grub_le_to_cpu32 (sb.level);

	/* Multipath.  */
	if ((int) level == -4)
	  level = 1;

	if (level != 0 && level != 1 && level != 4 &&
	    level != 5 && level != 6 && level != 10)
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
			     "Unsupported RAID level: %d", sb.level);

	/* 1.x superblocks don't have a fixed size on disk.  So we have to
	   read it again now that we now the max device count.  */
	sb_size = sizeof (struct grub_raid_super_1x) 
	  + 2 * grub_le_to_cpu32 (sb.max_dev);
	real_sb = grub_malloc (sb_size);
	if (! real_sb)
	  return grub_errno;

	if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
	  {
	    grub_free (real_sb);
	    return grub_errno;
	  }

	array->name = grub_strdup (real_sb->set_name);
	if (! array->name)
	  {
	    grub_free (real_sb);
	    return grub_errno;
	  }

	array->number = 0;
	array->level = grub_le_to_cpu32 (real_sb->level);
	array->layout = grub_le_to_cpu32 (real_sb->layout);
	array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
	array->disk_size = grub_le_to_cpu64 (real_sb->size);
	array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);

	if (grub_le_to_cpu32 (real_sb->dev_number) >=
	    grub_le_to_cpu32 (real_sb->max_dev))
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
			     "spares aren't implemented");

	array->index = grub_le_to_cpu16
	  (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
	array->uuid_len = 16;
	array->uuid = grub_malloc (16);
	if (!array->uuid)
	  {
	    grub_free (real_sb);
	    return grub_errno;
	  }

	grub_memcpy (array->uuid, real_sb->set_uuid, 16);
	
	*start_sector = grub_le_to_cpu64 (real_sb->data_offset);

	grub_free (real_sb);
	return 0;
      }
    }

  return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
}
Beispiel #3
0
/*
 * uboot_disk_open():
 *   Opens a disk device already enumerated.
 */
static grub_err_t
uboot_disk_open (const char *name, struct grub_disk *disk)
{
  struct ubootdisk_data *d;
  struct device_info *devinfo;
  int num;
  int retval;

  grub_dprintf ("ubootdisk", "Opening '%s'\n", name);

  num = grub_strtoul (name + 2, 0, 10);
  if (grub_errno != GRUB_ERR_NONE)
    {
      grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid number\n",
		    name);
      goto fail;
    }

  if (name[1] != 'd')
    {
      grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid name\n", name);
      goto fail;
    }

  switch (name[0])
    {
    case 'h':
      d = get_hd_device (num);
      break;
    default:
      goto fail;
    }

  if (!d)
    goto fail;

  /*
   * Subsystems may call open on the same device recursively - but U-Boot
   * does not deal with this. So simply keep track of number of calls and
   * return success if already open.
   */
  if (d->opencount > 0)
    {
      grub_dprintf ("ubootdisk", "(%s) already open\n", disk->name);
      d->opencount++;
      retval = 0;
    }
  else
    {
      retval = grub_uboot_dev_open (d->dev);
      if (retval != 0)
	goto fail;
      d->opencount = 1;
    }

  grub_dprintf ("ubootdisk", "cookie: 0x%08x\n", (grub_addr_t) d->cookie);
  disk->id = (grub_addr_t) d->cookie;

  devinfo = d->dev;

  d->block_size = devinfo->di_stor.block_size;
  if (d->block_size == 0)
    return grub_error (GRUB_ERR_IO, "no block size");

  for (disk->log_sector_size = 0;
       (1U << disk->log_sector_size) < d->block_size;
       disk->log_sector_size++);

  grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n",
		disk->name, d->block_size, disk->log_sector_size);

  if (devinfo->di_stor.block_count)
    disk->total_sectors = devinfo->di_stor.block_count;
  else
    disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;

  disk->data = d;

  return GRUB_ERR_NONE;

fail:
  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device");
}
Beispiel #4
0
static grub_err_t
grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
		    int argc, char *argv[])
{
  grub_file_t file = 0;
  grub_err_t err;

  grub_loader_unset ();

  highest_load = 0;

#ifndef GRUB_USE_MULTIBOOT2
  grub_multiboot_quirks = GRUB_MULTIBOOT_QUIRKS_NONE;
  int option_found = 0;

  do
    {
      option_found = 0;
      if (argc != 0 && grub_strcmp (argv[0], "--quirk-bad-kludge") == 0)
	{
	  argc--;
	  argv++;
	  option_found = 1;
	  grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE;
	}

      if (argc != 0 && grub_strcmp (argv[0], "--quirk-modules-after-kernel") == 0)
	{
	  argc--;
	  argv++;
	  option_found = 1;
	  grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL;
	}
    } while (option_found);
#endif

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

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

  grub_dl_ref (my_mod);

  /* Skip filename.  */
  grub_multiboot_init_mbi (argc - 1, argv + 1);

  grub_relocator_unload (grub_multiboot_relocator);
  grub_multiboot_relocator = grub_relocator_new ();

  if (!grub_multiboot_relocator)
    goto fail;

  err = grub_multiboot_load (file, argv[0]);
  if (err)
    goto fail;

  grub_multiboot_set_bootdev ();

  grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);

 fail:
  if (file)
    grub_file_close (file);

  if (grub_errno != GRUB_ERR_NONE)
    {
      grub_relocator_unload (grub_multiboot_relocator);
      grub_multiboot_relocator = NULL;
      grub_dl_unref (my_mod);
    }

  return grub_errno;
}
Beispiel #5
0
static grub_err_t
pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
			grub_embed_type_t embed_type,
			grub_disk_addr_t **sectors)
{
  grub_disk_addr_t end = ~0ULL;
  struct grub_msdos_partition_mbr mbr;
  int labeln = 0;
  /* Any value different than `p.offset' will satisfy the check during
     first loop.  */
  grub_disk_addr_t lastaddr = 1;
  grub_disk_addr_t ext_offset = 0;
  grub_disk_addr_t offset = 0;

  if (embed_type != GRUB_EMBED_PCBIOS)
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		       "PC-style partitions curently support "
		       "only PC-BIOS embedding");

  if (disk->partition)
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
		       "Embedding on MSDOS subpartition isn't supported");

  while (1)
    {
      int i;
      struct grub_msdos_partition_entry *e;
      grub_err_t err;

      /* Read the MBR.  */
      err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr);
      if (err)
	return err;

      /* This is our loop-detection algorithm. It works the following way:
	 It saves last position which was a power of two. Then it compares the
	 saved value with a current one. This way it's guaranteed that the loop
	 will be broken by at most third walk.
       */
      if (labeln && lastaddr == offset)
	return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected");

      labeln++;
      if ((labeln & (labeln - 1)) == 0)
	lastaddr = offset;

      /* Check if it is valid.  */
      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
	return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");

      for (i = 0; i < 4; i++)
	if (mbr.entries[i].flag & 0x7f)
	  return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");

      /* Analyze DOS partitions.  */
      for (i = 0; i < 4; i++)
	{
	  e = mbr.entries + i;

	  if (!grub_msdos_partition_is_empty (e->type)
	      && end > offset + grub_le_to_cpu32 (e->start))
	    end = offset + grub_le_to_cpu32 (e->start);

	  /* If this is a GPT partition, this MBR is just a dummy.  */
	  if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
	    return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
	}

      /* Find an extended partition.  */
      for (i = 0; i < 4; i++)
	{
	  e = mbr.entries + i;

	  if (grub_msdos_partition_is_extended (e->type))
	    {
	      offset = ext_offset + grub_le_to_cpu32 (e->start);
	      if (! ext_offset)
		ext_offset = offset;

	      break;
	    }
	}

      /* If no extended partition, the end.  */
      if (i == 4)
	break;
    }

  if (end >= *nsectors + 2)
    {
      unsigned i;
      *nsectors = end - 2;
      *sectors = grub_malloc (*nsectors * sizeof (**sectors));
      if (!*sectors)
	return grub_errno;
      for (i = 0; i < *nsectors; i++)
	(*sectors)[i] = 1 + i;
      return GRUB_ERR_NONE;
    }

  if (end <= 1)
    return grub_error (GRUB_ERR_FILE_NOT_FOUND,
		       "This msdos-style partition label has no "
		       "post-MBR gap; embedding won't be possible!");

  if (*nsectors > 62)
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
		       "Your core.img is unusually large.  "
		       "It won't fit in the embedding area.");

  return grub_error (GRUB_ERR_OUT_OF_RANGE,
		     "Your embedding area is unusually small.  "
		     "core.img won't fit in it.");
}
static grub_err_t
grub_cmd_pxechain (grub_command_t cmd __attribute__ ((unused)),
		int argc, char *argv[])
{
  grub_file_t file = 0;
  grub_err_t err;
  void *image;
  grub_size_t imagesize;
  char *fname;

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

  grub_dl_ref (my_mod);

  rel = grub_relocator_new ();
  if (!rel)
    goto fail;

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

  if (file->device->net && file->device->net->name)
    fname = file->device->net->name;
  else
    {
      fname = argv[0];
      if (fname[0] == '(')
	{
	  fname = grub_strchr (fname, ')');
	  if (fname)
	    fname++;
	  else
	    fname = argv[0];
	}
    }

  grub_memset (boot_file, 0, sizeof (boot_file));
  grub_strncpy (boot_file, fname, sizeof (boot_file));

  grub_memset (server_name, 0, sizeof (server_name));
  if (file->device->net && file->device->net->server)
    grub_strncpy (server_name, file->device->net->server, sizeof (server_name));

  edx = grub_get_root_biosnumber ();

  imagesize = grub_file_size (file);
  {
    grub_relocator_chunk_t ch;
    err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7c00, imagesize);
    if (err)
      goto fail;
    image = get_virtual_current_address (ch);
  }

  if (grub_file_read (file, image, imagesize) != (grub_ssize_t) imagesize)
    goto fail;
 
  grub_loader_set (grub_pxechain_boot, grub_pxechain_unload,
		   GRUB_LOADER_FLAG_NORETURN | GRUB_LOADER_FLAG_PXE_NOT_UNLOAD);
  return GRUB_ERR_NONE;

 fail:

  if (file)
    grub_file_close (file);

  grub_pxechain_unload ();

  return grub_errno;
}
Beispiel #7
0
/* Relocate symbols.  */
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
{
  Elf_Ehdr *e = ehdr;
  Elf_Shdr *s;
  Elf_Word entsize;
  unsigned i;
  grub_uint64_t *gp, *gpptr;
  struct grub_ia64_trampoline *tr;

  gp = (grub_uint64_t *) mod->base;
  gpptr = (grub_uint64_t *) mod->got;
  tr = mod->tramp;

  /* Find a symbol table.  */
  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
       i < e->e_shnum;
       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
    if (s->sh_type == SHT_SYMTAB)
      break;

  if (i == e->e_shnum)
    return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table"));

  entsize = s->sh_entsize;

  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
       i < e->e_shnum;
       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
    if (s->sh_type == SHT_RELA)
      {
	grub_dl_segment_t seg;

	/* Find the target segment.  */
	for (seg = mod->segment; seg; seg = seg->next)
	  if (seg->section == s->sh_info)
	    break;

	if (seg)
	  {
	    Elf_Rela *rel, *max;

	    for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
		   max = rel + s->sh_size / s->sh_entsize;
		 rel < max;
		 rel++)
	      {
		grub_addr_t addr;
		Elf_Sym *sym;
		grub_uint64_t value;

		if (seg->size < (rel->r_offset & ~3))
		  return grub_error (GRUB_ERR_BAD_MODULE,
				     "reloc offset is out of the segment");

		addr = (grub_addr_t) seg->addr + rel->r_offset;
		sym = (Elf_Sym *) ((char *) mod->symtab
				     + entsize * ELF_R_SYM (rel->r_info));

		/* On the PPC the value does not have an explicit
		   addend, add it.  */
		value = sym->st_value + rel->r_addend;

		switch (ELF_R_TYPE (rel->r_info))
		  {
		  case R_IA64_PCREL21B:
		    {
		      grub_uint64_t noff;
		      grub_ia64_make_trampoline (tr, value);
		      noff = ((char *) tr - (char *) (addr & ~3)) >> 4;
		      tr = (struct grub_ia64_trampoline *) ((char *) tr + GRUB_IA64_DL_TRAMP_SIZE);
		      if (noff & ~MASK19)
			return grub_error (GRUB_ERR_BAD_OS,
					   "trampoline offset too big (%lx)", noff);
		      grub_ia64_add_value_to_slot_20b (addr, noff);
		    }
		    break;
		  case R_IA64_SEGREL64LSB:
		    *(grub_uint64_t *) addr += value - (grub_addr_t) seg->addr;
		    break;
		  case R_IA64_FPTR64LSB:
		  case R_IA64_DIR64LSB:
		    *(grub_uint64_t *) addr += value;
		    break;
		  case R_IA64_PCREL64LSB:
		    *(grub_uint64_t *) addr += value - addr;
		    break;
		  case R_IA64_GPREL22:
		    grub_ia64_add_value_to_slot_21 (addr, value - (grub_addr_t) gp);
		    break;

		  case R_IA64_LTOFF22X:
		  case R_IA64_LTOFF22:
		    if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
		      value = *(grub_uint64_t *) sym->st_value + rel->r_addend;
		  case R_IA64_LTOFF_FPTR22:
		    *gpptr = value;
		    grub_ia64_add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp);
		    gpptr++;
		    break;

		    /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV.  */
		  case R_IA64_LDXMOV:
		    break;
		  default:
		    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
				       N_("relocation 0x%x is not implemented yet"),
				       ELF_R_TYPE (rel->r_info));
		  }
	      }
	  }
      }
static grub_err_t
parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
		 grub_off_t off, grub_size_t sz)
{
  char *buf;
  char *ptr;
  int has_paddr = 0;
  if (grub_file_seek (elf->file, off) == (grub_off_t) -1)
    return grub_errno;
  buf = grub_malloc (sz);
  if (!buf)
    return grub_errno;

  if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz)
    {
      if (grub_errno)
	return grub_errno;
      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
			 elf->file->name);
    }
  xi->has_xen_guest = 1;
  for (ptr = buf; ptr && ptr - buf < (grub_ssize_t) sz;
       ptr = grub_strchr (ptr, ','), (ptr ? ptr++ : 0))
    {
      if (grub_strncmp (ptr, "PAE=no,", sizeof ("PAE=no,") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386;
	  continue;
	}

      if (grub_strncmp (ptr, "PAE=yes,", sizeof ("PAE=yes,") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386_PAE;
	  continue;
	}

      if (grub_strncmp (ptr, "PAE=yes[extended-cr3],",
			sizeof ("PAE=yes[extended-cr3],") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386_PAE;
	  xi->extended_cr3 = 1;
	  continue;
	}

      if (grub_strncmp (ptr, "PAE=bimodal,", sizeof ("PAE=bimodal,") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE;
	  continue;
	}

      if (grub_strncmp (ptr, "PAE=bimodal[extended-cr3],",
			sizeof ("PAE=bimodal[extended-cr3],") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE;
	  xi->extended_cr3 = 1;
	  continue;
	}

      if (grub_strncmp (ptr, "PAE=yes,bimodal,", sizeof ("PAE=yes,bimodal,") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE;
	  continue;
	}

      if (grub_strncmp (ptr, "PAE=yes[extended-cr3],bimodal,",
			sizeof ("PAE=yes[extended-cr3],bimodal,") - 1) == 0)
	{
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    continue;
	  xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE;
	  xi->extended_cr3 = 1;
	  continue;
	}

      if (grub_strncmp (ptr, "VIRT_BASE=", sizeof ("VIRT_BASE=") - 1) == 0)
	{
	  xi->virt_base = grub_strtoull (ptr + sizeof ("VIRT_BASE=") - 1, &ptr, 16);
	  if (grub_errno)
	    return grub_errno;
	  continue;
	}
      if (grub_strncmp (ptr, "VIRT_ENTRY=", sizeof ("VIRT_ENTRY=") - 1) == 0)
	{
	  xi->entry_point = grub_strtoull (ptr + sizeof ("VIRT_ENTRY=") - 1, &ptr, 16);
	  if (grub_errno)
	    return grub_errno;
	  continue;
	}
      if (grub_strncmp (ptr, "HYPERCALL_PAGE=", sizeof ("HYPERCALL_PAGE=") - 1) == 0)
	{
	  xi->hypercall_page = grub_strtoull (ptr + sizeof ("HYPERCALL_PAGE=") - 1, &ptr, 16);
	  xi->has_hypercall_page = 1;
	  if (grub_errno)
	    return grub_errno;
	  continue;
	}
      if (grub_strncmp (ptr, "ELF_PADDR_OFFSET=", sizeof ("ELF_PADDR_OFFSET=") - 1) == 0)
	{
	  xi->paddr_offset = grub_strtoull (ptr + sizeof ("ELF_PADDR_OFFSET=") - 1, &ptr, 16);
	  has_paddr = 1;
	  if (grub_errno)
	    return grub_errno;
	  continue;
	}
    }
  if (xi->has_hypercall_page)
    xi->hypercall_page = (xi->hypercall_page << 12) + xi->virt_base;
  if (!has_paddr)
    xi->paddr_offset = xi->virt_base;
  return GRUB_ERR_NONE;
}
Beispiel #9
0
/* Parse <width>x<height>[x<depth>]*/
static grub_err_t
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
{
  const char *value;
  const char *param = current_mode;

  *width = *height = *depth = -1;

  if (grub_strcmp (param, "auto") == 0)
    {
      *width = *height = 0;
      return GRUB_ERR_NONE;
    }

  /* Find width value.  */
  value = param;
  param = grub_strchr(param, 'x');
  if (param == NULL)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
		       "Invalid mode: %s\n",
		       current_mode);

  param++;
  
  *width = grub_strtoul (value, 0, 0);
  if (grub_errno != GRUB_ERR_NONE)
      return grub_error (GRUB_ERR_BAD_ARGUMENT,
			 "Invalid mode: %s\n",
			 current_mode);
  
  /* Find height value.  */
  value = param;
  param = grub_strchr(param, 'x');
  if (param == NULL)
    {
      *height = grub_strtoul (value, 0, 0);
      if (grub_errno != GRUB_ERR_NONE)
	return grub_error (GRUB_ERR_BAD_ARGUMENT,
			   "Invalid mode: %s\n",
			   current_mode);
    }
  else
    {
      /* We have optional color depth value.  */
      param++;
      
      *height = grub_strtoul (value, 0, 0);
      if (grub_errno != GRUB_ERR_NONE)
	return grub_error (GRUB_ERR_BAD_ARGUMENT,
			   "Invalid mode: %s\n",
			   current_mode);
      
      /* Convert color depth value.  */
      value = param;
      *depth = grub_strtoul (value, 0, 0);
      if (grub_errno != GRUB_ERR_NONE)
	return grub_error (GRUB_ERR_BAD_ARGUMENT,
			   "Invalid mode: %s\n",
			   current_mode);
    }
  return GRUB_ERR_NONE;
}
Beispiel #10
0
static void
init_dynamic_block (grub_gzio_t gzio)
{
    int i;			/* temporary variables */
    unsigned j;
    unsigned l;			/* last length */
    unsigned m;			/* mask for bit lengths table */
    unsigned n;			/* number of lengths to get */
    unsigned nb;			/* number of bit length codes */
    unsigned nl;			/* number of literal/length codes */
    unsigned nd;			/* number of distance codes */
    unsigned ll[286 + 30];	/* literal/length and distance code lengths */
    register ulg b;		/* bit buffer */
    register unsigned k;		/* number of bits in bit buffer */

    /* make local bit buffer */
    b = gzio->bb;
    k = gzio->bk;

    /* read in table lengths */
    NEEDBITS (5);
    nl = 257 + ((unsigned) b & 0x1f);	/* number of literal/length codes */
    DUMPBITS (5);
    NEEDBITS (5);
    nd = 1 + ((unsigned) b & 0x1f);	/* number of distance codes */
    DUMPBITS (5);
    NEEDBITS (4);
    nb = 4 + ((unsigned) b & 0xf);	/* number of bit length codes */
    DUMPBITS (4);
    if (nl > 286 || nd > 30)
    {
        grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too much data");
        return;
    }

    /* read in bit-length-code lengths */
    for (j = 0; j < nb; j++)
    {
        NEEDBITS (3);
        ll[bitorder[j]] = (unsigned) b & 7;
        DUMPBITS (3);
    }
    for (; j < 19; j++)
        ll[bitorder[j]] = 0;

    /* build decoding table for trees--single level, 7 bit lookup */
    gzio->bl = 7;
    if (huft_build (ll, 19, 19, NULL, NULL, &gzio->tl, &gzio->bl) != 0)
    {
        grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
                    "failed in building a Huffman code table");
        return;
    }

    /* read in literal and distance code lengths */
    n = nl + nd;
    m = mask_bits[gzio->bl];
    i = l = 0;
    while ((unsigned) i < n)
    {
        NEEDBITS ((unsigned) gzio->bl);
        j = (gzio->td = gzio->tl + ((unsigned) b & m))->b;
        DUMPBITS (j);
        j = gzio->td->v.n;
        if (j < 16)		/* length of code in bits (0..15) */
            ll[i++] = l = j;	/* save last length in l */
        else if (j == 16)		/* repeat last length 3 to 6 times */
        {
            NEEDBITS (2);
            j = 3 + ((unsigned) b & 3);
            DUMPBITS (2);
            if ((unsigned) i + j > n)
            {
                grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
                return;
            }
            while (j--)
                ll[i++] = l;
        }
        else if (j == 17)		/* 3 to 10 zero length codes */
        {
            NEEDBITS (3);
            j = 3 + ((unsigned) b & 7);
            DUMPBITS (3);
            if ((unsigned) i + j > n)
            {
                grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
                return;
            }
            while (j--)
                ll[i++] = 0;
            l = 0;
        }
        else
            /* j == 18: 11 to 138 zero length codes */
        {
            NEEDBITS (7);
            j = 11 + ((unsigned) b & 0x7f);
            DUMPBITS (7);
            if ((unsigned) i + j > n)
            {
                grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
                return;
            }
            while (j--)
                ll[i++] = 0;
            l = 0;
        }
    }

    /* free decoding table for trees */
    huft_free (gzio->tl);
    gzio->td = 0;
    gzio->tl = 0;

    /* restore the global bit buffer */
    gzio->bb = b;
    gzio->bk = k;

    /* build the decoding tables for literal/length and distance codes */
    gzio->bl = lbits;
    if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
    {
        grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
                    "failed in building a Huffman code table");
        return;
    }
    gzio->bd = dbits;
    if (huft_build (ll + nl, nd, 0, cpdist, cpdext, &gzio->td, &gzio->bd) != 0)
    {
        huft_free (gzio->tl);
        gzio->tl = 0;
        grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
                    "failed in building a Huffman code table");
        return;
    }

    /* indicate we're now working on a block */
    gzio->code_state = 0;
    gzio->block_len++;
}
static grub_err_t
parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
	    grub_off_t off, grub_size_t sz)
{
  grub_uint32_t *buf;
  grub_uint32_t *ptr;
  if (grub_file_seek (elf->file, off) == (grub_off_t) -1)
    return grub_errno;
  buf = grub_malloc (sz);
  if (!buf)
    return grub_errno;

  if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz)
    {
      if (grub_errno)
	return grub_errno;
      return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
			 elf->file->name);
    }
  for (ptr = buf; ptr - buf < (grub_ssize_t) (sz / sizeof (grub_uint32_t));)
    {
      Elf_Nhdr *nh = (Elf_Nhdr *) ptr;
      char *name;
      grub_uint32_t *desc;
      grub_uint32_t namesz, descsz;
      ptr += sizeof (*nh) / sizeof (grub_uint32_t);
      name = (char *) ptr;
      namesz = grub_le_to_cpu32 (nh->n_namesz);
      descsz = grub_le_to_cpu32 (nh->n_descsz);
      ptr += (namesz + 3) / 4;
      desc = ptr;
      ptr += (grub_le_to_cpu32 (nh->n_descsz) + 3) / 4;
      if ((namesz < 3) || grub_memcmp (name, "Xen", namesz == 3 ? 3 : 4) != 0)
	continue;
      xi->has_note = 1;
      switch (nh->n_type)
	{
	case 1:
	  xi->entry_point = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
	  break;
	case 2:
	  xi->hypercall_page = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
	  xi->has_hypercall_page = 1;
	  break;
	case 3:
	  xi->virt_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
	  break;
	case 4:
	  xi->paddr_offset = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
	  break;
	case 5:
	  grub_dprintf ("xen", "xenversion = `%s'\n", (char *) desc);
	  break;
	case 6:
	  grub_dprintf ("xen", "name = `%s'\n", (char *) desc);
	  break;
	case 7:
	  grub_dprintf ("xen", "version = `%s'\n", (char *) desc);
	  break;
	case 8:
	  if (descsz < 7
	      || grub_memcmp (desc, "generic", descsz == 7 ? 7 : 8) != 0)
	    return grub_error (GRUB_ERR_BAD_OS, "invalid loader");
	  break;
	  /* PAE */
	case 9:
	  grub_dprintf ("xen", "pae = `%s', %d, %d\n", (char *) desc,
			xi->arch, descsz);
	  if (xi->arch != GRUB_XEN_FILE_I386
	      && xi->arch != GRUB_XEN_FILE_I386_PAE
	      && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE)
	    break;
	  if (descsz >= 3 && grub_memcmp (desc, "yes",
					  descsz == 3 ? 3 : 4) == 0)
	    {
	      xi->extended_cr3 = 1;
	      xi->arch = GRUB_XEN_FILE_I386_PAE;
	    }
	  if (descsz >= 7 && grub_memcmp (desc, "bimodal",
					  descsz == 7 ? 7 : 8) == 0)
	    {
	      xi->extended_cr3 = 1;
	      xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE;
	    }
	  if (descsz >= 11 && grub_memcmp (desc, "yes,bimodal",
					   descsz == 11 ? 11 : 12) == 0)
	    {
	      xi->extended_cr3 = 1;
	      xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE;
	    }
	  if (descsz >= 2 && grub_memcmp (desc, "no",
					  descsz == 2 ? 2 : 3) == 0)
	    xi->arch = GRUB_XEN_FILE_I386;
	  break;
	default:
	  grub_dprintf ("xen", "unknown note type %d\n", nh->n_type);
	  break;
	}
    }
  return GRUB_ERR_NONE;
}
Beispiel #12
0
static int
inflate_codes_in_window (grub_gzio_t gzio)
{
    register unsigned e;		/* table entry flag/number of extra bits */
    unsigned n, d;		/* length and index for copy */
    unsigned w;			/* current window position */
    struct huft *t;		/* pointer to table entry */
    unsigned ml, md;		/* masks for bl and bd bits */
    register ulg b;		/* bit buffer */
    register unsigned k;		/* number of bits in bit buffer */

    /* make local copies of globals */
    d = gzio->inflate_d;
    n = gzio->inflate_n;
    b = gzio->bb;			/* initialize bit buffer */
    k = gzio->bk;
    w = gzio->wp;			/* initialize window position */

    /* inflate the coded data */
    ml = mask_bits[gzio->bl];		/* precompute masks for speed */
    md = mask_bits[gzio->bd];
    for (;;)			/* do until end of block */
    {
        if (! gzio->code_state)
        {
            NEEDBITS ((unsigned) gzio->bl);
            if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16)
                do
                {
                    if (e == 99)
                    {
                        grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
                                    "an unused code found");
                        return 1;
                    }
                    DUMPBITS (t->b);
                    e -= 16;
                    NEEDBITS (e);
                }
                while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
            DUMPBITS (t->b);

            if (e == 16)		/* then it's a literal */
            {
                gzio->slide[w++] = (uch) t->v.n;
                if (w == WSIZE)
                    break;
            }
            else
                /* it's an EOB or a length */
            {
                /* exit if end of block */
                if (e == 15)
                {
                    gzio->block_len = 0;
                    break;
                }

                /* get length of block to copy */
                NEEDBITS (e);
                n = t->v.n + ((unsigned) b & mask_bits[e]);
                DUMPBITS (e);

                /* decode distance of block to copy */
                NEEDBITS ((unsigned) gzio->bd);
                if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16)
                    do
                    {
                        if (e == 99)
                        {
                            grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
                                        "an unused code found");
                            return 1;
                        }
                        DUMPBITS (t->b);
                        e -= 16;
                        NEEDBITS (e);
                    }
                    while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
                            > 16);
                DUMPBITS (t->b);
                NEEDBITS (e);
                d = w - t->v.n - ((unsigned) b & mask_bits[e]);
                DUMPBITS (e);
                gzio->code_state++;
            }
        }

        if (gzio->code_state)
        {
            /* do the copy */
            do
            {
                n -= (e = (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n
                          : e);

                if (w - d >= e)
                {
                    grub_memmove (gzio->slide + w, gzio->slide + d, e);
                    w += e;
                    d += e;
                }
                else
                    /* purposefully use the overlap for extra copies here!! */
                {
                    while (e--)
                        gzio->slide[w++] = gzio->slide[d++];
                }

                if (w == WSIZE)
                    break;
            }
            while (n);

            if (! n)
                gzio->code_state--;

            /* did we break from the loop too soon? */
            if (w == WSIZE)
                break;
        }
    }

    /* restore the globals from the locals */
    gzio->inflate_d = d;
    gzio->inflate_n = n;
    gzio->wp = w;			/* restore global window pointer */
    gzio->bb = b;			/* restore global bit buffer */
    gzio->bk = k;

    return ! gzio->block_len;
}
Beispiel #13
0
static void
inflate_window (grub_gzio_t gzio)
{
    /* initialize window */
    gzio->wp = 0;

    /*
     *  Main decompression loop.
     */

    while (gzio->wp < WSIZE && grub_errno == GRUB_ERR_NONE)
    {
        if (! gzio->block_len)
        {
            if (gzio->last_block)
                break;

            get_new_block (gzio);
        }

        if (gzio->block_type > INFLATE_DYNAMIC)
            grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
                        "unknown block type %d", gzio->block_type);

        if (grub_errno != GRUB_ERR_NONE)
            return;

        /*
         *  Expand stored block here.
         */
        if (gzio->block_type == INFLATE_STORED)
        {
            int w = gzio->wp;

            /*
             *  This is basically a glorified pass-through
             */

            while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE)
            {
                gzio->slide[w++] = get_byte (gzio);
                gzio->block_len--;
            }

            gzio->wp = w;

            continue;
        }

        /*
         *  Expand other kind of block.
         */

        if (inflate_codes_in_window (gzio))
        {
            huft_free (gzio->tl);
            huft_free (gzio->td);
            gzio->tl = 0;
            gzio->td = 0;
        }
    }

    gzio->saved_offset += WSIZE;

    /* XXX do CRC calculation here! */
}
Beispiel #14
0
static grub_err_t
grub_ofdisk_open (const char *name, grub_disk_t disk)
{
  grub_ieee1275_phandle_t dev;
  char *devpath;
  /* XXX: This should be large enough for any possible case.  */
  char prop[64];
  grub_ssize_t actual;
  grub_uint32_t block_size = 0;
  grub_err_t err;

  if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
			 "not IEEE1275 device");
  devpath = compute_dev_path (name + sizeof ("ieee1275/") - 1);
  if (! devpath)
    return grub_errno;

  grub_dprintf ("disk", "Opening `%s'.\n", devpath);

  if (grub_ieee1275_finddevice (devpath, &dev))
    {
      grub_free (devpath);
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
			 "can't read device properties");
    }

  if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
				  &actual))
    {
      grub_free (devpath);
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
    }

  if (grub_strcmp (prop, "block"))
    {
      grub_free (devpath);
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
    }

  /* XXX: There is no property to read the number of blocks.  There
     should be a property `#blocks', but it is not there.  Perhaps it
     is possible to use seek for this.  */
  disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;

  {
    struct ofdisk_hash_ent *op;
    op = ofdisk_hash_find (devpath);
    if (!op)
      op = ofdisk_hash_add (devpath, NULL);
    if (!op)
      {
        grub_free (devpath);
        return grub_errno;
      }
    disk->id = (unsigned long) op;
    disk->data = op->open_path;

    err = grub_ofdisk_get_block_size (devpath, &block_size, op);
    if (err)
      {
        grub_free (devpath);
        return err;
      }
    if (block_size != 0)
      {
	for (disk->log_sector_size = 0;
	     (1U << disk->log_sector_size) < block_size;
	     disk->log_sector_size++);
      }
    else
      disk->log_sector_size = 9;
  }

  grub_free (devpath);
  return 0;
}
char *
grub_legacy_parse (const char *buf, char **entryname, char **suffix)
{
  const char *ptr;
  const char *cmdname;
  unsigned i, cmdnum;
  char *args[ARRAY_SIZE (legacy_commands[0].argt)];

  *suffix = NULL;

  for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
  if (!*ptr || *ptr == '#')
    {
      char *ret;
      int len = grub_strlen (buf);
      ret = grub_malloc (len + 2);
      grub_memcpy (ret, buf, len);
      if (len && ret[len - 1] == '\n')
	ret[len] = 0;
      else
	{
	  ret[len] = '\n';
	  ret[len + 1] = 0;
	}
      return ret;
    }

  cmdname = ptr;
  for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++);

  for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++)
    if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0
	&& legacy_commands[cmdnum].name[ptr - cmdname] == 0
	&& (!(*entryname != NULL && (legacy_commands[cmdnum].flags
				     & FLAG_NO_MENUENTRY)))
	&& (!(*entryname == NULL && (legacy_commands[cmdnum].flags
				     & FLAG_MENUENTRY_ONLY))))
      break;
  if (cmdnum == ARRAY_SIZE (legacy_commands))
    return grub_xasprintf ("# Unsupported legacy command: %s\n", buf);

  for (; grub_isspace (*ptr) || *ptr == '='; ptr++);

  if (legacy_commands[cmdnum].flags & FLAG_TITLE)
    {
      const char *ptr2;
      ptr2 = ptr + grub_strlen (ptr);
      while (ptr2 > ptr && grub_isspace (*(ptr2 - 1)))
	ptr2--;
      *entryname = grub_strndup (ptr, ptr2 - ptr);
      return NULL;
    }

  if (legacy_commands[cmdnum].flags & FLAG_TERMINAL)
    {
      int dumb = 0, lines = 24;
#ifdef TODO
      int no_echo = 0, no_edit = 0;
#endif
      int hercules = 0;
      int console = 0, serial = 0, graphics = 0;
      /* Big enough for any possible resulting command. */
      char outbuf[512] = "";
      char *outptr;
      while (*ptr)
	{
	  /*	  "[--timeout=SECS] [--silent]"
		  " [console] [serial] [hercules]"*/
	  if (grub_memcmp (ptr, "--dumb", sizeof ("--dumb") - 1) == 0)
	    dumb = 1;
#ifdef TODO
	  if (grub_memcmp (ptr, "--no-echo", sizeof ("--no-echo") - 1) == 0)
	    no_echo = 1;

	  if (grub_memcmp (ptr, "--no-edit", sizeof ("--no-edit") - 1) == 0)
	    no_edit = 1;
#endif
	  if (grub_memcmp (ptr, "--lines=", sizeof ("--lines=") - 1) == 0)
	    {
	      lines = grub_strtoul (ptr + sizeof ("--lines=") - 1, 0, 0);
	      if (grub_errno)
		{
		  lines = 24;
		  grub_errno = GRUB_ERR_NONE;
		}
	    }

	  if (grub_memcmp (ptr, "console", sizeof ("console") - 1) == 0)
	    console = 1;

	  if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0)
	    serial = 1;
	  if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0)
	    hercules = 1;
	  if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0)
	    graphics = 1;
	  while (*ptr && !grub_isspace (*ptr))
	    ptr++;
	  while (*ptr && grub_isspace (*ptr))
	    ptr++;
	}

      if (!console && !serial && !hercules && !graphics)
	return grub_strdup ("terminal_input; terminal_output; terminfo\n");

      outptr = outbuf;

      if (graphics)
	outptr = grub_stpcpy (outptr, "insmod all_video; ");

      outptr = grub_stpcpy (outptr, "terminal_input ");
      if (serial)
	outptr = grub_stpcpy (outptr, "serial ");
      if (console || hercules || graphics)
	outptr = grub_stpcpy (outptr, "console ");
      outptr = grub_stpcpy (outptr, "; terminal_output ");
      if (serial)
	outptr = grub_stpcpy (outptr, "serial ");
      if (console)
	outptr = grub_stpcpy (outptr, "console ");
      if (hercules)
	outptr = grub_stpcpy (outptr, "mda_text ");
      if (graphics)
	outptr = grub_stpcpy (outptr, "gfxterm ");
      outptr = grub_stpcpy (outptr, "; ");
      *outptr = '\0';
      if (serial)
	{
	  grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr,
			 "terminfo serial -g 80x%d %s; ",
			 lines, dumb ? "dumb" : "vt100");
	  outptr += grub_strlen (outptr);
	}

      grub_strcpy (outptr, "\n");

      return grub_strdup (outbuf);
    }

  grub_memset (args, 0, sizeof (args));

  {
    int hold_arg = 0;
    const char *curarg = NULL; 
    for (i = 0; i < legacy_commands[cmdnum].argc; i++)
      {
 	grub_size_t curarglen;
	if (hold_arg)
	  {
	    ptr = curarg;
	    hold_arg = 0;
	  }
	for (; grub_isspace (*ptr); ptr++);
	curarg = ptr;
	if (!*curarg)
	  break;
	for (; *ptr && !grub_isspace (*ptr); ptr++);
	if (i != legacy_commands[cmdnum].argc - 1
	    || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST))
	  curarglen = ptr - curarg;
	else
	  {
	    curarglen = grub_strlen (curarg);
	    while (curarglen > 0 && grub_isspace (curarg[curarglen - 1]))
	      curarglen--;
	  }
	if (*ptr)
	  ptr++;
	switch (legacy_commands[cmdnum].argt[i])
	  {
	  case TYPE_FILE_NO_CONSUME:
	    hold_arg = 1;
	  case TYPE_PARTITION:
	  case TYPE_FILE:
	    args[i] = adjust_file (curarg, curarglen);
	    break;

	  case TYPE_REST_VERBATIM:
	    {
	      char *outptr, *outptr0;
	      int overhead = 3;
	      ptr = curarg;
	      while (*ptr)
		{
		  for (; *ptr && grub_isspace (*ptr); ptr++);
		  for (; *ptr && !grub_isspace (*ptr); ptr++)
		    if (*ptr == '\'')
		      overhead += 3;
		  if (*ptr)
		    ptr++;
		  overhead += 3;
		}
		
	      outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg));
	      if (!outptr0)
		return NULL;
	      ptr = curarg;
	      outptr = outptr0;
	      while (*ptr)
		{
		  for (; *ptr && grub_isspace (*ptr); ptr++);
		  if (outptr != outptr0)
		    *outptr++ = ' ';
		  *outptr++ = '\'';
		  for (; *ptr && !grub_isspace (*ptr); ptr++)
		    {
		      if (*ptr == '\'')
			{
			  *outptr++ = '\'';
			  *outptr++ = '\\';
			  *outptr++ = '\'';
			  *outptr++ = '\'';
			}
		      else
			*outptr++ = *ptr;
		    }
		  *outptr++ = '\'';
		  if (*ptr)
		    ptr++;
		}
	      *outptr++ = 0;
	    }
	    break;

	  case TYPE_VERBATIM:
	    args[i] = grub_legacy_escape (curarg, curarglen);
	    break;
	  case TYPE_WITH_CONFIGFILE_OPTION:
	  case TYPE_FORCE_OPTION:
	  case TYPE_NOAPM_OPTION:
	  case TYPE_TYPE_OR_NOMEM_OPTION:
	  case TYPE_OPTION:
	    if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen))
	      {
		args[i] = grub_strndup (curarg, curarglen);
		break;
	      }
	    args[i] = grub_strdup ("");
	    hold_arg = 1;
	    break;
	  case TYPE_INT:
	    {
	      const char *brk;
	      int base = 10;
	      brk = curarg;
	      if (brk[0] == '0' && brk[1] == 'x')
		{
		  base = 16;
		  brk += 2;
		}
	      else if (brk[0] == '0')
		base = 8;
	      for (; *brk && brk < curarg + curarglen; brk++)
		{
		  if (base == 8 &&  (*brk == '8' || *brk == '9'))
		    break;
		  if (grub_isdigit (*brk))
		    continue;
		  if (base != 16)
		    break;
		  if (!(*brk >= 'a' && *brk <= 'f')
		      && !(*brk >= 'A' && *brk <= 'F'))
		    break;
		}
	      if (brk == curarg)
		args[i] = grub_strdup ("0");
	      else
		args[i] = grub_strndup (curarg, brk - curarg);
	    }
	    break;
	  case TYPE_VBE_MODE:
	    {
	      unsigned mod;
	      struct grub_vesa_mode_table_entry *modedesc;

	      mod = grub_strtoul (curarg, 0, 0);
	      if (grub_errno)
		{
		  mod = 0;
		  grub_errno = GRUB_ERR_NONE;
		}
	      if (mod < GRUB_VESA_MODE_TABLE_START
		  || mod > GRUB_VESA_MODE_TABLE_END)
		{
		  args[i] = grub_strdup ("auto");
		  break;
		}
	      modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START];
	      if (!modedesc->width)
		{
		  args[i] = grub_strdup ("auto");
		  break;
		}
	      args[i] = grub_xasprintf ("%ux%ux%u",
					modedesc->width, modedesc->height,
					modedesc->depth);
	      break;
	    }
	  case TYPE_BOOL:
	    if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n')
	      args[i] = grub_strdup ("1");
	    else
	      args[i] = grub_strdup ("0");
	    break;
	  }
      }
  }

  while (legacy_commands[cmdnum].argc > 0
	 && args[legacy_commands[cmdnum].argc - 1] == NULL
	 && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE)
	 && args[legacy_commands[cmdnum + 1].argc] == NULL)
    cmdnum++;

  for (; i < legacy_commands[cmdnum].argc; i++)
    switch (legacy_commands[cmdnum].argt[i])
      {
      case TYPE_FILE_NO_CONSUME:
      case TYPE_PARTITION:
      case TYPE_FILE:
      case TYPE_REST_VERBATIM:
      case TYPE_VERBATIM:
      case TYPE_WITH_CONFIGFILE_OPTION:
      case TYPE_FORCE_OPTION:
      case TYPE_NOAPM_OPTION:
      case TYPE_TYPE_OR_NOMEM_OPTION:
      case TYPE_OPTION:	
	args[i] = grub_strdup ("");
	break;
      case TYPE_BOOL:
      case TYPE_INT:
	args[i] = grub_strdup ("0");
	break;
      case TYPE_VBE_MODE:    
	args[i] = grub_strdup ("auto");
	break;
      }

  if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT)
    {
      char *corig = args[legacy_commands[cmdnum].argc - 1];
      char *slash = grub_strchr (corig, '/');
      char *invert;
      grub_size_t len;

      len = grub_strlen (corig);
      if (!slash)
	{
	  grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid color specification `%s'"),
		      args[0]);
	  return NULL;
	}
      invert = grub_malloc (len + 1);
      if (!invert)
	return NULL;
      grub_memcpy (invert, slash + 1, len - (slash - corig) - 1);
      invert[len - (slash - args[0]) - 1] = '/'; 
      grub_memcpy (invert + len - (slash - corig), corig, slash - corig);
      invert[len] = 0;
      args[legacy_commands[cmdnum].argc] = invert;
    }

  if (legacy_commands[cmdnum].suffix)
    {
      *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix,
				args[legacy_commands[cmdnum].suffixarg]);
      if (*suffix)
	return NULL;
    }

  {
    char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1],
				args[2], args[3]);
    grub_free (args[0]);
    grub_free (args[1]);
    grub_free (args[2]);
    grub_free (args[3]);
    return ret;
  }
}
Beispiel #16
0
grub_err_t
grub_video_set_mode (const char *modestring,
		     unsigned int modemask,
		     unsigned int modevalue)
{
  char *tmp;
  char *next_mode;
  char *current_mode;
  char *modevar;

  modevalue &= modemask;

  /* Take copy of env.var. as we don't want to modify that.  */
  modevar = grub_strdup (modestring);

  /* Initialize next mode.  */
  next_mode = modevar;

  if (! modevar)
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
		       "couldn't allocate space for local modevar copy");

  if (grub_memcmp (next_mode, "keep", sizeof ("keep")) == 0
      || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
      || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
    {
      int suitable = 1;
      grub_err_t err;

      if (grub_video_adapter_active)
	{
	  struct grub_video_mode_info mode_info;
	  grub_memset (&mode_info, 0, sizeof (mode_info));
	  err = grub_video_get_info (&mode_info);
	  if (err)
	    {
	      suitable = 0;
	      grub_errno = GRUB_ERR_NONE;
	    }
	  if ((mode_info.mode_type & modemask) != modevalue)
	    suitable = 0;
	}
      else if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
	       && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
	suitable = 0;

      if (suitable)
	{
	  grub_free (modevar);
	  return GRUB_ERR_NONE;
	}
      next_mode += sizeof ("keep") - 1;
      if (! *next_mode)
	{
	  grub_free (modevar);

	  return grub_error (GRUB_ERR_BAD_ARGUMENT,
			     "no suitable mode found");
	}

      /* Skip separator. */
      next_mode++;
    }

  /* De-activate last set video adapter.  */
  if (grub_video_adapter_active)
    {
      /* Finalize adapter.  */
      grub_video_adapter_active->fini ();
      if (grub_errno != GRUB_ERR_NONE)
	grub_errno = GRUB_ERR_NONE;

      /* Mark active adapter as not set.  */
      grub_video_adapter_active = 0;
    }

  /* Loop until all modes has been tested out.  */
  while (next_mode != NULL)
    {
      int width = -1;
      int height = -1;
      int depth = -1;
      grub_err_t err;
      unsigned int flags = modevalue;
      unsigned int flagmask = modemask;

      /* Use last next_mode as current mode.  */
      tmp = next_mode;

      /* Save position of next mode and separate modes.  */
      for (; *next_mode; next_mode++)
	if (*next_mode == ',' || *next_mode == ';')
	  break;
      if (*next_mode)
	{
	  *next_mode = 0;
	  next_mode++;
	}
      else
	next_mode = 0;

      /* Skip whitespace.  */
      while (grub_isspace (*tmp))
	tmp++;

      /* Initialize token holders.  */
      current_mode = tmp;

      /* XXX: we assume that we're in pure text mode if
	 no video mode is initialized. Is it always true? */
      if (grub_strcmp (current_mode, "text") == 0)
	{
	  struct grub_video_mode_info mode_info;

	  grub_memset (&mode_info, 0, sizeof (mode_info));
	  if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0)
	      || ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0))
	    {
	      /* Valid mode found from adapter, and it has been activated.
		 Specify it as active adapter.  */
	      grub_video_adapter_active = NULL;

	      /* Free memory.  */
	      grub_free (modevar);

	      return GRUB_ERR_NONE;
	    }
	}

      err = parse_modespec (current_mode, &width, &height, &depth);
      if (err)
	{
	  /* Free memory before returning.  */
	  grub_free (modevar);

	  return err;
	}

      /* Try out video mode.  */

      /* If user requested specific depth check if this depth is supported.  */
      if (depth != -1 && (flagmask & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
	  &&
	  (((flags & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
	    != ((depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
		& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK))))
	continue;

      if (depth != -1)
	{
	  flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
	    & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
	  flagmask |= GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
	}

      /* Try to initialize requested mode.  Ignore any errors.  */
      grub_video_adapter_t p;

      /* Loop thru all possible video adapter trying to find requested mode.  */
      for (p = grub_video_adapter_list; p; p = p->next)
	{
	  struct grub_video_mode_info mode_info;

	  grub_memset (&mode_info, 0, sizeof (mode_info));

	  /* Try to initialize adapter, if it fails, skip to next adapter.  */
	  err = p->init ();
	  if (err != GRUB_ERR_NONE)
	    {
	      grub_errno = GRUB_ERR_NONE;
	      continue;
	    }

	  /* Try to initialize video mode.  */
	  err = p->setup (width, height, flags, flagmask);
	  if (err != GRUB_ERR_NONE)
	    {
	      p->fini ();
	      grub_errno = GRUB_ERR_NONE;
	      continue;
	    }

	  err = p->get_info (&mode_info);
	  if (err != GRUB_ERR_NONE)
	    {
	      p->fini ();
	      grub_errno = GRUB_ERR_NONE;
	      continue;
	    }

	  flags = mode_info.mode_type & ~GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
	  flags |= (mode_info.bpp << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
	    & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;

	  /* Check that mode is suitable for upper layer.  */
	  if ((flags & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
	      ? (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
		 && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
	      : ((flags & modemask) != modevalue))
	    {
	      p->fini ();
	      grub_errno = GRUB_ERR_NONE;
	      continue;
	    }

	  /* Valid mode found from adapter, and it has been activated.
	     Specify it as active adapter.  */
	  grub_video_adapter_active = p;

	  /* Free memory.  */
	  grub_free (modevar);

	  return GRUB_ERR_NONE;
	}

    }

  /* Free memory.  */
  grub_free (modevar);

  return grub_error (GRUB_ERR_BAD_ARGUMENT,
		     "no suitable mode found");
}
Beispiel #17
0
unsigned long long
grub_strtoull (const char *str, char **end, int base)
{
  unsigned long long num = 0;
  int found = 0;

  /* Skip white spaces.  */
  while (*str && grub_isspace (*str))
    str++;

  /* Guess the base, if not specified. The prefix `0x' means 16, and
     the prefix `0' means 8.  */
  if (str[0] == '0')
    {
      if (str[1] == 'x')
	{
	  if (base == 0 || base == 16)
	    {
	      base = 16;
	      str += 2;
	    }
	}
      else if (base == 0 && str[1] >= '0' && str[1] <= '7')
	base = 8;
    }

  if (base == 0)
    base = 10;

  while (*str)
    {
      unsigned long digit;

      digit = grub_tolower (*str) - '0';
      if (digit > 9)
	{
	  digit += '0' - 'a' + 10;
	  if (digit >= (unsigned long) base)
	    break;
	}

      found = 1;

      /* NUM * BASE + DIGIT > ~0ULL */
      if (num > grub_divmod64 (~0ULL - digit, base, 0))
	{
	  grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
	  return ~0ULL;
	}

      num = num * base + digit;
      str++;
    }

  if (! found)
    {
      grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
      return 0;
    }

  if (end)
    *end = (char *) str;

  return num;
}
Beispiel #18
0
static grub_err_t
grub_cmd_tr (grub_extcmd_context_t ctxt, int argc, char **args)
{
  char *var = 0;
  const char *input = 0;
  char *output = 0, *optr;
  const char *s1 = 0;
  const char *s2 = 0;
  const char *iptr;

  /* Select the defaults from options. */
  if (ctxt->state[0].set) {
    var = ctxt->state[0].arg;
    input = grub_env_get (var);
  }

  if (ctxt->state[1].set) {
    s1 = letters_lowercase;
    s2 = letters_uppercase;
  }

  if (ctxt->state[2].set) {
    s1 = letters_uppercase;
    s2 = letters_lowercase;
  }

  /* Check for arguments and update the defaults.  */
  if (argc == 1)
    input = args[0];

  else if (argc == 2) {
    s1 = args[0];
    s2 = args[1];

  } else if (argc == 3) {
    s1 = args[0];
    s2 = args[1];
    input = args[2];

  } else if (argc > 3)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters");

  if (argc <= 0 && (!s1 || !s2 || !input))
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing parameters");

  if (grub_strlen (s1) != grub_strlen (s2))
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "set sizes did not match");

  /* Translate input into output buffer.  */

  output = grub_malloc (grub_strlen (input) + 1);
  if (! output)
    return grub_errno;

  optr = output;
  for (iptr = input; *iptr; iptr++)
    {
      char *p = grub_strchr (s1, *iptr);
      if (p)
	*optr++ = s2[p - s1];
      else
	*optr++ = *iptr;
    }
  *optr = '\0';

  if (ctxt->state[0].set)
    grub_env_set (var, output);
  else
    grub_printf ("%s\n", output);

  grub_free (output);
  return GRUB_ERR_NONE;
}
Beispiel #19
0
static grub_err_t
grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)),
		int argc, char *argv[])
{
  grub_file_t file = 0;
  grub_err_t err;
  void *bs, *ntldr;
  grub_size_t ntldrsize;
  grub_device_t dev;

  if (argc == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");

  grub_dl_ref (my_mod);

  rel = grub_relocator_new ();
  if (!rel)
    goto fail;

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

  {
    grub_relocator_chunk_t ch;
    err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00,
					   GRUB_DISK_SECTOR_SIZE);
    if (err)
      goto fail;
    bs = get_virtual_current_address (ch);
  }

  edx = grub_get_root_biosnumber ();
  dev = grub_device_open (0);

  if (dev && dev->disk)
    {
      err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs);
      if (err)
	{
	  grub_device_close (dev);
	  goto fail;
	}
    }

  if (dev)
    grub_device_close (dev);

  ntldrsize = grub_file_size (file);
  {
    grub_relocator_chunk_t ch;
    err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4,
					   ntldrsize);
    if (err)
      goto fail;
    ntldr = get_virtual_current_address (ch);
  }

  if (grub_file_read (file, ntldr, ntldrsize)
      != (grub_ssize_t) ntldrsize)
    goto fail;
 
  grub_loader_set (grub_ntldr_boot, grub_ntldr_unload, 1);
  return GRUB_ERR_NONE;

 fail:

  if (file)
    grub_file_close (file);

  grub_ntldr_unload ();

  return grub_errno;
}
Beispiel #20
0
static grub_err_t
amiga_partition_map_iterate (grub_disk_t disk,
			     int (*hook) (grub_disk_t disk,
					  const grub_partition_t partition))
{
  struct grub_partition part;
  struct grub_amiga_rdsk rdsk;
  int partno = 0;
  int next = -1;
  unsigned pos;

  /* The RDSK block is one of the first 15 blocks.  */
  for (pos = 0; pos < 15; pos++)
    {
      /* Read the RDSK block which is a descriptor for the entire disk.  */
      if (grub_disk_read (disk, pos, 0, sizeof (rdsk), &rdsk))
	return grub_errno;

      if (grub_memcmp (rdsk.magic, GRUB_AMIGA_RDSK_MAGIC,
		       sizeof (rdsk.magic)) == 0)
	{
	  /* Found the first PART block.  */
	  next = grub_be_to_cpu32 (rdsk.partitionlst);
	  break;
	}
    }

  if (next == -1)
    return grub_error (GRUB_ERR_BAD_PART_TABLE,
		       "Amiga partition map not found");

  /* The end of the partition list is marked using "-1".  */
  while (next != -1)
    {
      struct grub_amiga_partition apart;

      /* Read the RDSK block which is a descriptor for the entire disk.  */
      if (grub_disk_read (disk, next, 0, sizeof (apart), &apart))
	return grub_errno;

      if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC,
		       sizeof (apart.magic)) == 0)

      /* Calculate the first block and the size of the partition.  */
      part.start = (grub_be_to_cpu32 (apart.lowcyl)
		    * grub_be_to_cpu32 (apart.heads)
		    * grub_be_to_cpu32 (apart.block_per_track));
      part.len = ((grub_be_to_cpu32 (apart.highcyl)
		   - grub_be_to_cpu32 (apart.lowcyl) + 1)
		  * grub_be_to_cpu32 (apart.heads)
		  * grub_be_to_cpu32 (apart.block_per_track));

      part.offset = (grub_off_t) next * 512;
      part.number = partno;
      part.index = 0;
      part.partmap = &grub_amiga_partition_map;

      if (hook (disk, &part))
	return grub_errno;

      next = grub_be_to_cpu32 (apart.next);
      partno++;
    }

  return 0;
}
Beispiel #21
0
static grub_err_t
apple_partition_map_iterate (grub_disk_t disk,
			     grub_partition_iterate_hook_t hook,
			     void *hook_data)
{
  struct grub_partition part;
  struct grub_apple_header aheader;
  struct grub_apple_part apart;
  int partno = 0, partnum = 0;
  unsigned pos;

  part.partmap = &grub_apple_partition_map;

  if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader))
    return grub_errno;

  if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
    {
      grub_dprintf ("partition",
		    "bad magic (found 0x%x; wanted 0x%x)\n",
		    grub_be_to_cpu16 (aheader.magic),
		    GRUB_APPLE_HEADER_MAGIC);
      goto fail;
    }

  pos = grub_be_to_cpu16 (aheader.blocksize);

  do
    {
      part.offset = pos / GRUB_DISK_SECTOR_SIZE;
      part.index = pos % GRUB_DISK_SECTOR_SIZE;

      if (grub_disk_read (disk, part.offset, part.index,
			  sizeof (struct grub_apple_part),  &apart))
	return grub_errno;

      if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC)
	{
	  grub_dprintf ("partition",
			"partition %d: bad magic (found 0x%x; wanted 0x%x)\n",
			partno, grub_be_to_cpu16 (apart.magic),
			GRUB_APPLE_PART_MAGIC);
	  break;
	}

      if (partnum == 0)
	partnum = grub_be_to_cpu32 (apart.partmap_size);

      part.start = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.first_phys_block)
		    * grub_be_to_cpu16 (aheader.blocksize))
	/ GRUB_DISK_SECTOR_SIZE;
      part.len = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.blockcnt)
		  * grub_be_to_cpu16 (aheader.blocksize))
	/ GRUB_DISK_SECTOR_SIZE;
      part.offset = pos;
      part.index = partno;
      part.number = partno;

      grub_dprintf ("partition",
		    "partition %d: name %s, type %s, start 0x%x, len 0x%x\n",
		    partno, apart.partname, apart.parttype,
		    grub_be_to_cpu32 (apart.first_phys_block),
		    grub_be_to_cpu32 (apart.blockcnt));

      if (hook (disk, &part, hook_data))
	return grub_errno;

      pos += grub_be_to_cpu16 (aheader.blocksize);
      partno++;
    }
  while (partno < partnum);

  if (partno != 0)
    return 0;

 fail:
  return grub_error (GRUB_ERR_BAD_PART_TABLE,
		     "Apple partition map not found");
}
Beispiel #22
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;
}
Beispiel #23
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);
  return GRUB_ERR_NONE;
}
Beispiel #24
0
static grub_err_t
fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
	       grub_uint32_t ptrdest, int fill_generic)
{
  grub_uint32_t vbe_mode;
  struct grub_vbe_mode_info_block *mode_info;
#if GRUB_MACHINE_HAS_VBE
  grub_vbe_status_t status;
  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
    
  status = grub_vbe_bios_get_controller_info (scratch);
  if (status != GRUB_VBE_STATUS_OK)
    return grub_error (GRUB_ERR_IO, "Can't get controller info.");
  
  mbi->vbe_control_info = ptrdest;
  grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block));
  ptrorig += sizeof (struct grub_vbe_info_block);
  ptrdest += sizeof (struct grub_vbe_info_block);
#else
  mbi->vbe_control_info = 0;
#endif

#if GRUB_MACHINE_HAS_VBE  
  status = grub_vbe_bios_get_mode (scratch);
  vbe_mode = *(grub_uint32_t *) scratch;
  if (status != GRUB_VBE_STATUS_OK)
    return grub_error (GRUB_ERR_IO, "can't get VBE mode");
#else
  vbe_mode = 3;
#endif
  mbi->vbe_mode = vbe_mode;

  mode_info = (struct grub_vbe_mode_info_block *) ptrorig;
  mbi->vbe_mode_info = ptrdest;
  /* get_mode_info isn't available for mode 3.  */
  if (vbe_mode == 3)
    {
      grub_memset (mode_info, 0, sizeof (struct grub_vbe_mode_info_block));
      mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
      mode_info->x_resolution = 80;
      mode_info->y_resolution = 25;
    }
  else
    {
#if GRUB_MACHINE_HAS_VBE  
      status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
      if (status != GRUB_VBE_STATUS_OK)
	return grub_error (GRUB_ERR_IO, "can't get mode info");
      grub_memcpy (mode_info, scratch,
		   sizeof (struct grub_vbe_mode_info_block));
#endif
    }
  ptrorig += sizeof (struct grub_vbe_mode_info_block);
  ptrdest += sizeof (struct grub_vbe_mode_info_block);

#if GRUB_MACHINE_HAS_VBE        
  grub_vbe_bios_get_pm_interface (&mbi->vbe_interface_seg,
				  &mbi->vbe_interface_off,
				  &mbi->vbe_interface_len);
#endif
  
  mbi->flags |= MULTIBOOT_INFO_VBE_INFO;

  if (fill_generic && mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
    {
      mbi->framebuffer_addr = 0xb8000;

      mbi->framebuffer_pitch = 2 * mode_info->x_resolution;	
      mbi->framebuffer_width = mode_info->x_resolution;
      mbi->framebuffer_height = mode_info->y_resolution;

      mbi->framebuffer_bpp = 16;

      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;

      mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
    }

  return GRUB_ERR_NONE;
}
Beispiel #25
0
grub_err_t
grub_partition_msdos_iterate (grub_disk_t disk,
			      int (*hook) (grub_disk_t disk,
					   const grub_partition_t partition))
{
  struct grub_partition p;
  struct grub_msdos_partition_mbr mbr;
  int labeln = 0;
  grub_disk_addr_t lastaddr;
  grub_disk_addr_t ext_offset;
  grub_disk_addr_t delta = 0;

  if (disk->partition && disk->partition->partmap == &grub_msdos_partition_map)
    {
      if (disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_LINUX_MINIX)
	delta = disk->partition->start;
      else
	return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
    }

  p.offset = 0;
  ext_offset = 0;
  p.number = -1;
  p.partmap = &grub_msdos_partition_map;

  /* Any value different than `p.offset' will satisfy the check during
     first loop.  */
  lastaddr = !p.offset;

  while (1)
    {
      int i;
      struct grub_msdos_partition_entry *e;

      /* Read the MBR.  */
      if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr))
	goto finish;

      /* This is our loop-detection algorithm. It works the following way:
	 It saves last position which was a power of two. Then it compares the
	 saved value with a current one. This way it's guaranteed that the loop
	 will be broken by at most third walk.
       */
      if (labeln && lastaddr == p.offset)
	return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected");

      labeln++;
      if ((labeln & (labeln - 1)) == 0)
	lastaddr = p.offset;

      /* Check if it is valid.  */
      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
	return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");

      for (i = 0; i < 4; i++)
	if (mbr.entries[i].flag & 0x7f)
	  return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");

      /* Analyze DOS partitions.  */
      for (p.index = 0; p.index < 4; p.index++)
	{
	  e = mbr.entries + p.index;

	  p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
	  p.len = grub_le_to_cpu32 (e->length);
	  p.msdostype = e->type;

	  grub_dprintf ("partition",
			"partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
			p.index, e->flag, e->type,
			(unsigned long long) p.start,
			(unsigned long long) p.len);

	  /* If this is a GPT partition, this MBR is just a dummy.  */
	  if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0)
	    return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");

	  /* If this partition is a normal one, call the hook.  */
	  if (! grub_msdos_partition_is_empty (e->type)
	      && ! grub_msdos_partition_is_extended (e->type))
	    {
	      p.number++;

	      if (hook (disk, &p))
		return grub_errno;
	    }
	  else if (p.number < 4)
	    /* If this partition is a logical one, shouldn't increase the
	       partition number.  */
	    p.number++;
	}

      /* Find an extended partition.  */
      for (i = 0; i < 4; i++)
	{
	  e = mbr.entries + i;

	  if (grub_msdos_partition_is_extended (e->type))
	    {
	      p.offset = ext_offset + grub_le_to_cpu32 (e->start);
	      if (! ext_offset)
		ext_offset = p.offset;

	      break;
	    }
	}

      /* If no extended partition, the end.  */
      if (i == 4)
	break;
    }

 finish:
  return grub_errno;
}
Beispiel #26
0
static grub_err_t
grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
{
  const char *ptr;
  unsigned i;

  pciid_check_value = 0;
  pciid_check_mask = 0;

  if (ctxt->state[0].set)
    {
      ptr = ctxt->state[0].arg;
      pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
	{
	  grub_errno = GRUB_ERR_NONE;
	  ptr = ctxt->state[0].arg;
	}
      else
	pciid_check_mask |= 0xffff;
      if (grub_errno)
	return grub_errno;
      if (*ptr != ':')
	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
      ptr++;
      pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff)
	<< 16;
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
	grub_errno = GRUB_ERR_NONE;
      else
	pciid_check_mask |= 0xffff0000;
    }

  pciid_check_value &= pciid_check_mask;

  check_bus = check_device = check_function = 0;

  if (ctxt->state[1].set)
    {
      const char *optr;
      
      ptr = ctxt->state[1].arg;
      optr = ptr;
      bus = grub_strtoul (ptr, (char **) &ptr, 16);
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
	{
	  grub_errno = GRUB_ERR_NONE;
	  ptr = optr;
	}
      else
	check_bus = 1;
      if (grub_errno)
	return grub_errno;
      if (*ptr != ':')
	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
      ptr++;
      optr = ptr;
      device = grub_strtoul (ptr, (char **) &ptr, 16);
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
	{
	  grub_errno = GRUB_ERR_NONE;
	  ptr = optr;
	}
      else
	check_device = 1;
      if (*ptr == '.')
	{
	  ptr++;
	  function = grub_strtoul (ptr, (char **) &ptr, 16);
	  if (grub_errno)
	    return grub_errno;
	  check_function = 1;
	}
    }

  if (ctxt->state[2].set)
    varname = ctxt->state[2].arg;
  else
    varname = NULL;

  write_mask = 0;

  if (argc == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Command expected.");

  if (argc > 1)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one command is supported.");

  ptr = argv[0];

  for (i = 0; i < ARRAY_SIZE (pci_registers); i++)
    {
      if (grub_strncmp (ptr, pci_registers[i].name,
			grub_strlen (pci_registers[i].name)) == 0)
	break;
    }
  if (i == ARRAY_SIZE (pci_registers))
    {
      regsize = 0;
      regaddr = grub_strtoul (ptr, (char **) &ptr, 16);
      if (grub_errno)
	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown register");
    }
  else
    {
      regaddr = pci_registers[i].addr;
      regsize = pci_registers[i].size;
      ptr += grub_strlen (pci_registers[i].name);
    }

  if (grub_errno)
    return grub_errno;

  if (*ptr == '+')
    {
      ptr++;
      regaddr += grub_strtoul (ptr, (char **) &ptr, 16);
      if (grub_errno)
	return grub_errno;
    }

  if (grub_memcmp (ptr, ".L", sizeof (".L") - 1) == 0
      || grub_memcmp (ptr, ".l", sizeof (".l") - 1) == 0)
    {
      regsize = 4;
      ptr += sizeof (".l") - 1;
    }
  else if (grub_memcmp (ptr, ".W", sizeof (".W") - 1) == 0
      || grub_memcmp (ptr, ".w", sizeof (".w") - 1) == 0)
    {
      regsize = 2;
      ptr += sizeof (".w") - 1;
    }
  else if (grub_memcmp (ptr, ".B", sizeof (".B") - 1) == 0
      || grub_memcmp (ptr, ".b", sizeof (".b") - 1) == 0)
    {
      regsize = 1;
      ptr += sizeof (".b") - 1;
    }

  if (!regsize)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
		       "Unknown register size.");

  write_mask = 0;
  if (*ptr == '=')
    {
      ptr++;
      regwrite = grub_strtoul (ptr, (char **) &ptr, 16);
      if (grub_errno)
	return grub_errno;
      write_mask = 0xffffffff;
      if (*ptr == ':')
	{
	  ptr++;
	  write_mask = grub_strtoul (ptr, (char **) &ptr, 16);
	  if (grub_errno)
	    return grub_errno;
	  write_mask = 0xffffffff;
	}
      regwrite &= write_mask;
    }

  if (write_mask && varname)
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
		       "Option -v isn't valid for writes.");

  grub_pci_iterate (grub_setpci_iter);
  return GRUB_ERR_NONE;
}
Beispiel #27
0
/* Creates new bitmap, saves created bitmap on success to *bitmap.  */
grub_err_t
grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
                          unsigned int width, unsigned int height,
                          enum grub_video_blit_format blit_format)
{
  struct grub_video_mode_info *mode_info;
  unsigned int size;

  if (!bitmap)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");

  *bitmap = 0;

  if (width == 0 || height == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");

  *bitmap = (struct grub_video_bitmap *)grub_malloc (sizeof (struct grub_video_bitmap));
  if (! *bitmap)
    return grub_errno;

  mode_info = &((*bitmap)->mode_info);

  /* Populate mode_info.  */
  mode_info->width = width;
  mode_info->height = height;
  mode_info->blit_format = blit_format;

  switch (blit_format)
    {
      case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888:
        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB
                               | GRUB_VIDEO_MODE_TYPE_ALPHA;
        mode_info->bpp = 32;
        mode_info->bytes_per_pixel = 4;
        mode_info->number_of_colors = 256;
        mode_info->red_mask_size = 8;
        mode_info->red_field_pos = 0;
        mode_info->green_mask_size = 8;
        mode_info->green_field_pos = 8;
        mode_info->blue_mask_size = 8;
        mode_info->blue_field_pos = 16;
        mode_info->reserved_mask_size = 8;
        mode_info->reserved_field_pos = 24;
        break;

      case GRUB_VIDEO_BLIT_FORMAT_RGB_888:
        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
        mode_info->bpp = 24;
        mode_info->bytes_per_pixel = 3;
        mode_info->number_of_colors = 256;
        mode_info->red_mask_size = 8;
        mode_info->red_field_pos = 0;
        mode_info->green_mask_size = 8;
        mode_info->green_field_pos = 8;
        mode_info->blue_mask_size = 8;
        mode_info->blue_field_pos = 16;
        mode_info->reserved_mask_size = 0;
        mode_info->reserved_field_pos = 0;
        break;

      case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR:
        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
        mode_info->bpp = 8;
        mode_info->bytes_per_pixel = 1;
        mode_info->number_of_colors = 256;
        mode_info->red_mask_size = 0;
        mode_info->red_field_pos = 0;
        mode_info->green_mask_size = 0;
        mode_info->green_field_pos = 0;
        mode_info->blue_mask_size = 0;
        mode_info->blue_field_pos = 0;
        mode_info->reserved_mask_size = 0;
        mode_info->reserved_field_pos = 0;
        break;

      default:
        grub_free (*bitmap);
        *bitmap = 0;

        return grub_error (GRUB_ERR_BAD_ARGUMENT,
                           "unsupported bitmap format");
    }

  mode_info->pitch = width * mode_info->bytes_per_pixel;

  /* Calculate size needed for the data.  */
  size = (width * mode_info->bytes_per_pixel) * height;

  (*bitmap)->data = grub_zalloc (size);
  if (! (*bitmap)->data)
    {
      grub_free (*bitmap);
      *bitmap = 0;

      return grub_errno;
    }

  return GRUB_ERR_NONE;
}
Beispiel #28
0
grub_err_t
grub_multiboot_load (grub_file_t file)
{
  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);
      return grub_error (GRUB_ERR_BAD_OS, "file too small");
    }

  /* Look for the multiboot header in the buffer.  The header should
     be at least 12 bytes and aligned on a 4-byte boundary.  */
  for (header = (struct multiboot_header *) buffer;
       ((char *) header <= buffer + len - 12) || (header = 0);
       header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
    {
      if (header->magic == MULTIBOOT_HEADER_MAGIC
	  && !(header->magic + header->flags + header->checksum))
	break;
    }

  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);
    }

  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
    {
      int offset = ((char *) header - buffer -
		    (header->header_addr - header->load_addr));
      int load_size = ((header->load_end_addr == 0) ? file->size - offset :
		       header->load_end_addr - header->load_addr);
      grub_size_t code_size;
      void *source;
      grub_relocator_chunk_t ch;

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

      err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, 
					     &ch, header->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 (header->bss_end_addr)
	grub_memset ((grub_uint8_t *) source + load_size, 0,
		     header->bss_end_addr - header->load_addr - load_size);

      grub_multiboot_payload_eip = header->entry_addr;
    }
  else
    {
      err = grub_multiboot_load_elf (file, buffer);
      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;
}
Beispiel #29
0
/* FIXME: Previously 't' changed to text menu is it necessary?  */
static grub_err_t
grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
{
  grub_gfxmenu_view_t view = NULL;
  const char *theme_path;
  struct grub_menu_viewer *instance;
  grub_err_t err;
  struct grub_video_mode_info mode_info;

  theme_path = grub_env_get ("theme");
  if (! theme_path)
    {
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified");
    }

  instance = grub_zalloc (sizeof (*instance));
  if (!instance)
    {
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return grub_errno;
    }

  err = grub_video_get_info (&mode_info);
  if (err)
    {
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return err;
    }

  if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0
      || cached_view->screen.width != mode_info.width
      || cached_view->screen.height != mode_info.height)
    {
      grub_free (cached_view);
      /* Create the view.  */
      cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width,
					   mode_info.height);
    }

  if (! cached_view)
    {
      grub_free (instance);
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return grub_errno;
    }

  view = cached_view;

  view->double_repaint = (mode_info.mode_type
			  & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
    && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
  view->selected = entry;
  view->menu = menu;
  view->nested = nested;
  view->first_timeout = -1;

  grub_gfxmenu_view_draw (view);

  instance->data = view;
  instance->set_chosen_entry = grub_gfxmenu_set_chosen_entry;
  instance->fini = grub_gfxmenu_viewer_fini;
  instance->print_timeout = grub_gfxmenu_print_timeout;
  instance->clear_timeout = grub_gfxmenu_clear_timeout;

  grub_menu_register_viewer (instance);

  return GRUB_ERR_NONE;
}
Beispiel #30
0
/* Bilinear interpolation image scaling algorithm.

   Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
   dimensions of DST.  This function uses the bilinear interpolation algorithm
   to interpolate the pixels.

   Supports only direct color modes which have components separated
   into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
   But because of this simplifying assumption, the implementation is
   greatly simplified.  */
static grub_err_t
scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
{
  /* Verify the simplifying assumptions. */
  if (dst == 0 || src == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale func");
  if (dst->mode_info.red_field_pos % 8 != 0
      || dst->mode_info.green_field_pos % 8 != 0
      || dst->mode_info.blue_field_pos % 8 != 0
      || dst->mode_info.reserved_field_pos % 8 != 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported");
  if (src->mode_info.red_field_pos % 8 != 0
      || src->mode_info.green_field_pos % 8 != 0
      || src->mode_info.blue_field_pos % 8 != 0
      || src->mode_info.reserved_field_pos % 8 != 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported");
  if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
      || dst->mode_info.red_mask_size != src->mode_info.red_mask_size
      || dst->mode_info.green_field_pos != src->mode_info.green_field_pos
      || dst->mode_info.green_mask_size != src->mode_info.green_mask_size
      || dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
      || dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
      || dst->mode_info.reserved_field_pos !=
      src->mode_info.reserved_field_pos
      || dst->mode_info.reserved_mask_size !=
      src->mode_info.reserved_mask_size)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
  if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
  if (dst->mode_info.width == 0 || dst->mode_info.height == 0
      || src->mode_info.width == 0 || src->mode_info.height == 0)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension");

  grub_uint8_t *ddata = dst->data;
  grub_uint8_t *sdata = src->data;
  int dw = dst->mode_info.width;
  int dh = dst->mode_info.height;
  int sw = src->mode_info.width;
  int sh = src->mode_info.height;
  int dstride = dst->mode_info.pitch;
  int sstride = src->mode_info.pitch;
  /* bytes_per_pixel is the same for both src and dst. */
  int bytes_per_pixel = dst->mode_info.bytes_per_pixel;

  int dy;
  for (dy = 0; dy < dh; dy++)
    {
      int dx;
      for (dx = 0; dx < dw; dx++)
        {
          grub_uint8_t *dptr;
          grub_uint8_t *sptr;
          int sx;
          int sy;
          int comp;

          /* Compute the source coordinate that the destination coordinate
             maps to.  Note: sx/sw = dx/dw  =>  sx = sw*dx/dw. */
          sx = sw * dx / dw;
          sy = sh * dy / dh;

          /* Get the address of the pixels in src and dst. */
          dptr = ddata + dy * dstride + dx * bytes_per_pixel;
          sptr = sdata + sy * sstride + sx * bytes_per_pixel;

          /* If we have enough space to do so, use bilinear interpolation.
             Otherwise, fall back to nearest neighbor for this pixel. */
          if (sx < sw - 1 && sy < sh - 1)
            {
              /* Do bilinear interpolation. */

              /* Fixed-point .8 numbers representing the fraction of the
                 distance in the x (u) and y (v) direction within the
                 box of 4 pixels in the source. */
              int u = (256 * sw * dx / dw) - (sx * 256);
              int v = (256 * sh * dy / dh) - (sy * 256);

              for (comp = 0; comp < bytes_per_pixel; comp++)
                {
                  /* Get the component's values for the
                     four source corner pixels. */
                  grub_uint8_t f00 = sptr[comp];
                  grub_uint8_t f10 = sptr[comp + bytes_per_pixel];
                  grub_uint8_t f01 = sptr[comp + sstride];
                  grub_uint8_t f11 = sptr[comp + sstride + bytes_per_pixel];

                  /* Do linear interpolations along the top and bottom
                     rows of the box. */
                  grub_uint8_t f0y = (256 - v) * f00 / 256 + v * f01 / 256;
                  grub_uint8_t f1y = (256 - v) * f10 / 256 + v * f11 / 256;

                  /* Interpolate vertically. */
                  grub_uint8_t fxy = (256 - u) * f0y / 256 + u * f1y / 256;

                  dptr[comp] = fxy;
                }
            }
          else
            {
              /* Fall back to nearest neighbor interpolation. */
              /* Copy the pixel color value. */
              for (comp = 0; comp < bytes_per_pixel; comp++)
                dptr[comp] = sptr[comp];
            }
        }
    }
  return GRUB_ERR_NONE;
}