Exemplo n.º 1
0
static int
test_gzip_header (grub_file_t file)
{
    struct {
        grub_uint16_t magic;
        grub_uint8_t method;
        grub_uint8_t flags;
        grub_uint32_t timestamp;
        grub_uint8_t extra_flags;
        grub_uint8_t os_type;
    } hdr;
    grub_uint16_t extra_len;
    grub_uint32_t orig_len;
    grub_gzio_t gzio = file->data;

    if (grub_file_tell (gzio->file) != 0)
        grub_file_seek (gzio->file, 0);

    /*
     *  This checks if the file is gzipped.  If a problem occurs here
     *  (other than a real error with the disk) then we don't think it
     *  is a compressed file, and simply mark it as such.
     */
    if (grub_file_read (gzio->file, &hdr, 10) != 10
            || ((hdr.magic != GZIP_MAGIC)
                && (hdr.magic != OLD_GZIP_MAGIC)))
        return 0;

    /*
     *  This does consistency checking on the header data.  If a
     *  problem occurs from here on, then we have corrupt or otherwise
     *  bad data, and the error should be reported to the user.
     */
    if (hdr.method != DEFLATED
            || (hdr.flags & UNSUPPORTED_FLAGS)
            || ((hdr.flags & EXTRA_FIELD)
                && (grub_file_read (gzio->file, &extra_len, 2) != 2
                    || eat_field (gzio->file,
                                  grub_le_to_cpu16 (extra_len))))
            || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1))
            || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1)))
        return 0;

    gzio->data_offset = grub_file_tell (gzio->file);

    /* FIXME: don't do this on not easily seekable files.  */
    {
        grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4);
        if (grub_file_read (gzio->file, &orig_len, 4) != 4)
            return 0;
        /* FIXME: this does not handle files whose original size is over 4GB.
           But how can we know the real original size?  */
        file->size = grub_le_to_cpu32 (orig_len);
    }

    initialize_tables (gzio);

    return 1;
}
Exemplo n.º 2
0
/* Try to find out size of uncompressed data,
 * also do some footer sanity checks.  */
static int
test_footer (grub_file_t file)
{
  grub_xzio_t xzio = file->data;
  grub_uint8_t footer[FOOTER_MAGIC_SIZE];
  grub_uint32_t backsize;
  grub_uint8_t imarker;
  grub_uint64_t uncompressed_size_total = 0;
  grub_uint64_t uncompressed_size;
  grub_uint64_t records;

  grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE);
  if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) !=
      FOOTER_MAGIC_SIZE
      || grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0)
    goto ERROR;

  grub_file_seek (xzio->file, xzio->file->size - 8);
  if (grub_file_read (xzio->file, &backsize, sizeof (backsize))
      != sizeof (backsize))
    goto ERROR;

  /* Calculate real backward size.  */
  backsize = (grub_le_to_cpu32 (backsize) + 1) * 4;

  /* Set file to the beginning of stream index.  */
  grub_file_seek (xzio->file,
		  xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize);

  /* Test index marker.  */
  if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) !=
      sizeof (imarker) && imarker != 0x00)
    goto ERROR;

  if (read_vli (xzio->file, &records) <= 0)
    goto ERROR;

  for (; records != 0; records--)
    {
      if (read_vli (xzio->file, &uncompressed_size) <= 0)	/* Ignore unpadded.  */
	goto ERROR;
      if (read_vli (xzio->file, &uncompressed_size) <= 0)	/* Uncompressed.  */
	goto ERROR;

      uncompressed_size_total += uncompressed_size;
    }

  file->size = uncompressed_size_total;
  grub_file_seek (xzio->file, STREAM_HEADER_SIZE);
  return 1;

