1 /* 2 * Copyright (c) 2021-2023, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #ifndef VARIABLE_INDEX_H 9 #define VARIABLE_INDEX_H 10 11 #include <protocols/common/efi/efi_status.h> 12 #include <protocols/common/efi/efi_types.h> 13 #include <protocols/service/smm_variable/smm_variable_proto.h> 14 #include <stdbool.h> 15 #include <stddef.h> 16 #include <stdint.h> 17 18 #include "variable_checker.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /** 25 * Implementation limits 26 */ 27 #define VARIABLE_INDEX_MAX_NAME_SIZE (64) 28 #define FINGERPRINT_SIZE (32) 29 30 /** 31 * \brief variable_metadata structure definition 32 * 33 * Holds metadata associated with stored variable. 34 */ 35 struct variable_metadata { 36 EFI_GUID guid; 37 EFI_TIME timestamp; 38 uint8_t fingerprint[FINGERPRINT_SIZE]; 39 size_t name_size; 40 int16_t name[VARIABLE_INDEX_MAX_NAME_SIZE]; 41 uint32_t attributes; 42 uint64_t uid; 43 }; 44 45 /** 46 * \brief variable_info structure definition 47 * 48 * Holds information about a stored variable. 49 */ 50 struct variable_info { 51 struct variable_metadata metadata; 52 struct variable_constraints check_constraints; 53 54 bool is_variable_set; 55 bool is_constraints_set; 56 }; 57 58 /** 59 * \brief An entry in the index 60 * 61 * Represents a store variable in the variable index. 62 */ 63 struct variable_entry { 64 struct variable_info info; 65 66 bool in_use; 67 bool dirty; 68 }; 69 70 /** 71 * \brief variable_index structure definition 72 * 73 * Provides an index of stored variables to allow the uefi variable store 74 * contents to be enumerated. 75 */ 76 struct variable_index { 77 size_t max_variables; 78 uint32_t counter; 79 struct variable_entry *entries; 80 }; 81 82 /** 83 * @brief Initialises a variable_index 84 * 85 * @param[in] context variable_index 86 * @param[in] max_variables The maximum number of stored variables 87 * 88 * @return EFI_SUCCESS if initialized successfully 89 */ 90 efi_status_t variable_index_init(struct variable_index *context, size_t max_variables); 91 92 /** 93 * @brief De-initialises a variable_index 94 * 95 * @param[in] context variable_index 96 */ 97 void variable_index_deinit(struct variable_index *context); 98 99 /** 100 * @brief Returns the maximum dump size 101 * 102 * For a given maximum index size, returns the size of the 103 * buffer that is needed to hold all serialized variable_info 104 * objects. 105 * 106 * @param[in] context variable_index 107 */ 108 size_t variable_index_max_dump_size(struct variable_index *context); 109 110 /** 111 * @brief Find info about a variable 112 * 113 * @param[in] context variable_index 114 * @param[in] guid The variable's guid 115 * @param[in] name_size The name parameter's size 116 * @param[in] name The variable's name 117 * 118 * @return Pointer to variable_info or NULL 119 */ 120 struct variable_info *variable_index_find(const struct variable_index *context, 121 const EFI_GUID *guid, size_t name_size, 122 const int16_t *name); 123 124 /** 125 * @brief Find the next variable in the index 126 * 127 * @param[in] context variable_index 128 * @param[in] guid The variable's guid 129 * @param[in] name_size The name parameter's size 130 * @param[in] name The variable's name 131 * @param[out] status Provides error status 132 * 133 * @return Pointer to variable_info or NULL 134 */ 135 struct variable_info *variable_index_find_next(const struct variable_index *context, 136 const EFI_GUID *guid, size_t name_size, 137 const int16_t *name, efi_status_t *status); 138 139 /** 140 * @brief Add a new entry to the index 141 * 142 * An entry is needed either when a new variable is created or 143 * when variable constraints are set for a variable that doesn't 144 * yet exist. 145 * 146 * @param[in] context variable_index 147 * @param[in] guid The variable's guid 148 * @param[in] name_size The name parameter's size 149 * @param[in] name The variable's name 150 * 151 * @return Pointer to variable_info or NULL 152 */ 153 struct variable_info *variable_index_add_entry(const struct variable_index *context, 154 const EFI_GUID *guid, size_t name_size, 155 const int16_t *name); 156 157 /** 158 * @brief Remove an unused entry from the index 159 * 160 * Removes an entry if it is not in use. 161 * 162 * @param[in] context variable_index 163 * @param[in] info The variable info corresponding to the entry to remove 164 */ 165 void variable_index_remove_unused_entry(const struct variable_index *context, 166 struct variable_info *info); 167 168 /** 169 * @brief Set a variable to the index 170 * 171 * An entry for the variable must already exist. 172 * 173 * @param[in] info variable info 174 * @param[in] attributes The variable's attributes 175 */ 176 void variable_index_set_variable(struct variable_info *info, uint32_t attributes); 177 178 /** 179 * @brief Clear a variable from the index 180 * 181 * Clears a variable from the index 182 * 183 * @param[in] context variable_index 184 * @param[in] info The variable info corresponding to the variable to clear 185 */ 186 void variable_index_clear_variable(const struct variable_index *context, 187 struct variable_info *info); 188 189 /** 190 * @brief Set a check constraints object associated with a variavle 191 * 192 * @param[in] info variable info 193 * @param[in] constraints The check constraints 194 */ 195 void variable_index_set_constraints(struct variable_info *info, 196 const struct variable_constraints *constraints); 197 198 /** 199 * @brief Dump the serialized index contents for persistent backup 200 * 201 * @param[in] context variable_index 202 * @param[in] buffer_size Size of destination buffer 203 * @param[in] buffer Dump to this buffer 204 * @param[out] data_len Length of serialized data 205 * @param[out] any_dirty True if there is unsaved data 206 * 207 * @return EFI_SUCCESS if all the changes are dumped successfully 208 */ 209 efi_status_t variable_index_dump(const struct variable_index *context, size_t buffer_size, 210 uint8_t *buffer, size_t *data_len, bool *any_dirty); 211 212 /** 213 * @brief Confirms the successful write of the variable index into the storage 214 * by stepping the counter. 215 * 216 * @param[in] context variable_index 217 */ 218 void variable_index_confirm_write(struct variable_index *context); 219 220 /** 221 * @brief Restore the serialized index contents 222 * 223 * Should be called straight after the variable index is initialized to 224 * restore any NV variable info from persistent storage. 225 * 226 * @param[in] context variable_index 227 * @param[in] data_len The length of the data to load 228 * @param[in] buffer Load from this buffer 229 * 230 * @return Number of bytes loaded 231 */ 232 size_t variable_index_restore(struct variable_index *context, size_t data_len, 233 const uint8_t *buffer); 234 235 #ifdef __cplusplus 236 } 237 #endif 238 239 #endif /* VARIABLE_INDEX_H */ 240