/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mmc.h" #include "mmc_cmds.h" int read_extcsd(int fd, __u8 *ext_csd) { int ret = 0; struct mmc_ioc_cmd idata; memset(&idata, 0, sizeof(idata)); memset(ext_csd, 0, sizeof(__u8) * 512); idata.write_flag = 0; idata.opcode = MMC_SEND_EXT_CSD; idata.arg = 0; idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; idata.blksz = 512; idata.blocks = 1; mmc_ioc_cmd_set_data(idata, ext_csd); ret = ioctl(fd, MMC_IOC_CMD, &idata); if (ret) perror("ioctl"); return ret; } int write_extcsd_value(int fd, __u8 index, __u8 value) { int ret = 0; struct mmc_ioc_cmd idata; memset(&idata, 0, sizeof(idata)); idata.write_flag = 1; idata.opcode = MMC_SWITCH; idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | EXT_CSD_CMD_SET_NORMAL; idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; ret = ioctl(fd, MMC_IOC_CMD, &idata); if (ret) perror("ioctl"); return ret; } int do_read_extcsd(int nargs, char **argv) { __u8 ext_csd[512]; int fd, ret; char *device; CHECK(nargs != 2, "Usage: mmc \n", exit(1)); device = argv[1]; fd = open(device, O_RDWR); if (fd < 0) { perror("open"); exit(1); } ret = read_extcsd(fd, ext_csd); if (ret) { fprintf(stderr, "Could not read EXT_CSD from %s\n", device); exit(1); } printf("Power ro locking: "); if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PWR_WP_DIS) printf("not possible\n"); else printf("possible\n"); printf("Permanent ro locking: "); if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PERM_WP_DIS) printf("not possible\n"); else printf("possible\n"); printf("ro lock status: "); if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PWR_WP_EN) printf("locked until next power on\n"); else if (ext_csd[EXT_CSD_BOOT_WP] & EXT_CSD_BOOT_WP_B_PERM_WP_EN) printf("locked permanently\n"); else printf("not locked\n"); return ret; } int do_write_extcsd(int nargs, char **argv) { __u8 ext_csd[512], value; int fd, ret; char *device; if (nargs != 2) { fprintf (stderr, "Usage: %s \n", argv[0]); exit (1); } device = argv[1]; fd = open(device, O_RDWR); if (fd < 0) { perror("open"); exit(1); } ret = read_extcsd(fd, ext_csd); if (ret) { fprintf(stderr, "Could not read EXT_CSD from %s\n", device); exit(1); } value = ext_csd[EXT_CSD_BOOT_WP] | EXT_CSD_BOOT_WP_B_PWR_WP_EN; ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value); if (ret) { fprintf(stderr, "Could not write 0x%02x to " "EXT_CSD[%d] in %s\n", value, EXT_CSD_BOOT_WP, device); exit(1); } return ret; }