gitee.com/mysnapcore/mysnapd@v0.1.0/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 /** try_recovery_system contains the label of a recovery system to be 105 * tried. This entry is completely transparent to the bootloader and is 106 * only modified by snapd or snap-bootstrap. 107 */ 108 Try_recovery_system [SNAP_FILE_NAME_MAX_LEN]byte 109 110 /** recovery_system_status contains the status of a tried recovery 111 * systems, which is one of "", "try", "tried". This entry is completely 112 * transparent to the bootloader and is only modified by snapd or 113 * snap-bootstrap 114 */ 115 Recovery_system_status [SNAP_FILE_NAME_MAX_LEN]byte 116 117 /** device_lock_state contains the lock state of the device. It is used by the 118 * bootloader to track device lock changes. When lock state changes, device goes 119 * automatically to install mode. This entry is completely transparent 120 * to the snapd and is only modified by bootloader. 121 * Only first char in the array is used (device_lock_state[0]) 122 * Permitted values: 123 * 0: DEVICE_STATE_UNKNOWN: initial value at first boot. 124 * This is changed by the bootloader to reflect actual device state. 125 * 1: DEVICE_STATE_UNLOCKED: unlocked device 126 * 2: DEVICE_STATE_LOCKED: locked device 127 */ 128 Device_lock_state [SNAP_FILE_NAME_MAX_LEN]byte 129 130 /* unused placeholders for additional parameters in the future */ 131 Unused_key_01 [SNAP_FILE_NAME_MAX_LEN]byte 132 Unused_key_02 [SNAP_FILE_NAME_MAX_LEN]byte 133 Unused_key_03 [SNAP_FILE_NAME_MAX_LEN]byte 134 Unused_key_04 [SNAP_FILE_NAME_MAX_LEN]byte 135 Unused_key_05 [SNAP_FILE_NAME_MAX_LEN]byte 136 Unused_key_06 [SNAP_FILE_NAME_MAX_LEN]byte 137 Unused_key_07 [SNAP_FILE_NAME_MAX_LEN]byte 138 Unused_key_08 [SNAP_FILE_NAME_MAX_LEN]byte 139 Unused_key_09 [SNAP_FILE_NAME_MAX_LEN]byte 140 Unused_key_10 [SNAP_FILE_NAME_MAX_LEN]byte 141 Unused_key_11 [SNAP_FILE_NAME_MAX_LEN]byte 142 Unused_key_12 [SNAP_FILE_NAME_MAX_LEN]byte 143 Unused_key_13 [SNAP_FILE_NAME_MAX_LEN]byte 144 Unused_key_14 [SNAP_FILE_NAME_MAX_LEN]byte 145 Unused_key_15 [SNAP_FILE_NAME_MAX_LEN]byte 146 Unused_key_16 [SNAP_FILE_NAME_MAX_LEN]byte 147 Unused_key_17 [SNAP_FILE_NAME_MAX_LEN]byte 148 149 /* unused array of 10 key value pairs */ 150 Key_value_pairs [10][2][SNAP_FILE_NAME_MAX_LEN]byte 151 152 /* crc32 value for structure */ 153 Crc32 uint32 154 } 155 156 func newV2Recovery() *SnapBootSelect_v2_recovery { 157 return &SnapBootSelect_v2_recovery{ 158 Version: SNAP_BOOTSELECT_VERSION_V2, 159 Signature: SNAP_BOOTSELECT_RECOVERY_SIGNATURE, 160 } 161 } 162 163 func (v2recovery *SnapBootSelect_v2_recovery) currentVersion() uint32 { return v2recovery.Version } 164 func (v2recovery *SnapBootSelect_v2_recovery) currentSignature() uint32 { return v2recovery.Signature } 165 func (v2recovery *SnapBootSelect_v2_recovery) currentCrc32() uint32 { return v2recovery.Crc32 } 166 167 func (v2recovery *SnapBootSelect_v2_recovery) get(key string) string { 168 switch key { 169 case "snapd_recovery_mode": 170 return cToGoString(v2recovery.Snapd_recovery_mode[:]) 171 case "snapd_recovery_system": 172 return cToGoString(v2recovery.Snapd_recovery_system[:]) 173 case "bootimg_file_name": 174 return cToGoString(v2recovery.Bootimg_file_name[:]) 175 case "try_recovery_system": 176 return cToGoString(v2recovery.Try_recovery_system[:]) 177 case "recovery_system_status": 178 return cToGoString(v2recovery.Recovery_system_status[:]) 179 } 180 return "" 181 } 182 183 func (v2recovery *SnapBootSelect_v2_recovery) set(key, value string) { 184 switch key { 185 case "snapd_recovery_mode": 186 copyString(v2recovery.Snapd_recovery_mode[:], value) 187 case "snapd_recovery_system": 188 copyString(v2recovery.Snapd_recovery_system[:], value) 189 case "bootimg_file_name": 190 copyString(v2recovery.Bootimg_file_name[:], value) 191 case "try_recovery_system": 192 copyString(v2recovery.Try_recovery_system[:], value) 193 case "recovery_system_status": 194 copyString(v2recovery.Recovery_system_status[:], value) 195 } 196 } 197 198 func (v2recovery *SnapBootSelect_v2_recovery) bootImgRecoverySystemMatrix() (bootimgMatrixGeneric, error) { 199 return (bootimgMatrixGeneric)((&v2recovery.Bootimg_matrix)[:]), nil 200 } 201 202 func (v2recovery *SnapBootSelect_v2_recovery) bootImgKernelMatrix() (bootimgMatrixGeneric, error) { 203 return nil, fmt.Errorf("internal error: v2 recovery lkenv has no boot image partition kernel matrix") 204 } 205 206 type SnapBootSelect_v2_run struct { 207 /* Contains value BOOTSELECT_SIGNATURE defined above */ 208 Signature uint32 209 /* snappy boot select version */ 210 Version uint32 211 212 /* kernel_status, one of: 'empty', "try", "trying" */ 213 Kernel_status [SNAP_FILE_NAME_MAX_LEN]byte 214 /* current kernel snap revision */ 215 Snap_kernel [SNAP_FILE_NAME_MAX_LEN]byte 216 /* current try kernel snap revision */ 217 Snap_try_kernel [SNAP_FILE_NAME_MAX_LEN]byte 218 219 /* gadget_mode, one of: 'empty', "try", "trying" */ 220 Gadget_mode [SNAP_FILE_NAME_MAX_LEN]byte 221 /* GADGET assets: current gadget assets revision */ 222 Snap_gadget [SNAP_FILE_NAME_MAX_LEN]byte 223 /* GADGET assets: try gadget assets revision */ 224 Snap_try_gadget [SNAP_FILE_NAME_MAX_LEN]byte 225 226 /** 227 * Matrix for mapping of run mode boot img partition to installed kernel 228 * snap revision 229 * 230 * First column represents boot image partition label (e.g. boot_a,boot_b ) 231 * value are static and should be populated at gadget built time 232 * or latest at image build time. Values are not further altered at run 233 * time. 234 * Second column represents name currently installed kernel snap 235 * e.g. pi2-kernel_123.snap 236 * initial value representing initial kernel snap revision 237 * is populated at image build time by snapd 238 * 239 * There are two rows in the matrix, representing current and previous 240 * kernel revision 241 * The following describes how this matrix should be modified at different 242 * stages: 243 * - snapd in install mode: 244 * - extracted kernel snap revision name should be filled 245 * into free slot (first row, second row) 246 * - snapd in run mode: 247 * - when new kernel snap revision is being installed, snapd cycles 248 * through matrix to find unused 'boot slot' to be used for new kernel 249 * snap revision from free slot, first column represents partition 250 * label to which kernel snap boot image should be extracted. Second 251 * column is then populated with kernel snap revision name. 252 * - kernel_status, snap_try_kernel, snap_try_core behaves same way as 253 * with u-boot 254 * - bootloader: 255 * - bootloader reads kernel_status to determine if snap_kernel or 256 * snap_try_kernel is used to get kernel snap revision name. 257 * kernel snap revision is then used to search matrix to determine 258 * partition label to be used for current boot 259 * - bootloader NEVER alters this matrix values 260 * 261 * [ <bootimg 1 part label> ] [ <kernel snap revision installed in this boot partition> ] 262 * [ <bootimg 2 part label> ] [ <kernel snap revision installed in this boot partition> ] 263 */ 264 Bootimg_matrix [SNAP_RUN_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte 265 266 /* name of the boot image from kernel snap to be used for extraction 267 when not defined or empty, default boot.img will be used */ 268 Bootimg_file_name [SNAP_FILE_NAME_MAX_LEN]byte 269 270 /** 271 * gadget assets: Matrix for mapping of gadget asset partitions 272 * Optional boot asset tracking, based on bootloader support 273 * Some boot chains support A/B boot assets for increased robustness 274 * example being A/B TrustExecutionEnvironment 275 * This matrix can be used to track current and try boot assets for 276 * robust updates 277 * Use of Gadget_asset_matrix matches use of Bootimg_matrix 278 * 279 * [ <boot assets 1 part label> ] [ <currently installed assets revision in this partition> ] 280 * [ <boot assets 2 part label> ] [ <currently installed assets revision in this partition> ] 281 */ 282 Gadget_asset_matrix [SNAP_RUN_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte 283 284 /* unused placeholders for additional parameters in the future */ 285 Unused_key_01 [SNAP_FILE_NAME_MAX_LEN]byte 286 Unused_key_02 [SNAP_FILE_NAME_MAX_LEN]byte 287 Unused_key_03 [SNAP_FILE_NAME_MAX_LEN]byte 288 Unused_key_04 [SNAP_FILE_NAME_MAX_LEN]byte 289 Unused_key_05 [SNAP_FILE_NAME_MAX_LEN]byte 290 Unused_key_06 [SNAP_FILE_NAME_MAX_LEN]byte 291 Unused_key_07 [SNAP_FILE_NAME_MAX_LEN]byte 292 Unused_key_08 [SNAP_FILE_NAME_MAX_LEN]byte 293 Unused_key_09 [SNAP_FILE_NAME_MAX_LEN]byte 294 Unused_key_10 [SNAP_FILE_NAME_MAX_LEN]byte 295 Unused_key_11 [SNAP_FILE_NAME_MAX_LEN]byte 296 Unused_key_12 [SNAP_FILE_NAME_MAX_LEN]byte 297 Unused_key_13 [SNAP_FILE_NAME_MAX_LEN]byte 298 Unused_key_14 [SNAP_FILE_NAME_MAX_LEN]byte 299 Unused_key_15 [SNAP_FILE_NAME_MAX_LEN]byte 300 Unused_key_16 [SNAP_FILE_NAME_MAX_LEN]byte 301 Unused_key_17 [SNAP_FILE_NAME_MAX_LEN]byte 302 Unused_key_18 [SNAP_FILE_NAME_MAX_LEN]byte 303 Unused_key_19 [SNAP_FILE_NAME_MAX_LEN]byte 304 Unused_key_20 [SNAP_FILE_NAME_MAX_LEN]byte 305 306 /* unused array of 10 key value pairs */ 307 Key_value_pairs [10][2][SNAP_FILE_NAME_MAX_LEN]byte 308 309 /* crc32 value for structure */ 310 Crc32 uint32 311 } 312 313 func newV2Run() *SnapBootSelect_v2_run { 314 return &SnapBootSelect_v2_run{ 315 Version: SNAP_BOOTSELECT_VERSION_V2, 316 Signature: SNAP_BOOTSELECT_SIGNATURE, 317 } 318 } 319 320 func (v2run *SnapBootSelect_v2_run) currentCrc32() uint32 { return v2run.Crc32 } 321 func (v2run *SnapBootSelect_v2_run) currentVersion() uint32 { return v2run.Version } 322 func (v2run *SnapBootSelect_v2_run) currentSignature() uint32 { return v2run.Signature } 323 324 func (v2run *SnapBootSelect_v2_run) get(key string) string { 325 switch key { 326 case "kernel_status": 327 return cToGoString(v2run.Kernel_status[:]) 328 case "snap_kernel": 329 return cToGoString(v2run.Snap_kernel[:]) 330 case "snap_try_kernel": 331 return cToGoString(v2run.Snap_try_kernel[:]) 332 case "snap_gadget": 333 return cToGoString(v2run.Snap_gadget[:]) 334 case "snap_try_gadget": 335 return cToGoString(v2run.Snap_try_gadget[:]) 336 case "bootimg_file_name": 337 return cToGoString(v2run.Bootimg_file_name[:]) 338 } 339 return "" 340 } 341 342 func (v2run *SnapBootSelect_v2_run) set(key, value string) { 343 switch key { 344 case "kernel_status": 345 copyString(v2run.Kernel_status[:], value) 346 case "snap_kernel": 347 copyString(v2run.Snap_kernel[:], value) 348 case "snap_try_kernel": 349 copyString(v2run.Snap_try_kernel[:], value) 350 case "snap_gadget": 351 copyString(v2run.Snap_gadget[:], value) 352 case "snap_try_gadget": 353 copyString(v2run.Snap_try_gadget[:], value) 354 case "bootimg_file_name": 355 copyString(v2run.Bootimg_file_name[:], value) 356 } 357 } 358 359 func (v2run *SnapBootSelect_v2_run) bootImgKernelMatrix() (bootimgMatrixGeneric, error) { 360 return (bootimgMatrixGeneric)((&v2run.Bootimg_matrix)[:]), nil 361 } 362 363 func (v2run *SnapBootSelect_v2_run) bootImgRecoverySystemMatrix() (bootimgMatrixGeneric, error) { 364 return nil, fmt.Errorf("internal error: v2 run lkenv has no boot image partition recovery system matrix") 365 }