ERROR:
  grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "bad footer magic");
  return 0;
}
Exemplo n.º 3
0
grub_err_t
SUFFIX (grub_macho_readfile) (grub_macho_t macho, void *dest)
{
  grub_ssize_t read;
  if (! SUFFIX (grub_macho_contains_macho) (macho))
    return grub_error (GRUB_ERR_BAD_OS,
		       "couldn't read architecture-specific part");

  if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1)
    {
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS,
			 "invalid offset in program header");
    }

  read = grub_file_read (macho->file, dest,
			 macho->endXX - macho->offsetXX);
  if (read != (grub_ssize_t) (macho->endXX - macho->offsetXX))
    {
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS,
			 "couldn't read architecture-specific part");
    }
  return GRUB_ERR_NONE;
}
Exemplo n.º 4
0
grub_err_t
grub_elfXX_load_phdrs (grub_elf_t elf)
{
  grub_ssize_t phdrs_size;

  if (elf->phdrs)
    return GRUB_ERR_NONE;

  phdrs_size = elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize;

  grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
		(unsigned long long) elf->ehdr.ehdrXX.e_phoff,
		(unsigned long) phdrs_size);

  elf->phdrs = grub_malloc (phdrs_size);
  if (! elf->phdrs)
    return grub_errno;

  if ((grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_phoff) == (grub_off_t) -1)
      || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
    {
      if (!grub_errno)
	grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
		    elf->filename);
      return grub_errno;
    }

  return GRUB_ERR_NONE;
}
Exemplo n.º 5
0
Arquivo: elf.c Projeto: TemmeR/grub2
grub_elf_t
grub_elf_file (grub_file_t file)
{
  grub_elf_t elf;

  elf = grub_zalloc (sizeof (*elf));
  if (! elf)
    return 0;

  elf->file = file;

  if (grub_file_seek (elf->file, 0) == (grub_off_t) -1)
    goto fail;

  if (grub_file_read (elf->file, &elf->ehdr, sizeof (elf->ehdr))
      != sizeof (elf->ehdr))
    {
      grub_error_push ();
      grub_error (GRUB_ERR_READ_ERROR, "cannot read ELF header");
      goto fail;
    }

  if (grub_elf_check_header (elf))
    goto fail;

  return elf;

fail:
  grub_free (elf->phdrs);
  grub_free (elf);
  return 0;
}
Exemplo n.º 6
0
static grub_err_t
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
		    grub_size_t size, char *buf)
{
  grub_file_t file = (grub_file_t) disk->data;
  grub_off_t pos;

  grub_file_seek (file, sector << GRUB_DISK_SECTOR_BITS);

  grub_file_read (file, buf, size << GRUB_DISK_SECTOR_BITS);
  if (grub_errno)
    return grub_errno;

  /* In case there is more data read than there is available, in case
     of files that are not a multiple of GRUB_DISK_SECTOR_SIZE, fill
     the rest with zeros.  */
  pos = (sector + size) << GRUB_DISK_SECTOR_BITS;
  if (pos > file->size)
    {
      grub_size_t amount = pos - file->size;
      grub_memset (buf + (size << GRUB_DISK_SECTOR_BITS) - amount, 0, amount);
    }

  return 0;
}
Exemplo n.º 7
0
Arquivo: elf.c Projeto: TemmeR/grub2
/* Load every loadable segment into memory specified by `_load_hook'.  */
grub_err_t
grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
		 grub_addr_t *base, grub_size_t *size)
{
  grub_addr_t load_base = (grub_addr_t) -1ULL;
  grub_size_t load_size = 0;
  grub_err_t err;

  auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook);
  int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook)
  {
    grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook;
    grub_addr_t load_addr;
    int do_load = 1;

    load_addr = phdr->p_paddr;
    if (load_hook && load_hook (phdr, &load_addr, &do_load))
      return 1;

    if (! do_load)
      return 0;

    if (load_addr < load_base)
      load_base = load_addr;

    grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n",
		  (unsigned long long) load_addr,
		  (unsigned long long) phdr->p_memsz);

    if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
      {
	grub_error_push ();
	return grub_error (GRUB_ERR_BAD_OS,
			   "invalid offset in program header");
      }

    if (phdr->p_filesz)
      {
	grub_ssize_t read;
	read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz);
	if (read != (grub_ssize_t) phdr->p_filesz)
	  {
	    /* XXX How can we free memory from `load_hook'? */
	    grub_error_push ();
	    return grub_error (GRUB_ERR_BAD_OS,
			       "couldn't read segment from file: "
			       "wanted 0x%lx bytes; read 0x%lx bytes",
			       phdr->p_filesz, read);
	  }
      }

    if (phdr->p_filesz < phdr->p_memsz)
      grub_memset ((void *) (long) (load_addr + phdr->p_filesz),
		   0, phdr->p_memsz - phdr->p_filesz);

    load_size += phdr->p_memsz;

    return 0;
  }
