* grub-core/fs/btrfs.c (grub_btrfs_embed) [GRUB_UTIL]: New function.
(grub_btrfs_fs) [GRUB_UTIL]: Set embed.
* include/grub/fs.h (grub_fs) [GRUB_UTIL]: New field embed.
* util/grub-setup.c (setup): Use fs embedding if available.
Add additional sanity check.
+2011-11-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Support BtrFS embedding.
+
+ * grub-core/fs/btrfs.c (grub_btrfs_embed) [GRUB_UTIL]: New function.
+ (grub_btrfs_fs) [GRUB_UTIL]: Set embed.
+ * include/grub/fs.h (grub_fs) [GRUB_UTIL]: New field embed.
+ * util/grub-setup.c (setup): Use fs embedding if available.
+ Add additional sanity check.
+
2011-11-05 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub-install.in: Fix condition for config_opt.
return grub_errno;
}
+#ifdef GRUB_UTIL
+static grub_err_t
+grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
+ unsigned int *nsectors,
+ grub_embed_type_t embed_type,
+ grub_disk_addr_t **sectors)
+{
+ unsigned i;
+
+ if (embed_type != GRUB_EMBED_PCBIOS)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "BtrFS curently supports only PC-BIOS embedding");
+
+ if (64 * 2 - 1 < *nsectors)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "Your core.img is unusually large. "
+ "It won't fit in the embedding area.");
+
+ *nsectors = 64 * 2 - 1;
+ *sectors = grub_malloc (*nsectors * sizeof (**sectors));
+ if (!*sectors)
+ return grub_errno;
+ for (i = 0; i < *nsectors; i++)
+ (*sectors)[i] = i + 1;
+
+ return GRUB_ERR_NONE;
+}
+#endif
+
static struct grub_fs grub_btrfs_fs = {
.name = "btrfs",
.dir = grub_btrfs_dir,
.uuid = grub_btrfs_uuid,
.label = grub_btrfs_label,
#ifdef GRUB_UTIL
+ .embed = grub_btrfs_embed,
.reserved_first_sector = 1,
#endif
};
#include <grub/types.h>
#include <grub/list.h>
+/* For embedding types. */
+#ifdef GRUB_UTIL
+#include <grub/partition.h>
+#endif
/* Forward declaration is required, because of mutual reference. */
struct grub_file;
grub_err_t (*mtime) (grub_device_t device, grub_int32_t *timebuf);
#ifdef GRUB_UTIL
+ /* Determine sectors available for embedding. */
+ grub_err_t (*embed) (grub_device_t device, unsigned int *nsectors,
+ grub_embed_type_t embed_type,
+ grub_disk_addr_t **sectors);
+
/* Whether this filesystem reserves first sector for DOS-style boot. */
int reserved_first_sector;
#endif
free (tmp_img);
- if (! dest_partmap)
+ if (! dest_partmap && ! fs)
{
grub_util_warn (_("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
goto unable_to_embed;
}
- if (multiple_partmaps || fs)
+ if (multiple_partmaps || (dest_partmap && fs))
{
grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet."));
goto unable_to_embed;
}
- if (!dest_partmap->embed)
+ if (dest_partmap && !dest_partmap->embed)
{
grub_util_warn ("Partition style '%s' doesn't support embeding",
dest_partmap->name);
goto unable_to_embed;
}
+ if (fs && !fs->embed)
+ {
+ grub_util_warn ("File system '%s' doesn't support embeding",
+ fs->name);
+ goto unable_to_embed;
+ }
+
nsec = core_sectors;
- err = dest_partmap->embed (dest_dev->disk, &nsec,
- GRUB_EMBED_PCBIOS, §ors);
- if (nsec > 2 * core_sectors)
- nsec = 2 * core_sectors;
+ if (dest_partmap)
+ err = dest_partmap->embed (dest_dev->disk, &nsec,
+ GRUB_EMBED_PCBIOS, §ors);
+ else
+ err = fs->embed (dest_dev, &nsec,
+ GRUB_EMBED_PCBIOS, §ors);
+ if (!err && nsec < core_sectors)
+ {
+ err = grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "Your embedding area is unusually small. "
+ "core.img won't fit in it.");
+ }
if (err)
{
goto unable_to_embed;
}
+ if (nsec > 2 * core_sectors)
+ nsec = 2 * core_sectors;
+
/* Clean out the blocklists. */
block = first_block;
while (block->len)