gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/bootloader/lkenv/lkenv_v1.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_v1.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  type SnapBootSelect_v1 struct {
    40  	/* Contains value BOOTSELECT_SIGNATURE defined above */
    41  	Signature uint32
    42  	/* snappy boot select version */
    43  	Version uint32
    44  
    45  	/* snap_mode, one of: 'empty', "try", "trying" */
    46  	Snap_mode [SNAP_FILE_NAME_MAX_LEN]byte
    47  	/* current core snap revision */
    48  	Snap_core [SNAP_FILE_NAME_MAX_LEN]byte
    49  	/* try core snap revision */
    50  	Snap_try_core [SNAP_FILE_NAME_MAX_LEN]byte
    51  	/* current kernel snap revision */
    52  	Snap_kernel [SNAP_FILE_NAME_MAX_LEN]byte
    53  	/* current kernel snap revision */
    54  	Snap_try_kernel [SNAP_FILE_NAME_MAX_LEN]byte
    55  
    56  	/* gadget_mode, one of: 'empty', "try", "trying" */
    57  	Gadget_mode [SNAP_FILE_NAME_MAX_LEN]byte
    58  	/* GADGET assets: current gadget assets revision */
    59  	Snap_gadget [SNAP_FILE_NAME_MAX_LEN]byte
    60  	/* GADGET assets: try gadget assets revision */
    61  	Snap_try_gadget [SNAP_FILE_NAME_MAX_LEN]byte
    62  
    63  	/**
    64  	 * Reboot reason
    65  	 * optional parameter to signal bootloader alternative reboot reasons
    66  	 * e.g. recovery/factory-reset/boot asset update
    67  	 */
    68  	Reboot_reason [SNAP_FILE_NAME_MAX_LEN]byte
    69  
    70  	/**
    71  	 * Matrix for mapping of boot img partition to installed kernel snap revision
    72  	 *
    73  	 * First column represents boot image partition label (e.g. boot_a,boot_b )
    74  	 *   value are static and should be populated at gadget built time
    75  	 *   or latest at image build time. Values are not further altered at run time.
    76  	 * Second column represents name currently installed kernel snap
    77  	 *   e.g. pi2-kernel_123.snap
    78  	 * initial value representing initial kernel snap revision
    79  	 *   is populated at image build time by snapd
    80  	 *
    81  	 * There are two rows in the matrix, representing current and previous kernel revision
    82  	 * following describes how this matrix should be modified at different stages:
    83  	 *  - at image build time:
    84  	 *    - extracted kernel snap revision name should be filled
    85  	 *      into free slot (first row, second column)
    86  	 *  - snapd:
    87  	 *    - when new kernel snap revision is being installed, snapd cycles through
    88  	 *      matrix to find unused 'boot slot' to be used for new kernel snap revision
    89  	 *      from free slot, first column represents partition label to which kernel
    90  	 *      snap boot image should be extracted. Second column is then populated with
    91  	 *      kernel snap revision name.
    92  	 *    - snap_mode, snap_try_kernel, snap_try_core behaves same way as with u-boot
    93  	 *  - bootloader:
    94  	 *    - bootloader reads snap_mode to determine if snap_kernel or snap_try_kernel is used
    95  	 *      to get kernel snap revision name
    96  	 *      kernel snap revision is then used to search matrix to determine
    97  	 *      partition label to be used for current boot
    98  	 *    - bootloader NEVER alters this matrix values
    99  	 *
   100  	 * [ <bootimg 1 part label> ] [ <kernel snap revision installed in this boot partition> ]
   101  	 * [ <bootimg 2 part label> ] [ <kernel snap revision installed in this boot partition> ]
   102  	 */
   103  	Bootimg_matrix [SNAP_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte
   104  
   105  	/**
   106  	 * name of the boot image from kernel snap to be used for extraction
   107  	 * when not defined or empty, default boot.img will be used
   108  	 */
   109  	Bootimg_file_name [SNAP_FILE_NAME_MAX_LEN]byte
   110  
   111  	/**
   112  	 * gadget assets: Matrix for mapping of gadget asset partitions
   113  	 * Optional boot asset tracking, based on bootloader support
   114  	 * Some boot chains support A/B boot assets for increased robustness
   115  	 * example being A/B TrustExecutionEnvironment
   116  	 * This matrix can be used to track current and try boot assets for
   117  	 * robust updates
   118  	 * Use of Gadget_asset_matrix matches use of Bootimg_matrix
   119  	 *
   120  	 * [ <boot assets 1 part label> ] [ <currently installed assets revision in this partition> ]
   121  	 * [ <boot assets 2 part label> ] [ <currently installed assets revision in this partition> ]
   122  	 */
   123  	Gadget_asset_matrix [SNAP_BOOTIMG_PART_NUM][2][SNAP_FILE_NAME_MAX_LEN]byte
   124  
   125  	/* unused placeholders for additional parameters in the future */
   126  	Unused_key_01 [SNAP_FILE_NAME_MAX_LEN]byte
   127  	Unused_key_02 [SNAP_FILE_NAME_MAX_LEN]byte
   128  	Unused_key_03 [SNAP_FILE_NAME_MAX_LEN]byte
   129  	Unused_key_04 [SNAP_FILE_NAME_MAX_LEN]byte
   130  	Unused_key_05 [SNAP_FILE_NAME_MAX_LEN]byte
   131  	Unused_key_06 [SNAP_FILE_NAME_MAX_LEN]byte
   132  	Unused_key_07 [SNAP_FILE_NAME_MAX_LEN]byte
   133  	Unused_key_08 [SNAP_FILE_NAME_MAX_LEN]byte
   134  	Unused_key_09 [SNAP_FILE_NAME_MAX_LEN]byte
   135  	Unused_key_10 [SNAP_FILE_NAME_MAX_LEN]byte
   136  	Unused_key_11 [SNAP_FILE_NAME_MAX_LEN]byte
   137  	Unused_key_12 [SNAP_FILE_NAME_MAX_LEN]byte
   138  	Unused_key_13 [SNAP_FILE_NAME_MAX_LEN]byte
   139  	Unused_key_14 [SNAP_FILE_NAME_MAX_LEN]byte
   140  	Unused_key_15 [SNAP_FILE_NAME_MAX_LEN]byte
   141  	Unused_key_16 [SNAP_FILE_NAME_MAX_LEN]byte
   142  	Unused_key_17 [SNAP_FILE_NAME_MAX_LEN]byte
   143  	Unused_key_18 [SNAP_FILE_NAME_MAX_LEN]byte
   144  	Unused_key_19 [SNAP_FILE_NAME_MAX_LEN]byte
   145  	Unused_key_20 [SNAP_FILE_NAME_MAX_LEN]byte
   146  
   147  	/* unused array of 10 key value pairs */
   148  	Key_value_pairs [10][2][SNAP_FILE_NAME_MAX_LEN]byte
   149  
   150  	/* crc32 value for structure */
   151  	Crc32 uint32
   152  }
   153  
   154  func newV1() *SnapBootSelect_v1 {
   155  	return &SnapBootSelect_v1{
   156  		Version:   SNAP_BOOTSELECT_VERSION_V1,
   157  		Signature: SNAP_BOOTSELECT_SIGNATURE,
   158  	}
   159  }
   160  
   161  func (v1 *SnapBootSelect_v1) currentCrc32() uint32     { return v1.Crc32 }
   162  func (v1 *SnapBootSelect_v1) currentVersion() uint32   { return v1.Version }
   163  func (v1 *SnapBootSelect_v1) currentSignature() uint32 { return v1.Signature }
   164  
   165  func (v1 *SnapBootSelect_v1) get(key string) string {
   166  	switch key {
   167  	case "snap_mode":
   168  		return cToGoString(v1.Snap_mode[:])
   169  	case "snap_kernel":
   170  		return cToGoString(v1.Snap_kernel[:])
   171  	case "snap_try_kernel":
   172  		return cToGoString(v1.Snap_try_kernel[:])
   173  	case "snap_core":
   174  		return cToGoString(v1.Snap_core[:])
   175  	case "snap_try_core":
   176  		return cToGoString(v1.Snap_try_core[:])
   177  	case "snap_gadget":
   178  		return cToGoString(v1.Snap_gadget[:])
   179  	case "snap_try_gadget":
   180  		return cToGoString(v1.Snap_try_gadget[:])
   181  	case "reboot_reason":
   182  		return cToGoString(v1.Reboot_reason[:])
   183  	case "bootimg_file_name":
   184  		return cToGoString(v1.Bootimg_file_name[:])
   185  	}
   186  	return ""
   187  }
   188  
   189  func (v1 *SnapBootSelect_v1) set(key, value string) {
   190  	switch key {
   191  	case "snap_mode":
   192  		copyString(v1.Snap_mode[:], value)
   193  	case "snap_kernel":
   194  		copyString(v1.Snap_kernel[:], value)
   195  	case "snap_try_kernel":
   196  		copyString(v1.Snap_try_kernel[:], value)
   197  	case "snap_core":
   198  		copyString(v1.Snap_core[:], value)
   199  	case "snap_try_core":
   200  		copyString(v1.Snap_try_core[:], value)
   201  	case "snap_gadget":
   202  		copyString(v1.Snap_gadget[:], value)
   203  	case "snap_try_gadget":
   204  		copyString(v1.Snap_try_gadget[:], value)
   205  	case "reboot_reason":
   206  		copyString(v1.Reboot_reason[:], value)
   207  	case "bootimg_file_name":
   208  		copyString(v1.Bootimg_file_name[:], value)
   209  	}
   210  }
   211  
   212  func (v1 *SnapBootSelect_v1) bootImgKernelMatrix() (bootimgMatrixGeneric, error) {
   213  	return (bootimgMatrixGeneric)((&v1.Bootimg_matrix)[:]), nil
   214  }
   215  
   216  func (v1 *SnapBootSelect_v1) bootImgRecoverySystemMatrix() (bootimgMatrixGeneric, error) {
   217  	return nil, fmt.Errorf("internal error: v1 lkenv has no boot image partition recovery system matrix")
   218  }