OK, I haven't quite gotten around to posting the Windows kernel driver
source that goes with this. So I'm not asking that this patch be merged,
since nobody else can use it yet. :-) I'd love to get review, though:
Does this look like it's in a mergeable state? I'm happy with it, but do
I need to change anything to make it acceptable to you folks?

This patch requires basically all the other patches I've posted.


 Makefile.in                       |    1 +
 include/byteswap.h                |   39 +++++++
 kexec/Makefile                    |    6 +
 kexec/arch/i386/Makefile          |    2 +
 kexec/arch/i386/kexec-x86.c       |    2 +
 kexec/arch/i386/x86-linux-setup.c |    4 +
 kexec/kexec-syscall.h             |    7 ++
 kexec/kexec.c                     |    4 +
 kexec/kexec.h                     |   10 ++
 kexec/win32.c                     |  214 +++++++++++++++++++++++++++++++++++++
 10 files changed, 289 insertions(+), 0 deletions(-)
 create mode 100644 include/byteswap.h
 create mode 100644 kexec/win32.c

diff --git a/Makefile.in b/Makefile.in
index b51c3a1..bdd6ba7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -24,6 +24,7 @@ ARCH          = @ARCH@
 OBJDIR         = @OBJDIR@
 target         = @target@
 host           = @host@
+host_os                = @host_os@
 
 # Compiler for building kexec
 CC             = @CC@
diff --git a/include/byteswap.h b/include/byteswap.h
new file mode 100644
index 0000000..cd5a726
--- /dev/null
+++ b/include/byteswap.h
@@ -0,0 +1,39 @@
+/* byteswap.h
+
+Copyright 2005 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef _BYTESWAP_H
+#define _BYTESWAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static __inline unsigned short
+bswap_16 (unsigned short __x)
+{
+  return (__x >> 8) | (__x << 8);
+}
+
+static __inline unsigned int
+bswap_32 (unsigned int __x)
+{
+  return (bswap_16 (__x & 0xffff) << 16) | (bswap_16 (__x >> 16));
+}
+
+static __inline unsigned long long
+bswap_64 (unsigned long long __x)
+{
+  return (((unsigned long long) bswap_32 (__x & 0xffffffffull)) << 32) | 
(bswap_32 (__x >> 32));
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _BYTESWAP_H */
diff --git a/kexec/Makefile b/kexec/Makefile
index a80b940..fe05340 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -11,16 +11,22 @@ KEXEC_SRCS =
 KEXEC_GENERATED_SRCS =
 
 KEXEC_SRCS += kexec/kexec.c
+ifneq ($(host_os),mingw32msvc)
 KEXEC_SRCS += kexec/ifdown.c
+endif
 KEXEC_SRCS += kexec/kexec-elf.c
 KEXEC_SRCS += kexec/kexec-elf-exec.c
 KEXEC_SRCS += kexec/kexec-elf-core.c
 KEXEC_SRCS += kexec/kexec-elf-rel.c
 KEXEC_SRCS += kexec/kexec-elf-boot.c
 KEXEC_SRCS += kexec/kexec-iomem.c
+ifneq ($(host_os),mingw32msvc)
 KEXEC_SRCS += kexec/crashdump.c
 KEXEC_SRCS += kexec/crashdump-xen.c
 KEXEC_SRCS += kexec/phys_arch.c
+else
+KEXEC_SRCS += kexec/win32.c
+endif
 
 KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)
 
diff --git a/kexec/arch/i386/Makefile b/kexec/arch/i386/Makefile
index f2d9636..f9dbb7b 100644
--- a/kexec/arch/i386/Makefile
+++ b/kexec/arch/i386/Makefile
@@ -9,7 +9,9 @@ i386_KEXEC_SRCS += kexec/arch/i386/kexec-multiboot-x86.c
 i386_KEXEC_SRCS += kexec/arch/i386/kexec-beoboot-x86.c
 i386_KEXEC_SRCS += kexec/arch/i386/kexec-nbi.c
 i386_KEXEC_SRCS += kexec/arch/i386/x86-linux-setup.c
