github.com/stolowski/snapd@v0.0.0-20210407085831-115137ce5a22/boot/debug.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 boot 21 22 import ( 23 "fmt" 24 "io" 25 "strings" 26 27 "github.com/snapcore/snapd/bootloader" 28 "github.com/snapcore/snapd/dirs" 29 "github.com/snapcore/snapd/osutil" 30 ) 31 32 // DebugDumpBootVars writes a dump of the snapd bootvars to the given writer 33 func DebugDumpBootVars(w io.Writer, dir string, uc20 bool) error { 34 opts := &bootloader.Options{ 35 NoSlashBoot: dir != "" && dir != "/", 36 } 37 switch dir { 38 // is it any of the well-known UC20 boot partition mount locations? 39 case InitramfsUbuntuBootDir: 40 opts.Role = bootloader.RoleRunMode 41 uc20 = true 42 case InitramfsUbuntuSeedDir: 43 opts.Role = bootloader.RoleRecovery 44 uc20 = true 45 } 46 if !opts.NoSlashBoot && !uc20 { 47 // this may still be a UC20 system 48 if osutil.FileExists(dirs.SnapModeenvFile) { 49 uc20 = true 50 } 51 } 52 allKeys := []string{ 53 "snap_mode", 54 "snap_core", 55 "snap_try_core", 56 "snap_kernel", 57 "snap_try_kernel", 58 } 59 if uc20 { 60 if !opts.NoSlashBoot { 61 // no root directory set, default to run mode 62 opts.Role = bootloader.RoleRunMode 63 } 64 // keys relevant to all uc20 bootloader implementations 65 allKeys = []string{ 66 "snapd_recovery_mode", 67 "snapd_recovery_system", 68 "snapd_recovery_kernel", 69 "snap_kernel", 70 "snap_try_kernel", 71 "kernel_status", 72 "recovery_system_status", 73 "try_recovery_system", 74 } 75 } 76 bloader, err := bootloader.Find(dir, opts) 77 if err != nil { 78 return err 79 } 80 81 bootVars, err := bloader.GetBootVars(allKeys...) 82 if err != nil { 83 return err 84 } 85 for _, k := range allKeys { 86 fmt.Fprintf(w, "%s=%s\n", k, bootVars[k]) 87 } 88 return nil 89 } 90 91 // DebugSetBootVars is a debug helper that takes a list of <var>=<value> entries 92 // and sets them for the configured bootloader. 93 func DebugSetBootVars(dir string, recoveryBootloader bool, varEqVal []string) error { 94 opts := &bootloader.Options{ 95 NoSlashBoot: dir != "" && dir != "/", 96 } 97 if opts.NoSlashBoot || osutil.FileExists(dirs.SnapModeenvFile) { 98 // implied UC20 bootloader 99 opts.Role = bootloader.RoleRunMode 100 } 101 // try some well known UC20 root dirs 102 switch dir { 103 case InitramfsUbuntuBootDir: 104 if recoveryBootloader { 105 return fmt.Errorf("cannot use run bootloader root-dir with a recovery flag") 106 } 107 opts.Role = bootloader.RoleRunMode 108 case InitramfsUbuntuSeedDir: 109 opts.Role = bootloader.RoleRecovery 110 } 111 if recoveryBootloader { 112 // UC20 recovery bootloader 113 opts.Role = bootloader.RoleRecovery 114 if !opts.NoSlashBoot { 115 // no root dir was provided, use the default one for a 116 // recovery bootloader 117 dir = InitramfsUbuntuSeedDir 118 } 119 } 120 bloader, err := bootloader.Find(dir, opts) 121 if err != nil { 122 return err 123 } 124 125 toSet := map[string]string{} 126 127 for _, req := range varEqVal { 128 split := strings.SplitN(req, "=", 2) 129 if len(split) != 2 { 130 return fmt.Errorf("incorrect setting %q", varEqVal) 131 } 132 toSet[split[0]] = split[1] 133 } 134 return bloader.SetBootVars(toSet) 135 }