// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2017 General Electric Company. All rights reserved. */ #include #include #include #define BC_MAGIC 0xbd #define BC_VERSION 1 typedef struct { u8 magic; u8 version; u8 bootcount; u8 upgrade_available; } bootcount_ext_t; static u8 upgrade_available = 1; void bootcount_store(ulong a) { bootcount_ext_t *buf; loff_t len; int ret; if (fs_set_blk_dev(CONFIG_SYS_BOOTCOUNT_EXT_INTERFACE, CONFIG_SYS_BOOTCOUNT_EXT_DEVPART, FS_TYPE_EXT)) { puts("Error selecting device\n"); return; } /* Only update bootcount during upgrade process */ if (!upgrade_available) return; buf = map_sysmem(CONFIG_SYS_BOOTCOUNT_ADDR, sizeof(bootcount_ext_t)); buf->magic = BC_MAGIC; buf->version = BC_VERSION; buf->bootcount = (a & 0xff); buf->upgrade_available = upgrade_available; unmap_sysmem(buf); ret = fs_write(CONFIG_SYS_BOOTCOUNT_EXT_NAME, CONFIG_SYS_BOOTCOUNT_ADDR, 0, sizeof(bootcount_ext_t), &len); if (ret != 0) puts("Error storing bootcount\n"); } ulong bootcount_load(void) { bootcount_ext_t *buf; loff_t len_read; int ret; if (fs_set_blk_dev(CONFIG_SYS_BOOTCOUNT_EXT_INTERFACE, CONFIG_SYS_BOOTCOUNT_EXT_DEVPART, FS_TYPE_EXT)) { puts("Error selecting device\n"); return 0; } ret = fs_read(CONFIG_SYS_BOOTCOUNT_EXT_NAME, CONFIG_SYS_BOOTCOUNT_ADDR, 0, sizeof(bootcount_ext_t), &len_read); if (ret != 0 || len_read != sizeof(bootcount_ext_t)) { puts("Error loading bootcount\n"); return 0; } buf = map_sysmem(CONFIG_SYS_BOOTCOUNT_ADDR, sizeof(bootcount_ext_t)); if (buf->magic == BC_MAGIC && buf->version == BC_VERSION) { upgrade_available = buf->upgrade_available; if (upgrade_available) ret = buf->bootcount; } else { puts("Incorrect bootcount file\n"); } unmap_sysmem(buf); return ret; }