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