<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>No Name Blog &#187; grub</title>
	<atom:link href="http://ebroder.net/tag/grub/feed/" rel="self" type="application/rss+xml" />
	<link>http://ebroder.net</link>
	<description>Because all the cool names are taken</description>
	<lastBuildDate>Mon, 14 Jun 2010 03:14:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Installing GRUB onto a Disk Image</title>
		<link>http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/</link>
		<comments>http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 23:22:32 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[planet sipb]]></category>
		<category><![CDATA[posts]]></category>
		<category><![CDATA[disk]]></category>
		<category><![CDATA[grub]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[virtualization]]></category>

		<guid isPermaLink="false">http://ebroder.net/?p=274</guid>
		<description><![CDATA[As part of my summer internship, I needed to write an installer for VMs. For various reasons, I wasn&#8217;t able to use the multitude of VM installers already out there, but one thing I noticed is that most of them don&#8217;t actually install a bootloader. They create a /boot/grub/menu.lst, but never run grub-install. Turns out <a href='http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>As part of my <a href="http://debmarshal.googlecode.com">summer internship</a>, I needed to write an installer for VMs. For various reasons, I wasn&#8217;t able to use the <a href="http://www.xen-tools.org/software/xen-tools/">multitude</a> <a href="http://virt-manager.et.redhat.com/">of</a> <a href="https://launchpad.net/vmbuilder">VM</a> <a href="http://susestudio.com/">installers</a> already out there, but one thing I noticed is that most of them don&#8217;t actually install a bootloader. They create a <code>/boot/grub/menu.lst</code>, but never run <code>grub-install</code>.</p>
<p>Turns out this is because it&#8217;s <em>hard</em> to do. <code>grub-install</code> is very complicated and seems to be pretty explicitly designed for the case of running in an installer environment, where all of the disks and block devices are laid out the same way as they will be the next time you boot. When you&#8217;re installing in a host into a loop mount or something, that&#8217;s definitely not the case.</p>
<p>In trying to make this work, I discovered a few core issues:</p>
<ul>
<li><code>grub-install</code> assumes that the block device you&#8217;re installing onto &#8220;looks like&#8221; the sort of device you&#8217;d normally install GRUB onto (i.e. is named like a hard disk or floppy &#8211; hda, sda, fd0, etc.)</li>
<li><code>grub-install</code> uses <code>df</code> to determine the block device a given file or directory&#8217;s filesystem is on. That works really poorly when you&#8217;re already chrooting into your loop mount.</li>
</ul>
<p>If you read my wording carefully, you might see where I&#8217;m going with this. In order to get grub-install to work, I needed to convince it it&#8217;s installing onto a hard drive, and I needed to run it outside of the loop mount.</p>
<p>The former is obviously a bit more challenging, and to accomplish that, I used the device-mapper to create a node named something like <code>/dev/mapper/hda</code>.</p>
<p>I&#8217;ve only tested this on an Ubuntu Jaunty host so far, so I can&#8217;t guarantee that it works on Debian or even other Ubuntu versions, but I think it should. I&#8217;d love to hear if you have good or bad experiences on other Linux versions.</p>
<p>Here&#8217;s roughly how it works (you&#8217;ve probably performed some of these steps already in the process of running an installer):</p>
<ol>
<li>Loop mount your partitioned disk image:<br />
<blockquote><pre>mathias:~ evan$ sudo losetup --show --find disk.img
/dev/loop0</pre>
</blockquote>
</li>
<li>To setup the device map, you&#8217;ll need the major and minor numbers of the loop device, and the size (in bytes) of the disk. The latter is easiest to get from the disk image file, instead of from the loop device (emphasis mine):<br />
<blockquote><pre>mathias:~ evan$ ls -l /dev/loop0
brw-rw---- 1 root disk <strong>7, 0</strong> 2009-07-18 11:27 /dev/loop0
mathias:~ evan$ ls -l disk.img
-rw-r--r-- 1 evan evan <strong>10737418240</strong> 2009-08-04 15:28 disk.img</pre>
</blockquote>
</li>
<li>Create a device-mapper node. Any name of the form <code>hd[a-z]</code>, <code>sd[a-z]</code>, or <code>vd[a-z]</code> will work. Others might as well. The size of the disk should be converted to 512-byte sectors, and the device numbers for the loop device should be in the form major:minor. This will create a new device node in <code>/dev/mapper</code>:<br />
<blockquote><pre>mathias:~ evan$ echo '0 20971520 linear 7:0 0' | sudo dmsetup create hda
mathias:~ evan$ ls -l /dev/mapper/hda
brw-rw---- 1 root disk 252, 4 2009-08-04 15:36 /dev/mapper/hda
</pre>
</blockquote>
</li>
<li>Use <code>kpartx</code> to create device-mapper nodes for the partitions on the disk image:<br />
<blockquote><pre>mathias:~ evan$ sudo kpartx -a /dev/mapper/hda
mathias:~ evan$ ls -l /dev/mapper/hda*
brw-rw---- 1 root disk 252, 4 2009-08-04 15:36 /dev/mapper/hda
brw-rw---- 1 root disk 252, 5 2009-08-04 15:38 /dev/mapper/hda1
brw-rw---- 1 root disk 252, 6 2009-08-04 15:38 /dev/mapper/hda2</pre>
</blockquote>
</li>
<li>Mount the root partition onto a tempdir (note: this is not a loop mount, because the kernel already thinks this is a real block device):<br />
<blockquote><pre>mathias:~ evan$ mktemp -d
/tmp/tmp.MPUXeJWqpn
mathias:~ evan$ sudo mount /dev/mapper/hda1 /tmp/tmp.MPUXeJWqpn</pre>
</blockquote>
</li>
<li>Create a fake device.map for grub-install to use (yeah, this is a bad use of <code>tee</code>, but I&#8217;m trying to be clear about what I&#8217;m doing):<br />
<blockquote><pre>mathias:~ evan$ echo '(hd0) /dev/mapper/hda' | sudo tee /tmp/tmp.MPUXeJWqpn/boot/grub/device.map
(hd0) /dev/mapper/hda</pre>
</blockquote>
</li>
<li>And now, for the grand finale, actually install GRUB from <em>outside</em> the chroot:<br />
<blockquote><pre>mathias:~ evan$ sudo grub-install --root-directory=/tmp/tmp.MPUXeJWqpn /dev/mapper/hda
grub-probe: error: no mapping exists for `hda1'
[: 494: =: unexpected operator
Installing GRUB to /dev/mapper/hda as (hd0)...
Installation finished. No error reported.
This is the contents of the device map /tmp/tmp.MPUXeJWqpn/boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.

(hd0) /dev/mapper/hda</pre>
</blockquote>
<p>	(You don&#8217;t need to worry about those two errors at the beginning of the output &#8211; it&#8217;s some logic specialized for XFS filesystems)</p>
</li>
<li>Cleanup the mess you made:<br />
<blockquote><pre>mathias:~ evan$ sudo umount /tmp/tmp.MPUXeJWqpn
mathias:~ evan$ sudo rm -rf /tmp/tmp.MPUXeJWqpn
mathias:~ evan$ sudo kpartx -d /dev/mapper/hda
mathias:~ evan$ sudo dmsetup remove hda
mathias:~ evan$ sudo losetup -d /dev/loop0</pre>
</blockquote>
</li>
<li>Finally, examine your disk image, and see that it definitely has GRUB installed:<br />
<blockquote><pre>mathias:~ evan$ file disk.img
disk.img: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, 1st sector stage2 0x884009; partition 1: ID=0x83, active, starthead 0, startsector 1, 18876374 sectors; partition 2: ID=0x82, starthead 254, startsector 18876375, 2088450 sectors</pre>
</blockquote>
</li>
</ol>
<p>And there you have it! You will, of course, still need to write out GRUB&#8217;s menu.lst through some other means (such as Debian/Ubuntu&#8217;s <code>update-grub</code>).</p>
]]></content:encoded>
			<wfw:commentRss>http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

