[RFC] Win32 port of the userspace tools using MinGW.
Jamey Sharp
jamey at thetovacompany.com
Fri May 16 01:48:13 EDT 2008
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
More information about the kexec
mailing list