[12/29] net/sfc/base: support direct FW update for bundle partitions

Message ID 1560152324-20538-13-git-send-email-arybchenko@solarflare.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc/base: update base driver |

Checks

Context Check Description
ci/Intel-compilation fail Compilation issues
ci/checkpatch warning coding style issues

Commit Message

Andrew Rybchenko June 10, 2019, 7:38 a.m. UTC
  From: Richard Houldsworth <rhouldsworth@solarflare.com>

All signed images other than for the MCFW partition should
be written fully to the partition with no rearrangement.

Signed-off-by: Richard Houldsworth <rhouldsworth@solarflare.com>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/net/sfc/base/ef10_image.c | 74 ++++++++++++++++++++++++---------------
 drivers/net/sfc/base/efx.h        |  1 +
 2 files changed, 47 insertions(+), 28 deletions(-)
  

Patch

diff --git a/drivers/net/sfc/base/ef10_image.c b/drivers/net/sfc/base/ef10_image.c
index c035e0d..a19df7f 100644
--- a/drivers/net/sfc/base/ef10_image.c
+++ b/drivers/net/sfc/base/ef10_image.c
@@ -7,6 +7,8 @@ 
 #include "efx.h"
 #include "efx_impl.h"
 
+#include "ef10_firmware_ids.h"
+
 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
 
 #if EFSYS_OPT_IMAGE_LAYOUT
@@ -429,54 +431,59 @@ 
 
 static	__checkReturn	efx_rc_t
 efx_check_unsigned_image(
-	__in		void		*bufferp,
-	__in		uint32_t	buffer_size)
+	__in		void			*bufferp,
+	__in		uint32_t		buffer_size,
+	__out		efx_image_header_t	**headerpp,
+	__out		efx_image_trailer_t	**trailerpp)
 {
-	efx_image_header_t *header;
-	efx_image_trailer_t *trailer;
+	efx_image_header_t *headerp;
+	efx_image_trailer_t *trailerp;
 	uint32_t crc;
 	efx_rc_t rc;
 
-	EFX_STATIC_ASSERT(sizeof (*header) == EFX_IMAGE_HEADER_SIZE);
-	EFX_STATIC_ASSERT(sizeof (*trailer) == EFX_IMAGE_TRAILER_SIZE);
+	EFX_STATIC_ASSERT(sizeof (*headerp) == EFX_IMAGE_HEADER_SIZE);
+	EFX_STATIC_ASSERT(sizeof (*trailerp) == EFX_IMAGE_TRAILER_SIZE);
 
 	/* Must have at least enough space for required image header fields */
 	if (buffer_size < (EFX_FIELD_OFFSET(efx_image_header_t, eih_size) +
-		sizeof (header->eih_size))) {
+		sizeof (headerp->eih_size))) {
 		rc = ENOSPC;
 		goto fail1;
 	}
-	header = (efx_image_header_t *)bufferp;
+	headerp = (efx_image_header_t *)bufferp;
 
-	if (header->eih_magic != EFX_IMAGE_HEADER_MAGIC) {
-		rc = EINVAL;
+	/* Buffer must have space for image header, code and image trailer. */
+	if (buffer_size < (headerp->eih_size + headerp->eih_code_size +
+		EFX_IMAGE_TRAILER_SIZE)) {
+		rc = ENOSPC;
 		goto fail2;
 	}
 
+	trailerp = (efx_image_trailer_t *)((uint8_t *)headerp +
+	    headerp->eih_size + headerp->eih_code_size);
+
+	*headerpp = headerp;
+	*trailerpp = trailerp;
+
+	if (headerp->eih_magic != EFX_IMAGE_HEADER_MAGIC) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
 	/*
 	 * Check image header version is same or higher than lowest required
 	 * version.
 	 */
-	if (header->eih_version < EFX_IMAGE_HEADER_VERSION) {
+	if (headerp->eih_version < EFX_IMAGE_HEADER_VERSION) {
 		rc = EINVAL;
-		goto fail3;
-	}
-
-	/* Buffer must have space for image header, code and image trailer. */
-	if (buffer_size < (header->eih_size + header->eih_code_size +
-		EFX_IMAGE_TRAILER_SIZE)) {
-		rc = ENOSPC;
 		goto fail4;
 	}
 
 	/* Check CRC from image buffer matches computed CRC. */
-	trailer = (efx_image_trailer_t *)((uint8_t *)header +
-	    header->eih_size + header->eih_code_size);
+	crc = efx_crc32_calculate(0, (uint8_t *)headerp,
+	    (headerp->eih_size + headerp->eih_code_size));
 
-	crc = efx_crc32_calculate(0, (uint8_t *)header,
-	    (header->eih_size + header->eih_code_size));
-
-	if (trailer->eit_crc != crc) {
+	if (trailerp->eit_crc != crc) {
 		rc = EINVAL;
 		goto fail5;
 	}
@@ -507,9 +514,10 @@ 
 	uint32_t image_offset;
 	uint32_t image_size;
 	void *imagep;
+	efx_image_header_t *headerp;
+	efx_image_trailer_t *trailerp;
 	efx_rc_t rc;
 
-
 	EFSYS_ASSERT(infop != NULL);
 	if (infop == NULL) {
 		rc = EINVAL;
@@ -531,7 +539,7 @@ 
 	if (rc == 0) {
 		/*
 		 * Buffer holds signed image format. Check that the encapsulated
-		 * content is in unsigned image format.
+		 * content contains an unsigned image format header.
 		 */
 		format = EFX_IMAGE_FORMAT_SIGNED;
 	} else {
@@ -546,11 +554,21 @@ 
 	}
 	imagep = (uint8_t *)bufferp + image_offset;
 
-	/* Check unsigned image layout (image header, code, image trailer) */
-	rc = efx_check_unsigned_image(imagep, image_size);
+	/* Check image layout (image header, code, image trailer) */
+	rc = efx_check_unsigned_image(imagep, image_size, &headerp, &trailerp);
 	if (rc != 0)
 		goto fail4;
 
+	/*
+	 * Signed images are packages consumed directly by the firmware,
+	 * with the exception of MC firmware, where the image must be
+	 * rearranged for booting purposes.
+	 */
+	if (format == EFX_IMAGE_FORMAT_SIGNED) {
+		if (headerp->eih_type != FIRMWARE_TYPE_MCFW)
+			format = EFX_IMAGE_FORMAT_SIGNED_PACKAGE;
+	}
+
 	/* Return image details */
 	infop->eii_format = format;
 	infop->eii_imagep = bufferp;
diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h
index 4905918..d46e650 100644
--- a/drivers/net/sfc/base/efx.h
+++ b/drivers/net/sfc/base/efx.h
@@ -1889,6 +1889,7 @@  enum {
 	EFX_IMAGE_FORMAT_INVALID,
 	EFX_IMAGE_FORMAT_UNSIGNED,
 	EFX_IMAGE_FORMAT_SIGNED,
+	EFX_IMAGE_FORMAT_SIGNED_PACKAGE
 } efx_image_format_t;
 
 typedef struct efx_image_info_s {