/*
 * The core of the solution
 * Keep a break vector "breaks"
 * If breaks[i] is true, a split is needed at v[i]
 */
void print_vec(std::vector<int>& v, std::vector<bool>& breaks, int start_offset)
{
    if (start_offset < breaks.size()) {
        breaks[start_offset] = false;
        print_vec(v, breaks, start_offset + 1);
        breaks[start_offset] = true;
        print_vec(v, breaks, start_offset + 1);
    } else {
        print_segments(v, breaks);
    }
}
示例#2
0
/*
 *	Load the new kernel
 */
static int my_load(const char *type, int fileind, int argc, char **argv,
	unsigned long kexec_flags)
{
	char *kernel;
	char *kernel_buf;
	off_t kernel_size;
	int i = 0;
	int result;
	struct kexec_info info;
	int guess_only = 0;

	memset(&info, 0, sizeof(info));
	info.segment = NULL;
	info.nr_segments = 0;
	info.entry = NULL;
	info.backup_start = 0;
	info.kexec_flags = kexec_flags;

	result = 0;
	if (argc - fileind <= 0) {
		fprintf(stderr, "No kernel specified\n");
		usage();
		return -1;
	}
	kernel = argv[fileind];
	/* slurp in the input kernel */
	kernel_buf = slurp_decompress_file(kernel, &kernel_size);
#if 0
	fprintf(stderr, "kernel: %p kernel_size: %lx\n", 
		kernel_buf, kernel_size);
#endif

	if (get_memory_ranges(&info.memory_range, &info.memory_ranges,
		info.kexec_flags) < 0) {
		fprintf(stderr, "Could not get memory layout\n");
		return -1;
	}
	/* if a kernel type was specified, try to honor it */
	if (type) {
		for (i = 0; i < file_types; i++) {
			if (strcmp(type, file_type[i].name) == 0)
				break;
		}
		if (i == file_types) {
			fprintf(stderr, "Unsupported kernel type %s\n", type);
			return -1;
		} else {
			/* make sure our file is really of that type */
			if (file_type[i].probe(kernel_buf, kernel_size) < 0)
				guess_only = 1;
		}
	}
	if (!type || guess_only) {
		for (i = 0; i < file_types; i++) {
			if (file_type[i].probe(kernel_buf, kernel_size) >= 0)
				break;
		}
		if (i == file_types) {
			fprintf(stderr, "Cannot determine the file type "
					"of %s\n", kernel);
			return -1;
		} else {
			if (guess_only) {
				fprintf(stderr, "Wrong file type %s, "
					"file matches type %s\n",
					type, file_type[i].name);
				return -1;
			}
		}
	}
	if (file_type[i].load(argc, argv, kernel_buf,
			      kernel_size, &info) < 0) {
		fprintf(stderr, "Cannot load %s\n", kernel);
		return -1;
	}
	/* If we are not in native mode setup an appropriate trampoline */
	if (arch_compat_trampoline(&info) < 0) {
		return -1;
	}
	/* Verify all of the segments load to a valid location in memory */
	for (i = 0; i < info.nr_segments; i++) {
		if (!valid_memory_segment(&info, info.segment +i)) {
			fprintf(stderr, "Invalid memory segment %p - %p\n",
				info.segment[i].mem,
				((char *)info.segment[i].mem) + 
				info.segment[i].memsz);
			return -1;
		}
	}
	/* Sort the segments and verify we don't have overlaps */
	if (sort_segments(&info) < 0) {
		return -1;
	}
	/* if purgatory is loaded update it */
	update_purgatory(&info);
#if 0
	fprintf(stderr, "kexec_load: entry = %p flags = %lx\n", 
		info.entry, info.kexec_flags);
	print_segments(stderr, &info);
#endif
	result = kexec_load(
		info.entry, info.nr_segments, info.segment, info.kexec_flags);
	if (result != 0) {
		/* The load failed, print some debugging information */
		fprintf(stderr, "kexec_load failed: %s\n", 
			strerror(errno));
		fprintf(stderr, "entry       = %p flags = %lx\n", 
			info.entry, info.kexec_flags);
		print_segments(stderr, &info);
	}
	return result;
}
示例#3
0
/*! Read segments from a tsv file into a sorted minimal linked list, and write
 *
 * @param in the input file
 * @param out the output file
 */
void
merge_segments (FILE * in, FILE * out)
{
  segment s;	     /* the current working segment */
  slist_ends ends = {NULL, NULL}; /* the limits of the segment list */
  segment_link /*@null@*/ /*@dependent@*/ *c = NULL; /* pointed to segment in list being consedered */
  segment_link /*@null@*/ /*@dependent@*/ *n = NULL; /* pointed to segment after one being consedered */
  int last_field;		/* the last field in the new segment */
  bool eof_found;               /* end of file marker encounetered */

  /* If we reach the end of the input right away, exist without doing anything */
  eof_found = !read_segment(in, &s);
  if (eof_found)
    {
      return;
    }
  
  link_segment(NULL, &ends, s);

  /* Work through the remaining input lines */
  while (read_segment(in, &s))
    {
      last_field = s.field + s.nfields - 1;

      /* Find the location in the list to put the new entry. */

      /* c points to the segment after which we will add the new segment */

      /* Start from the end, because this will be faster if the input 
       * already in order.
       */
      c = ends.last;
      while (c != NULL 
	     && s.run < c->segment.run)
	c = (segment_link *) c->previous;
      while (c != NULL 
	     && s.run == c->segment.run 
	     && s.rerun < c->segment.rerun)
	c = (segment_link *) c->previous;
      while (c != NULL
	     && s.run == c->segment.run 
	     && s.rerun == c->segment.rerun 
	     && s.camcol < c->segment.camcol)
	c = (segment_link *) c->previous;
      while (c != NULL 
	     && s.run == c->segment.run 
	     && s.rerun == c->segment.rerun 
	     && s.camcol == c->segment.camcol
	     && s.field < c->segment.field)
	c = (segment_link *) c->previous;

      /* check for potential merges */
      /* See if the s can be merged with the segment that preceeds it */
      if (c != NULL 
	  && s.run == c->segment.run && s.rerun == c->segment.rerun 
	  && s.camcol == c->segment.camcol)
	{
	  /* check whether the previous segment completely includes s */
	  if (c->segment.field + c->segment.nfields - 1 >= last_field)
	    {
	      continue;
	    }
	  /* check whether we can expand the previous segment to include s */
	  if (c->segment.field + c->segment.nfields >= s.field)
	    {
	      c->segment.nfields = last_field - c->segment.field + 1;
	      continue;
	    }
	}
      
      /* See if s can be merged by the segment that follows it */
      n = c == NULL ? ends.first : (segment_link *) c->next; 
      if (n != NULL 
	  && s.run == n->segment.run && s.rerun == n->segment.rerun 
	  && s.camcol == n->segment.camcol)
	{
	  /* check whether s overlaps the next one */
	  if (last_field >= n->segment.field - 1)
	    {
	      last_field = n->segment.field + n->segment.nfields - 1 > last_field
		? n->segment.field + n->segment.nfields - 1: last_field;
	      n->segment.field = s.field;
	      n->segment.nfields = last_field - n->segment.field + 1;
	      continue;
	    }
	}

      link_segment(c, &ends, s);

      /* print_segments(ends.first, stderr); */
      
    }

  print_segments(ends.first, out);
  fflush(out);

  free_segment_link (ends.first);
  
}