/* Parts of target interface that deal with accessing memory and memory-like
   objects.

   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.

   This file is part of GDB.

   This program 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.

   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "vec.h"
#include "target.h"
#include "memory-map.h"

#include "gdb_assert.h"

#include <stdio.h>
#include <sys/time.h>

static int
compare_block_starting_address (const void *a, const void *b)
{
  const struct memory_write_request *a_req = a;
  const struct memory_write_request *b_req = b;

  if (a_req->begin < b_req->begin)
    return -1;
  else if (a_req->begin == b_req->begin)
    return 0;
  else
    return 1;
}

/* Adds to RESULT all memory write requests from BLOCK that are
   in [BEGIN, END) range.

   If any memory request is only partially in the specified range,
   that part of the memory request will be added.  */

static void
claim_memory (VEC(memory_write_request_s) *blocks,
	      VEC(memory_write_request_s) **result,
	      ULONGEST begin,
	      ULONGEST end)
{
  int i;
  ULONGEST claimed_begin;
  ULONGEST claimed_end;
  struct memory_write_request *r;

  for (i = 0; VEC_iterate (memory_write_request_s, blocks, i, r); ++i)
    {
      /* If the request doesn't overlap [BEGIN, END), skip it.  We
	 must handle END == 0 meaning the top of memory; we don't yet
	 check for R->end == 0, which would also mean the top of
	 memory, but there's an assertion in
	 target_write_memory_blocks which checks for that.  */

      if (begin >= r->end)
	continue;
      if (end != 0 && end <= r->begin)
	continue;

      claimed_begin = max (begin, r->begin);
      if (end == 0)
	claimed_end = r->end;
      else
	claimed_end = min (end, r->end);

      if (claimed_begin == r->begin && claimed_end == r->end)
	VEC_safe_push (memory_write_request_s, *result, r);
      else
	{
	  struct memory_write_request *n =
	    VEC_safe_push (memory_write_request_s, *result, NULL);

	  *n = *r;
	  n->begin = claimed_begin;
	  n->end = claimed_end;
	  n->data += claimed_begin - r->begin;
	}
    }
}

/* Given a vector of struct memory_write_request objects in BLOCKS,
   add memory requests for flash memory into FLASH_BLOCKS, and for
   regular memory to REGULAR_BLOCKS.  */

static void
split_regular_and_flash_blocks (VEC(memory_write_request_s) *blocks,
				VEC(memory_write_request_s) **regular_blocks,
				VEC(memory_write_request_s) **flash_blocks)
{
  struct mem_region *region;
  CORE_ADDR cur_address;

  /* This implementation runs in O(length(regions)*length(blocks)) time.
     However, in most cases the number of blocks will be small, so this does
     not matter.

     Note also that it's extremely unlikely that a memory write request
     will span more than one memory region, however for safety we handle
     such situations.  */

  cur_address = 0;
  while (1)
    {
      VEC(memory_write_request_s) **r;

      region = lookup_mem_region (cur_address);
      r = region->attrib.mode == MEM_FLASH ? flash_blocks : regular_blocks;
      cur_address = region->hi;
      claim_memory (blocks, r, region->lo, region->hi);

      if (cur_address == 0)
	break;
    }
}

/* Given an ADDRESS, if BEGIN is non-NULL this function sets *BEGIN
   to the start of the flash block containing the address.  Similarly,
   if END is non-NULL *END will be set to the address one past the end
   of the block containing the address.  */

static void
block_boundaries (CORE_ADDR address, CORE_ADDR *begin, CORE_ADDR *end)
{
  struct mem_region *region;
  unsigned blocksize;

  region = lookup_mem_region (address);
  gdb_assert (region->attrib.mode == MEM_FLASH);
  blocksize = region->attrib.blocksize;
  if (begin)
    *begin = address / blocksize * blocksize;
  if (end)
    *end = (address + blocksize - 1) / blocksize * blocksize;
}

/* Given the list of memory requests to be WRITTEN, this function
   returns write requests covering each group of flash blocks which must
   be erased.  */

