1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * (C) Copyright 2012 4 * Stefan Roese, DENX Software Engineering, sr@denx.de. 5 */ 6 #ifndef _BOOTCOUNT_H__ 7 #define _BOOTCOUNT_H__ 8 9 #include <common.h> 10 #include <asm/io.h> 11 #include <asm/byteorder.h> 12 13 #ifdef CONFIG_DM_BOOTCOUNT 14 15 struct bootcount_ops { 16 /** 17 * get() - get the current bootcount value 18 * 19 * Returns the current counter value of the bootcount backing 20 * store. 21 * 22 * @dev: Device to read from 23 * @bootcount: Address to put the current bootcount value 24 */ 25 int (*get)(struct udevice *dev, u32 *bootcount); 26 27 /** 28 * set() - set a bootcount value (e.g. to reset or increment) 29 * 30 * Sets the value in the bootcount backing store. 31 * 32 * @dev: Device to read from 33 * @bootcount: New bootcount value to store 34 */ 35 int (*set)(struct udevice *dev, const u32 bootcount); 36 }; 37 38 /* Access the operations for a bootcount device */ 39 #define bootcount_get_ops(dev) ((struct bootcount_ops *)(dev)->driver->ops) 40 41 /** 42 * dm_bootcount_get() - Read the current value from a bootcount storage 43 * 44 * @dev: Device to read from 45 * @bootcount: Place to put the current bootcount 46 * @return 0 if OK, -ve on error 47 */ 48 int dm_bootcount_get(struct udevice *dev, u32 *bootcount); 49 50 /** 51 * dm_bootcount_set() - Write a value to a bootcount storage 52 * 53 * @dev: Device to read from 54 * @bootcount: Value to be written to the backing storage 55 * @return 0 if OK, -ve on error 56 */ 57 int dm_bootcount_set(struct udevice *dev, u32 bootcount); 58 59 #endif 60 61 #if defined(CONFIG_SPL_BOOTCOUNT_LIMIT) || defined(CONFIG_BOOTCOUNT_LIMIT) 62 63 #if !defined(CONFIG_SYS_BOOTCOUNT_LE) && !defined(CONFIG_SYS_BOOTCOUNT_BE) 64 # if __BYTE_ORDER == __LITTLE_ENDIAN 65 # define CONFIG_SYS_BOOTCOUNT_LE 66 # else 67 # define CONFIG_SYS_BOOTCOUNT_BE 68 # endif 69 #endif 70 71 #ifdef CONFIG_SYS_BOOTCOUNT_LE 72 static inline void raw_bootcount_store(volatile u32 *addr, u32 data) 73 { 74 out_le32(addr, data); 75 } 76 77 static inline u32 raw_bootcount_load(volatile u32 *addr) 78 { 79 return in_le32(addr); 80 } 81 #else 82 static inline void raw_bootcount_store(volatile u32 *addr, u32 data) 83 { 84 out_be32(addr, data); 85 } 86 87 static inline u32 raw_bootcount_load(volatile u32 *addr) 88 { 89 return in_be32(addr); 90 } 91 #endif 92 93 DECLARE_GLOBAL_DATA_PTR; 94 static inline int bootcount_error(void) 95 { 96 unsigned long bootcount = bootcount_load(); 97 unsigned long bootlimit = env_get_ulong("bootlimit", 10, 0); 98 99 if (bootlimit && bootcount > bootlimit) { 100 printf("Warning: Bootlimit (%lu) exceeded.", bootlimit); 101 if (!(gd->flags & GD_FLG_SPL_INIT)) 102 printf(" Using altbootcmd."); 103 printf("\n"); 104 105 return 1; 106 } 107 108 return 0; 109 } 110 111 static inline void bootcount_inc(void) 112 { 113 unsigned long bootcount = bootcount_load(); 114 115 if (gd->flags & GD_FLG_SPL_INIT) { 116 bootcount_store(++bootcount); 117 return; 118 } 119 120 #ifndef CONFIG_SPL_BUILD 121 /* Only increment bootcount when no bootcount support in SPL */ 122 #ifndef CONFIG_SPL_BOOTCOUNT_LIMIT 123 bootcount_store(++bootcount); 124 #endif 125 env_set_ulong("bootcount", bootcount); 126 #endif /* !CONFIG_SPL_BUILD */ 127 } 128 129 #if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT) 130 void bootcount_store(ulong a) {}; 131 ulong bootcount_load(void) { return 0; } 132 #endif /* CONFIG_SPL_BUILD && !CONFIG_SPL_BOOTCOUNT_LIMIT */ 133 #else 134 static inline int bootcount_error(void) { return 0; } 135 static inline void bootcount_inc(void) {} 136 #endif /* CONFIG_SPL_BOOTCOUNT_LIMIT || CONFIG_BOOTCOUNT_LIMIT */ 137 #endif /* _BOOTCOUNT_H__ */ 138