Mount root and exec GNU bash.
[cascardo/b2hw.git] / main.c
1 /*
2  * Copyright (C) 2016  Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, visit the http://fsf.org website.
16  */
17
18 #include "init.h"
19 #include <stdio.h>
20
21 #include <stdlib.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #define PREFIX "/sys/class/android_usb/android0/"
32
33 int do_write(char *fname, char *text)
34 {
35         int fd;
36         fd = open(fname, O_WRONLY);
37         write(fd, text, strlen(text));
38         close(fd);
39         return 0;
40 }
41
42 int do_read(char *fname, char *buffer, size_t len)
43 {
44         int fd;
45         int r;
46         fd = open(fname, O_RDONLY);
47         if (fd < 0) {
48                 fprintf(stderr, "failed to open %s: %s\n", fname,
49                         strerror(errno));
50                 return -1;
51         }
52         r = read(fd, buffer, len);
53         close(fd);
54         return r;
55 }
56
57 int
58 do_mknod(char *path, char *name, int block, int wait)
59 {
60         char *fullpath;
61         size_t len;
62         int r;
63         char dev[33];
64         int maj, min;
65         len = strlen(path) + strlen(name) + 6;
66         fullpath = malloc(len);
67         if (!fullpath) {
68                 fprintf(stderr, "failed to allocate buffer\n");
69                 return -1;
70         }
71         snprintf(fullpath, len, "%s/%s/dev", path, name);
72         do {
73                 r = do_read(fullpath, dev, sizeof(dev));
74                 if (r < 0 && !wait) {
75                         fprintf(stderr, "failed to read %s: %s\n", fullpath,
76                                         strerror(errno));
77                         goto out;
78                 }
79         } while (r < 0 && wait);
80         r = sscanf(dev, "%d:%d", &maj, &min);
81         if (r < 0) {
82                 fprintf(stderr, "failed to read devno from %s\n", dev);
83                 goto out;
84         }
85         snprintf(fullpath, len, "/dev/%s", name);
86         r = mknod(fullpath, 0666 | (block ? S_IFBLK : S_IFCHR), makedev(maj, min));
87         if (r < 0) {
88                 fprintf(stderr, "failed to mknod %s: %s\n", fullpath,
89                                 strerror(errno));
90         }
91 out:
92         free(fullpath);
93         return r;
94 }
95
96 int main(int argc, char **argv)
97 {
98         int r;
99         int fd = -1;
100         int i;
101         char *args[] = { "bash", "-l", NULL };
102         r = devmount_setup();
103         if (r < 0) {
104                 fprintf(stderr, "failed to mount devtmpfs, proceeding anyway\n");
105         }
106         r = sysfsmount_setup();
107         if (r < 0) {
108                 fprintf(stderr, "failed to mount sysfs, proceeding anyway\n");
109         }
110         do_write(PREFIX "/enable", "0");
111         do_write(PREFIX "/idVendor", "04E8");
112         do_write(PREFIX "/idProduct", "6860");
113         do_write(PREFIX "/f_acm/acm_transports", "tty");
114         do_write(PREFIX "/functions", "acm");
115         do_write(PREFIX "/enable", "1");
116         do_mknod("/sys/class/tty", "ttyGS0", 0, 1);
117         fd = open("/dev/ttyGS0", O_RDWR);
118         for (i = 0; i < 10; i++) {
119                 write(fd, "Hello World!\n", 13);
120                 sleep(1);
121         }
122         write(fd, "G\n", 2);
123         dup2(fd, 0);
124         dup2(fd, 1);
125         dup2(fd, 2);
126         printf("N\n");
127         r = do_mknod("/sys/block/mmcblk1", "mmcblk1p3", 1, 1);
128         if (r < 0) {
129                 fprintf(stderr, "Failed to create mmcblk1p3\n");
130         }
131         printf("U\n");
132         printf("Mounting root\n");
133         r = mkdir("/root", 0755);
134         if (r) printf("failed mkdir\n");
135         r = mount("/dev/mmcblk1p3", "/root", "ext4", MS_NOATIME, NULL);
136         if (r) printf("failed mount: %d\n", errno);
137         printf("Chroot and chdir\n");
138         r = chdir("/root");
139         if (r) printf("failed first chdir\n");
140         r = chroot("/root");
141         if (r) printf("failed chroot\n");
142         r = chdir("/");
143         if (r) printf("failed second chdir\n");
144         execve("/bin/bash", args, NULL);
145         return 0;
146 }