blob: dce3eccb8c12606e3bc335704cf98c61d709a822 [file] [log] [blame]
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -05001/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/ioctl.h>
21#include <sys/types.h>
22#include <dirent.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <libgen.h>
27#include <limits.h>
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -050028#include <ctype.h>
29
30#include "mmc.h"
31#include "mmc_cmds.h"
32
33int read_extcsd(int fd, __u8 *ext_csd)
34{
35 int ret = 0;
36 struct mmc_ioc_cmd idata;
37 memset(&idata, 0, sizeof(idata));
38 memset(ext_csd, 0, sizeof(__u8) * 512);
39 idata.write_flag = 0;
40 idata.opcode = MMC_SEND_EXT_CSD;
41 idata.arg = 0;
42 idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
43 idata.blksz = 512;
44 idata.blocks = 1;
45 mmc_ioc_cmd_set_data(idata, ext_csd);
46
47 ret = ioctl(fd, MMC_IOC_CMD, &idata);
48 if (ret)
49 perror("ioctl");
50
51 return ret;
52}
53
54int write_extcsd_value(int fd, __u8 index, __u8 value)
55{
56 int ret = 0;
57 struct mmc_ioc_cmd idata;
58
59 memset(&idata, 0, sizeof(idata));
60 idata.write_flag = 1;
61 idata.opcode = MMC_SWITCH;
62 idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
63 (index << 16) |
64 (value << 8) |
65 EXT_CSD_CMD_SET_NORMAL;
66 idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
67
68 ret = ioctl(fd, MMC_IOC_CMD, &idata);
69 if (ret)
70 perror("ioctl");
71
72 return ret;
73}
74
75int do_read_extcsd(int nargs, char **argv)
76{
77 __u8 ext_csd[512];
78 int fd, ret;
79 char *device;
80
81 CHECK(nargs != 2, "Usage: mmc </path/to/mmcblkX>\n", exit(1));
82
83 device = argv[1];
84
85 fd = open(device, O_RDWR);
86 if (fd < 0) {
87 perror("open");
88 exit(1);
89 }
90
91 ret = read_extcsd(fd, ext_csd);
92 if (ret) {
93 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
94 exit(1);
95 }
96
97 printf("Power ro locking: ");
98 if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
99 printf("not possible\n");
100 else
101 printf("possible\n");
102
103 printf("Permanent ro locking: ");
104 if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PERM_WP_DIS)
105 printf("not possible\n");
106 else
107 printf("possible\n");
108
109 printf("ro lock status: ");
110 if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
111 printf("locked until next power on\n");
112 else if (ext_csd[EXT_CSD_BOOT_WP] &
113 EXT_CSD_BOOT_WP_B_PERM_WP_EN)
114 printf("locked permanently\n");
115 else
116 printf("not locked\n");
117
118 return ret;
119}
120
121int do_write_extcsd(int nargs, char **argv)
122{
123 __u8 ext_csd[512], value;
124 int fd, ret;
125 char *device;
126
127 if (nargs != 2) {
128 fprintf (stderr, "Usage: %s </path/to/mmcblkX>\n",
129 argv[0]);
130 exit (1);
131 }
132 device = argv[1];
133
134 fd = open(device, O_RDWR);
135 if (fd < 0) {
136 perror("open");
137 exit(1);
138 }
139
140 ret = read_extcsd(fd, ext_csd);
141 if (ret) {
142 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
143 exit(1);
144 }
145
146 value = ext_csd[EXT_CSD_BOOT_WP] |
147 EXT_CSD_BOOT_WP_B_PWR_WP_EN;
148 ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value);
149 if (ret) {
150 fprintf(stderr, "Could not write 0x%02x to "
151 "EXT_CSD[%d] in %s\n",
152 value, EXT_CSD_BOOT_WP, device);
153 exit(1);
154 }
155
156 return ret;
157}