[package] dropbear: Add RootLogin parameter to control whether ssh logins as root...
[openwrt.git] / package / kexec-tools / patches / 0005-mips64_support.patch
1 --- a/kexec/arch/mips/Makefile
2 +++ b/kexec/arch/mips/Makefile
3 @@ -4,7 +4,7 @@
4  mips_KEXEC_SRCS =  kexec/arch/mips/kexec-mips.c
5  mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-mips.c
6  mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-rel-mips.c
7 -mips_KEXEC_SRCS += kexec/arch/mips/mips-setup-simple.S
8 +mips_KEXEC_SRCS += kexec/arch/mips/crashdump-mips.c
9  
10  mips_ADD_BUFFER =
11  mips_ADD_SEGMENT =
12 --- /dev/null
13 +++ b/kexec/arch/mips/crashdump-mips.c
14 @@ -0,0 +1,371 @@
15 +/*
16 + * kexec: Linux boots Linux
17 + *
18 + * 2005 (C) IBM Corporation.
19 + * 2008 (C) MontaVista Software, Inc.
20 + *
21 + * This program is free software; you can redistribute it and/or modify
22 + * it under the terms of the GNU General Public License as published by
23 + * the Free Software Foundation (version 2 of the License).
24 + *
25 + * This program is distributed in the hope that it will be useful,
26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 + * GNU General Public License for more details.
29 + *
30 + * You should have received a copy of the GNU General Public License
31 + * along with this program; if not, write to the Free Software
32 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 + */
34 +#include <stdio.h>
35 +#include <string.h>
36 +#include <stdlib.h>
37 +#include <errno.h>
38 +#include <elf.h>
39 +#include <sys/types.h>
40 +#include <sys/stat.h>
41 +#include <unistd.h>
42 +#include "../../kexec.h"
43 +#include "../../kexec-elf.h"
44 +#include "../../kexec-syscall.h"
45 +#include "../../crashdump.h"
46 +#include "kexec-mips.h"
47 +#include "crashdump-mips.h"
48 +
49 +extern struct arch_options_t arch_options;
50 +
51 +/* Stores a sorted list of RAM memory ranges for which to create elf headers.
52 + * A separate program header is created for backup region */
53 +static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
54 +
55 +/* Memory region reserved for storing panic kernel and other data. */
56 +static struct memory_range crash_reserved_mem;
57 +
58 +/*
59 + * To store the memory size of the first kernel and this value will be
60 + * passed to the second kernel as command line (savemaxmem=xM).
61 + * The second kernel will be calculated saved_max_pfn based on this
62 + * variable.
63 + */
64 +unsigned long long saved_max_mem = 0;
65 +
66 +/* Removes crash reserve region from list of memory chunks for whom elf program
67 + * headers have to be created. Assuming crash reserve region to be a single
68 + * continuous area fully contained inside one of the memory chunks */
69 +static int exclude_crash_reserve_region(int *nr_ranges)
70 +{
71 +    int i, j, tidx = -1;
72 +    unsigned long long cstart, cend;
73 +    struct memory_range temp_region;
74 +
75 +    /* Crash reserved region. */
76 +    cstart = crash_reserved_mem.start;
77 +    cend = crash_reserved_mem.end;
78 +
79 +    for (i = 0; i < (*nr_ranges); i++) {
80 +        unsigned long long mstart, mend;
81 +        mstart = crash_memory_range[i].start;
82 +        mend = crash_memory_range[i].end;
83 +        if (cstart < mend && cend > mstart) {
84 +            if (cstart != mstart && cend != mend) {
85 +                /* Split memory region */
86 +                crash_memory_range[i].end = cstart - 1;
87 +                temp_region.start = cend + 1;
88 +                temp_region.end = mend;
89 +                temp_region.type = RANGE_RAM;
90 +                tidx = i+1;
91 +            } else if (cstart != mstart)
92 +                crash_memory_range[i].end = cstart - 1;
93 +            else
94 +                crash_memory_range[i].start = cend + 1;
95 +        }
96 +    }
97 +    /* Insert split memory region, if any. */
98 +    if (tidx >= 0) {
99 +        if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) {
100 +            /* No space to insert another element. */
101 +            fprintf(stderr, "Error: Number of crash memory ranges"
102 +                    " excedeed the max limit\n");
103 +            return -1;
104 +        }
105 +        for (j = (*nr_ranges - 1); j >= tidx; j--)
106 +            crash_memory_range[j+1] = crash_memory_range[j];
107 +        crash_memory_range[tidx].start = temp_region.start;
108 +        crash_memory_range[tidx].end = temp_region.end;
109 +        crash_memory_range[tidx].type = temp_region.type;
110 +        (*nr_ranges)++;
111 +    }
112 +    return 0;
113 +}
114 +/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
115 + * create Elf headers. Keeping it separate from get_memory_ranges() as
116 + * requirements are different in the case of normal kexec and crashdumps.
117 + *
118 + * Normal kexec needs to look at all of available physical memory irrespective
119 + * of the fact how much of it is being used by currently running kernel.
120 + * Crashdumps need to have access to memory regions actually being used by
121 + * running  kernel. Expecting a different file/data structure than /proc/iomem
122 + * to look into down the line. May be something like /proc/kernelmem or may
123 + * be zone data structures exported from kernel.
124 + */
125 +static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
126 +{
127 +    const char iomem[]= "/proc/iomem";
128 +    int i, memory_ranges = 0;
129 +    char line[MAX_LINE];
130 +    FILE *fp;
131 +    unsigned long long start, end;
132 +
133 +    fp = fopen(iomem, "r");
134 +    if (!fp) {
135 +        fprintf(stderr, "Cannot open %s: %s\n",
136 +            iomem, strerror(errno));
137 +        return -1;
138 +    }
139 +
140 +    /* Separate segment for backup region */
141 +    crash_memory_range[0].start = BACKUP_SRC_START;
142 +    crash_memory_range[0].end = BACKUP_SRC_END;
143 +    crash_memory_range[0].type = RANGE_RAM;
144 +    memory_ranges++;
145 +
146 +    while(fgets(line, sizeof(line), fp) != 0) {
147 +        char *str;
148 +        int type, consumed, count;
149 +        if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
150 +            break;
151 +        count = sscanf(line, "%Lx-%Lx : %n",
152 +            &start, &end, &consumed);
153 +        if (count != 2)
154 +            continue;
155 +        str = line + consumed;
156 +
157 +        /* Only Dumping memory of type System RAM. */
158 +        if (memcmp(str, "System RAM\n", 11) == 0) {
159 +            type = RANGE_RAM;
160 +        } else if (memcmp(str, "Crash kernel\n", 13) == 0) {
161 +                /* Reserved memory region. New kernel can
162 +                 * use this region to boot into. */
163 +                crash_reserved_mem.start = start;
164 +                crash_reserved_mem.end = end;
165 +                crash_reserved_mem.type = RANGE_RAM;
166 +                continue;
167 +        } else {
168 +            continue;
169 +        }
170 +
171 +        if (start == BACKUP_SRC_START && end >= (BACKUP_SRC_END + 1))
172 +            start = BACKUP_SRC_END + 1;
173 +
174 +        crash_memory_range[memory_ranges].start = start;
175 +        crash_memory_range[memory_ranges].end = end;
176 +        crash_memory_range[memory_ranges].type = type;
177 +        memory_ranges++;
178 +
179 +        /* Segregate linearly mapped region. */
180 +        if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) {
181 +            crash_memory_range[memory_ranges-1].end = MAXMEM -1;
182 +
183 +            /* Add segregated region. */
184 +            crash_memory_range[memory_ranges].start = MAXMEM;
185 +            crash_memory_range[memory_ranges].end = end;
186 +            crash_memory_range[memory_ranges].type = type;
187 +            memory_ranges++;
188 +        }
189 +    }
190 +    fclose(fp);
191 +
192 +    if (exclude_crash_reserve_region(&memory_ranges) < 0)
193 +        return -1;
194 +
195 +    for (i = 0; i < memory_ranges; i++)
196 +        if (saved_max_mem < crash_memory_range[i].end)
197 +            saved_max_mem = crash_memory_range[i].end + 1;
198 +
199 +    *range = crash_memory_range;
200 +    *ranges = memory_ranges;
201 +    return 0;
202 +}
203 +
204 +/* Converts unsigned long to ascii string. */
205 +static void ultoa(unsigned long i, char *str)
206 +{
207 +    int j = 0, k;
208 +    char tmp;
209 +
210 +    do {
211 +        str[j++] = i % 10 + '0';
212 +    } while ((i /=10) > 0);
213 +    str[j] = '\0';
214 +
215 +    /* Reverse the string. */
216 +    for (j = 0, k = strlen(str) - 1; j < k; j++, k--) {
217 +        tmp = str[k];
218 +        str[k] = str[j];
219 +        str[j] = tmp;
220 +    }
221 +}
222 +
223 +/* Adds the appropriate mem= options to command line, indicating the
224 + * memory region the new kernel can use to boot into. */
225 +static int cmdline_add_mem(char *cmdline, unsigned long addr, unsigned long size)
226 +{
227 +    int cmdlen, len;
228 +    char str[50], *ptr;
229 +
230 +    addr = addr/1024;
231 +    size = size/1024;
232 +    ptr = str;
233 +    strcpy (str, " mem=");
234 +    ptr += strlen(str);
235 +    ultoa(size, ptr);
236 +    strcat (str, "K@");
237 +    ptr = str + strlen(str);
238 +    ultoa(addr, ptr);
239 +    strcat (str, "K");
240 +    len = strlen(str);
241 +    cmdlen = strlen(cmdline) + len;
242 +    if (cmdlen > (COMMAND_LINE_SIZE - 1))
243 +        die("Command line overflow\n");
244 +    strcat(cmdline, str);
245 +
246 +    return 0;
247 +}
248 +
249 +/* Adds the elfcorehdr= command line parameter to command line. */
250 +static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr)
251 +{
252 +    int cmdlen, len, align = 1024;
253 +    char str[30], *ptr;
254 +
255 +    /* Passing in elfcorehdr=xxxK format. Saves space required in cmdline.
256 +     * Ensure 1K alignment*/
257 +    if (addr%align)
258 +        return -1;
259 +    addr = addr/align;
260 +    ptr = str;
261 +    strcpy(str, " elfcorehdr=");
262 +    ptr += strlen(str);
263 +    ultoa(addr, ptr);
264 +    strcat(str, "K");
265 +    len = strlen(str);
266 +    cmdlen = strlen(cmdline) + len;
267 +    if (cmdlen > (COMMAND_LINE_SIZE - 1))
268 +        die("Command line overflow\n");
269 +    strcat(cmdline, str);
270 +    return 0;
271 +}
272 +
273 +/* Adds the elfcorehdr= command line parameter to command line. */
274 +static int cmdline_add_savemaxmem(char *cmdline, unsigned long addr)
275 +{
276 +    int cmdlen, len, align = 1024;
277 +    char str[30], *ptr;
278 +
279 +    /* Passing in savemaxmem=xxxM format. Saves space required in cmdline.*/
280 +    addr = addr/(align*align);
281 +    ptr = str;
282 +    strcpy(str, " savemaxmem=");
283 +    ptr += strlen(str);
284 +    ultoa(addr, ptr);
285 +    strcat(str, "M");
286 +    len = strlen(str);
287 +    cmdlen = strlen(cmdline) + len;
288 +    if (cmdlen > (COMMAND_LINE_SIZE - 1))
289 +        die("Command line overflow\n");
290 +    strcat(cmdline, str);
291 +    return 0;
292 +}
293 +
294 +#ifdef __mips64
295 +static struct crash_elf_info elf_info64 =
296 +{
297 +    class: ELFCLASS64,
298 +    data: ELFDATA2MSB,
299 +    machine: EM_MIPS,
300 +    backup_src_start: BACKUP_SRC_START,
301 +    backup_src_end: BACKUP_SRC_END,
302 +    page_offset: PAGE_OFFSET,
303 +    lowmem_limit: MAXMEM,
304 +};
305 +#endif
306 +static struct crash_elf_info elf_info32 =
307 +{
308 +    class: ELFCLASS32,
309 +    data: ELFDATA2MSB,
310 +    machine: EM_MIPS,
311 +    backup_src_start: BACKUP_SRC_START,
312 +    backup_src_end: BACKUP_SRC_END,
313 +    page_offset: PAGE_OFFSET,
314 +    lowmem_limit: MAXMEM,
315 +};
316 +
317 +/* Loads additional segments in case of a panic kernel is being loaded.
318 + * One segment for backup region, another segment for storing elf headers
319 + * for crash memory image.
320 + */
321 +int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
322 +                unsigned long max_addr, unsigned long min_base)
323 +{
324 +    void *tmp;
325 +    unsigned long sz, elfcorehdr;
326 +    int nr_ranges, align = 1024;
327 +    struct memory_range *mem_range;
328 +
329 +    if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
330 +        return -1;
331 +
332 +    /* Create a backup region segment to store backup data*/
333 +    sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
334 +    tmp = xmalloc(sz);
335 +    memset(tmp, 0, sz);
336 +    info->backup_start = add_buffer(info, tmp, sz, sz, align,
337 +                crash_reserved_mem.start,
338 +                crash_reserved_mem.end,-1);
339 +
340 +#ifdef __mips64
341 +    /* Create elf header segment and store crash image data. */
342 +    if (arch_options.core_header_type == CORE_TYPE_ELF64) {
343 +        if (crash_create_elf64_headers(info, &elf_info64,
344 +                           crash_memory_range, nr_ranges,
345 +                           &tmp, &sz,
346 +                           ELF_CORE_HEADER_ALIGN) < 0)
347 +            return -1;
348 +    }
349 +    else {
350 +        if (crash_create_elf32_headers(info, &elf_info32,
351 +                           crash_memory_range, nr_ranges,
352 +                           &tmp, &sz,
353 +                           ELF_CORE_HEADER_ALIGN) < 0)
354 +            return -1;
355 +    }
356 +#else
357 +    if (crash_create_elf32_headers(info, &elf_info32,
358 +                   crash_memory_range, nr_ranges,
359 +                   &tmp, &sz,
360 +                   ELF_CORE_HEADER_ALIGN) < 0)
361 +        return -1;
362 +#endif
363 +    elfcorehdr = add_buffer(info, tmp, sz, sz, align,
364 +                crash_reserved_mem.start,
365 +                crash_reserved_mem.end, -1);
366 +
367 +    /*
368 +     * backup segment is after elfcorehdr, so use elfcorehdr as top of
369 +     * kernel's available memory
370 +     */
371 +    cmdline_add_mem(mod_cmdline, crash_reserved_mem.start,
372 +        elfcorehdr - crash_reserved_mem.start);
373 +    cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
374 +    cmdline_add_savemaxmem(mod_cmdline, saved_max_mem);
375 +    return 0;
376 +}
377 +
378 +int is_crashkernel_mem_reserved(void)
379 +{
380 +    uint64_t start, end;
381 +
382 +    return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ?
383 +      (start != end) : 0;
384 +}
385 +
386 --- /dev/null
387 +++ b/kexec/arch/mips/crashdump-mips.h
388 @@ -0,0 +1,26 @@
389 +#ifndef CRASHDUMP_MIPS_H
390 +#define CRASHDUMP_MIPS_H
391 +
392 +struct kexec_info;
393 +int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
394 +                unsigned long max_addr, unsigned long min_base);
395 +#ifdef __mips64
396 +#define PAGE_OFFSET    0xa800000000000000ULL
397 +#else
398 +#define PAGE_OFFSET    0x80000000
399 +#endif
400 +#define __pa(x)        ((unsigned long)(X)& 0x7fffffff)
401 +
402 +#define MAXMEM        0x80000000
403 +
404 +#define CRASH_MAX_MEMMAP_NR    (KEXEC_MAX_SEGMENTS + 1)
405 +#define CRASH_MAX_MEMORY_RANGES    (MAX_MEMORY_RANGES + 2)
406 +
407 +#define COMMAND_LINE_SIZE    512
408 +
409 +/* Backup Region, First 1M of System RAM. */
410 +#define BACKUP_SRC_START    0x00000000
411 +#define BACKUP_SRC_END        0x000fffff
412 +#define BACKUP_SRC_SIZE    (BACKUP_SRC_END - BACKUP_SRC_START + 1)
413 +
414 +#endif /* CRASHDUMP_MIPS_H */
415 --- a/kexec/arch/mips/include/arch/options.h
416 +++ b/kexec/arch/mips/include/arch/options.h
417 @@ -2,10 +2,21 @@
418  #define KEXEC_ARCH_MIPS_OPTIONS_H
419  
420  #define OPT_ARCH_MAX   (OPT_MAX+0)
421 +#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
422  
423 +#ifdef __mips64
424 +#define OPT_ELF64_CORE (OPT_MAX+1)
425  #define KEXEC_ARCH_OPTIONS \
426         KEXEC_OPTIONS \
427 +       { "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \
428  
429  #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
430 +#define OPT_ARCH_MAX       (OPT_MAX+2)
431 +#else
432 +#define KEXEC_ARCH_OPTIONS \
433 +       KEXEC_OPTIONS \
434 +
435 +#define OPT_ARCH_MAX   (OPT_MAX+0)
436 +#endif
437  
438  #endif /* KEXEC_ARCH_MIPS_OPTIONS_H */
439 --- a/kexec/arch/mips/kexec-elf-mips.c
440 +++ b/kexec/arch/mips/kexec-elf-mips.c
441 @@ -25,51 +25,18 @@
442  #include <ip_checksum.h>
443  #include "../../kexec.h"
444  #include "../../kexec-elf.h"
445 +#include "../../kexec-syscall.h"
446  #include "kexec-mips.h"
447  #include <arch/options.h>
448 +#include "crashdump-mips.h"
449  
450  static const int probe_debug = 0;
451  
452  #define BOOTLOADER         "kexec"
453  #define MAX_COMMAND_LINE   256
454  
455 -#define UPSZ(X) ((sizeof(X) + 3) & ~3)
456 -static struct boot_notes {
457 -       Elf_Bhdr hdr;
458 -       Elf_Nhdr bl_hdr;
459 -       unsigned char bl_desc[UPSZ(BOOTLOADER)];
460 -       Elf_Nhdr blv_hdr;
461 -       unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
462 -       Elf_Nhdr cmd_hdr;
463 -       unsigned char command_line[0];
464 -} elf_boot_notes = {
465 -       .hdr = {
466 -               .b_signature = 0x0E1FB007,
467 -               .b_size = sizeof(elf_boot_notes),
468 -               .b_checksum = 0,
469 -               .b_records = 3,
470 -       },
471 -       .bl_hdr = {
472 -               .n_namesz = 0,
473 -               .n_descsz = sizeof(BOOTLOADER),
474 -               .n_type = EBN_BOOTLOADER_NAME,
475 -       },
476 -       .bl_desc = BOOTLOADER,
477 -       .blv_hdr = {
478 -               .n_namesz = 0,
479 -               .n_descsz = sizeof(BOOTLOADER_VERSION),
480 -               .n_type = EBN_BOOTLOADER_VERSION,
481 -       },
482 -       .blv_desc = BOOTLOADER_VERSION,
483 -       .cmd_hdr = {
484 -               .n_namesz = 0,
485 -               .n_descsz = 0,
486 -               .n_type = EBN_COMMAND_LINE,
487 -       },
488 -};
489 -
490 -
491 -#define OPT_APPEND     (OPT_ARCH_MAX+0)
492 +/* 'kexec' in cmdline is used to find cmdline buffer by kernel */
493 +static char cmdline_buf[256] = "kexec ";
494  
495  int elf_mips_probe(const char *buf, off_t len)
496  {
497 @@ -108,16 +75,14 @@ int elf_mips_load(int argc, char **argv,
498         struct kexec_info *info)
499  {
500         struct mem_ehdr ehdr;
501 -       char *arg_buf;
502 -       size_t arg_bytes;
503 -       unsigned long arg_base;
504 -       struct boot_notes *notes;
505 -       size_t note_bytes;
506 -       const char *command_line;
507 -       int command_line_len;
508 -       unsigned char *setup_start;
509 -       uint32_t setup_size;
510 +       unsigned long bss_start, bss_size = 0;
511 +       const char *command_line = NULL;
512 +       char *modified_cmdline;
513 +       int modified_cmdline_len;
514 +       unsigned long cmdline_addr;
515 +       int result,i;
516         int opt;
517 +#define OPT_APPEND     (OPT_ARCH_MAX+0)
518         static const struct option options[] = {
519                 KEXEC_ARCH_OPTIONS
520                 {"command-line", 1, 0, OPT_APPEND},
521 @@ -144,38 +109,81 @@ int elf_mips_load(int argc, char **argv,
522                         break;
523                 }
524         }
525 -       command_line_len = 0;
526 -       setup_simple_regs.spr9 = 0;
527 -       if (command_line) {
528 -               command_line_len = strlen(command_line) + 1;
529 -               setup_simple_regs.spr9 = 2;
530 +       /* Need to append some command line parameters internally in case of
531 +        * taking crash dumps.
532 +        */
533 +       if (info->kexec_flags & KEXEC_ON_CRASH) {
534 +               modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
535 +               memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
536 +               if (command_line) {
537 +                       strncpy(modified_cmdline, command_line, COMMAND_LINE_SIZE);
538 +                       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
539 +               }
540 +               modified_cmdline_len = strlen(modified_cmdline);
541         }
542  
543 -       /* Load the ELF executable */
544 -       elf_exec_build_load(info, &ehdr, buf, len, 0);
545 -
546 -       setup_start = setup_simple_start;
547 -       setup_size = setup_simple_size;
548 -       setup_simple_regs.spr8 = ehdr.e_entry;
549 -
550 -       note_bytes = sizeof(elf_boot_notes) + ((command_line_len + 3) & ~3);
551 -       arg_bytes = note_bytes + ((setup_size + 3) & ~3);
552 -
553 -       arg_buf = xmalloc(arg_bytes);
554 -       arg_base = add_buffer_virt(info,
555 -                arg_buf, arg_bytes, arg_bytes, 4, 0, elf_max_addr(&ehdr), 1);
556 +       /* Parse the Elf file */
557 +       result = build_elf_exec_info(buf, len, &ehdr, 0);
558 +       if (result < 0) {
559 +               die("ELF exec parse failed\n");
560 +       }
561  
562 -       notes = (struct boot_notes *)(arg_buf + ((setup_size + 3) & ~3));
563 +       /* Read in the PT_LOAD segments and remove CKSEG0 mask from address*/
564 +       for(i = 0; i < ehdr.e_phnum; i++) {
565 +               struct mem_phdr *phdr;
566 +               phdr = &ehdr.e_phdr[i];
567 +               if (phdr->p_type == PT_LOAD) {
568 +                       phdr->p_paddr = virt_to_phys(phdr->p_paddr);
569 +               }
570 +       }
571  
572 -       memcpy(arg_buf, setup_start, setup_size);
573 -       memcpy(notes, &elf_boot_notes, sizeof(elf_boot_notes));
574 -       memcpy(notes->command_line, command_line, command_line_len);
575 +       for(i = 0; i < ehdr.e_shnum; i++) {
576 +               struct mem_shdr *shdr;
577 +               unsigned char *strtab;
578 +               strtab = (unsigned char *)ehdr.e_shdr[ehdr.e_shstrndx].sh_data;
579 +
580 +               shdr = &ehdr.e_shdr[i];
581 +               if ( shdr->sh_size &&
582 +                               strcmp((char *)&strtab[shdr->sh_name],
583 +                                       ".bss") == 0) {
584 +                       bss_start = virt_to_phys(shdr->sh_addr);
585 +                       bss_size = shdr->sh_size;
586 +                       break;
587 +               }
588 +       }
589  
590 -       notes->hdr.b_size = note_bytes;
591 -       notes->cmd_hdr.n_descsz = command_line_len;
592 -       notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes);
593 +       /* Load the Elf data */
594 +       result = elf_exec_load(&ehdr, info);
595 +       if (result < 0) {
596 +               die("ELF exec load failed\n");
597 +       }
598 +       info->entry = (void *)virt_to_phys(ehdr.e_entry);
599 +       if(!bss_size)
600 +               die("No .bss segment present\n");
601 +
602 +       /* Put cmdline right after bss */
603 +       cmdline_addr = bss_start + bss_size;
604 +
605 +       /* If panic kernel is being loaded, additional segments need
606 +        * to be created.
607 +        */
608 +       if (info->kexec_flags & KEXEC_ON_CRASH) {
609 +               result = load_crashdump_segments(info, modified_cmdline,
610 +                                                               0, 0);
611 +               if (result < 0)
612 +                       return -1;
613 +               /* Use new command line. */
614 +               command_line = modified_cmdline;
615 +       }
616  
617 -       info->entry = (void *)arg_base;
618 +       if (command_line)
619 +       {
620 +               strncat(cmdline_buf,command_line,
621 +                       sizeof(cmdline_buf) - strlen(cmdline_buf) - 1);
622 +               add_buffer(info, cmdline_buf, sizeof(cmdline_buf),
623 +                       sizeof(cmdline_buf), sizeof(void*),
624 +                       cmdline_addr, 0x0fffffff, 1);
625 +       }
626  
627         return 0;
628  }
629 --- a/kexec/arch/mips/kexec-mips.c
630 +++ b/kexec/arch/mips/kexec-mips.c
631 @@ -97,8 +97,18 @@ int file_types = sizeof(file_type) / siz
632  
633  void arch_usage(void)
634  {
635 +#ifdef __mips64
636 +       fprintf(stderr, "        --elf32-core-headers Prepare core headers in "
637 +                       "ELF32 format\n");
638 +#endif
639  }
640  
641 +#ifdef __mips64
642 +struct arch_options_t arch_options = {
643 +       .core_header_type = CORE_TYPE_ELF64
644 +};
645 +#endif
646 +
647  int arch_process_options(int argc, char **argv)
648  {
649         static const struct option options[] = {
650 @@ -113,6 +123,11 @@ int arch_process_options(int argc, char 
651                 switch(opt) {
652                 default:
653                         break;
654 +#ifdef __mips64
655 +               case OPT_ELF64_CORE:
656 +                       arch_options.core_header_type = CORE_TYPE_ELF64;
657 +                       break;
658 +#endif
659                 }
660         }
661         /* Reset getopt for the next pass; called in other source modules */
662 @@ -126,6 +141,10 @@ const struct arch_map_entry arches[] = {
663          * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here.
664          */
665         { "mips", KEXEC_ARCH_DEFAULT },
666 +       /* Not using KEXEC_ARCH_DEFAULT because that will fail
667 +        * in the kernel's compat_sys_kexec_load() routine.
668 +        */
669 +       { "mips64", KEXEC_ARCH_MIPS },
670         { 0 },
671  };
672  
673 @@ -138,18 +157,9 @@ void arch_update_purgatory(struct kexec_
674  {
675  }
676  
677 -/*
678 - * Adding a dummy function, so that build on mips will not break.
679 - * Need to implement the actual checking code
680 - */
681 -int is_crashkernel_mem_reserved(void)
682 -{
683 -       return 1;
684 -}
685 -
686  unsigned long virt_to_phys(unsigned long addr)
687  {
688 -       return addr - 0x80000000;
689 +       return ((addr)& 0x7fffffff);
690  }
691  
692  /*
693 --- a/kexec/arch/mips/kexec-mips.h
694 +++ b/kexec/arch/mips/kexec-mips.h
695 @@ -1,17 +1,16 @@
696  #ifndef KEXEC_MIPS_H
697  #define KEXEC_MIPS_H
698  
699 -extern unsigned char setup_simple_start[];
700 -extern uint32_t setup_simple_size;
701 -
702 -extern struct {
703 -       uint32_t spr8;
704 -       uint32_t spr9;
705 -} setup_simple_regs;
706 +#define MAX_MEMORY_RANGES 64
707 +#define CORE_TYPE_ELF32 1
708 +#define CORE_TYPE_ELF64 2
709  
710  int elf_mips_probe(const char *buf, off_t len);
711  int elf_mips_load(int argc, char **argv, const char *buf, off_t len,
712         struct kexec_info *info);
713  void elf_mips_usage(void);
714  
715 +struct arch_options_t {
716 +       int core_header_type;
717 +};
718  #endif /* KEXEC_MIPS_H */