blob: f8c8674f874c60e2858922f196959c2ec6c68486 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +05302/*
3 * (C) Copyright 2018 Xilinx, Inc.
4 * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +05305 */
6
7#include <common.h>
8#include <malloc.h>
9#include <asm/arch/sys_proto.h>
10#include <asm/io.h>
11
Vipul Kumar95a3f872018-07-11 15:18:28 +053012static int do_zynqmp_verify_secure(cmd_tbl_t *cmdtp, int flag, int argc,
13 char * const argv[])
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +053014{
Vipul Kumar95a3f872018-07-11 15:18:28 +053015 u64 src_addr, addr;
16 u32 len, src_lo, src_hi;
17 u8 *key_ptr = NULL;
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +053018 int ret;
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +053019 u32 key_lo = 0;
20 u32 key_hi = 0;
21 u32 ret_payload[PAYLOAD_ARG_CNT];
Vipul Kumar95a3f872018-07-11 15:18:28 +053022
23 if (argc < 4)
24 return CMD_RET_USAGE;
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +053025
Vipul Kumar95a3f872018-07-11 15:18:28 +053026 src_addr = simple_strtoull(argv[2], NULL, 16);
27 len = simple_strtoul(argv[3], NULL, 16);
28
29 if (argc == 5)
30 key_ptr = (uint8_t *)(uintptr_t)simple_strtoull(argv[4],
31 NULL, 16);
32
33 if ((ulong)src_addr != ALIGN((ulong)src_addr,
34 CONFIG_SYS_CACHELINE_SIZE)) {
35 printf("Failed: source address not aligned:%lx\n",
36 (ulong)src_addr);
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +053037 return -EINVAL;
38 }
39
Vipul Kumar95a3f872018-07-11 15:18:28 +053040 src_lo = lower_32_bits((ulong)src_addr);
41 src_hi = upper_32_bits((ulong)src_addr);
42 flush_dcache_range((ulong)src_addr, (ulong)(src_addr + len));
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +053043
44 if (key_ptr) {
45 key_lo = lower_32_bits((ulong)key_ptr);
46 key_hi = upper_32_bits((ulong)key_ptr);
47 flush_dcache_range((ulong)key_ptr,
48 (ulong)(key_ptr + KEY_PTR_LEN));
49 }
50
51 ret = invoke_smc(ZYNQMP_SIP_SVC_PM_SECURE_IMG_LOAD, src_lo, src_hi,
52 key_lo, key_hi, ret_payload);
53 if (ret) {
54 printf("Failed: secure op status:0x%x\n", ret);
55 } else {
56 addr = (u64)ret_payload[1] << 32 | ret_payload[2];
57 printf("Verified image at 0x%llx\n", addr);
58 env_set_hex("zynqmp_verified_img_addr", addr);
59 }
60
61 return ret;
62}
63
Vipul Kumar869ed8c2018-07-16 18:04:22 +053064static int do_zynqmp_mmio_read(cmd_tbl_t *cmdtp, int flag, int argc,
65 char * const argv[])
66{
67 u32 read_val, addr;
68 int ret;
69
70 if (argc != cmdtp->maxargs)
71 return CMD_RET_USAGE;
72
73 addr = simple_strtoul(argv[2], NULL, 16);
74
75 ret = zynqmp_mmio_read(addr, &read_val);
76 if (!ret)
77 printf("mmio read value at 0x%x = 0x%x\n",
78 addr, read_val);
79 else
80 printf("Failed: mmio read\n");
81
82 return ret;
83}
84
85static int do_zynqmp_mmio_write(cmd_tbl_t *cmdtp, int flag, int argc,
86 char * const argv[])
87{
88 u32 addr, mask, val;
89 int ret;
90
91 if (argc != cmdtp->maxargs)
92 return CMD_RET_USAGE;
93
94 addr = simple_strtoul(argv[2], NULL, 16);
95 mask = simple_strtoul(argv[3], NULL, 16);
96 val = simple_strtoul(argv[4], NULL, 16);
97
98 ret = zynqmp_mmio_write(addr, mask, val);
99 if (ret != 0)
100 printf("Failed: mmio write\n");
101
102 return ret;
103}
104
Vipul Kumar95a3f872018-07-11 15:18:28 +0530105static cmd_tbl_t cmd_zynqmp_sub[] = {
106 U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""),
Vipul Kumar869ed8c2018-07-16 18:04:22 +0530107 U_BOOT_CMD_MKENT(mmio_read, 3, 0, do_zynqmp_mmio_read, "", ""),
108 U_BOOT_CMD_MKENT(mmio_write, 5, 0, do_zynqmp_mmio_write, "", ""),
Vipul Kumar95a3f872018-07-11 15:18:28 +0530109};
110
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530111/**
112 * do_zynqmp - Handle the "zynqmp" command-line command
113 * @cmdtp: Command data struct pointer
114 * @flag: Command flag
115 * @argc: Command-line argument count
116 * @argv: Array of command-line arguments
117 *
118 * Processes the zynqmp specific commands
119 *
120 * Return: return 0 on success and CMD_RET_USAGE incase of misuse and error
121 */
122static int do_zynqmp(cmd_tbl_t *cmdtp, int flag, int argc,
123 char *const argv[])
124{
Vipul Kumar95a3f872018-07-11 15:18:28 +0530125 cmd_tbl_t *c;
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530126
Vipul Kumar95a3f872018-07-11 15:18:28 +0530127 if (argc < 2)
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530128 return CMD_RET_USAGE;
129
Vipul Kumar95a3f872018-07-11 15:18:28 +0530130 c = find_cmd_tbl(argv[1], &cmd_zynqmp_sub[0],
131 ARRAY_SIZE(cmd_zynqmp_sub));
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530132
Vipul Kumar95a3f872018-07-11 15:18:28 +0530133 if (c)
134 return c->cmd(c, flag, argc, argv);
135 else
136 return CMD_RET_USAGE;
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530137}
138
139/***************************************************/
140#ifdef CONFIG_SYS_LONGHELP
141static char zynqmp_help_text[] =
142 "secure src len [key_addr] - verifies secure images of $len bytes\n"
143 " long at address $src. Optional key_addr\n"
144 " can be specified if user key needs to\n"
Vipul Kumar869ed8c2018-07-16 18:04:22 +0530145 " be used for decryption\n"
146 "zynqmp mmio_read address - read from address\n"
147 "zynqmp mmio_write address mask value - write value after masking to\n"
148 " address\n";
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530149#endif
150
151U_BOOT_CMD(
152 zynqmp, 5, 1, do_zynqmp,
Vipul Kumar95a3f872018-07-11 15:18:28 +0530153 "ZynqMP sub-system",
Siva Durga Prasad Paladugub1acb652018-02-28 13:26:53 +0530154 zynqmp_help_text
155)