summaryrefslogtreecommitdiffstats
path: root/grub-core/osdep/windows
diff options
context:
space:
mode:
Diffstat (limited to 'grub-core/osdep/windows')
-rw-r--r--grub-core/osdep/windows/blocklist.c118
-rw-r--r--grub-core/osdep/windows/config.c57
-rw-r--r--grub-core/osdep/windows/cputime.c19
-rw-r--r--grub-core/osdep/windows/dl.c59
-rw-r--r--grub-core/osdep/windows/emuconsole.c308
-rw-r--r--grub-core/osdep/windows/getroot.c355
-rw-r--r--grub-core/osdep/windows/hostdisk.c689
-rw-r--r--grub-core/osdep/windows/init.c190
-rw-r--r--grub-core/osdep/windows/password.c51
-rw-r--r--grub-core/osdep/windows/platform.c426
-rw-r--r--grub-core/osdep/windows/random.c55
-rw-r--r--grub-core/osdep/windows/relpath.c96
-rw-r--r--grub-core/osdep/windows/sleep.c31
13 files changed, 2454 insertions, 0 deletions
diff --git a/grub-core/osdep/windows/blocklist.c b/grub-core/osdep/windows/blocklist.c
new file mode 100644
index 0000000..6d0809a
--- /dev/null
+++ b/grub-core/osdep/windows/blocklist.c
@@ -0,0 +1,118 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/disk.h>
+#include <grub/partition.h>
+#include <grub/fs.h>
+#include <grub/ntfs.h>
+#include <grub/fat.h>
+#include <grub/exfat.h>
+#include <grub/udf.h>
+#include <grub/util/misc.h>
+#include <grub/util/install.h>
+#include <grub/emu/getroot.h>
+#include <grub/emu/hostfile.h>
+
+#include <windows.h>
+#include <winioctl.h>
+
+void
+grub_install_get_blocklist (grub_device_t root_dev,
+ const char *core_path,
+ const char *core_img __attribute__ ((unused)),
+ size_t core_size,
+ void (*callback) (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length,
+ void *data),
+ void *hook_data)
+{
+ grub_disk_addr_t first_lcn = 0;
+ HANDLE filehd;
+ DWORD rets;
+ RETRIEVAL_POINTERS_BUFFER *extbuf;
+ size_t extbuf_size;
+ DWORD i;
+ grub_uint64_t sec_per_lcn;
+ grub_uint64_t curvcn = 0;
+ STARTING_VCN_INPUT_BUFFER start_vcn;
+ grub_fs_t fs;
+ grub_err_t err;
+
+ fs = grub_fs_probe (root_dev);
+ if (!fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ /* This is ugly but windows doesn't give all needed data. Or does anyone
+ have a pointer how to retrieve it?
+ */
+ if (grub_strcmp (fs->name, "ntfs") == 0)
+ {
+ struct grub_ntfs_bpb bpb;
+ err = grub_disk_read (root_dev->disk, 0, 0, sizeof (bpb), &bpb);
+ if (err)
+ grub_util_error ("%s", grub_errmsg);
+ sec_per_lcn = ((grub_uint32_t) bpb.sectors_per_cluster
+ * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector))
+ >> 9;
+ first_lcn = 0;
+ }
+ else if (grub_strcmp (fs->name, "exfat") == 0)
+ first_lcn = grub_exfat_get_cluster_sector (root_dev->disk, &sec_per_lcn);
+ else if (grub_strcmp (fs->name, "fat") == 0)
+ first_lcn = grub_fat_get_cluster_sector (root_dev->disk, &sec_per_lcn);
+ else if (grub_strcmp (fs->name, "udf") == 0)
+ first_lcn = grub_udf_get_cluster_sector (root_dev->disk, &sec_per_lcn);
+ else
+ grub_util_error ("unsupported fs for blocklist on windows: %s",
+ fs->name);
+
+ grub_util_info ("sec_per_lcn = %" GRUB_HOST_PRIuLONG_LONG
+ ", first_lcn=%" GRUB_HOST_PRIuLONG_LONG,
+ (unsigned long long) sec_per_lcn,
+ (unsigned long long) first_lcn);
+
+ first_lcn += grub_partition_get_start (root_dev->disk->partition);
+
+ start_vcn.StartingVcn.QuadPart = 0;
+
+ filehd = grub_util_fd_open (core_path, GRUB_UTIL_FD_O_RDONLY);
+ if (!GRUB_UTIL_FD_IS_VALID (filehd))
+ grub_util_error (_("cannot open `%s': %s"), core_path,
+ grub_util_fd_strerror ());
+
+ extbuf_size = sizeof (*extbuf) + sizeof (extbuf->Extents[0])
+ * ((core_size + 511) / 512);
+ extbuf = xmalloc (extbuf_size);
+
+ if (!DeviceIoControl(filehd, FSCTL_GET_RETRIEVAL_POINTERS,
+ &start_vcn, sizeof (start_vcn),
+ extbuf, extbuf_size, &rets, NULL))
+ grub_util_error ("FSCTL_GET_RETRIEVAL_POINTERS fails: %s",
+ grub_util_fd_strerror ());
+
+ CloseHandle (filehd);
+
+ for (i = 0; i < extbuf->ExtentCount; i++)
+ callback (extbuf->Extents[i].Lcn.QuadPart
+ * sec_per_lcn + first_lcn,
+ 0, 512 * sec_per_lcn * (extbuf->Extents[i].NextVcn.QuadPart - curvcn), hook_data);
+ free (extbuf);
+}
diff --git a/grub-core/osdep/windows/config.c b/grub-core/osdep/windows/config.c
new file mode 100644
index 0000000..928ab1a
--- /dev/null
+++ b/grub-core/osdep/windows/config.c
@@ -0,0 +1,57 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <config-util.h>
+
+#include <grub/emu/hostfile.h>
+#include <grub/emu/config.h>
+#include <grub/util/install.h>
+#include <grub/util/misc.h>
+
+void
+grub_util_load_config (struct grub_util_config *cfg)
+{
+ const char *cfgfile;
+ FILE *f = NULL;
+ const char *v;
+
+ cfgfile = grub_util_get_config_filename ();
+ if (!grub_util_is_regular (cfgfile))
+ return;
+
+ memset (cfg, 0, sizeof (*cfg));
+
+ v = getenv ("GRUB_ENABLE_CRYPTODISK");
+ if (v && v[0] == 'y' && v[1] == '\0')
+ cfg->is_cryptodisk_enabled = 1;
+
+ v = getenv ("GRUB_DISTRIBUTOR");
+ if (v)
+ cfg->grub_distributor = xstrdup (v);
+
+ f = grub_util_fopen (cfgfile, "r");
+ if (f)
+ {
+ grub_util_parse_config (f, cfg, 0);
+ fclose (f);
+ }
+ else
+ grub_util_warn (_("cannot open configuration file `%s': %s"),
+ cfgfile, strerror (errno));
+}
diff --git a/grub-core/osdep/windows/cputime.c b/grub-core/osdep/windows/cputime.c
new file mode 100644
index 0000000..3568aa2
--- /dev/null
+++ b/grub-core/osdep/windows/cputime.c
@@ -0,0 +1,19 @@
+#include <config.h>
+#include <config-util.h>
+
+#include <grub/emu/misc.h>
+#include <windows.h>
+
+grub_uint64_t
+grub_util_get_cpu_time_ms (void)
+{
+ FILETIME cr, ex, ke, us;
+ ULARGE_INTEGER us_ul;
+
+ GetProcessTimes (GetCurrentProcess (), &cr, &ex, &ke, &us);
+ us_ul.LowPart = us.dwLowDateTime;
+ us_ul.HighPart = us.dwHighDateTime;
+
+ return us_ul.QuadPart / 10000;
+}
+
diff --git a/grub-core/osdep/windows/dl.c b/grub-core/osdep/windows/dl.c
new file mode 100644
index 0000000..eec6a24
--- /dev/null
+++ b/grub-core/osdep/windows/dl.c
@@ -0,0 +1,59 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <config-util.h>
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+
+void *
+grub_osdep_dl_memalign (grub_size_t align, grub_size_t size)
+{
+ void *ret;
+ if (align > 4096)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too large alignment");
+ return NULL;
+ }
+
+ size = ALIGN_UP (size, 4096);
+
+ ret = VirtualAlloc (NULL, size, MEM_COMMIT | MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE);
+
+ if (!ret)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ return NULL;
+ }
+
+ return ret;
+}
+
+void
+grub_dl_osdep_dl_free (void *ptr)
+{
+ if (!ptr)
+ return;
+ VirtualFree (ptr, 0, MEM_RELEASE);
+}
diff --git a/grub-core/osdep/windows/emuconsole.c b/grub-core/osdep/windows/emuconsole.c
new file mode 100644
index 0000000..4fb3693
--- /dev/null
+++ b/grub-core/osdep/windows/emuconsole.c
@@ -0,0 +1,308 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <config-util.h>
+
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/err.h>
+
+#include <grub/emu/console.h>
+
+#include <windows.h>
+
+static HANDLE hStdin, hStdout;
+static DWORD orig_mode;
+static int saved_orig;
+
+
+static void
+grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
+ const struct grub_unicode_glyph *c)
+{
+ TCHAR str[2 + 30];
+ unsigned i, j;
+ DWORD written;
+
+ /* For now, do not try to use a surrogate pair. */
+ if (c->base > 0xffff)
+ str[0] = '?';
+ else
+ str[0] = (c->base & 0xffff);
+ j = 1;
+ for (i = 0; i < c->ncomb && j+1 < ARRAY_SIZE (str); i++)
+ if (c->base < 0xffff)
+ str[j++] = grub_unicode_get_comb (c)[i].code;
+ str[j] = 0;
+
+ WriteConsole (hStdout, str, j, &written, NULL);
+}
+
+const unsigned windows_codes[] =
+ {
+ /* 0x21 */ [VK_PRIOR] = GRUB_TERM_KEY_PPAGE,
+ /* 0x22 */ [VK_NEXT] = GRUB_TERM_KEY_NPAGE,
+ /* 0x23 */ [VK_END] = GRUB_TERM_KEY_END,
+ /* 0x24 */ [VK_HOME] = GRUB_TERM_KEY_HOME,
+ /* 0x25 */ [VK_LEFT] = GRUB_TERM_KEY_LEFT,
+ /* 0x26 */ [VK_UP] = GRUB_TERM_KEY_UP,
+ /* 0x27 */ [VK_RIGHT] = GRUB_TERM_KEY_RIGHT,
+ /* 0x28 */ [VK_DOWN] = GRUB_TERM_KEY_DOWN,
+ /* 0x2e */ [VK_DELETE] = GRUB_TERM_KEY_DC,
+ /* 0x70 */ [VK_F1] = GRUB_TERM_KEY_F1,
+ /* 0x71 */ [VK_F2] = GRUB_TERM_KEY_F2,
+ /* 0x72 */ [VK_F3] = GRUB_TERM_KEY_F3,
+ /* 0x73 */ [VK_F4] = GRUB_TERM_KEY_F4,
+ /* 0x74 */ [VK_F5] = GRUB_TERM_KEY_F5,
+ /* 0x75 */ [VK_F6] = GRUB_TERM_KEY_F6,
+ /* 0x76 */ [VK_F7] = GRUB_TERM_KEY_F7,
+ /* 0x77 */ [VK_F8] = GRUB_TERM_KEY_F8,
+ /* 0x78 */ [VK_F9] = GRUB_TERM_KEY_F9,
+ /* 0x79 */ [VK_F10] = GRUB_TERM_KEY_F10,
+ /* 0x7a */ [VK_F11] = GRUB_TERM_KEY_F11,
+ /* 0x7b */ [VK_F12] = GRUB_TERM_KEY_F12,
+ };
+
+
+static int
+grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ while (1)
+ {
+ DWORD nev;
+ INPUT_RECORD ir;
+ int ret;
+
+ if (!GetNumberOfConsoleInputEvents (hStdin, &nev))
+ return GRUB_TERM_NO_KEY;
+
+ if (nev == 0)
+ return GRUB_TERM_NO_KEY;
+
+ if (!ReadConsoleInput (hStdin, &ir, 1,
+ &nev))
+ return GRUB_TERM_NO_KEY;
+
+ if (ir.EventType != KEY_EVENT)
+ continue;
+
+ if (!ir.Event.KeyEvent.bKeyDown)
+ continue;
+ ret = ir.Event.KeyEvent.uChar.UnicodeChar;
+ if (ret == 0)
+ {
+ unsigned kc = ir.Event.KeyEvent.wVirtualKeyCode;
+ if (kc < ARRAY_SIZE (windows_codes) && windows_codes[kc])
+ ret = windows_codes[kc];
+ else
+ continue;
+ if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
+ ret |= GRUB_TERM_SHIFT;
+ }
+ /* Workaround for AltGr bug. */
+ if (ir.Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED)
+ return ret;
+ if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
+ ret |= GRUB_TERM_ALT;
+ if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
+ ret |= GRUB_TERM_CTRL;
+ return ret;
+ }
+}
+
+static struct grub_term_coordinate
+grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ csbi.dwSize.X = 80;
+ csbi.dwSize.Y = 25;
+
+ GetConsoleScreenBufferInfo (hStdout, &csbi);
+
+ return (struct grub_term_coordinate) { csbi.dwSize.X, csbi.dwSize.Y };
+}
+
+static struct grub_term_coordinate
+grub_console_getxy (struct grub_term_output *term __attribute__ ((unused)))
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ GetConsoleScreenBufferInfo (hStdout, &csbi);
+
+ return (struct grub_term_coordinate) { csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y };
+}
+
+static void
+grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
+ struct grub_term_coordinate pos)
+{
+ COORD coord = { pos.x, pos.y };
+
+ SetConsoleCursorPosition (hStdout, coord);
+}
+
+static void
+grub_console_cls (struct grub_term_output *term)
+{
+ int tsz;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ struct grub_unicode_glyph c =
+ {
+ .base = ' ',
+ .variant = 0,
+ .attributes = 0,
+ .ncomb = 0,
+ .estimated_width = 1
+ };
+
+ GetConsoleScreenBufferInfo (hStdout, &csbi);
+
+ SetConsoleTextAttribute (hStdout, 0);
+ grub_console_gotoxy (term, (struct grub_term_coordinate) { 0, 0 });
+ tsz = csbi.dwSize.X * csbi.dwSize.Y;
+
+ while (tsz--)
+ grub_console_putchar (term, &c);
+
+ grub_console_gotoxy (term, (struct grub_term_coordinate) { 0, 0 });
+ SetConsoleTextAttribute (hStdout, csbi.wAttributes);
+}
+
+static void
+grub_console_setcolorstate (struct grub_term_output *term
+ __attribute__ ((unused)),
+ grub_term_color_state state)
+{
+
+
+ switch (state) {
+ case GRUB_TERM_COLOR_STANDARD:
+ SetConsoleTextAttribute (hStdout, GRUB_TERM_DEFAULT_STANDARD_COLOR
+ & 0x7f);
+ break;
+ case GRUB_TERM_COLOR_NORMAL:
+ SetConsoleTextAttribute (hStdout, grub_term_normal_color & 0x7f);
+ break;
+ case GRUB_TERM_COLOR_HIGHLIGHT:
+ SetConsoleTextAttribute (hStdout, grub_term_highlight_color & 0x7f);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
+ int on)
+{
+ CONSOLE_CURSOR_INFO ci;
+ ci.dwSize = 5;
+ ci.bVisible = on;
+ SetConsoleCursorInfo (hStdout, &ci);
+}
+
+static grub_err_t
+grub_efi_console_init (struct grub_term_output *term)
+{
+ grub_console_setcursor (term, 1);
+ return 0;
+}
+
+static grub_err_t
+grub_efi_console_fini (struct grub_term_output *term)
+{
+ grub_console_setcursor (term, 1);
+ return 0;
+}
+
+
+static grub_err_t
+grub_console_init_input (struct grub_term_input *term)
+{
+ if (!saved_orig)
+ {
+ GetConsoleMode (hStdin, &orig_mode);
+ }
+
+ saved_orig = 1;
+
+ SetConsoleMode (hStdin, orig_mode & ~ENABLE_ECHO_INPUT
+ & ~ENABLE_LINE_INPUT & ~ENABLE_PROCESSED_INPUT);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_console_fini_input (struct grub_term_input *term
+ __attribute__ ((unused)))
+{
+ SetConsoleMode (hStdin, orig_mode);
+ saved_orig = 0;
+ return GRUB_ERR_NONE;
+}
+
+
+static struct grub_term_input grub_console_term_input =
+ {
+ .name = "console",
+ .getkey = grub_console_getkey,
+ .init = grub_console_init_input,
+ .fini = grub_console_fini_input,
+ };
+
+static struct grub_term_output grub_console_term_output =
+ {
+ .name = "console",
+ .init = grub_efi_console_init,
+ .fini = grub_efi_console_fini,
+ .putchar = grub_console_putchar,
+ .getwh = grub_console_getwh,
+ .getxy = grub_console_getxy,
+ .gotoxy = grub_console_gotoxy,
+ .cls = grub_console_cls,
+ .setcolorstate = grub_console_setcolorstate,
+ .setcursor = grub_console_setcursor,
+ .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS,
+ .progress_update_divisor = GRUB_PROGRESS_FAST
+ };
+
+void
+grub_console_init (void)
+{
+ hStdin = GetStdHandle (STD_INPUT_HANDLE);
+ hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
+
+ grub_term_register_input ("console", &grub_console_term_input);
+ grub_term_register_output ("console", &grub_console_term_output);
+}
+
+void
+grub_console_fini (void)
+{
+ if (saved_orig)
+ {
+ SetConsoleMode (hStdin, orig_mode);
+ saved_orig = 0;
+ }
+ grub_term_unregister_input (&grub_console_term_input);
+ grub_term_unregister_output (&grub_console_term_output);
+}
diff --git a/grub-core/osdep/windows/getroot.c b/grub-core/osdep/windows/getroot.c
new file mode 100644
index 0000000..eada663
--- /dev/null
+++ b/grub-core/osdep/windows/getroot.c
@@ -0,0 +1,355 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config-util.h>
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <grub/types.h>
+
+#include <grub/util/misc.h>
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+#include <grub/charset.h>
+#include <grub/util/windows.h>
+#include <windows.h>
+#include <winioctl.h>
+
+TCHAR *
+grub_get_mount_point (const TCHAR *path)
+{
+ const TCHAR *ptr;
+ TCHAR *out;
+ TCHAR letter = 0;
+ size_t allocsize;
+
+ for (ptr = path; *ptr; ptr++);
+ allocsize = (ptr - path + 10) * 2;
+ out = xcalloc (allocsize, sizeof (out[0]));
+
+ /* When pointing to EFI system partition GetVolumePathName fails
+ for ESP root and returns abberant information for everything
+ else. Since GetVolumePathName shouldn't fail for any valid
+ //?/X: we use it as indicator. */
+ if ((path[0] == '/' || path[0] == '\\')
+ && (path[1] == '/' || path[1] == '\\')
+ && (path[2] == '?' || path[2] == '.')
+ && (path[3] == '/' || path[3] == '\\')
+ && path[4]
+ && (path[5] == ':'))
+ letter = path[4];
+ if (path[0] && path[1] == ':')
+ letter = path[0];
+ if (letter)
+ {
+ TCHAR letterpath[10] = TEXT("\\\\?\\#:");
+ letterpath[4] = letter;
+ if (!GetVolumePathName (letterpath, out, allocsize))
+ {
+ if (path[1] == ':')
+ {
+ out[0] = path[0];
+ out[1] = ':';
+ out[2] = '\0';
+ return out;
+ }
+ memcpy (out, path, sizeof (out[0]) * 6);
+ out[6] = '\0';
+ return out;
+ }
+ }
+
+ if (!GetVolumePathName (path, out, allocsize))
+ {
+ free (out);
+ return NULL;
+ }
+ return out;
+}
+
+char **
+grub_guess_root_devices (const char *dir)
+{
+ char **os_dev = NULL;
+ TCHAR *dirwindows, *mntpointwindows;
+ TCHAR *ptr;
+ TCHAR volumename[100];
+
+ dirwindows = grub_util_get_windows_path (dir);
+ if (!dirwindows)
+ return 0;
+
+ mntpointwindows = grub_get_mount_point (dirwindows);
+
+ if (!mntpointwindows)
+ {
+ free (dirwindows);
+ grub_util_info ("can't get volume path name: %d", (int) GetLastError ());
+ return 0;
+ }
+
+ if (!mntpointwindows[0])
+ {
+ free (dirwindows);
+ free (mntpointwindows);
+ return 0;
+ }
+
+ for (ptr = mntpointwindows; *ptr; ptr++);
+ if (*(ptr - 1) != '\\')
+ {
+ *ptr = '\\';
+ *(ptr + 1) = '\0';
+ }
+
+ if (!GetVolumeNameForVolumeMountPoint (mntpointwindows,
+ volumename,
+ ARRAY_SIZE (volumename)))
+ {
+ TCHAR letter = 0;
+ if ((mntpointwindows[0] == '/' || mntpointwindows[0] == '\\')
+ && (mntpointwindows[1] == '/' || mntpointwindows[1] == '\\')
+ && (mntpointwindows[2] == '?' || mntpointwindows[2] == '.')
+ && (mntpointwindows[3] == '/' || mntpointwindows[3] == '\\')
+ && mntpointwindows[4]
+ && (mntpointwindows[5] == ':'))
+ letter = mntpointwindows[4];
+ if (mntpointwindows[0] && mntpointwindows[1] == ':')
+ letter = mntpointwindows[0];
+ if (!letter)
+ {
+ free (dirwindows);
+ free (mntpointwindows);
+ return 0;
+ }
+ volumename[0] = '\\';
+ volumename[1] = '\\';
+ volumename[2] = '?';
+ volumename[3] = '\\';
+ volumename[4] = letter;
+ volumename[5] = ':';
+ volumename[6] = '\0';
+ }
+ os_dev = xmalloc (2 * sizeof (os_dev[0]));
+
+ for (ptr = volumename; *ptr; ptr++);
+ while (ptr > volumename && *(ptr - 1) == '\\')
+ *--ptr = '\0';
+
+ os_dev[0] = grub_util_tchar_to_utf8 (volumename);
+ free (dirwindows);
+ free (mntpointwindows);
+
+ if (!os_dev[0])
+ {
+ free (os_dev);
+ return 0;
+ }
+
+ os_dev[1] = 0;
+
+ return os_dev;
+}
+
+static int tcharncasecmp (LPCTSTR a, const char *b, size_t sz)
+{
+ for (; sz; sz--, a++, b++)
+ {
+ char ac, bc;
+ if(*a >= 0x80)
+ return +1;
+ if (*b & 0x80)
+ return -1;
+ if (*a == '\0' && *b == '\0')
+ return 0;
+ ac = *a;
+ bc = *b;
+ if (ac >= 'A' && ac <= 'Z')
+ ac -= 'A' - 'a';
+ if (bc >= 'A' && bc <= 'Z')
+ bc -= 'A' - 'a';
+ if (ac > bc)
+ return +1;
+ if (ac < bc)
+ return -1;
+ }
+ return 0;
+}
+
+char *
+grub_util_part_to_disk (const char *os_dev,
+ struct stat *st __attribute__ ((unused)),
+ int *is_part)
+{
+ HANDLE hd;
+ LPTSTR name = grub_util_get_windows_path (os_dev);
+ VOLUME_DISK_EXTENTS exts;
+ DWORD extsbytes;
+ char *ret;
+
+ if (((name[0] == '/') || (name[0] == '\\')) &&
+ ((name[1] == '/') || (name[1] == '\\')) &&
+ ((name[2] == '.') || (name[2] == '?')) &&
+ ((name[3] == '/') || (name[3] == '\\'))
+ && (tcharncasecmp (name + 4, "PhysicalDrive", sizeof ("PhysicalDrive") - 1) == 0
+ || tcharncasecmp (name + 4, "Harddisk", sizeof ("Harddisk") - 1) == 0
+ || ((name[4] == 'A' || name[4] == 'a' || name[4] == 'B' || name[4] == 'b')
+ && name[5] == ':' && name[6] == '\0')))
+ {
+ grub_util_info ("Matches full disk pattern");
+ ret = grub_util_tchar_to_utf8 (name);
+ free (name);
+ return ret;
+ }
+
+ hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, OPEN_EXISTING, 0, 0);
+ if (hd == INVALID_HANDLE_VALUE)
+ {
+ grub_util_info ("CreateFile failed");
+ ret = grub_util_tchar_to_utf8 (name);
+ free (name);
+ return ret;
+ }
+
+ if (!DeviceIoControl(hd, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+ NULL, 0, &exts, sizeof (exts), &extsbytes, NULL))
+ {
+ grub_util_info ("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed");
+ ret = grub_util_tchar_to_utf8 (name);
+ CloseHandle (hd);
+ free (name);
+ return ret;
+ }
+
+ CloseHandle (hd);
+
+ *is_part = 1;
+ free (name);
+ return xasprintf ("\\\\?\\PhysicalDrive%lu", (unsigned long) exts.Extents[0].DiskNumber);
+}
+
+enum grub_dev_abstraction_types
+grub_util_get_dev_abstraction_os (const char *os_dev __attribute__((unused)))
+{
+ return GRUB_DEV_ABSTRACTION_NONE;
+}
+
+int
+grub_util_pull_device_os (const char *os_dev __attribute__ ((unused)),
+ enum grub_dev_abstraction_types ab __attribute__ ((unused)))
+{
+ return 0;
+}
+
+char *
+grub_util_get_grub_dev_os (const char *os_dev __attribute__ ((unused)))
+{
+ return NULL;
+}
+
+
+grub_disk_addr_t
+grub_util_find_partition_start_os (const char *os_dev)
+{
+ HANDLE hd;
+ LPTSTR name = grub_util_get_windows_path (os_dev);
+ VOLUME_DISK_EXTENTS exts;
+ DWORD extsbytes;
+ char *ret;
+
+ if (((name[0] == '/') || (name[0] == '\\')) &&
+ ((name[1] == '/') || (name[1] == '\\')) &&
+ ((name[2] == '.') || (name[2] == '?')) &&
+ ((name[3] == '/') || (name[3] == '\\'))
+ && (tcharncasecmp (name + 4, "PhysicalDrive", sizeof ("PhysicalDrive") - 1) == 0
+ || tcharncasecmp (name + 4, "Harddisk", sizeof ("Harddisk") - 1) == 0
+ || ((name[4] == 'A' || name[4] == 'a' || name[4] == 'B' || name[4] == 'b')
+ && name[5] == ':' && name[6] == '\0')))
+ {
+ ret = grub_util_tchar_to_utf8 (name);
+ free (name);
+ return 0;
+ }
+
+ hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, OPEN_EXISTING, 0, 0);
+ if (hd == INVALID_HANDLE_VALUE)
+ {
+ ret = grub_util_tchar_to_utf8 (name);
+ free (name);
+ return 0;
+ }
+
+ if (!DeviceIoControl(hd, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+ NULL, 0, &exts, sizeof (exts), &extsbytes, NULL))
+ {
+ ret = grub_util_tchar_to_utf8 (name);
+ CloseHandle (hd);
+ free (name);
+ return 0;
+ }
+
+ CloseHandle (hd);
+ free (name);
+ return exts.Extents[0].StartingOffset.QuadPart / 512;
+}
+
+int
+grub_util_biosdisk_is_floppy (grub_disk_t disk)
+{
+ int ret;
+ const char *dname;
+ LPTSTR name;
+
+ dname = grub_util_biosdisk_get_osdev (disk);
+
+ if (!dname)
+ return 0;
+
+ name = grub_util_get_windows_path (dname);
+
+ ret = (((name[0] == '/') || (name[0] == '\\')) &&
+ ((name[1] == '/') || (name[1] == '\\')) &&
+ ((name[2] == '.') || (name[2] == '?')) &&
+ ((name[3] == '/') || (name[3] == '\\'))
+ && (name[4] == 'A' || name[4] == 'a' || name[4] == 'B' || name[4] == 'b')
+ && name[5] == ':' && name[6] == '\0');
+ free (name);
+
+ return ret;
+}
diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c
new file mode 100644
index 0000000..0be3273
--- /dev/null
+++ b/grub-core/osdep/windows/hostdisk.c
@@ -0,0 +1,689 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config-util.h>
+
+#include <grub/disk.h>
+#include <grub/partition.h>
+#include <grub/msdos_partition.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/list.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <grub/util/windows.h>
+#include <grub/charset.h>
+
+#include <windows.h>
+#include <winioctl.h>
+#include <wincrypt.h>
+
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+
+#if SIZEOF_TCHAR == 1
+
+LPTSTR
+grub_util_utf8_to_tchar (const char *in)
+{
+ return xstrdup (in);
+}
+
+char *
+grub_util_tchar_to_utf8 (LPCTSTR in)
+{
+ return xstrdup (in);
+}
+
+#elif SIZEOF_TCHAR == 2
+
+LPTSTR
+grub_util_utf8_to_tchar (const char *in)
+{
+ LPTSTR ret;
+ size_t ssz = strlen (in);
+ size_t tsz = 2 * (GRUB_MAX_UTF16_PER_UTF8 * ssz + 1);
+ ret = xmalloc (tsz);
+ tsz = grub_utf8_to_utf16 (ret, tsz,
+ (const grub_uint8_t *) in, ssz, NULL);
+ ret[tsz] = 0;
+ return ret;
+}
+
+char *
+grub_util_tchar_to_utf8 (LPCTSTR in)
+{
+ size_t ssz;
+ for (ssz = 0; in[ssz]; ssz++);
+
+ size_t tsz = GRUB_MAX_UTF8_PER_UTF16 * ssz + 1;
+ grub_uint8_t *ret = xmalloc (tsz);
+ *grub_utf16_to_utf8 (ret, in, ssz) = '\0';
+ return (char *) ret;
+}
+
+#else
+#error "Unsupported TCHAR size"
+#endif
+
+
+static LPTSTR
+grub_util_get_windows_path_real (const char *path)
+{
+ LPTSTR fpa;
+ LPTSTR tpath;
+ size_t alloc, len;
+
+ tpath = grub_util_utf8_to_tchar (path);
+
+ alloc = PATH_MAX;
+
+ while (1)
+ {
+ fpa = xcalloc (alloc, sizeof (fpa[0]));
+
+ len = GetFullPathName (tpath, alloc, fpa, NULL);
+ if (len >= alloc)
+ {
+ free (fpa);
+ alloc = 2 * (len + 2);
+ continue;
+ }
+ if (len == 0)
+ {
+ free (fpa);
+ return tpath;
+ }
+
+ free (tpath);
+ return fpa;
+ }
+}
+
+#ifdef __CYGWIN__
+LPTSTR
+grub_util_get_windows_path (const char *path)
+{
+ LPTSTR winpath;
+ /* Workaround cygwin bugs with //?/. */
+ if ((path[0] == '\\' || path[0] == '/')
+ && (path[1] == '\\' || path[1] == '/')
+ && (path[2] == '?' || path[2] == '.')
+ && (path[3] == '\\' || path[3] == '/'))
+ return grub_util_get_windows_path_real (path);
+
+ winpath = xmalloc (sizeof (winpath[0]) * PATH_MAX);
+ memset (winpath, 0, sizeof (winpath[0]) * PATH_MAX);
+ if (cygwin_conv_path ((sizeof (winpath[0]) == 1 ? CCP_POSIX_TO_WIN_A
+ : CCP_POSIX_TO_WIN_W) | CCP_ABSOLUTE, path, winpath,
+ sizeof (winpath[0]) * PATH_MAX))
+ grub_util_error ("%s", _("cygwin_conv_path() failed"));
+ return winpath;
+}
+#else
+LPTSTR
+grub_util_get_windows_path (const char *path)
+{
+ return grub_util_get_windows_path_real (path);
+}
+#endif
+
+grub_uint64_t
+grub_util_get_fd_size (grub_util_fd_t hd, const char *name_in,
+ unsigned *log_secsize)
+{
+ grub_int64_t size = -1LL;
+ int log_sector_size = 9;
+ LPTSTR name = grub_util_get_windows_path (name_in);
+
+ if (log_secsize)
+ *log_secsize = log_sector_size;
+
+ if (((name[0] == '/') || (name[0] == '\\')) &&
+ ((name[1] == '/') || (name[1] == '\\')) &&
+ ((name[2] == '.') || (name[2] == '?')) &&
+ ((name[3] == '/') || (name[3] == '\\')))
+ {
+ 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;
+
+ for (log_sector_size = 0;
+ (1 << log_sector_size) < g.BytesPerSector;
+ log_sector_size++);
+ }
+ else
+ {
+ ULARGE_INTEGER s;
+
+ s.LowPart = GetFileSize (hd, &s.HighPart);
+ size = s.QuadPart;
+ }
+
+ fail:
+
+ if (log_secsize)
+ *log_secsize = log_sector_size;
+
+ free (name);
+
+ return size;
+}
+
+void
+grub_hostdisk_flush_initial_buffer (const char *os_dev __attribute__ ((unused)))
+{
+}
+
+int
+grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
+{
+ LARGE_INTEGER offset;
+ offset.QuadPart = off;
+
+ if (!SetFilePointerEx (fd, offset, NULL, FILE_BEGIN))
+ return -1;
+ return 0;
+}
+
+grub_util_fd_t
+grub_util_fd_open (const char *os_dev, int flags)
+{
+ DWORD flg = 0, crt;
+ LPTSTR dev = grub_util_get_windows_path (os_dev);
+ grub_util_fd_t ret;
+
+ if (flags & GRUB_UTIL_FD_O_WRONLY)
+ flg |= GENERIC_WRITE;
+ if (flags & GRUB_UTIL_FD_O_RDONLY)
+ flg |= GENERIC_READ;
+
+ if (flags & GRUB_UTIL_FD_O_CREATTRUNC)
+ crt = CREATE_ALWAYS;
+ else
+ crt = OPEN_EXISTING;
+
+ ret = CreateFile (dev, flg, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, crt, 0, 0);
+ free (dev);
+ return ret;
+}
+
+ssize_t
+grub_util_fd_read (grub_util_fd_t fd, char *buf, size_t len)
+{
+ DWORD real_read;
+ if (!ReadFile(fd, buf, len, &real_read, NULL))
+ {
+ grub_util_info ("read err %x", (int) GetLastError ());
+ return -1;
+ }
+ grub_util_info ("successful read");
+ return real_read;
+}
+
+ssize_t
+grub_util_fd_write (grub_util_fd_t fd, const char *buf, size_t len)
+{
+ DWORD real_read;
+ if (!WriteFile(fd, buf, len, &real_read, NULL))
+ {
+ grub_util_info ("write err %x", (int) GetLastError ());
+ return -1;
+ }
+
+ grub_util_info ("successful write");
+ return real_read;
+}
+
+static int allow_fd_syncs = 1;
+
+int
+grub_util_fd_sync (grub_util_fd_t fd)
+{
+ if (allow_fd_syncs)
+ {
+ if (!FlushFileBuffers (fd))
+ {
+ grub_util_info ("flush err %x", (int) GetLastError ());
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void
+grub_util_disable_fd_syncs (void)
+{
+ allow_fd_syncs = 0;
+}
+
+int
+grub_util_fd_close (grub_util_fd_t fd)
+{
+ if (!CloseHandle (fd))
+ {
+ grub_util_info ("close err %x", (int) GetLastError ());
+ return -1;
+ }
+ return 0;
+}
+
+const char *
+grub_util_fd_strerror (void)
+{
+ DWORD err = GetLastError ();
+ LPTSTR tstr = NULL;
+ static char *last;
+ char *ret, *ptr;
+
+ free (last);
+ last = 0;
+
+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, 0, (void *) &tstr,
+ 0, NULL);
+
+ if (!tstr)
+ return "unknown error";
+
+ ret = grub_util_tchar_to_utf8 (tstr);
+
+ LocalFree (tstr);
+
+ last = ret;
+
+ for (ptr = ret + strlen (ret) - 1;
+ ptr >= ret && (*ptr == '\n' || *ptr == '\r');
+ ptr--);
+ ptr[1] = '\0';
+
+ return ret;
+}
+
+char *
+grub_canonicalize_file_name (const char *path)
+{
+ char *ret;
+ LPTSTR windows_path;
+ ret = xmalloc (PATH_MAX);
+
+ windows_path = grub_util_get_windows_path (path);
+ if (!windows_path)
+ return NULL;
+ ret = grub_util_tchar_to_utf8 (windows_path);
+ free (windows_path);
+
+ return ret;
+}
+
+void
+grub_util_mkdir (const char *dir)
+{
+ LPTSTR windows_name;
+
+ windows_name = grub_util_get_windows_path (dir);
+ CreateDirectory (windows_name, NULL);
+ free (windows_name);
+}
+
+int
+grub_util_rename (const char *from, const char *to)
+{
+ LPTSTR windows_from, windows_to;
+ int ret;
+
+ windows_from = grub_util_get_windows_path (from);
+ windows_to = grub_util_get_windows_path (to);
+ ret = !MoveFile (windows_from, windows_to);
+ free (windows_from);
+ free (windows_to);
+ return ret;
+}
+
+struct grub_util_fd_dir
+{
+ WIN32_FIND_DATA fd;
+ HANDLE hnd;
+ int is_end;
+ char *last;
+};
+
+grub_util_fd_dir_t
+grub_util_fd_opendir (const char *name)
+{
+ struct grub_util_fd_dir *ret;
+ LPTSTR name_windows;
+ LPTSTR pattern;
+ ssize_t l;
+
+ name_windows = grub_util_get_windows_path (name);
+ for (l = 0; name_windows[l]; l++);
+ for (l--; l >= 0 && (name_windows[l] == '\\' || name_windows[l] == '/'); l--);
+ l++;
+ pattern = xcalloc (l + 3, sizeof (pattern[0]));
+ memcpy (pattern, name_windows, l * sizeof (pattern[0]));
+ pattern[l] = '\\';
+ pattern[l + 1] = '*';
+ pattern[l + 2] = '\0';
+
+ ret = xmalloc (sizeof (*ret));
+ memset (ret, 0, sizeof (*ret));
+
+ ret->hnd = FindFirstFile (pattern, &ret->fd);
+
+ free (name_windows);
+ free (pattern);
+
+ if (ret->hnd == INVALID_HANDLE_VALUE)
+ {
+ DWORD err = GetLastError ();
+ if (err == ERROR_FILE_NOT_FOUND)
+ {
+ ret->is_end = 1;
+ return ret;
+ }
+ return NULL;
+ }
+ return ret;
+}
+
+void
+grub_util_fd_closedir (grub_util_fd_dir_t dirp)
+{
+ if (dirp->hnd != INVALID_HANDLE_VALUE)
+ CloseHandle (dirp->hnd);
+ free (dirp->last);
+ free (dirp);
+}
+
+grub_util_fd_dirent_t
+grub_util_fd_readdir (grub_util_fd_dir_t dirp)
+{
+ char *ret;
+ free (dirp->last);
+ dirp->last = NULL;
+
+ if (dirp->is_end)
+ return NULL;
+
+ ret = grub_util_tchar_to_utf8 (dirp->fd.cFileName);
+ dirp->last = ret;
+
+ if (!FindNextFile (dirp->hnd, &dirp->fd))
+ dirp->is_end = 1;
+ return (grub_util_fd_dirent_t) ret;
+}
+
+int
+grub_util_unlink (const char *name)
+{
+ LPTSTR name_windows;
+ int ret;
+
+ name_windows = grub_util_get_windows_path (name);
+
+ ret = !DeleteFile (name_windows);
+ free (name_windows);
+ return ret;
+}
+
+int
+grub_util_rmdir (const char *name)
+{
+ LPTSTR name_windows;
+ int ret;
+
+ name_windows = grub_util_get_windows_path (name);
+
+ ret = !RemoveDirectory (name_windows);
+ free (name_windows);
+ return ret;
+}
+
+#ifndef __CYGWIN__
+
+static char *
+get_temp_name (void)
+{
+ TCHAR rt[1024];
+ TCHAR *ptr;
+ HCRYPTPROV hCryptProv;
+ grub_uint8_t rnd[5];
+ int i;
+
+ GetTempPath (ARRAY_SIZE (rt) - 100, rt);
+
+ if (!CryptAcquireContext (&hCryptProv,
+ NULL,
+ MS_DEF_PROV,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT)
+ || !CryptGenRandom (hCryptProv, 5, rnd))
+ grub_util_error ("%s", _("couldn't retrieve random data"));
+
+ CryptReleaseContext (hCryptProv, 0);
+
+ for (ptr = rt; *ptr; ptr++);
+ memcpy (ptr, TEXT("\\GRUB."), sizeof (TEXT("\\GRUB.")));
+ ptr += sizeof ("\\GRUB.") - 1;
+
+ for (i = 0; i < 8; i++)
+ {
+ grub_size_t b = i * 5;
+ grub_uint8_t r;
+ grub_size_t f1 = GRUB_CHAR_BIT - b % GRUB_CHAR_BIT;
+ grub_size_t f2;
+ if (f1 > 5)
+ f1 = 5;
+ f2 = 5 - f1;
+ r = (rnd[b / GRUB_CHAR_BIT] >> (b % GRUB_CHAR_BIT)) & ((1 << f1) - 1);
+ if (f2)
+ r |= (rnd[b / GRUB_CHAR_BIT + 1] & ((1 << f2) - 1)) << f1;
+ if (r < 10)
+ *ptr++ = '0' + r;
+ else
+ *ptr++ = 'a' + (r - 10);
+ }
+ *ptr = '\0';
+
+ return grub_util_tchar_to_utf8 (rt);
+}
+
+char *
+grub_util_make_temporary_file (void)
+{
+ char *ret = get_temp_name ();
+ FILE *f;
+
+ f = grub_util_fopen (ret, "wb");
+ if (f)
+ fclose (f);
+ return ret;
+}
+
+char *
+grub_util_make_temporary_dir (void)
+{
+ char *ret = get_temp_name ();
+
+ grub_util_mkdir (ret);
+
+ return ret;
+}
+
+#endif
+
+int
+grub_util_is_directory (const char *name)
+{
+ LPTSTR name_windows;
+ DWORD attr;
+
+ name_windows = grub_util_get_windows_path (name);
+ if (!name_windows)
+ return 0;
+
+ attr = GetFileAttributes (name_windows);
+ grub_free (name_windows);
+
+ return !!(attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+int
+grub_util_is_regular (const char *name)
+{
+ LPTSTR name_windows;
+ DWORD attr;
+
+ name_windows = grub_util_get_windows_path (name);
+ if (!name_windows)
+ return 0;
+
+ attr = GetFileAttributes (name_windows);
+ grub_free (name_windows);
+
+ return !(attr & FILE_ATTRIBUTE_DIRECTORY)
+ && !(attr & FILE_ATTRIBUTE_REPARSE_POINT) && attr;
+}
+
+grub_uint32_t
+grub_util_get_mtime (const char *path)
+{
+ LPTSTR name_windows;
+ BOOL b;
+ WIN32_FILE_ATTRIBUTE_DATA attr;
+ ULARGE_INTEGER us_ul;
+
+ name_windows = grub_util_get_windows_path (path);
+ if (!name_windows)
+ return 0;
+
+ b = GetFileAttributesEx (name_windows, GetFileExInfoStandard, &attr);
+ grub_free (name_windows);
+
+ if (!b)
+ return 0;
+
+ us_ul.LowPart = attr.ftLastWriteTime.dwLowDateTime;
+ us_ul.HighPart = attr.ftLastWriteTime.dwHighDateTime;
+
+ return (us_ul.QuadPart / 10000000)
+ - 86400ULL * 365 * (1970 - 1601)
+ - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
+}
+
+
+#ifdef __MINGW32__
+
+FILE *
+grub_util_fopen (const char *path, const char *mode)
+{
+ LPTSTR tpath;
+ FILE *ret;
+ tpath = grub_util_get_windows_path (path);
+#if SIZEOF_TCHAR == 1
+ ret = fopen (tpath, tmode);
+#else
+ LPTSTR tmode;
+ tmode = grub_util_utf8_to_tchar (mode);
+ ret = _wfopen (tpath, tmode);
+ free (tmode);
+#endif
+ free (tpath);
+ return ret;
+}
+
+int
+grub_util_file_sync (FILE *f)
+{
+ HANDLE hnd;
+
+ if (fflush (f) != 0)
+ {
+ grub_util_info ("fflush err %x", (int) GetLastError ());
+ return -1;
+ }
+ if (!allow_fd_syncs)
+ return 0;
+ hnd = (HANDLE) _get_osfhandle (fileno (f));
+ if (!FlushFileBuffers (hnd))
+ {
+ grub_util_info ("flush err %x", (int) GetLastError ());
+ return -1;
+ }
+ return 0;
+}
+
+int
+grub_util_is_special_file (const char *name)
+{
+ LPTSTR name_windows;
+ DWORD attr;
+
+ name_windows = grub_util_get_windows_path (name);
+ if (!name_windows)
+ return 1;
+
+ attr = GetFileAttributes (name_windows);
+ grub_free (name_windows);
+
+ return !!(attr & FILE_ATTRIBUTE_REPARSE_POINT) || !attr;
+}
+
+#else
+
+void
+grub_util_file_sync (FILE *f)
+{
+ fflush (f);
+ if (!allow_fd_syncs)
+ return;
+ fsync (fileno (f));
+}
+
+FILE *
+grub_util_fopen (const char *path, const char *mode)
+{
+ return fopen (path, mode);
+}
+
+#endif
diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c
new file mode 100644
index 0000000..6297de6
--- /dev/null
+++ b/grub-core/osdep/windows/init.c
@@ -0,0 +1,190 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <config-util.h>
+#include <grub/util/misc.h>
+#include <grub/osdep/hostfile.h>
+#include <grub/util/windows.h>
+#include <grub/emu/config.h>
+
+#include <wincon.h>
+#include <windows.h>
+
+#include <grub/util/misc.h>
+
+#include "progname.h"
+
+struct grub_windows_console_font_infoex {
+ ULONG cbSize;
+ DWORD nFont;
+ COORD dwFontSize;
+ UINT FontFamily;
+ UINT FontWeight;
+ WCHAR FaceName[LF_FACESIZE];
+};
+
+static int
+check_is_raster (HMODULE kernel32, HANDLE hnd)
+{
+ CONSOLE_FONT_INFO console_font_info;
+ BOOL (WINAPI * func_GetCurrentConsoleFont) (HANDLE, BOOL,
+ PCONSOLE_FONT_INFO);
+
+ func_GetCurrentConsoleFont = (void *)
+ GetProcAddress (kernel32, "GetCurrentConsoleFont");
+
+ if (!func_GetCurrentConsoleFont)
+ return 1;
+
+ if (!func_GetCurrentConsoleFont (hnd, FALSE, &console_font_info))
+ return 1;
+ return console_font_info.nFont < 12;
+}
+
+static void
+set_console_unicode_font (void)
+{
+ BOOL (WINAPI * func_SetCurrentConsoleFontEx) (HANDLE, BOOL,
+ struct grub_windows_console_font_infoex *);
+ BOOL (WINAPI * func_SetConsoleFont)(HANDLE, DWORD);
+ HMODULE kernel32;
+ HANDLE out_handle = GetStdHandle (STD_OUTPUT_HANDLE);
+ HANDLE err_handle = GetStdHandle (STD_ERROR_HANDLE);
+ int out_raster, err_raster;
+
+ kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
+ if (!kernel32)
+ return;
+
+ out_raster = check_is_raster (kernel32, out_handle);
+ err_raster = check_is_raster (kernel32, err_handle);
+
+ if (!out_raster && !err_raster)
+ return;
+
+ func_SetCurrentConsoleFontEx = (void *) GetProcAddress (kernel32, "SetCurrentConsoleFontEx");
+
+ /* Newer windows versions. */
+ if (func_SetCurrentConsoleFontEx)
+ {
+ struct grub_windows_console_font_infoex new_console_font_info;
+ new_console_font_info.cbSize = sizeof (new_console_font_info);
+ new_console_font_info.nFont = 12;
+ new_console_font_info.dwFontSize.X = 7;
+ new_console_font_info.dwFontSize.Y = 12;
+ new_console_font_info.FontFamily = FF_DONTCARE;
+ new_console_font_info.FontWeight = 400;
+ memcpy (new_console_font_info.FaceName, TEXT("Lucida Console"),
+ sizeof (TEXT("Lucida Console")));
+ if (out_raster)
+ func_SetCurrentConsoleFontEx (out_handle, FALSE,
+ &new_console_font_info);
+ if (err_raster)
+ func_SetCurrentConsoleFontEx (err_handle, FALSE,
+ &new_console_font_info);
+ return;
+ }
+
+ /* Fallback for older versions. */
+ func_SetConsoleFont = (void *) GetProcAddress (kernel32, "SetConsoleFont");
+ if (func_SetConsoleFont)
+ {
+ if (out_raster)
+ func_SetConsoleFont (out_handle, 12);
+ if (err_raster)
+ func_SetConsoleFont (err_handle, 12);
+ }
+}
+
+static char *grub_util_base_directory;
+static char *locale_dir;
+
+const char *
+grub_util_get_config_filename (void)
+{
+ static char *value = NULL;
+ if (!value)
+ value = grub_util_path_concat (2, grub_util_base_directory, "grub.cfg");
+ return value;
+}
+
+const char *
+grub_util_get_pkgdatadir (void)
+{
+ return grub_util_base_directory;
+}
+
+const char *
+grub_util_get_localedir (void)
+{
+ return locale_dir;
+}
+
+const char *
+grub_util_get_pkglibdir (void)
+{
+ return grub_util_base_directory;
+}
+
+void
+grub_util_host_init (int *argc __attribute__ ((unused)),
+ char ***argv)
+{
+ char *ptr;
+
+ SetConsoleOutputCP (CP_UTF8);
+ SetConsoleCP (CP_UTF8);
+
+ set_console_unicode_font ();
+
+#if SIZEOF_TCHAR == 1
+
+#elif SIZEOF_TCHAR == 2
+ LPWSTR tcmdline = GetCommandLineW ();
+ int i;
+ LPWSTR *targv;
+
+ targv = CommandLineToArgvW (tcmdline, argc);
+ *argv = xcalloc (*argc + 1, sizeof (argv[0]));
+
+ for (i = 0; i < *argc; i++)
+ (*argv)[i] = grub_util_tchar_to_utf8 (targv[i]);
+ (*argv)[i] = NULL;
+#else
+#error "Unsupported TCHAR size"
+#endif
+
+ grub_util_base_directory = grub_canonicalize_file_name ((*argv)[0]);
+ if (!grub_util_base_directory)
+ grub_util_base_directory = xstrdup ((*argv)[0]);
+ for (ptr = grub_util_base_directory + strlen (grub_util_base_directory) - 1;
+ ptr >= grub_util_base_directory && *ptr != '/' && *ptr != '\\'; ptr--);
+ if (ptr >= grub_util_base_directory)
+ *ptr = '\0';
+
+ locale_dir = grub_util_path_concat (2, grub_util_base_directory, "locale");
+
+ set_program_name ((*argv)[0]);
+
+#if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, locale_dir);
+ textdomain (PACKAGE);
+#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
+}
diff --git a/grub-core/osdep/windows/password.c b/grub-core/osdep/windows/password.c
new file mode 100644
index 0000000..1d3af0c
--- /dev/null
+++ b/grub-core/osdep/windows/password.c
@@ -0,0 +1,51 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/crypto.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+int
+grub_password_get (char buf[], unsigned buf_size)
+{
+ HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE);
+ DWORD mode = 0;
+ char *ptr;
+
+ grub_refresh ();
+
+ GetConsoleMode (hStdin, &mode);
+ SetConsoleMode (hStdin, mode & (~ENABLE_ECHO_INPUT));
+
+ fgets (buf, buf_size, stdin);
+ ptr = buf + strlen (buf) - 1;
+ while (buf <= ptr && (*ptr == '\n' || *ptr == '\r'))
+ *ptr-- = 0;
+
+ SetConsoleMode (hStdin, mode);
+
+ grub_refresh ();
+
+ return 1;
+}
diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
new file mode 100644
index 0000000..253f8d1
--- /dev/null
+++ b/grub-core/osdep/windows/platform.c
@@ -0,0 +1,426 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config-util.h>
+
+#include <windows.h>
+#include <grub/util/install.h>
+#include <grub/util/misc.h>
+#include <grub/efi/api.h>
+#include <grub/charset.h>
+#include <grub/gpt_partition.h>
+
+#define GRUB_EFI_GLOBAL_VARIABLE_GUID_WINDOWS_STR L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}"
+
+static enum { PLAT_UNK, PLAT_BIOS, PLAT_EFI } platform;
+static DWORD (WINAPI * func_GetFirmwareEnvironmentVariableW) (LPCWSTR lpName,
+ LPCWSTR lpGuid,
+ PVOID pBuffer,
+ DWORD nSize);
+static BOOL (WINAPI * func_SetFirmwareEnvironmentVariableW) (LPCWSTR lpName,
+ LPCWSTR lpGuid,
+ PVOID pBuffer,
+ DWORD nSize);
+static void (WINAPI * func_GetNativeSystemInfo) (LPSYSTEM_INFO lpSystemInfo);
+
+static int
+get_efi_privilegies (void)
+{
+ int ret = 1;
+ HANDLE hSelf;
+ TOKEN_PRIVILEGES tkp;
+
+ if (!OpenProcessToken (GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hSelf))
+ return 0;
+
+ LookupPrivilegeValue (NULL, SE_SYSTEM_ENVIRONMENT_NAME,
+ &tkp.Privileges[0].Luid);
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ if (!AdjustTokenPrivileges (hSelf, FALSE, &tkp, 0, NULL, 0))
+ ret = 0;
+ if (GetLastError () != ERROR_SUCCESS)
+ ret = 0;
+ CloseHandle (hSelf);
+ return 1;
+}
+
+static void
+get_platform (void)
+{
+ HMODULE kernel32;
+ char buffer[256];
+
+ if (platform != PLAT_UNK)
+ return;
+
+ kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
+ if (!kernel32)
+ {
+ platform = PLAT_BIOS;
+ return;
+ }
+
+ func_GetFirmwareEnvironmentVariableW = (void *)
+ GetProcAddress (kernel32, "GetFirmwareEnvironmentVariableW");
+ func_SetFirmwareEnvironmentVariableW = (void *)
+ GetProcAddress (kernel32, "SetFirmwareEnvironmentVariableW");
+ func_GetNativeSystemInfo = (void *)
+ GetProcAddress (kernel32, "GetNativeSystemInfo");
+ if (!func_GetNativeSystemInfo)
+ func_GetNativeSystemInfo = GetSystemInfo;
+ if (!func_GetFirmwareEnvironmentVariableW
+ || !func_SetFirmwareEnvironmentVariableW)
+ {
+ platform = PLAT_BIOS;
+ return;
+ }
+
+ if (!get_efi_privilegies ())
+ {
+ grub_util_warn (_("Insufficient privileges to access firmware, assuming BIOS"));
+ platform = PLAT_BIOS;
+ }
+
+ if (!func_GetFirmwareEnvironmentVariableW (L"BootOrder", GRUB_EFI_GLOBAL_VARIABLE_GUID_WINDOWS_STR,
+ buffer, sizeof (buffer))
+ && GetLastError () == ERROR_INVALID_FUNCTION)
+ {
+ platform = PLAT_BIOS;
+ return;
+ }
+ platform = PLAT_EFI;
+ return;
+}
+
+const char *
+grub_install_get_default_x86_platform (void)
+{
+ SYSTEM_INFO si;
+
+ get_platform ();
+ if (platform != PLAT_EFI)
+ return "i386-pc";
+
+ /* EFI */
+ /* Assume 64-bit in case of failure. */
+ si.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
+ func_GetNativeSystemInfo (&si);
+ if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL)
+ return "x86_64-efi";
+ else
+ return "i386-efi";
+}
+
+static void *
+get_efi_variable (const wchar_t *varname, ssize_t *len)
+{
+ void *ret = NULL;
+ size_t alloc_size = 256, read_size;
+ get_platform ();
+ while (1)
+ {
+ DWORD err;
+ ret = xmalloc (alloc_size);
+ read_size = func_GetFirmwareEnvironmentVariableW (varname, GRUB_EFI_GLOBAL_VARIABLE_GUID_WINDOWS_STR,
+ ret, alloc_size);
+ err = GetLastError ();
+ if (read_size)
+ {
+ *len = read_size;
+ return ret;
+ }
+ if (err == ERROR_INSUFFICIENT_BUFFER
+ && alloc_size * 2 != 0)
+ {
+ alloc_size *= 2;
+ free (ret);
+ continue;
+ }
+ if (err == ERROR_ENVVAR_NOT_FOUND)
+ {
+ *len = -1;
+ return NULL;
+ }
+ *len = -2;
+ return NULL;
+ }
+}
+
+static void
+set_efi_variable (const wchar_t *varname, void *in, grub_size_t len)
+{
+ get_platform ();
+ func_SetFirmwareEnvironmentVariableW (varname, GRUB_EFI_GLOBAL_VARIABLE_GUID_WINDOWS_STR,
+ in, len);
+}
+
+static char
+bin2hex (int v)
+{
+ if (v < 10)
+ return '0' + v;
+ return 'A' + v - 10;
+}
+
+static void *
+get_efi_variable_bootn (grub_uint16_t n, ssize_t *len)
+{
+ wchar_t varname[20] = L"Boot0000";
+ varname[7] = bin2hex (n & 0xf);
+ varname[6] = bin2hex ((n >> 4) & 0xf);
+ varname[5] = bin2hex ((n >> 8) & 0xf);
+ varname[4] = bin2hex ((n >> 12) & 0xf);
+ return get_efi_variable (varname, len);
+}
+
+static void
+set_efi_variable_bootn (grub_uint16_t n, void *in, grub_size_t len)
+{
+ wchar_t varname[20] = L"Boot0000";
+ varname[7] = bin2hex (n & 0xf);
+ varname[6] = bin2hex ((n >> 4) & 0xf);
+ varname[5] = bin2hex ((n >> 8) & 0xf);
+ varname[4] = bin2hex ((n >> 12) & 0xf);
+ set_efi_variable (varname, in, len);
+}
+
+int
+grub_install_register_efi (grub_device_t efidir_grub_dev,
+ const char *efifile_path,
+ const char *efi_distributor)
+{
+ grub_uint16_t *boot_order, *new_boot_order;
+ grub_uint16_t *distributor16;
+ grub_uint8_t *entry;
+ grub_size_t distrib8_len, distrib16_len, path16_len, path8_len;
+ ssize_t boot_order_len, new_boot_order_len;
+ grub_uint16_t order_num = 0;
+ int have_order_num = 0;
+ grub_size_t max_path_length;
+ grub_uint8_t *path;
+ void *pathptr;
+ struct grub_efi_hard_drive_device_path *hddp;
+ struct grub_efi_file_path_device_path *filep;
+ struct grub_efi_device_path *endp;
+
+ get_platform ();
+ if (platform != PLAT_EFI)
+ grub_util_error ("%s", _("no EFI routines are available when running in BIOS mode"));
+
+ distrib8_len = grub_strlen (efi_distributor);
+ distributor16 = xcalloc (distrib8_len + 1,
+ GRUB_MAX_UTF16_PER_UTF8 * sizeof (grub_uint16_t));
+ distrib16_len = grub_utf8_to_utf16 (distributor16, distrib8_len * GRUB_MAX_UTF16_PER_UTF8,
+ (const grub_uint8_t *) efi_distributor,
+ distrib8_len, 0);
+ distributor16[distrib16_len] = 0;
+
+ /* Windows doesn't allow to list variables so first look for bootorder to
+ find if there is an entry from the same distributor. If not try sequentially
+ until we find same distributor or empty spot. */
+ boot_order = get_efi_variable (L"BootOrder", &boot_order_len);
+ if (boot_order_len < -1)
+ grub_util_error ("%s", _("unexpected EFI error"));
+ if (boot_order_len > 0)
+ {
+ size_t i;
+ for (i = 0; i < boot_order_len / 2; i++)
+ {
+ void *current = NULL;
+ ssize_t current_len;
+ current = get_efi_variable_bootn (i, &current_len);
+ if (current_len < 0)
+ continue; /* FIXME Should we abort on error? */
+ if (current_len < (distrib16_len + 1) * sizeof (grub_uint16_t)
+ + 6)
+ {
+ grub_free (current);
+ continue;
+ }
+ if (grub_memcmp ((grub_uint16_t *) current + 3,
+ distributor16,
+ (distrib16_len + 1) * sizeof (grub_uint16_t)) != 0)
+ {
+ grub_free (current);
+ continue;
+ }
+ order_num = i;
+ have_order_num = 1;
+ grub_util_info ("Found matching distributor at Boot%04x",
+ order_num);
+ grub_free (current);
+ break;
+ }
+ }
+ if (!have_order_num)
+ {
+ size_t i;
+ for (i = 0; i < 0x10000; i++)
+ {
+ void *current = NULL;
+ ssize_t current_len;
+ current = get_efi_variable_bootn (i, &current_len);
+ if (current_len < -1)
+ continue; /* FIXME Should we abort on error? */
+ if (current_len == -1)
+ {
+ if (!have_order_num)
+ {
+ order_num = i;
+ have_order_num = 1;
+ grub_util_info ("Creating new entry at Boot%04x",
+ order_num);
+ }
+ continue;
+ }
+ if (current_len < (distrib16_len + 1) * sizeof (grub_uint16_t)
+ + 6)
+ {
+ grub_free (current);
+ continue;
+ }
+ if (grub_memcmp ((grub_uint16_t *) current + 3,
+ distributor16,
+ (distrib16_len + 1) * sizeof (grub_uint16_t)) != 0)
+ {
+ grub_free (current);
+ continue;
+ }
+ order_num = i;
+ have_order_num = 1;
+ grub_util_info ("Found matching distributor at Boot%04x",
+ order_num);
+ grub_free (current);
+ break;
+ }
+ }
+ if (!have_order_num)
+ grub_util_error ("%s", _("Couldn't find a free BootNNNN slot"));
+ path8_len = grub_strlen (efifile_path);
+ max_path_length = sizeof (*hddp) + sizeof (*filep) + (path8_len * GRUB_MAX_UTF16_PER_UTF8 + 1) * sizeof (grub_uint16_t) + sizeof (*endp);
+ entry = xmalloc (6 + (distrib16_len + 1) * sizeof (grub_uint16_t) + max_path_length);
+ /* attributes: active. */
+ entry[0] = 1;
+ entry[1] = 0;
+ entry[2] = 0;
+ entry[3] = 0;
+ grub_memcpy (entry + 6,
+ distributor16,
+ (distrib16_len + 1) * sizeof (grub_uint16_t));
+
+ path = entry + 6 + (distrib16_len + 1) * sizeof (grub_uint16_t);
+ pathptr = path;
+
+ hddp = pathptr;
+ grub_memset (hddp, 0, sizeof (*hddp));
+ hddp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
+ hddp->header.subtype = GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE;
+ hddp->header.length = sizeof (*hddp);
+ hddp->partition_number = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
+ if (efidir_grub_dev->disk->partition
+ && grub_strcmp (efidir_grub_dev->disk->partition->partmap->name, "msdos") == 0)
+ {
+ grub_partition_t p;
+
+ p = efidir_grub_dev->disk->partition;
+ efidir_grub_dev->disk->partition = p->parent;
+ if (grub_disk_read (efidir_grub_dev->disk, 0, 440,
+ 4, hddp->partition_signature))
+ grub_util_error ("%s", grub_errmsg);
+ efidir_grub_dev->disk->partition = p;
+
+ hddp->partmap_type = 1;
+ hddp->signature_type = 1;
+ }
+ else if (efidir_grub_dev->disk->partition
+ && grub_strcmp (efidir_grub_dev->disk->partition->partmap->name, "gpt") == 0)
+ {
+ struct grub_gpt_partentry gptdata;
+ grub_partition_t p;
+
+ p = efidir_grub_dev->disk->partition;
+ efidir_grub_dev->disk->partition = p->parent;
+ if (grub_disk_read (efidir_grub_dev->disk,
+ p->offset, p->index,
+ sizeof (gptdata), &gptdata))
+ grub_util_error ("%s", grub_errmsg);
+ efidir_grub_dev->disk->partition = p;
+ grub_memcpy (hddp->partition_signature,
+ &gptdata.guid, 16);
+
+ hddp->partmap_type = 2;
+ hddp->signature_type = 2;
+ }
+
+ hddp->partition_start = grub_partition_get_start (efidir_grub_dev->disk->partition)
+ >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+ hddp->partition_size = grub_disk_native_sectors (efidir_grub_dev->disk)
+ >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+
+ pathptr = hddp + 1;
+ filep = pathptr;
+ filep->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
+ filep->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
+
+ path16_len = grub_utf8_to_utf16 (filep->path_name,
+ path8_len * GRUB_MAX_UTF16_PER_UTF8,
+ (const grub_uint8_t *) efifile_path,
+ path8_len, 0);
+ filep->path_name[path16_len] = 0;
+ filep->header.length = sizeof (*filep) + (path16_len + 1) * sizeof (grub_uint16_t);
+ pathptr = &filep->path_name[path16_len + 1];
+ endp = pathptr;
+ endp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ endp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ endp->length = sizeof (*endp);
+ pathptr = endp + 1;
+
+ entry[4] = (grub_uint8_t *) pathptr - path;
+ entry[5] = ((grub_uint8_t *) pathptr - path) >> 8;
+
+ new_boot_order = xmalloc ((boot_order_len > 0 ? boot_order_len : 0) + 2);
+ new_boot_order[0] = order_num;
+ new_boot_order_len = 1;
+ {
+ ssize_t i;
+ for (i = 0; i < boot_order_len / 2; i++)
+ if (boot_order[i] != order_num)
+ new_boot_order[new_boot_order_len++] = boot_order[i];
+ }
+
+ set_efi_variable_bootn (order_num, entry, (grub_uint8_t *) pathptr - entry);
+ set_efi_variable (L"BootOrder", new_boot_order, new_boot_order_len * sizeof (grub_uint16_t));
+
+ return 0;
+}
+
+void
+grub_install_register_ieee1275 (int is_prep, const char *install_device,
+ int partno, const char *relpath)
+{
+ grub_util_error ("%s", _("no IEEE1275 routines are available for your platform"));
+}
+
+void
+grub_install_sgi_setup (const char *install_device,
+ const char *imgfile, const char *destname)
+{
+ grub_util_error ("%s", _("no SGI routines are available for your platform"));
+}
diff --git a/grub-core/osdep/windows/random.c b/grub-core/osdep/windows/random.c
new file mode 100644
index 0000000..78f5082
--- /dev/null
+++ b/grub-core/osdep/windows/random.c
@@ -0,0 +1,55 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1992-1999,2001,2003,2004,2005,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/types.h>
+#include <grub/crypto.h>
+#include <grub/auth.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+int
+grub_get_random (void *out, grub_size_t len)
+{
+ HCRYPTPROV hCryptProv;
+ if (!CryptAcquireContext (&hCryptProv,
+ NULL,
+ MS_DEF_PROV,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return 1;
+ if (!CryptGenRandom (hCryptProv, len, out))
+ {
+ CryptReleaseContext (hCryptProv, 0);
+ return 1;
+ }
+
+ CryptReleaseContext (hCryptProv, 0);
+
+ return 0;
+}
diff --git a/grub-core/osdep/windows/relpath.c b/grub-core/osdep/windows/relpath.c
new file mode 100644
index 0000000..478e8ef
--- /dev/null
+++ b/grub-core/osdep/windows/relpath.c
@@ -0,0 +1,96 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config-util.h>
+#include <config.h>
+
+#include <grub/types.h>
+
+#include <grub/util/misc.h>
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+#include <grub/charset.h>
+#include <grub/util/windows.h>
+#include <windows.h>
+#include <winioctl.h>
+
+static size_t
+tclen (const TCHAR *s)
+{
+ const TCHAR *s0 = s;
+ while (*s)
+ s++;
+ return s - s0;
+}
+
+char *
+grub_make_system_path_relative_to_its_root (const char *path)
+{
+ TCHAR *dirwindows, *mntpointwindows;
+ TCHAR *ptr;
+ size_t offset, flen;
+ TCHAR *ret;
+ char *cret;
+
+ dirwindows = grub_util_get_windows_path (path);
+ if (!dirwindows)
+ return xstrdup (path);
+
+ mntpointwindows = grub_get_mount_point (dirwindows);
+
+ if (!mntpointwindows)
+ {
+ offset = 0;
+ if (dirwindows[0] && dirwindows[1] == ':')
+ offset = 2;
+ }
+ offset = tclen (mntpointwindows);
+ free (mntpointwindows);
+ flen = tclen (dirwindows);
+ if (offset > flen)
+ {
+ offset = 0;
+ if (dirwindows[0] && dirwindows[1] == ':')
+ offset = 2;
+ }
+ ret = xcalloc (flen - offset + 2, sizeof (ret[0]));
+ if (dirwindows[offset] != '\\'
+ && dirwindows[offset] != '/'
+ && dirwindows[offset])
+ {
+ ret[0] = '\\';
+ memcpy (ret + 1, dirwindows + offset, (flen - offset + 1) * sizeof (ret[0]));
+ }
+ else
+ memcpy (ret, dirwindows + offset, (flen - offset + 1) * sizeof (ret[0]));
+
+ free (dirwindows);
+
+ for (ptr = ret; *ptr; ptr++)
+ if (*ptr == '\\')
+ *ptr = '/';
+
+ cret = grub_util_tchar_to_utf8 (ret);
+ free (ret);
+
+ return cret;
+}
diff --git a/grub-core/osdep/windows/sleep.c b/grub-core/osdep/windows/sleep.c
new file mode 100644
index 0000000..03b846b
--- /dev/null
+++ b/grub-core/osdep/windows/sleep.c
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config-util.h>
+#include <config.h>
+
+#include <windows.h>
+#include <winioctl.h>
+#include <grub/time.h>
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+ Sleep (ms);
+}
+