feat(hikey960): read serial number from UFS

Serial number is written into UFS by fastboot
Pass BL2 params to BL31 (serial number)

Change-Id: I9a490db07ca10088da69191a2f2c1621d44a278c
Signed-off-by: vallau01 <valentin.laurent@trustonic.com>
Signed-off-by: Lukas Hanel <lukas.hanel@trustonic.com>
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
index c1c2a8c..7334853 100644
--- a/plat/hisilicon/hikey960/hikey960_bl2_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -31,6 +31,9 @@
 
 #define BL2_RW_BASE		(BL_CODE_END)
 
+/* BL2 platform parameters passed to BL31 */
+static plat_params_from_bl2_t plat_params_from_bl2;
+
 static meminfo_t bl2_el3_tzram_layout;
 static console_t console;
 extern int load_lpm3(void);
@@ -217,6 +220,11 @@
 	assert(bl_mem_params);
 
 	switch (image_id) {
+	case BL31_IMAGE_ID:
+		/* Pass BL2 platform parameter to BL31 */
+		bl_mem_params->ep_info.args.arg1 = (uint64_t) &plat_params_from_bl2;
+		break;
+
 #ifdef __aarch64__
 	case BL32_IMAGE_ID:
 #ifdef SPD_opteed
@@ -307,6 +315,8 @@
 
 void bl2_platform_setup(void)
 {
+	int ret;
+
 	/* disable WDT0 */
 	if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) {
 		mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK);
@@ -322,4 +332,13 @@
 	hikey960_gpio_init();
 	hikey960_init_ufs();
 	hikey960_io_setup();
+
+	/* Read serial number from storage */
+	plat_params_from_bl2.fastboot_serno = 0;
+	ret = hikey960_load_serialno(&plat_params_from_bl2.fastboot_serno);
+	if (ret != 0) {
+		ERROR("BL2: could not read serial number\n");
+	}
+	INFO("BL2: fastboot_serno %lx\n", plat_params_from_bl2.fastboot_serno);
+	flush_dcache_range((uintptr_t)&plat_params_from_bl2, sizeof(plat_params_from_bl2_t));
 }
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index 49918ef..0debe1e 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -33,6 +33,9 @@
 static entry_point_info_t bl33_ep_info;
 static console_t console;
 
+/* fastboot serial number consumed by Kinibi SPD/LP for gpd.tee.deviceID. */
+uint64_t fastboot_serno;
+
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
  * interrupts.
@@ -73,6 +76,7 @@
 {
 	unsigned int id, uart_base;
 	void *from_bl2;
+	plat_params_from_bl2_t *plat_params_from_bl2 = (plat_params_from_bl2_t *) arg1;
 
 	from_bl2 = (void *) arg0;
 
@@ -91,6 +95,10 @@
 	cci_init(CCI400_REG_BASE, cci_map, ARRAY_SIZE(cci_map));
 	cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
 
+	/* Fastboot serial number passed from BL2 as a platform parameter */
+	fastboot_serno = plat_params_from_bl2->fastboot_serno;
+	INFO("BL31: fastboot_serno %lx\n", fastboot_serno);
+
 	/*
 	 * Check params passed from BL2 should not be NULL,
 	 */
diff --git a/plat/hisilicon/hikey960/hikey960_io_storage.c b/plat/hisilicon/hikey960/hikey960_io_storage.c
index 883085b..475e416 100644
--- a/plat/hisilicon/hikey960/hikey960_io_storage.c
+++ b/plat/hisilicon/hikey960/hikey960_io_storage.c
@@ -23,6 +23,9 @@
 #include <lib/semihosting.h>
 #include <tools_share/firmware_image_package.h>
 
+#include "hikey960_def.h"
+#include "hikey960_private.h"
+
 struct plat_io_policy {
 	uintptr_t *dev_handle;
 	uintptr_t image_spec;
@@ -45,6 +48,12 @@
 			  (PLAT_PARTITION_MAX_ENTRIES / 4 + 2),
 };
 
+/* Fastboot serial number stored within first UFS device blocks */
+static const io_block_spec_t ufs_fastboot_spec = {
+	.offset         = UFS_BASE,
+	.length         = 1 << 20,
+};
+
 static const io_block_dev_spec_t ufs_dev_spec = {
 	/* It's used as temp buffer in block driver. */
 	.buffer		= {
@@ -253,6 +262,54 @@
 			io_close(local_image_handle);
 		}
 	}
+	return result;
+}
+
+int hikey960_load_serialno(uint64_t *serno)
+{
+	int result;
+	size_t len = 0;
+	uintptr_t local_handle;
+	uint64_t buf[HIKEY960_SERIAL_NUMBER_SIZE / sizeof(uint64_t)];
+
+	if (serno == NULL) {
+		return -1;
+	}
+
+	result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
+	if (result != 0) {
+		return result;
+	}
+
+	result = io_open(ufs_dev_handle,
+		(uintptr_t)&ufs_fastboot_spec, &local_handle);
+	if (result != 0) {
+		return result;
+	}
+
+	result = io_seek(local_handle, IO_SEEK_SET,
+		HIKEY960_SERIAL_NUMBER_LBA * UFS_BLOCK_SIZE);
+	if (result != 0) {
+		goto closing;
+	}
+
+	result = io_read(local_handle, (uintptr_t)buf,
+		HIKEY960_SERIAL_NUMBER_SIZE, &len);
+	if (result != 0) {
+		goto closing;
+	}
+
+	if (len != HIKEY960_SERIAL_NUMBER_SIZE) {
+		result = -1;
+		goto closing;
+	}
+
+	/* UEFI fastboot app stores a 16 bytes blob       */
+	/* We extract only relevant 8 bytes serial number */
+	*serno = buf[1];
+
+closing:
+	io_close(local_handle);
 	return result;
 }
 
diff --git a/plat/hisilicon/hikey960/hikey960_private.h b/plat/hisilicon/hikey960/hikey960_private.h
index 54bf501..742725c 100644
--- a/plat/hisilicon/hikey960/hikey960_private.h
+++ b/plat/hisilicon/hikey960/hikey960_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,10 @@
 
 #include <common/bl_common.h>
 
+/* Fastboot serial number */
+#define HIKEY960_SERIAL_NUMBER_LBA	(UFS_BASE + 20)
+#define HIKEY960_SERIAL_NUMBER_SIZE	16
+
 /*
  * Function and variable prototypes
  */
@@ -27,6 +31,7 @@
 void hikey960_io_setup(void);
 int hikey960_read_boardid(unsigned int *id);
 int hikey960_set_fip_addr(unsigned int image_id, const char *name);
+int hikey960_load_serialno(uint64_t *serno);
 void hikey960_clk_init(void);
 void hikey960_pmu_init(void);
 void hikey960_regulator_enable(void);
@@ -39,4 +44,12 @@
 void clr_ex(void);
 void nop(void);
 
+/*******************************************************************************
+ * Struct for parameters received from BL2
+ ******************************************************************************/
+typedef struct plat_params_from_bl2 {
+	/* Fastboot serial number gathered from UFS */
+	uint64_t fastboot_serno;
+} plat_params_from_bl2_t;
+
 #endif /* HIKEY960_PRIVATE_H */