diff --git a/package/kexec-tools/Makefile b/package/kexec-tools/Makefile index 63e0bbf43..101572b02 100644 --- a/package/kexec-tools/Makefile +++ b/package/kexec-tools/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2006-2009 OpenWrt.org +# Copyright (C) 2006-2010 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=kexec-tools -PKG_VERSION:=2.0.1 -PKG_RELEASE:=3 +PKG_VERSION:=2.0.2 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 -PKG_SOURCE_URL:=@KERNEL/linux/kernel/people/horms/kexec-tools -PKG_MD5SUM:=67c1a396fdf67b984dad939a59a01571 +PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/kexec +PKG_MD5SUM:=35d05fed1c97008ac34c5bfb929295eb PKG_FIXUP:=autoreconf @@ -22,7 +22,7 @@ include $(INCLUDE_DIR)/package.mk define Package/kexec-tools SECTION:=utils CATEGORY:=Utilities - DEPENDS:=@armeb||@i386||@powerpc64||@mipsel||@mips +zlib + DEPENDS:=@armeb||@arm||@i386||@powerpc64||@mipsel||@mips +zlib TITLE:=Kernel boots kernel URL:=http://kernel.org/pub/linux/kernel/people/horms/kexec-tools/ MENU:=1 diff --git a/package/kexec-tools/patches/0005-mips64_support.patch b/package/kexec-tools/patches/0005-mips64_support.patch deleted file mode 100644 index e5da10e14..000000000 --- a/package/kexec-tools/patches/0005-mips64_support.patch +++ /dev/null @@ -1,718 +0,0 @@ ---- a/kexec/arch/mips/Makefile -+++ b/kexec/arch/mips/Makefile -@@ -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 = ---- /dev/null -+++ b/kexec/arch/mips/crashdump-mips.c -@@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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; -+} -+ ---- /dev/null -+++ b/kexec/arch/mips/crashdump-mips.h -@@ -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 */ ---- a/kexec/arch/mips/include/arch/options.h -+++ b/kexec/arch/mips/include/arch/options.h -@@ -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 */ ---- a/kexec/arch/mips/kexec-elf-mips.c -+++ b/kexec/arch/mips/kexec-elf-mips.c -@@ -25,51 +25,18 @@ - #include - #include "../../kexec.h" - #include "../../kexec-elf.h" -+#include "../../kexec-syscall.h" - #include "kexec-mips.h" - #include -+#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 @@ int elf_mips_load(int argc, char **argv, - 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 @@ int elf_mips_load(int argc, char **argv, - 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; - } ---- a/kexec/arch/mips/kexec-mips.c -+++ b/kexec/arch/mips/kexec-mips.c -@@ -97,8 +97,18 @@ int file_types = sizeof(file_type) / siz - - 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 @@ int arch_process_options(int argc, char - 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 @@ const struct arch_map_entry arches[] = { - * 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 @@ void arch_update_purgatory(struct kexec_ - { - } - --/* -- * 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); - } - - /* ---- a/kexec/arch/mips/kexec-mips.h -+++ b/kexec/arch/mips/kexec-mips.h -@@ -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 */