Merge lp:~superm1/usb-creator/grub-support into lp:usb-creator

Proposed by Mario Limonciello
Status: Merged
Merged at revision: 323
Proposed branch: lp:~superm1/usb-creator/grub-support
Merge into: lp:usb-creator
Diff against target: 158 lines (+49/-19)
3 files modified
bin/usb-creator-helper (+28/-10)
debian/changelog (+2/-0)
usbcreator/install.py (+19/-9)
To merge this branch: bzr merge lp:~superm1/usb-creator/grub-support
Reviewer Review Type Date Requested Status
Colin Watson Pending
usb-creator hackers Pending
Review via email: mp+34504@code.launchpad.net

Description of the change

This adds early support for installing using grub rather than syslinux (when applicable) to avoid getting into the same situation as had happened with 10.10 changing syntax of the syslinux.cfg.

It makes an assumption that when grub is installed to CDs it will be installed in boot/grub/i386-pc. This assumption was based upon the way that EFI was implemented on AMD64 CDs for 10.10 that modules were in /boot/grub/x86_64-efi. If that's a bad assumption, this can be modified.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) wrote :

On Thu, Sep 02, 2010 at 11:49:55PM -0000, Mario Limonciello wrote:
> It makes an assumption that when grub is installed to CDs it will be
> installed in boot/grub/i386-pc. This assumption was based upon the
> way that EFI was implemented on AMD64 CDs for 10.10 that modules were
> in /boot/grub/x86_64-efi. If that's a bad assumption, this can be
> modified.

I think this assumption is OK.

> - num = deviceobj.Get(device, 'partition-number',
> - dbus_interface=PROPS_IFACE)
> - try:
> - popen(['/sbin/parted', parent, 'set', str(num), 'boot', 'on'])
> - except USBCreatorProcessException:
> - # Don't worry about not being able to re-read the partition table.
> - # TODO: As this will still be a problem for KVM users, this should
> - # be fixed by unmounting all the partitions before we get to this
> - # point, then remounting the target partition after.
> - pass

We need the parted call for both syslinux and GRUB. Some BIOSes refuse
to boot from a device that doesn't have an active partition.

> + if bootloader == 'grub':
> + core = tempfile.mktemp()
> + popen(['grub-mkimage', '-p', '/boot/grub/i386-pc', '-o', core,
> + 'biosdisk', 'part_msdos', 'fat', 'ntfs'])

This creates a GRUB image based on the version of grub-pc that you have
installed, on the assumption that it will continue to work with the old
configuration file on the CD image. This is not necessarily a sound
assumption. It also hardcodes module names; the set chosen isn't likely
to change all that much, but I feel it's worth mentioning.

If you use the installed version of grub-pc, then you must also copy
over modules from the installed system. The ABI between core.img and
modules changes frequently.

> + popen(['/usr/sbin/grub-setup', '-d', '/', '-b', '/usr/lib/grub/i386-pc/boot.img',
> + '-c', core, parent])

Hardcoded path to grub-setup. Also surely this should be '-d
/usr/lib/grub/i386-pc' rather than using both -d and -b? '-d /' makes
no sense.

In general, I have to say that I'm kind of uneasy with this approach; I
think it will break just as much as syslinux has been breaking, if not
more. I have an alternative suggestion. When we switch to GRUB, we
should arrange that the very same core.img on the CD contains the
necessary modules to boot on USB sticks as well. We can then simply dd
the existing core.img into the space after the MBR, and not have to
worry about these interface issues.

lp:~superm1/usb-creator/grub-support updated
319. By Colin Watson

GTK frontend: don't grey out "Make Startup Disk" when the source is a
physical CD.

Revision history for this message
Mario Limonciello (superm1) wrote :

This should hopefully address all of the concerns that Colin raised (but Launchpad decided to eat).

lp:~superm1/usb-creator/grub-support updated
320. By Mario Limonciello

Grow support for installing GRUB to USB sticks if it's detected in the image
rather than isolinux.

Revision history for this message
Mario Limonciello (superm1) wrote :

I did a couple of tests with handcrafted boot.img and core.img files, and this appears to work properly for them using dd now.

Revision history for this message
Mario Limonciello (superm1) wrote :

After more testing i've merged this in today.

The boot.img was used as it existed on the system.
The handcrafted core.img was generated like this:

#grub-mkimage -c grub.cfg -o core.img biosdisk part_msdos fat search_fs_file iso9660

