Skip to contentSkip to conversation

GE: Move from ext4 to eeprom bootcounter

PATCH Superseded Sebastian Reichel 2 participants 9 messages Jun 26, 2018 – Jul 19, 2018

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover GE: Move from ext4 to eeprom bootcounter

Writing to ext4 from U-Boot is dangerous in case of inconsistent filesystem state (i.e. due to power-loss). The current U-Boot code can modify the filesystem, so that it is no longer usable by Linux after fsck. This patchset avoids writing to the partition on GE devices by moving the boot counter to the last two bytes of VPD EEPROM (together with some VPD cleanups). It also adds non RTC device support to the i2c bootcounter driver.

-- Sebastian

Denis Zalevskiy (6):
board: ge: Remove EEPROM bus param from read_vpd()
board: ge: Move VPD EEPROM configuration to the defconfig
bootcount: i2c: Add bus switching to the I2C bootcount driver
bootcount: Configure length limit for I2C bootcount
board: ge: Move VPD reading to the vpd_reader
board: ge: Store bootcount in EEPROM on PPD and Bx50v3

 board/ge/bx50v3/Kconfig           |  2 +
 board/ge/bx50v3/bx50v3.c          | 57 +++++-----------------
 board/ge/common/vpd_reader.c      | 57 ++++++++++++++++++++--
 board/ge/common/vpd_reader.h      | 16 +++++--
 board/ge/mx53ppd/Kconfig          |  2 +
 board/ge/mx53ppd/mx53ppd.c        | 50 ++++----------------
 configs/ge_bx50v3_defconfig       | 27 +++++++++--
 configs/mx53ppd_defconfig         | 29 ++++++++++--
 drivers/bootcount/Kconfig         | 21 ++++++++-
 drivers/bootcount/bootcount_i2c.c | 78 ++++++++++++++++++++++++++-----
 include/configs/ge_bx50v3.h       |  6 +--
 include/configs/mx53ppd.h         |  6 +--
 12 files changed, 230 insertions(+), 121 deletions(-)
Signature · 1 line
2.18.0
#1 lore raw

PATCH 1/6 board: ge: Remove EEPROM bus param from read_vpd()

From: Denis Zalevskiy <[email protected]>

The bus is statically defined, so remove redundant parameters from read_vpd() for PPD and Bx50v3.

---
 board/ge/bx50v3/bx50v3.c   | 6 +++---
 board/ge/mx53ppd/mx53ppd.c | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)
board/ge/bx50v3/bx50v3.c +3 -3
index 33f7ee6e3be5..60d600c50c8b 100644
@@ -624,14 +624,14 @@ static void process_vpd(struct vpd_cache *vpd)
 		eth_env_set_enetaddr_by_index("eth", i210_index, vpd->mac2);
 }
 
-static int read_vpd(uint eeprom_bus)
+static int read_vpd()
 {
 	int res;
 	int size = 1024;
 	uint8_t *data;
 	unsigned int current_i2c_bus = i2c_get_bus_num();
 
-	res = i2c_set_bus_num(eeprom_bus);
+	res = i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS);
 	if (res < 0)
 		return res;
 
@@ -715,7 +715,7 @@ int board_init(void)
 	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
 	setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
 
-	read_vpd(CONFIG_SYS_I2C_EEPROM_BUS);
+	read_vpd();
 
 	set_confidx(&vpd);
 
board/ge/mx53ppd/mx53ppd.c +3 -3
index 0010998d66cf..317d7f69d5a1 100644
@@ -329,7 +329,7 @@ static void process_vpd(struct vpd_cache *vpd)
 		eth_env_set_enetaddr("ethaddr", vpd->mac1);
 }
 
