Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 6351 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 #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 DEBUG(("New size = %llu\n", ramdisk_size));
99 }
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 DEBUG(("kinit: inflate returned %d\n", rv));
121
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 DEBUG(("kinit: writing %d bytes\n", BUF_SZ - zs.avail_out));
128
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 DEBUG(("start: %llu size: %llu fssize: %llu\n",
157 ramdisk_start, ramdisk_size, fssize));
158
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 int ramdisk_load(int argc, char *argv[], dev_t root_dev)
193 {
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 DEBUG(("kinit: ramdisk is %s, size %llu\n", fstype, fssize));
250
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 }