bootcount.h 3.3 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0+ */
2 3 4 5
/*
 * (C) Copyright 2012
 * Stefan Roese, DENX Software Engineering, sr@denx.de.
 */
6 7
#ifndef _BOOTCOUNT_H__
#define _BOOTCOUNT_H__
8 9 10 11 12

#include <common.h>
#include <asm/io.h>
#include <asm/byteorder.h>

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#ifdef CONFIG_DM_BOOTCOUNT

struct bootcount_ops {
	/**
	 * get() - get the current bootcount value
	 *
	 * Returns the current counter value of the bootcount backing
	 * store.
	 *
	 * @dev:	Device to read from
	 * @bootcount:	Address to put the current bootcount value
	 */
	int (*get)(struct udevice *dev, u32 *bootcount);

	/**
	 * set() - set a bootcount value (e.g. to reset or increment)
	 *
	 * Sets the value in the bootcount backing store.
	 *
	 * @dev:	Device to read from
	 * @bootcount:	New bootcount value to store
	 */
	int (*set)(struct udevice *dev, const u32 bootcount);
};

/* Access the operations for a bootcount device */
#define bootcount_get_ops(dev)	((struct bootcount_ops *)(dev)->driver->ops)

/**
 * dm_bootcount_get() - Read the current value from a bootcount storage
 *
 * @dev:	Device to read from
 * @bootcount:	Place to put the current bootcount
 * @return 0 if OK, -ve on error
 */
int dm_bootcount_get(struct udevice *dev, u32 *bootcount);

/**
 * dm_bootcount_set() - Write a value to a bootcount storage
 *
 * @dev:	Device to read from
 * @bootcount:  Value to be written to the backing storage
 * @return 0 if OK, -ve on error
 */
int dm_bootcount_set(struct udevice *dev, u32 bootcount);

#endif

61 62
#if defined(CONFIG_SPL_BOOTCOUNT_LIMIT) || defined(CONFIG_BOOTCOUNT_LIMIT)

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#if !defined(CONFIG_SYS_BOOTCOUNT_LE) && !defined(CONFIG_SYS_BOOTCOUNT_BE)
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define CONFIG_SYS_BOOTCOUNT_LE
# else
#  define CONFIG_SYS_BOOTCOUNT_BE
# endif
#endif

#ifdef CONFIG_SYS_BOOTCOUNT_LE
static inline void raw_bootcount_store(volatile u32 *addr, u32 data)
{
	out_le32(addr, data);
}

static inline u32 raw_bootcount_load(volatile u32 *addr)
{
	return in_le32(addr);
}
#else
static inline void raw_bootcount_store(volatile u32 *addr, u32 data)
{
	out_be32(addr, data);
}

static inline u32 raw_bootcount_load(volatile u32 *addr)
{
	return in_be32(addr);
}
#endif
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

DECLARE_GLOBAL_DATA_PTR;
static inline int bootcount_error(void)
{
	unsigned long bootcount = bootcount_load();
	unsigned long bootlimit = env_get_ulong("bootlimit", 10, 0);

	if (bootlimit && bootcount > bootlimit) {
		printf("Warning: Bootlimit (%lu) exceeded.", bootlimit);
		if (!(gd->flags & GD_FLG_SPL_INIT))
			printf(" Using altbootcmd.");
		printf("\n");

		return 1;
	}

	return 0;
}

static inline void bootcount_inc(void)
{
	unsigned long bootcount = bootcount_load();

	if (gd->flags & GD_FLG_SPL_INIT) {
		bootcount_store(++bootcount);
		return;
	}

#ifndef CONFIG_SPL_BUILD
	/* Only increment bootcount when no bootcount support in SPL */
#ifndef CONFIG_SPL_BOOTCOUNT_LIMIT
	bootcount_store(++bootcount);
#endif
	env_set_ulong("bootcount", bootcount);
#endif /* !CONFIG_SPL_BUILD */
}

#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT)
void bootcount_store(ulong a) {};
ulong bootcount_load(void) { return 0; }
#endif /* CONFIG_SPL_BUILD && !CONFIG_SPL_BOOTCOUNT_LIMIT */
#else
static inline int bootcount_error(void) { return 0; }
static inline void bootcount_inc(void) {}
#endif /* CONFIG_SPL_BOOTCOUNT_LIMIT || CONFIG_BOOTCOUNT_LIMIT */
137
#endif /* _BOOTCOUNT_H__ */