1041 lines
32 KiB
Diff
1041 lines
32 KiB
Diff
--- kexec-tools-1.101/purgatory/arch/x86_64/include/arch/debug.h.orig 2004-12-20 18:05:40.000000000 -0500
|
|
+++ kexec-tools-1.101/purgatory/arch/x86_64/include/arch/debug.h 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -311,7 +311,7 @@
|
|
TTYS0_TX_AL
|
|
|
|
|
|
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
|
|
--- kexec-tools-1.101/purgatory/arch/i386/linux-entry16.S.orig 2004-12-20 05:48:45.000000000 -0500
|
|
+++ kexec-tools-1.101/purgatory/arch/i386/linux-entry16.S 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -127,10 +127,10 @@
|
|
TTYS0_TX_AL
|
|
|
|
|
|
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#else
|
|
-#define DEBUG(x)
|
|
+#define DEBUG_CHAR(x)
|
|
#define DEBUG_TX_HEX32(x)
|
|
#endif
|
|
|
|
@@ -142,15 +142,15 @@
|
|
entry16:
|
|
.code32
|
|
|
|
-DEBUG('a')
|
|
+DEBUG_CHAR('a')
|
|
/* Setup the classic BIOS interrupt table at 0x0 */
|
|
lidt idtptr
|
|
|
|
-DEBUG('b')
|
|
+DEBUG_CHAR('b')
|
|
/* Provide us with 16bit segments that we can use */
|
|
lgdt gdt
|
|
|
|
-DEBUG('c')
|
|
+DEBUG_CHAR('c')
|
|
/* Note we don't disable the a20 line, (this shouldn't be required)
|
|
* The code to do it is in kexec_test and it is a real pain.
|
|
* I will worry about that when I need it.
|
|
@@ -164,26 +164,26 @@ DEBUG('c')
|
|
movl %eax, %fs
|
|
movl %eax, %gs
|
|
|
|
-DEBUG('d')
|
|
+DEBUG_CHAR('d')
|
|
|
|
/* switch to 16bit mode */
|
|
ljmp $0x08, $1f - entry16
|
|
1:
|
|
.code16
|
|
-DEBUG('e')
|
|
+DEBUG_CHAR('e')
|
|
/* Disable Paging and protected mode */
|
|
/* clear the PG & PE bits of CR0 */
|
|
movl %cr0,%eax
|
|
andl $~((1 << 31)|(1<<0)),%eax
|
|
movl %eax,%cr0
|
|
|
|
-DEBUG('f')
|
|
+DEBUG_CHAR('f')
|
|
/* make intersegment jmp to flush the processor pipeline
|
|
* and reload %cs:%eip (to clear upper 16 bits of %eip).
|
|
*/
|
|
ljmp *(realptr - entry16)
|
|
3:
|
|
-DEBUG('g')
|
|
+DEBUG_CHAR('g')
|
|
/* we are in real mode now
|
|
* set up the real mode segment registers : %ds, $ss, %es
|
|
*/
|
|
@@ -191,7 +191,7 @@ DEBUG('g')
|
|
movw %cs, %ax
|
|
movw %ax, %ds
|
|
|
|
-DEBUG('h')
|
|
+DEBUG_CHAR('h')
|
|
/* Load the registers */
|
|
movl eax - entry16, %eax
|
|
movl ebx - entry16, %ebx
|
|
@@ -386,10 +386,10 @@ gdt_end:
|
|
TTYS0_TX_AL
|
|
|
|
|
|
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#else
|
|
-#define DEBUG(x)
|
|
+#define DEBUG_CHAR(x)
|
|
#define DEBUG_TX_HEX32(x)
|
|
#endif
|
|
|
|
@@ -403,7 +403,7 @@ setup16_debug_start:
|
|
_reloc = .
|
|
.balign 16
|
|
.code32
|
|
-DEBUG('a')
|
|
+DEBUG_CHAR('a')
|
|
/* Compute where I am running at */
|
|
call 1f
|
|
1: popl %ebx
|
|
@@ -412,13 +412,13 @@ DEBUG('a')
|
|
/* Remember where I am running at */
|
|
movl %ebx, location - _reloc(%ebx)
|
|
|
|
-DEBUG('b')
|
|
+DEBUG_CHAR('b')
|
|
/* Fixup my real mode segment */
|
|
movl %ebx, %eax
|
|
shrl $4, %eax
|
|
movw %ax, 2 + realptr - _reloc(%ebx)
|
|
|
|
-DEBUG('c')
|
|
+DEBUG_CHAR('c')
|
|
/* Fixup the gdt */
|
|
movl %ebx, %eax
|
|
shll $16, %eax
|
|
@@ -440,7 +440,7 @@ DEBUG('c')
|
|
|
|
|
|
|
|
-DEBUG('d')
|
|
+DEBUG_CHAR('d')
|
|
/* Setup the classic BIOS interrupt table at 0x0 */
|
|
lidt idtptr - _reloc(%ebx)
|
|
|
|
@@ -465,20 +465,20 @@ DEBUG('d')
|
|
ljmp $0x08, $2f - _reloc
|
|
2:
|
|
.code16
|
|
-DEBUG('e')
|
|
+DEBUG_CHAR('e')
|
|
/* Disable Paging and protected mode */
|
|
/* clear the PG & PE bits of CR0 */
|
|
movl %cr0,%eax
|
|
andl $~((1 << 31)|(1<<0)),%eax
|
|
movl %eax,%cr0
|
|
|
|
-DEBUG('f')
|
|
+DEBUG_CHAR('f')
|
|
/* make intersegment jmp to flush the processor pipeline
|
|
* and reload %cs:%eip (to clear upper 16 bits of %eip).
|
|
*/
|
|
ljmp *(realptr - _reloc)
|
|
3:
|
|
-DEBUG('g')
|
|
+DEBUG_CHAR('g')
|
|
/* we are in real mode now
|
|
* set up the real mode segment registers : %ds, $ss, %es
|
|
*/
|
|
@@ -486,7 +486,7 @@ DEBUG('g')
|
|
movw %cs, %ax
|
|
movw %ax, %ds
|
|
|
|
-DEBUG('h')
|
|
+DEBUG_CHAR('h')
|
|
/* Load the registers */
|
|
movl eax - _reloc, %eax
|
|
movl ebx - _reloc, %ebx
|
|
@@ -600,7 +600,7 @@ debug_gdt_end:
|
|
|
|
setup16_debug_kernel_pre_protected:
|
|
.code16
|
|
- DEBUG('i')
|
|
+ DEBUG_CHAR('i')
|
|
cli # no interrupts allowed !
|
|
movb $0x80, %al # disable NMI for bootup
|
|
# sequence
|
|
@@ -611,7 +611,7 @@ setup16_debug_first_code32:
|
|
.byte 0xbf /* movl $0x12345678, %edi */
|
|
location:
|
|
.long 0x12345678
|
|
- DEBUG('j')
|
|
+ DEBUG_CHAR('j')
|
|
.byte 0xb8 /* movl $0x10000, %eax */
|
|
setup16_debug_old_code32:
|
|
.long 0x10000
|
|
--- kexec-tools-1.101/purgatory/arch/i386/entry32-16-debug.S.orig 2004-12-20 18:11:43.000000000 -0500
|
|
+++ kexec-tools-1.101/purgatory/arch/i386/entry32-16-debug.S 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -55,15 +55,15 @@ entry16_debug:
|
|
orl %ecx, 0x14 + gdt
|
|
|
|
|
|
-DEBUG('a')
|
|
+DEBUG_CHAR('a')
|
|
/* Setup the classic BIOS interrupt table at 0x0 */
|
|
lidt idtptr
|
|
|
|
-DEBUG('b')
|
|
+DEBUG_CHAR('b')
|
|
/* Provide us with 16bit segments that we can use */
|
|
lgdt gdt
|
|
|
|
-DEBUG('c')
|
|
+DEBUG_CHAR('c')
|
|
/* Note we don't disable the a20 line, (this shouldn't be required)
|
|
* The code to do it is in kexec_test and it is a real pain.
|
|
* I will worry about that when I need it.
|
|
@@ -77,26 +77,26 @@ DEBUG('c')
|
|
movl %eax, %fs
|
|
movl %eax, %gs
|
|
|
|
-DEBUG('d')
|
|
+DEBUG_CHAR('d')
|
|
|
|
/* switch to 16bit mode */
|
|
ljmp $0x08, $1f - entry16_debug
|
|
1:
|
|
.code16
|
|
-DEBUG('e')
|
|
+DEBUG_CHAR('e')
|
|
/* Disable Paging and protected mode */
|
|
/* clear the PG & PE bits of CR0 */
|
|
movl %cr0,%eax
|
|
andl $~((1 << 31)|(1<<0)),%eax
|
|
movl %eax,%cr0
|
|
|
|
-DEBUG('f')
|
|
+DEBUG_CHAR('f')
|
|
/* make intersegment jmp to flush the processor pipeline
|
|
* and reload %cs:%eip (to clear upper 16 bits of %eip).
|
|
*/
|
|
ljmp *(realptr - entry16_debug)
|
|
3:
|
|
-DEBUG('g')
|
|
+DEBUG_CHAR('g')
|
|
/* we are in real mode now
|
|
* set up the real mode segment registers : %ds, $ss, %es
|
|
*/
|
|
@@ -104,7 +104,7 @@ DEBUG('g')
|
|
movw %cs, %ax
|
|
movw %ax, %ds
|
|
|
|
-DEBUG('h')
|
|
+DEBUG_CHAR('h')
|
|
/* Load the registers */
|
|
movl eax - entry16_debug, %eax
|
|
movl ebx - entry16_debug, %ebx
|
|
@@ -176,7 +176,7 @@ gdt_end:
|
|
.text
|
|
entry16_debug_pre32:
|
|
.code16
|
|
-DEBUG('i')
|
|
+DEBUG_CHAR('i')
|
|
cli # no interrupts allowed !
|
|
movb $0x80, %al # disable NMI for bootup
|
|
# sequence
|
|
@@ -186,7 +186,7 @@ DEBUG('i')
|
|
|
|
entry16_debug_first32:
|
|
.code32
|
|
-DEBUG('j')
|
|
+DEBUG_CHAR('j')
|
|
.byte 0xb8 /* movl $0x10000, %eax */
|
|
entry16_debug_old_first32:
|
|
.long 0x100000
|
|
--- kexec-tools-1.101/purgatory/arch/i386/include/arch/debug.h.orig 2004-12-20 18:03:17.000000000 -0500
|
|
+++ kexec-tools-1.101/purgatory/arch/i386/include/arch/debug.h 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -311,6 +311,6 @@
|
|
TTYS0_TX_AL
|
|
|
|
|
|
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
#define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
|
|
--- kexec-tools-1.101/kexec/Makefile.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/Makefile 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -13,6 +13,7 @@ KEXEC_C_SRCS:= kexec/kexec.c
|
|
KEXEC_C_SRCS+= kexec/ifdown.c
|
|
KEXEC_C_SRCS+= kexec/kexec-elf.c
|
|
KEXEC_C_SRCS+= kexec/kexec-elf-exec.c
|
|
+KEXEC_C_SRCS+= kexec/kexec-elf-core.c
|
|
KEXEC_C_SRCS+= kexec/kexec-elf-rel.c
|
|
KEXEC_C_SRCS+= kexec/kexec-elf-boot.c
|
|
KEXEC_C_SRCS+= kexec/crashdump.c
|
|
--- kexec-tools-1.101/kexec/kexec-elf-rel.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec-elf-rel.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -135,10 +135,11 @@ static struct mem_rela elf_rela(struct m
|
|
return rela;
|
|
}
|
|
|
|
-int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
|
|
+int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags)
|
|
{
|
|
int result;
|
|
- result = build_elf_info(buf, len, ehdr);
|
|
+ result = build_elf_info(buf, len, ehdr, flags);
|
|
if (result < 0) {
|
|
return result;
|
|
}
|
|
@@ -412,12 +413,12 @@ int elf_rel_load(struct mem_ehdr *ehdr,
|
|
|
|
void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
|
|
const char *buf, off_t len, unsigned long min, unsigned long max,
|
|
- int end)
|
|
+ int end, uint32_t flags)
|
|
{
|
|
int result;
|
|
|
|
/* Parse the Elf file */
|
|
- result = build_elf_rel_info((char *)purgatory, purgatory_size, ehdr);
|
|
+ result = build_elf_rel_info(buf, len, ehdr, flags);
|
|
if (result < 0) {
|
|
die("ELF rel parse failed\n");
|
|
}
|
|
--- kexec-tools-1.101/kexec/kexec-elf.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec-elf.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -368,7 +368,8 @@ static int build_mem_elf64_phdr(const ch
|
|
return 0;
|
|
}
|
|
|
|
-static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
|
|
+static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags)
|
|
{
|
|
size_t phdr_size, mem_phdr_size;
|
|
int i;
|
|
@@ -418,9 +419,11 @@ static int build_mem_phdrs(const char *b
|
|
|
|
/* Check the program headers to be certain
|
|
* they are safe to use.
|
|
+ * Skip the check if ELF_SKIP_FILESZ_CHECK is set.
|
|
*/
|
|
phdr = &ehdr->e_phdr[i];
|
|
- if ((phdr->p_offset + phdr->p_filesz) > len) {
|
|
+ if (!(flags & ELF_SKIP_FILESZ_CHECK)
|
|
+ && (phdr->p_offset + phdr->p_filesz) > len) {
|
|
/* The segment does not fit in the buffer */
|
|
if (probe_debug) {
|
|
fprintf(stderr, "ELF segment not in file\n");
|
|
@@ -580,7 +583,8 @@ static int build_mem_elf64_shdr(const ch
|
|
return 0;
|
|
}
|
|
|
|
-static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
|
|
+static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags)
|
|
{
|
|
size_t shdr_size, mem_shdr_size;
|
|
int i;
|
|
@@ -628,11 +632,12 @@ static int build_mem_shdrs(const char *b
|
|
}
|
|
/* Check the section headers to be certain
|
|
* they are safe to use.
|
|
+ * Skip the check if ELF_SKIP_FILESZ_CHECK is set.
|
|
*/
|
|
shdr = &ehdr->e_shdr[i];
|
|
- if ((shdr->sh_type != SHT_NOBITS) &&
|
|
- ((shdr->sh_offset + shdr->sh_size) > len))
|
|
- {
|
|
+ if (!(flags & ELF_SKIP_FILESZ_CHECK)
|
|
+ && (shdr->sh_type != SHT_NOBITS)
|
|
+ && (shdr->sh_offset + shdr->sh_size) > len) {
|
|
/* The section does not fit in the buffer */
|
|
if (probe_debug) {
|
|
fprintf(stderr, "ELF section %d not in file\n",
|
|
@@ -710,7 +715,8 @@ static int build_mem_notes(const char *b
|
|
note_size += (hdr.n_descsz + 3) & ~3;
|
|
|
|
if ((hdr.n_namesz != 0) && (name[hdr.n_namesz -1] != '\0')) {
|
|
- die("Note name is not null termiated");
|
|
+ fprintf(stderr, "Note name is not null termiated\n");
|
|
+ return -1;
|
|
}
|
|
ehdr->e_note[i].n_type = hdr.n_type;
|
|
ehdr->e_note[i].n_name = (char *)name;
|
|
@@ -729,7 +735,8 @@ void free_elf_info(struct mem_ehdr *ehdr
|
|
memset(ehdr, 0, sizeof(*ehdr));
|
|
}
|
|
|
|
-int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
|
|
+int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags)
|
|
{
|
|
int result;
|
|
result = build_mem_ehdr(buf, len, ehdr);
|
|
@@ -737,14 +744,14 @@ int build_elf_info(const char *buf, off_
|
|
return result;
|
|
}
|
|
if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) {
|
|
- result = build_mem_phdrs(buf, len, ehdr);
|
|
+ result = build_mem_phdrs(buf, len, ehdr, flags);
|
|
if (result < 0) {
|
|
free_elf_info(ehdr);
|
|
return result;
|
|
}
|
|
}
|
|
if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) {
|
|
- result = build_mem_shdrs(buf, len, ehdr);
|
|
+ result = build_mem_shdrs(buf, len, ehdr, flags);
|
|
if (result < 0) {
|
|
free_elf_info(ehdr);
|
|
return result;
|
|
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -56,7 +56,7 @@ int elf_ia64_probe(const char *buf, off_
|
|
{
|
|
struct mem_ehdr ehdr;
|
|
int result;
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
if (probe_debug) {
|
|
fprintf(stderr, "Not an ELF executable\n");
|
|
@@ -163,7 +163,7 @@ int elf_ia64_load(int argc, char **argv,
|
|
}
|
|
|
|
/* Parse the Elf file */
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
fprintf(stderr, "ELF parse failed\n");
|
|
free_elf_info(&ehdr);
|
|
@@ -198,7 +198,7 @@ int elf_ia64_load(int argc, char **argv,
|
|
|
|
/* Load the setup code */
|
|
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
|
|
- 0x0, ULONG_MAX, -1);
|
|
+ 0x0, ULONG_MAX, -1, 0);
|
|
|
|
|
|
if (load_crashdump_segments(info, &ehdr, max_addr, 0,
|
|
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -24,8 +24,10 @@
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <elf.h>
|
|
+#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
+#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
#include "../../kexec.h"
|
|
#include "../../kexec-elf.h"
|
|
@@ -40,6 +42,137 @@ extern struct arch_options_t arch_option
|
|
/* Forward Declaration. */
|
|
static int exclude_crash_reserve_region(int *nr_ranges);
|
|
|
|
+#define KERN_VADDR_ALIGN 0x200000 /* 2MB */
|
|
+
|
|
+/* Read kernel physical load addr from /proc/iomem (Kernel Code) and
|
|
+ * store in kexec_info */
|
|
+static int get_kernel_paddr(struct kexec_info *info)
|
|
+{
|
|
+ const char iomem[]= "/proc/iomem";
|
|
+ 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;
|
|
+ }
|
|
+ while(fgets(line, sizeof(line), fp) != 0) {
|
|
+ char *str;
|
|
+ int consumed, count;
|
|
+ count = sscanf(line, "%Lx-%Lx : %n",
|
|
+ &start, &end, &consumed);
|
|
+ if (count != 2)
|
|
+ continue;
|
|
+ str = line + consumed;
|
|
+#ifdef DEBUG
|
|
+ printf("%016Lx-%016Lx : %s",
|
|
+ start, end, str);
|
|
+#endif
|
|
+ if (memcmp(str, "Kernel code\n", 12) == 0) {
|
|
+ info->kern_paddr_start = start;
|
|
+
|
|
+#ifdef DEBUG
|
|
+ printf("kernel load physical addr start = 0x%016Lx\n",
|
|
+ start);
|
|
+#endif
|
|
+ fclose(fp);
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ fprintf(stderr, "Cannot determine kernel physical load addr\n");
|
|
+ fclose(fp);
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* Hardcoding kernel virtual address and size. While writting
|
|
+ * this patch vanilla kernel is compiled for addr 2MB. Anybody
|
|
+ * using kernel older than that which was compiled for 1MB
|
|
+ * physical addr, use older version of kexec-tools. This function
|
|
+ * is there just for backward compatibility reasons and we should
|
|
+ * get rid of it at some point of time.
|
|
+ */
|
|
+
|
|
+static int hardcode_kernel_vaddr_size(struct kexec_info *info)
|
|
+{
|
|
+ fprintf(stderr, "Warning: Hardcoding kernel virtual addr and size\n");
|
|
+ info->kern_vaddr_start = __START_KERNEL_map + 0x200000;
|
|
+ info->kern_size = KERNEL_TEXT_SIZE - 0x200000;
|
|
+ fprintf(stderr, "Warning: virtual addr = 0x%lx size = 0x%lx\n",
|
|
+ info->kern_vaddr_start, info->kern_size);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* Retrieve info regarding virtual address kernel has been compiled for and
|
|
+ * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
|
|
+ * from kexec-tools fails because of malformed elf notes. A kernel patch has
|
|
+ * been submitted. For the folks using older kernels, this function
|
|
+ * hard codes the values to remain backward compatible. Once things stablize
|
|
+ * we should get rid of backward compatible code. */
|
|
+
|
|
+static int get_kernel_vaddr_and_size(struct kexec_info *info)
|
|
+{
|
|
+ int result;
|
|
+ const char kcore[] = "/proc/kcore";
|
|
+ char *buf;
|
|
+ struct mem_ehdr ehdr;
|
|
+ struct mem_phdr *phdr, *end_phdr;
|
|
+ int align;
|
|
+ unsigned long size;
|
|
+ uint32_t elf_flags = 0;
|
|
+
|
|
+ align = getpagesize();
|
|
+ size = KCORE_ELF_HEADERS_SIZE;
|
|
+ buf = slurp_file_len(kcore, size);
|
|
+ if (!buf) {
|
|
+ fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /* Don't perform checks to make sure stated phdrs and shdrs are
|
|
+ * actually present in the core file. It is not practical
|
|
+ * to read the GB size file into a user space buffer, Given the
|
|
+ * fact that we don't use any info from that.
|
|
+ */
|
|
+ elf_flags |= ELF_SKIP_FILESZ_CHECK;
|
|
+ result = build_elf_core_info(buf, size, &ehdr, elf_flags);
|
|
+ if (result < 0) {
|
|
+ fprintf(stderr, "ELF core (kcore) parse failed\n");
|
|
+ hardcode_kernel_vaddr_size(info);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* Traverse through the Elf headers and find the region where
|
|
+ * kernel is mapped. */
|
|
+ end_phdr = &ehdr.e_phdr[ehdr.e_phnum];
|
|
+ for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
|
|
+ if (phdr->p_type == PT_LOAD) {
|
|
+ unsigned long saddr = phdr->p_vaddr;
|
|
+ unsigned long eaddr = phdr->p_vaddr + phdr->p_memsz;
|
|
+ unsigned long size;
|
|
+
|
|
+ /* Look for kernel text mapping header. */
|
|
+ if ((saddr >= __START_KERNEL_map) &&
|
|
+ (eaddr <= __START_KERNEL_map + KERNEL_TEXT_SIZE)) {
|
|
+ saddr = (saddr) & (~(KERN_VADDR_ALIGN - 1));
|
|
+ info->kern_vaddr_start = saddr;
|
|
+ size = eaddr - saddr;
|
|
+ /* Align size to page size boundary. */
|
|
+ size = (size + align - 1) & (~(align - 1));
|
|
+ info->kern_size = size;
|
|
+#ifdef DEBUG
|
|
+ printf("kernel vaddr = 0x%lx size = 0x%lx\n",
|
|
+ saddr, size);
|
|
+#endif
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ fprintf(stderr, "Can't find kernel text map area from kcore\n");
|
|
+ return -1;
|
|
+}
|
|
+
|
|
/* 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];
|
|
@@ -245,7 +378,7 @@ static int add_memmap(struct memory_rang
|
|
memmap_p[j+1] = memmap_p[j];
|
|
memmap_p[tidx].start = addr;
|
|
memmap_p[tidx].end = addr + size - 1;
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("Memmap after adding segment\n");
|
|
for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
|
|
mstart = memmap_p[i].start;
|
|
@@ -330,7 +463,7 @@ static int delete_memmap(struct memory_r
|
|
memmap_p[j-1] = memmap_p[j];
|
|
memmap_p[j-1].start = memmap_p[j-1].end = 0;
|
|
}
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("Memmap after deleting segment\n");
|
|
for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
|
|
mstart = memmap_p[i].start;
|
|
@@ -404,7 +537,7 @@ static int cmdline_add_memmap(char *cmdl
|
|
die("Command line overflow\n");
|
|
strcat(cmdline, str_mmap);
|
|
}
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("Command line after adding memmap\n");
|
|
printf("%s\n", cmdline);
|
|
#endif
|
|
@@ -432,7 +565,7 @@ static int cmdline_add_elfcorehdr(char *
|
|
if (cmdlen > (COMMAND_LINE_SIZE - 1))
|
|
die("Command line overflow\n");
|
|
strcat(cmdline, str);
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("Command line after adding elfcorehdr\n");
|
|
printf("%s\n", cmdline);
|
|
#endif
|
|
@@ -465,7 +598,7 @@ static int cmdline_add_memmap_acpi(char
|
|
die("Command line overflow\n");
|
|
strcat(cmdline, str_mmap);
|
|
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("Command line after adding acpi memmap\n");
|
|
printf("%s\n", cmdline);
|
|
#endif
|
|
@@ -536,6 +669,27 @@ static int prepare_crash_memory_elf64_he
|
|
(elf->e_phnum)++;
|
|
}
|
|
|
|
+ /* Setup an PT_LOAD type program header for the region where
|
|
+ * Kernel is mapped.
|
|
+ */
|
|
+ phdr = (Elf64_Phdr *) bufp;
|
|
+ bufp += sizeof(Elf64_Phdr);
|
|
+ phdr->p_type = PT_LOAD;
|
|
+ phdr->p_flags = PF_R|PF_W|PF_X;
|
|
+ phdr->p_offset = phdr->p_paddr = info->kern_paddr_start;
|
|
+ phdr->p_vaddr = info->kern_vaddr_start;
|
|
+ phdr->p_filesz = phdr->p_memsz = info->kern_size;
|
|
+ phdr->p_align = 0;
|
|
+ (elf->e_phnum)++;
|
|
+#ifdef DEBUG
|
|
+ printf("Kernel text Elf header: p_type = %d, p_offset = 0x%lx "
|
|
+ "p_paddr = 0x%lx p_vaddr = 0x%lx "
|
|
+ "p_filesz = 0x%lx p_memsz = 0x%lx\n",
|
|
+ phdr->p_type, phdr->p_offset, phdr->p_paddr,
|
|
+ phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
|
|
+#endif
|
|
+
|
|
+
|
|
/* Setup PT_LOAD type program header for every system RAM chunk.
|
|
* A seprate program header for Backup Region*/
|
|
for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
|
|
@@ -555,21 +709,13 @@ static int prepare_crash_memory_elf64_he
|
|
else
|
|
phdr->p_offset = mstart;
|
|
|
|
- /* Handle linearly mapped region.*/
|
|
+ /* We already prepared the header for kernel text. Map
|
|
+ * rest of the memory segments to kernel linearly mapped
|
|
+ * memory region.
|
|
+ */
|
|
|
|
- /* Filling the vaddr conditionally as we have two linearly
|
|
- * mapped regions here. One is __START_KERNEL_map 0 to 40 MB
|
|
- * other one is PAGE_OFFSET */
|
|
-
|
|
- if ((mend <= (MAXMEM - 1)) && mstart < KERNEL_TEXT_SIZE)
|
|
- phdr->p_vaddr = mstart + __START_KERNEL_map;
|
|
- else {
|
|
- if (mend <= (MAXMEM - 1))
|
|
- phdr->p_vaddr = mstart + PAGE_OFFSET;
|
|
- else
|
|
- phdr->p_vaddr = -1ULL;
|
|
- }
|
|
phdr->p_paddr = mstart;
|
|
+ phdr->p_vaddr = mstart + PAGE_OFFSET;
|
|
phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
|
|
/* Do we need any alignment of segments? */
|
|
phdr->p_align = 0;
|
|
@@ -593,6 +739,12 @@ int load_crashdump_segments(struct kexec
|
|
long int nr_cpus = 0;
|
|
struct memory_range *mem_range, *memmap_p;
|
|
|
|
+ if (get_kernel_paddr(info))
|
|
+ return -1;
|
|
+
|
|
+ if (get_kernel_vaddr_and_size(info))
|
|
+ return -1;
|
|
+
|
|
if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
|
|
return -1;
|
|
|
|
@@ -638,7 +790,7 @@ int load_crashdump_segments(struct kexec
|
|
* This is a makeshift solution until it is fixed in kernel.
|
|
*/
|
|
elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
|
|
- max_addr, 1);
|
|
+ max_addr, -1);
|
|
if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
|
|
return -1;
|
|
cmdline_add_memmap(mod_cmdline, memmap_p);
|
|
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-rel-x86_64.c.orig 2004-12-21 12:51:24.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-rel-x86_64.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -60,7 +60,7 @@ static const char *reloc_name(unsigned l
|
|
void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
|
|
void *location, unsigned long address, unsigned long value)
|
|
{
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
fprintf(stderr, "%s\n", reloc_name(r_type));
|
|
#endif
|
|
switch(r_type) {
|
|
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -47,7 +47,7 @@ int elf_x86_64_probe(const char *buf, of
|
|
|
|
struct mem_ehdr ehdr;
|
|
int result;
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
if (probe_debug) {
|
|
fprintf(stderr, "Not an ELF executable\n");
|
|
@@ -177,7 +177,7 @@ int elf_x86_64_load(int argc, char **arg
|
|
}
|
|
|
|
/* Load the ELF executable */
|
|
- elf_exec_build_load(info, &ehdr, buf, len);
|
|
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
|
|
|
|
entry = ehdr.e_entry;
|
|
max_addr = elf_max_addr(&ehdr);
|
|
@@ -186,7 +186,7 @@ int elf_x86_64_load(int argc, char **arg
|
|
if (arg_style != ARG_STYLE_NONE) {
|
|
/* Load the setup code */
|
|
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
|
|
- 0, ULONG_MAX, 1);
|
|
+ 0, ULONG_MAX, 1, 0);
|
|
}
|
|
if (arg_style == ARG_STYLE_NONE) {
|
|
info->entry = (void *)entry;
|
|
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -64,7 +64,7 @@ int get_memory_ranges(struct memory_rang
|
|
continue;
|
|
str = line + consumed;
|
|
end = end + 1;
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("%016Lx-%016Lx : %s",
|
|
start, end, str);
|
|
#endif
|
|
@@ -104,7 +104,7 @@ int get_memory_ranges(struct memory_rang
|
|
memory_range[memory_ranges].start = start;
|
|
memory_range[memory_ranges].end = end;
|
|
memory_range[memory_ranges].type = type;
|
|
-#if 0
|
|
+#ifdef DEBUG
|
|
printf("%016Lx-%016Lx : %x\n",
|
|
start, end, type);
|
|
#endif
|
|
--- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -47,7 +47,7 @@ int elf_x86_probe(const char *buf, off_t
|
|
|
|
struct mem_ehdr ehdr;
|
|
int result;
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
if (probe_debug) {
|
|
fprintf(stderr, "Not an ELF executable\n");
|
|
@@ -177,7 +177,7 @@ int elf_x86_load(int argc, char **argv,
|
|
}
|
|
|
|
/* Load the ELF executable */
|
|
- elf_exec_build_load(info, &ehdr, buf, len);
|
|
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
|
|
|
|
entry = ehdr.e_entry;
|
|
max_addr = elf_max_addr(&ehdr);
|
|
@@ -186,7 +186,7 @@ int elf_x86_load(int argc, char **argv,
|
|
if (arg_style != ARG_STYLE_NONE) {
|
|
/* Load the setup code */
|
|
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
|
|
- 0, ULONG_MAX, 1);
|
|
+ 0, ULONG_MAX, 1, 0);
|
|
}
|
|
if (arg_style == ARG_STYLE_NONE) {
|
|
info->entry = (void *)entry;
|
|
--- kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -209,10 +209,11 @@ int multiboot_x86_load(int argc, char **
|
|
|
|
|
|
/* Load the ELF executable */
|
|
- elf_exec_build_load(info, &ehdr, buf, len);
|
|
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
|
|
|
|
/* Load the setup code */
|
|
- elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0, ULONG_MAX, 1);
|
|
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0,
|
|
+ ULONG_MAX, 1, 0);
|
|
|
|
/* The first segment will contain the multiboot headers:
|
|
* =============
|
|
--- kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c.orig 2005-01-20 14:10:56.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -72,7 +72,7 @@ int elf_ppc_probe(const char *buf, off_t
|
|
|
|
struct mem_ehdr ehdr;
|
|
int result;
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
goto out;
|
|
}
|
|
@@ -180,7 +180,7 @@ int elf_ppc_load(int argc, char **argv,
|
|
}
|
|
|
|
/* Parse the Elf file */
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
free_elf_info(&ehdr);
|
|
return result;
|
|
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -52,7 +52,7 @@ int elf_ppc64_probe(const char *buf, off
|
|
{
|
|
struct mem_ehdr ehdr;
|
|
int result;
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
goto out;
|
|
}
|
|
@@ -163,7 +163,7 @@ int elf_ppc64_load(int argc, char **argv
|
|
}
|
|
|
|
/* Parse the Elf file */
|
|
- result = build_elf_exec_info(buf, len, &ehdr);
|
|
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
|
|
if (result < 0) {
|
|
free_elf_info(&ehdr);
|
|
return result;
|
|
@@ -213,7 +213,7 @@ int elf_ppc64_load(int argc, char **argv
|
|
memcpy(seg_buf, purgatory, purgatory_size);
|
|
seg_size = purgatory_size;
|
|
elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
|
|
- purgatory_size, 0, max_addr, 1);
|
|
+ purgatory_size, 0, max_addr, 1, 0);
|
|
|
|
/* Add a ram-disk to the current image
|
|
* Note: Add the ramdisk after elf_rel_build_load
|
|
--- /dev/null 2006-12-27 08:05:56.458406418 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec-elf-core.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -0,0 +1,29 @@
|
|
+#include <stdio.h>
|
|
+#include <stdint.h>
|
|
+#include <errno.h>
|
|
+#include <stdlib.h>
|
|
+#include "elf.h"
|
|
+#include "kexec-elf.h"
|
|
+
|
|
+
|
|
+int build_elf_core_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags)
|
|
+{
|
|
+ int result;
|
|
+ result = build_elf_info(buf, len, ehdr, flags);
|
|
+ if (result < 0) {
|
|
+ return result;
|
|
+ }
|
|
+ if ((ehdr->e_type != ET_CORE)) {
|
|
+ /* not an ELF Core */
|
|
+ fprintf(stderr, "Not ELF type ET_CORE\n");
|
|
+ return -1;
|
|
+ }
|
|
+ if (!ehdr->e_phdr) {
|
|
+ /* No program header */
|
|
+ fprintf(stderr, "No ELF program header\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
--- kexec-tools-1.101/kexec/kexec-elf.h.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec-elf.h 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -82,22 +82,29 @@ typedef struct
|
|
uint32_t n_type; /* Type of the note. */
|
|
} ElfNN_Nhdr;
|
|
|
|
+/* Misc flags */
|
|
|
|
+#define ELF_SKIP_FILESZ_CHECK 0x00000001
|
|
|
|
extern void free_elf_info(struct mem_ehdr *ehdr);
|
|
-extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
|
|
-extern int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
|
|
-extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
|
|
+extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags);
|
|
+extern int build_elf_exec_info(const char *buf, off_t len,
|
|
+ struct mem_ehdr *ehdr, uint32_t flags);
|
|
+extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags);
|
|
|
|
+extern int build_elf_core_info(const char *buf, off_t len,
|
|
+ struct mem_ehdr *ehdr, uint32_t flags);
|
|
extern int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info);
|
|
extern int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info,
|
|
unsigned long min, unsigned long max, int end);
|
|
|
|
extern void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
|
|
- const char *buf, off_t len);
|
|
+ const char *buf, off_t len, uint32_t flags);
|
|
extern void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
|
|
const char *buf, off_t len, unsigned long min, unsigned long max,
|
|
- int end);
|
|
+ int end, uint32_t flags);
|
|
|
|
extern int elf_rel_find_symbol(struct mem_ehdr *ehdr,
|
|
const char *name, struct mem_sym *ret_sym);
|
|
--- kexec-tools-1.101/kexec/kexec-elf-exec.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec-elf-exec.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -11,11 +11,12 @@
|
|
|
|
static const int probe_debug = 0;
|
|
|
|
-int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
|
|
+int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
|
|
+ uint32_t flags)
|
|
{
|
|
struct mem_phdr *phdr, *end_phdr;
|
|
int result;
|
|
- result = build_elf_info(buf, len, ehdr);
|
|
+ result = build_elf_info(buf, len, ehdr, flags);
|
|
if (result < 0) {
|
|
return result;
|
|
}
|
|
@@ -136,11 +137,11 @@ int elf_exec_load(struct mem_ehdr *ehdr,
|
|
}
|
|
|
|
void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
|
|
- const char *buf, off_t len)
|
|
+ const char *buf, off_t len, uint32_t flags)
|
|
{
|
|
int result;
|
|
/* Parse the Elf file */
|
|
- result = build_elf_exec_info(buf, len, ehdr);
|
|
+ result = build_elf_exec_info(buf, len, ehdr, flags);
|
|
if (result < 0) {
|
|
die("ELF exec parse failed\n");
|
|
}
|
|
--- kexec-tools-1.101/kexec/crashdump.h.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/crashdump.h 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -5,5 +5,7 @@ extern int get_crash_notes_per_cpu(int c
|
|
|
|
/* Need to find a better way to determine per cpu notes section size. */
|
|
#define MAX_NOTE_BYTES 1024
|
|
+/* Expecting ELF headers to fit in 4K. Increase it if you need more. */
|
|
+#define KCORE_ELF_HEADERS_SIZE 4096
|
|
|
|
#endif /* CRASHDUMP_H */
|
|
--- kexec-tools-1.101/kexec/kexec.h.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec.h 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -116,6 +116,9 @@ struct kexec_info {
|
|
struct mem_ehdr rhdr;
|
|
unsigned long backup_start;
|
|
unsigned long kexec_flags;
|
|
+ unsigned long kern_vaddr_start;
|
|
+ unsigned long kern_paddr_start;
|
|
+ unsigned long kern_size;
|
|
};
|
|
|
|
void usage(void);
|
|
@@ -177,6 +180,7 @@ extern void die(char *fmt, ...);
|
|
extern void *xmalloc(size_t size);
|
|
extern void *xrealloc(void *ptr, size_t size);
|
|
extern char *slurp_file(const char *filename, off_t *r_size);
|
|
+extern char *slurp_file_len(const char *filename, off_t size);
|
|
extern char *slurp_decompress_file(const char *filename, off_t *r_size);
|
|
extern void add_segment(struct kexec_info *info,
|
|
const void *buf, size_t bufsz, unsigned long base, size_t memsz);
|
|
--- kexec-tools-1.101/kexec/kexec.c.orig 2007-01-05 13:32:05.000000000 -0500
|
|
+++ kexec-tools-1.101/kexec/kexec.c 2007-01-05 13:32:24.000000000 -0500
|
|
@@ -391,6 +391,50 @@ char *slurp_file(const char *filename, o
|
|
return buf;
|
|
}
|
|
|
|
+/* This functions reads either specified number of bytes from the file or
|
|
+ lesser if EOF is met. */
|
|
+
|
|
+char *slurp_file_len(const char *filename, off_t size)
|
|
+{
|
|
+ int fd;
|
|
+ char *buf;
|
|
+ off_t progress;
|
|
+ ssize_t result;
|
|
+
|
|
+ if (!filename)
|
|
+ return 0;
|
|
+ fd = open(filename, O_RDONLY);
|
|
+ if (fd < 0) {
|
|
+ fprintf(stderr, "Cannot open %s: %s\n", filename,
|
|
+ strerror(errno));
|
|
+ return 0;
|
|
+ }
|
|
+ buf = xmalloc(size);
|
|
+ progress = 0;
|
|
+ while(progress < size) {
|
|
+ result = read(fd, buf + progress, size - progress);
|
|
+ if (result < 0) {
|
|
+ if ((errno == EINTR) || (errno == EAGAIN))
|
|
+ continue;
|
|
+ fprintf(stderr, "read on %s of %ld bytes failed: %s\n",
|
|
+ filename, (size - progress)+ 0UL,
|
|
+ strerror(errno));
|
|
+ free(buf);
|
|
+ return 0;
|
|
+ }
|
|
+ if (result == 0)
|
|
+ /* EOF */
|
|
+ break;
|
|
+ progress += result;
|
|
+ }
|
|
+ result = close(fd);
|
|
+ if (result < 0) {
|
|
+ die("Close of %s failed: %s\n",
|
|
+ filename, strerror(errno));
|
|
+ }
|
|
+ return buf;
|
|
+}
|
|
+
|
|
#if HAVE_ZLIB_H
|
|
char *slurp_decompress_file(const char *filename, off_t *r_size)
|
|
{
|