| /* * Load the new kernel */ static int my_load(const char *type, int fileind, int argc, char **argv, unsigned long kexec_flags, void *entry)//****************** {
char *kernel; char *kernel_buf; off_t kernel_size; int i = 0; int result; struct kexec_info info;//1.注意这个结构体 long native_arch; 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);//kernel_buf中含有解压缩的内核 #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 */ /* 此处用到的变量file_type的结构体 struct file_type {
const char *name; probe_t *probe; load_t *load; usage_t *usage; };//类似指定回调函数 struct file_type file_type[] = {
{ "multiboot-x86", multiboot_x86_probe, multiboot_x86_load, multiboot_x86_usage }, { "elf-x86", elf_x86_probe, elf_x86_load, elf_x86_usage }, { "bzImage", bzImage_probe, bzImage_load, bzImage_usage }, { "beoboot-x86", beoboot_probe, beoboot_load, beoboot_usage }, { "nbi-x86", nbi_probe, nbi_load, nbi_usage }, }; */ 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) {
//===========>trap into elf_x86_load fprintf(stderr, "Cannot load %s\n", kernel); return -1; } /* If we are not in native mode setup an appropriate trampoline */ native_arch = physical_arch(); if (native_arch < 0) {
return -1; } info.kexec_flags |= native_arch; if (arch_compat_trampoline(&info) < 0) {
return -1; } if (info.kexec_flags & KEXEC_PRESERVE_CONTEXT) {
add_backup_segments(&info, mem_min, mem_max - mem_min + 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);//这个对新内核做下hash来进行完整性检测,,并将前640k保留起来(没仔细看,根据kdump相关资料猜得,可能有误,以后确认) if (entry) info.entry = entry; #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; } |