/[gxemul]/trunk/src/disk/bootblock_iso9660.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/disk/bootblock_iso9660.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (hide annotations)
Mon Oct 8 16:21:34 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 9781 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1497 2007/03/18 03:41:36 debug Exp $
20070224	Minor update to the initialization of the ns16550 in
		machine_walnut.c, to allow that machine type to boot with the
		new interrupt system (although it is still a dummy machine).
		Adding a wdc at 0x14000000 to machine_landisk.c, and fixing
		the SCIF serial interrupts of the SH4 cpu enough to get
		NetBSD/landisk booting from a disk image :-)  Adding a
		preliminary install instruction skeleton to guestoses.html.
20070306	Adding SH-IPL+G PROM emulation, and also passing the "end"
		symbol in r5 on bootup, for Landisk emulation. This is enough
		to get OpenBSD/landisk to install :)  Adding a preliminary
		install instruction skeleton to the documentation. SuperH
		emulation is still shaky, though :-/
20070307	Fixed a strangeness in memory_sh.c (read/write was never
		returned for any page). (Unknown whether this fixes any actual
		problems, though.)
20070308	dev_ram.c fix: invalidate code translations on writes to
		RAM, emulated as separate devices. Linux/dreamcast gets
		further in the boot process than before, but still bugs out
		in userland.
		Fixing bugs in the "stc.l gbr,@-rN" and "ldc.l @rN+,gbr" SuperH 
		instructions (they should NOT check the MD bit), allowing the
		Linux/dreamcast Live CD to reach userland correctly :-)
20070310	Changing the cpu name "Alpha" in src/useremul.c to "21364" to
		unbreak userland syscall emulation of FreeBSD/Alpha binaries.
20070314	Applying a patch from Michael Yaroslavtsev which fixes the
		previous Linux lib64 patch to the configure script.
20070315	Adding a (dummy) sun4v machine type, and SPARC T1 cpu type.
20070316	Creating a new directory, src/disk, and moving diskimage.c
		to it. Separating out bootblock loading stuff from emul.c into
		new files in src/disk.
		Adding some more SPARC registers.
20070318	Preparing/testing for a minirelease, 0.4.4.1.

==============  RELEASE 0.4.4.1  ==============


