This patch adds support for reserving space for backup region. Also adds code 
in purgatory to copy the first 640K to backup region.
---

Signed-off-by: Vivek Goyal <[EMAIL PROTECTED]>
---


diff -puN /dev/null kexec/arch/i386/crashdump-x86.h
--- /dev/null   2004-06-16 19:10:55.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/crashdump-x86.h      2005-02-24 
18:55:46.000000000 +0530
@@ -0,0 +1,9 @@
+#ifndef CRASHDUMP_X86_H
+#define CRASHDUMP_X86_H
+
+/* Backup Region, First 640K of System RAM. */
+#define BACKUP_START   0x00000000
+#define BACKUP_END     0x0009ffff
+#define BACKUP_SIZE    (BACKUP_END - BACKUP_START + 1)
+
+#endif /* CRASHDUMP_X86_H */
diff -puN kexec/arch/i386/kexec-beoboot-x86.c~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/kexec-beoboot-x86.c
--- 
kexec-tools-1.101/kexec/arch/i386/kexec-beoboot-x86.c~kexec-tools-crashdump-backup-x86
      2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/kexec-beoboot-x86.c  2005-02-24 
18:55:46.000000000 +0530
@@ -76,7 +76,7 @@ void beoboot_usage(void)
 #define INITRD_BASE 0x1000000 /* 16MB */
 
 int beoboot_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        struct beoboot_header bb_header;
        const unsigned char *command_line, *kernel, *initrd;
diff -puN kexec/arch/i386/kexec-bzImage.c~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/kexec-bzImage.c
--- 
kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c~kexec-tools-crashdump-backup-x86
  2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/kexec-bzImage.c      2005-02-24 
18:55:46.000000000 +0530
@@ -221,7 +221,7 @@ int do_bzImage_load(struct kexec_info *i
 }
        
 int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        const char *command_line;
        const char *ramdisk;
diff -puN kexec/arch/i386/kexec-elf-x86.c~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/kexec-elf-x86.c
--- 
kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c~kexec-tools-crashdump-backup-x86
  2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/kexec-elf-x86.c      2005-02-24 
18:55:46.000000000 +0530
@@ -32,10 +32,12 @@
 #include <elf.h>
 #include <x86/x86-linux.h>
 #include "../../kexec.h"
+#include "../../kexec-syscall.h"
 #include "../../kexec-elf.h"
 #include "../../kexec-elf-boot.h"
 #include "x86-linux-setup.h"
 #include "kexec-x86.h"
+#include "crashdump-x86.h"
 #include <arch/options.h>
 
 static const int probe_debug = 0;
