github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/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 "snapd_extra_cmdline_args", 75 "snapd_full_cmdline_args", 76 } 77 } 78 bloader, err := bootloader.Find(dir, opts) 79 if err != nil { 80 return err 81 } 82 83 bootVars, err := bloader.GetBootVars(allKeys...) 84 if err != nil { 85 return err 86 } 87 for _, k := range allKeys { 88 fmt.Fprintf(w, "%s=%s\n", k, bootVars[k]) 89 } 90 return nil 91 } 92 93 // DebugSetBootVars is a debug helper that takes a list of <var>=<value> entries 94 // and sets them for the configured bootloader. 95 func DebugSetBootVars(dir string, recoveryBootloader bool, varEqVal []string) error { 96 opts := &bootloader.Options{ 97 NoSlashBoot: dir != "" && dir != "/", 98 } 99 if opts.NoSlashBoot || osutil.FileExists(dirs.SnapModeenvFile) { 100 // implied UC20 bootloader 101 opts.Role = bootloader.RoleRunMode 102 } 103 // try some well known UC20 root dirs 104 switch dir { 105 case InitramfsUbuntuBootDir: 106 if recoveryBootloader { 107 return fmt.Errorf("cannot use run bootloader root-dir with a recovery flag") 108 } 109 opts.Role = bootloader.RoleRunMode 110 case InitramfsUbuntuSeedDir: 111 opts.Role = bootloader.RoleRecovery 112 } 113 if recoveryBootloader { 114 // UC20 recovery bootloader 115 opts.Role = bootloader.RoleRecovery 116 if !opts.NoSlashBoot { 117 // no root dir was provided, use the default one for a 118 // recovery bootloader 119 dir = InitramfsUbuntuSeedDir 120 } 121 } 122 bloader, err := bootloader.Find(dir, opts) 123 if err != nil { 124 return err 125 } 126 127 toSet := map[string]string{} 128 129 for _, req := range varEqVal { 130 split := strings.SplitN(req, "=", 2) 131 if len(split) != 2 { 132 return fmt.Errorf("incorrect setting %q", varEqVal) 133 } 134 toSet[split[0]] = split[1] 135 } 136 return bloader.SetBootVars(toSet) 137 }