xref: /rk3399_rockchip-uboot/cmd/ufs.c (revision 13ceb2afdcb6f5114908e39f0d2453728eb24e0f)
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 
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 
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 
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 
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 
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 
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 
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