@@ -82,7 +84,7 @@ void elf_x86_usage(void)
 }
 
 int elf_x86_load(int argc, char **argv, const char *buf, off_t len, 
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        struct mem_ehdr ehdr;
        const char *command_line;
@@ -221,6 +223,21 @@ int elf_x86_load(int argc, char **argv, 
                        ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
                }
 
+               /* If panic kernel is being loaded, additional segments need
+                * to be created. */
+               if (kexec_flags & KEXEC_ON_CRASH) {
+                       void *tmp;
+                       unsigned long sz;
+                       int nr_ranges, align = 1024;
+                       /* Create a backup region segment to store first 638K
+                        * memory*/
+                       sz = (BACKUP_SIZE + align - 1) & ~(align - 1);
+                       tmp = xmalloc(sz);
+                       memset(tmp, 0, sz);
+                       info->backup_start = add_buffer(info, tmp, sz, sz, 1024,
+                                               0, max_addr, 1);
+               }
+
                /* Tell the kernel what is going on */
                setup_linux_bootloader_parameters(info, &hdr->hdr, param_base, 
                        offsetof(struct x86_linux_faked_param_header, 
command_line),
diff -puN 
kexec/arch/i386/kexec-multiboot-x86.c~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/kexec-multiboot-x86.c
--- 
kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c~kexec-tools-crashdump-backup-x86
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/kexec-multiboot-x86.c        
2005-02-24 18:55:46.000000000 +0530
@@ -138,7 +138,7 @@ void multiboot_x86_usage(void)
 }
 
 int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 /* Marshal up a multiboot-style kernel */
 {
        struct multiboot_info *mbi;
@@ -246,7 +246,7 @@ int multiboot_x86_load(int argc, char **
        mbi->boot_loader_name = sizeof(*mbi) + command_line_len; 
 
        /* Memory map */
-       if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+       if ((get_memory_ranges(&range, &ranges, kexec_flags) < 0) || ranges == 
0) {
                fprintf(stderr, "Cannot get memory information\n");
                return -1;
        }
diff -puN kexec/arch/i386/kexec-x86.c~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/kexec-x86.c
--- 
kexec-tools-1.101/kexec/arch/i386/kexec-x86.c~kexec-tools-crashdump-backup-x86  
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/kexec-x86.c  2005-02-24 
18:55:46.000000000 +0530
@@ -37,7 +37,8 @@
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+                               unsigned long kexec_flags)
 {
        const char iomem[]= "/proc/iomem";
        int memory_ranges = 0;
@@ -79,6 +80,20 @@ int get_memory_ranges(struct memory_rang
                else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
                        type = RANGE_ACPI_NVS;
                }
+               else if (memcmp(str, "Crash kernel\n", 13) == 0) {
+               /* Redefine the memory region boundaries if kernel
+                * exports the limits and if it is panic kernel.
+                * Override user values only if kernel exported values are
+                * subset of user defined values.
+                */
+                       if (kexec_flags & KEXEC_ON_CRASH) {
+                               if (start > mem_min)
+                                       mem_min = start;
+                               if (end < mem_max)
+                                       mem_max = end;
+                       }
+                       continue;
+               }
                else {
                        continue;
                }
@@ -247,8 +262,10 @@ int arch_compat_trampoline(struct kexec_
        return 0;
 }
 
-void arch_update_purgatory(struct kexec_info *info)
+void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
 {
+       uint8_t panic_kernel = 0;
+
        elf_rel_set_symbol(&info->rhdr, "reset_vga",
                &arch_options.reset_vga, sizeof(arch_options.reset_vga));
        elf_rel_set_symbol(&info->rhdr, "serial_base",
@@ -259,4 +276,11 @@ void arch_update_purgatory(struct kexec_
                &arch_options.console_vga, sizeof(arch_options.console_vga));
        elf_rel_set_symbol(&info->rhdr, "console_serial", 
                &arch_options.console_serial, 
sizeof(arch_options.console_serial));
+       if (kexec_flags & KEXEC_ON_CRASH) {
+               panic_kernel = 1;
+               elf_rel_set_symbol(&info->rhdr, "backup_start",
+                               &info->backup_start, 
sizeof(info->backup_start));
+       }
+       elf_rel_set_symbol(&info->rhdr, "panic_kernel",
+               &panic_kernel, sizeof(panic_kernel));
 }
diff -puN kexec/arch/i386/kexec-x86.h~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/kexec-x86.h
--- 
kexec-tools-1.101/kexec/arch/i386/kexec-x86.h~kexec-tools-crashdump-backup-x86  
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/kexec-x86.h  2005-02-24 
18:55:46.000000000 +0530
@@ -37,17 +37,17 @@ struct entry16_regs {
 
 int multiboot_x86_probe(const char *buf, off_t len);
 int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void multiboot_x86_usage(void);
 
 int elf_x86_probe(const char *buf, off_t len);
 int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void elf_x86_usage(void);
 
 int bzImage_probe(const char *buf, off_t len);
 int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void bzImage_usage(void);
 int do_bzImage_load(struct kexec_info *info,
        const char *kernel, off_t kernel_len,
@@ -57,7 +57,7 @@ int do_bzImage_load(struct kexec_info *i
 
 int beoboot_probe(const char *buf, off_t len);
 int beoboot_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void beoboot_usage(void);
 
 int nbi_probe(const char *buf, off_t len);
diff -puN kexec/arch/i386/x86-linux-setup.c~kexec-tools-crashdump-backup-x86 
kexec/arch/i386/x86-linux-setup.c
--- 
kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c~kexec-tools-crashdump-backup-x86
        2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/i386/x86-linux-setup.c    2005-02-24 
18:55:46.000000000 +0530
@@ -99,6 +99,7 @@ void setup_linux_system_parameters(struc
        /* Fill in information the BIOS would usually provide */
        struct memory_range *range;
        int i, ranges;
+       unsigned long kexec_flags = 0;
        
        /* Default screen size */
        real_mode->orig_x = 0;
@@ -135,7 +136,7 @@ void setup_linux_system_parameters(struc
        real_mode->aux_device_info = 0;
 
        /* Fill in the memory info */
-       if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+       if ((get_memory_ranges(&range, &ranges, kexec_flags) < 0) || ranges == 
0) {
                die("Cannot get memory information\n");
        }
        if (ranges > E820MAX) {
diff -puN kexec/arch/ia64/kexec-elf-ia64.c~kexec-tools-crashdump-backup-x86 
kexec/arch/ia64/kexec-elf-ia64.c
--- 
kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c~kexec-tools-crashdump-backup-x86
 2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ia64/kexec-elf-ia64.c     2005-02-24 
18:55:46.000000000 +0530
@@ -78,7 +78,7 @@ void elf_ia64_usage(void)
 }
 
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        struct mem_ehdr ehdr;
        const char *command_line;
diff -puN kexec/arch/ia64/kexec-ia64.c~kexec-tools-crashdump-backup-x86 
kexec/arch/ia64/kexec-ia64.c
--- 
kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c~kexec-tools-crashdump-backup-x86 
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ia64/kexec-ia64.c 2005-02-24 
18:55:46.000000000 +0530
@@ -38,7 +38,8 @@
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /* Return a sorted list of available memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+                               unsigned long kexec_flags)
 {
        int memory_ranges;
        /*
@@ -150,7 +151,7 @@ int arch_compat_trampoline(struct kexec_
        return 0;
 }
 
-void arch_update_purgatory(struct kexec_info *info)
+void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
 {
 }
 
diff -puN kexec/arch/ia64/kexec-ia64.h~kexec-tools-crashdump-backup-x86 
kexec/arch/ia64/kexec-ia64.h
--- 
kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h~kexec-tools-crashdump-backup-x86 
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ia64/kexec-ia64.h 2005-02-24 
18:55:46.000000000 +0530
@@ -3,7 +3,7 @@
 
 int elf_ia64_probe(const char *buf, off_t len);
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void elf_ia64_usage(void);
 
 #endif /* KEXEC_IA64_H */
diff -puN kexec/arch/ppc/kexec-dol-ppc.c~kexec-tools-crashdump-backup-x86 
kexec/arch/ppc/kexec-dol-ppc.c
--- 
kexec-tools-1.101/kexec/arch/ppc/kexec-dol-ppc.c~kexec-tools-crashdump-backup-x86
   2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-dol-ppc.c       2005-02-24 
18:55:46.000000000 +0530
@@ -320,7 +320,7 @@ void dol_ppc_usage(void)
 }
 
 int dol_ppc_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        dol_header header, *h;
        unsigned long entry;
diff -puN kexec/arch/ppc/kexec-elf-ppc.c~kexec-tools-crashdump-backup-x86 
kexec/arch/ppc/kexec-elf-ppc.c
--- 
kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c~kexec-tools-crashdump-backup-x86
   2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-elf-ppc.c       2005-02-24 
18:55:46.000000000 +0530
@@ -124,7 +124,7 @@ static void gamecube_hack_addresses(stru
 }
 
 int elf_ppc_load(int argc, char **argv,        const char *buf, off_t len, 
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        struct mem_ehdr ehdr;
        char *arg_buf;
diff -puN kexec/arch/ppc/kexec-ppc.c~kexec-tools-crashdump-backup-x86 
kexec/arch/ppc/kexec-ppc.c
--- 
kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.c~kexec-tools-crashdump-backup-x86   
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-ppc.c   2005-02-24 
18:55:46.000000000 +0530
@@ -23,7 +23,8 @@
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+                                       unsigned long kexec_flags)
 {
        int memory_ranges = 0;
 #ifdef CONFIG_GAMECUBE
@@ -145,7 +146,7 @@ int arch_compat_trampoline(struct kexec_
        return 0;
 }
 
-void arch_update_purgatory(struct kexec_info *info)
+void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
 {
 }
 
diff -puN kexec/arch/ppc/kexec-ppc.h~kexec-tools-crashdump-backup-x86 
kexec/arch/ppc/kexec-ppc.h
--- 
kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.h~kexec-tools-crashdump-backup-x86   
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-ppc.h   2005-02-24 
18:55:46.000000000 +0530
@@ -17,12 +17,12 @@ extern struct {
 
 int elf_ppc_probe(const char *buf, off_t len);
 int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void elf_ppc_usage(void);
 
 int dol_ppc_probe(const char *buf, off_t len);
 int dol_ppc_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void dol_ppc_usage(void);
 
 #endif /* KEXEC_PPC_H */
diff -puN kexec/arch/ppc64/kexec-elf-ppc64.c~kexec-tools-crashdump-backup-x86 
kexec/arch/ppc64/kexec-elf-ppc64.c
--- 
kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c~kexec-tools-crashdump-backup-x86
       2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ppc64/kexec-elf-ppc64.c   2005-02-24 
18:55:46.000000000 +0530
@@ -95,7 +95,7 @@ int elf_ppc64_probe(const char *buf, off
 }
 
 int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, 
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        struct mem_ehdr ehdr;
 
diff -puN kexec/arch/ppc64/kexec-ppc64.h~kexec-tools-crashdump-backup-x86 
kexec/arch/ppc64/kexec-ppc64.h
--- 
kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h~kexec-tools-crashdump-backup-x86
   2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/ppc64/kexec-ppc64.h       2005-02-24 
18:55:46.000000000 +0530
@@ -3,7 +3,7 @@
 
 int elf_ppc64_probe(const char *buf, off_t len);
 int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void elf_ppc64_usage(void);
 
 #endif /* KEXEC_PPC_H */
diff -puN kexec/arch/x86_64/kexec-elf-x86_64.c~kexec-tools-crashdump-backup-x86 
kexec/arch/x86_64/kexec-elf-x86_64.c
--- 
kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c~kexec-tools-crashdump-backup-x86
     2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/x86_64/kexec-elf-x86_64.c 2005-02-24 
18:55:46.000000000 +0530
@@ -81,7 +81,7 @@ void elf_x86_64_usage(void)
 }
 
 int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len, 
-       struct kexec_info *info)
+       struct kexec_info *info, unsigned long kexec_flags)
 {
        struct mem_ehdr ehdr;
        const char *command_line;
diff -puN kexec/arch/x86_64/kexec-x86_64.c~kexec-tools-crashdump-backup-x86 
kexec/arch/x86_64/kexec-x86_64.c
--- 
kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c~kexec-tools-crashdump-backup-x86
 2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/x86_64/kexec-x86_64.c     2005-02-24 
18:55:46.000000000 +0530
@@ -37,7 +37,8 @@
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+                                       unsigned long kexec_flags)
 {
        const char iomem[]= "/proc/iomem";
        int memory_ranges = 0;
@@ -232,7 +233,7 @@ int arch_compat_trampoline(struct kexec_
        return 0;
 }
 
-void arch_update_purgatory(struct kexec_info *info)
+void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
 {
        elf_rel_set_symbol(&info->rhdr, "reset_vga",
                &arch_options.reset_vga, sizeof(arch_options.reset_vga));
diff -puN kexec/arch/x86_64/kexec-x86_64.h~kexec-tools-crashdump-backup-x86 
kexec/arch/x86_64/kexec-x86_64.h
--- 
kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.h~kexec-tools-crashdump-backup-x86
 2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/arch/x86_64/kexec-x86_64.h     2005-02-24 
18:55:46.000000000 +0530
@@ -25,7 +25,7 @@ struct entry64_regs {
 
 int elf_x86_64_probe(const char *buf, off_t len);
 int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 void elf_x86_64_usage(void);
 
 #endif /* KEXEC_X86_64_H */
diff -puN kexec/kexec.c~kexec-tools-crashdump-backup-x86 kexec/kexec.c
--- kexec-tools-1.101/kexec/kexec.c~kexec-tools-crashdump-backup-x86    
2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/kexec.c        2005-02-24 18:55:46.000000000 
+0530
@@ -38,8 +38,8 @@
 #include "kexec-elf.h"
 #include "kexec-sha256.h"
 
-static unsigned long long mem_min = 0;
-static unsigned long long mem_max = ULONG_MAX;
+unsigned long long mem_min = 0;
+unsigned long long mem_max = ULONG_MAX;
 
 void die(char *fmt, ...)
 {
@@ -445,7 +445,7 @@ char *slurp_decompress_file(const char *
 }
 #endif
 
-static void update_purgatory(struct kexec_info *info)
+static void update_purgatory(struct kexec_info *info, unsigned long 
kexec_flags)
 {
        static const uint8_t null_buf[256];
        sha256_context ctx;
@@ -456,7 +456,7 @@ static void update_purgatory(struct kexe
        if (!info->rhdr.e_shdr) {
                return;
        }
-       arch_update_purgatory(info);
+       arch_update_purgatory(info, kexec_flags);
        memset(region, 0, sizeof(region));
        sha256_starts(&ctx);
        /* Compute a hash of the loaded kernel */
@@ -470,6 +470,10 @@ static void update_purgatory(struct kexe
                if (info->segment[i].mem == (void *)info->rhdr.rel_addr) {
                        continue;
                }
+               /* Don't include backup region in the checksum */
+               if (info->segment[i].mem == (void *)info->backup_start) {
+                       continue;
+               }
                sha256_update(&ctx, info->segment[i].buf, 
info->segment[i].bufsz);
                nullsz = info->segment[i].memsz - info->segment[i].bufsz;
                while(nullsz) {
@@ -507,6 +511,7 @@ static int my_load(const char *type, int
        info.segment = NULL;
        info.nr_segments = 0;
        info.entry = NULL;
+       info.backup_start = 0;
 
        result = 0;
        if (argc - fileind <= 0) {
@@ -522,7 +527,7 @@ static int my_load(const char *type, int
                kernel_buf, kernel_size);
 #endif
 
-       if (get_memory_ranges(&memory_range, &memory_ranges) < 0) {
+       if (get_memory_ranges(&memory_range, &memory_ranges, kexec_flags) < 0) {
                fprintf(stderr, "Could not get memory layout\n");
                return -1;
        }
@@ -559,7 +564,8 @@ static int my_load(const char *type, int
                        }
                }
        }
-       if (file_type[i].load(argc, argv, kernel_buf, kernel_size, &info) < 0) {
+       if (file_type[i].load(argc, argv, kernel_buf, kernel_size, &info,
+                               kexec_flags) < 0) {
                fprintf(stderr, "Cannot load %s\n", kernel);
                return -1;
        }
@@ -582,7 +588,7 @@ static int my_load(const char *type, int
                return -1;
        }
        /* if purgatory is loaded update it */
-       update_purgatory(&info);
+       update_purgatory(&info, kexec_flags);
 #if 0
        fprintf(stderr, "kexec_load: entry = %p flags = %lx\n", 
                info.entry, kexec_flags);
diff -puN kexec/kexec.h~kexec-tools-crashdump-backup-x86 kexec/kexec.h
--- kexec-tools-1.101/kexec/kexec.h~kexec-tools-crashdump-backup-x86    
2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/kexec/kexec.h        2005-02-24 18:55:46.000000000 
+0530
@@ -91,6 +91,8 @@ do { \
 } while(0)
 #endif
 
+extern unsigned long long mem_min, mem_max;
+
 struct kexec_segment {
        const void *buf;
        size_t bufsz;
@@ -112,10 +114,12 @@ struct kexec_info {
        int nr_segments;
        void *entry;
        struct mem_ehdr rhdr;
+       unsigned long backup_start;
 };
 
 void usage(void);
-int get_memory_ranges(struct memory_range **range, int *ranges);
+int get_memory_ranges(struct memory_range **range, int *ranges,
+                                               unsigned long kexec_flags);
 int valid_memory_range(unsigned long sstart, unsigned long send);
 int valid_memory_segment(struct kexec_segment *segment);
 void print_segments(FILE *file, struct kexec_info *info);
@@ -128,7 +132,7 @@ unsigned long locate_hole(struct kexec_i
 typedef int (probe_t)(const char *kernel_buf, off_t kernel_size);
 typedef int (load_t )(int argc, char **argv,
        const char *kernel_buf, off_t kernel_size, 
-       struct kexec_info *info);
+       struct kexec_info *info, unsigned long kexec_flags);
 typedef void (usage_t)(void);
 struct file_type {
        const char *name;
@@ -189,6 +193,6 @@ extern size_t purgatory_size;
 void arch_usage(void);
 int arch_process_options(int argc, char **argv);
 int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags);
-void arch_update_purgatory(struct kexec_info *info);
+void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags);
 
 #endif /* KEXEC_H */
diff -puN purgatory/arch/i386/Makefile~kexec-tools-crashdump-backup-x86 
purgatory/arch/i386/Makefile
--- 
kexec-tools-1.101/purgatory/arch/i386/Makefile~kexec-tools-crashdump-backup-x86 
    2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/purgatory/arch/i386/Makefile 2005-02-24 
18:55:46.000000000 +0530
@@ -12,3 +12,4 @@ PURGATORY_C_SRCS+= purgatory/arch/i386/p
 PURGATORY_C_SRCS+= purgatory/arch/i386/console-x86.c
 PURGATORY_C_SRCS+= purgatory/arch/i386/vga.c
 PURGATORY_C_SRCS+= purgatory/arch/i386/pic.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/crashdump_backup.c
diff -puN /dev/null purgatory/arch/i386/crashdump_backup.c
--- /dev/null   2004-06-16 19:10:55.000000000 +0530
+++ kexec-tools-1.101-root/purgatory/arch/i386/crashdump_backup.c       
2005-02-24 18:55:46.000000000 +0530
@@ -0,0 +1,44 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by:  Vivek goyal ([EMAIL PROTECTED])
+ * Copyright (C) IBM Corporation, 2005. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#define BACKUP_REGION_SOURCE 0x00000000
+#define BACKUP_REGION_SIZE 0xa0000
+
+/* Backup region start gets set after /proc/iomem has been parsed. */
+uint32_t backup_start = 0;
+
+/* Backup first 640K of memory to backup region as reserved by kexec.
+ * Assuming first 640K has to be present on i386 machines and no address
+ * validity checks have to be performed. */
+
+void crashdump_backup_memory(void)
+{
+       void *dest, *src;
+
+       src = (void *) BACKUP_REGION_SOURCE;
+
+       if (backup_start) {
+               dest = (void *)(backup_start);
+               memcpy(dest, src, BACKUP_REGION_SIZE);
+       }
+}
diff -puN purgatory/arch/i386/purgatory-x86.c~kexec-tools-crashdump-backup-x86 
purgatory/arch/i386/purgatory-x86.c
--- 
kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.c~kexec-tools-crashdump-backup-x86
      2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/purgatory/arch/i386/purgatory-x86.c  2005-02-24 
18:55:46.000000000 +0530
@@ -30,6 +30,7 @@ void x86_setup_cpu(void)
 uint8_t reset_vga = 0;
 uint8_t legacy_timer = 0;
 uint8_t legacy_pic   = 0;
+uint8_t panic_kernel = 0;
 
 void setup_arch(void)
 {
@@ -37,4 +38,5 @@ void setup_arch(void)
        if (reset_vga)    x86_reset_vga();
        if (legacy_pic)   x86_setup_legacy_pic();
        /* if (legacy_timer) x86_setup_legacy_timer(); */
+       if (panic_kernel)   crashdump_backup_memory();
 }
diff -puN purgatory/arch/i386/purgatory-x86.h~kexec-tools-crashdump-backup-x86 
purgatory/arch/i386/purgatory-x86.h
--- 
kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.h~kexec-tools-crashdump-backup-x86
      2005-02-24 18:55:46.000000000 +0530
+++ kexec-tools-1.101-root/purgatory/arch/i386/purgatory-x86.h  2005-02-24 
18:55:46.000000000 +0530
@@ -4,5 +4,6 @@
 void x86_reset_vga(void);
 void x86_setup_legacy_pic(void);
 void x86_setup_legacy_timer(void);
+void crashdump_backup_memory(void);
 
 #endif /* PURGATORY_X86_H */
_

Reply via email to