• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-mcu / 1746045300

01 Apr 2025 07:28AM UTC coverage: 56.938%. First build
1746045300

push

gitlab-ci

lluiscampos
feat: Get the initial `artifact_name` from the build config

When auto-generating a Mender Artifact we do have an Artifact name so
use that one instead of the default `unknown`.

Changelog: None
Ticket: MEN-8102

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>

1 of 4 new or added lines in 2 files covered. (25.0%)

2105 of 3697 relevant lines covered (56.94%)

67.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.05
/src/platform/storage/zephyr/nvs/storage.c
1
/**
2
 * @file      storage.c
3
 * @brief     Mender storage interface for Zephyr platform
4
 *
5
 * Copyright joelguittet and mender-mcu-client contributors
6
 * Copyright Northern.tech AS
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
#include <errno.h>
22
#include <zephyr/drivers/flash.h>
23
#include <zephyr/fs/nvs.h>
24
#include <zephyr/sys/crc.h>
25
#include <zephyr/storage/flash_map.h>
26
#include "log.h"
27
#include "storage.h"
28

29
/**
30
 * @brief NVS storage
31
 */
32
#define MENDER_STORAGE_LABEL  storage_partition
33
#define MENDER_STORAGE_DEVICE FIXED_PARTITION_DEVICE(MENDER_STORAGE_LABEL)
34
#define MENDER_STORAGE_OFFSET FIXED_PARTITION_OFFSET(MENDER_STORAGE_LABEL)
35

36
/**
37
 * @brief NVS keys
38
 */
39
#define MENDER_STORAGE_NVS_PRIVATE_KEY     1
40
#define MENDER_STORAGE_NVS_PUBLIC_KEY      2
41
#define MENDER_STORAGE_NVS_DEPLOYMENT_DATA 3
42
#define MENDER_STORAGE_NVS_PROVIDES        4
43
#define MENDER_STORAGE_NVS_ARTICACT_NAME   5
44

45
/**
46
 * @brief Cached Artifact name
47
 */
48
static char *cached_artifact_name = NULL;
49

50
/**
51
 * @brief NVS storage handle
52
 */
53
static struct nvs_fs mender_storage_nvs_handle;
54

55
static mender_err_t
56
nvs_read_alloc(struct nvs_fs *nvs, uint16_t id, void **data, size_t *length) {
192✔
57
    ssize_t ret;
58

59
    /* Peek read to retrieve length of the data */
60
    uint8_t byte;
61
    ret = nvs_read(nvs, id, &byte, 0);
192✔
62
    if (ret <= 0) {
192✔
63
        return (0 == ret || -ENOENT == ret) ? MENDER_NOT_FOUND : MENDER_FAIL;
128✔
64
    }
65
    *length = (size_t)ret;
64✔
66

67
    /* Allocate memory */
68
    *data = mender_malloc(*length);
64✔
69
    if (NULL == *data) {
64✔
70
        mender_log_error("Unable to allocate memory for: %d", id);
×
71
        return MENDER_FAIL;
×
72
    }
73

74
    /* Read data */
75
    ret = nvs_read(nvs, id, *data, *length);
64✔
76
    if (ret < 0) {
64✔
77
        FREE_AND_NULL(*data);
×
78
        return MENDER_FAIL;
×
79
    }
80

81
    return MENDER_OK;
64✔
82
}
83

84
static inline bool
85
checked_nvs_write(struct nvs_fs *fs, uint16_t id, const void *data, size_t len) {
5✔
86
    ssize_t ret = nvs_write(fs, id, data, len);
5✔
87
    /* nvs_write() docs say:
88
     *    When a rewrite of the same data already stored is attempted, nothing is written to flash, thus 0 is returned.
89
     */
90
    return (len == ret) || (0 == ret);
5✔
91
}
92

