16002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall/*
26002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * Copyright (C) 2011, 2012 The Android Open Source Project
36002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall *
46002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * Licensed under the Apache License, Version 2.0 (the "License");
56002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * you may not use this file except in compliance with the License.
66002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * You may obtain a copy of the License at
76002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall *
86002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall *      http://www.apache.org/licenses/LICENSE-2.0
96002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall *
106002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * Unless required by applicable law or agreed to in writing, software
116002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * distributed under the License is distributed on an "AS IS" BASIS,
126002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * See the License for the specific language governing permissions and
146002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall * limitations under the License.
156002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall */
166002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
176002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <stdlib.h>
186002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <stdio.h>
196002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <sys/types.h>
206002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <sys/stat.h>
216002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <fcntl.h>
226002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <unistd.h>
236002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <sys/ioctl.h>
246002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <linux/fs.h>
256002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#include <errno.h>
266002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
276002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumralltypedef unsigned long long u64;
286002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
296002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#ifndef BLKDISCARD
306002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#define BLKDISCARD _IO(0x12,119)
316002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#endif
326002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
336002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#ifndef BLKSECDISCARD
346002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#define BLKSECDISCARD _IO(0x12,125)
356002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall#endif
366002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
376002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrallstatic u64 get_block_device_size(int fd)
386002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall{
396002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        u64 size = 0;
406002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        int ret;
416002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
426002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        ret = ioctl(fd, BLKGETSIZE64, &size);
436002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
446002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        if (ret)
456002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall                return 0;
466002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
476002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        return size;
486002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall}
496002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
506002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrallstatic int wipe_block_device(int fd, u64 len, int secure)
516002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall{
526002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    u64 range[2];
536002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    int ret;
546002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    int req;
556002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
566002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    range[0] = 0;
576002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    range[1] = len;
586002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (secure) {
596002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall       req = BLKSECDISCARD;
606002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    } else {
616002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall       req = BLKDISCARD;
626002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
636002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
646002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    ret = ioctl(fd, req, &range);
656002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (ret < 0) {
666002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        fprintf(stderr, "%s discard failed, errno = %d\n",
676002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall                secure ? "Secure" : "Nonsecure", errno);
686002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
696002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
706002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    return ret;
716002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall}
726002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
736002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrallstatic void usage(void)
746002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall{
756002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    fprintf(stderr, "Usage: wipe_blkdev [-s] <partition>\n");
766002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    exit(1);
776002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall}
786002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
796002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrallint main(int argc, char *argv[])
806002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall{
816002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    int secure = 0;
826002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    char *devname;
836002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    int fd;
846002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    u64 len;
856002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    struct stat statbuf;
866002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    int ret;
876002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
886002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if ((argc != 2) && (argc != 3)) {
896002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        usage();
906002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
916002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
926002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (argc == 3) {
936002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        if (!strcmp(argv[1], "-s")) {
946002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall            secure = 1;
956002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall            devname = argv[2];
966002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        } else {
976002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall            usage();
986002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        }
996002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    } else {
1006002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        devname = argv[1];
1016002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
1026002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1036002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    fd = open(devname, O_RDWR);
1046002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (fd < 0) {
1056002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        fprintf(stderr, "Cannot open device %s\n", devname);
1066002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        exit(1);
1076002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
1086002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1096002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (fstat(fd, &statbuf) < 0) {
1106002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        fprintf(stderr, "Cannot stat %s\n", devname);
1116002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        exit(1);
1126002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
1136002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1146002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (!S_ISBLK(statbuf.st_mode)) {
1156002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        fprintf(stderr, "%s is not a block device\n", devname);
1166002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        exit(1);
1176002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
1186002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1196002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    len = get_block_device_size(fd);
1206002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1216002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    if (! len) {
1226002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        fprintf(stderr, "Cannot get size of block device %s\n", devname);
1236002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall        exit(1);
1246002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    }
1256002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1266002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    ret = wipe_block_device(fd, len, secure);
1276002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1286002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    close(fd);
1296002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall
1306002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall    return ret;
1316002c64f41c3e169e68eeb4c5272c6ec63642514Ken Sumrall}
132