1 dpavlin 36 /*
2     * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28     * $Id: bootblock_iso9660.c,v 1.2 2007/03/16 15:17:55 debug Exp $
29     *
30     * ISO9660 CD-ROM "bootblock" handling.
31     *
32     * There is really no bootblock; instead, the file which is to be booted
33     * is extracted into a temporary file, and started as if it was given
34     * as a normal file argument on the command line.
35     *
36     * TODO: This is really ugly. It's a quick hack. All the magic constants
37     * need to be replaced with real code!
38     */
39    
40     #include <stdio.h>
41     #include <stdlib.h>
42     #include <string.h>
43     #include <sys/types.h>
44     #include <unistd.h>
45    
46     #include "cpu.h"
47     #include "diskimage.h"
48     #include "machine.h"
49     #include "misc.h"
50    
51     /* #define ISO_DEBUG */
52    
53    
54     static void debug_print_volume_id_and_filename(int iso_type,
55     unsigned char *buf, char *filename)
56     {
57     /* Volume ID: */
58     char str[35];
59     int i, ofs = iso_type == 3? 48 : 40;
60    
61     memcpy(str, buf + ofs, sizeof(str));
62     str[32] = '\0'; i = 31;
63    
64     while (i >= 0 && str[i]==' ')
65     str[i--] = '\0';
66     if (str[0])
67     debug("\"%s\"", str);
68     else {
69     /* System ID: */
70     ofs = iso_type == 3? 16 : 8;
71     memcpy(str, buf + ofs, sizeof(str));
72     str[32] = '\0'; i = 31;
73     while (i >= 0 && str[i]==' ')
74     str[i--] = '\0';
75     if (str[0])
76     debug("\"%s\"", str);
77     else
78     debug("(no ID)");
79     }
80    
81     debug(":%s\n", filename);
82     }
83    
84    
85     /*
86     * iso_load_bootblock():
87     *
88     * Try to load a kernel from an ISO 9660 disk image. iso_type is 1 for
89     * "CD001" (standard), 2 for "CDW01" (ECMA), and 3 for "CDROM" (Sierra).
90     *
91     * TODO: This function uses too many magic offsets and so on; it should be
92     * cleaned up some day.
93     *
94     * Returns 1 on success, 0 on failure.
95     */
96     int iso_load_bootblock(struct machine *m, struct cpu *cpu,
97     int disk_id, int disk_type, int iso_type, unsigned char *buf,
98     int *n_loadp, char ***load_namesp)
99     {
100     int filenr, dirlen, res = 0, res2, iadd = DEBUG_INDENTATION;
101     int found_dir;
102     uint64_t dirofs;
103     uint64_t fileofs, filelen;
104     unsigned char *dirbuf = NULL, *dp;
105     unsigned char *match_entry = NULL;
106     char *p, *filename_orig;
107     char *filename = strdup(cpu->machine->boot_kernel_filename);
108     unsigned char *filebuf = NULL;
109     char *tmpfname = NULL;
110     char **new_array;
111     int tmpfile_handle;
112    
113     if (filename == NULL) {
114     fatal("out of memory\n");
115     exit(1);
116     }
117     filename_orig = filename;
118    
119     debug("ISO9660 boot:\n");
120     debug_indentation(iadd);
121    
122     debug_print_volume_id_and_filename(iso_type, buf, filename);
123    
124    
125     /*
126     * Traverse the directory structure to find the kernel.
127     */
128    
129     dirlen = buf[0x84] + 256*buf[0x85] + 65536*buf[0x86];
130     if (dirlen != buf[0x8b] + 256*buf[0x8a] + 65536*buf[0x89])
131     fatal("WARNING: Root directory length mismatch?\n");
132    
133     dirofs = (int64_t)(buf[0x8c] + (buf[0x8d] << 8) + (buf[0x8e] << 16) +
134     ((uint64_t)buf[0x8f] << 24)) * 2048;
135    
136     #ifdef ISO_DEBUG
137     debug("root = %i bytes at 0x%llx\n", dirlen, (long long)dirofs);
138     #endif
139    
140     dirbuf = malloc(dirlen);
141     if (dirbuf == NULL) {
142     fatal("out of memory in iso_load_bootblock()\n");
143     exit(1);
144     }
145    
146     res2 = diskimage_access(m, disk_id, disk_type, 0, dirofs, dirbuf,
147     dirlen);
148     if (!res2) {
149     fatal("Couldn't read the disk image. Aborting.\n");
150     goto ret;
151     }
152    
153     found_dir = 1; /* Assume root dir */
154     dp = dirbuf; filenr = 1;
155     p = NULL;
156     while (dp < dirbuf + dirlen) {
157     size_t i, nlen = dp[0];
158     int x = dp[2] + (dp[3] << 8) + (dp[4] << 16) +
159     ((uint64_t)dp[5] << 24);
160     int y = dp[6] + (dp[7] << 8);
161     char direntry[65];
162    
163     dp += 8;
164    
165     /*
166     * As long as there is an \ or / in the filename, then we
167     * have not yet found the directory.
168     */
169     p = strchr(filename, '/');
170     if (p == NULL)
171     p = strchr(filename, '\\');
172    
173     #ifdef ISO_DEBUG
174     debug("%i%s: %i, %i, \"", filenr, filenr == found_dir?
175     " [CURRENT]" : "", x, y);
176     #endif
177     for (i=0; i<nlen && i<sizeof(direntry)-1; i++)
178     if (dp[i]) {
179     direntry[i] = dp[i];
180     #ifdef ISO_DEBUG
181     debug("%c", dp[i]);
182     #endif
183     } else
184     break;
185     #ifdef ISO_DEBUG
186     debug("\"\n");
187     #endif
188     direntry[i] = '\0';
189    
190     /* A directory name match? */
191     if ((p != NULL && strncasecmp(filename, direntry, nlen) == 0
192     && nlen == (size_t)p - (size_t)filename && found_dir == y)
193     || (p == NULL && direntry[0] == '\0') ) {
194     found_dir = filenr;
195     if (p != NULL)
196     filename = p+1;
197     dirofs = 2048 * (int64_t)x;
198     }
199    
200     dp += nlen;
201    
202     /* 16-bit aligned lenght: */
203     if (nlen & 1)
204     dp ++;
205    
206     filenr ++;
207     }
208    
209     p = strchr(filename, '/');
210     if (p == NULL)
211     p = strchr(filename, '\\');
212    
213     if (p != NULL) {
214     char *blah = filename_orig;
215    
216     fatal("could not find '%s' in /", filename);
217    
218     /* Print the first part of the filename: */
219     while (blah != filename)
220     fatal("%c", *blah++);
221    
222     fatal("\n");
223     goto ret;
224     }
225    
226     /* debug("dirofs = 0x%llx\n", (long long)dirofs); */
227    
228     /* Free the old dirbuf, and allocate a new one: */
229     free(dirbuf);
230     dirbuf = malloc(512);
231     if (dirbuf == NULL) {
232     fatal("out of memory in iso_load_bootblock()\n");
233     exit(1);
234     }
235    
236     for (;;) {
237     size_t len, i;
238    
239     /* Too close to another sector? Then realign. */
240     if ((dirofs & 2047) + 70 > 2047) {
241     dirofs = (dirofs | 2047) + 1;
242     /* debug("realign dirofs = 0x%llx\n", dirofs); */
243     }
244    
245     res2 = diskimage_access(m, disk_id, disk_type, 0, dirofs,
246     dirbuf, 256);
247     if (!res2) {
248     fatal("Couldn't read the disk image. Aborting.\n");
249     goto ret;
250     }
251    
252     dp = dirbuf;
253     len = dp[0];
254     if (len < 2)
255     break;
256    
257     /*
258     * TODO: Actually parse the directory entry!
259     *
260     * Haha, this must be rewritten.
261     */
262    
263     #if 0
264     /* hahahaha */
265     printf("filename = '%s'\n", filename);
266     {
267     int j;
268     for (j=32; j<len; j++)
269     printf("%c", dp[j] >= ' ' && dp[j] < 128? dp[j] : '.');
270     printf("\n");
271     }
272     #endif
273    
274     for (i=32; i<len; i++) {
275     if (i < len - strlen(filename))
276     if (strncmp(filename, (char *)dp + i,
277     strlen(filename)) == 0) {
278     /* The filename was found somewhere
279     in the directory entry. */
280     if (match_entry != NULL) {
281     fatal("TODO: I'm too lazy to"
282     " implement a correct "
283     "directory parser right "
284     "now... (BUG)\n");
285     exit(1);
286     }
287     match_entry = malloc(512);
288     if (match_entry == NULL) {
289     fatal("out of memory\n");
290     exit(1);
291     }
292     memcpy(match_entry, dp, 512);
293     break;
294     }
295     }
296    
297     if (match_entry != NULL)
298     break;
299    
300     dirofs += len;
301     }
302    
303     if (match_entry == NULL) {
304     char *blah = filename_orig;
305    
306     fatal("could not find '%s' in /", filename);
307    
308     /* Print the first part of the filename: */
309     while (blah != filename)
310     fatal("%c", *blah++);
311    
312     fatal("\n");
313     goto ret;
314     }
315    
316     fileofs = match_entry[2] + (match_entry[3] << 8) +
317     (match_entry[4] << 16) + ((uint64_t)match_entry[5] << 24);
318     filelen = match_entry[10] + (match_entry[11] << 8) +
319     (match_entry[12] << 16) + ((uint64_t)match_entry[13] << 24);
320     fileofs *= 2048;
321    
322     /* debug("filelen=%llx fileofs=%llx\n", (long long)filelen,
323     (long long)fileofs); */
324    
325     filebuf = malloc(filelen);
326     if (filebuf == NULL) {
327     fatal("could not allocate %lli bytes to read the file"
328     " from the disk image!\n", (long long)filelen);
329     goto ret;
330     }
331    
332     tmpfname = strdup("/tmp/gxemul.XXXXXXXXXXXX");
333    
334     res2 = diskimage_access(m, disk_id, disk_type, 0, fileofs, filebuf,
335     filelen);
336     if (!res2) {
337     fatal("could not read the file from the disk image!\n");
338     goto ret;
339     }
340    
341     tmpfile_handle = mkstemp(tmpfname);
342     if (tmpfile_handle < 0) {
343     fatal("could not create %s\n", tmpfname);
344     exit(1);
345     }
346     write(tmpfile_handle, filebuf, filelen);
347     close(tmpfile_handle);
348    
349     debug("extracted %lli bytes into %s\n", (long long)filelen, tmpfname);
350    
351     /* Add the temporary filename to the load_namesp array: */
352     (*n_loadp)++;
353     new_array = malloc(sizeof(char *) * (*n_loadp));
354     if (new_array == NULL) {
355     fatal("out of memory\n");
356     exit(1);
357     }
358     memcpy(new_array, *load_namesp, sizeof(char *) * (*n_loadp));
359     *load_namesp = new_array;
360    
361     /* This adds a Backspace char in front of the filename; this
362     is a special hack which causes the file to be removed once
363     it has been loaded. */
364     tmpfname = realloc(tmpfname, strlen(tmpfname) + 2);
365     memmove(tmpfname + 1, tmpfname, strlen(tmpfname) + 1);
366     tmpfname[0] = 8;
367    
368     (*load_namesp)[*n_loadp - 1] = tmpfname;
369    
370     res = 1;
371    
372     ret:
373     if (dirbuf != NULL)
374     free(dirbuf);
375    
376     if (filebuf != NULL)
377     free(filebuf);
378    
379     if (match_entry != NULL)
380     free(match_entry);
381    
382     free(filename_orig);
383    
384     debug_indentation(-iadd);
385     return res;
386     }
387    

  ViewVC Help
Powered by ViewVC 1.1.26