github.com/chipaca/snappy@v0.0.0-20210104084008-1f06296fe8ad/bootloader/lkenv/lkenv_v2.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 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 lkenv 21 22 import ( 23 "fmt" 24 ) 25 26 /** 27 * Following structure has to be kept in sync with c structure defined by 28 * include/lk/snappy-boot_v2.h 29 * c headerfile is used by bootloader, this ensures sync of the environment 30 * between snapd and bootloader 31 32 * when this structure needs to be updated, 33 * new version should be introduced instead together with c header file, 34 * which is to be adopted by bootloader 35 * 36 * !!! Support for old version has to be maintained, as it is not guaranteed 37 * all existing bootloader would adopt new version! 38 */ 39 40 type SnapBootSelect_v2_recovery struct { 41 /* Contains value BOOTSELECT_SIGNATURE defined above */ 42 Signature uint32 43 /* snappy boot select version */ 44 Version uint32 45 46 /** snapd_recovery_mode is what mode the system will be booted in, one of 47 * "install", "recover" or "run" 48 */ 49 Snapd_recovery_mode [SNAP_FILE_NAME_MAX_LEN]byte 50 51 /** snapd_recovery_system defines the recovery system label to be used when 52 * booting the system, it must be defined to one of the values in the 53 * bootimg matrix below 54 */ 55 Snapd_recovery_system [SNAP_FILE_NAME_MAX_LEN]byte 56 57 /** 58 * Matrix for mapping of recovery system boot img partition to kernel snap 59 * revisions for those recovery systems 60 * 61 * First column represents boot image partition label (e.g. recov_a, recov_a) 62 * value are static and should be populated at gadget build time 63 * or latest at image build time. Values are not further altered at run 64 * time. 65 * Second column represents the name of the currently installed recovery 66 * system label there - note that every recovery system has only one 67 * kernel for it, so this is in effect a proxy for the kernel revision 68 * 69 * The initial value representing initial single recovery system is 70 * populated at image build time by snapd 71 * 72 * There are SNAP_RECOVERY_BOOTIMG_PART_NUM rows in the matrix, representing 73 * all possible recovery systems on the image. 74 * The following describes how this matrix should be modified at different 75 * stages: 76 * - at image build time: 77 * - default recovery system label should be filled into free slot 78 * (first row, second column) 79 * - snapd: 80 * - when new recovery system is being created, snapd cycles 81 * through matrix to find unused 'boot slot' to be used for new 82 * recovery system from free slot, first column represents partition 83 * label to which kernel snap boot image should be extracted. Second 84 * column is then populated recovery system label. 85 * - snapd_recovery_mode and snapd_recovery_system are written/used 86 * normally when transitioning to/from recover/install/run modes 87 * - bootloader: 88 * - bootloader reads snapd_recovery_system to determine what label 89 * should be searched for in the matrix, then finds the corresponding 90 * partition label for the kernel snap from that recovery system. Then 91 * snapd_recovery_mode is read and both variables are put onto the 92 * kernel commandline when booting the linux kernel 93 * - bootloader NEVER alters this matrix values 94 * 95 * [ <bootimg 1 part label> ] [ <kernel snap revision installed in this boot partition> ] 96 * [ <bootimg 2 part label> ] [ <kernel snap revision installed in this boot partition> ] 97 */ 98 Bootimg_matrix [SNAP_RECOVERY_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte 99 100 /* name of the boot image from kernel snap to be used for extraction 101 when not defined or empty, default boot.img will be used */ 102 Bootimg_file_name [SNAP_FILE_NAME_MAX_LEN]byte 103 104 /* unused placeholders for additional parameters in the future */ 105 Unused_key_01 [SNAP_FILE_NAME_MAX_LEN]byte 106 Unused_key_02 [SNAP_FILE_NAME_MAX_LEN]byte 107 Unused_key_03 [SNAP_FILE_NAME_MAX_LEN]byte 108 Unused_key_04 [SNAP_FILE_NAME_MAX_LEN]byte 109 Unused_key_05 [SNAP_FILE_NAME_MAX_LEN]byte 110 Unused_key_06 [SNAP_FILE_NAME_MAX_LEN]byte 111 Unused_key_07 [SNAP_FILE_NAME_MAX_LEN]byte 112 Unused_key_08 [SNAP_FILE_NAME_MAX_LEN]byte 113 Unused_key_09 [SNAP_FILE_NAME_MAX_LEN]byte 114 Unused_key_10 [SNAP_FILE_NAME_MAX_LEN]byte 115 Unused_key_11 [SNAP_FILE_NAME_MAX_LEN]byte 116 Unused_key_12 [SNAP_FILE_NAME_MAX_LEN]byte 117 Unused_key_13 [SNAP_FILE_NAME_MAX_LEN]byte 118 Unused_key_14 [SNAP_FILE_NAME_MAX_LEN]byte 119 Unused_key_15 [SNAP_FILE_NAME_MAX_LEN]byte 120 Unused_key_16 [SNAP_FILE_NAME_MAX_LEN]byte 121 Unused_key_17 [SNAP_FILE_NAME_MAX_LEN]byte 122 Unused_key_18 [SNAP_FILE_NAME_MAX_LEN]byte 123 Unused_key_19 [SNAP_FILE_NAME_MAX_LEN]byte 124 Unused_key_20 [SNAP_FILE_NAME_MAX_LEN]byte 125 126 /* unused array of 10 key value pairs */ 127 Key_value_pairs [10][2][SNAP_FILE_NAME_MAX_LEN]byte 128 129 /* crc32 value for structure */ 130 Crc32 uint32 131 } 132 133 func newV2Recovery() *SnapBootSelect_v2_recovery { 134 return &SnapBootSelect_v2_recovery{ 135 Version: SNAP_BOOTSELECT_VERSION_V2, 136 Signature: SNAP_BOOTSELECT_RECOVERY_SIGNATURE, 137 } 138 } 139 140 func (v2recovery *SnapBootSelect_v2_recovery) currentVersion() uint32 { return v2recovery.Version } 141 func (v2recovery *SnapBootSelect_v2_recovery) currentSignature() uint32 { return v2recovery.Signature } 142 func (v2recovery *SnapBootSelect_v2_recovery) currentCrc32() uint32 { return v2recovery.Crc32 } 143 144 func (v2recovery *SnapBootSelect_v2_recovery) get(key string) string { 145 switch key { 146 case "snapd_recovery_mode": 147 return cToGoString(v2recovery.Snapd_recovery_mode[:]) 148 case "snapd_recovery_system": 149 return cToGoString(v2recovery.Snapd_recovery_system[:]) 150 case "bootimg_file_name": 151 return cToGoString(v2recovery.Bootimg_file_name[:]) 152 } 153 return "" 154 } 155 156 func (v2recovery *SnapBootSelect_v2_recovery) set(key, value string) { 157 switch key { 158 case "snapd_recovery_mode": 159 copyString(v2recovery.Snapd_recovery_mode[:], value) 160 case "snapd_recovery_system": 161 copyString(v2recovery.Snapd_recovery_system[:], value) 162 case "bootimg_file_name": 163 copyString(v2recovery.Bootimg_file_name[:], value) 164 } 165 } 166 167 func (v2recovery *SnapBootSelect_v2_recovery) bootImgRecoverySystemMatrix() (bootimgMatrixGeneric, error) { 168 return (bootimgMatrixGeneric)((&v2recovery.Bootimg_matrix)[:]), nil 169 } 170 171 func (v2recovery *SnapBootSelect_v2_recovery) bootImgKernelMatrix() (bootimgMatrixGeneric, error) { 172 return nil, fmt.Errorf("internal error: v2 recovery lkenv has no boot image partition kernel matrix") 173 } 174 175 type SnapBootSelect_v2_run struct { 176 /* Contains value BOOTSELECT_SIGNATURE defined above */ 177 Signature uint32 178 /* snappy boot select version */ 179 Version uint32 180 181 /* kernel_status, one of: 'empty', "try", "trying" */ 182 Kernel_status [SNAP_FILE_NAME_MAX_LEN]byte 183 /* current kernel snap revision */ 184 Snap_kernel [SNAP_FILE_NAME_MAX_LEN]byte 185 /* current try kernel snap revision */ 186 Snap_try_kernel [SNAP_FILE_NAME_MAX_LEN]byte 187 188 /* gadget_mode, one of: 'empty', "try", "trying" */ 189 Gadget_mode [SNAP_FILE_NAME_MAX_LEN]byte 190 /* GADGET assets: current gadget assets revision */ 191 Snap_gadget [SNAP_FILE_NAME_MAX_LEN]byte 192 /* GADGET assets: try gadget assets revision */ 193 Snap_try_gadget [SNAP_FILE_NAME_MAX_LEN]byte 194 195 /** 196 * Matrix for mapping of run mode boot img partition to installed kernel 197 * snap revision 198 * 199 * First column represents boot image partition label (e.g. boot_a,boot_b ) 200 * value are static and should be populated at gadget built time 201 * or latest at image build time. Values are not further altered at run 202 * time. 203 * Second column represents name currently installed kernel snap 204 * e.g. pi2-kernel_123.snap 205 * initial value representing initial kernel snap revision 206 * is populated at image build time by snapd 207 * 208 * There are two rows in the matrix, representing current and previous 209 * kernel revision 210 * The following describes how this matrix should be modified at different 211 * stages: 212 * - snapd in install mode: 213 * - extracted kernel snap revision name should be filled 214 * into free slot (first row, second row) 215 * - snapd in run mode: 216 * - when new kernel snap revision is being installed, snapd cycles 217 * through matrix to find unused 'boot slot' to be used for new kernel 218 * snap revision from free slot, first column represents partition 219 * label to which kernel snap boot image should be extracted. Second 220 * column is then populated with kernel snap revision name. 221 * - kernel_status, snap_try_kernel, snap_try_core behaves same way as 222 * with u-boot 223 * - bootloader: 224 * - bootloader reads kernel_status to determine if snap_kernel or 225 * snap_try_kernel is used to get kernel snap revision name. 226 * kernel snap revision is then used to search matrix to determine 227 * partition label to be used for current boot 228 * - bootloader NEVER alters this matrix values 229 * 230 * [ <bootimg 1 part label> ] [ <kernel snap revision installed in this boot partition> ] 231 * [ <bootimg 2 part label> ] [ <kernel snap revision installed in this boot partition> ] 232 */ 233 Bootimg_matrix [SNAP_RUN_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte 234 235 /* name of the boot image from kernel snap to be used for extraction 236 when not defined or empty, default boot.img will be used */ 237 Bootimg_file_name [SNAP_FILE_NAME_MAX_LEN]byte 238 239 /** 240 * gadget assets: Matrix for mapping of gadget asset partitions 241 * Optional boot asset tracking, based on bootloader support 242 * Some boot chains support A/B boot assets for increased robustness 243 * example being A/B TrustExecutionEnvironment 244 * This matrix can be used to track current and try boot assets for 245 * robust updates 246 * Use of Gadget_asset_matrix matches use of Bootimg_matrix 247 * 248 * [ <boot assets 1 part label> ] [ <currently installed assets revision in this partition> ] 249 * [ <boot assets 2 part label> ] [ <currently installed assets revision in this partition> ] 250 */ 251 Gadget_asset_matrix [SNAP_RUN_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte 252 253 /* unused placeholders for additional parameters in the future */ 254 Unused_key_01 [SNAP_FILE_NAME_MAX_LEN]byte 255 Unused_key_02 [SNAP_FILE_NAME_MAX_LEN]byte 256 Unused_key_03 [SNAP_FILE_NAME_MAX_LEN]byte 257 Unused_key_04 [SNAP_FILE_NAME_MAX_LEN]byte 258 Unused_key_05 [SNAP_FILE_NAME_MAX_LEN]byte 259 Unused_key_06 [SNAP_FILE_NAME_MAX_LEN]byte 260 Unused_key_07 [SNAP_FILE_NAME_MAX_LEN]byte 261 Unused_key_08 [SNAP_FILE_NAME_MAX_LEN]byte 262 Unused_key_09 [SNAP_FILE_NAME_MAX_LEN]byte 263 Unused_key_10 [SNAP_FILE_NAME_MAX_LEN]byte 264 Unused_key_11 [SNAP_FILE_NAME_MAX_LEN]byte 265 Unused_key_12 [SNAP_FILE_NAME_MAX_LEN]byte 266 Unused_key_13 [SNAP_FILE_NAME_MAX_LEN]byte 267 Unused_key_14 [SNAP_FILE_NAME_MAX_LEN]byte 268 Unused_key_15 [SNAP_FILE_NAME_MAX_LEN]byte 269 Unused_key_16 [SNAP_FILE_NAME_MAX_LEN]byte 270 Unused_key_17 [SNAP_FILE_NAME_MAX_LEN]byte 271 Unused_key_18 [SNAP_FILE_NAME_MAX_LEN]byte 272 Unused_key_19 [SNAP_FILE_NAME_MAX_LEN]byte 273 Unused_key_20 [SNAP_FILE_NAME_MAX_LEN]byte 274 275 /* unused array of 10 key value pairs */ 276 Key_value_pairs [10][2][SNAP_FILE_NAME_MAX_LEN]byte 277 278 /* crc32 value for structure */ 279 Crc32 uint32 280 } 281 282 func newV2Run() *SnapBootSelect_v2_run { 283 return &SnapBootSelect_v2_run{ 284 Version: SNAP_BOOTSELECT_VERSION_V2, 285 Signature: SNAP_BOOTSELECT_SIGNATURE, 286 } 287 } 288 289 func (v2run *SnapBootSelect_v2_run) currentCrc32() uint32 { return v2run.Crc32 } 290 func (v2run *SnapBootSelect_v2_run) currentVersion() uint32 { return v2run.Version } 291 func (v2run *SnapBootSelect_v2_run) currentSignature() uint32 { return v2run.Signature } 292 293 func (v2run *SnapBootSelect_v2_run) get(key string) string { 294 switch key { 295 case "kernel_status": 296 return cToGoString(v2run.Kernel_status[:]) 297 case "snap_kernel": 298 return cToGoString(v2run.Snap_kernel[:]) 299 case "snap_try_kernel": 300 return cToGoString(v2run.Snap_try_kernel[:]) 301 case "snap_gadget": 302 return cToGoString(v2run.Snap_gadget[:]) 303 case "snap_try_gadget": 304 return cToGoString(v2run.Snap_try_gadget[:]) 305 case "bootimg_file_name": 306 return cToGoString(v2run.Bootimg_file_name[:]) 307 } 308 return "" 309 } 310 311 func (v2run *SnapBootSelect_v2_run) set(key, value string) { 312 switch key { 313 case "kernel_status": 314 copyString(v2run.Kernel_status[:], value) 315 case "snap_kernel": 316 copyString(v2run.Snap_kernel[:], value) 317 case "snap_try_kernel": 318 copyString(v2run.Snap_try_kernel[:], value) 319 case "snap_gadget": 320 copyString(v2run.Snap_gadget[:], value) 321 case "snap_try_gadget": 322 copyString(v2run.Snap_try_gadget[:], value) 323 case "bootimg_file_name": 324 copyString(v2run.Bootimg_file_name[:], value) 325 } 326 } 327 328 func (v2run *SnapBootSelect_v2_run) bootImgKernelMatrix() (bootimgMatrixGeneric, error) { 329 return (bootimgMatrixGeneric)((&v2run.Bootimg_matrix)[:]), nil 330 } 331 332 func (v2run *SnapBootSelect_v2_run) bootImgRecoverySystemMatrix() (bootimgMatrixGeneric, error) { 333 return nil, fmt.Errorf("internal error: v2 run lkenv has no boot image partition recovery system matrix") 334 }