[Skiboot] [PATCH V6 01/21] hw: Move lpc firmware space helpers

Abhishek SIngh Tomar abhishek at linux.ibm.com
Thu Sep 29 16:20:46 AEST 2022


On Tue, Sep 13, 2022 at 12:26:45PM +0200, Christophe Lombard wrote:
> Add new lpc helpers for doing a bulk io to firmware space.
> 
> Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
Reviewed-by: Abhishek Singh Tomar <abhishek at linux.ibm.com>
> ---
>  hw/lpc.c                         | 74 ++++++++++++++++++++++++++++++++
>  include/lpc.h                    |  6 +++
>  libflash/ipmi-hiomap.c           | 66 +---------------------------
>  libflash/mbox-flash.c            | 64 +--------------------------
>  libflash/test/mbox-server.c      | 68 +++++++++++++++++++++++++++++
>  libflash/test/test-ipmi-hiomap.c | 66 ++++++++++++++++++++++++++++
>  6 files changed, 218 insertions(+), 126 deletions(-)
> 
> diff --git a/hw/lpc.c b/hw/lpc.c
> index bf3ab1fa..caaacc46 100644
> --- a/hw/lpc.c
> +++ b/hw/lpc.c
> @@ -667,6 +667,80 @@ int64_t lpc_probe_read(enum OpalLPCAddressType addr_type, uint32_t addr,
>  	return __lpc_read_sanity(addr_type, addr, data, sz, true);
>  }
> 
> +int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len)
> +{
> +	int rc;
> +
> +	prlog(PR_TRACE, "Reading 0x%08x bytes at FW offset 0x%08x\n",
> +	      len, off);
> +
> +	while (len) {
> +		uint32_t chunk;
> +		uint32_t dat;
> +
> +		/* XXX: make this read until it's aligned */
> +		if (len > 3 && !(off & 3)) {
> +			rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
> +			if (!rc) {
> +				/*
> +				 * lpc_read swaps to CPU endian but it's not
> +				 * really a 32-bit value, so convert back.
> +				 */
> +				*(__be32 *)buf = cpu_to_be32(dat);
> +			}
> +			chunk = 4;
> +		} else {
> +			rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
> +			if (!rc)
> +				*(uint8_t *)buf = dat;
> +			chunk = 1;
> +		}
> +		if (rc) {
> +			prlog(PR_ERR, "lpc_read failure %d to FW 0x%08x\n", rc, off);
> +			return rc;
> +		}
> +		len -= chunk;
> +		off += chunk;
> +		buf += chunk;
> +	}
> +
> +	return 0;
> +}
> +
> +int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len)
> +{
> +	int rc;
> +
> +	prlog(PR_TRACE, "Writing 0x%08x bytes at FW offset 0x%08x\n",
> +	      len, off);
> +
> +	while (len) {
> +		uint32_t chunk;
> +
> +		if (len > 3 && !(off & 3)) {
> +			/* endian swap: see lpc_window_write */
> +			uint32_t dat = be32_to_cpu(*(__be32 *)buf);
> +
> +			rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
> +			chunk = 4;
> +		} else {
> +			uint8_t dat = *(uint8_t *)buf;
> +
> +			rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
> +			chunk = 1;
> +		}
> +		if (rc) {
> +			prlog(PR_ERR, "lpc_write failure %d to FW 0x%08x\n", rc, off);
> +			return rc;
> +		}
> +		len -= chunk;
> +		off += chunk;
> +		buf += chunk;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * The "OPAL" variant add the emulation of 2 and 4 byte accesses using
>   * byte accesses for IO and MEM space in order to be compatible with
> diff --git a/include/lpc.h b/include/lpc.h
> index b641aa4e..ce9c33dc 100644
> --- a/include/lpc.h
> +++ b/include/lpc.h
> @@ -102,6 +102,12 @@ extern int64_t lpc_probe_write(enum OpalLPCAddressType addr_type, uint32_t addr,
>  extern int64_t lpc_probe_read(enum OpalLPCAddressType addr_type, uint32_t addr,
>  			      uint32_t *data, uint32_t sz);
> 
> +/*
> + * helpers for doing a bulk io to firmware space.
> + */
> +extern int64_t lpc_fw_read(uint32_t addr, void *buf, uint32_t sz);
> +extern int64_t lpc_fw_write(uint32_t addr, const void *buf, uint32_t sz);
> +
>  /* Mark LPC bus as used by console */
>  extern void lpc_used_by_console(void);
> 
> diff --git a/libflash/ipmi-hiomap.c b/libflash/ipmi-hiomap.c
> index 29355d66..93aaef45 100644
> --- a/libflash/ipmi-hiomap.c
> +++ b/libflash/ipmi-hiomap.c
> @@ -555,45 +555,11 @@ static int lpc_window_read(struct ipmi_hiomap *ctx, uint32_t pos,
>  			   void *buf, uint32_t len)
>  {
>  	uint32_t off = ctx->current.lpc_addr + (pos - ctx->current.cur_pos);
> -	int rc;
> 
>  	if ((ctx->current.lpc_addr + ctx->current.size) < (off + len))
>  		return FLASH_ERR_PARM_ERROR;
> 
> -	prlog(PR_TRACE, "Reading at 0x%08x for 0x%08x offset: 0x%08x\n",
> -	      pos, len, off);
> -
> -	while(len) {
> -		uint32_t chunk;
> -		uint32_t dat;
> -
> -		/* XXX: make this read until it's aligned */
> -		if (len > 3 && !(off & 3)) {
> -			rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
> -			if (!rc) {
> -				/*
> -				 * lpc_read swaps to CPU endian but it's not
> -				 * really a 32-bit value, so convert back.
> -				 */
> -				*(__be32 *)buf = cpu_to_be32(dat);
> -			}
> -			chunk = 4;
> -		} else {
> -			rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
> -			if (!rc)
> -				*(uint8_t *)buf = dat;
> -			chunk = 1;
> -		}
> -		if (rc) {
> -			prlog(PR_ERR, "lpc_read failure %d to FW 0x%08x\n", rc, off);
> -			return rc;
> -		}
> -		len -= chunk;
> -		off += chunk;
> -		buf += chunk;
> -	}
> -
> -	return 0;
> +	return lpc_fw_read(off, buf, len);
>  }
> 
>  static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
> @@ -601,7 +567,6 @@ static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
>  {
>  	uint32_t off = ctx->current.lpc_addr + (pos - ctx->current.cur_pos);
>  	enum lpc_window_state state;
> -	int rc;
> 
>  	lock(&ctx->lock);
>  	state = ctx->window_state;
> @@ -613,34 +578,7 @@ static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
>  	if ((ctx->current.lpc_addr + ctx->current.size) < (off + len))
>  		return FLASH_ERR_PARM_ERROR;
> 
> -	prlog(PR_TRACE, "Writing at 0x%08x for 0x%08x offset: 0x%08x\n",
> -	      pos, len, off);
> -
> -	while(len) {
> -		uint32_t chunk;
> -
> -		if (len > 3 && !(off & 3)) {
> -			/* endian swap: see lpc_window_read */
> -			uint32_t dat = be32_to_cpu(*(__be32 *)buf);
> -
> -			rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
> -			chunk = 4;
> -		} else {
> -			uint8_t dat = *(uint8_t *)buf;
> -
> -			rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
> -			chunk = 1;
> -		}
> -		if (rc) {
> -			prlog(PR_ERR, "lpc_write failure %d to FW 0x%08x\n", rc, off);
> -			return rc;
> -		}
> -		len -= chunk;
> -		off += chunk;
> -		buf += chunk;
> -	}
> -
> -	return 0;
> +	return lpc_fw_write(off, buf, len);
>  }
> 
>  /* Best-effort asynchronous event handling by blocklevel callbacks */
> diff --git a/libflash/mbox-flash.c b/libflash/mbox-flash.c
> index 4c20f15f..9e686c97 100644
> --- a/libflash/mbox-flash.c
> +++ b/libflash/mbox-flash.c
> @@ -147,79 +147,19 @@ static int lpc_window_read(struct mbox_flash_data *mbox_flash, uint32_t pos,
>  			   void *buf, uint32_t len)
>  {
>  	uint32_t off = mbox_flash->read.lpc_addr + (pos - mbox_flash->read.cur_pos);
> -	int rc;
> 
>  	prlog(PR_TRACE, "Reading at 0x%08x for 0x%08x offset: 0x%08x\n",
>  			pos, len, off);
> 
> -	while(len) {
> -		uint32_t chunk;
> -		uint32_t dat;
> -
> -		/* XXX: make this read until it's aligned */
> -		if (len > 3 && !(off & 3)) {
> -			rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
> -			if (!rc) {
> -				/*
> -				 * lpc_read swaps to CPU endian but it's not
> -				 * really a 32-bit value, so convert back.
> -				 */
> -				*(__be32 *)buf = cpu_to_be32(dat);
> -			}
> -			chunk = 4;
> -		} else {
> -			rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
> -			if (!rc)
> -				*(uint8_t *)buf = dat;
> -			chunk = 1;
> -		}
> -		if (rc) {
> -			prlog(PR_ERR, "lpc_read failure %d to FW 0x%08x\n", rc, off);
> -			return rc;
> -		}
> -		len -= chunk;
> -		off += chunk;
> -		buf += chunk;
> -	}
> -
> -	return 0;
> +	return lpc_fw_read(off, buf, len);
>  }
> 
>  static int lpc_window_write(struct mbox_flash_data *mbox_flash, uint32_t pos,
>  			    const void *buf, uint32_t len)
>  {
>  	uint32_t off = mbox_flash->write.lpc_addr + (pos - mbox_flash->write.cur_pos);
> -	int rc;
> -
> -
> -	prlog(PR_TRACE, "Writing at 0x%08x for 0x%08x offset: 0x%08x\n",
> -			pos, len, off);
> -
> -	while(len) {
> -		uint32_t chunk;
> -
> -		if (len > 3 && !(off & 3)) {
> -			/* endian swap: see lpc_window_read */
> -			uint32_t dat = be32_to_cpu(*(__be32 *)buf);
> -
> -			rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
> -			chunk = 4;
> -		} else {
> -			uint8_t dat = *(uint8_t *)buf;
> -
> -			rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
> -			chunk = 1;
> -		}
> -		if (rc) {
> -			prlog(PR_ERR, "lpc_write failure %d to FW 0x%08x\n", rc, off);
> -			return rc;
> -		}
> -		len -= chunk;
> -		off += chunk;
> -		buf += chunk;
> -	}
> 
> -	return 0;
> +	return lpc_fw_write(off, buf, len);
>  }
> 
>  static uint64_t mbox_flash_mask(struct mbox_flash_data *mbox_flash)
> diff --git a/libflash/test/mbox-server.c b/libflash/test/mbox-server.c
> index 8a68cfff..053be989 100644
> --- a/libflash/test/mbox-server.c
> +++ b/libflash/test/mbox-server.c
> @@ -142,6 +142,74 @@ int64_t lpc_write(enum OpalLPCAddressType __unused addr_type, uint32_t addr,
>  	return 0;
>  }
> 
> +int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len);
> +int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len)
> +{
> +	int rc;
> +
> +	while (len) {
> +		uint32_t chunk;
> +		uint32_t dat;
> +
> +		/* XXX: make this read until it's aligned */
> +		if (len > 3 && !(off & 3)) {
> +			rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
> +			if (!rc) {
> +				/*
> +				 * lpc_read swaps to CPU endian but it's not
> +				 * really a 32-bit value, so convert back.
> +				 */
> +				*(__be32 *)buf = cpu_to_be32(dat);
> +			}
> +			chunk = 4;
> +		} else {
> +			rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
> +			if (!rc)
> +				*(uint8_t *)buf = dat;
> +			chunk = 1;
> +		}
> +		if (rc)
> +			return rc;
> +
> +		len -= chunk;
> +		off += chunk;
> +		buf += chunk;
> +	}
> +
> +	return 0;
> +}
> +
> +int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len);
> +int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len)
> +{
> +	int rc;
> +
> +	while (len) {
> +		uint32_t chunk;
> +
> +		if (len > 3 && !(off & 3)) {
> +			/* endian swap: see lpc_window_write */
> +			uint32_t dat = be32_to_cpu(*(__be32 *)buf);
> +
> +			rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
> +			chunk = 4;
> +		} else {
> +			uint8_t dat = *(uint8_t *)buf;
> +
> +			rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
> +			chunk = 1;
> +		}
> +		if (rc)
> +			return rc;
> +
> +		len -= chunk;
> +		off += chunk;
> +		buf += chunk;
> +	}
> +
> +	return 0;
> +}
> +
>  int bmc_mbox_register_attn(mbox_attn_cb handler, void *drv_data)
>  {
>  	mbox_data.attn = handler;
> diff --git a/libflash/test/test-ipmi-hiomap.c b/libflash/test/test-ipmi-hiomap.c
> index 6117e9dd..b740a6f2 100644
> --- a/libflash/test/test-ipmi-hiomap.c
> +++ b/libflash/test/test-ipmi-hiomap.c
> @@ -223,6 +223,72 @@ int64_t lpc_read(enum OpalLPCAddressType addr_type __attribute__((unused)),
>  	return 0;
>  }
> 
> +int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len)
> +{
> +	int rc;
> +
> +	while (len) {
> +		uint32_t chunk;
> +		uint32_t dat;
> +
> +		/* XXX: make this read until it's aligned */
> +		if (len > 3 && !(off & 3)) {
> +			rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
> +			if (!rc) {
> +				/*
> +				 * lpc_read swaps to CPU endian but it's not
> +				 * really a 32-bit value, so convert back.
> +				 */
> +				*(__be32 *)buf = cpu_to_be32(dat);
> +			}
> +			chunk = 4;
> +		} else {
> +			rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
> +			if (!rc)
> +				*(uint8_t *)buf = dat;
> +			chunk = 1;
> +		}
> +		if (rc)
> +			return rc;
> +
> +		len -= chunk;
> +		off += chunk;
> +		buf += chunk;
> +	}
> +
> +	return 0;
> +}
> +
> +int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len)
> +{
> +	int rc;
> +
> +	while (len) {
> +		uint32_t chunk;
> +
> +		if (len > 3 && !(off & 3)) {
> +			/* endian swap: see lpc_window_write */
> +			uint32_t dat = be32_to_cpu(*(__be32 *)buf);
> +
> +			rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
> +			chunk = 4;
> +		} else {
> +			uint8_t dat = *(uint8_t *)buf;
> +
> +			rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
> +			chunk = 1;
> +		}
> +		if (rc)
> +			return rc;
> +
> +		len -= chunk;
> +		off += chunk;
> +		buf += chunk;
> +	}
> +
> +	return 0;
> +}
> +
>  static bool lpc_read_success(const uint8_t *buf, size_t len)
>  {
>  	if (len < 64) {
> -- 
> 2.37.3
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot


More information about the Skiboot mailing list