blob: 82fd016925f523e166c431bb13c2c177604ecd31 [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>
28#include <uuid/uuid.h>
29#include <ctype.h>
30
31#include "mmc.h"
32#include "mmc_cmds.h"
33
34int read_extcsd(int fd, __u8 *ext_csd)
35{
36 int ret = 0;
37 struct mmc_ioc_cmd idata;
38 memset(&idata, 0, sizeof(idata));
39 memset(ext_csd, 0, sizeof(__u8) * 512);
40 idata.write_flag = 0;
41 idata.opcode = MMC_SEND_EXT_CSD;
42 idata.arg = 0;
43 idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
44 idata.blksz = 512;
45 idata.blocks = 1;
46 mmc_ioc_cmd_set_data(idata, ext_csd);
47
48 ret = ioctl(fd, MMC_IOC_CMD, &idata);
49 if (ret)
50 perror("ioctl");
51
52 return ret;
53}
54
55int write_extcsd_value(int fd, __u8 index, __u8 value)
56{
57 int ret = 0;
58 struct mmc_ioc_cmd idata;
59
60 memset(&idata, 0, sizeof(idata));
61 idata.write_flag = 1;
62 idata.opcode = MMC_SWITCH;
63 idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
64 (index << 16) |
65 (value << 8) |
66 EXT_CSD_CMD_SET_NORMAL;
67 idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
68
69 ret = ioctl(fd, MMC_IOC_CMD, &idata);
70 if (ret)
71 perror("ioctl");
72
73 return ret;
74}
75
76int do_read_extcsd(int nargs, char **argv)
77{
78 __u8 ext_csd[512];
79 int fd, ret;
80 char *device;
81
82 CHECK(nargs != 2, "Usage: mmc </path/to/mmcblkX>\n", exit(1));
83
84 device = argv[1];
85
86 fd = open(device, O_RDWR);
87 if (fd < 0) {
88 perror("open");
89 exit(1);
90 }
91
92 ret = read_extcsd(fd, ext_csd);
93 if (ret) {
94 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
95 exit(1);
96 }
97
98 printf("Power ro locking: ");
99 if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
100 printf("not possible\n");
101 else
102 printf("possible\n");
103
104 printf("Permanent ro locking: ");
105 if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PERM_WP_DIS)
106 printf("not possible\n");
107 else
108 printf("possible\n");
109
110 printf("ro lock status: ");
111 if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
112 printf("locked until next power on\n");
113 else if (ext_csd[EXT_CSD_BOOT_WP] &
114 EXT_CSD_BOOT_WP_B_PERM_WP_EN)
115 printf("locked permanently\n");
116 else
117 printf("not locked\n");
118
119 return ret;
120}
121
122int do_write_extcsd(int nargs, char **argv)
123{
124 __u8 ext_csd[512], value;
125 int fd, ret;
126 char *device;
127
128 if (nargs != 2) {
129 fprintf (stderr, "Usage: %s </path/to/mmcblkX>\n",
130 argv[0]);
131 exit (1);
132 }
133 device = argv[1];
134
135 fd = open(device, O_RDWR);
136 if (fd < 0) {
137 perror("open");
138 exit(1);
139 }
140
141 ret = read_extcsd(fd, ext_csd);
142 if (ret) {
143 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
144 exit(1);
145 }
146
147 value = ext_csd[EXT_CSD_BOOT_WP] |
148 EXT_CSD_BOOT_WP_B_PWR_WP_EN;
149 ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value);
150 if (ret) {
151 fprintf(stderr, "Could not write 0x%02x to "
152 "EXT_CSD[%d] in %s\n",
153 value, EXT_CSD_BOOT_WP, device);
154 exit(1);
155 }
156
157 return ret;
158}