diff options
Diffstat (limited to 'grub-core/osdep/windows')
-rw-r--r-- | grub-core/osdep/windows/blocklist.c | 118 | ||||
-rw-r--r-- | grub-core/osdep/windows/config.c | 57 | ||||
-rw-r--r-- | grub-core/osdep/windows/cputime.c | 19 | ||||
-rw-r--r-- | grub-core/osdep/windows/dl.c | 59 | ||||
-rw-r--r-- | grub-core/osdep/windows/emuconsole.c | 308 | ||||
-rw-r--r-- | grub-core/osdep/windows/getroot.c | 355 | ||||
-rw-r--r-- | grub-core/osdep/windows/hostdisk.c | 689 | ||||
-rw-r--r-- | grub-core/osdep/windows/init.c | 190 | ||||
-rw-r--r-- | grub-core/osdep/windows/password.c | 51 | ||||
-rw-r--r-- | grub-core/osdep/windows/platform.c | 426 | ||||
-rw-r--r-- | grub-core/osdep/windows/random.c | 55 | ||||
-rw-r--r-- | grub-core/osdep/windows/relpath.c | 96 | ||||
-rw-r--r-- | grub-core/osdep/windows/sleep.c | 31 |
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, ¤t_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, ¤t_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); +} + |