grub.cfg:
     search.file /boot/grub/i386-pc/grub.cfg root
     set prefix=($root)/boot/grub/i386-pc

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/usb-creator-helper'
--- bin/usb-creator-helper 2010-04-01 13:11:48 +0000
+++ bin/usb-creator-helper 2010-09-04 00:08:40 +0000
@@ -18,6 +18,7 @@
18import gobject18import gobject
19import dbus.service19import dbus.service
20import logging20import logging
21import os
21logging.basicConfig(level=logging.DEBUG)22logging.basicConfig(level=logging.DEBUG)
22from dbus.mainloop.glib import DBusGMainLoop23from dbus.mainloop.glib import DBusGMainLoop
23from usbcreator.misc import *24from usbcreator.misc import *
@@ -67,15 +68,23 @@
67 self.polkit = None68 self.polkit = None
6869
69 # TODO return boolean success70 # TODO return boolean success
70 @dbus.service.method(USBCREATOR_IFACE, in_signature='s', out_signature='',71 @dbus.service.method(USBCREATOR_IFACE, in_signature='ss', out_signature='',
71 sender_keyword='sender', connection_keyword='conn')72 sender_keyword='sender', connection_keyword='conn')
72 def InstallBootloader(self, device, sender=None, conn=None):73 def InstallBootloader(self, device, grub_location, sender=None, conn=None):
73 '''Installs syslinux to the partition boot code area and writes the74 '''Install a bootloader to the boot code area, either grub or syslinux.
75
76 The function takes a partition device file of the form /dev/sda1
77 and an option grub_location argument for where grub is located
78
79 For GRUB, it's expected that GRUB already exists, all that is
80 installed is the bootsector code from grub-setup.
81
82 For syslinux:
83 Installs syslinux to the partition boot code area and writes the
74 syslinux boot code to the disk code area. The latter is done to84 syslinux boot code to the disk code area. The latter is done to
75 handle cases where a bootloader is accidentally installed to the85 handle cases where a bootloader is accidentally installed to the
76 MBR, and to handle some buggy BIOSes.86 MBR, and to handle some buggy BIOSes.'''
7787
78 The function takes a partition device file of the form /dev/sda1.'''
7988
80 self.check_polkit(sender, conn, 'com.ubuntu.usbcreator.bootloader')89 self.check_polkit(sender, conn, 'com.ubuntu.usbcreator.bootloader')
81 check_system_internal(device)90 check_system_internal(device)
@@ -87,17 +96,26 @@
87 udisks = dbus.Interface(udisks, DISKS_IFACE)96 udisks = dbus.Interface(udisks, DISKS_IFACE)
88 device = udisks.FindDeviceByDeviceFile(device)97 device = udisks.FindDeviceByDeviceFile(device)
89 deviceobj = bus.get_object(DISKS_IFACE, device)98 deviceobj = bus.get_object(DISKS_IFACE, device)
90 99
91 popen(['syslinux', '-f', device_file])
92 # Find the parent of the partition.100 # Find the parent of the partition.
93 parent = deviceobj.Get(device, 'partition-slave',101 parent = deviceobj.Get(device, 'partition-slave',
94 dbus_interface=PROPS_IFACE)102 dbus_interface=PROPS_IFACE)
95 parentobj = bus.get_object(DISKS_IFACE, parent)103 parentobj = bus.get_object(DISKS_IFACE, parent)
96 parent = parentobj.Get(parent, 'device-file',104 parent = parentobj.Get(parent, 'device-file',
97 dbus_interface=PROPS_IFACE)105 dbus_interface=PROPS_IFACE)
98 # Write the syslinux MBR.106
99 popen(['dd', 'if=/usr/lib/syslinux/mbr.bin', 'of=%s' % parent,107 if grub_location:
100 'bs=446', 'count=1', 'conv=sync'])108 #Expect that boot.img and core.img both pre-built in grub_location
109 popen(['dd', 'if=%s' % os.path.join(grub_location, 'boot.img'), 'of=%s' % parent,
110 'bs=446', 'count=1', 'conv=sync'])
111 popen(['dd', 'if=%s' % os.path.join(grub_location, 'core.img'), 'of=%s' % parent,
112 'bs=512', 'count=62', 'seek=1', 'conv=sync'])
113 else:
114 popen(['syslinux', '-f', device_file])
115 # Write the syslinux MBR.
116 popen(['dd', 'if=/usr/lib/syslinux/mbr.bin', 'of=%s' % parent,
117 'bs=446', 'count=1', 'conv=sync'])
118
101 num = deviceobj.Get(device, 'partition-number',119 num = deviceobj.Get(device, 'partition-number',
102 dbus_interface=PROPS_IFACE)120 dbus_interface=PROPS_IFACE)
103 try:121 try:
104122
=== modified file 'debian/changelog'
--- debian/changelog 2010-09-03 16:10:16 +0000
+++ debian/changelog 2010-09-04 00:08:40 +0000
@@ -3,6 +3,8 @@
3 [ Mario Limonciello ]3 [ Mario Limonciello ]
4 * Mangle whether the 'ui' keyword is in syslinux.cfg based on the OS version.4 * Mangle whether the 'ui' keyword is in syslinux.cfg based on the OS version.
5 (LP: #608382)5 (LP: #608382)
6 * Grow support for installing GRUB to USB sticks if it's detected in the image
7 rather than isolinux.
68
7 [ Colin Watson ]9 [ Colin Watson ]
8 * GTK frontend: don't grey out "Make Startup Disk" when the source is a10 * GTK frontend: don't grey out "Make Startup Disk" when the source is a
911
=== modified file 'usbcreator/install.py'
--- usbcreator/install.py 2010-08-31 18:33:45 +0000
+++ usbcreator/install.py 2010-09-04 00:08:40 +0000
@@ -185,7 +185,7 @@
185 if os.path.exists(ldlinux):185 if os.path.exists(ldlinux):
186 os.remove(ldlinux)186 os.remove(ldlinux)
187187
188 def install_bootloader(self):188 def install_bootloader(self, grub_location=None):
189 logging.debug('install_bootloader')189 logging.debug('install_bootloader')
190 self.progress_pulse()190 self.progress_pulse()
191 self.progress_message(_('Installing the bootloader...'))191 self.progress_message(_('Installing the bootloader...'))
@@ -207,7 +207,7 @@
207 bus = dbus.SystemBus()207 bus = dbus.SystemBus()
208 obj = bus.get_object('com.ubuntu.USBCreator',208 obj = bus.get_object('com.ubuntu.USBCreator',
209 '/com/ubuntu/USBCreator')209 '/com/ubuntu/USBCreator')
210 obj.InstallBootloader(self.device,210 obj.InstallBootloader(self.device, grub_location,
211 dbus_interface='com.ubuntu.USBCreator',211 dbus_interface='com.ubuntu.USBCreator',
212 timeout=MAX_DBUS_TIMEOUT)212 timeout=MAX_DBUS_TIMEOUT)
213 except dbus.DBusException:213 except dbus.DBusException:
@@ -419,7 +419,6 @@
419 self.remove_extras()419 self.remove_extras()
420 420
421 self.initialize_progress_thread()421 self.initialize_progress_thread()
422 self.install_bootloader()
423422
424 # Copy.423 # Copy.
425 424
@@ -476,8 +475,14 @@
476 # and line[1] (HH:MM:SS).475 # and line[1] (HH:MM:SS).
477 logging.debug('mkdir %s' % os.path.join(self.target, line[2]))476 logging.debug('mkdir %s' % os.path.join(self.target, line[2]))
478 os.mkdir(os.path.join(self.target, line[2]))477 os.mkdir(os.path.join(self.target, line[2]))
479 478
480 self.mangle_syslinux()479 grub = os.path.join(self.target, 'boot', 'grub', 'i386-pc')
480 if os.path.isdir(grub):
481 self.install_bootloader(grub)
482 else:
483 self.install_bootloader()
484 self.mangle_syslinux()
485
481 self.create_persistence()486 self.create_persistence()
482 self.sync()487 self.sync()
483488
@@ -507,8 +512,7 @@
507 self.check()512 self.check()
508 513
509 self.initialize_progress_thread()514 self.initialize_progress_thread()
510 self.install_bootloader()515
511
512 self.progress_message(_('Copying files...'))516 self.progress_message(_('Copying files...'))
513 for dirpath, dirnames, filenames in os.walk(self.source):517 for dirpath, dirnames, filenames in os.walk(self.source):
514 sp = dirpath[len(self.source.rstrip(os.path.sep))+1:]518 sp = dirpath[len(self.source.rstrip(os.path.sep))+1:]
@@ -542,8 +546,14 @@
542 if os.path.exists(targetpath):546 if os.path.exists(targetpath):
543 os.unlink(targetpath)547 os.unlink(targetpath)
544 self.copy_file(sourcepath, targetpath)548 self.copy_file(sourcepath, targetpath)
545 549
546 self.mangle_syslinux()550 grub = os.path.join(self.target, 'boot', 'grub', 'i386-pc')
551 if os.path.isdir(grub):
552 self.install_bootloader(grub)
553 else:
554 self.install_bootloader()
555 self.mangle_syslinux()
556
547 self.create_persistence()557 self.create_persistence()
548 self.sync()558 self.sync()
549 559

Subscribers

People subscribed via source and target branches