From 4b2f46e510080b6d5df0ee04a3fae8e53df1ea7a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 21 Dec 2017 00:12:01 -0400 Subject: Grub.boots, Grub.bootsMounted: Pass --target to grub-install. This is to support eg, coreboot. The GrubTarget passed to Grub.installed is introspected to determine --target. If multiple grubs are installed, it currently doesn't pass any --target. Might make more sense to run grub-install repeatedly, but I don't know if that case is sane at all. The Xen -> "x86_64-xen" mapping is kind of arbitrarily chosen since there's a i386-xen available too. I don't know when that case would be used in any case though; chainPVGrub uses installed Xen, but it does not run grub-install. If this does become a problem, would probably need to split it into Xen64 and Xen32. Renamed BIOS to GrubTarget in passing to match grub's terminology; BIOS was kind of a joke term for this in propellor. This commit was sponsored by Francois Marier on Patreon. --- debian/changelog | 1 + ...nt_10_4cfd25f81e2ed3a0cc491558038e347b._comment | 7 +++ src/Propellor/Property/DiskImage.hs | 11 ++-- src/Propellor/Property/Grub.hs | 62 +++++++++++++++------- src/Propellor/Types/Bootloader.hs | 7 ++- 5 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment diff --git a/debian/changelog b/debian/changelog index 3da0622f..c1694108 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,6 +13,7 @@ propellor (5.2.0) UNRELEASED; urgency=medium chroot. * Fix bug in unmountBelow that caused unmounting of nested mounts to fail. + * Grub.boots, Grub.bootsMounted: Pass --target to grub-install. -- Joey Hess Wed, 29 Nov 2017 11:45:08 -0400 diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment new file mode 100644 index 00000000..a6eb510a --- /dev/null +++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment @@ -0,0 +1,7 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 10""" + date="2017-12-21T04:05:40Z" + content=""" +Implemented --target passing based on Grub.installed's Info. +"""]] diff --git a/src/Propellor/Property/DiskImage.hs b/src/Propellor/Property/DiskImage.hs index 1f4f8118..24459476 100644 --- a/src/Propellor/Property/DiskImage.hs +++ b/src/Propellor/Property/DiskImage.hs @@ -17,7 +17,7 @@ module Propellor.Property.DiskImage ( imageRebuiltFor, imageBuiltFrom, imageExists, - Grub.BIOS(..), + GrubTarget(..), ) where import Propellor.Base @@ -221,7 +221,7 @@ imageBuilt' rebuild img mkchroot tabletype partspec = -- installed. final = case fromInfo (containerInfo chroot) of [] -> unbootable "no bootloader is installed" - [GrubInstalled] -> grubFinalized + [GrubInstalled grubtarget] -> grubFinalized grubtarget [UbootInstalled p] -> ubootFinalized p [FlashKernelInstalled] -> flashKernelFinalized [UbootInstalled p, FlashKernelInstalled] -> @@ -454,9 +454,10 @@ unbootable msg = \_ _ _ -> property desc $ do where desc = "image is not bootable" -grubFinalized :: Finalization -grubFinalized _img mnt loopdevs = Grub.bootsMounted mnt wholediskloopdev - `describe` "disk image boots using grub" +grubFinalized :: GrubTarget -> Finalization +grubFinalized grubtarget _img mnt loopdevs = + Grub.bootsMounted mnt wholediskloopdev grubtarget + `describe` "disk image boots using grub" where -- It doesn't matter which loopdev we use; all -- come from the same disk image, and it's the loop dev diff --git a/src/Propellor/Property/Grub.hs b/src/Propellor/Property/Grub.hs index d0516dc8..a23f12e4 100644 --- a/src/Propellor/Property/Grub.hs +++ b/src/Propellor/Property/Grub.hs @@ -1,4 +1,15 @@ -module Propellor.Property.Grub where +module Propellor.Property.Grub ( + GrubDevice, + OSDevice, + GrubTarget(..), + installed, + mkConfig, + installed', + boots, + bootsMounted, + TimeoutSecs, + chainPVGrub +) where import Propellor.Base import qualified Propellor.Property.File as File @@ -14,40 +25,36 @@ type GrubDevice = String -- | Eg, \"\/dev/sda\" type OSDevice = String -type TimeoutSecs = Int - --- | Types of machines that grub can boot. -data BIOS = PC | EFI64 | EFI32 | Coreboot | Xen - -- | Installs the grub package. This does not make grub be used as the -- bootloader. -- -- This includes running update-grub, unless it's run in a chroot. -installed :: BIOS -> Property (HasInfo + DebianLike) -installed bios = installed' bios +installed :: GrubTarget -> Property (HasInfo + DebianLike) +installed grubtarget = installed' grubtarget `onChange` (check (not <$> inChroot) mkConfig) --- Run update-grub, to generate the grub boot menu. It will be +-- | Run update-grub, to generate the grub boot menu. It will be -- automatically updated when kernel packages are installed. mkConfig :: Property DebianLike mkConfig = tightenTargets $ cmdProperty "update-grub" [] `assume` MadeChange -- | Installs grub; does not run update-grub. -installed' :: BIOS -> Property (HasInfo + DebianLike) -installed' bios = setInfoProperty aptinstall - (toInfo [GrubInstalled]) +installed' :: GrubTarget -> Property (HasInfo + DebianLike) +installed' grubtarget = setInfoProperty aptinstall + (toInfo [GrubInstalled grubtarget]) `describe` "grub package installed" where aptinstall = Apt.installed [debpkg] - debpkg = case bios of + debpkg = case grubtarget of PC -> "grub-pc" EFI64 -> "grub-efi-amd64" EFI32 -> "grub-efi-ia32" Coreboot -> "grub-coreboot" Xen -> "grub-xen" --- | Installs grub onto a device, so the system can boot from that device. +-- | Installs grub onto a device's boot loader, +-- so the system can boot from that device. -- -- You may want to install grub to multiple devices; eg for a system -- that uses software RAID. @@ -57,9 +64,24 @@ installed' bios = setInfoProperty aptinstall -- to arrange for this property to only run once, by eg making it be run -- onChange after OS.cleanInstallOnce. boots :: OSDevice -> Property Linux -boots dev = tightenTargets $ cmdProperty "grub-install" [dev] - `assume` MadeChange - `describe` ("grub boots " ++ dev) +boots dev = property' ("grub boots " ++ dev) $ \w -> do + grubtarget <- askInfo + let ps = case grubtarget of + [GrubInstalled t] -> [targetParam t] + _ -> [] + ensureProperty w $ + cmdProperty "grub-install" (ps ++ [dev]) + `assume` MadeChange + +targetParam :: GrubTarget -> String +targetParam t = "--target=" ++ case t of + PC -> "i386-pc" + EFI64 -> "i386-efi" + EFI32 -> "x86_64-efi" + Coreboot -> "i386-coreboot" + Xen -> "x86_64-xen" + +type TimeoutSecs = Int -- | Use PV-grub chaining to boot -- @@ -95,8 +117,8 @@ chainPVGrub rootdev bootdev timeout = combineProperties desc $ props -- at a particular directory. The OSDevice should be the underlying disk -- device that grub will be installed to (generally a whole disk, -- not a partition). -bootsMounted :: FilePath -> OSDevice -> Property Linux -bootsMounted mnt wholediskdev = combineProperties desc $ props +bootsMounted :: FilePath -> OSDevice -> GrubTarget -> Property Linux +bootsMounted mnt wholediskdev grubtarget = combineProperties desc $ props -- remove mounts that are done below to make sure the right thing -- gets mounted & cleanupmounts @@ -112,7 +134,7 @@ bootsMounted mnt wholediskdev = combineProperties desc $ props & inchroot "update-grub" [] `assume` MadeChange & check haveosprober (inchroot "chmod" ["+x", osprober]) - & inchroot "grub-install" [wholediskdev] + & inchroot "grub-install" [targetParam grubtarget, wholediskdev] `assume` MadeChange & cleanupmounts -- sync all buffered changes out to the disk in case it's diff --git a/src/Propellor/Types/Bootloader.hs b/src/Propellor/Types/Bootloader.hs index fd929d7e..65117bd2 100644 --- a/src/Propellor/Types/Bootloader.hs +++ b/src/Propellor/Types/Bootloader.hs @@ -7,13 +7,16 @@ import Propellor.Types.Info -- | Boot loader installed on a host. data BootloaderInstalled - = GrubInstalled + = GrubInstalled GrubTarget | FlashKernelInstalled | UbootInstalled (FilePath -> FilePath -> Property Linux) deriving (Typeable) +-- | Platforms that grub can boot. +data GrubTarget = PC | EFI64 | EFI32 | Coreboot | Xen + instance Show BootloaderInstalled where - show GrubInstalled = "GrubInstalled" + show (GrubInstalled _) = "GrubInstalled" show FlashKernelInstalled = "FlashKernelInstalled" show (UbootInstalled _) = "UbootInstalled" -- cgit v1.2.3