Exemplo n.º 8
0
Arquivo: offset.c Projeto: flihp/grub2
static grub_ssize_t
grub_offset_read (grub_file_t file, char *buf, grub_size_t len)
{
  struct grub_offset_file *data = file->data;
  if (grub_file_seek (data->parent, data->off + file->offset) == (grub_off_t) -1)
    return -1;
  return grub_file_read (data->parent, buf, len);
}
Exemplo n.º 9
0
static grub_err_t
load_kernel (grub_file_t file, const char *filename,
	     char *buffer, struct multiboot_header *header)
{
  grub_err_t err;
  if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
    {
      err = grub_multiboot_load_elf (file, filename, buffer);
      if (err == GRUB_ERR_NONE) {
	return GRUB_ERR_NONE;
      }
      if (err == GRUB_ERR_UNKNOWN_OS && (header->flags & MULTIBOOT_AOUT_KLUDGE))
	grub_errno = err = GRUB_ERR_NONE;
    }
  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");
	  return err;
	}
      source = get_virtual_current_address (ch);

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

      grub_file_read (file, source, load_size);
      if (grub_errno)
	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;
      return GRUB_ERR_NONE;
    }

  return grub_multiboot_load_elf (file, filename, buffer);
}
Exemplo n.º 10
0
static inline grub_err_t
read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr)
{
 if (grub_file_seek (file, 0) == (grub_off_t) -1)
    return grub_errno;

  if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
    {
      if (grub_errno)
	return grub_errno;
      else
	return grub_error (GRUB_ERR_BAD_OS, "file is too short");
    }

  if (e->e_ident[EI_MAG0] != ELFMAG0
      || e->e_ident[EI_MAG1] != ELFMAG1
      || e->e_ident[EI_MAG2] != ELFMAG2
      || e->e_ident[EI_MAG3] != ELFMAG3
      || e->e_ident[EI_VERSION] != EV_CURRENT
      || e->e_version != EV_CURRENT)
    return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic");

  if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
    return grub_error (GRUB_ERR_BAD_OS, "invalid arch dependent ELF magic");

  *shdr = grub_malloc (e->e_shnum * e->e_shentsize);
  if (! *shdr)
    return grub_errno;

  if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
    return grub_errno;

  if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize)
      != e->e_shnum * e->e_shentsize)
    {
      if (grub_errno)
	return grub_errno;
      else
	return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
    }

  return GRUB_ERR_NONE;
}
Exemplo n.º 11
0
static grub_ssize_t
grub_gettext_pread (grub_file_t file, void *buf, grub_size_t len,
		    grub_off_t offset)
{
  if (grub_file_seek (file, offset) == (grub_off_t) - 1)
    {
      return -1;
    }
  return grub_file_read (file, buf, len);
}
Exemplo n.º 12
0
grub_elf_t
grub_xen_file (grub_file_t file)
{
  grub_elf_t elf;
  struct linux_kernel_header lh;
  grub_file_t off_file;

  elf = grub_elf_file (file, file->name);
  if (elf)
    return elf;
  grub_errno = GRUB_ERR_NONE;

  if (grub_file_seek (file, 0) == (grub_off_t) -1)
    goto fail;

  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
    goto fail;

  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)
      || lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
      || grub_le_to_cpu16 (lh.version) < 0x0208)
    {
      grub_error (GRUB_ERR_BAD_OS, "version too old for xen boot");
      return NULL;
    }

  if (lh.payload_length < 4)
    {
      grub_error (GRUB_ERR_BAD_OS, "payload too short");
      return NULL;
    }

  grub_dprintf ("xen", "found bzimage payload 0x%llx-0x%llx\n",
		(unsigned long long) (lh.setup_sects + 1) * 512
		+ lh.payload_offset,
		(unsigned long long) lh.payload_length - 4);

  off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512
				    + lh.payload_offset,
				    lh.payload_length - 4);
  if (!off_file)
    goto fail;

  elf = grub_elf_file (off_file, file->name);
  if (elf)
    return elf;
  grub_file_offset_close (off_file);

