blocklist.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2013 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <config.h>
  19. #include <grub/disk.h>
  20. #include <grub/partition.h>
  21. #include <grub/fs.h>
  22. #include <grub/ntfs.h>
  23. #include <grub/fat.h>
  24. #include <grub/exfat.h>
  25. #include <grub/udf.h>
  26. #include <grub/util/misc.h>
  27. #include <grub/util/install.h>
  28. #include <grub/emu/getroot.h>
  29. #include <grub/emu/hostfile.h>
  30. #include <windows.h>
  31. #include <winioctl.h>
  32. void
  33. grub_install_get_blocklist (grub_device_t root_dev,
  34. const char *core_path,
  35. const char *core_img __attribute__ ((unused)),
  36. size_t core_size,
  37. void (*callback) (grub_disk_addr_t sector,
  38. unsigned offset,
  39. unsigned length,
  40. void *data),
  41. void *hook_data)
  42. {
  43. grub_disk_addr_t first_lcn = 0;
  44. HANDLE filehd;
  45. DWORD rets;
  46. RETRIEVAL_POINTERS_BUFFER *extbuf;
  47. size_t extbuf_size;
  48. DWORD i;
  49. grub_uint64_t sec_per_lcn;
  50. grub_uint64_t curvcn = 0;
  51. STARTING_VCN_INPUT_BUFFER start_vcn;
  52. grub_fs_t fs;
  53. grub_err_t err;
  54. fs = grub_fs_probe (root_dev);
  55. if (!fs)
  56. grub_util_error ("%s", grub_errmsg);
  57. /* This is ugly but windows doesn't give all needed data. Or does anyone
  58. have a pointer how to retrieve it?
  59. */
  60. if (grub_strcmp (fs->name, "ntfs") == 0)
  61. {
  62. struct grub_ntfs_bpb bpb;
  63. err = grub_disk_read (root_dev->disk, 0, 0, sizeof (bpb), &bpb);
  64. if (err)
  65. grub_util_error ("%s", grub_errmsg);
  66. sec_per_lcn = ((grub_uint32_t) bpb.sectors_per_cluster
  67. * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector))
  68. >> 9;
  69. first_lcn = 0;
  70. }
  71. else if (grub_strcmp (fs->name, "exfat") == 0)
  72. first_lcn = grub_exfat_get_cluster_sector (root_dev->disk, &sec_per_lcn);
  73. else if (grub_strcmp (fs->name, "fat") == 0)
  74. first_lcn = grub_fat_get_cluster_sector (root_dev->disk, &sec_per_lcn);
  75. else if (grub_strcmp (fs->name, "udf") == 0)
  76. first_lcn = grub_udf_get_cluster_sector (root_dev->disk, &sec_per_lcn);
  77. else
  78. grub_util_error ("unsupported fs for blocklist on windows: %s",
  79. fs->name);
  80. grub_util_info ("sec_per_lcn = %" GRUB_HOST_PRIuLONG_LONG
  81. ", first_lcn=%" GRUB_HOST_PRIuLONG_LONG,
  82. (unsigned long long) sec_per_lcn,
  83. (unsigned long long) first_lcn);
  84. first_lcn += grub_partition_get_start (root_dev->disk->partition);
  85. start_vcn.StartingVcn.QuadPart = 0;
  86. filehd = grub_util_fd_open (core_path, GRUB_UTIL_FD_O_RDONLY);
  87. if (!GRUB_UTIL_FD_IS_VALID (filehd))
  88. grub_util_error (_("cannot open `%s': %s"), core_path,
  89. grub_util_fd_strerror ());
  90. extbuf_size = sizeof (*extbuf) + sizeof (extbuf->Extents[0])
  91. * ((core_size + 511) / 512);
  92. extbuf = xmalloc (extbuf_size);
  93. if (!DeviceIoControl(filehd, FSCTL_GET_RETRIEVAL_POINTERS,
  94. &start_vcn, sizeof (start_vcn),
  95. extbuf, extbuf_size, &rets, NULL))
  96. grub_util_error ("FSCTL_GET_RETRIEVAL_POINTERS fails: %s",
  97. grub_util_fd_strerror ());
  98. CloseHandle (filehd);
  99. for (i = 0; i < extbuf->ExtentCount; i++)
  100. callback (extbuf->Extents[i].Lcn.QuadPart
  101. * sec_per_lcn + first_lcn,
  102. 0, 512 * sec_per_lcn * (extbuf->Extents[i].NextVcn.QuadPart - curvcn), hook_data);
  103. free (extbuf);
  104. }