Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/ramdisk_load.c
Parent Directory | 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)
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 | } |