Hi,

This patch add support for mingw, now you can create native executable
for windows.

I still use cygwin to compile it:

./configure CC="gcc -mno-cygwin"

It might be possible to use pure mingw environment, but configure.ac
would need some modification.


2008-08-23  Bean  <[EMAIL PROTECTED]>

        * include/grub/symbol.h: Replace #ifndef __CYGWIN__ with
        #if ! defined (__CYGWIN__) && ! defined (__MINGW32__).

        * include/grub/util/misc.h: Add #include <grub/types.h>, add function
        fseeko, ftello, sync, asprintf, grub_util_get_disk_size and sleep for
        mingw.

        * util/biosdisk.c (grub_util_biosdisk_open): Use grub_util_get_disk_size
        to get size in mingw.
        (open_device): Use flag O_BINARY.
        (find_root_device): Add handling for mingw.

        * util/hostfs.c: Add #include <grub/util/misc.h>
        (grub_hostfs_open): Use "rb" flag to open file, use
        grub_util_get_disk_size to get disk size.

        * util/misc.c: Add #include <winioctl.h> and <stdarg.h> in mingw.
        (fseeko): New function.
        (ftello): Likewise.
        (sync): Likewise.
        (asprintf): Likewise.
        (grub_util_get_disk_size): Likewise.

-- 
Bean
diff --git a/include/grub/symbol.h b/include/grub/symbol.h
index e951490..c662c14 100644
--- a/include/grub/symbol.h
+++ b/include/grub/symbol.h
@@ -28,7 +28,7 @@
 # define EXT_C(sym)	sym
 #endif
 
-#ifndef __CYGWIN__
+#if ! defined (__CYGWIN__) && ! defined (__MINGW32__)
 #define FUNCTION(x)	.globl EXT_C(x) ; .type EXT_C(x), "function" ; EXT_C(x):
 #define VARIABLE(x)	.globl EXT_C(x) ; .type EXT_C(x), "object" ; EXT_C(x):
 #else
diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h
index c9a8528..4d2ce8f 100644
--- a/include/grub/util/misc.h
+++ b/include/grub/util/misc.h
@@ -24,6 +24,8 @@
 #include <setjmp.h>
 #include <unistd.h>
 
+#include <grub/types.h>
+
 #ifdef __NetBSD__
 /* NetBSD uses /boot for its boot block.  */
 # define DEFAULT_DIRECTORY	"/grub"
@@ -55,4 +57,19 @@ void grub_util_write_image_at (const void *img, size_t size, off_t offset,
 			       FILE *out);
 char *grub_util_get_disk_name (int disk, char *name);
 
+#ifdef __MINGW32__
+
+#include <windows.h>
+
+grub_int64_t fseeko (FILE *fp, grub_int64_t offset, int whence);
+grub_int64_t ftello (FILE *fp);
+void sync (void);
+int asprintf (char **buf, const char *fmt, ...);
+
+grub_int64_t grub_util_get_disk_size (char *name);
+
+#define sleep	Sleep
+
+#endif
+
 #endif /* ! GRUB_UTIL_MISC_HEADER */
diff --git a/util/biosdisk.c b/util/biosdisk.c
index 1137e98..bdede12 100644
--- a/util/biosdisk.c
+++ b/util/biosdisk.c
@@ -157,7 +157,22 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
   disk->id = drive;
 
   /* Get the size.  */
