1 // SPDX-License-Identifier: GPL-2.0+
2 /**
3 * ufs.c - UFS specific U-boot commands
4 *
5 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
6 *
7 */
8 #include <common.h>
9 #include <command.h>
10 #include <console.h>
11 #include <ufs.h>
12
13 #ifdef CONFIG_ROCKCHIP_UFS_RPMB
14 int ufs_rpmb_blk_read(char *blk_data, uint8_t *key, uint16_t blk_index, uint16_t block_count);
15 int ufs_rpmb_blk_write(char *write_data, uint8_t *key, uint16_t blk_index, uint16_t blk_count);
16 int check_ufs_rpmb_key(uint8_t *package, int package_size);
17 int ufs_rpmb_write_key(uint8_t * key, uint8_t len);
18 uint32_t ufs_rpmb_read_writecount(void);
19 /* @retrun 0 rpmb key unwritten */
20 int is_wr_ufs_rpmb_key(void);
21 int prepare_rpmb_lu(void);
22
23 #define RPMB_KEY_SIZE 32
24 char rpmb_test_key[RPMB_KEY_SIZE] =
25 {
26 '0', '1', '2', '3', '4', '5', '6', '7',
27 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
28 '0', '1', '2', '3', '4', '5', '6', '7',
29 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
30 };
31
confirm_key_prog(char * key_addr)32 static int confirm_key_prog(char *key_addr)
33 {
34 int i;
35
36 printf("\nProgram key data is:\n");
37 for (i = 0; i < 32; i++) {
38 printf("%2x ", key_addr[i]);
39 if (i == 15)
40 printf("\n");
41 }
42
43 puts("\nWarning: Programming authentication key can be done only once !\n"
44 " Use this command only if you are sure of what you are doing,\n"
45 "Really perform the key programming? <y/N> ");
46 if (confirm_yesno())
47 return 1;
48
49 puts("Authentication key programming aborted\n");
50 return 0;
51 }
52
do_ufs_rpmb_key(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])53 static int do_ufs_rpmb_key(cmd_tbl_t *cmdtp, int flag,
54 int argc, char * const argv[])
55 {
56 void *key_addr;
57
58 if (argc != 2)
59 return CMD_RET_USAGE;
60
61 key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
62 if (!key_addr)
63 key_addr = rpmb_test_key;
64
65 if (!confirm_key_prog(key_addr))
66 return CMD_RET_FAILURE;
67
68 if (ufs_rpmb_write_key(key_addr, RPMB_KEY_SIZE)) {
69 printf("ERROR - Key already programmed ?\n");
70 return CMD_RET_FAILURE;
71 }
72
73 return CMD_RET_SUCCESS;
74 }
75
do_ufs_rpmb_read(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])76 static int do_ufs_rpmb_read(cmd_tbl_t *cmdtp, int flag,
77 int argc, char * const argv[])
78 {
79 u16 blk, cnt;
80 void *addr;
81 int n;
82 void *key_addr = NULL;
83
84 if (argc < 4)
85 return CMD_RET_USAGE;
86
87 addr = (void *)simple_strtoul(argv[1], NULL, 16);
88 blk = simple_strtoul(argv[2], NULL, 16);
89 cnt = simple_strtoul(argv[3], NULL, 16);
90
91 if (argc == 5) {
92 key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
93 if (!key_addr)
94 key_addr = rpmb_test_key;
95 }
96
97 printf("\nMMC RPMB read: block # %d, count %d ... \n", blk, cnt);
98 n = ufs_rpmb_blk_read(addr, key_addr, blk, cnt);
99
100 printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
101 if (n != cnt)
102 return CMD_RET_FAILURE;
103
104 return CMD_RET_SUCCESS;
105 }
106
do_ufs_rpmb_write(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])107 static int do_ufs_rpmb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
108 {
109 u16 blk, cnt;
110 void *addr;
111 int n;
112 void *key_addr;
113
114 if (argc != 5)
115 return CMD_RET_USAGE;
116
117 addr = (void *)simple_strtoul(argv[1], NULL, 16);
118 blk = simple_strtoul(argv[2], NULL, 16);
119 cnt = simple_strtoul(argv[3], NULL, 16);
120 key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
121 if (!key_addr)
122 key_addr = rpmb_test_key;
123 printf("\nUFS RPMB write: block # %d, count %d ...\n", blk, cnt);
124
125 n = ufs_rpmb_blk_write(addr, key_addr, blk, cnt);
126
127 printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
128 if (n != cnt)
129 return CMD_RET_FAILURE;
130
131 return CMD_RET_SUCCESS;
132 }
133
do_ufs_rpmb_counter(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])134 static int do_ufs_rpmb_counter(cmd_tbl_t *cmdtp, int flag,
135 int argc, char * const argv[])
136 {
137 uint32_t counter;
138
139 counter = ufs_rpmb_read_writecount();
140 printf("RPMB Write counter= %x\n", counter);
141
142 return CMD_RET_SUCCESS;
143 }
144
145 static cmd_tbl_t cmd_rpmb[] = {
146 U_BOOT_CMD_MKENT(key, 2, 0, do_ufs_rpmb_key, "", ""),
147 U_BOOT_CMD_MKENT(read, 5, 1, do_ufs_rpmb_read, "", ""),
148 U_BOOT_CMD_MKENT(write, 5, 0, do_ufs_rpmb_write, "", ""),
149 U_BOOT_CMD_MKENT(counter, 1, 1, do_ufs_rpmb_counter, "", ""),
150 };
151
do_ufs_rpmb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])152 static int do_ufs_rpmb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
153 {
154 cmd_tbl_t *cp;
155
156 cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
157
158 /* Drop the rpmb subcommand */
159 argc--;
160 argv++;
161
162 if (cp == NULL || argc > cp->maxargs)
163 return CMD_RET_USAGE;
164
165 if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
166 return CMD_RET_SUCCESS;
167
168 return cp->cmd(cmdtp, flag, argc, argv);
169 }
170 #endif
171
do_ufs(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])172 static int do_ufs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
173 {
174 int dev, ret;
175
176 if (argc >= 2) {
177 if (!strcmp(argv[1], "init")) {
178 if (argc == 3) {
179 dev = simple_strtoul(argv[2], NULL, 10);
180 ret = ufs_probe_dev(dev);
181 if (ret)
182 return CMD_RET_FAILURE;
183 } else {
184 ufs_probe();
185 }
186
187 return CMD_RET_SUCCESS;
188 }
189 #ifdef CONFIG_ROCKCHIP_UFS_RPMB
190 else if (!strcmp(argv[1], "rpmb")){
191 /* Drop the ufs subcommand */
192 argc--;
193 argv++;
194
195 return do_ufs_rpmb(cmdtp, flag, argc, argv);
196 }
197 #endif
198 }
199
200 return CMD_RET_USAGE;
201 }
202
203 U_BOOT_CMD(ufs, 7, 1, do_ufs,
204 "UFS sub system",
205 "init [dev] - init UFS subsystem\n"
206 #ifdef CONFIG_ROCKCHIP_UFS_RPMB
207 "ufs rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
208 "ufs rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
209 "ufs rpmb key <address of auth-key> - program the RPMB authentication key.\n"
210 "ufs rpmb counter - read the value of the write counter\n"
211 #endif
212 );
213