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 13typedef struct { 14 u8 magic; 15 u8 version; 16 u8 bootcount; 17 u8 upgrade_available; 18} bootcount_ext_t; 19 20static u8 upgrade_available = 1; 21 22void 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 52ulong 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