diff options
Diffstat (limited to 'package')
| -rw-r--r-- | package/kexec-tools/Makefile | 2 | ||||
| -rw-r--r-- | package/kexec-tools/patches/0005-mips64_support.patch | 732 | 
2 files changed, 733 insertions, 1 deletions
diff --git a/package/kexec-tools/Makefile b/package/kexec-tools/Makefile index e7fcb6728..d350bb2c8 100644 --- a/package/kexec-tools/Makefile +++ b/package/kexec-tools/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk  PKG_NAME:=kexec-tools  PKG_VERSION:=2.0.1 -PKG_RELEASE:=2 +PKG_RELEASE:=3  PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2  PKG_SOURCE_URL:=@KERNEL/linux/kernel/people/horms/kexec-tools diff --git a/package/kexec-tools/patches/0005-mips64_support.patch b/package/kexec-tools/patches/0005-mips64_support.patch new file mode 100644 index 000000000..6b53eace4 --- /dev/null +++ b/package/kexec-tools/patches/0005-mips64_support.patch @@ -0,0 +1,732 @@ +Index: kexec-tools-2.0.1/kexec/arch/mips/Makefile +=================================================================== +--- kexec-tools-2.0.1.orig/kexec/arch/mips/Makefile	2008-07-15 02:46:43.000000000 +0200 ++++ kexec-tools-2.0.1/kexec/arch/mips/Makefile	2009-09-27 19:07:26.000000000 +0200 +@@ -4,7 +4,7 @@ + mips_KEXEC_SRCS =  kexec/arch/mips/kexec-mips.c + mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-mips.c + mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-rel-mips.c +-mips_KEXEC_SRCS += kexec/arch/mips/mips-setup-simple.S ++mips_KEXEC_SRCS += kexec/arch/mips/crashdump-mips.c +  + mips_ADD_BUFFER = + mips_ADD_SEGMENT = +Index: kexec-tools-2.0.1/kexec/arch/mips/crashdump-mips.c +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.1/kexec/arch/mips/crashdump-mips.c	2009-09-27 19:07:26.000000000 +0200 +@@ -0,0 +1,371 @@ ++/* ++ * kexec: Linux boots Linux ++ * ++ * 2005 (C) IBM Corporation. ++ * 2008 (C) MontaVista Software, Inc. ++ * ++ * 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 (version 2 of the License). ++ * ++ * 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, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++#include <stdio.h> ++#include <string.h> ++#include <stdlib.h> ++#include <errno.h> ++#include <elf.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <unistd.h> ++#include "../../kexec.h" ++#include "../../kexec-elf.h" ++#include "../../kexec-syscall.h" ++#include "../../crashdump.h" ++#include "kexec-mips.h" ++#include "crashdump-mips.h" ++ ++extern struct arch_options_t arch_options; ++ ++/* Stores a sorted list of RAM memory ranges for which to create elf headers. ++ * A separate program header is created for backup region */ ++static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; ++ ++/* Memory region reserved for storing panic kernel and other data. */ ++static struct memory_range crash_reserved_mem; ++ ++/* ++ * To store the memory size of the first kernel and this value will be ++ * passed to the second kernel as command line (savemaxmem=xM). ++ * The second kernel will be calculated saved_max_pfn based on this ++ * variable. ++ */ ++unsigned long long saved_max_mem = 0; ++ ++/* Removes crash reserve region from list of memory chunks for whom elf program ++ * headers have to be created. Assuming crash reserve region to be a single ++ * continuous area fully contained inside one of the memory chunks */ ++static int exclude_crash_reserve_region(int *nr_ranges) ++{ ++    int i, j, tidx = -1; ++    unsigned long long cstart, cend; ++    struct memory_range temp_region; ++ ++    /* Crash reserved region. */ ++    cstart = crash_reserved_mem.start; ++    cend = crash_reserved_mem.end; ++ ++    for (i = 0; i < (*nr_ranges); i++) { ++        unsigned long long mstart, mend; ++        mstart = crash_memory_range[i].start; ++        mend = crash_memory_range[i].end; ++        if (cstart < mend && cend > mstart) { ++            if (cstart != mstart && cend != mend) { ++                /* Split memory region */ ++                crash_memory_range[i].end = cstart - 1; ++                temp_region.start = cend + 1; ++                temp_region.end = mend; ++                temp_region.type = RANGE_RAM; ++                tidx = i+1; ++            } else if (cstart != mstart) ++                crash_memory_range[i].end = cstart - 1; ++            else ++                crash_memory_range[i].start = cend + 1; ++        } ++    } ++    /* Insert split memory region, if any. */ ++    if (tidx >= 0) { ++        if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) { ++            /* No space to insert another element. */ ++            fprintf(stderr, "Error: Number of crash memory ranges" ++                    " excedeed the max limit\n"); ++            return -1; ++        } ++        for (j = (*nr_ranges - 1); j >= tidx; j--) ++            crash_memory_range[j+1] = crash_memory_range[j]; ++        crash_memory_range[tidx].start = temp_region.start; ++        crash_memory_range[tidx].end = temp_region.end; ++        crash_memory_range[tidx].type = temp_region.type; ++        (*nr_ranges)++; ++    } ++    return 0; ++} ++/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to ++ * create Elf headers. Keeping it separate from get_memory_ranges() as ++ * requirements are different in the case of normal kexec and crashdumps. ++ * ++ * Normal kexec needs to look at all of available physical memory irrespective ++ * of the fact how much of it is being used by currently running kernel. ++ * Crashdumps need to have access to memory regions actually being used by ++ * running  kernel. Expecting a different file/data structure than /proc/iomem ++ * to look into down the line. May be something like /proc/kernelmem or may ++ * be zone data structures exported from kernel. ++ */ ++static int get_crash_memory_ranges(struct memory_range **range, int *ranges) ++{ ++    const char iomem[]= "/proc/iomem"; ++    int i, memory_ranges = 0; ++    char line[MAX_LINE]; ++    FILE *fp; ++    unsigned long long start, end; ++ ++    fp = fopen(iomem, "r"); ++    if (!fp) { ++        fprintf(stderr, "Cannot open %s: %s\n", ++            iomem, strerror(errno)); ++        return -1; ++    } ++ ++    /* Separate segment for backup region */ ++    crash_memory_range[0].start = BACKUP_SRC_START; ++    crash_memory_range[0].end = BACKUP_SRC_END; ++    crash_memory_range[0].type = RANGE_RAM; ++    memory_ranges++; ++ ++    while(fgets(line, sizeof(line), fp) != 0) { ++        char *str; ++        int type, consumed, count; ++        if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) ++            break; ++        count = sscanf(line, "%Lx-%Lx : %n", ++            &start, &end, &consumed); ++        if (count != 2) ++            continue; ++        str = line + consumed; ++ ++        /* Only Dumping memory of type System RAM. */ ++        if (memcmp(str, "System RAM\n", 11) == 0) { ++            type = RANGE_RAM; ++        } else if (memcmp(str, "Crash kernel\n", 13) == 0) { ++                /* Reserved memory region. New kernel can ++                 * use this region to boot into. */ ++                crash_reserved_mem.start = start; ++                crash_reserved_mem.end = end; ++                crash_reserved_mem.type = RANGE_RAM; ++                continue; ++        } else { ++            continue; ++        } ++ ++        if (start == BACKUP_SRC_START && end >= (BACKUP_SRC_END + 1)) ++            start = BACKUP_SRC_END + 1; ++ ++        crash_memory_range[memory_ranges].start = start; ++        crash_memory_range[memory_ranges].end = end; ++        crash_memory_range[memory_ranges].type = type; ++        memory_ranges++; ++ ++        /* Segregate linearly mapped region. */ ++        if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) { ++            crash_memory_range[memory_ranges-1].end = MAXMEM -1; ++ ++            /* Add segregated region. */ ++            crash_memory_range[memory_ranges].start = MAXMEM; ++            crash_memory_range[memory_ranges].end = end; ++            crash_memory_range[memory_ranges].type = type; ++            memory_ranges++; ++        } ++    } ++    fclose(fp); ++ ++    if (exclude_crash_reserve_region(&memory_ranges) < 0) ++        return -1; ++ ++    for (i = 0; i < memory_ranges; i++) ++        if (saved_max_mem < crash_memory_range[i].end) ++            saved_max_mem = crash_memory_range[i].end + 1; ++ ++    *range = crash_memory_range; ++    *ranges = memory_ranges; ++    return 0; ++} ++ ++/* Converts unsigned long to ascii string. */ ++static void ultoa(unsigned long i, char *str) ++{ ++    int j = 0, k; ++    char tmp; ++ ++    do { ++        str[j++] = i % 10 + '0'; ++    } while ((i /=10) > 0); ++    str[j] = '\0'; ++ ++    /* Reverse the string. */ ++    for (j = 0, k = strlen(str) - 1; j < k; j++, k--) { ++        tmp = str[k]; ++        str[k] = str[j]; ++        str[j] = tmp; ++    } ++} ++ ++/* Adds the appropriate mem= options to command line, indicating the ++ * memory region the new kernel can use to boot into. */ ++static int cmdline_add_mem(char *cmdline, unsigned long addr, unsigned long size) ++{ ++    int cmdlen, len; ++    char str[50], *ptr; ++ ++    addr = addr/1024; ++    size = size/1024; ++    ptr = str; ++    strcpy (str, " mem="); ++    ptr += strlen(str); ++    ultoa(size, ptr); ++    strcat (str, "K@"); ++    ptr = str + strlen(str); ++    ultoa(addr, ptr); ++    strcat (str, "K"); ++    len = strlen(str); ++    cmdlen = strlen(cmdline) + len; ++    if (cmdlen > (COMMAND_LINE_SIZE - 1)) ++        die("Command line overflow\n"); ++    strcat(cmdline, str); ++ ++    return 0; ++} ++ ++/* Adds the elfcorehdr= command line parameter to command line. */ ++static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr) ++{ ++    int cmdlen, len, align = 1024; ++    char str[30], *ptr; ++ ++    /* Passing in elfcorehdr=xxxK format. Saves space required in cmdline. ++     * Ensure 1K alignment*/ ++    if (addr%align) ++        return -1; ++    addr = addr/align; ++    ptr = str; ++    strcpy(str, " elfcorehdr="); ++    ptr += strlen(str); ++    ultoa(addr, ptr); ++    strcat(str, "K"); ++    len = strlen(str); ++    cmdlen = strlen(cmdline) + len; ++    if (cmdlen > (COMMAND_LINE_SIZE - 1)) ++        die("Command line overflow\n"); ++    strcat(cmdline, str); ++    return 0; ++} ++ ++/* Adds the elfcorehdr= command line parameter to command line. */ ++static int cmdline_add_savemaxmem(char *cmdline, unsigned long addr) ++{ ++    int cmdlen, len, align = 1024; ++    char str[30], *ptr; ++ ++    /* Passing in savemaxmem=xxxM format. Saves space required in cmdline.*/ ++    addr = addr/(align*align); ++    ptr = str; ++    strcpy(str, " savemaxmem="); ++    ptr += strlen(str); ++    ultoa(addr, ptr); ++    strcat(str, "M"); ++    len = strlen(str); ++    cmdlen = strlen(cmdline) + len; ++    if (cmdlen > (COMMAND_LINE_SIZE - 1)) ++        die("Command line overflow\n"); ++    strcat(cmdline, str); ++    return 0; ++} ++ ++#ifdef __mips64 ++static struct crash_elf_info elf_info64 = ++{ ++    class: ELFCLASS64, ++    data: ELFDATA2MSB, ++    machine: EM_MIPS, ++    backup_src_start: BACKUP_SRC_START, ++    backup_src_end: BACKUP_SRC_END, ++    page_offset: PAGE_OFFSET, ++    lowmem_limit: MAXMEM, ++}; ++#endif ++static struct crash_elf_info elf_info32 = ++{ ++    class: ELFCLASS32, ++    data: ELFDATA2MSB, ++    machine: EM_MIPS, ++    backup_src_start: BACKUP_SRC_START, ++    backup_src_end: BACKUP_SRC_END, ++    page_offset: PAGE_OFFSET, ++    lowmem_limit: MAXMEM, ++}; ++ ++/* Loads additional segments in case of a panic kernel is being loaded. ++ * One segment for backup region, another segment for storing elf headers ++ * for crash memory image. ++ */ ++int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, ++                unsigned long max_addr, unsigned long min_base) ++{ ++    void *tmp; ++    unsigned long sz, elfcorehdr; ++    int nr_ranges, align = 1024; ++    struct memory_range *mem_range; ++ ++    if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0) ++        return -1; ++ ++    /* Create a backup region segment to store backup data*/ ++    sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1); ++    tmp = xmalloc(sz); ++    memset(tmp, 0, sz); ++    info->backup_start = add_buffer(info, tmp, sz, sz, align, ++                crash_reserved_mem.start, ++                crash_reserved_mem.end,-1); ++ ++#ifdef __mips64 ++    /* Create elf header segment and store crash image data. */ ++    if (arch_options.core_header_type == CORE_TYPE_ELF64) { ++        if (crash_create_elf64_headers(info, &elf_info64, ++                           crash_memory_range, nr_ranges, ++                           &tmp, &sz, ++                           ELF_CORE_HEADER_ALIGN) < 0) ++            return -1; ++    } ++    else { ++        if (crash_create_elf32_headers(info, &elf_info32, ++                           crash_memory_range, nr_ranges, ++                           &tmp, &sz, ++                           ELF_CORE_HEADER_ALIGN) < 0) ++            return -1; ++    } ++#else ++    if (crash_create_elf32_headers(info, &elf_info32, ++                   crash_memory_range, nr_ranges, ++                   &tmp, &sz, ++                   ELF_CORE_HEADER_ALIGN) < 0) ++        return -1; ++#endif ++    elfcorehdr = add_buffer(info, tmp, sz, sz, align, ++                crash_reserved_mem.start, ++                crash_reserved_mem.end, -1); ++ ++    /* ++     * backup segment is after elfcorehdr, so use elfcorehdr as top of ++     * kernel's available memory ++     */ ++    cmdline_add_mem(mod_cmdline, crash_reserved_mem.start, ++        elfcorehdr - crash_reserved_mem.start); ++    cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); ++    cmdline_add_savemaxmem(mod_cmdline, saved_max_mem); ++    return 0; ++} ++ ++int is_crashkernel_mem_reserved(void) ++{ ++    uint64_t start, end; ++ ++    return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ? ++      (start != end) : 0; ++} ++ +Index: kexec-tools-2.0.1/kexec/arch/mips/crashdump-mips.h +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.1/kexec/arch/mips/crashdump-mips.h	2009-09-27 19:07:26.000000000 +0200 +@@ -0,0 +1,26 @@ ++#ifndef CRASHDUMP_MIPS_H ++#define CRASHDUMP_MIPS_H ++ ++struct kexec_info; ++int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, ++                unsigned long max_addr, unsigned long min_base); ++#ifdef __mips64 ++#define PAGE_OFFSET    0xa800000000000000ULL ++#else ++#define PAGE_OFFSET    0x80000000 ++#endif ++#define __pa(x)        ((unsigned long)(X)& 0x7fffffff) ++ ++#define MAXMEM        0x80000000 ++ ++#define CRASH_MAX_MEMMAP_NR    (KEXEC_MAX_SEGMENTS + 1) ++#define CRASH_MAX_MEMORY_RANGES    (MAX_MEMORY_RANGES + 2) ++ ++#define COMMAND_LINE_SIZE    512 ++ ++/* Backup Region, First 1M of System RAM. */ ++#define BACKUP_SRC_START    0x00000000 ++#define BACKUP_SRC_END        0x000fffff ++#define BACKUP_SRC_SIZE    (BACKUP_SRC_END - BACKUP_SRC_START + 1) ++ ++#endif /* CRASHDUMP_MIPS_H */ +Index: kexec-tools-2.0.1/kexec/arch/mips/include/arch/options.h +=================================================================== +--- kexec-tools-2.0.1.orig/kexec/arch/mips/include/arch/options.h	2008-07-15 02:46:43.000000000 +0200 ++++ kexec-tools-2.0.1/kexec/arch/mips/include/arch/options.h	2009-09-27 19:18:21.000000000 +0200 +@@ -2,10 +2,21 @@ + #define KEXEC_ARCH_MIPS_OPTIONS_H +  + #define OPT_ARCH_MAX   (OPT_MAX+0) ++#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" +  ++#ifdef __mips64 ++#define OPT_ELF64_CORE	(OPT_MAX+1) + #define KEXEC_ARCH_OPTIONS \ + 	KEXEC_OPTIONS \ ++	{ "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \ +  + #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" ++#define OPT_ARCH_MAX       (OPT_MAX+2) ++#else ++#define KEXEC_ARCH_OPTIONS \ ++	KEXEC_OPTIONS \ ++ ++#define OPT_ARCH_MAX   (OPT_MAX+0) ++#endif +  + #endif /* KEXEC_ARCH_MIPS_OPTIONS_H */ +Index: kexec-tools-2.0.1/kexec/arch/mips/kexec-elf-mips.c +=================================================================== +--- kexec-tools-2.0.1.orig/kexec/arch/mips/kexec-elf-mips.c	2008-07-15 02:46:43.000000000 +0200 ++++ kexec-tools-2.0.1/kexec/arch/mips/kexec-elf-mips.c	2009-09-27 19:16:39.000000000 +0200 +@@ -25,51 +25,18 @@ + #include <ip_checksum.h> + #include "../../kexec.h" + #include "../../kexec-elf.h" ++#include "../../kexec-syscall.h" + #include "kexec-mips.h" + #include <arch/options.h> ++#include "crashdump-mips.h" +  + static const int probe_debug = 0; +  + #define BOOTLOADER         "kexec" + #define MAX_COMMAND_LINE   256 +  +-#define UPSZ(X) ((sizeof(X) + 3) & ~3) +-static struct boot_notes { +-	Elf_Bhdr hdr; +-	Elf_Nhdr bl_hdr; +-	unsigned char bl_desc[UPSZ(BOOTLOADER)]; +-	Elf_Nhdr blv_hdr; +-	unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; +-	Elf_Nhdr cmd_hdr; +-	unsigned char command_line[0]; +-} elf_boot_notes = { +-	.hdr = { +-		.b_signature = 0x0E1FB007, +-		.b_size = sizeof(elf_boot_notes), +-		.b_checksum = 0, +-		.b_records = 3, +-	}, +-	.bl_hdr = { +-		.n_namesz = 0, +-		.n_descsz = sizeof(BOOTLOADER), +-		.n_type = EBN_BOOTLOADER_NAME, +-	}, +-	.bl_desc = BOOTLOADER, +-	.blv_hdr = { +-		.n_namesz = 0, +-		.n_descsz = sizeof(BOOTLOADER_VERSION), +-		.n_type = EBN_BOOTLOADER_VERSION, +-	}, +-	.blv_desc = BOOTLOADER_VERSION, +-	.cmd_hdr = { +-		.n_namesz = 0, +-		.n_descsz = 0, +-		.n_type = EBN_COMMAND_LINE, +-	}, +-}; +- +- +-#define OPT_APPEND	(OPT_ARCH_MAX+0) ++/* 'kexec' in cmdline is used to find cmdline buffer by kernel */ ++static char cmdline_buf[256] = "kexec "; +  + int elf_mips_probe(const char *buf, off_t len) + { +@@ -108,16 +75,14 @@ + 	struct kexec_info *info) + { + 	struct mem_ehdr ehdr; +-	char *arg_buf; +-	size_t arg_bytes; +-	unsigned long arg_base; +-	struct boot_notes *notes; +-	size_t note_bytes; +-	const char *command_line; +-	int command_line_len; +-	unsigned char *setup_start; +-	uint32_t setup_size; ++	unsigned long bss_start, bss_size = 0; ++	const char *command_line = NULL; ++	char *modified_cmdline; ++	int modified_cmdline_len; ++	unsigned long cmdline_addr; ++	int result,i; + 	int opt; ++#define OPT_APPEND     (OPT_ARCH_MAX+0) + 	static const struct option options[] = { + 		KEXEC_ARCH_OPTIONS + 		{"command-line", 1, 0, OPT_APPEND}, +@@ -144,38 +109,81 @@ + 			break; + 		} + 	} +-	command_line_len = 0; +-	setup_simple_regs.spr9 = 0; +-	if (command_line) { +-		command_line_len = strlen(command_line) + 1; +-		setup_simple_regs.spr9 = 2; ++	/* Need to append some command line parameters internally in case of ++	 * taking crash dumps. ++	 */ ++	if (info->kexec_flags & KEXEC_ON_CRASH) { ++		modified_cmdline = xmalloc(COMMAND_LINE_SIZE); ++		memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE); ++		if (command_line) { ++			strncpy(modified_cmdline, command_line, COMMAND_LINE_SIZE); ++			modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0'; ++		} ++		modified_cmdline_len = strlen(modified_cmdline); + 	} +  +-	/* Load the ELF executable */ +-	elf_exec_build_load(info, &ehdr, buf, len, 0); +- +-	setup_start = setup_simple_start; +-	setup_size = setup_simple_size; +-	setup_simple_regs.spr8 = ehdr.e_entry; +- +-	note_bytes = sizeof(elf_boot_notes) + ((command_line_len + 3) & ~3); +-	arg_bytes = note_bytes + ((setup_size + 3) & ~3); +- +-	arg_buf = xmalloc(arg_bytes); +-	arg_base = add_buffer_virt(info, +-		 arg_buf, arg_bytes, arg_bytes, 4, 0, elf_max_addr(&ehdr), 1); ++	/* Parse the Elf file */ ++	result = build_elf_exec_info(buf, len, &ehdr, 0); ++	if (result < 0) { ++		die("ELF exec parse failed\n"); ++	} +  +-	notes = (struct boot_notes *)(arg_buf + ((setup_size + 3) & ~3)); ++	/* Read in the PT_LOAD segments and remove CKSEG0 mask from address*/ ++	for(i = 0; i < ehdr.e_phnum; i++) { ++		struct mem_phdr *phdr; ++		phdr = &ehdr.e_phdr[i]; ++		if (phdr->p_type == PT_LOAD) { ++			phdr->p_paddr = virt_to_phys(phdr->p_paddr); ++		} ++	} +  +-	memcpy(arg_buf, setup_start, setup_size); +-	memcpy(notes, &elf_boot_notes, sizeof(elf_boot_notes)); +-	memcpy(notes->command_line, command_line, command_line_len); ++	for(i = 0; i < ehdr.e_shnum; i++) { ++		struct mem_shdr *shdr; ++		unsigned char *strtab; ++		strtab = (unsigned char *)ehdr.e_shdr[ehdr.e_shstrndx].sh_data; ++ ++		shdr = &ehdr.e_shdr[i]; ++		if ( shdr->sh_size && ++				strcmp((char *)&strtab[shdr->sh_name], ++					".bss") == 0) { ++			bss_start = virt_to_phys(shdr->sh_addr); ++			bss_size = shdr->sh_size; ++			break; ++		} ++	} +  +-	notes->hdr.b_size = note_bytes; +-	notes->cmd_hdr.n_descsz = command_line_len; +-	notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes); ++	/* Load the Elf data */ ++	result = elf_exec_load(&ehdr, info); ++	if (result < 0) { ++		die("ELF exec load failed\n"); ++	} ++	info->entry = (void *)virt_to_phys(ehdr.e_entry); ++	if(!bss_size) ++		die("No .bss segment present\n"); ++ ++	/* Put cmdline right after bss */ ++	cmdline_addr = bss_start + bss_size; ++ ++	/* If panic kernel is being loaded, additional segments need ++	 * to be created. ++	 */ ++	if (info->kexec_flags & KEXEC_ON_CRASH) { ++		result = load_crashdump_segments(info, modified_cmdline, ++								0, 0); ++		if (result < 0) ++			return -1; ++		/* Use new command line. */ ++		command_line = modified_cmdline; ++	} +  +-	info->entry = (void *)arg_base; ++	if (command_line) ++	{ ++		strncat(cmdline_buf,command_line, ++			sizeof(cmdline_buf) - strlen(cmdline_buf) - 1); ++		add_buffer(info, cmdline_buf, sizeof(cmdline_buf), ++			sizeof(cmdline_buf), sizeof(void*), ++			cmdline_addr, 0x0fffffff, 1); ++	} +  + 	return 0; + } +Index: kexec-tools-2.0.1/kexec/arch/mips/kexec-mips.c +=================================================================== +--- kexec-tools-2.0.1.orig/kexec/arch/mips/kexec-mips.c	2008-07-15 02:46:43.000000000 +0200 ++++ kexec-tools-2.0.1/kexec/arch/mips/kexec-mips.c	2009-09-27 19:20:25.000000000 +0200 +@@ -97,8 +97,18 @@ +  + void arch_usage(void) + { ++#ifdef __mips64 ++       fprintf(stderr, "        --elf32-core-headers Prepare core headers in " ++                       "ELF32 format\n"); ++#endif + } +  ++#ifdef __mips64 ++struct arch_options_t arch_options = { ++       .core_header_type = CORE_TYPE_ELF64 ++}; ++#endif ++ + int arch_process_options(int argc, char **argv) + { + 	static const struct option options[] = { +@@ -113,6 +123,11 @@ + 		switch(opt) { + 		default: + 			break; ++#ifdef __mips64 ++		case OPT_ELF64_CORE: ++			arch_options.core_header_type = CORE_TYPE_ELF64; ++			break; ++#endif + 		} + 	} + 	/* Reset getopt for the next pass; called in other source modules */ +@@ -126,6 +141,10 @@ + 	 * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here. + 	 */ + 	{ "mips", KEXEC_ARCH_DEFAULT }, ++	/* Not using KEXEC_ARCH_DEFAULT because that will fail ++	 * in the kernel's compat_sys_kexec_load() routine. ++	 */ ++	{ "mips64", KEXEC_ARCH_MIPS }, + 	{ 0 }, + }; +  +@@ -138,18 +157,9 @@ + { + } +  +-/* +- * Adding a dummy function, so that build on mips will not break. +- * Need to implement the actual checking code +- */ +-int is_crashkernel_mem_reserved(void) +-{ +-	return 1; +-} +- + unsigned long virt_to_phys(unsigned long addr) + { +-	return addr - 0x80000000; ++	return ((addr)& 0x7fffffff); + } +  + /* +Index: kexec-tools-2.0.1/kexec/arch/mips/kexec-mips.h +=================================================================== +--- kexec-tools-2.0.1.orig/kexec/arch/mips/kexec-mips.h	2008-07-15 02:46:43.000000000 +0200 ++++ kexec-tools-2.0.1/kexec/arch/mips/kexec-mips.h	2009-09-27 19:21:32.000000000 +0200 +@@ -1,17 +1,16 @@ + #ifndef KEXEC_MIPS_H + #define KEXEC_MIPS_H +  +-extern unsigned char setup_simple_start[]; +-extern uint32_t setup_simple_size; +- +-extern struct { +-	uint32_t spr8; +-	uint32_t spr9; +-} setup_simple_regs; ++#define MAX_MEMORY_RANGES 64 ++#define CORE_TYPE_ELF32 1 ++#define CORE_TYPE_ELF64 2 +  + int elf_mips_probe(const char *buf, off_t len); + int elf_mips_load(int argc, char **argv, const char *buf, off_t len, + 	struct kexec_info *info); + void elf_mips_usage(void); +  ++struct arch_options_t { ++	int core_header_type; ++}; + #endif /* KEXEC_MIPS_H */  | 
