Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bootloader/lk: add support for UC20 lk bootloader with V2 lkenv structs #9695

Merged
merged 36 commits into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1ad7561
bootloader/lk: add support for UC20 lk bootloader with V2 lkenv structs
anonymouse64 Nov 20, 2020
6c1a52d
bootloader/lk{,env}: use xerrors to make Load() err observable as Err…
anonymouse64 Nov 25, 2020
1c83b92
Merge remote-tracking branch 'upstream/master' into feature/uc20-lk-b…
bboozzoo Nov 27, 2020
a2438c6
Merge branch 'master' into feature/uc20-lk-bootloader-5
anonymouse64 Nov 30, 2020
9531654
many: rename disks.FindMatching... to FindMatching...WithFsLabel and …
anonymouse64 Nov 30, 2020
f36c6d0
osutil/disks: add FindMatchingPartitionUUIDFromPartLabel to Disk iface
anonymouse64 Nov 30, 2020
98e667c
bootloader/lk: search for partition labels on the bootloader disk, no…
anonymouse64 Nov 30, 2020
47c2847
bootloader/lk: rename inRuntimeMode to prepareImageTime
anonymouse64 Nov 30, 2020
74dc349
bootloader/lk.go: rename var
anonymouse64 Nov 30, 2020
ea1879e
bootloader/lk.go: fix handling of os.ErrNotExist everywhere, add comm…
anonymouse64 Nov 30, 2020
9987809
bootloader/lk.go: move prepare-image check earlier in ExtractRecovery…
anonymouse64 Nov 30, 2020
b8f86da
osutil/disks/disks_linux.go: adjust comment about optional partition …
anonymouse64 Dec 1, 2020
4fd0d05
osutil/disks/disks.go: fix typo
anonymouse64 Dec 1, 2020
a304490
osutil/disks/disks_linux.go: add some TODOs about things to cleanup/s…
anonymouse64 Dec 1, 2020
7797633
osutil/disks/disks_linux.go: add comments about the encoding of the u…
anonymouse64 Dec 1, 2020
261a5ab
osutil/disks/mockdisk.go: fix typo
anonymouse64 Dec 1, 2020
26d7069
osutil/disks: add FindMatchingPartitionUUIDFromPartLabel to Disk iface
anonymouse64 Nov 30, 2020
947d834
many: fix rename of disks pkg function name from rebase
anonymouse64 Dec 1, 2020
89fa366
bootloader/lk: don't use l.rootdir for the returned partition file
anonymouse64 Dec 1, 2020
3c42cc0
bootloader/lkenv: add compatibility error impl for Go 1.9
anonymouse64 Dec 2, 2020
80c92bd
Merge branch 'master' into feature/uc20-lk-bootloader-5
anonymouse64 Dec 2, 2020
0b6df85
bootloader/lk: use specific backup file for lkenv
anonymouse64 Dec 3, 2020
7da10c7
bootloader/lk: add test scaffolding and TODO about recovery system ad…
anonymouse64 Dec 3, 2020
23fd1f4
bootloader/lk.go: adjust comments
anonymouse64 Dec 3, 2020
f9daf3a
bootloader/lkenv/lkenv.go: change XXX to TODO
anonymouse64 Dec 3, 2020
a1f8dc9
bootloader/lkenv/lkenv.go: inspect the err in compatErrNotExist for U…
anonymouse64 Dec 3, 2020
598243c
bootloader/lk: refactor helper methods
anonymouse64 Dec 3, 2020
12a43a6
bootloader/lk: move some function definitions around for conventions'…
anonymouse64 Dec 3, 2020
bfafd8a
bootloader/lk: adjust comment to explain we should try to use kernel …
anonymouse64 Dec 3, 2020
18ddfb8
bootloader/lkenv/lkenv.go: fix for gofmt 1.9
anonymouse64 Dec 3, 2020
f38b2f5
bootloader/lk: update handling of os.ErrNotExist for various cases
anonymouse64 Dec 4, 2020
f136f75
bootloader/lk.go: rename variable, simplify return statement
anonymouse64 Dec 4, 2020
b74ceef
bootloader/lk.go: implement TODO about checking the backup file in Pr…
anonymouse64 Dec 4, 2020
d085669
bootloader/lk.go: re-word awkwardly phrased TODO about using kernel c…
anonymouse64 Dec 4, 2020
86a7aeb
Merge branch 'master' into feature/uc20-lk-bootloader-5
anonymouse64 Dec 4, 2020
b609f38
bootloader/lk_test.go: add unit test for Present() RoleSole checking …
anonymouse64 Dec 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion bootloader/bootloader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/snapcore/snapd/bootloader"
"github.com/snapcore/snapd/bootloader/assets"
"github.com/snapcore/snapd/bootloader/bootloadertest"
"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/testutil"
)
Expand All @@ -56,6 +57,8 @@ func (s *baseBootenvTestSuite) SetUpTest(c *C) {
s.BaseTest.SetUpTest(c)
s.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {}))
s.rootdir = c.MkDir()
dirs.SetRootDir(s.rootdir)
s.AddCleanup(func() { dirs.SetRootDir("") })
}

