ARMv8/sec_firmware : Update chosen/kaslr-seed with random number
kASLR support in kernel requires a random number to be passed via
chosen/kaslr-seed propert. sec_firmware generates this random seed
which can then be passed in the device tree node.
sec_firmware reserves JR3 for it's own usage. Node for JR3 is
removed from device-tree.
Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c
index fffce71..0e74834 100644
--- a/arch/arm/cpu/armv8/sec_firmware.c
+++ b/arch/arm/cpu/armv8/sec_firmware.c
@@ -232,6 +232,59 @@
#endif
/*
+ * Check with sec_firmware if it supports random number generation
+ * via HW RNG
+ *
+ * The return value will be true if it is supported
+ */
+bool sec_firmware_support_hwrng(void)
+{
+ uint8_t rand[8];
+ if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) {
+ if (!sec_firmware_get_random(rand, 8))
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * sec_firmware_get_random - Get a random number from SEC Firmware
+ * @rand: random number buffer to be filled
+ * @bytes: Number of bytes of random number to be supported
+ * @eret: -1 in case of error, 0 for success
+ */
+int sec_firmware_get_random(uint8_t *rand, int bytes)
+{
+ unsigned long long num;
+ struct pt_regs regs;
+ int param1;
+
+ if (!bytes || bytes > 8) {
+ printf("Max Random bytes genration supported is 8\n");
+ return -1;
+ }
+#define SIP_RNG_64 0xC200FF11
+ regs.regs[0] = SIP_RNG_64;
+
+ if (bytes <= 4)
+ param1 = 0;
+ else
+ param1 = 1;
+ regs.regs[1] = param1;
+
+ smc_call(®s);
+
+ if (regs.regs[0])
+ return -1;
+
+ num = regs.regs[1];
+ memcpy(rand, &num, bytes);
+
+ return 0;
+}
+
+/*
* sec_firmware_init - Initialize the SEC Firmware
* @sec_firmware_img: the SEC Firmware image address
* @eret_hold_l: the address to hold exception return address low
@@ -278,3 +331,49 @@
return 0;
}
+
+/*
+ * fdt_fix_kaslr - Add kalsr-seed node in Device tree
+ * @fdt: Device tree
+ * @eret: 0 in case of error, 1 for success
+ */
+int fdt_fixup_kaslr(void *fdt)
+{
+ int nodeoffset;
+ int err, ret = 0;
+ u8 rand[8];
+
+#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT)
+ /* Check if random seed generation is supported */
+ if (sec_firmware_support_hwrng() == false)
+ return 0;
+
+ ret = sec_firmware_get_random(rand, 8);
+ if (ret < 0) {
+ printf("WARNING: No random number to set kaslr-seed\n");
+ return 0;
+ }
+
+ err = fdt_check_header(fdt);
+ if (err < 0) {
+ printf("fdt_chosen: %s\n", fdt_strerror(err));
+ return 0;
+ }
+
+ /* find or create "/chosen" node. */
+ nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+ if (nodeoffset < 0)
+ return 0;
+
+ err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand,
+ sizeof(rand));
+ if (err < 0) {
+ printf("WARNING: can't set kaslr-seed %s.\n",
+ fdt_strerror(err));
+ return 0;
+ }
+ ret = 1;
+#endif
+
+ return ret;
+}