Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/ramdisk_load.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1297 - (hide annotations) (download)
Fri May 27 15:12:11 2011 UTC (12 years, 11 months ago) by niro
File MIME type: text/plain
File size: 6339 byte(s)
-updated to klibc-1.5.22 with mntproc definitions patch included
1 niro 532 #include <errno.h>
2     #include <fcntl.h>
3     #include <stdio.h>
4     #include <stdlib.h>
5     #include <string.h>
6     #include <unistd.h>
7     #include <inttypes.h>
8     #include <sys/stat.h>
9     #include <linux/fs.h>
10     #include <linux/cdrom.h>
11     #include <linux/fd.h>
12    
13     #include "kinit.h"
14     #include "do_mounts.h"
15     #include "fstype.h"
16     #include "zlib.h"
17    
18     #define BUF_SZ 65536
19    
20     static void wait_for_key(void)
21     {
22     /* Wait until the user presses Enter */
23     while (getchar() != '\n')
24     ;
25     }
26    
27     static int change_disk(const char *devpath, int rfd, int disk)
28     {
29     /* Try to eject and/or quiesce the device */
30     sync();
31     if (ioctl(rfd, FDEJECT, 0)) {
32     if (errno == ENOTTY) {
33     /* Not a floppy */
34     ioctl(rfd, CDROMEJECT, 0);
35     } else {
36     /* Non-ejectable floppy */
37     ioctl(rfd, FDRESET, FD_RESET_IF_NEEDED);
38     }
39     }
40     close(rfd);
41    
42     fprintf(stderr,
43     "\nPlease insert disk %d for ramdisk and press Enter...", disk);
44     wait_for_key();
45    
46     return open(devpath, O_RDONLY);
47     }
48    
49     /* Also used in initrd.c */
50     int load_ramdisk_compressed(const char *devpath, FILE * wfd,
51     off_t ramdisk_start)
52     {
53     int rfd = -1;
54     unsigned long long ramdisk_size, ramdisk_left;
55     int disk = 1;
56     ssize_t bytes;
57     int rv;
58     unsigned char in_buf[BUF_SZ], out_buf[BUF_SZ];
59     z_stream zs;
60    
61     zs.zalloc = Z_NULL; /* Use malloc() */
62     zs.zfree = Z_NULL; /* Use free() */
63     zs.next_in = Z_NULL; /* No data read yet */
64     zs.avail_in = 0;
65     zs.next_out = out_buf;
66     zs.avail_out = BUF_SZ;
67    
68     if (inflateInit2(&zs, 32 + 15) != Z_OK)
69     goto err1;
70    
71     rfd = open(devpath, O_RDONLY);
72     if (rfd < 0)
73     goto err2;
74    
75     /* Set to the size of the medium, or "infinite" */
76     if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size))
77     ramdisk_size = ~0ULL;
78    
79     do {
80     /* Purge the output preferentially over reading new
81     input, so we don't end up overrunning the input by
82     accident and demanding a new disk which doesn't
83     exist... */
84     if (zs.avail_out == 0) {
85     _fwrite(out_buf, BUF_SZ, wfd);
86     zs.next_out = out_buf;
87     zs.avail_out = BUF_SZ;
88     } else if (zs.avail_in == 0) {
89     if (ramdisk_start >= ramdisk_size) {
90     rfd = change_disk(devpath, rfd, ++disk);
91     if (rfd < 0)
92     goto err2;
93    
94     if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size))
95     ramdisk_size = ~0ULL;
96     ramdisk_start = 0;
97 niro 1122 dprintf("New size = %llu\n", ramdisk_size);
98 niro 532 }
99     do {
100     ramdisk_left = ramdisk_size - ramdisk_start;
101     bytes = min(ramdisk_left,
102     (unsigned long long)BUF_SZ);
103     bytes = pread(rfd, in_buf, bytes,
104     ramdisk_start);
105     } while (bytes == -1 && errno == EINTR);
106     if (bytes <= 0)
107     goto err2;
108     ramdisk_start += bytes;
109     zs.next_in = in_buf;
110     zs.avail_in = bytes;
111    
112     /* Print dots if we're reading from a real block device */
113     if (ramdisk_size != ~0ULL)
114     putc('.', stderr);
115     }
116     rv = inflate(&zs, Z_SYNC_FLUSH);
117     } while (rv == Z_OK || rv == Z_BUF_ERROR);
118    
119 niro 1122 dprintf("kinit: inflate returned %d\n", rv);
120 niro 532
121     if (rv != Z_STREAM_END)
122     goto err2;
123    
124     /* Write the last */
125     _fwrite(out_buf, BUF_SZ - zs.avail_out, wfd);
126 niro 1122 dprintf("kinit: writing %d bytes\n", BUF_SZ - zs.avail_out);
127 niro 532
128     inflateEnd(&zs);
129     return 0;
130    
131     err2:
132     inflateEnd(&zs);
133     err1:
134     return -1;
135     }
136    
137     static int
138     load_ramdisk_raw(const char *devpath, FILE * wfd, off_t ramdisk_start,
139     unsigned long long fssize)
140     {
141     unsigned long long ramdisk_size, ramdisk_left;
142     int disk = 1;
143     ssize_t bytes;
144     unsigned char buf[BUF_SZ];
145     int rfd;
146    
147     rfd = open(devpath, O_RDONLY);
148     if (rfd < 0)
149     return -1;
150    
151     /* Set to the size of the medium, or "infinite" */
152     if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size))
153     ramdisk_size = ~0ULL;
154    
155 niro 1122 dprintf("start: %llu size: %llu fssize: %llu\n",
156     ramdisk_start, ramdisk_size, fssize);
157 niro 532
158     while (fssize) {
159    
160     if (ramdisk_start >= ramdisk_size) {
161     rfd = change_disk(devpath, rfd, ++disk);
162     if (rfd < 0)
163     return -1;
164    
165     if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size))
166     ramdisk_size = ~0ULL;
167     ramdisk_start = 0;
168     }
169    
170     do {
171     ramdisk_left =
172     min(ramdisk_size - ramdisk_start, fssize);
173     bytes = min(ramdisk_left, (unsigned long long)BUF_SZ);
174     bytes = pread(rfd, buf, bytes, ramdisk_start);
175     } while (bytes == -1 && errno == EINTR);
176     if (bytes <= 0)
177     break;
178     _fwrite(buf, bytes, wfd);
179    
180     ramdisk_start += bytes;
181     fssize -= bytes;
182    
183     /* Print dots if we're reading from a real block device */
184     if (ramdisk_size != ~0ULL)
185     putc('.', stderr);
186     }
187    
188     return !!fssize;
189     }
190    
191 niro 1122 int ramdisk_load(int argc, char *argv[])
192 niro 532 {
193     const char *arg_prompt_ramdisk = get_arg(argc, argv, "prompt_ramdisk=");
194     const char *arg_ramdisk_blocksize =
195     get_arg(argc, argv, "ramdisk_blocksize=");
196     const char *arg_ramdisk_start = get_arg(argc, argv, "ramdisk_start=");
197     const char *arg_ramdisk_device = get_arg(argc, argv, "ramdisk_device=");
198    
199     int prompt_ramdisk = arg_prompt_ramdisk ? atoi(arg_prompt_ramdisk) : 0;
200     int ramdisk_blocksize =
201     arg_ramdisk_blocksize ? atoi(arg_ramdisk_blocksize) : 512;
202     off_t ramdisk_start =
203     arg_ramdisk_start
204     ? strtoumax(arg_ramdisk_start, NULL, 10) * ramdisk_blocksize : 0;
205     const char *ramdisk_device =
206     arg_ramdisk_device ? arg_ramdisk_device : "/dev/fd0";
207    
208     dev_t ramdisk_dev;
209     int rfd;
210     FILE *wfd;
211     const char *fstype;
212     unsigned long long fssize;
213     int is_gzip = 0;
214     int err;
215    
216     if (prompt_ramdisk) {
217     fprintf(stderr,
218     "Please insert disk for ramdisk and press Enter...");
219     wait_for_key();
220     }
221    
222     ramdisk_dev = name_to_dev_t(ramdisk_device);
223     if (!ramdisk_dev) {
224     fprintf(stderr,
225     "Failure loading ramdisk: unknown device: %s\n",
226     ramdisk_device);
227     return 0;
228     }
229    
230     create_dev("/dev/rddev", ramdisk_dev);
231     create_dev("/dev/ram0", Root_RAM0);
232     rfd = open("/dev/rddev", O_RDONLY);
233     wfd = fopen("/dev/ram0", "w");
234    
235     if (rfd < 0 || !wfd) {
236     perror("Could not open ramdisk device");
237     return 0;
238     }
239    
240     /* Check filesystem type */
241     if (identify_fs(rfd, &fstype, &fssize, ramdisk_start) ||
242     (fssize == 0 && !(is_gzip = !strcmp(fstype, "gzip")))) {
243     fprintf(stderr,
244     "Failure loading ramdisk: unknown filesystem type\n");
245 niro 1297 close(rfd);
246     fclose(wfd);
247 niro 532 return 0;
248     }
249    
250 niro 1122 dprintf("kinit: ramdisk is %s, size %llu\n", fstype, fssize);
251 niro 532
252     fprintf(stderr, "Loading ramdisk (%s) ...", is_gzip ? "gzip" : "raw");
253    
254     close(rfd);
255    
256     if (is_gzip)
257     err = load_ramdisk_compressed("/dev/rddev", wfd, ramdisk_start);
258     else
259     err = load_ramdisk_raw("/dev/rddev", wfd,
260     ramdisk_start, fssize);
261    
262     fclose(wfd);
263    
264     putc('\n', stderr);
265    
266     if (err) {
267     perror("Failure loading ramdisk");
268     return 0;
269     }
270    
271     return 1;
272     }