github.com/rigado/snapd@v2.42.5-go-mod+incompatible/bootloader/lk_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package bootloader_test 21 22 import ( 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "sort" 27 28 . "gopkg.in/check.v1" 29 30 "github.com/snapcore/snapd/bootloader" 31 "github.com/snapcore/snapd/bootloader/lkenv" 32 "github.com/snapcore/snapd/osutil" 33 "github.com/snapcore/snapd/snap" 34 "github.com/snapcore/snapd/snap/snaptest" 35 ) 36 37 type lkTestSuite struct { 38 baseBootenvTestSuite 39 } 40 41 var _ = Suite(&lkTestSuite{}) 42 43 func (s *lkTestSuite) TestNewLkNolkReturnsNil(c *C) { 44 l := bootloader.NewLk("/does/not/exist", nil) 45 c.Assert(l, IsNil) 46 } 47 48 func (s *lkTestSuite) TestNewLk(c *C) { 49 bootloader.MockLkFiles(c, s.rootdir, nil) 50 l := bootloader.NewLk(s.rootdir, nil) 51 c.Assert(l, NotNil) 52 c.Check(bootloader.LkRuntimeMode(l), Equals, true) 53 c.Check(l.ConfigFile(), Equals, filepath.Join(s.rootdir, "/dev/disk/by-partlabel", "snapbootsel")) 54 } 55 56 func (s *lkTestSuite) TestNewLkImageBuildingTime(c *C) { 57 opts := &bootloader.Options{ 58 PrepareImageTime: true, 59 } 60 bootloader.MockLkFiles(c, s.rootdir, opts) 61 l := bootloader.NewLk(s.rootdir, opts) 62 c.Assert(l, NotNil) 63 c.Check(bootloader.LkRuntimeMode(l), Equals, false) 64 c.Check(l.ConfigFile(), Equals, filepath.Join(s.rootdir, "/boot/lk", "snapbootsel.bin")) 65 } 66 67 func (s *lkTestSuite) TestSetGetBootVar(c *C) { 68 bootloader.MockLkFiles(c, s.rootdir, nil) 69 l := bootloader.NewLk(s.rootdir, nil) 70 bootVars := map[string]string{"snap_mode": "try"} 71 l.SetBootVars(bootVars) 72 73 v, err := l.GetBootVars("snap_mode") 74 c.Assert(err, IsNil) 75 c.Check(v, HasLen, 1) 76 c.Check(v["snap_mode"], Equals, "try") 77 } 78 79 func (s *lkTestSuite) TestExtractKernelAssetsUnpacksBootimgImageBuilding(c *C) { 80 opts := &bootloader.Options{ 81 PrepareImageTime: true, 82 } 83 bootloader.MockLkFiles(c, s.rootdir, opts) 84 l := bootloader.NewLk(s.rootdir, opts) 85 86 c.Assert(l, NotNil) 87 88 files := [][]string{ 89 {"kernel.img", "I'm a kernel"}, 90 {"initrd.img", "...and I'm an initrd"}, 91 {"boot.img", "...and I'm an boot image"}, 92 {"dtbs/foo.dtb", "g'day, I'm foo.dtb"}, 93 {"dtbs/bar.dtb", "hello, I'm bar.dtb"}, 94 // must be last 95 {"meta/kernel.yaml", "version: 4.2"}, 96 } 97 si := &snap.SideInfo{ 98 RealName: "ubuntu-kernel", 99 Revision: snap.R(42), 100 } 101 fn := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) 102 snapf, err := snap.Open(fn) 103 c.Assert(err, IsNil) 104 105 info, err := snap.ReadInfoFromSnapFile(snapf, si) 106 c.Assert(err, IsNil) 107 108 err = l.ExtractKernelAssets(info, snapf) 109 c.Assert(err, IsNil) 110 111 // just boot.img and snapbootsel.bin are there, no kernel.img 112 infos, err := ioutil.ReadDir(filepath.Join(s.rootdir, "boot", "lk", "")) 113 c.Assert(err, IsNil) 114 var fnames []string 115 for _, info := range infos { 116 fnames = append(fnames, info.Name()) 117 } 118 sort.Strings(fnames) 119 c.Assert(fnames, HasLen, 2) 120 c.Assert(fnames, DeepEquals, []string{"boot.img", "snapbootsel.bin"}) 121 } 122 123 func (s *lkTestSuite) TestExtractKernelAssetsUnpacksCustomBootimgImageBuilding(c *C) { 124 opts := &bootloader.Options{ 125 PrepareImageTime: true, 126 } 127 bootloader.MockLkFiles(c, s.rootdir, opts) 128 l := bootloader.NewLk(s.rootdir, opts) 129 130 c.Assert(l, NotNil) 131 132 // first configure custom boot image file name 133 env := lkenv.NewEnv(l.ConfigFile()) 134 env.Load() 135 env.ConfigureBootimgName("boot-2.img") 136 err := env.Save() 137 c.Assert(err, IsNil) 138 139 files := [][]string{ 140 {"kernel.img", "I'm a kernel"}, 141 {"initrd.img", "...and I'm an initrd"}, 142 {"boot-2.img", "...and I'm an boot image"}, 143 {"dtbs/foo.dtb", "g'day, I'm foo.dtb"}, 144 {"dtbs/bar.dtb", "hello, I'm bar.dtb"}, 145 // must be last 146 {"meta/kernel.yaml", "version: 4.2"}, 147 } 148 si := &snap.SideInfo{ 149 RealName: "ubuntu-kernel", 150 Revision: snap.R(42), 151 } 152 fn := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) 153 snapf, err := snap.Open(fn) 154 c.Assert(err, IsNil) 155 156 info, err := snap.ReadInfoFromSnapFile(snapf, si) 157 c.Assert(err, IsNil) 158 159 err = l.ExtractKernelAssets(info, snapf) 160 c.Assert(err, IsNil) 161 162 // boot-2.img is there 163 bootimg := filepath.Join(s.rootdir, "boot", "lk", "boot-2.img") 164 c.Assert(osutil.FileExists(bootimg), Equals, true) 165 } 166 167 func (s *lkTestSuite) TestExtractKernelAssetsUnpacksAndRemoveInRuntimeMode(c *C) { 168 bootloader.MockLkFiles(c, s.rootdir, nil) 169 lk := bootloader.NewLk(s.rootdir, nil) 170 c.Assert(lk, NotNil) 171 172 // create mock bootsel, boot_a, boot_b partitions 173 for _, partName := range []string{"snapbootsel", "boot_a", "boot_b"} { 174 mockPart := filepath.Join(s.rootdir, "/dev/disk/by-partlabel/", partName) 175 err := os.MkdirAll(filepath.Dir(mockPart), 0755) 176 c.Assert(err, IsNil) 177 err = ioutil.WriteFile(mockPart, nil, 0600) 178 c.Assert(err, IsNil) 179 } 180 // ensure we have a valid boot env 181 bootselPartition := filepath.Join(s.rootdir, "/dev/disk/by-partlabel/snapbootsel") 182 lkenv := lkenv.NewEnv(bootselPartition) 183 lkenv.ConfigureBootPartitions("boot_a", "boot_b") 184 err := lkenv.Save() 185 c.Assert(err, IsNil) 186 187 // mock a kernel snap that has a boot.img 188 files := [][]string{ 189 {"boot.img", "I'm the default boot image name"}, 190 } 191 si := &snap.SideInfo{ 192 RealName: "ubuntu-kernel", 193 Revision: snap.R(42), 194 } 195 fn := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) 196 snapf, err := snap.Open(fn) 197 c.Assert(err, IsNil) 198 199 info, err := snap.ReadInfoFromSnapFile(snapf, si) 200 c.Assert(err, IsNil) 201 202 // now extract 203 err = lk.ExtractKernelAssets(info, snapf) 204 c.Assert(err, IsNil) 205 206 // and validate it went to the "boot_a" partition 207 bootA := filepath.Join(s.rootdir, "/dev/disk/by-partlabel/boot_a") 208 content, err := ioutil.ReadFile(bootA) 209 c.Assert(err, IsNil) 210 c.Assert(string(content), Equals, "I'm the default boot image name") 211 212 // also validate that bootB is empty 213 bootB := filepath.Join(s.rootdir, "/dev/disk/by-partlabel/boot_b") 214 content, err = ioutil.ReadFile(bootB) 215 c.Assert(err, IsNil) 216 c.Assert(content, HasLen, 0) 217 218 // test that boot partition got set 219 err = lkenv.Load() 220 c.Assert(err, IsNil) 221 bootPart, err := lkenv.GetBootPartition("ubuntu-kernel_42.snap") 222 c.Assert(err, IsNil) 223 c.Assert(bootPart, Equals, "boot_a") 224 225 // now remove the kernel 226 err = lk.RemoveKernelAssets(info) 227 c.Assert(err, IsNil) 228 // and ensure its no longer available in the boot partions 229 err = lkenv.Load() 230 c.Assert(err, IsNil) 231 bootPart, err = lkenv.GetBootPartition("ubuntu-kernel_42.snap") 232 c.Assert(err, ErrorMatches, "cannot find kernel .* in boot image partitions") 233 c.Assert(bootPart, Equals, "") 234 }