-#if defined(__linux__) || defined(__CYGWIN__)
+#if defined(__MINGW32__)
+  {
+    grub_uint64_t size;
+
+    size = grub_util_get_disk_size (map[drive].device);
+
+    if (size % 512)
+      grub_util_error ("unaligned device size");
+
+    disk->total_sectors = size >> 9;
+
+    grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
+
+    return GRUB_ERR_NONE;
+  }
+#elif defined(__linux__) || defined(__CYGWIN__)
   {
     unsigned long long nr;
     int fd;
@@ -275,6 +290,9 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
 #ifdef O_FSYNC
   flags |= O_FSYNC;
 #endif
+#ifdef O_BINARY
+  flags |= O_BINARY;
+#endif
   
 #ifdef __linux__
   /* Linux has a bug that the disk cache for a whole disk is not consistent
diff --git a/util/getroot.c b/util/getroot.c
index c8d31ed..5fcf2e5 100644
--- a/util/getroot.c
+++ b/util/getroot.c
@@ -169,7 +169,16 @@ grub_get_prefix (const char *dir)
   return prefix;
 }
 
-#ifndef __CYGWIN__
+#ifdef __MINGW32__
+
+static char *
+find_root_device (const char *dir __attribute__ ((unused)),
+                  dev_t dev __attribute__ ((unused)))
+{
+  return 0;
+}
+
+#elif ! defined(__CYGWIN__)
 
 static char *
 find_root_device (const char *dir, dev_t dev)
diff --git a/util/hostfs.c b/util/hostfs.c
index b74fbd3..8773c1c 100644
--- a/util/hostfs.c
+++ b/util/hostfs.c
@@ -22,6 +22,7 @@
 #include <grub/disk.h>
 #include <grub/misc.h>
 #include <grub/dl.h>
+#include <grub/util/misc.h>
 
 #include <dirent.h>
 #include <stdio.h>
@@ -95,15 +96,19 @@ grub_hostfs_open (struct grub_file *file, const char *name)
 {
   FILE *f;
 
-  f = fopen (name, "r");
+  f = fopen (name, "rb");
   if (! f)
     return grub_error (GRUB_ERR_BAD_FILENAME,
 		       "can't open `%s'", name);
   file->data = f;
 
+#ifdef __MINGW32__
+  file->size = grub_util_get_disk_size (name);
+#else
   fseeko (f, 0, SEEK_END);
   file->size = ftello (f);
   fseeko (f, 0, SEEK_SET);
+#endif
 
   return GRUB_ERR_NONE;
 }
diff --git a/util/misc.c b/util/misc.c
index 7d877cc..6d3aae4 100644
--- a/util/misc.c
+++ b/util/misc.c
@@ -313,3 +313,103 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)),
 		       grub_size_t len __attribute__ ((unused)))
 {
 }
+
+#ifdef __MINGW32__
+
+#include <winioctl.h>
+#include <stdarg.h>
+
+grub_int64_t
+fseeko (FILE *fp, grub_int64_t offset, int whence)
+{
+  fpos_t pos;
+
+  if (whence == SEEK_CUR)
+    {
+      fgetpos (fp, &pos);
+      pos += (fpos_t) offset;
+    }
+  else if (whence == SEEK_END)
+    {
+      pos = (fpos_t) (_filelengthi64 (fileno (fp)) + offset);
+    }
+  else if (whence == SEEK_SET)
+    pos = (fpos_t) offset;
+
+  return fsetpos(fp, &pos);
+}
+
+grub_int64_t
+ftello (FILE *fp)
+{
+  fpos_t pos;
+
+  return (fgetpos(fp, &pos)) ? (grub_int64_t) -1LL : (grub_int64_t) pos;
+}
+
+void sync (void)
+{
+}
+
+int
+asprintf (char **buf, const char *fmt, ...)
+{
+  int status;
+  va_list ap;
+
+  /* Should be large enough.  */
+  *buf = xmalloc (512);
+
+  va_start (ap, fmt);
+  status = vsprintf (*buf, fmt, ap);
+  va_end (ap);
+
+  return status;
+}
+
+grub_int64_t
+grub_util_get_disk_size (char *name)
+{
+  char new_name[strlen (name) + 1], *p;
+  HANDLE hd;
+  grub_int64_t size = -1LL;
+
+  strcpy (new_name, name);
+  for (p = new_name; *p; p++)
+    if (*p == '/')
+      *p = '\\';
+
+  hd = CreateFile (new_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                   0, OPEN_EXISTING, 0, 0);
+
+  if (hd == INVALID_HANDLE_VALUE)
+    return size;
+
+  if (! strncmp (new_name, "\\\\.\\", 4))
+    {
+      DWORD nr;
+      DISK_GEOMETRY g;
+
+      if (! DeviceIoControl (hd, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                             0, 0, &g, sizeof (g), &nr, 0))
+        goto fail;
+
+      size = g.Cylinders.QuadPart;
+      size *= g.TracksPerCylinder * g.SectorsPerTrack * g.BytesPerSector;
+    }
+  else
+    {
+      LARGE_INTEGER s;
+
+      s.LowPart = GetFileSize (hd, &s.HighPart);
+      size = s.QuadPart;
+    }
+
+fail:
+
+  CloseHandle (hd);
+
+  return size;
+}
+
+#endif
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to