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  }