1
Description: Several EFI device discovery patches to fix boot failures
2
Move compare_device_paths to an externally-visible function.
6
Accept whole disk declared as partition.
8
Fix incorrect memory usage.
10
Remove unreachable code.
12
Simplify root device discovery and don't fail when trying to open incorrect
14
Author: Vladimir Serbinenko <phcoder@gmail.com>
15
Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3375
16
Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3383
17
Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3652
18
Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3781
19
Bug-Ubuntu: https://bugs.launchpad.net/bugs/975061
21
Last-Update: 2012-04-17
23
Index: b/grub-core/disk/efi/efidisk.c
24
===================================================================
25
--- a/grub-core/disk/efi/efidisk.c
26
+++ b/grub-core/disk/efi/efidisk.c
31
-/* Compare device paths. */
33
-compare_device_paths (const grub_efi_device_path_t *dp1,
34
- const grub_efi_device_path_t *dp2)
37
- /* Return non-zero. */
42
- grub_efi_uint8_t type1, type2;
43
- grub_efi_uint8_t subtype1, subtype2;
44
- grub_efi_uint16_t len1, len2;
47
- type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
48
- type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
51
- return (int) type2 - (int) type1;
53
- subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
54
- subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
56
- if (subtype1 != subtype2)
57
- return (int) subtype1 - (int) subtype2;
59
- len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
60
- len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
63
- return (int) len1 - (int) len2;
65
- ret = grub_memcmp (dp1, dp2, len1);
69
- if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
72
- dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
73
- dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
79
static struct grub_efidisk_data *
86
- if (compare_device_paths (parent->device_path, dp) == 0)
87
+ if (grub_efi_compare_device_paths (parent->device_path, dp) == 0)
90
if (! parent->last_device_path)
92
ldp->length[0] = sizeof (*ldp);
95
- if (compare_device_paths (dp, d->device_path) == 0)
96
+ if (grub_efi_compare_device_paths (dp, d->device_path) == 0)
100
@@ -273,11 +225,11 @@
104
- ret = compare_device_paths (find_last_device_path ((*p)->device_path),
105
- find_last_device_path (d->device_path));
106
+ ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
107
+ find_last_device_path (d->device_path));
109
- ret = compare_device_paths ((*p)->device_path,
111
+ ret = grub_efi_compare_device_paths ((*p)->device_path,
117
and total sectors should be replaced with total blocks. */
118
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
119
m, (unsigned long long) m->last_block, m->block_size);
120
- disk->total_sectors = m->last_block;
121
+ disk->total_sectors = m->last_block + 1;
122
if (m->block_size & (m->block_size - 1) || !m->block_size)
123
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
125
@@ -703,10 +655,52 @@
129
+#define NEEDED_BUFLEN sizeof ("XdXXXXXXXXXX")
131
+get_diskname_from_path_real (const grub_efi_device_path_t *path,
132
+ struct grub_efidisk_data *head,
136
+ struct grub_efidisk_data *d;
137
+ for (d = head, count = 0; d; d = d->next, count++)
138
+ if (grub_efi_compare_device_paths (d->device_path, path) == 0)
140
+ grub_snprintf (buf, NEEDED_BUFLEN - 1, "d%d", count);
147
+get_diskname_from_path (const grub_efi_device_path_t *path,
150
+ if (get_diskname_from_path_real (path, hd_devices, buf + 1))
156
+ if (get_diskname_from_path_real (path, fd_devices, buf + 1))
162
+ if (get_diskname_from_path_real (path, cd_devices, buf + 1))
171
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
173
grub_efi_device_path_t *dp, *ldp;
174
+ char device_name[NEEDED_BUFLEN];
176
dp = grub_efi_get_device_path (handle);
178
@@ -720,39 +714,13 @@
179
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
180
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
182
- /* This is a hard disk partition. */
183
- grub_disk_t parent = 0;
184
- grub_partition_t tpart = NULL;
186
+ char *partition_name = NULL;
188
grub_efi_device_path_t *dup_dp, *dup_ldp;
189
grub_efi_hard_drive_device_path_t hd;
190
- auto int find_parent_disk (const char *name);
191
- auto int find_partition (grub_disk_t disk, const grub_partition_t part);
193
- /* Find the disk which is the parent of a given hard disk partition. */
194
- int find_parent_disk (const char *name)
198
- disk = grub_disk_open (name);
202
- if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
204
- struct grub_efidisk_data *d;
207
- if (compare_device_paths (d->device_path, dup_dp) == 0)
213
+ grub_disk_t parent = 0;
215
- grub_disk_close (disk);
218
+ auto int find_partition (grub_disk_t disk, const grub_partition_t part);
220
/* Find the identical partition. */
221
int find_partition (grub_disk_t disk __attribute__ ((unused)),
223
if (grub_partition_get_start (part) == hd.partition_start
224
&& grub_partition_get_len (part) == hd.partition_size)
227
+ partition_name = grub_partition_get_name (part);
232
dup_ldp->length[0] = sizeof (*dup_ldp);
233
dup_ldp->length[1] = 0;
235
- grub_efidisk_iterate (find_parent_disk);
236
+ if (!get_diskname_from_path (dup_dp, device_name))
238
+ parent = grub_disk_open (device_name);
242
@@ -788,58 +758,33 @@
244
/* Find a partition which matches the hard drive device path. */
245
grub_memcpy (&hd, ldp, sizeof (hd));
246
- grub_partition_iterate (parent, find_partition);
249
+ if (hd.partition_start == 0
250
+ && hd.partition_size == grub_disk_get_size (parent))
252
- grub_disk_close (parent);
254
+ dev_name = grub_strdup (parent->name);
258
- char *partition_name = grub_partition_get_name (tpart);
259
- device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
260
- grub_free (partition_name);
262
- grub_disk_close (parent);
264
- return device_name;
268
- /* This should be an entire disk. */
269
- auto int find_disk (const char *name);
270
- char *device_name = 0;
272
- int find_disk (const char *name)
277
- disk = grub_disk_open (name);
280
+ grub_partition_iterate (parent, find_partition);
282
- if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
283
+ if (! partition_name)
285
- struct grub_efidisk_data *d;
288
- if (compare_device_paths (d->device_path, dp) == 0)
290
- device_name = grub_strdup (disk->name);
291
- grub_disk_close (disk);
294
+ grub_disk_close (parent);
298
- grub_disk_close (disk);
301
+ dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
302
+ grub_free (partition_name);
304
+ grub_disk_close (parent);
306
- grub_efidisk_iterate (find_disk);
307
- return device_name;
312
+ /* This should be an entire disk. */
313
+ if (!get_diskname_from_path (dp, device_name))
315
+ return grub_strdup (device_name);
320
Index: b/grub-core/kern/efi/efi.c
321
===================================================================
322
--- a/grub-core/kern/efi/efi.c
323
+++ b/grub-core/kern/efi/efi.c
325
dp = (grub_efi_device_path_t *) ((char *) dp + len);
329
+/* Compare device paths. */
331
+grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
332
+ const grub_efi_device_path_t *dp2)
334
+ if (! dp1 || ! dp2)
335
+ /* Return non-zero. */
340
+ grub_efi_uint8_t type1, type2;
341
+ grub_efi_uint8_t subtype1, subtype2;
342
+ grub_efi_uint16_t len1, len2;
345
+ type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
346
+ type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
348
+ if (type1 != type2)
349
+ return (int) type2 - (int) type1;
351
+ subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
352
+ subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
354
+ if (subtype1 != subtype2)
355
+ return (int) subtype1 - (int) subtype2;
357
+ len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
358
+ len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
361
+ return (int) len1 - (int) len2;
363
+ ret = grub_memcmp (dp1, dp2, len1);
367
+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
370
+ dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
371
+ dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
376
Index: b/include/grub/efi/efi.h
377
===================================================================
378
--- a/include/grub/efi/efi.h
379
+++ b/include/grub/efi/efi.h
381
grub_efi_uint32_t descriptor_version,
382
grub_efi_memory_descriptor_t *virtual_map);
385
+EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
386
+ const grub_efi_device_path_t *dp2);
388
void grub_efi_mm_init (void);
389
void grub_efi_mm_fini (void);
390
void grub_efi_init (void);