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