+ifneq ($(host_os),mingw32msvc)
 i386_KEXEC_SRCS += kexec/arch/i386/crashdump-x86.c
+endif
 
 dist += kexec/arch/i386/Makefile $(i386_KEXEC_SRCS)                    \
        kexec/arch/i386/kexec-x86.h kexec/arch/i386/crashdump-x86.h     \
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
index 89ccb0b..f937856 100644
--- a/kexec/arch/i386/kexec-x86.c
+++ b/kexec/arch/i386/kexec-x86.c
@@ -32,6 +32,7 @@
 #include "crashdump-x86.h"
 #include <arch/options.h>
 
+#ifndef __MINGW32__
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /* Return a sorted list of memory ranges. */
@@ -113,6 +114,7 @@ int get_memory_ranges(struct memory_range **range, int 
*ranges,
        *ranges = memory_ranges;
        return 0;
 }
+#endif /* !defined(__MINGW32__) */
 
 struct file_type file_type[] = {
        { "multiboot-x86", multiboot_x86_probe, multiboot_x86_load, 
diff --git a/kexec/arch/i386/x86-linux-setup.c 
b/kexec/arch/i386/x86-linux-setup.c
index 4b9a5e5..e750d82 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -23,8 +23,10 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#ifndef __MINGW32__
 #include <sys/ioctl.h>
 #include <linux/fb.h>
+#endif
 #include <unistd.h>
 #include <x86/x86-linux.h>
 #include "../../kexec.h"
@@ -101,6 +103,7 @@ void setup_linux_bootloader_parameters(
 
 int setup_linux_vesafb(struct x86_linux_param_header *real_mode)
 {
+#ifndef __MINGW32__
        struct fb_fix_screeninfo fix;
        struct fb_var_screeninfo var;
        int fd;
@@ -153,6 +156,7 @@ int setup_linux_vesafb(struct x86_linux_param_header 
*real_mode)
 
  out:
        close(fd);
+#endif /* !defined(__MINGW32__) */
        return -1;
 }
 
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index 2b9345f..f6f8dc5 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -1,6 +1,8 @@
 #ifndef KEXEC_SYSCALL_H
 #define KEXEC_SYSCALL_H
 
+#ifndef __MINGW32__
+
 #define __LIBRARY__
 #include <syscall.h>
 #include <sys/syscall.h>
@@ -69,6 +71,11 @@ static inline long kexec_reboot(void)
        return (long) syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, 
LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC, 0);
 }
 
+#else /* defined(__MINGW32__) */
+extern long kexec_load(void *entry, unsigned long nr_segments,
+                      struct kexec_segment *segments, unsigned long flags);
+extern long kexec_reboot(void);
+#endif /* defined(__MINGW32__) */
 
 #define KEXEC_ON_CRASH  0x00000001
 #define KEXEC_ARCH_MASK 0xffff0000
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 0b02a3a..27a3573 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -804,6 +804,7 @@ static int kexec_loaded(void)
 /* check we retained the initrd */
 void check_reuse_initrd(void)
 {
+#ifndef __MINGW32__
        FILE * fp;
        char * line = NULL;
        size_t len = 0;
@@ -814,11 +815,14 @@ void check_reuse_initrd(void)
                die("unable to open /proc/cmdline\n");
        read = getline(&line, &len, fp);
        if (strstr(line, "retain_initrd") == NULL)
+#endif
                die("unrecoverable error: current boot didn't "
                    "retain the initrd for reuse.\n");
+#ifndef __MINGW32__
        if (line)
                free(line);
        fclose(fp);
+#endif
 }
 
 int main(int argc, char *argv[])
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 3724862..f7a64ac 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -8,7 +8,13 @@
 #include <stdint.h>
 #define USE_BSD
 #include <byteswap.h>
+#ifdef __MINGW32__
+#include <sys/param.h>
+extern int getpagesize(void);
+#define sync()
+#else
 #include <endian.h>
+#endif
 #define _GNU_SOURCE
 
 #include "kexec-elf.h"
@@ -217,7 +223,11 @@ extern unsigned long add_buffer_phys_virt(struct 
kexec_info *info,
        int buf_end, int phys);
 extern void arch_reuse_initrd(void);
 
+#ifdef __MINGW32__
+#define ifdown()
+#else
 extern int ifdown(void);
+#endif
 
 extern unsigned char purgatory[];
 extern size_t purgatory_size;
diff --git a/kexec/win32.c b/kexec/win32.c
new file mode 100644
index 0000000..d3c18db
--- /dev/null
+++ b/kexec/win32.c
@@ -0,0 +1,214 @@
+#include "kexec.h"
+#include "kexec-syscall.h"
+#include <errno.h>
+#include <stddef.h>
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <ddk/ntddk.h>
+
+#define IOCTL_LOAD_KERNEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, 
METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+struct kexec_user_segment {
+       size_t bufsz;
+       unsigned long mem;
+       size_t memsz;
+};
+
+struct kexec_user_buffer {
+       unsigned long entry;
+       unsigned long kexec_flags;
+       int nr_segments;
+       struct kexec_user_segment segments[0];
+};
+
+int getpagesize(void)
+{
+       SYSTEM_INFO sysinfo;
+       GetNativeSystemInfo(&sysinfo);
+       return sysinfo.dwPageSize;
+}
+
+long physical_arch(void)
+{
+       SYSTEM_INFO sysinfo;
+       GetNativeSystemInfo(&sysinfo);
+       switch(sysinfo.wProcessorArchitecture) {
+       case PROCESSOR_ARCHITECTURE_INTEL:
+               /* For compatibility with older patches
+                * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_386 here.
+                */
+               return KEXEC_ARCH_DEFAULT;
+
+       case PROCESSOR_ARCHITECTURE_AMD64:
+               return KEXEC_ARCH_X86_64;
+       }
+       fprintf(stderr, "Unsupported machine type: %d\n",
+               sysinfo.wProcessorArchitecture);
+       return -1;
+}
+
+int get_memory_ranges(struct memory_range **range, int *ranges,
+                               unsigned long kexec_flags)
+{
+       static struct memory_range *memory_range;
+       static int memory_ranges;
+
+       HKEY key = HKEY_LOCAL_MACHINE;
+       char path[] = "HARDWARE\\RESOURCEMAP\\System Resources\\Physical 
Memory\\.Translated";
+       char *next = path;
+       char *slash;
+       LONG result;
+       DWORD size, type;
+       void *buf = 0;
+       CM_RESOURCE_LIST *resource_list;
+       CM_PARTIAL_RESOURCE_LIST *partial_list;
+       int i;
+
+       if(memory_range)
+       {
+               *range = memory_range;
+               *ranges = memory_ranges;
+               return 0;
+       }
+
+       while((slash = strchr(next, '\\')))
+       {
+               HKEY subkey;
+               *slash = '\0';
+               result = RegOpenKeyEx(key, next, 0, KEY_READ, &subkey);
+               RegCloseKey(key);
+               if(result != ERROR_SUCCESS)
+               {
+                       fprintf(stderr, "get_memory_ranges: registry key '%s' 
not found\n", next);
+                       return -1;
+               }
+               key = subkey;
+               next = slash + 1;
+       }
+
+       if((result = RegQueryValueEx(key, next, 0, 0, 0, &size)) == 
ERROR_SUCCESS)
+       {
+               buf = malloc(size);
+               if(!buf)
+               {
+                       RegCloseKey(key);
+                       fprintf(stderr, "get_memory_ranges: %s\n", 
strerror(errno));
+                       return -1;
+               }
+               result = RegQueryValueEx(key, next, 0, &type, buf, &size);
+       }
+       RegCloseKey(key);
+       if(result != ERROR_SUCCESS)
+       {
+               fprintf(stderr, "get_memory_ranges: registry key '%s' not 
found\n", next);
+               goto fail;
+       }
+       if(type != REG_RESOURCE_LIST)
+       {
+               fprintf(stderr, "get_memory_ranges: registry key '%s' has wrong 
type\n", next);
+               goto fail;
+       }
+       resource_list = buf;
+       partial_list = &resource_list->List[0].PartialResourceList;
+       if(size < offsetof(CM_RESOURCE_LIST, 
List[0].PartialResourceList.PartialDescriptors) ||
+          resource_list->Count != 1 ||
+          size < (char *) (partial_list->PartialDescriptors + 
partial_list->Count) - (char *) buf)
+       {
+               fprintf(stderr, "get_memory_ranges: registry key '%s' is too 
small\n", next);
+               goto fail;
+       }
+
+       memory_ranges = partial_list->Count;
+       memory_range = malloc(sizeof(*memory_range) * memory_ranges);
+       if(!memory_range)
+       {
+               fprintf(stderr, "get_memory_ranges: %s\n", strerror(errno));
+               goto fail;
+       }
+       for(i = 0; i < memory_ranges; ++i)
+       {
+               if(partial_list->PartialDescriptors[i].Type != 
CmResourceTypeMemory)
+               {
+                       free(memory_range);
+                       memory_range = 0;
+                       fprintf(stderr, "get_memory_ranges: range %d is not 
memory\n", i + 1);
+                       goto fail;
+               }
+               memory_range[i].start = 
partial_list->PartialDescriptors[i].u.Memory.Start.QuadPart;
+               memory_range[i].end = memory_range[i].start + 
partial_list->PartialDescriptors[i].u.Memory.Length;
+               memory_range[i].type = RANGE_RAM;
+       }
+
+       *range = memory_range;
+       *ranges = memory_ranges;
+       return 0;
+
+fail:
+       free(buf);
+       return -1;
+}
+
+long kexec_load(void *entry, unsigned long nr_segments,
+               struct kexec_segment *segments, unsigned long flags)
+{
+       struct kexec_user_buffer *image;
+       long size = sizeof(*image) + nr_segments * sizeof(*image->segments);
+       DWORD bytes_returned;
+       char *tmp;
+       int i, success;
+
+       for(i = 0; i < nr_segments; ++i)
+               size += segments[i].bufsz;
+
+       image = malloc(size);
+       if(!image)
+               return -1;
+
+       image->entry = (unsigned long) entry;
+       image->kexec_flags = flags;
+       image->nr_segments = nr_segments;
+       tmp = (char *) (image->segments + nr_segments);
+       for(i = 0; i < nr_segments; ++i)
+       {
+               image->segments[i].bufsz = segments[i].bufsz;
+               image->segments[i].mem = (unsigned long) segments[i].mem;
+               image->segments[i].memsz = segments[i].memsz;
+               memcpy(tmp, segments[i].buf, segments[i].bufsz);
+               tmp += segments[i].bufsz;
+       }
+
+       HANDLE device = CreateFile(TEXT("\\\\.\\kexec"),
+                       /* open mode */ 0,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE,
+                       /* security attributes */ NULL,
+                       OPEN_EXISTING,
+                       /* file attributes */ 0,
+                       /* template file */ NULL);
+
+       success = device != INVALID_HANDLE_VALUE && DeviceIoControl(device,
+                               IOCTL_LOAD_KERNEL,
+                               image, size,
+                               NULL, 0, &bytes_returned,
+                               /* async structure */ (LPOVERLAPPED) NULL);
+
+       CloseHandle(device);
+       free(image);
+       return success ? 0 : -1;
+}
+
+long kexec_reboot(void)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
+int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
+                           unsigned long max_addr, unsigned long min_base)
+{
+       return -1;
+}
+
+int is_crashkernel_mem_reserved(void)
+{
+       return 0;
+}
-- 
1.5.4.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to