fail:
  grub_error (GRUB_ERR_BAD_OS, "not xen image");
  return NULL;
}
Exemplo n.º 13
0
static void
gzio_seek (grub_gzio_t gzio, grub_off_t off)
{
    if (gzio->mem_input)
    {
        if (off > gzio->mem_input_size)
            grub_error (GRUB_ERR_OUT_OF_RANGE,
                        N_("attempt to seek outside of the file"));
        else
            gzio->mem_input_off = off;
    }
    else
        grub_file_seek (gzio->file, off);
}
Exemplo n.º 14
0
/* Jump to next block and read its header.  */
static int
jump_block (struct grub_lzopio *lzopio)
{
  /* only jump if block was not decompressed (and read from disk) */
  if (!lzopio->block.udata)
    {
      grub_off_t off = grub_file_tell (lzopio->file) + lzopio->block.csize;

      if (grub_file_seek (lzopio->file, off) == ((grub_off_t) - 1))
	return -1;
    }

  return read_block_header (lzopio);
}
Exemplo n.º 15
0
static inline grub_err_t
load (grub_file_t file, void *where, grub_off_t off, grub_size_t size)
{
  if (grub_file_seek (file, off) == (grub_off_t) -1)
    return grub_errno;
  if (grub_file_read (file, where, size) != (grub_ssize_t) size)
    {
      if (grub_errno)
	return grub_errno;
      else
	return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
    }
  return GRUB_ERR_NONE;
}
Exemplo n.º 16
0
Arquivo: compat.c Projeto: xk/bits
int ungetc(int c, FILE *stream)
{
    grub_errno = GRUB_ERR_NONE;
    if (stream == stdout || stream == stderr) {
        grub_printf("Internal error: Python attempted to ungetc on stdout or stderr.\n");
        return EOF;
    }
    if (stream == stdin) {
        grub_printf("Internal error: Python attempted to ungetc on stdin.\n");
        return EOF;
    }
    if (stream->offset == 0) {
        grub_printf("Internal error: Python attempted to ungetc at the beginning of a file.\n");
        return EOF;
    }
    grub_file_seek(stream, stream->offset-1);
    if (fgetc(stream) != c) {
        grub_printf("Internal error: Python attempted to ungetc a character it didn't getc.\n");
        return EOF;
    }
    grub_file_seek(stream, stream->offset-1);
    return c;
}
Exemplo n.º 17
0
static grub_ssize_t
read_vli (grub_file_t file, grub_uint64_t * num)
{
  grub_uint8_t buf[VLI_MAX_DIGITS];
  grub_ssize_t read;
  grub_size_t dec;

  read = grub_file_read (file, buf, VLI_MAX_DIGITS);
  if (read < 0)
    return -1;

  dec = decode_vli (buf, read, num);
  grub_file_seek (file, file->offset - (read - dec));
  return dec;
}
Exemplo n.º 18
0
static grub_err_t
grub_gettext_pread (grub_file_t file, void *buf, grub_size_t len,
		    grub_off_t offset)
{
  if (len == 0)
    return GRUB_ERR_NONE;
  if (grub_file_seek (file, offset) == (grub_off_t) - 1)
    return grub_errno;
  if (grub_file_read (file, buf, len) != (grub_ssize_t) len)
    {
      if (!grub_errno)
	grub_error (GRUB_ERR_READ_ERROR, N_("premature end of file"));
      return grub_errno;
    }
  return GRUB_ERR_NONE;
}
Exemplo n.º 19
0
static int
grub_macho_load_do_load (grub_macho_t _macho,
			 struct grub_macho_cmd *hdr0,
			 void *closure)
{
  struct grub_macho_load_closure *c = closure;
  grub_macho_segment_t *hdr = (grub_macho_segment_t *) hdr0;

  if (hdr->cmd != GRUB_MACHO_CMD_SEGMENT)
    return 0;

  if (! hdr->filesize && (c->flags & GRUB_MACHO_NOBSS))
    return 0;
  if (! hdr->vmsize)
    return 0;

  if (grub_file_seek (_macho->file, hdr->fileoff
		      + _macho->offsetXX) == (grub_off_t) -1)
    {
      grub_error_push ();
      grub_error (GRUB_ERR_BAD_OS,
		  "invalid offset in program header");
      return 1;
    }

  if (hdr->filesize)
    {
      grub_ssize_t read;
      read = grub_file_read (_macho->file, c->offset + hdr->vmaddr,
			     min (hdr->filesize, hdr->vmsize));
      if (read != (grub_ssize_t) min (hdr->filesize, hdr->vmsize))
	{
	  /* XXX How can we free memory from `load_hook'? */
	  grub_error_push ();
	  c->err = grub_error (GRUB_ERR_BAD_OS,
			       "couldn't read segment from file: "
			       "wanted 0x%lx bytes; read 0x%lx bytes",
			       hdr->filesize, read);
	  return 1;
	}
    }

  if (hdr->filesize < hdr->vmsize)
    grub_memset (c->offset + hdr->vmaddr + hdr->filesize,
		 0, hdr->vmsize - hdr->filesize);
  return 0;
}
Exemplo n.º 20
0
static inline grub_err_t
load (grub_file_t file, void *where, grub_off_t off, grub_size_t size)
{
  if (PTR_TO_UINT32 (where) + size > grub_os_area_addr + grub_os_area_size)
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
		       "not enough memory for the module");
  if (grub_file_seek (file, off) == (grub_off_t) -1)
    return grub_errno;
  if (grub_file_read (file, where, size)
      != (grub_ssize_t) size)
    {
      if (grub_errno)
	return grub_errno;
      else
	return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
    }
  return GRUB_ERR_NONE;
}
Exemplo n.º 21
0
void
SUFFIX (grub_macho_parse) (grub_macho_t macho)
{
  grub_macho_header_t head;

  /* Is there any candidate at all? */
  if (macho->offsetXX == -1)
    return;

  /* Read header and check magic*/
  if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1
      || grub_file_read (macho->file, &head, sizeof (head))
      != sizeof(head))
    {
      grub_error (GRUB_ERR_READ_ERROR, "cannot read Mach-O header");
      macho->offsetXX = -1;
      return;
    }
  if (head.magic != GRUB_MACHO_MAGIC)
    {
      grub_error (GRUB_ERR_BAD_OS, "invalid Mach-O " XX "-bit header");
      macho->offsetXX = -1;
      return;
    }

  /* Read commands. */
  macho->ncmdsXX = head.ncmds;
  macho->cmdsizeXX = head.sizeofcmds;
  macho->cmdsXX = grub_malloc(macho->cmdsizeXX);
  if (! macho->cmdsXX)
    {
      grub_error (GRUB_ERR_OUT_OF_MEMORY, "not enough memory to read commands");
      return;
    }
  if (grub_file_read (macho->file, macho->cmdsXX,
		      (grub_size_t) macho->cmdsizeXX)
      != (grub_ssize_t) macho->cmdsizeXX)
    {
      grub_error (GRUB_ERR_READ_ERROR, "cannot read Mach-O header");
      macho->offsetXX = -1;
    }
}
Exemplo n.º 22
0
Arquivo: gzio.c Projeto: TemmeR/grub2
static void
initialize_tables (grub_file_t file)
{
  grub_gzio_t gzio = file->data;

  gzio->saved_offset = 0;
  grub_file_seek (gzio->file, gzio->data_offset);

  /* Initialize the bit buffer.  */
  gzio->bk = 0;
  gzio->bb = 0;

  /* Reset partial decompression code.  */
  gzio->last_block = 0;
  gzio->block_len = 0;

  /* Reset memory allocation stuff.  */
  huft_free (gzio->tl);
  huft_free (gzio->td);
}
Exemplo n.º 23
0
Arquivo: gzio.c Projeto: TemmeR/grub2
/* Open a new decompressing object on the top of IO. If TRANSPARENT is true,
   even if IO does not contain data compressed by gzip, return a valid file
   object. Note that this function won't close IO, even if an error occurs.  */
