/* * 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); } }
/* * 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; }
/*! 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); }