static VEC(memory_write_request_s) *
blocks_to_erase (VEC(memory_write_request_s) *written)
{
  unsigned i;
  struct memory_write_request *ptr;

  VEC(memory_write_request_s) *result = NULL;

  for (i = 0; VEC_iterate (memory_write_request_s, written, i, ptr); ++i)
    {
      CORE_ADDR begin, end;

      block_boundaries (ptr->begin, &begin, 0);
      block_boundaries (ptr->end - 1, 0, &end);

      if (!VEC_empty (memory_write_request_s, result)
	  && VEC_last (memory_write_request_s, result)->end >= begin)
	{
	  VEC_last (memory_write_request_s, result)->end = end;
	}
      else
	{
	  struct memory_write_request *n =
	    VEC_safe_push (memory_write_request_s, result, NULL);

	  memset (n, 0, sizeof (struct memory_write_request));
	  n->begin = begin;
	  n->end = end;
	}
    }

  return result;
}

/* Given ERASED_BLOCKS, a list of blocks that will be erased with
   flash erase commands, and WRITTEN_BLOCKS, the list of memory
   addresses that will be written, compute the set of memory addresses
   that will be erased but not rewritten (e.g. padding within a block
   which is only partially filled by "load").  */

static VEC(memory_write_request_s) *
compute_garbled_blocks (VEC(memory_write_request_s) *erased_blocks,
			VEC(memory_write_request_s) *written_blocks)
{
  VEC(memory_write_request_s) *result = NULL;

  unsigned i, j;
  unsigned je = VEC_length (memory_write_request_s, written_blocks);
  struct memory_write_request *erased_p;

  /* Look at each erased memory_write_request in turn, and
     see what part of it is subsequently written to.

     This implementation is O(length(erased) * length(written)).  If
     the lists are sorted at this point it could be rewritten more
     efficiently, but the complexity is not generally worthwhile.  */

  for (i = 0;
       VEC_iterate (memory_write_request_s, erased_blocks, i, erased_p);
       ++i)
    {
      /* Make a deep copy -- it will be modified inside the loop, but
	 we don't want to modify original vector.  */
      struct memory_write_request erased = *erased_p;

      for (j = 0; j != je;)
	{
	  struct memory_write_request *written
	    = VEC_index (memory_write_request_s,
			 written_blocks, j);

	  /* Now try various cases.  */

	  /* If WRITTEN is fully to the left of ERASED, check the next
	     written memory_write_request.  */
	  if (written->end <= erased.begin)
	    {
	      ++j;
	      continue;
	    }

	  /* If WRITTEN is fully to the right of ERASED, then ERASED
	     is not written at all.  WRITTEN might affect other
	     blocks.  */
	  if (written->begin >= erased.end)
	    {
	      VEC_safe_push (memory_write_request_s, result, &erased);
	      goto next_erased;
	    }

	  /* If all of ERASED is completely written, we can move on to
	     the next erased region.  */
	  if (written->begin <= erased.begin
	      && written->end >= erased.end)
	    {
	      goto next_erased;
	    }

	  /* If there is an unwritten part at the beginning of ERASED,
	     then we should record that part and try this inner loop
	     again for the remainder.  */
	  if (written->begin > erased.begin)
	    {
	      struct memory_write_request *n =
		VEC_safe_push (memory_write_request_s, result, NULL);

	      memset (n, 0, sizeof (struct memory_write_request));
	      n->begin = erased.begin;
	      n->end = written->begin;
	      erased.begin = written->begin;
	      continue;
	    }

	  /* If there is an unwritten part at the end of ERASED, we
	     forget about the part that was written to and wait to see
	     if the next write request writes more of ERASED.  We can't
	     push it yet.  */
	  if (written->end < erased.end)
	    {
	      erased.begin = written->end;
	      ++j;
	      continue;
	    }
	}

      /* If we ran out of write requests without doing anything about
	 ERASED, then that means it's really erased.  */
      VEC_safe_push (memory_write_request_s, result, &erased);

    next_erased:
      ;
    }

  return result;
}

static void
cleanup_request_data (void *p)
{
  VEC(memory_write_request_s) **v = p;
  struct memory_write_request *r;
  int i;

  for (i = 0; VEC_iterate (memory_write_request_s, *v, i, r); ++i)
    xfree (r->data);
}

static void
cleanup_write_requests_vector (void *p)
{
  VEC(memory_write_request_s) **v = p;

  VEC_free (memory_write_request_s, *v);
}

