[package] add mips64 support to kexec-tools, counterpart of r17768.
[openwrt/svn-archive/archive.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 */