93
static mender_err_t
94
crc_add(char **data, size_t *data_len) {
77✔
95

96
    assert(NULL != data);
77✔
97
    assert(NULL != data_len);
77✔
98

99
    uint32_t crc = crc32_ieee(*data, *data_len);
77✔
100
    char    *tmp = mender_realloc(*data, *data_len + sizeof(crc));
77✔
101
    if (NULL == tmp) {
77✔
102
        mender_log_error("Unable to allocate memory for deployment data");
×
103
        return MENDER_FAIL;
×
104
    }
105
    memcpy(tmp + *data_len, &crc, sizeof(crc));
77✔
106
    *data_len += sizeof(crc);
77✔
107
    *data = tmp;
77✔
108

109
    return MENDER_OK;
77✔
110
}
111

112
static mender_err_t
113
crc_check(const unsigned char *data, const size_t data_len) {
16✔
114

115
    assert(NULL != data);
16✔
116

117
    if (data_len > sizeof(uint32_t)) {
16✔
118

119
        /* Extract the CRC  */
120
        uint32_t crc = *(uint32_t *)(data + data_len - sizeof(crc));
16✔
121

122
        /* Compute CRC of the loaded data */
123
        uint32_t computed_crc = crc32_ieee(data, data_len - sizeof(crc));
16✔
124

125
        if (computed_crc != crc) {
16✔
126
            mender_log_error("CRC mismatch in deployment data");
×
127
            return MENDER_FAIL;
×
128
        }
129
    } else {
130
        mender_log_error("Invalid deployment data size (too small for CRC)");
×
131
        return MENDER_FAIL;
×
132
    }
133

134
    return MENDER_OK;
16✔
135
}
136

137
mender_err_t
138
mender_storage_init(void) {
29✔
139

140
    int result;
141

142
    /* Get flash info */
143
    mender_storage_nvs_handle.flash_device = MENDER_STORAGE_DEVICE;
29✔
144
    if (!device_is_ready(mender_storage_nvs_handle.flash_device)) {
29✔
145
        mender_log_error("Flash device not ready");
×
146
        return MENDER_FAIL;
×
147
    }
148
    struct flash_pages_info info;
149
    mender_storage_nvs_handle.offset = MENDER_STORAGE_OFFSET;
29✔
150
    if (0 != flash_get_page_info_by_offs(mender_storage_nvs_handle.flash_device, mender_storage_nvs_handle.offset, &info)) {
29✔
151
        mender_log_error("Unable to get storage page info");
×
152
        return MENDER_FAIL;
×
153
    }
154
    mender_storage_nvs_handle.sector_size  = (uint16_t)info.size;
29✔
155
    mender_storage_nvs_handle.sector_count = CONFIG_MENDER_STORAGE_NVS_SECTOR_COUNT;
29✔
156

157
    /* Mount NVS */
158
    if (0 != (result = nvs_mount(&mender_storage_nvs_handle))) {
29✔
159
        mender_log_error("Unable to mount NVS storage, result = %d", result);
×
160
        return MENDER_FAIL;
×
161
    }
162

163
    return MENDER_OK;
29✔
164
}
165

166
mender_err_t
167
mender_storage_set_authentication_keys(unsigned char *private_key, size_t private_key_length, unsigned char *public_key, size_t public_key_length) {
13✔
168

169
    assert(NULL != private_key);
13✔
170
    assert(NULL != public_key);
13✔
171

172
    /* Write keys */
173
    if ((nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PRIVATE_KEY, private_key, private_key_length) < 0)
13✔
174
        || (nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PUBLIC_KEY, public_key, public_key_length) < 0)) {
13✔
175
        mender_log_error("Unable to write authentication keys");
×
176
        return MENDER_FAIL;
×
177
    }
178

179
    return MENDER_OK;
13✔
180
}
181

182
mender_err_t
183
mender_storage_get_authentication_keys(unsigned char **private_key, size_t *private_key_length, unsigned char **public_key, size_t *public_key_length) {
29✔
184

185
    assert(NULL != private_key);
29✔
186
    assert(NULL != private_key_length);
29✔
187
    assert(NULL != public_key);
29✔
188
    assert(NULL != public_key_length);
29✔
189

190
    /* Read private key */
191
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PRIVATE_KEY, (void **)private_key, private_key_length);
29✔
192
    if (MENDER_OK != ret) {
29✔
193
        if (MENDER_NOT_FOUND == ret) {
13✔
194
            mender_log_debug("Private key not available");
13✔
195
        } else {
196
            mender_log_error("Unable to read private key");
×
197
        }
198
        return ret;
13✔
199
    }
