Skip to content

Commit 56b2723

Browse files
authored
Install grub.cfg into EFI System Partition (#1904)
* Install grub.cfg into EFI System Partition Change the bootloader install logic to install the grub.cfg into the EFI System Partition (ESP). This needs some changes to how root is set in the grub.cfg as well as moving grub_oem_env file to ESP when created in install/reset/upgrade command. Install grub-modules to both EFI/BOOT and EFI/ELEMENTAL. Signed-off-by: Fredrik Lönnegren <[email protected]>
1 parent 2e18efa commit 56b2723

File tree

24 files changed

+192
-131
lines changed

24 files changed

+192
-131
lines changed

.github/workflows/build_and_test_x86.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ jobs:
9595
sudo rm -rf /usr/local/lib/android # will release about 10 GB if you don't need Android
9696
sudo rm -rf /usr/share/dotnet # will release about 20GB if you don't need .NET
9797
sudo df -h
98+
- if: ${{ steps.cache-check.outputs.cache-hit != 'true' }}
99+
name: Build toolkit
100+
run: |
101+
make build
98102
- if: ${{ steps.cache-check.outputs.cache-hit != 'true' }}
99103
name: Install to disk
100104
run: |

pkg/action/build-disk.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (b *BuildDiskAction) BuildDiskRun() (err error) { //nolint:gocyclo
178178
}
179179

180180
// Install grub
181-
err = b.bootloader.InstallConfig(activeRoot, b.roots[constants.StatePartName])
181+
err = b.bootloader.InstallConfig(activeRoot, b.roots[constants.EfiPartName])
182182
if err != nil {
183183
b.cfg.Logger.Errorf("failed installing grub configuration: %s", err.Error())
184184
return err
@@ -199,7 +199,7 @@ func (b *BuildDiskAction) BuildDiskRun() (err error) { //nolint:gocyclo
199199

200200
grubVars := b.spec.GetGrubLabels()
201201
err = b.bootloader.SetPersistentVariables(
202-
filepath.Join(b.roots[constants.StatePartName], constants.GrubOEMEnv),
202+
filepath.Join(b.roots[constants.EfiPartName], constants.GrubOEMEnv),
203203
grubVars,
204204
)
205205
if err != nil {
@@ -208,7 +208,7 @@ func (b *BuildDiskAction) BuildDiskRun() (err error) { //nolint:gocyclo
208208
}
209209

210210
err = b.bootloader.InstallEFI(
211-
activeRoot, b.roots[constants.StatePartName],
211+
activeRoot, b.roots[constants.EfiPartName],
212212
b.roots[constants.EfiPartName], b.spec.Partitions.State.FilesystemLabel,
213213
)
214214
if err != nil {
@@ -217,7 +217,7 @@ func (b *BuildDiskAction) BuildDiskRun() (err error) { //nolint:gocyclo
217217
}
218218

219219
// Rebrand
220-
err = b.bootloader.SetDefaultEntry(b.roots[constants.StatePartName], activeRoot, b.spec.GrubDefEntry)
220+
err = b.bootloader.SetDefaultEntry(b.roots[constants.EfiPartName], activeRoot, b.spec.GrubDefEntry)
221221
if err != nil {
222222
return elementalError.NewFromError(err, elementalError.SetDefaultGrubEntry)
223223
}

pkg/action/build-iso.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030
)
3131

3232
const (
33-
grubPrefixDir = "/boot/grub2"
33+
grubPrefixDir = "/EFI/BOOT"
3434
isoBootCatalog = "/boot/boot.catalog"
3535
)
3636

@@ -73,7 +73,7 @@ func NewBuildISOAction(cfg *v1.BuildConfig, spec *v1.LiveISO, opts ...BuildISOAc
7373
}
7474

7575
if b.bootloader == nil {
76-
b.bootloader = bootloader.NewGrub(&cfg.Config, bootloader.WithGrubPrefix(grubPrefixDir))
76+
b.bootloader = bootloader.NewGrub(&cfg.Config)
7777
}
7878

7979
return b

pkg/action/install.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ func (i InstallAction) Run() (err error) {
197197
// Install grub
198198
err = i.bootloader.Install(
199199
cnst.WorkingImgDir,
200-
i.spec.Partitions.State.MountPoint,
201-
i.spec.Partitions.State.FilesystemLabel,
200+
i.spec.Partitions.EFI.MountPoint,
201+
i.spec.Partitions.EFI.FilesystemLabel,
202202
)
203203
if err != nil {
204204
return elementalError.NewFromError(err, elementalError.InstallGrub)
@@ -221,7 +221,7 @@ func (i InstallAction) Run() (err error) {
221221

222222
grubVars := i.spec.GetGrubLabels()
223223
err = i.bootloader.SetPersistentVariables(
224-
filepath.Join(i.spec.Partitions.State.MountPoint, cnst.GrubOEMEnv),
224+
filepath.Join(i.spec.Partitions.EFI.MountPoint, cnst.GrubOEMEnv),
225225
grubVars,
226226
)
227227
if err != nil {
@@ -231,7 +231,7 @@ func (i InstallAction) Run() (err error) {
231231

232232
// Installation rebrand (only grub for now)
233233
err = i.bootloader.SetDefaultEntry(
234-
i.spec.Partitions.State.MountPoint,
234+
i.spec.Partitions.EFI.MountPoint,
235235
cnst.WorkingImgDir,
236236
i.spec.GrubDefEntry,
237237
)

pkg/action/install_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ var _ = Describe("Install action tests", func() {
169169
{
170170
Name: "device1",
171171
FilesystemLabel: "COS_GRUB",
172-
Type: "ext4",
172+
Type: "vfat",
173173
},
174174
{
175175
Name: "device2",
@@ -388,7 +388,7 @@ var _ = Describe("Install action tests", func() {
388388
spec.GrubDefEntry = "cOS"
389389
bootloader.ErrorSetDefaultEntry = true
390390
Expect(installer.Run()).NotTo(BeNil())
391-
Expect(runner.MatchMilestones([][]string{{"grub2-editenv", filepath.Join(constants.StateDir, constants.GrubOEMEnv)}}))
391+
Expect(runner.MatchMilestones([][]string{{"grub2-editenv", filepath.Join(constants.EfiDir, constants.GrubOEMEnv)}}))
392392
})
393393
})
394394
})

pkg/action/reset.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ func (r ResetAction) Run() (err error) {
205205
// install grub
206206
err = r.bootloader.Install(
207207
cnst.WorkingImgDir,
208-
r.spec.Partitions.State.MountPoint,
209-
r.spec.Partitions.State.FilesystemLabel,
208+
r.spec.Partitions.EFI.MountPoint,
209+
r.spec.Partitions.EFI.FilesystemLabel,
210210
)
211211

212212
if err != nil {
@@ -242,7 +242,7 @@ func (r ResetAction) Run() (err error) {
242242

243243
grubVars := r.spec.GetGrubLabels()
244244
err = r.bootloader.SetPersistentVariables(
245-
filepath.Join(r.spec.Partitions.State.MountPoint, cnst.GrubOEMEnv),
245+
filepath.Join(r.spec.Partitions.EFI.MountPoint, cnst.GrubOEMEnv),
246246
grubVars,
247247
)
248248
if err != nil {
@@ -252,7 +252,7 @@ func (r ResetAction) Run() (err error) {
252252

253253
// installation rebrand (only grub for now)
254254
err = r.bootloader.SetDefaultEntry(
255-
r.spec.Partitions.State.MountPoint,
255+
r.spec.Partitions.EFI.MountPoint,
256256
cnst.WorkingImgDir,
257257
r.spec.GrubDefEntry,
258258
)

pkg/action/upgrade.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ func (u *UpgradeAction) Run() (err error) {
182182
return elementalError.NewFromError(err, elementalError.MountRecoveryPartition)
183183
}
184184
cleanup.Push(umount)
185+
umount, err = elemental.MountRWPartition(u.config.Config, u.spec.Partitions.EFI)
186+
if err != nil {
187+
return elementalError.NewFromError(err, elementalError.MountPartitions)
188+
}
189+
cleanup.Push(umount)
185190

186191
// Cleanup transition image file before leaving
187192
cleanup.Push(func() error { return u.remove(upgradeImg.File) })
@@ -253,7 +258,7 @@ func (u *UpgradeAction) Run() (err error) {
253258

254259
grubVars := u.spec.GetGrubLabels()
255260
err = u.bootloader.SetPersistentVariables(
256-
filepath.Join(u.spec.Partitions.State.MountPoint, constants.GrubOEMEnv),
261+
filepath.Join(u.spec.Partitions.EFI.MountPoint, constants.GrubOEMEnv),
257262
grubVars,
258263
)
259264
if err != nil {
@@ -265,7 +270,7 @@ func (u *UpgradeAction) Run() (err error) {
265270
if !u.spec.RecoveryUpgrade {
266271
u.Info("rebranding")
267272

268-
err = u.bootloader.SetDefaultEntry(u.spec.Partitions.State.MountPoint, constants.WorkingImgDir, u.spec.GrubDefEntry)
273+
err = u.bootloader.SetDefaultEntry(u.spec.Partitions.EFI.MountPoint, constants.WorkingImgDir, u.spec.GrubDefEntry)
269274
if err != nil {
270275
u.Error("failed setting default entry")
271276
return elementalError.NewFromError(err, elementalError.SetDefaultGrubEntry)

pkg/action/upgrade_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ var _ = Describe("Runtime Actions", func() {
9898
logger.SetLevel(logrus.DebugLevel)
9999

100100
// Create paths used by tests
101+
utils.MkdirAll(fs, constants.EfiDir, constants.DirPerm)
101102
utils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.RunningStateDir), constants.DirPerm)
102103
utils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.LiveDir), constants.DirPerm)
103104

@@ -107,7 +108,8 @@ var _ = Describe("Runtime Actions", func() {
107108
{
108109
Name: "device1",
109110
FilesystemLabel: "COS_GRUB",
110-
Type: "ext4",
111+
Type: "vfat",
112+
MountPoint: constants.EfiDir,
111113
},
112114
{
113115
Name: "device2",
@@ -337,7 +339,7 @@ var _ = Describe("Runtime Actions", func() {
337339
err := upgrade.Run()
338340
Expect(err).ToNot(HaveOccurred())
339341

340-
actualBytes, err := fs.ReadFile(filepath.Join(constants.RunningStateDir, "grub_oem_env"))
342+
actualBytes, err := fs.ReadFile(filepath.Join(constants.EfiDir, "grub_oem_env"))
341343
Expect(err).To(BeNil())
342344

343345
expected := map[string]string{

pkg/bootloader/bootloader_suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ import (
2525

2626
func TestTypes(t *testing.T) {
2727
RegisterFailHandler(Fail)
28-
RunSpecs(t, "booloader type test suite")
28+
RunSpecs(t, "bootloader type test suite")
2929
}

pkg/bootloader/grub.go

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ import (
2727
"github.com/rancher/elemental-toolkit/pkg/utils"
2828

2929
efilib "github.com/canonical/go-efilib"
30+
3031
eleefi "github.com/rancher/elemental-toolkit/pkg/efi"
3132
)
3233

3334
const (
34-
grubPrefix = "/grub2"
3535
grubCfgFile = "grub.cfg"
36+
)
3637

37-
grubEFICfgTmpl = "search --no-floppy --label --set=root %s" +
38-
"\nset prefix=($root)%s" +
39-
"\nconfigfile $prefix/" + grubCfgFile
38+
var (
39+
defaultGrubPrefixes = []string{"/EFI/ELEMENTAL", "/EFI/BOOT"}
4040
)
4141

4242
func getGModulePatterns(module string) []string {
@@ -57,7 +57,7 @@ type Grub struct {
5757
grubEfiImg string
5858
mokMngr string
5959

60-
grubPrefix string
60+
grubPrefixes []string
6161
configFile string
6262
elementalCfg string
6363
disableBootEntry bool
@@ -80,8 +80,8 @@ func NewGrub(cfg *v1.Config, opts ...GrubOptions) *Grub {
8080
logger: cfg.Logger,
8181
runner: cfg.Runner,
8282
platform: cfg.Platform,
83-
grubPrefix: grubPrefix,
8483
configFile: grubCfgFile,
84+
grubPrefixes: defaultGrubPrefixes,
8585
elementalCfg: filepath.Join(constants.GrubCfgPath, constants.GrubCfg),
8686
clearBootEntry: true,
8787
secureBoot: secureBoot,
@@ -107,7 +107,7 @@ func WithSecureBoot(secureboot bool) func(g *Grub) error {
107107

108108
func WithGrubPrefix(prefix string) func(g *Grub) error {
109109
return func(g *Grub) error {
110-
g.grubPrefix = prefix
110+
g.grubPrefixes = append(g.grubPrefixes, prefix)
111111
return nil
112112
}
113113
}
@@ -174,16 +174,18 @@ func (g *Grub) installModules(rootDir, bootDir string, modules ...string) error
174174
if err != nil {
175175
return err
176176
}
177-
for _, module := range modules {
178-
fileWriteName := filepath.Join(bootDir, g.grubPrefix, fmt.Sprintf("%s-efi", g.platform.Arch), filepath.Base(module))
179-
g.logger.Debugf("Copying %s to %s", module, fileWriteName)
180-
err = utils.MkdirAll(g.fs, filepath.Dir(fileWriteName), constants.DirPerm)
181-
if err != nil {
182-
return fmt.Errorf("error creating destination folder: %v", err)
183-
}
184-
err = utils.CopyFile(g.fs, module, fileWriteName)
185-
if err != nil {
186-
return fmt.Errorf("error copying %s to %s: %s", module, fileWriteName, err.Error())
177+
for _, grubPrefix := range g.grubPrefixes {
178+
for _, module := range modules {
179+
fileWriteName := filepath.Join(bootDir, grubPrefix, fmt.Sprintf("%s-efi", g.platform.Arch), filepath.Base(module))
180+
g.logger.Debugf("Copying %s to %s", module, fileWriteName)
181+
err = utils.MkdirAll(g.fs, filepath.Dir(fileWriteName), constants.DirPerm)
182+
if err != nil {
183+
return fmt.Errorf("error creating destination folder: %v", err)
184+
}
185+
err = utils.CopyFile(g.fs, module, fileWriteName)
186+
if err != nil {
187+
return fmt.Errorf("error copying %s to %s: %s", module, fileWriteName, err.Error())
188+
}
187189
}
188190
}
189191
return nil
@@ -208,15 +210,15 @@ func (g *Grub) InstallEFI(rootDir, bootDir, efiDir, deviceLabel string) error {
208210
return nil
209211
}
210212

211-
func (g *Grub) InstallEFIFallbackBinaries(rootDir, efiDir, deviceLabel string) error {
212-
return g.installEFIPartitionBinaries(rootDir, efiDir, constants.FallbackEFIPath, deviceLabel)
213+
func (g *Grub) InstallEFIFallbackBinaries(rootDir, efiDir, _ string) error {
214+
return g.installEFIPartitionBinaries(rootDir, efiDir, constants.FallbackEFIPath)
213215
}
214216

215-
func (g *Grub) InstallEFIElementalBinaries(rootDir, efiDir, deviceLabel string) error {
216-
return g.installEFIPartitionBinaries(rootDir, efiDir, constants.EntryEFIPath, deviceLabel)
217+
func (g *Grub) InstallEFIElementalBinaries(rootDir, efiDir, _ string) error {
218+
return g.installEFIPartitionBinaries(rootDir, efiDir, constants.EntryEFIPath)
217219
}
218220

219-
func (g *Grub) installEFIPartitionBinaries(rootDir, efiDir, efiPath, deviceLabel string) error {
221+
func (g *Grub) installEFIPartitionBinaries(rootDir, efiDir, efiPath string) error {
220222
err := g.findEFIImages(rootDir)
221223
if err != nil {
222224
return err
@@ -274,12 +276,6 @@ func (g *Grub) installEFIPartitionBinaries(rootDir, efiDir, efiPath, deviceLabel
274276
return fmt.Errorf("failed copying %s to %s: %s", g.grubEfiImg, installPath, err.Error())
275277
}
276278

277-
grubCfgContent := []byte(fmt.Sprintf(grubEFICfgTmpl, deviceLabel, g.grubPrefix))
278-
err = g.fs.WriteFile(filepath.Join(efiDir, efiPath, grubCfgFile), grubCfgContent, constants.FilePerm)
279-
if err != nil {
280-
return fmt.Errorf("error writing %s: %s", filepath.Join(efiDir, efiPath, grubCfgFile), err)
281-
}
282-
283279
return nil
284280
}
285281

@@ -402,8 +398,8 @@ func (g *Grub) SetDefaultEntry(partMountPoint, imgMountPoint, defaultEntry strin
402398
}
403399

404400
// Install installs grub into the device, copy the config file and add any extra TTY to grub
405-
func (g *Grub) Install(rootDir, bootDir, stateLabel string) (err error) {
406-
err = g.InstallEFI(rootDir, bootDir, constants.EfiDir, stateLabel)
401+
func (g *Grub) Install(rootDir, bootDir, deviceLabel string) (err error) {
402+
err = g.InstallEFI(rootDir, bootDir, constants.EfiDir, deviceLabel)
407403
if err != nil {
408404
return err
409405
}
@@ -422,24 +418,29 @@ func (g *Grub) Install(rootDir, bootDir, stateLabel string) (err error) {
422418
return g.InstallConfig(rootDir, bootDir)
423419
}
424420

425-
// InstallConfig installs grub configuraton files to the expected location. rootDir is the root
426-
// of the OS image, bootDir is the folder grub read the configuration from, usually state partition mountpoint
421+
// InstallConfig installs grub configuraton files to the expected location.
422+
// rootDir is the root of the OS image, bootDir is the folder grub read the
423+
// configuration from, usually EFI partition mountpoint
427424
func (g Grub) InstallConfig(rootDir, bootDir string) error {
428-
grubFile := filepath.Join(rootDir, g.elementalCfg)
429-
dstGrubFile := filepath.Join(bootDir, g.grubPrefix, g.configFile)
425+
for _, path := range []string{constants.FallbackEFIPath, constants.EntryEFIPath} {
426+
grubFile := filepath.Join(rootDir, g.elementalCfg)
427+
dstGrubFile := filepath.Join(bootDir, path, g.configFile)
430428

431-
g.logger.Infof("Using grub config file %s", grubFile)
429+
g.logger.Infof("Using grub config file %s", grubFile)
432430

433-
// Create Needed dir under state partition to store the grub.cfg and any needed modules
434-
err := utils.MkdirAll(g.fs, filepath.Join(bootDir, g.grubPrefix), constants.DirPerm)
435-
if err != nil {
436-
return fmt.Errorf("error creating grub dir: %s", err)
437-
}
431+
// Create Needed dir under state partition to store the grub.cfg and any needed modules
432+
err := utils.MkdirAll(g.fs, filepath.Join(bootDir, path), constants.DirPerm)
433+
if err != nil {
434+
return fmt.Errorf("error creating grub dir: %s", err)
435+
}
438436

439-
g.logger.Infof("Copying grub config file from %s to %s", grubFile, dstGrubFile)
440-
err = utils.CopyFile(g.fs, grubFile, dstGrubFile)
441-
if err != nil {
442-
g.logger.Errorf("Failed copying grub config file: %s", err)
437+
g.logger.Infof("Copying grub config file from %s to %s", grubFile, dstGrubFile)
438+
err = utils.CopyFile(g.fs, grubFile, dstGrubFile)
439+
if err != nil {
440+
g.logger.Errorf("Failed copying grub config file: %s", err)
441+
return err
442+
}
443443
}
444-
return err
444+
445+
return nil
445446
}

0 commit comments

Comments
 (0)