1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2017 General Electric Company. All rights reserved.
4 */
5
6 #include <bootcount.h>
7 #include <fs.h>
8 #include <mapmem.h>
9
10 #define BC_MAGIC 0xbd
11 #define BC_VERSION 1
12
13 typedef struct {
14 u8 magic;
15 u8 version;
16 u8 bootcount;
17 u8 upgrade_available;
18 } bootcount_ext_t;
19
20 static u8 upgrade_available = 1;
21
bootcount_store(ulong a)22 void bootcount_store(ulong a)
23 {
24 bootcount_ext_t *buf;
25 loff_t len;
26 int ret;
27
28 if (fs_set_blk_dev(CONFIG_SYS_BOOTCOUNT_EXT_INTERFACE,
29 CONFIG_SYS_BOOTCOUNT_EXT_DEVPART, FS_TYPE_EXT)) {
30 puts("Error selecting device\n");
31 return;
32 }
33
34 /* Only update bootcount during upgrade process */
35 if (!upgrade_available)
36 return;
37
38 buf = map_sysmem(CONFIG_SYS_BOOTCOUNT_ADDR, sizeof(bootcount_ext_t));
39 buf->magic = BC_MAGIC;
40 buf->version = BC_VERSION;
41 buf->bootcount = (a & 0xff);
42 buf->upgrade_available = upgrade_available;
43 unmap_sysmem(buf);
44
45 ret = fs_write(CONFIG_SYS_BOOTCOUNT_EXT_NAME,
46 CONFIG_SYS_BOOTCOUNT_ADDR, 0, sizeof(bootcount_ext_t),
47 &len);
48 if (ret != 0)
49 puts("Error storing bootcount\n");
50 }
51
bootcount_load(void)52 ulong bootcount_load(void)
53 {
54 bootcount_ext_t *buf;
55 loff_t len_read;
56 int ret;
57
58 if (fs_set_blk_dev(CONFIG_SYS_BOOTCOUNT_EXT_INTERFACE,
59 CONFIG_SYS_BOOTCOUNT_EXT_DEVPART, FS_TYPE_EXT)) {
60 puts("Error selecting device\n");
61 return 0;
62 }
63
64 ret = fs_read(CONFIG_SYS_BOOTCOUNT_EXT_NAME, CONFIG_SYS_BOOTCOUNT_ADDR,
65 0, sizeof(bootcount_ext_t), &len_read);
66 if (ret != 0 || len_read != sizeof(bootcount_ext_t)) {
67 puts("Error loading bootcount\n");
68 return 0;
69 }
70
71 buf = map_sysmem(CONFIG_SYS_BOOTCOUNT_ADDR, sizeof(bootcount_ext_t));
72 if (buf->magic == BC_MAGIC && buf->version == BC_VERSION) {
73 upgrade_available = buf->upgrade_available;
74 if (upgrade_available)
75 ret = buf->bootcount;
76 } else {
77 puts("Incorrect bootcount file\n");
78 }
79
80 unmap_sysmem(buf);
81
82 return ret;
83 }
84