200

201
    /* Read public key */
202
    ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PUBLIC_KEY, (void **)public_key, public_key_length);
16✔
203
    if (MENDER_OK != ret) {
16✔
204
        if (MENDER_NOT_FOUND == ret) {
×
205
            mender_log_debug("Public key not available");
×
206
        } else {
207
            mender_log_error("Unable to read public key");
×
208
        }
209
        FREE_AND_NULL(*private_key);
×
210
        return ret;
×
211
    }
212

213
    return MENDER_OK;
16✔
214
}
215

216
mender_err_t
217
mender_storage_delete_authentication_keys(void) {
×
218

219
    /* Erase keys */
220
    if ((0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PRIVATE_KEY))
×
221
        || (0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PUBLIC_KEY))) {
×
222
        mender_log_error("Unable to erase authentication keys");
×
223
        return MENDER_FAIL;
×
224
    }
225

226
    return MENDER_OK;
×
227
}
228

229
mender_err_t
230
mender_storage_set_deployment_data(char *deployment_data) {
77✔
231

232
    assert(NULL != deployment_data);
77✔
233

234
    size_t data_len = strlen(deployment_data) + 1;
77✔
235

236
#ifdef CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC
237
    if (MENDER_OK != crc_add(&deployment_data, &data_len)) {
77✔
238
        return MENDER_FAIL;
×
239
    }
240
#endif /* CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC */
241

242
    /* Write deployment data  */
243
    if (nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_DEPLOYMENT_DATA, deployment_data, data_len) < 0) {
77✔
244
        mender_log_error("Unable to write deployment data");
×
245
        return MENDER_FAIL;
×
246
    }
247

248
    return MENDER_OK;
77✔
249
}
250

251
mender_err_t
252
mender_storage_get_deployment_data(char **deployment_data) {
29✔
253

254
    assert(NULL != deployment_data);
29✔
255
    size_t deployment_data_length = 0;
29✔
256

257
    /* Read deployment data */
258
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_DEPLOYMENT_DATA, (void **)deployment_data, &deployment_data_length);
29✔
259
    if (MENDER_OK != ret) {
29✔
260
        if (MENDER_NOT_FOUND == ret) {
13✔
261
            mender_log_debug("Deployment data not available");
13✔
262
        } else {
263
            mender_log_error("Unable to read deployment data");
×
264
        }
265
        return ret;
13✔
266
    }
267

268
#ifdef CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC
269
    if (MENDER_OK != crc_check(*deployment_data, deployment_data_length)) {
16✔
270
        return MENDER_FAIL;
×
271
    }
272
#endif /* CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC */
273

274
    return MENDER_OK;
16✔
275
}
276

277
mender_err_t
278
mender_storage_delete_deployment_data(void) {
10✔
279

280
    /* Delete deployment data */
281
    if (0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_DEPLOYMENT_DATA)) {
10✔
282
        mender_log_error("Unable to delete deployment data");
×
283
        return MENDER_FAIL;
×
284
    }
285

286
    return MENDER_OK;
10✔
287
}
288

289
#ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT
290
#ifdef CONFIG_MENDER_PROVIDES_DEPENDS
291
mender_err_t
292
mender_storage_set_provides(mender_key_value_list_t *provides) {
5✔
293

294
    assert(NULL != provides);
5✔
295

296
    char *provides_str = NULL;
5✔
297
    if (MENDER_OK != mender_utils_key_value_list_to_string(provides, &provides_str)) {
5✔
298
        return MENDER_FAIL;
×
299
    }
300

301
    /* Write provides */
302
    if (nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PROVIDES, provides_str, strlen(provides_str) + 1) < 0) {
5✔
303
        mender_log_error("Unable to write provides");
×
304
        mender_free(provides_str);
×
305
        return MENDER_FAIL;
×
306
    }
307

308
    mender_free(provides_str);
5✔
309
    return MENDER_OK;
5✔
310
}
311