int
target_write_memory_blocks (VEC(memory_write_request_s) *requests,
			    enum flash_preserve_mode preserve_flash_p,
			    void (*progress_cb) (ULONGEST, void *))
{
  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
  VEC(memory_write_request_s) *blocks = VEC_copy (memory_write_request_s,
						  requests);
  unsigned i;
  int err = 0;
  struct memory_write_request *r;
  VEC(memory_write_request_s) *regular = NULL;
  VEC(memory_write_request_s) *flash = NULL;
  VEC(memory_write_request_s) *erased, *garbled;

  /* END == 0 would represent wraparound: a write to the very last
     byte of the address space.  This file was not written with that
     possibility in mind.  This is fixable, but a lot of work for a
     rare problem; so for now, fail noisily here instead of obscurely
     later.  */
  for (i = 0; VEC_iterate (memory_write_request_s, requests, i, r); ++i)
    gdb_assert (r->end != 0);

  make_cleanup (cleanup_write_requests_vector, &blocks);

  /* Sort the blocks by their start address.  */
  qsort (VEC_address (memory_write_request_s, blocks),
	 VEC_length (memory_write_request_s, blocks),
	 sizeof (struct memory_write_request), compare_block_starting_address);

  /* Split blocks into list of regular memory blocks,
     and list of flash memory blocks. */
  make_cleanup (cleanup_write_requests_vector, &regular);
  make_cleanup (cleanup_write_requests_vector, &flash);
  split_regular_and_flash_blocks (blocks, &regular, &flash);

  /* If a variable is added to forbid flash write, even during "load",
     it should be checked here.  Similarly, if this function is used
     for other situations besides "load" in which writing to flash
     is undesirable, that should be checked here.  */

  /* Find flash blocks to erase.  */
  erased = blocks_to_erase (flash);
  make_cleanup (cleanup_write_requests_vector, &erased);

  /* Find what flash regions will be erased, and not overwritten; then
     either preserve or discard the old contents.  */
  garbled = compute_garbled_blocks (erased, flash);
  make_cleanup (cleanup_request_data, &garbled);
  make_cleanup (cleanup_write_requests_vector, &garbled);

  if (!VEC_empty (memory_write_request_s, garbled))
    {
      if (preserve_flash_p == flash_preserve)
	{
	  struct memory_write_request *r;

	  /* Read in regions that must be preserved and add them to
	     the list of blocks we read.  */
	  for (i = 0; VEC_iterate (memory_write_request_s, garbled, i, r); ++i)
	    {
	      gdb_assert (r->data == NULL);
	      r->data = xmalloc (r->end - r->begin);
	      err = target_read_memory (r->begin, r->data, r->end - r->begin);
	      if (err != 0)
		goto out;

	      VEC_safe_push (memory_write_request_s, flash, r);
	    }

	  qsort (VEC_address (memory_write_request_s, flash),
		 VEC_length (memory_write_request_s, flash),
		 sizeof (struct memory_write_request), compare_block_starting_address);
	}
    }

  /* We could coalesce adjacent memory blocks here, to reduce the
     number of write requests for small sections.  However, we would
     have to reallocate and copy the data pointers, which could be
     large; large sections are more common in loadable objects than
     large numbers of small sections (although the reverse can be true
     in object files).  So, we issue at least one write request per
     passed struct memory_write_request.  The remote stub will still
     have the opportunity to batch flash requests.  */

  /* Write regular blocks.  */
  for (i = 0; VEC_iterate (memory_write_request_s, regular, i, r); ++i)
    {
      LONGEST len;

      len = target_write_with_progress (current_target.beneath,
					TARGET_OBJECT_MEMORY, NULL,
					r->data, r->begin, r->end - r->begin,
					progress_cb, r->baton);
      if (len < (LONGEST) (r->end - r->begin))
	{
	  /* Call error?  */
	  err = -1;
	  goto out;
	}
    }

  if (!VEC_empty (memory_write_request_s, erased))
    {
      /* Erase all pages.  */
      for (i = 0; VEC_iterate (memory_write_request_s, erased, i, r); ++i)
	target_flash_erase (r->begin, r->end - r->begin);

      /* Write flash data.  */
      for (i = 0; VEC_iterate (memory_write_request_s, flash, i, r); ++i)
	{
	  LONGEST len;

	  len = target_write_with_progress (&current_target,
					    TARGET_OBJECT_FLASH, NULL,
					    r->data, r->begin, r->end - r->begin,
					    progress_cb, r->baton);
	  if (len < (LONGEST) (r->end - r->begin))
	    error (_("Error writing data to flash"));
	}

      target_flash_done ();
    }

 out:
  do_cleanups (back_to);

  return err;
}
