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 #include +#include + #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 + +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 #include #include +#include #include #include @@ -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 +#include + +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