312
mender_err_t
313
mender_storage_get_provides(mender_key_value_list_t **provides) {
89✔
314
    assert(NULL != provides);
89✔
315
    assert(NULL == *provides); /* otherwise we prepend to a bad list going nowhere */
89✔
316

317
    size_t provides_length = 0;
89✔
318

319
    char *provides_str = NULL;
89✔
320
    /* Read provides */
321
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PROVIDES, (void **)&provides_str, &provides_length);
89✔
322
    if (MENDER_OK != ret) {
89✔
323
        if (MENDER_NOT_FOUND == ret) {
79✔
324
            mender_log_debug("Provides not available");
79✔
325
        } else {
326
            mender_log_error("Unable to read provides");
×
327
        }
328
        return ret;
79✔
329
    }
330

331
    /* Convert str to key-value list */
332
    if (MENDER_OK != mender_utils_string_to_key_value_list(provides_str, provides)) {
10✔
333
        mender_free(provides_str);
×
334
        return MENDER_FAIL;
×
335
    }
336
    mender_free(provides_str);
10✔
337
    return MENDER_OK;
10✔
338
}
339

340
mender_err_t
341
mender_storage_delete_provides(void) {
×
342

343
    /* Delete provides */
344
    if (0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PROVIDES)) {
×
345
        mender_log_error("Unable to delete provides");
×
346
        return MENDER_FAIL;
×
347
    }
348

349
    return MENDER_OK;
×
350
}
351
#endif /* CONFIG_MENDER_PROVIDES_DEPENDS */
352
#endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */
353

354
mender_err_t
355
mender_storage_set_artifact_name(const char *artifact_name) {
5✔
356

357
    assert(NULL != artifact_name);
5✔
358

359
    /* Write artifact_name */
360
    if (!checked_nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_ARTICACT_NAME, artifact_name, strlen(artifact_name) + 1)) {
5✔
361
        mender_log_error("Unable to write artifact_name");
×
362
        return MENDER_FAIL;
×
363
    }
364

365
    mender_free(cached_artifact_name);
5✔
366
    cached_artifact_name = NULL;
5✔
367

368
    return MENDER_OK;
5✔
369
}
370

371
mender_err_t
372
mender_storage_get_artifact_name(const char **artifact_name) {
67✔
373

374
    assert(NULL != artifact_name);
67✔
375

376
    if (NULL != cached_artifact_name) {
67✔
377
        *artifact_name = cached_artifact_name;
38✔
378
        return MENDER_OK;
38✔
379
    }
380

381
    size_t artifact_name_length;
382

383
    /* Read artifact_name */
384
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_ARTICACT_NAME, (void **)artifact_name, &artifact_name_length);
29✔
385
    if (MENDER_OK != ret) {
29✔
386
        if (MENDER_NOT_FOUND == ret) {
23✔
387

388
            /* Get the Artifact Name from the build, if set */
389
#ifdef CONFIG_MENDER_ARTIFACT_NAME
390
            if (0 < strlen(CONFIG_MENDER_ARTIFACT_NAME)) {
391
                if (NULL == (*artifact_name = mender_utils_strdup(CONFIG_MENDER_ARTIFACT_NAME))) {
392
                    mender_log_error("Unable to allocate memory");
393
                    return MENDER_FAIL;
394
                }
395
            } else {
396
#endif
397
                if (NULL == (*artifact_name = mender_utils_strdup("unknown"))) {
23✔
NEW
398
                    mender_log_error("Unable to allocate memory");
×
NEW
399
                    return MENDER_FAIL;
×
400
                }
401
#ifdef CONFIG_MENDER_ARTIFACT_NAME
402
            }
403
#endif
404

405
            cached_artifact_name = (char *)*artifact_name;
23✔
406
            return MENDER_OK;
23✔
407

408
        } else {
409
            mender_log_error("Unable to read artifact_name");
×
410
        }
411
    } else {
412
        cached_artifact_name = (char *)*artifact_name;
6✔
413
    }
414

415
    return ret;
6✔
416
}
417

418
mender_err_t
419
mender_storage_exit(void) {
×
420

421
    FREE_AND_NULL(cached_artifact_name);
×
422

423
    return MENDER_OK;
×
424
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc