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