-static int read_vpd(uint eeprom_bus)
+static int read_vpd()
 {
 	struct vpd_cache vpd;
 	int res;
@@ -337,7 +337,7 @@ static int read_vpd(uint eeprom_bus)
 	u8 *data;
 	unsigned int current_i2c_bus = i2c_get_bus_num();
 
-	res = i2c_set_bus_num(eeprom_bus);
+	res = i2c_set_bus_num(VPD_EEPROM_BUS);
 	if (res < 0)
 		return res;
 
@@ -391,7 +391,7 @@ int board_late_init(void)
 {
 	int res;
 
-	read_vpd(VPD_EEPROM_BUS);
+	read_vpd();
 
 	res = clock_1GHz();
 	if (res != 0)
Signature · 1 line
2.18.0
#2 lore raw

PATCH 2/6 board: ge: Move VPD EEPROM configuration to the defconfig

In reply to Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

Use standard configuration logic to define EEPROM constants. Names are based on VPD_EEPROM_ prefix because EEPROM_ is already used by i2c_eeprom driver.

---
 board/ge/bx50v3/Kconfig     |  2 ++
 board/ge/bx50v3/bx50v3.c    | 17 ++++-------------
 board/ge/mx53ppd/Kconfig    |  2 ++
 board/ge/mx53ppd/mx53ppd.c  | 14 ++++----------
 configs/ge_bx50v3_defconfig |  9 +++++++++
 configs/mx53ppd_defconfig   | 10 ++++++++++
 6 files changed, 31 insertions(+), 23 deletions(-)
board/ge/bx50v3/Kconfig +2 -0
index 993b0559302b..05938560abda 100644
@@ -15,4 +15,6 @@ config SYS_SOC
 config SYS_CONFIG_NAME
 	default "ge_bx50v3"
 
+source "board/ge/common/Kconfig"
+
 endif
board/ge/bx50v3/bx50v3.c +4 -13
index 60d600c50c8b..c703aca7cab3 100644
@@ -39,15 +39,6 @@ struct vpd_cache;
 static int confidx = 3;  /* Default to b850v3. */
 static struct vpd_cache vpd;
 
-#ifndef CONFIG_SYS_I2C_EEPROM_ADDR
-# define CONFIG_SYS_I2C_EEPROM_ADDR     0x50
-# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
-#endif
-
-#ifndef CONFIG_SYS_I2C_EEPROM_BUS
-#define CONFIG_SYS_I2C_EEPROM_BUS       4
-#endif
-
 #define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP |	\
 	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |	\
 	PAD_CTL_HYS)
@@ -627,11 +618,11 @@ static void process_vpd(struct vpd_cache *vpd)
 static int read_vpd()
 {
 	int res;
-	int size = 1024;
+	static const int size = CONFIG_SYS_VPD_EEPROM_SIZE;
 	uint8_t *data;
 	unsigned int current_i2c_bus = i2c_get_bus_num();
 
-	res = i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS);
+	res = i2c_set_bus_num(CONFIG_SYS_VPD_EEPROM_I2C_BUS);
 	if (res < 0)
 		return res;
 
@@ -639,8 +630,8 @@ static int read_vpd()
 	if (!data)
 		return -ENOMEM;
 
-	res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0,
-			CONFIG_SYS_I2C_EEPROM_ADDR_LEN, data, size);
+	res = i2c_read(CONFIG_SYS_VPD_EEPROM_I2C_ADDR, 0,
+		       CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN, data, size);
 
 	if (res == 0) {
 		memset(&vpd, 0, sizeof(vpd));
board/ge/mx53ppd/Kconfig +2 -0
index 781c1cf59f61..cc43d839cf92 100644
@@ -14,4 +14,6 @@ config SYS_SOC
 config SYS_CONFIG_NAME
 	default "mx53ppd"
 
+source "board/ge/common/Kconfig"
+
 endif
board/ge/mx53ppd/mx53ppd.c +4 -10
index 317d7f69d5a1..47f6e9649cbe 100644
@@ -41,13 +41,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* Index of I2C1, SEGMENT 1 (see CONFIG_SYS_I2C_BUSES). */
-#define VPD_EEPROM_BUS 2
-
-/* Address of 24C08 EEPROM. */
-#define VPD_EEPROM_ADDR		0x50
-#define VPD_EEPROM_ADDR_LEN	1
-
 static u32 mx53_dram_size[2];
 
 phys_size_t get_effective_memsize(void)
@@ -333,11 +326,11 @@ static int read_vpd()
 {
 	struct vpd_cache vpd;
 	int res;
-	int size = 1024;
+	static const int size = CONFIG_SYS_VPD_EEPROM_SIZE;
 	u8 *data;
 	unsigned int current_i2c_bus = i2c_get_bus_num();
 
-	res = i2c_set_bus_num(VPD_EEPROM_BUS);
+	res = i2c_set_bus_num(CONFIG_SYS_VPD_EEPROM_I2C_BUS);
 	if (res < 0)
 		return res;
 
@@ -345,7 +338,8 @@ static int read_vpd()
 	if (!data)
 		return -ENOMEM;
 
-	res = i2c_read(VPD_EEPROM_ADDR, 0, VPD_EEPROM_ADDR_LEN, data, size);
+	res = i2c_read(CONFIG_SYS_VPD_EEPROM_I2C_ADDR, 0,
+		       CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN, data, size);
 	if (res == 0) {
 		memset(&vpd, 0, sizeof(vpd));
 		vpd_reader(size, data, &vpd, vpd_callback);
configs/ge_bx50v3_defconfig +9 -0
index a37df05d0994..829a39e08567 100644
@@ -7,6 +7,15 @@ CONFIG_FIT=y
 CONFIG_BOOTDELAY=1
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
+
+# monitor's EEPROM is connected to the bus through the mux channel 1
+# (the number is the offset in CONFIG_SYS_I2C_BUSES)
+CONFIG_SYS_VPD_EEPROM_I2C_BUS=4
+# Address of Atmel 24C08 EEPROM
+CONFIG_SYS_VPD_EEPROM_I2C_ADDR=0x50
+CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN=1
+CONFIG_SYS_VPD_EEPROM_SIZE=1024
+
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_LAST_STAGE_INIT=y
configs/mx53ppd_defconfig +10 -0
index 8a0cc5d481ad..4a7e8eee0df1 100644
@@ -8,6 +8,16 @@ CONFIG_BOOTDELAY=1
 # CONFIG_CONSOLE_MUX is not set
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
+
+# monitor's EEPROM is connected to the bus through the mux channel 1
+# (the number is the offset in CONFIG_SYS_I2C_BUSES)
+# (there is also Frame EEPROM connected to the channel 4 (bus 4))
+CONFIG_SYS_VPD_EEPROM_I2C_BUS=2
+# Address of Atmel 24C08 EEPROM
+CONFIG_SYS_VPD_EEPROM_I2C_ADDR=0x50
+CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN=1
+CONFIG_SYS_VPD_EEPROM_SIZE=1024
+
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
Signature · 1 line
2.18.0
#3 lore raw

PATCH 2/6 board: ge: Move VPD EEPROM configuration to the defconfig

Quoted 21 lines · Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

Use standard configuration logic to define EEPROM constants. Names are based on VPD_EEPROM_ prefix because EEPROM_ is already used by i2c_eeprom driver.

---
 board/ge/bx50v3/Kconfig     |  2 ++
 board/ge/bx50v3/bx50v3.c    | 17 ++++-------------
 board/ge/mx53ppd/Kconfig    |  2 ++
 board/ge/mx53ppd/mx53ppd.c  | 14 ++++----------
 configs/ge_bx50v3_defconfig |  9 +++++++++
 configs/mx53ppd_defconfig   | 10 ++++++++++
 6 files changed, 31 insertions(+), 23 deletions(-)
board/ge/bx50v3/Kconfig +0 -0
index 993b0559302b..05938560abda 100644

board/ge/bx50v3/Kconfig config SYS_SOC · line 18

Quoted 4 lines
board/ge/bx50v3/Kconfig +1 -0
@@ -15,4 +15,6 @@ config SYS_SOC
 config SYS_CONFIG_NAME
 	default "ge_bx50v3"
 
+source "board/ge/common/Kconfig"

The new file board/ge/common/Kconfig is missing, please repost the series with the file added, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180719/a53d1452/attachment.sig>
#4 lore raw

PATCH 2/6 board: ge: Move VPD EEPROM configuration to the defconfig

Hi Tom,

Quoted 26 lines · Tom Rini
Quoted 24 lines · Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

Use standard configuration logic to define EEPROM constants. Names are based on VPD_EEPROM_ prefix because EEPROM_ is already used by i2c_eeprom driver.

---
 board/ge/bx50v3/Kconfig     |  2 ++
 board/ge/bx50v3/bx50v3.c    | 17 ++++-------------
 board/ge/mx53ppd/Kconfig    |  2 ++
 board/ge/mx53ppd/mx53ppd.c  | 14 ++++----------
 configs/ge_bx50v3_defconfig |  9 +++++++++
 configs/mx53ppd_defconfig   | 10 ++++++++++
 6 files changed, 31 insertions(+), 23 deletions(-)
board/ge/bx50v3/Kconfig +0 -0
index 993b0559302b..05938560abda 100644
@@ -15,4 +15,6 @@ config SYS_SOC
 config SYS_CONFIG_NAME
 	default "ge_bx50v3"
 
Quoted 4 lines

board/ge/bx50v3/Kconfig config SYS_SOC · line 18

Quoted 1 line
board/ge/bx50v3/Kconfig +1 -0
+source "board/ge/common/Kconfig"

The new file board/ge/common/Kconfig is missing, please repost the series with the file added, thanks!

Oops, I just wondered how my test-built worked, but it's just me being too stupid to read git output 😓

Untracked files:
(use "git add <file>..." to include in what will be committed)

board/ge/common/Kconfig

Anyways, thanks for the review, I will resend the series!

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180719/8e795f68/attachment.sig>

#5 lore raw

PATCH 3/6 bootcount: i2c: Add bus switching to the I2C bootcount driver

In reply to Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

If there is an I2C mux, current bus should be switched before manipulating with I2C.

---
 drivers/bootcount/Kconfig         | 15 ++++++-
 drivers/bootcount/bootcount_i2c.c | 70 +++++++++++++++++++++++++++----
 2 files changed, 76 insertions(+), 9 deletions(-)
drivers/bootcount/Kconfig +14 -1
index d335ed14b961..a5349a62fdc3 100644
@@ -62,7 +62,9 @@ config BOOTCOUNT_I2C
 	bool "Boot counter on I2C device"
 	help
 	  Enable support for the bootcounter on an i2c (like RTC) device.
-	  CONFIG_SYS_I2C_RTC_ADDR = i2c chip address
+	  CONFIG_SYS_BOOTCOUNT_I2C_BUS = bus of the target I2C device,
+	                                 CONFIG_SYS_I2C_RTC_ADDR is used as fallback
+	  CONFIG_SYS_BOOTCOUNT_I2C_ADDR = target I2C device address
 	  CONFIG_SYS_BOOTCOUNT_ADDR = i2c addr which is used for
 	                              the bootcounter.
 
@@ -119,4 +121,15 @@ config SYS_BOOTCOUNT_ADDR
 	help
 	  Set the address used for reading and writing the boot counter.
 
+config SYS_BOOTCOUNT_I2C_BUS
+	int "I2C bootcounter device bus"
+	depends on BOOTCOUNT_I2C
+	help
+	  I2C bus of the device used to store bootcounter
+
+config SYS_BOOTCOUNT_I2C_ADDR
+	hex "I2C bootcounter device address"
+	depends on BOOTCOUNT_I2C
+	help
+	  I2C address of the device used to store bootcounter
 endif
drivers/bootcount/bootcount_i2c.c +62 -8

98 lines not on this page · raw message

Signature · 1 line
2.18.0
#6 lore raw

PATCH 4/6 bootcount: Configure length limit for I2C bootcount

In reply to Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

Bootcount driver should verify size against the maximum available space. New configuration parameter adds this capability and keeps backward compatibility by providing default value.

---
 drivers/bootcount/Kconfig         |  6 ++++++
 drivers/bootcount/bootcount_i2c.c | 10 ++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)
drivers/bootcount/Kconfig +6 -0
index a5349a62fdc3..e7f2e1ef65e0 100644
@@ -132,4 +132,10 @@ config SYS_BOOTCOUNT_I2C_ADDR
 	depends on BOOTCOUNT_I2C
 	help
 	  I2C address of the device used to store bootcounter
+
+config BOOTCOUNT_I2C_LEN
+	int "Maximum length of bootcounter in bytes"
+	default 2
+	depends on BOOTCOUNT_I2C
+
 endif
drivers/bootcount/bootcount_i2c.c +6 -4
index 79d82ad451f3..a8bb611eea9e 100644
@@ -54,14 +54,15 @@ void bootcount_store(ulong a)
 	if (prev_i2c_bus < 0)
 		return;
 
-	unsigned char buf[3];
+	unsigned char buf[2];
 	int ret;
 
+	BUILD_BUG_ON(CONFIG_BOOTCOUNT_I2C_LEN < sizeof(buf));
 	buf[0] = BC_MAGIC;
 	buf[1] = (a & 0xff);
 	ret = i2c_write(CONFIG_SYS_BOOTCOUNT_I2C_ADDR,
 			CONFIG_SYS_BOOTCOUNT_ADDR,
-			CONFIG_BOOTCOUNT_ALEN, buf, 2);
+			CONFIG_BOOTCOUNT_ALEN, buf, sizeof(buf));
 	if (ret != 0)
 		puts("Error writing bootcount\n");
 
@@ -77,12 +78,13 @@ ulong bootcount_load(void)
 	if (prev_i2c_bus < 0)
 		return count;
 
-	unsigned char buf[3];
+	unsigned char buf[2];
 	int ret;
 
+	BUILD_BUG_ON(CONFIG_BOOTCOUNT_I2C_LEN < sizeof(buf));
 	ret = i2c_read(CONFIG_SYS_BOOTCOUNT_I2C_ADDR,
 		       CONFIG_SYS_BOOTCOUNT_ADDR,
-		       CONFIG_BOOTCOUNT_ALEN, buf, 2);
+		       CONFIG_BOOTCOUNT_ALEN, buf, sizeof(buf));
 	if (ret != 0) {
 		puts("Error loading bootcount\n");
 		goto out;
Signature · 1 line
2.18.0
#7 lore raw

PATCH 5/6 board: ge: Move VPD reading to the vpd_reader

In reply to Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

Merge functionality duplicated in bx50v3 and mx53ppd: the logic is the same except that process_vpd is called at different phases. Also read_vpd could end up in error, so there is no VPD data in this case - it shouldn't be processed.

---
 board/ge/bx50v3/bx50v3.c     | 48 +++++++++---------------------------
 board/ge/common/vpd_reader.c | 37 ++++++++++++++++++++++++---
 board/ge/common/vpd_reader.h | 16 ++++++++----
 board/ge/mx53ppd/mx53ppd.c   | 44 +++++++--------------------------
 4 files changed, 65 insertions(+), 80 deletions(-)
board/ge/bx50v3/bx50v3.c +11 -37
index c703aca7cab3..917baaea7129 100644
@@ -34,8 +34,6 @@
 #include "../../../drivers/net/e1000.h"
 DECLARE_GLOBAL_DATA_PTR;
 
-struct vpd_cache;
-
 static int confidx = 3;  /* Default to b850v3. */
 static struct vpd_cache vpd;
 
@@ -553,6 +551,7 @@ int overwrite_console(void)
 #define VPD_MAC_ADDRESS_LENGTH 6
 
 struct vpd_cache {
+	bool is_read;
 	u8 product_id;
 	u8 has;
 	unsigned char mac1[VPD_MAC_ADDRESS_LENGTH];
@@ -562,11 +561,9 @@ struct vpd_cache {
 /*
  * Extracts MAC and product information from the VPD.
  */
-static int vpd_callback(void *userdata, u8 id, u8 version, u8 type,
+static int vpd_callback(struct vpd_cache *vpd, u8 id, u8 version, u8 type,
 			size_t size, u8 const *data)
 {
-	struct vpd_cache *vpd = (struct vpd_cache *)userdata;
-
 	if (id == VPD_BLOCK_HWID && version == 1 && type != VPD_TYPE_INVALID &&
 	    size >= 1) {
 		vpd->product_id = data[0];
@@ -590,6 +587,11 @@ static void process_vpd(struct vpd_cache *vpd)
 	int fec_index = -1;
 	int i210_index = -1;
 
+	if (!vpd->is_read) {
+		printf("VPD wasn't read");
+		return;
+	}
+
 	switch (vpd->product_id) {
 	case VPD_PRODUCT_B450:
 		env_set("confidx", "1");
@@ -615,35 +617,6 @@ static void process_vpd(struct vpd_cache *vpd)
 		eth_env_set_enetaddr_by_index("eth", i210_index, vpd->mac2);
 }
 
-static int read_vpd()
-{
-	int res;
-	static const int size = CONFIG_SYS_VPD_EEPROM_SIZE;
-	uint8_t *data;
-	unsigned int current_i2c_bus = i2c_get_bus_num();
-
-	res = i2c_set_bus_num(CONFIG_SYS_VPD_EEPROM_I2C_BUS);
-	if (res < 0)
-		return res;
-
-	data = (uint8_t *)malloc(size);
-	if (!data)
-		return -ENOMEM;
-
-	res = i2c_read(CONFIG_SYS_VPD_EEPROM_I2C_ADDR, 0,
-		       CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN, data, size);
-
-	if (res == 0) {
-		memset(&vpd, 0, sizeof(vpd));
-		vpd_reader(size, data, &vpd, vpd_callback);
-	}
-
-	free(data);
-
-	i2c_set_bus_num(current_i2c_bus);
-	return res;
-}
-
 int board_eth_init(bd_t *bis)
 {
 	setup_iomux_enet();
@@ -706,9 +679,10 @@ int board_init(void)
 	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
 	setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
 
-	read_vpd();
-
-	set_confidx(&vpd);
+	if (!read_vpd(&vpd, vpd_callback)) {
+		vpd.is_read = true;
+		set_confidx(&vpd);
+	}
 
 	gpio_direction_output(SUS_S3_OUT, 1);
 	gpio_direction_output(WIFI_EN, 1);
board/ge/common/vpd_reader.c +34 -3
index 7367427993b3..60f81342f9bc 100644
@@ -6,6 +6,7 @@
 
 #include "vpd_reader.h"
 
+#include <i2c.h>
 #include <linux/bch.h>
 #include <stdlib.h>
 
@@ -106,9 +107,9 @@ static const size_t HEADER_BLOCK_ECC_LEN = 4;
 
 static const u8 ECC_BLOCK_ID = 0xFF;
 
-int vpd_reader(size_t size, u8 *data, void *userdata,
-	       int (*fn)(void *userdata, u8 id, u8 version, u8 type,
-			 size_t size, u8 const *data))
+static int vpd_reader(size_t size, u8 *data, struct vpd_cache *userdata,
+		      int (*fn)(struct vpd_cache *, u8 id, u8 version, u8 type,
+				size_t size, u8 const *data))
 {
 	if (size < HEADER_BLOCK_LEN || !data || !fn)
 		return -EINVAL;
@@ -195,3 +196,33 @@ int vpd_reader(size_t size, u8 *data, void *userdata,
 			return ret;
 	}
 }
+
+int read_vpd(struct vpd_cache *cache,
+	     int (*process_block)(struct vpd_cache *, u8 id, u8 version,
+				  u8 type, size_t size, u8 const *data))
+{
+	static const size_t size = CONFIG_SYS_VPD_EEPROM_SIZE;
+
+	int res;
+	u8 *data;
+	unsigned int current_i2c_bus = i2c_get_bus_num();
+
+	res = i2c_set_bus_num(CONFIG_SYS_VPD_EEPROM_I2C_BUS);
+	if (res < 0)
+		return res;
+
+	data = malloc(size);
+	if (!data)
+		return -ENOMEM;
+
+	res = i2c_read(CONFIG_SYS_VPD_EEPROM_I2C_ADDR, 0,
+		       CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN,
+		       data, size);
+	if (res == 0)
+		res = vpd_reader(size, data, cache, process_block);
+
+	free(data);
+
+	i2c_set_bus_num(current_i2c_bus);
+	return res;
+}
board/ge/common/vpd_reader.h +11 -5
index 4abba8f5de72..f5e90dbf6629 100644
@@ -6,12 +6,18 @@
 
 #include "common.h"
 
+struct vpd_cache;
+
 /*
- * Read VPD from given data, verify content, and call callback
- * for each vital product data block.
+ * Read VPD from given data, verify content, call callback for each vital
+ * product data block.
+ *
+ * cache: structure used by process block to store VPD information
+ * process_block: callback called for each VPD data block
  *
  * Returns Non-zero on error.  Negative numbers encode errno.
  */
-int vpd_reader(size_t size, u8 *data, void *userdata,
-	       int (*fn)(void *userdata, u8 id, u8 version, u8 type,
-			 size_t size, u8 const *data));
+int read_vpd(struct vpd_cache *cache,
+	     int (*process_block)(struct vpd_cache *,
+				  u8 id, u8 version, u8 type,
+				  size_t size, u8 const *data));
board/ge/mx53ppd/mx53ppd.c +9 -35

64 lines not on this page · raw message

Signature · 1 line
2.18.0
#8 lore raw

PATCH 6/6 board: ge: Store bootcount in EEPROM on PPD and Bx50v3

In reply to Sebastian Reichel

From: Denis Zalevskiy <[email protected]>

u-boot's ext3/4 write/modify functionality sometimes corrupts filesystem in the case if it requires recovery (e.g. after unexpected shutdown) and we want to avoid the only filesystem modification we have - bootcounter writing. So, bootcounter will be stored in the EEPROM where VPD is stored.

---
 board/ge/common/vpd_reader.c | 20 ++++++++++++++++++++
 configs/ge_bx50v3_defconfig  | 18 ++++++++++++++----
 configs/mx53ppd_defconfig    | 19 +++++++++++++++----
 include/configs/ge_bx50v3.h  |  6 +++---
 include/configs/mx53ppd.h    |  6 +++---
 5 files changed, 55 insertions(+), 14 deletions(-)
board/ge/common/vpd_reader.c +20 -0
index 60f81342f9bc..7f1f8bca1baf 100644
@@ -6,6 +6,7 @@
 
 #include "vpd_reader.h"
 
+#include <linux/bug.h>
 #include <i2c.h>
 #include <linux/bch.h>
 #include <stdlib.h>
@@ -201,7 +202,26 @@ int read_vpd(struct vpd_cache *cache,
 	     int (*process_block)(struct vpd_cache *, u8 id, u8 version,
 				  u8 type, size_t size, u8 const *data))
 {
+#if defined(CONFIG_BOOTCOUNT_I2C) &&					\
+	(CONFIG_SYS_BOOTCOUNT_I2C_BUS == CONFIG_SYS_VPD_EEPROM_I2C_BUS) && \
+	((CONFIG_SYS_BOOTCOUNT_I2C_ADDR & 0xf0) == CONFIG_SYS_VPD_EEPROM_I2C_ADDR)
+	/*
+	 * bootcount is expected to reside at the end of EEPROM
+	 *
+	 * check is hard-wired to the logic of the 24C08 EEPROM 256-bytes
+	 * page-wise (4 pages) i2c_address/bootcount_address structure combined
+	 * with raw I2C access, so the I2C address and offset are combined into:
+	 *
+	 *     i2c_addr = (device_i2c_addr | page),
+	 *     offset = (offset - (page * 256)))
+	 */
+	BUILD_BUG_ON((CONFIG_SYS_BOOTCOUNT_I2C_ADDR & 0x0f) * 256 +
+		     CONFIG_SYS_BOOTCOUNT_ADDR + CONFIG_BOOTCOUNT_I2C_LEN !=
+		     CONFIG_SYS_VPD_EEPROM_SIZE);
+	static const size_t size = CONFIG_SYS_BOOTCOUNT_ADDR;
+#else
 	static const size_t size = CONFIG_SYS_VPD_EEPROM_SIZE;
+#endif
 
 	int res;
 	u8 *data;
configs/ge_bx50v3_defconfig +14 -4
index 829a39e08567..32a9200ea988 100644
@@ -16,6 +16,20 @@ CONFIG_SYS_VPD_EEPROM_I2C_ADDR=0x50
 CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN=1
 CONFIG_SYS_VPD_EEPROM_SIZE=1024
 
+CONFIG_BOOTCOUNT_I2C=y
+CONFIG_BOOTCOUNT_LIMIT=y
+CONFIG_SYS_BOOTCOUNT_I2C_BUS=4
+# bootcount is stored in VPD EEPROM
+# we are using generic driver instead of EEPROM one (while should use it)
+# at the end of VPD EEPROM: (SYS_VPD_EEPROM_SIZE - CONFIG_BOOTCOUNT_I2C_LEN)
+# so, the address is 0x3FE:
+#     ("VPD EEPROM chip address" | "3rd 256-byte page"):
+CONFIG_SYS_BOOTCOUNT_I2C_ADDR=0x53
+#     (+ "offset in the page"):
+CONFIG_SYS_BOOTCOUNT_ADDR=0xfe
+CONFIG_BOOTCOUNT_I2C_LEN=2
+CONFIG_BOOTCOUNT_ALEN=1
+
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_LAST_STAGE_INIT=y
@@ -35,10 +49,6 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_DOS_PARTITION=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_BOOTCOUNT_LIMIT=y
-CONFIG_BOOTCOUNT_EXT=y
-CONFIG_SYS_BOOTCOUNT_EXT_DEVPART="1:5"
-CONFIG_SYS_BOOTCOUNT_ADDR=0x7000A000
 CONFIG_FSL_ESDHC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
configs/mx53ppd_defconfig +15 -4
index 4a7e8eee0df1..43672d88e202 100644
@@ -18,6 +18,21 @@ CONFIG_SYS_VPD_EEPROM_I2C_ADDR=0x50
 CONFIG_SYS_VPD_EEPROM_I2C_ADDR_LEN=1
 CONFIG_SYS_VPD_EEPROM_SIZE=1024
 
+CONFIG_BOOTCOUNT_LIMIT=y
+CONFIG_BOOTCOUNT_I2C=y
+# using bus where monitor's EEPROM is connected to
+CONFIG_SYS_BOOTCOUNT_I2C_BUS=2
+# bootcount is stored in Monitor's VPD EEPROM
+# we are using generic driver instead of EEPROM one (while should use it)
+# at the end of VPD EEPROM: (SYS_VPD_EEPROM_SIZE - CONFIG_BOOTCOUNT_I2C_LEN)
+# so, the address is 0x3FE:
+#     ("VPD EEPROM chip address" | "3rd 256-byte page"):
+CONFIG_SYS_BOOTCOUNT_I2C_ADDR=0x53
+#     (+ "offset in the page"):
+CONFIG_SYS_BOOTCOUNT_ADDR=0xfe
+CONFIG_BOOTCOUNT_I2C_LEN=2
+CONFIG_BOOTCOUNT_ALEN=1
+
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
@@ -33,10 +48,6 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_ENV_IS_IN_MMC=y
-CONFIG_BOOTCOUNT_LIMIT=y
-CONFIG_BOOTCOUNT_EXT=y
-CONFIG_SYS_BOOTCOUNT_EXT_DEVPART="0:5"
-CONFIG_SYS_BOOTCOUNT_ADDR=0x7000A000
 CONFIG_FSL_ESDHC=y
 CONFIG_NETDEVICES=y
 CONFIG_RTC_S35392A=y
include/configs/ge_bx50v3.h +3 -3
index 307ec0101c0a..5576fd33d48d 100644
@@ -118,9 +118,9 @@
 		"setenv stdout vga; " \
 		"echo \"\n\n\n\n    \" $msg; " \
 		"setenv stdout serial; " \
-		"mw.b 0x7000A000 0xbc; " \
-		"mw.b 0x7000A001 0x00; " \
-		"ext4write ${dev} ${devnum}:5 0x7000A000 /boot/failures 2\0" \
+		"i2c dev 4; " \
+		"i2c mw.b 53 fe bc; " \
+		"i2c mw.b 53 ff 00; \0" \
 	"altbootcmd=" \
 		"run doquiet; " \
 		"setenv partnum 1; run hasfirstboot || setenv partnum 2; " \
include/configs/mx53ppd.h +3 -3
index 338f1434f2cc..549efc10c5e9 100644
@@ -130,9 +130,9 @@
 		"setenv stdout vga; " \
 		"echo \"\n\n\n\n    \" $msg; " \
 		"setenv stdout serial; " \
-		"mw.b 0x7000A000 0xbc; " \
-		"mw.b 0x7000A001 0x00; " \
-		"ext4write ${dev} ${devnum}:5 0x7000A000 /boot/failures 2\0" \
+		"i2c dev 2; " \
+		"i2c mw.b 53 fe bc; " \
+		"i2c mw.b 53 ff 00; \0" \
 	"altbootcmd=" \
 		"run doquiet; " \
 		"setenv partnum 1; run hasfirstboot || setenv partnum 2; " \
Signature · 1 line
2.18.0