type bootenvTestSuite struct {
Expand Down Expand Up @@ -114,7 +117,7 @@ func (s *bootenvTestSuite) TestInstallBootloaderConfigFromGadget(c *C) {
opts: &bootloader.Options{Role: bootloader.RoleRecovery},
},
{name: "androidboot", gadgetFile: "androidboot.conf", sysFile: "/boot/androidboot/androidboot.env"},
{name: "lk", gadgetFile: "lk.conf", sysFile: "/boot/lk/snapbootsel.bin"},
{name: "lk", gadgetFile: "lk.conf", sysFile: "/boot/lk/snapbootsel.bin", opts: &bootloader.Options{PrepareImageTime: true}},
} {
mockGadgetDir := c.MkDir()
rootDir := c.MkDir()
Expand Down
127 changes: 112 additions & 15 deletions bootloader/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (

"github.com/snapcore/snapd/bootloader/lkenv"
"github.com/snapcore/snapd/bootloader/ubootenv"
"github.com/snapcore/snapd/osutil"
"github.com/snapcore/snapd/osutil/disks"
)

// creates a new Androidboot bootloader object
Expand Down Expand Up @@ -72,45 +74,140 @@ func MockGrubFiles(c *C, rootdir string) {
c.Assert(err, IsNil)
}

func NewLk(rootdir string, opts *Options) Bootloader {
func NewLk(rootdir string, opts *Options) ExtractedRecoveryKernelImageBootloader {
if opts == nil {
opts = &Options{}
opts = &Options{
Role: RoleSole,
}
}
return newLk(rootdir, opts)
return newLk(rootdir, opts).(ExtractedRecoveryKernelImageBootloader)
}

func LkConfigFile(b Bootloader) string {
// LkConfigFile returns the primary lk bootloader environment file.
func LkConfigFile(b Bootloader) (string, error) {
lk := b.(*lk)
return lk.envFile()
return lk.envBackstore(primaryStorage)
}

func UbootConfigFile(b Bootloader) string {
u := b.(*uboot)
return u.envFile()
}

func MockLkFiles(c *C, rootdir string, opts *Options) {
func MockLkFiles(c *C, rootdir string, opts *Options) (restore func()) {
var cleanups []func()
if opts == nil {
opts = &Options{}
// default to v1, uc16/uc18 version for test simplicity
opts = &Options{
Role: RoleSole,
}
}

l := &lk{rootdir: rootdir}
l.processOpts(opts)

var version lkenv.Version
switch opts.Role {
case RoleSole:
version = lkenv.V1
case RoleRunMode:
version = lkenv.V2Run
case RoleRecovery:
version = lkenv.V2Recovery
}
l := &lk{rootdir: rootdir, inRuntimeMode: !opts.PrepareImageTime}
err := os.MkdirAll(l.dir(), 0755)
c.Assert(err, IsNil)

// first create empty env file
// setup some role specific things
if opts.Role == RoleRunMode || opts.Role == RoleRecovery {
// then we need to setup some additional files - namely the kernel
// command line and a mock disk for that
lkBootDisk := &disks.MockDiskMapping{
// mock the partition labels, since these structures won't have
// filesystems, but they will have partition labels
PartitionLabelToPartUUID: map[string]string{
"snapbootsel": "snapbootsel-partuuid",
"snapbootselbak": "snapbootselbak-partuuid",
"snaprecoverysel": "snaprecoverysel-partuuid",
"snaprecoveryselbak": "snaprecoveryselbak-partuuid",
// for run mode kernel snaps
"boot_a": "boot-a-partuuid",
"boot_b": "boot-b-partuuid",
// for recovery system kernel snaps
"boot_ra": "boot-ra-partuuid",
"boot_rb": "boot-rb-partuuid",
},
DiskHasPartitions: true,
DevNum: "lk-boot-disk-dev-num",
}

m := map[string]*disks.MockDiskMapping{
"lk-boot-disk": lkBootDisk,
}

// mock the disk
r := disks.MockDeviceNameDisksToPartitionMapping(m)
cleanups = append(cleanups, r)

// now mock the kernel command line
cmdLine := filepath.Join(c.MkDir(), "cmdline")
ioutil.WriteFile(cmdLine, []byte("snapd_lk_boot_disk=lk-boot-disk"), 0644)
r = osutil.MockProcCmdline(cmdLine)
cleanups = append(cleanups, r)
}

// next create empty env file
buf := make([]byte, 4096)
err = ioutil.WriteFile(l.envFile(), buf, 0660)
f, err := l.envBackstore(primaryStorage)
c.Assert(err, IsNil)

c.Assert(os.MkdirAll(filepath.Dir(f), 0755), IsNil)
err = ioutil.WriteFile(f, buf, 0660)
c.Assert(err, IsNil)

// now write env in it with correct crc
env := lkenv.NewEnv(l.envFile(), "", lkenv.V1)
env.InitializeBootPartitions("boot_a", "boot_b")
env := lkenv.NewEnv(f, "", version)
if version == lkenv.V2Recovery {
env.InitializeBootPartitions("boot_ra", "boot_rb")
} else {
env.InitializeBootPartitions("boot_a", "boot_b")
}

err = env.Save()
c.Assert(err, IsNil)

// also make the empty files for the boot_a and boot_b partitions
if opts.Role == RoleRunMode || opts.Role == RoleRecovery {
// for uc20 roles we need to mock the files in /dev/disk/by-partuuid
// and we also need to mock the snapbootselbak file (the snapbootsel
// was created above when we created envFile())
for _, label := range []string{"boot_a", "boot_b", "boot_ra", "boot_rb", "snapbootselbak"} {
disk, err := disks.DiskFromDeviceName("lk-boot-disk")
c.Assert(err, IsNil)
partUUID, err := disk.FindMatchingPartitionUUIDWithPartLabel(label)
c.Assert(err, IsNil)
bootFile := filepath.Join(rootdir, "/dev/disk/by-partuuid", partUUID)
c.Assert(os.MkdirAll(filepath.Dir(bootFile), 0755), IsNil)
c.Assert(ioutil.WriteFile(bootFile, nil, 0755), IsNil)
}
} else {
// for non-uc20 roles just mock the files in /dev/disk/by-partlabel
for _, partName := range []string{"boot_a", "boot_b"} {
mockPart := filepath.Join(rootdir, "/dev/disk/by-partlabel/", partName)
err := os.MkdirAll(filepath.Dir(mockPart), 0755)
c.Assert(err, IsNil)
err = ioutil.WriteFile(mockPart, nil, 0600)
c.Assert(err, IsNil)
}
}
return func() {
for _, r := range cleanups {
r()
}
}
}

func LkRuntimeMode(b Bootloader) bool {
lk := b.(*lk)
return lk.inRuntimeMode
return !lk.prepareImageTime
}

func MockAddBootloaderToFind(blConstructor func(string, *Options) Bootloader) (restore func()) {
Expand Down