Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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