static grub_file_t
grub_gzio_open (grub_file_t io)
{
  grub_file_t file;
  grub_gzio_t gzio = 0;

  file = (grub_file_t) grub_malloc (sizeof (*file));
  if (! file)
    return 0;

  gzio = grub_zalloc (sizeof (*gzio));
  if (! gzio)
    {
      grub_free (file);
      return 0;
    }

  gzio->file = io;

  file->device = io->device;
  file->offset = 0;
  file->data = gzio;
  file->read_hook = 0;
  file->fs = &grub_gzio_fs;
  file->not_easly_seekable = 1;

  if (! test_header (file))
    {
      grub_free (gzio);
      grub_free (file);
      grub_file_seek (io, 0);

      if (grub_errno == GRUB_ERR_BAD_FILE_TYPE)
	{
	  grub_errno = GRUB_ERR_NONE;
	  return io;
	}
    }

  return file;
}
Exemplo n.º 24
0
Arquivo: compat.c Projeto: xk/bits
int fseek(FILE *stream, long offset, int whence)
{
    grub_errno = GRUB_ERR_NONE;
    if (stream == stdin || stream == stdout || stream == stderr) {
        grub_printf("Internal error: Python attempted to seek on stdin, stdout, or stderr.\n");
        return -1;
    }
    switch (whence)
    {
        case SEEK_SET:
            break;
        case SEEK_CUR:
            offset += stream->offset;
            break;
        case SEEK_END:
            offset += stream->size;
            break;
        default:
            return -1;
    }
    return (grub_file_seek(stream, offset) == -1ULL) ? -1 : 0;
}
Exemplo n.º 25
0
grub_elf_t
grub_elf_file (grub_file_t file, const char *filename)
{
  grub_elf_t elf;

  elf = grub_zalloc (sizeof (*elf));
  if (! elf)
    return 0;

  elf->file = file;

  if (grub_file_seek (elf->file, 0) == (grub_off_t) -1)
    goto fail;

  if (grub_file_read (elf->file, &elf->ehdr, sizeof (elf->ehdr))
      != sizeof (elf->ehdr))
    {
      if (!grub_errno)
	grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
		    filename);
      goto fail;
    }

  if (grub_elf_check_header (elf))
    goto fail;

  elf->filename = grub_strdup (filename);
  if (!elf->filename)
    goto fail;

  return elf;

