Merge branch 'org.openembedded.dev' of git://git.openembedded.net/openembedded into...
[vuplus_openembedded] / packages / dreambox / dreambox-boottool / boottool-dm7025.c
1 #include <sys/mount.h>
2 #include <stdio.h>
3 #include <fcntl.h>
4 #include <linux/loop.h>
5 #include <dirent.h>
6 #include <errno.h>
7 #include <sys/mman.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #define PREFIX
13 //#define PREFIX "/boot"
14 #define SQUASHFS_FILENAME PREFIX"/mnt/flash/squashfs"
15
16 #define streq(a,b) (strcmp((a),(b)) == 0)
17
18 /* This really needs to be in a header file... */
19 extern long init_module(void *, unsigned long, const char *);
20
21 /* We use error numbers in a loose translation... */
22 static const char *moderror(int err)
23 {
24         switch (err) {
25         case ENOEXEC:
26                 return "Invalid module format";
27         case ENOENT:
28                 return "Unknown symbol in module";
29         case ESRCH:
30                 return "Module has wrong symbol version";
31         case EINVAL:
32                 return "Invalid parameters";
33         default:
34                 return strerror(err);
35         }
36 }
37
38 static void *grab_file(const char *filename, unsigned long *size)
39 {
40         unsigned int max = 16384;
41         int ret, fd;
42         void *buffer = malloc(max);
43
44         if (streq(filename, "-"))
45                 fd = dup(STDIN_FILENO);
46         else
47                 fd = open(filename, O_RDONLY, 0);
48
49         if (fd < 0)
50                 return NULL;
51
52         *size = 0;
53         while ((ret = read(fd, buffer + *size, max - *size)) > 0) {
54                 *size += ret;
55                 if (*size == max)
56                         buffer = realloc(buffer, max *= 2);
57         }
58         if (ret < 0) {
59                 free(buffer);
60                 buffer = NULL;
61         }
62         close(fd);
63         return buffer;
64 }
65
66
67 int insmod(const char *filename)
68 {
69         void *file;
70         unsigned long len;
71         long int ret;
72
73
74         file = grab_file(filename, &len);
75         if (!file) {
76                 fprintf(stderr, "insmod: can't read '%s': %s\n",
77                         filename, strerror(errno));
78                 return 1;
79         }
80
81         ret = init_module(file, len, "");
82         if (ret != 0) {
83                 fprintf(stderr, "insmod: error inserting '%s': %li %s\n",
84                         filename, ret, moderror(errno));
85                 return 1;
86         }
87         return 0;
88 }
89
90 int main(int argc, char *argv[], char *envp[])
91 {
92         int res, x;
93
94                 /* first, load some needed kernel modules located in the root of our boot partition */
95         const char *modules[] = { "fs/squashfs/unlzma.ko", "fs/squashfs/sqlzma.ko", "fs/squashfs/squashfs.ko", "fs/unionfs.ko", "drivers/block/loop.ko", 0 };
96         const char *modules_path = PREFIX"/lib/modules/2.6.12.6/kernel/";
97         char path[255];
98
99         printf("Hello world!\n");
100
101         x=0;
102         while(modules[x]) {
103                 strcpy(path, modules_path);
104                 strcat(path, modules[x++]);
105                 printf("insmodding %s..\n", path);
106                 if (insmod(path))
107                         return 1;
108         }
109         
110                 /* mount the RW jffs2 partition, which contains the squashfs image (in /squashfs) and the deltas (in /delta) */
111         printf("mounting mtd...\n");
112         res = mount("/dev/mtdblock/3", PREFIX"/mnt/flash", "jffs2", 0, 0);
113
114         if (res)
115         {
116                 perror("mounting /flash");
117                 return res;
118         }
119         
120                 /* loop-mount the squashfs, by first connecting the file to loop0 ... */
121         printf("opening squashfs...\n");
122         int squashfs_fd = open(SQUASHFS_FILENAME, O_RDONLY);
123         if (squashfs_fd < 0)
124         {
125                 perror(SQUASHFS_FILENAME);
126                 return 1;
127         }
128         
129         printf("setup loop\n");
130         int loop_fd = open("/dev/loop/0", O_RDONLY);
131         
132         if (loop_fd < 0)
133         {
134                 perror("/dev/loop/0");
135                 return 1;
136         }
137         
138         struct loop_info loopinfo;
139
140         memset(&loopinfo, 0, sizeof(loopinfo));
141         strncpy(loopinfo.lo_name, SQUASHFS_FILENAME, LO_NAME_SIZE);
142         loopinfo.lo_offset = 0;
143         loopinfo.lo_encrypt_key_size = 0;
144         if (ioctl(loop_fd, LOOP_SET_FD, (void*)squashfs_fd) < 0) {
145                 perror("LOOP_SET_FD");
146                 return 1;
147         }
148         if (ioctl(loop_fd, LOOP_SET_STATUS, &loopinfo) < 0) {
149                 perror("LOOP_SET_STATUS");
150                 return 1;
151         }
152         close(loop_fd);
153         close(squashfs_fd);
154
155         printf("mounting squashfs..\n");
156
157                 /* and then mounting the loop device. */
158         if (mount("/dev/loop/0", PREFIX"/mnt/squashfs", "squashfs", MS_MGC_VAL|MS_RDONLY, "") < 0)
159         {
160                 perror("mounting squashfs");
161                 return 1;
162         }
163         
164                 /* now the situation is:
165                 
166                         /                     - our boot jffs2 partition
167                         /flash                - our RW jffs2 partition
168                         /flash/squashfs       - our loop-mounted squashfs file,
169                         /flash/delta          - the delta for the root
170                         /squashfs             - RO root
171                         /root                 - yet empty, but we will populate it using unionfs 
172                 */
173         
174         
175         printf("mounting unionfs..\n");
176         res = mount("none", PREFIX"/mnt/root", "unionfs", MS_MGC_VAL, "dirs="PREFIX"/mnt/flash/delta=rw:"PREFIX"/mnt/squashfs=ro");
177         if (res < 0)
178         {
179                 perror("mounting unionfs");
180                 return 1;
181         }
182
183         printf("pivot_root\n");
184         if ( pivot_root(PREFIX"/mnt/root", PREFIX"/mnt/root/boot") < 0)
185         {
186                 perror("pivot_root");
187                 return 1;
188         }
189
190         printf("mounting devfs..\n");
191         res = mount("none", "/dev", "devfs", 0, 0);
192         if (res)
193         {
194                 perror("mounting /dev");
195                 return res;
196         }
197         
198         printf("try umount old devfs..\n");
199         res = umount("/boot/dev");
200         perror("umount /boot/dev");
201
202         printf("call init!\n");
203         execve("/sbin/init", argv, envp);
204         perror("/sbin/init");
205         
206         return 1;
207 }