Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1297 - (show 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 #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 dprintf("New size = %llu\n", ramdisk_size);
98 }
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 dprintf("kinit: inflate returned %d\n", rv);
120
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 dprintf("kinit: writing %d bytes\n", BUF_SZ - zs.avail_out);
127
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 dprintf("start: %llu size: %llu fssize: %llu\n",
156 ramdisk_start, ramdisk_size, fssize);
157
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 int ramdisk_load(int argc, char *argv[])
192 {
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 close(rfd);
246 fclose(wfd);
247 return 0;
248 }
249
250 dprintf("kinit: ramdisk is %s, size %llu\n", fstype, fssize);
251
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 }