fail:
  grub_free (elf->filename);
  grub_free (elf->phdrs);
  grub_free (elf);
  return 0;
}
Exemplo n.º 26
0
Arquivo: elf.c Projeto: TemmeR/grub2
static grub_err_t
grub_elf32_load_phdrs (grub_elf_t elf)
{
  grub_ssize_t phdrs_size;

  phdrs_size = elf->ehdr.ehdr32.e_phnum * elf->ehdr.ehdr32.e_phentsize;

  grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
		(unsigned long long) elf->ehdr.ehdr32.e_phoff,
		(unsigned long) phdrs_size);

  elf->phdrs = grub_malloc (phdrs_size);
  if (! elf->phdrs)
    return grub_errno;

  if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1)
      || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
    {
      grub_error_push ();
      return grub_error (GRUB_ERR_READ_ERROR, "cannot read program headers");
    }

  return GRUB_ERR_NONE;
}
Exemplo n.º 27
0
grub_err_t
SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
				   grub_addr_t kern_start,
				   void *kern_chunk_src,
				   struct grub_openbsd_ramdisk_descriptor *desc)
{
  unsigned symoff, stroff, symsize, strsize, symentsize;

  {
    grub_err_t err;
    Elf_Ehdr e;
    Elf_Shdr *s;
    char *shdr = NULL;
    
    err = read_headers (file, &e, &shdr);
    if (err)
      return err;

    for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
						  + e.e_shnum * e.e_shentsize);
	 s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
      if (s->sh_type == SHT_SYMTAB)
	break;
    if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize))
      {
	grub_free (shdr);
	return GRUB_ERR_NONE;
      }

    symsize = s->sh_size;
    symentsize = s->sh_entsize;
    symoff = s->sh_offset;
    
    s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
    stroff = s->sh_offset;
    strsize = s->sh_size;
    grub_free (shdr);
  }
  {
    Elf_Sym *syms, *sym, *imagesym = NULL, *sizesym = NULL;
    unsigned i;
    char *strs;

    syms = grub_malloc (symsize);
    if (!syms)
      return grub_errno;

    if (grub_file_seek (file, symoff) == (grub_off_t) -1)
      {
	grub_free (syms);
	return grub_errno;
      }
    if (grub_file_read (file, syms, symsize) != (grub_ssize_t) symsize)
      {
	grub_free (syms);
	if (! grub_errno)
	  return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
	return grub_errno;
      }

    strs = grub_malloc (strsize);
    if (!strs)
      {
	grub_free (syms);
	return grub_errno;
      }

    if (grub_file_seek (file, stroff) == (grub_off_t) -1)
      return grub_errno;
    if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize)
      {
	grub_free (syms);
	grub_free (strs);
	if (! grub_errno)
	  return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
	return grub_errno;
      }

    for (i = 0, sym = syms; i < symsize / symentsize;
       i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
      {
	if (ELF_ST_TYPE (sym->st_info) != STT_OBJECT)
	  continue;
	if (!sym->st_name)
	  continue;
	if (grub_strcmp (strs + sym->st_name, "rd_root_image") == 0)
	  imagesym = sym;
	if (grub_strcmp (strs + sym->st_name, "rd_root_size") == 0)
	  sizesym = sym;
	if (imagesym && sizesym)
	  break;
      }
    if (!imagesym || !sizesym)
      {
	grub_free (syms);
	grub_free (strs);
	return GRUB_ERR_NONE;
      }
    if (sizeof (*desc->size) != sizesym->st_size)
      {
	grub_free (syms);
	grub_free (strs);
	return grub_error (GRUB_ERR_BAD_OS, "unexpected size of rd_root_size");
      }
    desc->max_size = imagesym->st_size;
    desc->target = (imagesym->st_value & 0xFFFFFF) - kern_start
      + (grub_uint8_t *) kern_chunk_src;
    desc->size = (grub_uint32_t *) ((sizesym->st_value & 0xFFFFFF) - kern_start
				    + (grub_uint8_t *) kern_chunk_src);
    grub_free (syms);
    grub_free (strs);

    return GRUB_ERR_NONE;
  }
}
Exemplo n.º 28
0
grub_err_t
SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
				     grub_file_t file, grub_addr_t *kern_end)
{
  grub_err_t err;
  Elf_Ehdr e;
  Elf_Shdr *s;
  char *shdr = 0;
  unsigned symoff, stroff, symsize, strsize;
  grub_freebsd_addr_t symstart, symend, symentsize, dynamic;
  Elf_Sym *sym;
  void *sym_chunk;
  grub_uint8_t *curload;
  grub_freebsd_addr_t symtarget;
  const char *str;
  unsigned i;
  grub_size_t chunk_size;

  err = read_headers (file, &e, &shdr);
  if (err)
    return err;

  err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
			   FREEBSD_MODINFOMD_ELFHDR, &e,
			   sizeof (e));
  if (err)
    return err;

  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
						+ e.e_shnum * e.e_shentsize);
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
      if (s->sh_type == SHT_SYMTAB)
	break;
  if (s >= (Elf_Shdr *) ((char *) shdr
			+ e.e_shnum * e.e_shentsize))
    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
  symoff = s->sh_offset;
  symsize = s->sh_size;
  symentsize = s->sh_entsize;
  s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
  stroff = s->sh_offset;
  strsize = s->sh_size;

  chunk_size = ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t))
    + 2 * sizeof (grub_freebsd_addr_t);

  symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));

  {
    grub_relocator_chunk_t ch;
    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
					   symtarget, chunk_size);
    if (err)
      return err;
    sym_chunk = get_virtual_current_address (ch);
  }

  symstart = symtarget;
  symend = symstart + chunk_size;

  curload = sym_chunk;
  *((grub_freebsd_addr_t *) curload) = symsize;
  curload += sizeof (grub_freebsd_addr_t);

  if (grub_file_seek (file, symoff) == (grub_off_t) -1)
    return grub_errno;
  sym = (Elf_Sym *) curload;
  if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
    {
      if (! grub_errno)
	return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
      return grub_errno;
    }
  curload += symsize;

  *((grub_freebsd_addr_t *) curload) = strsize;
  curload += sizeof (grub_freebsd_addr_t);
  if (grub_file_seek (file, stroff) == (grub_off_t) -1)
    return grub_errno;
  str = (char *) curload;
  if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
    {
      if (! grub_errno)
	return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
      return grub_errno;
    }

  for (i = 0;
       i * symentsize < symsize;
       i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
    {
      const char *name = str + sym->st_name;
      if (grub_strcmp (name, "_DYNAMIC") == 0)
	break;
    }

  if (i * symentsize < symsize)
    {
      dynamic = sym->st_value;
      grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic);
      err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
			       FREEBSD_MODINFOMD_DYNAMIC, &dynamic,
			       sizeof (dynamic));
      if (err)
	return err;
    }

  err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
			   FREEBSD_MODINFOMD_SSYM, &symstart,
			   sizeof (symstart));
  if (err)
    return err;

  err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
			   FREEBSD_MODINFOMD_ESYM, &symend,
			   sizeof (symend));
  if (err)
    return err;

  *kern_end = ALIGN_PAGE (symend);

  return GRUB_ERR_NONE;
}
Exemplo n.º 29
0
grub_err_t
SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
				    grub_file_t file, grub_addr_t *kern_end)
{
  grub_err_t err;
  Elf_Ehdr e;
  Elf_Shdr *s, *symsh, *strsh;
  char *shdr = NULL;
  unsigned symsize, strsize;
  void *sym_chunk;
  grub_uint8_t *curload;
  grub_size_t chunk_size;
  Elf_Ehdr *e2;
  struct grub_netbsd_btinfo_symtab symtab;
  grub_addr_t symtarget;

  err = read_headers (file, &e, &shdr);
  if (err)
    return err;

  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
						+ e.e_shnum * e.e_shentsize);
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
      if (s->sh_type == SHT_SYMTAB)
	break;
  if (s >= (Elf_Shdr *) ((char *) shdr
			+ e.e_shnum * e.e_shentsize))
    return GRUB_ERR_NONE;
  symsize = s->sh_size;
  symsh = s;
  s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
  strsize = s->sh_size;
  strsh = s;

  chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
    + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
    + sizeof (e) + e.e_shnum * e.e_shentsize;

  symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
  {
    grub_relocator_chunk_t ch;
    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
					   symtarget, chunk_size);
    if (err)
      return err;
    sym_chunk = get_virtual_current_address (ch);
  }

  symtab.nsyms = 1;
  symtab.ssyms = symtarget;
  symtab.esyms = symtarget + chunk_size;

  curload = sym_chunk;
  
  e2 = (Elf_Ehdr *) curload;
  grub_memcpy (curload, &e, sizeof (e));
  e2->e_phoff = 0;
  e2->e_phnum = 0;
  e2->e_phentsize = 0;
  e2->e_shstrndx = 0;
  e2->e_shoff = sizeof (e);

  curload += sizeof (e);

  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
						+ e.e_shnum * e.e_shentsize);
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
    {
      Elf_Shdr *s2;
      s2 = (Elf_Shdr *) curload;
      grub_memcpy (curload, s, e.e_shentsize);
      if (s == symsh)
	s2->sh_offset = sizeof (e) + e.e_shnum * e.e_shentsize;
      else if (s == strsh)
	s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
	  + sizeof (e) + e.e_shnum * e.e_shentsize;
      else
	s2->sh_offset = 0;
      s2->sh_addr = s2->sh_offset;
      curload += e.e_shentsize;
    }

  if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1)
    return grub_errno;
  if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
    {
      if (! grub_errno)
	return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
      return grub_errno;
    }
  curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t));

  if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1)
    return grub_errno;
  if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
    {
      if (! grub_errno)
	return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
      return grub_errno;
    }

  err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB, 
			   &symtab,
			   sizeof (symtab));
  if (err)
    return err;

  *kern_end = ALIGN_PAGE (symtarget + chunk_size);

  return GRUB_ERR_NONE;
}
Exemplo n.º 30
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;
}