/* bsdlabel.c - Read BSD style partition tables.  */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2002,2004,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/partition.h>
#include <grub/bsdlabel.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/msdos_partition.h>
#include <grub/i18n.h>

GRUB_MOD_LICENSE ("GPLv3+");

#ifdef GRUB_UTIL
#include <grub/emu/misc.h>
#endif

static struct grub_partition_map grub_bsdlabel_partition_map;
static struct grub_partition_map grub_netbsdlabel_partition_map;
static struct grub_partition_map grub_openbsdlabel_partition_map;



static grub_err_t
iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
	      struct grub_partition_map *pmap,
	      grub_partition_iterate_hook_t hook, void *hook_data)
{
  struct grub_partition_bsd_disk_label label;
  struct grub_partition p;
  grub_disk_addr_t delta = 0;
  grub_disk_addr_t pos;

  /* Read the BSD label.  */
  if (grub_disk_read (disk, sector, 0, sizeof (label), &label))
    return grub_errno;

  /* Check if it is valid.  */
  if (label.magic != grub_cpu_to_le32_compile_time (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");

  /* A kludge to determine a base of be.offset.  */
  if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION
      < grub_cpu_to_le16 (label.num_partitions) && freebsd)
    {
      struct grub_partition_bsd_entry whole_disk_be;

      pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE
	+ sizeof (struct grub_partition_bsd_entry)
	* GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION;

      if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE,
			  pos % GRUB_DISK_SECTOR_SIZE, sizeof (whole_disk_be),
			  &whole_disk_be))
	return grub_errno;

      delta = grub_le_to_cpu32 (whole_disk_be.offset);
    }

  pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE;

  for (p.number = 0;
       p.number < grub_cpu_to_le16 (label.num_partitions);
       p.number++, pos += sizeof (struct grub_partition_bsd_entry))
    {
      struct grub_partition_bsd_entry be;

      if (p.number == GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION)
	continue;

      p.offset = pos / GRUB_DISK_SECTOR_SIZE;
      p.index = pos % GRUB_DISK_SECTOR_SIZE;

      if (grub_disk_read (disk, p.offset, p.index, sizeof (be),  &be))
	return grub_errno;

      p.start = grub_le_to_cpu32 (be.offset);
      p.len = grub_le_to_cpu32 (be.size);
      p.partmap = pmap;

      if (p.len == 0)
	continue;

      if (p.start < delta)
	{
#ifdef GRUB_UTIL
	  char *partname;
	  /* disk->partition != NULL as 0 < delta */
	  partname = disk->partition ? grub_partition_get_name (disk->partition)
	    : 0;
	  grub_util_warn (_("Discarding improperly nested partition (%s,%s,%s%d)"),
			  disk->name, partname ? : "", p.partmap->name,
			  p.number + 1);
	  grub_free (partname);
#endif
	  continue;
	}

      p.start -= delta;

      if (hook (disk, &p, hook_data))
	return grub_errno;
    }
  return GRUB_ERR_NONE;
}

static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
				grub_partition_iterate_hook_t hook,
				void *hook_data)
{

  if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
      == 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD)
    return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1,
			 &grub_bsdlabel_partition_map, hook, hook_data);

  if (disk->partition 
      && (grub_strcmp (disk->partition->partmap->name, "msdos") == 0
	  || disk->partition->partmap == &grub_bsdlabel_partition_map
	  || disk->partition->partmap == &grub_netbsdlabel_partition_map
	  || disk->partition->partmap == &grub_openbsdlabel_partition_map))
      return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");

  return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, 
		       &grub_bsdlabel_partition_map, hook, hook_data);
}

/* Context for netopenbsdlabel_partition_map_iterate.  */
struct netopenbsdlabel_ctx
{
  grub_uint8_t type;
  struct grub_partition_map *pmap;
  grub_partition_iterate_hook_t hook;
  void *hook_data;
  int count;
};

/* Helper for netopenbsdlabel_partition_map_iterate.  */
static int
check_msdos (grub_disk_t dsk, const grub_partition_t partition, void *data)
{
  struct netopenbsdlabel_ctx *ctx = data;
  grub_err_t err;

  if (partition->msdostype != ctx->type)
    return 0;

  err = iterate_real (dsk, partition->start
		      + GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, ctx->pmap,
		      ctx->hook, ctx->hook_data);
  if (err == GRUB_ERR_NONE)
    {
      ctx->count++;
      return 1;
    }
  if (err == GRUB_ERR_BAD_PART_TABLE)
    {
      grub_errno = GRUB_ERR_NONE;
      return 0;
    }
  grub_print_error ();
  return 0;
}

/* This is a total breakage. Even when net-/openbsd label is inside partition
   it actually describes the whole disk.
 */
static grub_err_t
netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type,
				       struct grub_partition_map *pmap,
				       grub_partition_iterate_hook_t hook,
				       void *hook_data)
{
  if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
      == 0)
    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");

  {
    struct netopenbsdlabel_ctx ctx = {
      .type = type,
      .pmap = pmap,
      .hook = hook,
      .hook_data = hook_data,
      .count = 0
    };
    grub_err_t err;

    err = grub_partition_msdos_iterate (disk, check_msdos, &ctx);

    if (err)
      return err;
    if (!ctx.count)
      return grub_error (GRUB_ERR_BAD_PART_TABLE, "no bsdlabel found");
  }
  return GRUB_ERR_NONE;
}

static grub_err_t
netbsdlabel_partition_map_iterate (grub_disk_t disk,
				   grub_partition_iterate_hook_t hook,
				   void *hook_data)
{
  return netopenbsdlabel_partition_map_iterate (disk,
						GRUB_PC_PARTITION_TYPE_NETBSD,
						&grub_netbsdlabel_partition_map,
						hook, hook_data);
}

static grub_err_t
openbsdlabel_partition_map_iterate (grub_disk_t disk,
				    grub_partition_iterate_hook_t hook,
				    void *hook_data)
{
  return netopenbsdlabel_partition_map_iterate (disk,
						GRUB_PC_PARTITION_TYPE_OPENBSD,
						&grub_openbsdlabel_partition_map,
						hook, hook_data);
}


static struct grub_partition_map grub_bsdlabel_partition_map =
  {
    .name = "bsd",
    .iterate = bsdlabel_partition_map_iterate,
  };

static struct grub_partition_map grub_openbsdlabel_partition_map =
  {
    .name = "openbsd",
    .iterate = openbsdlabel_partition_map_iterate,
  };

static struct grub_partition_map grub_netbsdlabel_partition_map =
  {
    .name = "netbsd",
    .iterate = netbsdlabel_partition_map_iterate,
  };



GRUB_MOD_INIT(part_bsd)
{
  grub_partition_map_register (&grub_bsdlabel_partition_map);
  grub_partition_map_register (&grub_netbsdlabel_partition_map);
  grub_partition_map_register (&grub_openbsdlabel_partition_map);
}

GRUB_MOD_FINI(part_bsd)
{
  grub_partition_map_unregister (&grub_bsdlabel_partition_map);
  grub_partition_map_unregister (&grub_netbsdlabel_partition_map);
  grub_partition_map_unregister (&grub_openbsdlabel_partition_map);
}
